蛇是这个游戏的主角,要实现的功能也是最复杂的一个。因为蛇不止有属性,还有行为。它会动,还会吃东西,还会长大!而且还会死!这是很要命的。我一向看不懂复杂的代码,也写不出复杂的代码。所以对于蛇,我很纠结,如何才能简单的实现它。

  毫无质疑的一点是,食物具有的属性,蛇也具有。蛇必须存在于世界中,有大小和位置以及颜色。这样最起码可以推测出一个蛇的简单定义。但是这还远远不够,蛇是活的,它能动,就必须有速度和方向,它能吃,就必须能长大。所以,抛开其它的一切,它最简单的形式起码也得这样:

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毫秒,表示蛇的速度,它是时间值,而不是移动的距离。

[C入门 - 游戏编程系列] 贪吃蛇篇(三) - 蛇定义的更多相关文章

  1. [C入门 - 游戏编程系列] 贪吃蛇篇(一) - 世界定义

    每个游戏都有一个很明确的目的或者说游戏主题,贪吃蛇的目的很明确:蛇找到并吃掉食物.只有目的是很无聊的,算不上一个好游戏.所以设计者增加了创意:1. 吃掉食物后蛇会增长:2. 吃掉食物后分数会增加.有些 ...

  2. [C入门 - 游戏编程系列] 贪吃蛇篇(六) - 蛇实现

    这一篇是关于设置蛇的属性的,接上一篇(五). 设置蛇的速度,很简单,只要不是负数就行了. void SNK_SetSnakeSpeed(Snake *snake, int speed) { ) sna ...

  3. [C入门 - 游戏编程系列] 贪吃蛇篇(四) - 食物实现

    由于食物是贪吃蛇游戏中最简单的一部分,而且和其他部分关联性不强,基本上是一个独立的部分,所以我打算先实现它. 我的想法是食物必须在世界中才能被创造出来,也就是说,先有世界再有食物,所以我得先判断世界是 ...

  4. [C入门 - 游戏编程系列] 贪吃蛇篇(二) - 食物定义

    游戏中的食物没有那么多复杂属性,特别是贪吃蛇游戏中,我把食物看待的很简单: 1. 它必须属于世界,才能出现在世界.不可能一个不属于世界的食物,出现在世界中:但是可能存在着一个食物,它属于世界,但是却没 ...

  5. [C入门 - 游戏编程系列] 贪吃蛇篇(五) - 蛇实现

    因为已经写了食物的实现,所以我不知道到底是该先写世界的实现还是蛇的实现.因为世界就是一个窗口,可以立刻在世界中看到食物的样子,对于大多数人来说,如果写完代码立刻就能看到效果,那就再好不过了.可是,我最 ...

  6. [C入门 - 游戏编程系列] 序言篇

    记得学习C语言的时候,看着别人能写各种各样的小游戏和小软件,甚是羡慕.而自己,虽然说语法都会,但是真正上手写个几百行的代码,就显得力不从心.曾经一度很是郁闷,看过一些书,大都处于教语法的层面,有些涉及 ...

  7. [C入门 - 游戏编程系列] 环境篇

    这一系列笔记的代码都是在Ubuntu 14.04下编码并测试的,原因无他,因为我笔记本电脑只装了一个Ubuntu系统,其中唯一使用的第三方库SDL也是开源并且跨平台的.所以即使你用的是Windows或 ...

  8. SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行)

    前言 本篇继续玩转模块的内容,关于索引在SQL Server的位置无须多言,本篇将分析如何利用Hint引导语句充分利用索引进行运行,同样,还是希望扎实掌握前面一系列的内容,才进入本模块的内容分析. 闲 ...

  9. SQL Server 调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行)

    前言 本篇继续玩转模块的内容,关于索引在SQL Server的位置无须多言,本篇将分析如何利用Hint引导语句充分利用索引进行运行,同样,还是希望扎实掌握前面一系列的内容,才进入本模块的内容分析. 闲 ...

随机推荐

  1. CVE-2014-3153 com.geohot.towelroot

    futex-prevent-requeue-pi-on-same-futex.patch futex: Forbid uaddr == uaddr2 ) If uaddr == uaddr2, the ...

  2. 分享注册AltiumDesignerLive官网账号注册方法教程

    在Altium中国注册Live账号时,Altium会要求填写一些个人信息来申请账号提交账号后,等很长一段时间都没有得到回复.于是选择另一种方法注册打开Altium在俄罗斯的网址 http://ru.a ...

  3. android 让图片充满整个屏幕

    方法1: <ImageView android:id="@+id/imageView1" android:layout_width="fill_parent&quo ...

  4. bzoj 1191

    http://www.lydsy.com/JudgeOnline/problem.php?id=1191 二分+二分图匹配. 首先二分可以答对前mid道题,然后做二分图. 左边是题目,右边是锦囊. 做 ...

  5. Linux磁盘及文件系统管理 2---- 使用fdisk进行磁盘管理

    1 FDISK分区工具 1 fsidk是来自IBM的分区工具,支持绝大多数的操作系统,几乎所有的Linux都装有fdisk 2 fdisk是一个支持MBR的分区工具,如果要使用GPT的话我们无法使用f ...

  6. Android去除系统自带动画的两种方法

    方法一: 在startActivity()或者finish()后紧跟调用: ((Activity) mContext).overridePendingTransition(0, 0); 方法二: 在一 ...

  7. c指针点滴2之比大小

    #include <stdio.h> #include <stdlib.h> void main2() { ]={,,,4.5}; ]; ]; if(p1<p2) { p ...

  8. C/C++基础概念

    1.类占用的内存大小: 1)在不同位数的操作系统下,各种数据类型所占用的内存大小:32位和64位操作系统 http://blog.csdn.net/b_zhang/article/details/68 ...

  9. javascript实现的有缩略图功能的幻灯片切换效果

    不久前写了一个简单的图片效果,没想到那么快就要用到项目中,所以功能方面要丰富一下: 主要改进: 1# 用圆点代替之前简单的页数显示,并且点击圆点可以显示对应图片: 2# 点击圆点,显示对应图片的缩略图 ...

  10. hdu 4666 Hyperspace

    曼哈顿距离,两个点设为(x1,y1),(x2,y2),其距离为|x1-x2|+|y1-y2| #include <cstdio> #include <set> #include ...