[C++ & SDL] Unfinished Snake Game
If I'm not allowed to post this here (in case this is only for discussing), please make me aware of that.
I found a source code/tutorial for a very basic snake game in C using SDL, so I decided to try to do a port to C++, and hopefully to the Maemo platform at the end.
Unfortunately, I do not believe I have the needed C++ knowledge etc. yet, so therefore I'm posting the current source code. Basically all I've done so far, is the porting to C++, and a little other changes.
It is not commented, and _definitely_ not perfect. So it can be optimized a lot!
You need to download a font from somewhere and use it. I'm not sure I'm allowed to use the borgnine font I found on dafont.
When you've got a font either edit TTF_OpenFont(); or make a folder called "data", put the font in there and then rename the font to "borgnine.ttf".
Screenshot:
http://img683.imageshack.us/img683/1...eenshot2xd.png
Compile with (Linux):
g++ -o main main.cpp -lSDL -lSDL_image -lSDL_ttf
Code:
#include <stdlib.h>
#include <string>
#include <sstream>
#include <iostream>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#include <time.h>
#define N 500 /*snake length*/
#define W 1000
#define NODESIZE 10 /*node height & width*/
#define WINSIZEW 800
#define WINSIZEH 480
typedef enum {Up, Down, Right, Left}TDirection; //Possible directions
SDL_Surface* screen = NULL;
SDL_Surface* Table[N] = {NULL};
SDL_Surface* blank;
SDL_Surface* message = NULL;
SDL_Surface* puce; //Snake puce
//FONT
TTF_Font *font = NULL;
SDL_Color textColor = {0, 0, 0};
SDL_Rect Tabpos[N], ppuce, Wallpos[W];
//WALLS
SDL_Rect left, right, top, bot;
bool running = true;
int NodeCounter;
int score = 0;
TDirection direction;
SDL_TimerID timer;
Uint32 Anime_it (Uint32, void *);
int snakeColl(void);
int consoleOutput(const char* text);
void initWalls(void);
void Quitter(void); //will be executed when exiting
void SetPos(void);
void MoveSnake(void);
void Show(void);
void PurgeScreen(void);
void SetPuce(void);
void Lose(void);
void freeNodes(void);
void AddNode(void);
int main (int argc, char** argv)
{
Uint32 speed; //game speed
SDL_Event event;
int done;
int i;
srand (time(NULL));
i = SDL_Init(SDL_INIT_VIDEO|SDL_DOUBLEBUF|SDL_INIT_TIMER);
if (i < 0){
exit(EXIT_FAILURE);
}
atexit (Quitter);
screen = SDL_SetVideoMode(WINSIZEW, WINSIZEH, 16, SDL_HWSURFACE);
if (screen == NULL){
exit(EXIT_FAILURE);
}
SDL_WM_SetCaption("SnakeDL", NULL); //S(nake)DL
//Initialisations of fonts
if (TTF_Init() == -1)
{
consoleOutput("Error TTF_Init");
return false;
}
font = TTF_OpenFont("./data/borgnine.ttf", 28);
if (font == NULL)
{
//consoleOutput(("Error %s", TTF_GetError()));
return false;
}
speed = 80;
//done = 1;
NodeCounter = 5;
direction = Right;
initWalls();
Table[0] = SDL_CreateRGBSurface(SDL_HWSURFACE, NODESIZE, NODESIZE, 16, 0, 0, 0, 0);
SDL_FillRect(Table[0], NULL, SDL_MapRGB(Table[0]->format, 0, 255, 0));
Tabpos[0].x = screen->w/2;
Tabpos[0].y = screen->h/2;
for (i = 1; i < NodeCounter; i++){
Table[i] = SDL_CreateRGBSurface(SDL_HWSURFACE, NODESIZE, NODESIZE, 16, 0, 0, 0, 0);
SDL_FillRect (Table[i], NULL, SDL_MapRGB (Table[i]->format, 0, 0, 0));
Tabpos[i].x = Tabpos[i-1].x - NODESIZE;
Tabpos[i].y = screen->h/2;
}
SDL_ShowCursor(0);
Show();
SDL_Flip(screen);
timer = SDL_AddTimer(1, Anime_it, &speed);
SetPuce();
while (running){
SDL_WaitEvent(&event);
switch (event.type){
case SDL_QUIT:
running = false;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym){
case SDLK_w:
if (direction != Down)
direction = Up;
break;
case SDLK_s:
if (direction != Up)
direction = Down;
break;
case SDLK_d:
if (direction != Left)
direction = Right;
break;
case SDLK_a:
if (direction != Right)
direction = Left;
break;
case SDLK_u: //INCREASE SPEED
if ((speed-5)>0)
speed -= 5;
break;
case SDLK_l: //DECREASE SPEED
if ((speed+5)<100)
speed += 5;
break;
case SDLK_q:
Quitter();
break;
}
break;
}//SWITCH
} //WHILE
return 0;
}
int consoleOutput(const char* text)
{
using namespace std;
cout << text << endl;
return 0;
}
void MoveSnake()
{
switch (direction){
case Up:
if ((Tabpos[0].y - NODESIZE) >= 10)
Tabpos[0].y -= NODESIZE;
else
Lose();
//Tabpos[0].y -= NODESIZE;
break;
case Down:
if ((Tabpos[0].y + NODESIZE) < (screen->h - 10))
Tabpos[0].y += NODESIZE;
else
Lose();
//Tabpos[0].y += NODESIZE;
break;
case Right:
if ((Tabpos[0].x + NODESIZE) < (screen->w - 10))
Tabpos[0].x += NODESIZE;
else
Lose();
//Tabpos[0].x += NODESIZE;
break;
case Left:
if ((Tabpos[0].x - NODESIZE) >= 10)
Tabpos[0].x -= NODESIZE;
else
Lose();
//Tabpos[0].x -= NODESIZE;
break;
}
//Incase teleporting from wall to opposite wall instead of loosing game
/*if ((Tabpos[0].x == WINSIZEW ))
Tabpos[0].x = 0;
else if ((Tabpos[0].x == 0))
Tabpos[0].x = WINSIZEW;
else if ((Tabpos[0].y == WINSIZEH))
Tabpos[0].y = 0;
else if ((Tabpos[0].y == 0))
Tabpos[0].y = WINSIZEH;*/
if ((Tabpos[0].x == ppuce.x) && (Tabpos[0].y == ppuce.y))
{
score++;
AddNode();
}
if (snakeColl())
Lose();
}
void SetPos(void)
{
int i;
for (i = (NodeCounter-1); i>0; i--)
{
Tabpos[i].x = Tabpos[i-1].x;
Tabpos[i].y = Tabpos[i-1].y;
}
}
void initWalls(void)
{
left.x = 0;
left.y = 0;
left.w = 10;
left.h = WINSIZEH;
right.x = (WINSIZEW - 10);
right.y = 0;
right.w = 10;
right.h = WINSIZEH;
top.x = 10;
top.y = 0;
top.w = (WINSIZEW - 20);
top.h = 10;
bot.x = 10;
bot.y = (WINSIZEH - 10);
bot.w = (WINSIZEW - 20);
bot.h = 10;
}
void Show(void)
{
int i;
int y;
char intScore[32];
SDL_Rect msgOffset;
for (i=0; i < NodeCounter; i++)
SDL_BlitSurface(Table[i], NULL, screen, &Tabpos[i]);
SDL_BlitSurface(puce, NULL, screen, &ppuce);
SDL_FillRect(screen, &left, SDL_MapRGB(screen->format, 0, 0, 0));
SDL_FillRect(screen, &right, SDL_MapRGB(screen->format, 0, 0, 0));
SDL_FillRect(screen, &top, SDL_MapRGB(screen->format, 0, 0, 0));
SDL_FillRect(screen, &bot, SDL_MapRGB(screen->format, 0, 0, 0));
msgOffset.x = 20;
msgOffset.y = (WINSIZEH - 38);
sprintf(intScore, "Score: %d", score);
message = TTF_RenderText_Solid(font, intScore, textColor);
if (message == NULL)
{
consoleOutput("Error TTF_RenderText_solid in Show()");
}
SDL_BlitSurface(message, NULL, screen, &msgOffset);
}
void Quitter(void)
{
freeNodes();
SDL_FreeSurface(puce);
SDL_FreeSurface(screen);
SDL_FreeSurface(message);
running = false;
SDL_Quit();
}
void PurgeScreen(void)
{
SDL_Rect p;
p.x = 0;
p.y = 0;
blank = SDL_CreateRGBSurface(SDL_HWSURFACE, screen->w, screen->h, 16, 0, 0, 0, 0);
SDL_FillRect(blank, NULL, SDL_MapRGB(blank->format, 189, 220, 144));
SDL_BlitSurface(blank, NULL, screen, &p);
SDL_FreeSurface(blank);
}
void SetPuce()
{
int genx, geny, flag = 1, cpt;
while (flag)
{
flag = 0;
genx = (rand() % ((WINSIZEW - 10)/10))*NODESIZE;
for (cpt=10; cpt < NodeCounter; cpt++)
if (genx == Tabpos[cpt].x)
{
flag = 1;
break;
}
}
flag = 1;
while (flag)
{
flag = 0;
geny = (rand() % ((WINSIZEH - 10)/10))*NODESIZE;
for (cpt=10; cpt < NodeCounter; cpt ++)
if (geny == Tabpos[cpt].y)
{
flag = 1;
break;
}
}
puce = SDL_CreateRGBSurface(SDL_HWSURFACE, NODESIZE, NODESIZE, 16, 0, 0, 0, 0);
SDL_FillRect (puce, NULL, SDL_MapRGB (puce->format, 0, 0, 0));
ppuce.x = genx;
ppuce.y = geny;
SDL_BlitSurface(puce, NULL, screen, &ppuce);
}
Uint32 Anime_it(Uint32 interval, void *param)
{
Uint32 *t = (Uint32*)param;
SDL_Delay (*t);
MoveSnake();
SetPos();
PurgeScreen();
Show();
SDL_Flip(screen);
return interval;
}
void Lose(void)
{
SDL_RemoveTimer(timer);
//running = false;
Quitter();
}
void freeNodes(void)
{
int i;
for (i = 0; i < NodeCounter; i++)
SDL_FreeSurface(Table[i]);
}
void AddNode(void)
{
NodeCounter++;
Table[NodeCounter-1] = SDL_CreateRGBSurface(SDL_HWSURFACE, NODESIZE, NODESIZE, 16, 0, 0, 0, 0);
SDL_FillRect(Table[NodeCounter-1], NULL, SDL_MapRGB (Table[NodeCounter-1]->format, 0, 0, 0));
SetPuce();
}
int snakeColl(void)
{
int i, cl = 0;
for (i = 3; i < NodeCounter; i++)
if ((Tabpos[0].x == Tabpos[i].x) && (Tabpos[0].y == Tabpos[i].y))
{
cl = 1;
break;
}
return cl;
}
Thanks to:
http://www.cprogrammingreference.com...ming/Snake.php
|