Monday, December 13, 2010

Code::Blocks(1) C++, SDL and Life

Time to finally start using code::blocks, we are going to create a simple first project:



Conway's Game of life

We have a few objectives to accomplish with the tutorial:

  • Use Code::Blocks to create projects, add classes, configure libraries, etc.
  • Setting up SDL with Code::Blocks
  • Creating a simplistic game engine.
  • Loading and displaying a image tile set on the screen.
  • Basic use of mouse, keyboard, timing.



Our prerequisite for the tutorial is a simple tile set image:


I have made it using Gimp, we have 5 different tiles, from left to right: empty cell, living cell, new born cell, death cell and the mouse cursor.


Conway's Game of Life is a simulation of "living" cells, let's suppose our world is a big 2D grid, now let's suppose again that each cell in the grid can have 4 different states :
  • 0 > Empty cell , a void in the map.
  • 1 > A living cell.
  • 2 > A new born cell.
  • 3 > A dying cell.
Actually, only the first to states are really important, the other are only used in an intermediate state to process correctly the map, the time is measured in "ticks" every tick if an empty cell has exactly 3 adjacent living cells will generate a new born cell, and a living cell that has less than 2, or more than 3 adjacent cells will die, I'm going to show a way of making a program to simulate the game with c++ and then i will start with code::blocks + SDL:

//We need a grid to store data, we have a map of 50 x 50 cells
Uint8 CellMap[50][50];

// A temporary counter of surrounding cells 
Uint8 counter;

// Variables used when working with the 2d array "CellMap" 
Uint8 x,y;

//Now let's initialize the array, it's always a very good idea to initialize variables to prevent unexpected results in the program.

 for (x=0;x<50;x++){
     for (y=0;y<50;y++){
         CellMap[x][y]=0; //We will start with an empty map
     }; //end y for
 }; // end x for

//We will start with just 5 living cells in a configuration called "slider"
CellMap[1][5]=1;
CellMap[2][5]=1;
CellMap[3][5]=1;
CellMap[3][4]=1;
CellMap[2][3]=1;

 // program main loop
    bool done = false;
    while (!done) //Will make an infinity loop unless we set done=true
    {
//Clear screen with a light grey
myengine.FillColour(200,200,200);
//FIRST LOOP //x loop for for (x=1;x<50;x++){         //y loop for         for (y=1;y<50;y++){              //Counter of the adjacent cells                        Counter=0;             //Count the number of adjacent living cells             if (CellMap[x-1][y-1]==1 or     CellMap[x-1][y-1]==3)Counter++;             if (CellMap[x-1][y]==1 or       CellMap[x-1][y]==3)Counter++;             if (CellMap[x-1][y+1]==1 or     CellMap[x-1][y+1]==3)Counter++;             if (CellMap[x][y-1]==1 or       CellMap[x][y-1]==3)Counter++;             if (CellMap[x][y+1]==1 or       CellMap[x][y+1]==3)Counter++;             if (CellMap[x+1][y-1]==1 or     CellMap[x+1][y-1]==3)Counter++;             if (CellMap[x+1][y]==1 or       CellMap[x+1][y]==3)Counter++;             if (CellMap[x+1][y+1]==1 or     CellMap[x+1][y+1]==3)Counter++;             //minimum adjacent cells = 0             //maximum adjacent cells = 8             //if a cell has is dead "0" and is surrounded by 3 cells will born             if (CellMap[x][y]==0 and Counter==3)CellMap[x][y]=2; //Born            //if a cell is living "1" and is surrounded by less than 2 cells,            //or more than 3 cells, will die            // the problem is that if we change the state from 0 to 1 or 1 to 0,            //when we continue counting, the results will not be correct, so we           //use a temporary state (2 for new born and 3 for dying cell), so           //when we continue counting adjacent cells the result will be ok                     if (CellMap[x][y]==1){                 if (Counter<2 or Counter >3)CellMap[x][y]=3; //Die                 }                 //draw the cell on the screen                myengine.BlitTileset(x,y,CellMap[x][y]);         }; //End for y     };  //End for x //Update the screen with the back buffer
myengine.Flip();
} //SECOND LOOP //x loop for for (x=1;x<50;x++){         //y loop for         for (y=1;y<50;y++){         //now we clean the map with the final cell state (1 or 0)         if (CellMap[x][y]==2)CellMap[x][y]=1; //Born         if (CellMap[x][y]==3)CellMap[x][y]=0; //Die         //draw the cell on the screen         myengine.BlitTileset(x,y,CellMap[x][y]);     };  }; //update the screen
myengine.Flip();
//wait 50 miliseconds to limit frame rate
myengine.Wait(50);
} //End of main loop

Notice i have written a few lines of code with red color, I'm going to create a c++ class to encapsulate a simple engine so many SDL functions will be integrated in it, making easier the process to write programs; i have removed too code from the program to make it more readable, I will show the complete code later.

On the next post, our first Code::Blocks c++ project!

No comments: