[C入门 - 游戏编程系列] 贪吃蛇篇(三) - 蛇定义
蛇是这个游戏的主角,要实现的功能也是最复杂的一个。因为蛇不止有属性,还有行为。它会动,还会吃东西,还会长大!而且还会死!这是很要命的。我一向看不懂复杂的代码,也写不出复杂的代码。所以对于蛇,我很纠结,如何才能简单的实现它。
毫无质疑的一点是,食物具有的属性,蛇也具有。蛇必须存在于世界中,有大小和位置以及颜色。这样最起码可以推测出一个蛇的简单定义。但是这还远远不够,蛇是活的,它能动,就必须有速度和方向,它能吃,就必须能长大。所以,抛开其它的一切,它最简单的形式起码也得这样:
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入门 - 游戏编程系列] 贪吃蛇篇(三) - 蛇定义的更多相关文章
- [C入门 - 游戏编程系列] 贪吃蛇篇(一) - 世界定义
每个游戏都有一个很明确的目的或者说游戏主题,贪吃蛇的目的很明确:蛇找到并吃掉食物.只有目的是很无聊的,算不上一个好游戏.所以设计者增加了创意:1. 吃掉食物后蛇会增长:2. 吃掉食物后分数会增加.有些 ...
- [C入门 - 游戏编程系列] 贪吃蛇篇(六) - 蛇实现
这一篇是关于设置蛇的属性的,接上一篇(五). 设置蛇的速度,很简单,只要不是负数就行了. void SNK_SetSnakeSpeed(Snake *snake, int speed) { ) sna ...
- [C入门 - 游戏编程系列] 贪吃蛇篇(四) - 食物实现
由于食物是贪吃蛇游戏中最简单的一部分,而且和其他部分关联性不强,基本上是一个独立的部分,所以我打算先实现它. 我的想法是食物必须在世界中才能被创造出来,也就是说,先有世界再有食物,所以我得先判断世界是 ...
- [C入门 - 游戏编程系列] 贪吃蛇篇(二) - 食物定义
游戏中的食物没有那么多复杂属性,特别是贪吃蛇游戏中,我把食物看待的很简单: 1. 它必须属于世界,才能出现在世界.不可能一个不属于世界的食物,出现在世界中:但是可能存在着一个食物,它属于世界,但是却没 ...
- [C入门 - 游戏编程系列] 贪吃蛇篇(五) - 蛇实现
因为已经写了食物的实现,所以我不知道到底是该先写世界的实现还是蛇的实现.因为世界就是一个窗口,可以立刻在世界中看到食物的样子,对于大多数人来说,如果写完代码立刻就能看到效果,那就再好不过了.可是,我最 ...
- [C入门 - 游戏编程系列] 序言篇
记得学习C语言的时候,看着别人能写各种各样的小游戏和小软件,甚是羡慕.而自己,虽然说语法都会,但是真正上手写个几百行的代码,就显得力不从心.曾经一度很是郁闷,看过一些书,大都处于教语法的层面,有些涉及 ...
- [C入门 - 游戏编程系列] 环境篇
这一系列笔记的代码都是在Ubuntu 14.04下编码并测试的,原因无他,因为我笔记本电脑只装了一个Ubuntu系统,其中唯一使用的第三方库SDL也是开源并且跨平台的.所以即使你用的是Windows或 ...
- SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行)
前言 本篇继续玩转模块的内容,关于索引在SQL Server的位置无须多言,本篇将分析如何利用Hint引导语句充分利用索引进行运行,同样,还是希望扎实掌握前面一系列的内容,才进入本模块的内容分析. 闲 ...
- SQL Server 调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行)
前言 本篇继续玩转模块的内容,关于索引在SQL Server的位置无须多言,本篇将分析如何利用Hint引导语句充分利用索引进行运行,同样,还是希望扎实掌握前面一系列的内容,才进入本模块的内容分析. 闲 ...
随机推荐
- IIC 概述之用IO模拟
最近做的一个项目,是基于IIC总线通信的传感器系统.由于另外一个传感器使用的是类IIC协议,而不是标准IIC,所以MCU不能与其通信,最后没有办法,只有通过I/O口模拟的方式实现IIC的总线通信.具体 ...
- 编写Swift代码的其他工具
Swift程序不能在Windows其他平台编译和运行,有人提供了一个网站swiftstub.com,左栏是代码编辑窗口,右栏是运行结果窗口.可以在任何平台下编译和运行Swift程序.
- 3D打印论坛
3D打印论坛:http://www.3done.cn http://www.03dp.com www.qjxxw.net/ http://www.3ddayin.net http://oa.zol.c ...
- hdu 5422 Rikka with Graph(简单题)
Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he ...
- MySql 查询表字段数
MySql 查询表字段数 SELECT COUNT(*) FROM information_schema.columns WHERE table_schema='test_cases' AND tab ...
- IOS UIlabel设置文本距离边框距离
自定义UILabel 继承 UILabel 重写drawTextInRect 方法具体如下: CGRect rect = CGRectMake(rect.origin.x + 5, rect.orig ...
- java如何从方法返回多个值
本文介绍三个方法,使java方法返回多个值. 方法1:使用集合类 方法2:使用封装对象 方法3:使用引用传递 示例代码如下: import java.util.HashMap; import java ...
- [Redux] Redux: Extracting Container Components -- AddTodo
Code to be refactored: const AddTodo = ({ onAddClick }) => { let input; return ( <div> < ...
- IPMITOOL常用操作指令
一.开关机,重启 1. 查看开关机状态: ipmitool -H (BMC的管理IP地址) -I lanplus -U (BMC登录用户名) -P (BMC 登录用户名的密码) power statu ...
- verilog 实现加法器
半加器 如果不考虑来自低位的进位将两个1二进制数相加,称为半加. 实现半加运算的逻辑电路称为半加器. 真值表 逻辑表达式和 \begin{align}\notag s = a{b}' + {a}'b ...