EatTheBlocks (bitte fragt mich nicht, wie ich auf diesen Namen gekommen bin... war schon ziemlich spät gestern

Ich hab das Spiel zu 100% selbst programmiert und dabei auch mein neues SDL-Wissen verwendet. Auch die Bilder hab ich selbst "gegimpt" (sogar den weißen 10*10 Pixel Block


Programmiert hab ich bis jetzt ca. 4 Stunden, davon ca. 1 Stunde Fehlersuche

Bis vorhin hatte ich noch einen Bug (der eigentlich gar keiner war). Die Blöcke werden immer an die Position des vorhergehenden gerückt. Das Programm blitete aber so schnell, dass schließlich nur noch ein Block zu sehen war. Das Problem bin ich jetzt umgangen, indem ich die Geschwindigkeit höher gestellt habe

Ich möchte euch nicht nur bitten Verbesserungsvorschläge zum Spiel, sondern auch zu meinem Programmierstil abzugeben. Diese globalen statischen Variablen mag ich auch nicht, die werden in der nächsten Version verschwinden. Im Buch wurden sie aber überall verwendet...
Was ich noch ändern will/werde:
* die Surface besser anpassen (gameover richtig platzieren usw.)
* Prüfung ob das Fenster groß genug eingestellt ist (-h, -w)
* "wachsende" Schlange
* steigende Geschwindigkeit
* zufälligere Zufallszahlen

* einen Counter der die Punkte zählt und in eine Datei schreibt *
* Fullscreen support
* die ganzen Arrays in Listen umwandeln, da jetzt noch ziemlich viel Speicher verschwendet wird **
* ausführliche englische Dokumentierung
* Kann man ASCII-Zeichen auf ein Surface schreiben?? Oder muss ich dann immer ein Bild erstellen?
** valgrind meldet bei mir einen Speicher-Leak (16 Byte). Ich hab keine Ahnung was das sein könnte. Die Bilder hab ich ja alle freigegeben. Kann es sein, dass das von einer SDL-Lib verursacht wird?
Hier ist der Code:
Code: Alles auswählen
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define VERSION 0.1
#define MAXLENGTH 15
#define MAXSPEED 1
#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3
typedef struct
{
int direction;
int x, y;
} block_info;
typedef struct
{
int x, y;
int eaten;
} fruit_struct;
static block_info snake[MAXLENGTH];
static SDL_Surface *screen, *block, *fruit_pic;
static fruit_struct fruit;
static int length = 3;
static float speed = 0.75;
void parameters (int *w, int *h, int argc, char *argv[]);
void draw_snake (int direction[], int newx[], int newy[]);
void draw_fruit ();
void new_fruit ();
void check_input (SDL_Event event);
void check_border_score ();
void move_snake (int direction[], int newx[], int newy[]);
void display_help ();
int main (int argc, char *argv[])
{
SDL_Surface *temp, *background;
SDL_Rect src, dest;
SDL_Event event;
int w = 800, h = 600, direction[MAXLENGTH], newx[MAXLENGTH], newy[MAXLENGTH];
char *path_block = "./pics/block.bmp", *background_path = "./pics/background.bmp", *fruit_path = "./pics/fruit.bmp";
parameters (&w, &h, argc, argv);
if (SDL_Init (SDL_INIT_VIDEO) != 0)
{
printf ("Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
}
atexit (SDL_Quit);
screen = SDL_SetVideoMode (w, h, 16, SDL_DOUBLEBUF);
if (screen == NULL)
{
printf ("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
background = IMG_Load (background_path);
if (background == NULL)
{
printf ("Unable to load background.\n");
return 1;
}
fruit_pic = IMG_Load (fruit_path);
if (fruit_pic == NULL)
{
printf ("Unable to load picture.\n");
return 1;
}
src.x = 0;
src.y = 0;
src.w = screen -> w;
src.h = screen -> h;
dest = src;
SDL_BlitSurface (background, &src, screen, &dest);
temp = IMG_Load (path_block);
if (temp == NULL)
{
printf ("Unable to load picture.\n");
return 1;
}
block = SDL_DisplayFormat (temp);
SDL_FreeSurface (temp);
snake[0].x = (float) screen -> w / 2;
snake[0].y = (float) screen -> h / 2;
snake[0].direction = LEFT;
snake[1].x = (float) snake[0].x + block -> w;
snake[1].y = (float) snake[0].y;
snake[1].direction = LEFT;
snake[2].x = (float) snake[1].x + block -> w;
snake[2].y = (float) snake[1].y;
snake[2].direction = LEFT;
fruit.eaten = 0;
new_fruit ();
SDL_Delay (1000);
while (1)
{
draw_snake (direction, newx, newy);
draw_fruit ();
SDL_PollEvent (&event);
check_border_score ();
switch (event.type)
{
case SDL_KEYDOWN: check_input (event);
break;
case SDL_QUIT: exit (0);
}
SDL_BlitSurface (background, &src, screen, &dest);
move_snake (direction, newx, newy);
}
SDL_FreeSurface (background);
SDL_FreeSurface (block);
return 0;
}
void parameters (int *w, int *h, int argc, char *argv[])
{
int i;
for (i = 0; i < argc; i++)
{
if (strcmp (argv[i], "-w") == 0)
*w = atoi (argv[i + 1]);
else if (strcmp (argv[i], "-h") == 0)
*h = atoi (argv[i + 1]);
else if (strcmp (argv[i], "--help") == 0)
{
display_help ();
exit (0);
}
}
}
void display_help ()
{
printf ("\nEatTheBlocks V%.1f\n", VERSION);
printf ("\nOptions:\n\t-w\t=\tspecify windows width\n\t-h\t=\tspecifiy window hight\n\t--help\t=\tshow this help\n");
}
void draw_snake (int direction[], int newx[], int newy[])
{
int i;
SDL_Rect src, dest;
src.x = 0;
src.y = 0;
src.w = block -> w;
src.h = block -> h;
dest.w = block -> w;
dest.h = block -> h;
for (i = 0; i < length; i++)
{
dest.x = snake[i].x;
dest.y = snake[i].y;
SDL_BlitSurface (block, &src, screen, &dest);
}
SDL_Flip (screen);
for (i = 0; i < length; i++)
{
direction[i] = snake[i].direction;
newx[i] = snake[i].x;
newy[i] = snake[i].y;
}
}
void draw_fruit ()
{
SDL_Rect src, dest;
src.x = 0;
src.y = 0;
src.w = fruit_pic -> w;
src.h = fruit_pic -> h;
dest.x = fruit.x;
dest.y = fruit.y;
dest.w = fruit_pic -> w;
dest.h = fruit_pic -> h;
SDL_BlitSurface (fruit_pic, &src, screen, &dest);
SDL_Flip (screen);
}
void new_fruit ()
{
fruit.x = rand () % screen -> w;
fruit.y = rand () % screen -> h;
}
void check_input (SDL_Event event)
{
SDL_keysym key = event.key.keysym;
if (key.sym == SDLK_UP && snake[0].direction != DOWN)
snake[0].direction = UP;
else if (key.sym == SDLK_RIGHT && snake[0].direction != LEFT)
snake[0].direction = RIGHT;
else if (key.sym == SDLK_DOWN && snake[0].direction != UP)
snake[0].direction = DOWN;
else if (key.sym == SDLK_LEFT && snake[0].direction != RIGHT)
snake[0].direction = LEFT;
else if (key.sym == SDLK_ESCAPE)
exit (0);
}
void check_border_score ()
{
SDL_Surface *gameover;
SDL_Rect src, dest;
if ((snake[0].x < 0) || ((snake[0].x + block -> w) > screen -> w) || (snake[0].y < 0) || ((snake[0].y + block -> h) > screen -> h))
{
printf ("Game over.\n");
gameover = IMG_Load ("./pics/gameover.bmp");
if (gameover == NULL)
{
printf ("Unable to load picture.\n");
exit (0);
}
src.x = 0;
src.y = 0;
src.w = gameover -> w;
src.h = gameover -> h;
dest.x = screen -> w / 3;
dest.y = screen -> h / 3;
dest.w = gameover -> w;
dest.h = gameover -> h;
SDL_BlitSurface (gameover, &src, screen, &dest);
SDL_FreeSurface (gameover);
SDL_Flip (screen);
SDL_Delay (5000);
exit (0);
}
if ((snake[0].x < (fruit.x + fruit_pic -> w) && snake[0].x > (fruit.x - fruit_pic -> w)) && (snake[0].y < (fruit.y + fruit_pic -> h) && snake[0].y > (fruit.y - fruit_pic -> h)))
new_fruit ();
}
void move_snake (int direction[], int newx[], int newy[])
{
int i;
for (i = 0; i < length; i++)
{
if (i == 0)
{
if (snake[0].direction == UP)
snake[0].y -= (speed * (block -> h));
else if (snake[0].direction == RIGHT)
snake[0].x += (speed * (block -> w));
else if (snake[0].direction == DOWN)
snake[0].y += (speed * (block -> h));
else if (snake[0].direction == LEFT)
snake[0].x -= (speed * (block -> w));
}
else
{
snake[i].direction = direction[i - 1];
snake[i].x = newx[i - 1];
snake[i].y = newy[i - 1];
}
}
}
Kompilieren mit:
Code: Alles auswählen
gcc -o eat EatTheBlocks.c -Wall `sdl-config --cflags --libs` -lSDL_image
Eigene Bilder einfach in den Ordner ./pics kopieren und entsprechend umbenennen. Ich habe 16 Bit RGB (565) Bilder verwendet.
Das Programm hab ich bis jetzt nur unter Ubuntu getestet, für Windows muss ich dann noch die ganzen Libs runterladen...

Bevor ichs vergesse: das Spiel ist entweder aus, wenn man gegen den Bildrand fährt, Escape gedrückt wird oder auf Schließen geklickt wird.
Hier noch ein Link zum Code inklusive Bilder:
*klick*
Von 2 MB auf 6.6 Kb gezippt (für alle mit langsamen Internet

Zurzeit liegt das Archiv noch auf meinem Webspace meiner ehemaligen Homepage (besteht inzwischen nur mehr aus 1 weißen Seite). Ich sollte aber noch von meinem ISP 500 MB Webspace gratis bekommen... muss ich mir mal genau ansehen.
Zum rechtlichen...

Das Programm darf frei weiterverbreitet und verändert werden. Ich übernehme keine Haftung für eventuell entstehende Schäden. Kann jedoch bestätigen, dass das Programm bei mir ohne Probleme funktioniert. Blabla...
Ok, das wars

Achja, wenn ich heute nicht mehr antworte, dann höchstwahrscheinlich die ganze nächste Woche nicht
