Ich hab mal versucht das ungefähr so zu realisieren...
Code: Alles auswählen
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define VERSION 0.1
#define SUBVERSION 'b'
#define MAXLENGTH 100
#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3
typedef struct
{
int direction;
float x, y;
} block_info;
typedef struct
{
int eaten;
float x, y;
} fruit_struct;
static block_info snake[MAXLENGTH];
static SDL_Surface *screen;
static fruit_struct fruit;
static int length = 0;
static float level = 1.0;
static long double speed = 0.0;
void parameters (int *w, int *h, int *fullscreen, int argc, char *argv[]);
void draw_snake (int direction[], float newx[], float newy[]);
void draw_fruit ();
void new_fruit ();
void check_input (SDL_Event event, int *run, int *start);
int check_border_score (int *run, int *numeaten, int *score);
void move_snake (int direction[], float newx[], float newy[]);
void display_help ();
void pause (int *start);
void create_blocks (int nr, int pos);
void draw_end (int score);
int main (int argc, char *argv[])
{
SDL_Event event;
Uint16 black;
int run = 1, w = 800, h = 600, fullscreen = 0, direction[MAXLENGTH],
start, startdiff, diff, numeaten = 0, score = 0;
unsigned int frames = 0;
float newx[MAXLENGTH], newy[MAXLENGTH];
long double fps;
srand (time (NULL));
if (argc > 1)
parameters (&w, &h, &fullscreen, argc, argv);
if (SDL_Init (SDL_INIT_VIDEO) != 0)
{
printf ("Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
}
atexit (SDL_Quit);
if(TTF_Init () != 0)
{
printf("Unable to initialize TTF: %s\n", TTF_GetError ());
return 1;
}
if (fullscreen)
screen = SDL_SetVideoMode (w, h, 16, SDL_FULLSCREEN);
else
screen = SDL_SetVideoMode (w, h, 16, SDL_DOUBLEBUF);
if (screen == NULL)
{
printf ("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
black = SDL_MapRGB (screen -> format, 0, 0, 0);
snake[0].x = (float) (screen -> w / 2) - 10.0;
snake[0].y = (float) (screen -> h / 2) - 10.0;
snake[0].direction = LEFT;
create_blocks (5, 1);
fruit.eaten = 0;
new_fruit ();
SDL_Delay (500);
startdiff = SDL_GetTicks ();
while (run)
{
start = SDL_GetTicks ();
frames++;
while (SDL_PollEvent (&event))
{
switch (event.type)
{
case SDL_KEYDOWN: check_input (event, &run, &start);
break;
case SDL_QUIT: run = 0;
break;
}
}
SDL_FillRect (screen, NULL, black);
draw_snake (direction, newx, newy);
draw_fruit ();
check_border_score (&run, &numeaten, &score);
move_snake (direction, newx, newy);
diff = ((start - startdiff));
fps = (long double) frames / diff * 2;
speed = 1.0 / fps / level;
SDL_Delay (speed);
}
return 0;
}
void parameters (int *w, int *h, int *fullscreen, int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++)
{
if (strcmp (argv[i], "-w") == 0)
{
if (atoi (argv[i + 1]) >= 256)
*w = atoi (argv[i + 1]);
else
{
printf ("Window too small.\n");
exit (0);
}
}
else if (strcmp (argv[i], "-h") == 0)
{
if (atoi (argv[i + 1]) >= 256)
*h = atoi (argv[i + 1]);
else
{
printf ("Window too small.\n");
exit (0);
}
}
else if (strcmp (argv[i], "--help") == 0)
{
display_help ();
exit (0);
}
else if (strcmp (argv[i], "--full") == 0)
*fullscreen = 1;
}
}
void display_help ()
{
printf ("\nEatTheBlocks V%.1f%c\n", VERSION, SUBVERSION);
printf ("\nOptions:\n\t-w\t=\tspecify windows width\n");
printf ("\t-h\t=\tspecify window hight\n\t--full\t");
printf ("=\tstart game in fullscreen mode\n\t--help\t=\tshow this help\n");
}
void draw_snake (int direction[], float newx[], float newy[])
{
int i;
SDL_Rect dest;
Uint16 white;
dest.w = 10;
dest.h = 10;
for (i = 0; i < length; i++)
{
dest.x = snake[i].x;
dest.y = snake[i].y;
white = SDL_MapRGB (screen -> format, 255, 255, 255);
SDL_FillRect (screen, &dest, white);
direction[i] = snake[i].direction;
newx[i] = snake[i].x;
newy[i] = snake[i].y;
}
}
void draw_fruit ()
{
SDL_Rect dest;
Uint16 green;
dest.x = fruit.x;
dest.y = fruit.y;
dest.w = 10;
dest.h = 10;
green = SDL_MapRGB (screen -> format, 0, 255, 0);
SDL_FillRect (screen, &dest, green);
SDL_Flip (screen);
}
void new_fruit ()
{
fruit.x = (float) ((rand () % (screen -> w - 20)) + 5);
fruit.y = (float) ((rand () % (screen -> h - 20)) + 5);
}
void check_input (SDL_Event event, int *run, int *start)
{
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_p)
pause (start);
else if (key.sym == SDLK_ESCAPE)
*run = 0;
}
int check_border_score (int *run, int *numeaten, int *score)
{
if ((snake[0].x < 0) || ((snake[0].x + 10) > screen -> w))
{
printf ("Game over.\nScore: %d\n", *score);
*run = 0;
draw_end (*score);
return 1;
}
else if ((snake[0].y < 0) || ((snake[0].y + 10) > screen -> h))
{
printf ("Game over.\nScore: %d\n", *score);
*run = 0;
draw_end (*score);
return 1;
}
if ((snake[0].x < (fruit.x + 10) && snake[0].x > (fruit.x - 10)))
{
if ((snake[0].y < (fruit.y + 10) && snake[0].y > (fruit.y - 10)))
{
(*score) += (100 * level);
(*numeaten)++;
if (length < MAXLENGTH)
create_blocks (1, length);
new_fruit ();
level += 0.01;
}
}
return 0;
}
void move_snake (int direction[], float newx[], float newy[])
{
int i;
for (i = 0; i < length; i++)
{
if (i == 0)
{
if (snake[0].direction == UP)
snake[0].y -= 10.0;
else if (snake[0].direction == RIGHT)
snake[0].x += 10.0;
else if (snake[0].direction == DOWN)
snake[0].y += 10.0;
else if (snake[0].direction == LEFT)
snake[0].x -= 10.0;
}
else
{
snake[i].direction = direction[i - 1];
snake[i].x = newx[i - 1];
snake[i].y = newy[i - 1];
}
}
}
void pause (int *start)
{
int pausegame = 1, time1, time2;
SDL_Event event;
SDL_keysym key;
time1 = SDL_GetTicks ();
while (pausegame)
{
while (SDL_PollEvent (&event))
{
switch (event.type)
{
case SDL_KEYDOWN:
key = event.key.keysym;
if (key.sym == SDLK_p)
pausegame = 0;
break;
}
}
}
time2 = SDL_GetTicks ();
*start -= (time1 - time2);
}
void create_blocks (int nr, int pos)
{
int i;
for (i = 0; i < nr; i++, pos++)
{
if (snake[pos - 1].direction == UP)
{
snake[pos].x = snake[pos - 1].x;
snake[pos].y = snake[pos - 1].y + 10.0;
}
else if (snake[pos - 1].direction == DOWN)
{
snake[pos].x = snake[pos - 1].x;
snake[pos].y = snake[pos - 1].y - 10.0;
}
else if (snake[pos - 1].direction == RIGHT)
{
snake[pos].x = snake[pos - 1].x - 10.0;
snake[pos].y = snake[pos - 1].y;
}
else if (snake[pos - 1].direction == LEFT)
{
snake[pos].x = snake[pos - 1].x + 10.0;
snake[pos].y = snake[pos - 1].y;
}
snake[pos].direction = snake[pos - 1].direction;
}
length = pos;
}
void draw_end (int score)
{
SDL_Surface *text, *gameover;
SDL_Rect dest;
SDL_Color color = {0, 255, 0}, color2 = {255, 0, 0};
TTF_Font *font, *font2;
Uint16 rectcolor;
char charscore[30], buffer[10];
strcpy (charscore, "Score: \0");
sprintf (buffer, "%d", score);
strcat (charscore, buffer);
dest.x = (screen -> w / 2) - 100;
dest.y = (screen -> h / 2) - 50;
dest.w = 210;
dest.h = 40;
rectcolor = SDL_MapRGB (screen -> format, 0, 0, 0);
SDL_FillRect (screen, NULL, rectcolor);
rectcolor = SDL_MapRGB (screen -> format, 255, 255, 255);
SDL_FillRect (screen, &dest, rectcolor);
font = TTF_OpenFont ("/usr/share/fonts/truetype/msttcorefonts/arial.ttf", 30);
font2 = TTF_OpenFont ("/usr/share/fonts/truetype/msttcorefonts/arial.ttf", 35);
if (font != NULL && font2 != NULL)
{
text = TTF_RenderText_Solid (font, charscore, color);
gameover = TTF_RenderText_Solid (font2, "GAME OVER", color2);
if (text != NULL && gameover != NULL)
{
SDL_BlitSurface (text, NULL, screen, NULL);
SDL_BlitSurface (gameover, NULL, screen, &dest);
SDL_Flip (screen);
SDL_Delay (3000);
}
else
printf ("Unable to blit text: %s\n", TTF_GetError ());
}
else
printf ("Unable to load font: %s\n", TTF_GetError ());
}
Mir ist auch aufgefallen, dass die Geschwindigkeit schwankt.
Außerdem ist diese Methode etwas unsicher. Wenn es mehr Frames gibt als unsigned int fast, hab ich ein Problem...
Unsigned int geht zwar bis 4.294.967.295 (also müsste man ziiiiiiiemlich lange spielen
), trotzdem ist das aber eine Unsicherheit.