蛇是这个游戏的主角,要实现的功能也是最复杂的一个。因为蛇不止有属性,还有行为。它会动,还会吃东西,还会长大!而且还会死!这是很要命的。我一向看不懂复杂的代码,也写不出复杂的代码。所以对于蛇,我很纠结,如何才能简单的实现它。
毫无质疑的一点是,食物具有的属性,蛇也具有。蛇必须存在于世界中,有大小和位置以及颜色。这样最起码可以推测出一个蛇的简单定义。但是这还远远不够,蛇是活的,它能动,就必须有速度和方向,它能吃,就必须能长大。所以,抛开其它的一切,它最简单的形式起码也得这样:
typedef struct Snake { World *world; int x, y, size; SDL_Color color; int speed, length, direction; struct Body { int x, y; int direction; struct Body *next; } *body; } Snake;
而我要的就是简单,于是乎,一咬牙一跺脚,就它了!
既然选择了创造这样的一条蛇,那我也只能接受创造它了。
extern Snake * SNK_CreateSnake(World *world, int size, int x, int y); extern void SNK_DestroySnake(Snake *snake);
这样的蛇,要操控它的属性,就必须实现多个函数。而由于属性之间的相互联系,就得实现更多的函数。例如,改变蛇的方向,会有两种结果:1. 能动,2. 会死!吃掉食物,也有两种结果:1. 能长大,2. 被撑死。所以,我把这些函数一一细分,分为属性函数、行为函数以及附加函数。
属性相关函数:
extern void SNK_SetSnakeSpeed(Snake *snake, int speed); extern void SNK_SetSnakeDirection(Snake *snake, int direction); extern void SNK_SetSnakeColor(Snake *snake, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
行为相关函数:
extern void SNK_MoveSnake(Snake *snake); extern void SNK_GrowSnake(Snake *snake);
附加函数:
extern int SNK_HasIntersection(Snake *snake, SDL_Rect rect); extern int SNK_GetSnakeStatus(Snake *snake);
当这样一条蛇被完完整整的创造出来,我就可以毫无顾虑的让它暴露在世界之中。
extern void SNK_DrawSnake(Snake *snake);
这是我目前所能想到的最简单的方式去实现一条蛇了。对,只是蛇!你会发现,从头到位,贪吃蛇游戏都是蛇在吃食物,但是我并没有在蛇的定义中,包含任何和食物相关的函数或变量, 我只是站在一个造物主的角度去创建生命罢了。蛇吃什么不是我要关心的,我创造了它,并制作了规则,让它去适应世界。
以下是snk-snake.h文件中的完整蛇定义:
#ifndef SNK_SNAKE_H_HEADER #define SNK_SNAKE_H_HEADER #define SNAKE_UP (1 << 0) #define SNAKE_LEFT (1 << 1) #define SNAKE_DOWN (1 << 2) #define SNAKE_RIGHT (1 << 3) #define SNAKE_DIED (1 << 4) #define SNAKE_MOVABLE (1 << 5) #define SNAKE_INIT_COLOR 0, 0xff, 0, 0xff #define SNAKE_DIED_COLOR 0xff, 0, 0, 0xff #define SNAKE_CTMV_COLOR 0xff, 0xff, 0, 0xff #define SNAKE_INIT_SPEED 900 #include "snk-world.h" typedef struct Snake { World *world; int x, y, size; SDL_Color color; int speed, length, direction; struct Body { int x, y; int direction; struct Body *next; } *body; } Snake; extern Snake * SNK_CreateSnake(World *world, int size, int x, int y); extern void SNK_DestroySnake(Snake *snake); extern int SNK_HasIntersection(Snake *snake, SDL_Rect rect); extern void SNK_MoveSnake(Snake *snake); extern void SNK_DrawSnake(Snake *snake); extern void SNK_GrowSnake(Snake *snake); extern int SNK_GetSnakeStatus(Snake *snake); extern void SNK_SetSnakeSpeed(Snake *snake, int speed); extern void SNK_SetSnakeDirection(Snake *snake, int direction); extern void SNK_SetSnakeColor(Snake *snake, Uint8 r, Uint8 g, Uint8 b, Uint8 a); #endif
最开始的几行宏定义是蛇的方向,然后是蛇的状态:已死或者可以移动。最下面几行宏只是为了提供方便,仅在设置属性时使用。SNAKE_INIT_SPEED设置为900毫秒,表示蛇的速度,它是时间值,而不是移动的距离。