Thursday, February 18, 2010

Adding SDL


Now that I have the basic data structure representing the cellular automata "world", it's time to start hacking in the graphics code. I'm using Simple DirectMedia Layer (SDL) to make the magic here. Why SDL? Well, I started doing this stuff in Python, where I used pygame to make the magic, and SDL is the magic behind pygame.

SDL was the library that Loki Games used to port commercial games from Windows to Linux. I even purchased one. Sadly, Loki is gone, but SDL is still here and is even still under development. Ignorant as I am, it seems as good a choice as any.

The magic so far

The display portions of the code were copied from a demo that I found somewhere on the net. Sorry, I don't remember where.  Ask Google -- the code is out there. Most of the comments are from that source. Originally the program displayed a bitmap; I hacked it to my bidding. I won't say much more about the code, although I could go on until the cows come home.

One tweak that come to mind is to change the world vector's data type, which is currently a C++ int, which is 4 bytes on my machine. I really don't need 4294967296 different values to hold 2 states, 0 or 1. A bool would do nicely, or maybe a shorter king of unsigned integer type, if I decide to encode more information about the cell. It's on the TODO list.


#include <iostream>
#include
<vector>

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


using namespace std;

const int XRES = 1024;
const int YRES = 768;
const int BLOCKSIZE = 8;
const int DELTA_T = 250;
const int FCOLOR = 0x00FF00;
const int BCOLOR = 0x000000;
const int ROWS = YRES / BLOCKSIZE;
const int COLS = XRES / BLOCKSIZE;

int randomStart(vector<SDL_Rect> & cells, vector<vector <int> > & world) {
        srand(time(NULL));

        SDL_Rect p;
        int pct;

        for (int row = 0; row < ROWS; ++row)
        {
            for (int col = 0; col < COLS; ++col)
            {
                pct  = rand() % 1000;
                if (pct < 375)
                {
                    p.x = col * BLOCKSIZE;
                    p.y = row * BLOCKSIZE;
                    p.w = BLOCKSIZE;
                    p.h = BLOCKSIZE;
                    cells.push_back(p);
                    world[row][col] = 1;
                }
                else
                    world[row][col] = 0;
            }
        }
    return 0;
}

int main() {
    vector<SDL_Rect> cells;
    vector< vector<int> > world(ROWS, vector<int>(COLS,0));

    // initialize SDL
    SDL_Init(SDL_INIT_VIDEO);

    // populate the world
    randomStart(cells, world);   // pass by reference

    // set the title bar
    SDL_WM_SetCaption("Cellular Automata", "Cellular Automata");

    // create window
    SDL_Surface* screen = SDL_SetVideoMode(XRES, YRES, 0, SDL_DOUBLEBUF);

    // Create background and block
    SDL_Surface* bg = SDL_CreateRGBSurface(SDL_SWSURFACE,XRES, YRES, 32, 0, 0, 0, 0);
    SDL_Surface* block = SDL_CreateRGBSurface(SDL_SWSURFACE, BLOCKSIZE - 2, BLOCKSIZE - 2, 32, 0, 0, 0, 0);
    SDL_FillRect(block, NULL, FCOLOR);

    // blit a block
    for (unsigned int i = 0; i < cells.size(); ++i)
        SDL_BlitSurface(block, NULL, bg, &cells[i]);

    SDL_Event event;
    bool gameover = false;

    // message pump
    while (!gameover)
    {
        // look for an event
        if (SDL_PollEvent(&event)) {
            // an event was found
            switch (event.type) {
                // close button clicked
                case SDL_QUIT:
                    gameover = true;
                    break;
                // handle the keyboard
                case SDL_KEYDOWN:
                    switch (event.key.keysym.sym) {
                        case SDLK_ESCAPE:
                        case SDLK_q:
                            gameover = true;
                            break;
                    }
                    break;
            }
        }
        // draw the background
        SDL_BlitSurface(bg, NULL, screen, NULL);

        // update the screen
        SDL_UpdateRect(screen, 0, 0, 0, 0);
    }
    // free the background surface
    SDL_FreeSurface(bg);

    // cleanup SDL
    SDL_Quit();

    return 0;
}



No comments:

Post a Comment