Very simple 2D graphic library

Hi guys

Just wanted to see what everyone thinks is the easiest, quickest, most efficient, opensource, cross platform 2D drawing library that can be used; basically all I am trying to do is create a blank screen and draw pixels at random points on the screen, I am simply looking for something that would only require something along the lines of
1
2
3
4
5
6
7
8
#include <simple2ddrawinglibrary>
CREATE_SCREEN (640, 480, 32)
..
.. more code
..
DRAW_PIXEL (10,10, 0 (or whatever black is)
..
.. more code

I know its probably not going to be that straightforward, but the more straightforward, the better.

Thanks guys
Simple Directmedia Layer (SDL) is very simple. Not quite that simple, but simple. http://www.lazyfoo.net/SDL_tutorials/index.php is a good tutorial which I like.

It's more like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// main.cpp
#include <SDL.h>
#include <string>

// Globals:

// Defining screen attributes:
const int sc_width  = 640; // Width
const int sc_height = 480; // Height
const int sc_bpp    = 32;  // Bits per pixel.

// foreground, background, screen
SDL_Surface* fg = NULL, *bg = NULL, *screen = NULL;

// Prototypes:
SDL_Surface* loadIMG(std::string); // Loads an image to the screen
void applySurface(int, int, SDL_Surface*, SDL_Surface*); // Applies image, but does not refresh screen
void FreeIMG(SDL_Surface*, ...); // Clears an image

// Main:
int main(int argc, char* argv[]) {
    // Try to initialize SDL:
    if (SDL_Init(SDL_INIT_EVERYTHING) == -1) {
        return 1; // SDL is being a bitch and failed to initialize itself. Obviously this is not the programmer's fault.
    }

    // Create the Window :O
    screen = SDL_SetVideoMode(sc_width, sc_height, sc_bpp, SDL_SWSURFACE);

    if (screen == NULL) {
        return 1; // SDL is being a bitch and the screen failed to load :O
    } // Or someone changed the image format from 24-bit.. cough.

    // Set the caption on the screen like a pro:
    SDL_WM_SetCaption("Hai world", NULL);

    // Load a pair of images (24-bit bitmaps)
    fg = loadIMG("hw.bmp");
    bg = loadIMG("bg.bmp");
    // As the images are not 32-bit like the screen, we have to change them to 32-bit
    applySurface(0, 0, bg, screen);
    applySurface(180, 140, fg, screen);

    // Update the screen:
    if (SDL_Flip(screen) == -1) {
        return 1; // The screen failed to be updated...
    }

    SDL_Delay(1000);
    /* I created a variadic function to handle 1 or more surfaces at once.
       The problem is that I haven't finished learning variadic functions yet... */
    FreeIMG(fg);
    FreeIMG(bg);
    // The following could also be used, but when I learn variadic functions properly... ZING.
    // SDL_FreeSurface(fg);
    // SDL_FreeSurface(bg);
    // Sleep for 1 second:
    SDL_Delay(1000);
    // Return 0.
    return 0;
}


which is actually very similar to the code in that tutorial, as that's where I'm learning SDL from, too.

Here's the rest of the files:
1
2
3
4
5
6
7
8
9
10
11
// applySurface.cpp
#include <SDL.h>
#include <string>

void applySurface(int x, int y, SDL_Surface* source, SDL_Surface* destination) {
    SDL_Rect offset;
    offset.x = x;
    offset.y = y;
    // Blit the surface:
    SDL_BlitSurface(source, NULL, destination, &offset);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// loadIMG.cpp
#include <SDL.h>
#include <string>

SDL_Surface* loadIMG(std::string filename) {
    SDL_Surface* temp = SDL_LoadBMP(filename.c_str()); // Load the image
    SDL_Surface* surface = NULL;

    if (temp) { // If temp != 0, the image loaded successfully.
        surface = SDL_DisplayFormat(temp); // Format the image correctly (32 bit instead of 24 bit)
        SDL_FreeSurface(temp); // Free the temporary surface from memory.
    }

    return surface; // Return the hopefully successfully loaded surface
}


1
2
3
4
5
6
7
8
9
// Freesurface.cpp
#include <SDL.h>
#include <string>

void FreeIMG(SDL_Surface* surf, ...) {
    if (surf != NULL) {
        SDL_FreeSurface(surf);
    }
}


It's really that easy.
Last edited on
Chris, that is a MASSIVE help, thank you so much mate, I knew it wouldn't be as simple as the example code I typed, but this is much better than I thought it would be. I never actually considered the screen would need to be flipped, but it makes sense. Thank you ever so much mate, you are a star.
LOL.

No problem.

(man I love helping people)
Is SDL a computer language, like C++, or do you have to put those strings/codes within the C++ program?
the question may be a bit weird, but.. explain a bit how it works.
SDL is an abstraction layer. Think of it this way: if you didn't have an operating system, you'd have to code everything yourself, from interrupts, hardware accesses and booting yourself. Writing directly to video memory, using CPU registers, using BIOS to take input (interrupts)... that kind of thing. Therefore the operating system is an abstraction layer - it is like the steering wheel of a car. It is there so that you can control the wheels without physically grabbing them and moving around.

SDL acts like an abstraction layer in that it does video card accesses and such itself, you just tell it what to do.

http://en.wikipedia.org/wiki/Abstraction_layer
The SDL API is written in C and can be used in any C/C++ program. It is not it's own language.
Hi guys, many thanks for all your help so far and SDL is exactly the sort of library I wanted

I have managed to code the following with a little bit (putpixel () function) borrowed from a tutorial I found but asking Google.

The program sort of works, but I was hoping someone could suggest a way of optimising the code a little (it seems a lot of code for what it does) and also I just can't seem to find a way of getting the program to stop if you press escape or click the left mouse button.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

#include "SDL/SDL.h"
#include <time.h>

//setup the putpixel function
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to set */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {
    case 1:
        *p = pixel;
        break;

    case 2:
        *(Uint16 *)p = pixel;
        break;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
            p[0] = (pixel >> 16) & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = pixel & 0xff;
        } else {
            p[0] = pixel & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = (pixel >> 16) & 0xff;
        }
        break;

    case 4:
        *(Uint32 *)p = pixel;
        break;
    }
}

int main( int argc, char* args[] )
{ //Start SDL
    SDL_Init( SDL_INIT_EVERYTHING );

    //The attributes of the screen
    const int SCREEN_WIDTH = 640;
    const int SCREEN_HEIGHT = 480;
    const int SCREEN_BPP = 32;
    const int NOOFFLAKES = 100;
    int x[NOOFFLAKES];
    int y[NOOFFLAKES];
    int xo[NOOFFLAKES];
    int yo[NOOFFLAKES];

    //The surface that will be used
    SDL_Surface *screen = NULL;

//Set up the screen
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_DOUBLEBUF|SDL_FULLSCREEN);
SDL_ShowCursor(SDL_DISABLE);

SDL_FillRect( SDL_GetVideoSurface(), NULL, 0 );
SDL_WM_SetCaption( "Snow Test 1", NULL );

 //If there was an error in setting up the screen
 if( screen == NULL ) { return 1; }

    Uint32 white;
    Uint32 black;

//Map the color white to this display (R=0xff, G=0xff, B=0xff)

    white = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
    black = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);

//Setup Snow Flakes
srand ( time (NULL));

for (int flake = 0; flake < NOOFFLAKES; flake ++)
{

x[flake] = rand () % SCREEN_WIDTH;
y[flake] = rand () % (SCREEN_HEIGHT / 2 );
xo[flake] = x[flake];
yo[flake] = y[flake];

    /* Lock the screen for direct access to the pixels */
    if ( SDL_MUSTLOCK(screen) ) {
        if ( SDL_LockSurface(screen) < 0 ) {
            fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
            return 0;
        }
    }
    if ( SDL_MUSTLOCK(screen) ) {
        SDL_UnlockSurface(screen);
        return 0;
    }

   // putpixel(screen, x[flake], y[flake], white);

    /* Update just the part of the display that we've changed */
    SDL_UpdateRect(screen, x[flake], y[flake], 1, 1);

}

int move, movex, movey;
for (int loop = 0; loop < 699; loop  ++)
{
    for (int flake = 0; flake < NOOFFLAKES; flake ++)
    {
// choose whether to move left, right or straight down and by how many pixels
move = rand () % 3;
movex = (rand () % 2) + 1;
movey = (rand () % 5) + 1;

//backup the existing positions
xo[flake] = x[flake];
yo[flake] = y[flake];

// now draw again

   /* Lock the screen for direct access to the pixels */
    if ( SDL_MUSTLOCK(screen) ) {
        if ( SDL_LockSurface(screen) < 0 ) {
            fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
            return 0;
        }
    }
    if ( SDL_MUSTLOCK(screen) ) {
        SDL_UnlockSurface(screen);
        return 0;
    }

    putpixel(screen, xo[flake], yo[flake], black);

    // move down the screen by the no of movey
if (y[flake] + (movey +1) < SCREEN_HEIGHT)
{y[flake] = y[flake] + (movey +1);}
else { putpixel(screen, x[flake], y[flake], white);
y[flake] = rand () % (SCREEN_HEIGHT / 2 );
}

if (x[flake] < 0)
{x[flake] = movex;}
if (x[flake] > SCREEN_WIDTH)
{x[flake] = (SCREEN_WIDTH - movex);}

// if 0 then left, 1 for right, else straight down
if (move == 0)
{x[flake] = x[flake] - movex;}
if (move == 1)
{x[flake] = x[flake] + movex;}

    putpixel(screen, x[flake], y[flake], white);

    /* Update just the part of the display that we've changed */
        SDL_UpdateRect(screen, xo[flake], yo[flake], 1, 1);
    SDL_UpdateRect(screen, x[flake], y[flake], 1, 1);

    }
//set snowflake loop update delay
SDL_Delay (80);

}

 //Wait 2 seconds
SDL_Delay( 2000 );

    //Quit SDL
    SDL_Quit(); return 0; }


If anyone can think of an easier or more efficient way of doing the above, I would greatly appreciate it as I've been programming in basic for many years (Spectrum BASIC - I kid you not and QBASIC) but I'm a complete NooB with C++ and very interested in learning to code with it.

One final question, can anyone think of a way of getting the landing flakes to roll down the ones already piled up and filling in the gaps?

With the greatest of thanks and respect.

Marto
I'm not sure, but if you want to quit you should check for SDL_QUIT:
1
2
3
4
SDL_EVENT Event; // Might be SDL_EVENT*

if (Event == SDL_QUIT) // Escape button pressed, etc.
    SDL_Quit();

Put that in your main game loop somewhere. You'll have a loop eventually.
Last edited on
Topic archived. No new replies allowed.