小明陪你编游戏系列(二)简单实现

来源:互联网 发布:nginx 访问权限控制 编辑:程序博客网 时间:2024/05/26 22:59

人生就好像是回力标一样,你投掷出的是什么,收到就是什么。

题前话,首先,小明非常抱歉,更新的慢了。第二个,就是再重申一下,本系列文章的目的,是为了给一些游戏初级编程爱好者一些入门的机会,最后,小明想说的就是,只要你愿意去学,其实很多看似很深奥的东西,在细细抽拨之后总是能够变得很简单。


好啦,开始正题。


内容简介:

(1).  前情提要

(2).  代码实现

1.  实现准备

2.  队伍的实现

3. 地图的实现

4. 消息的处理

5. 新块产生的实现

(3). 下期预告

1.  需求变更

2.  消灭臭虫

3.  重构分析与重构内容


(1). 前情提要

上回中,我们详细说明了这个类似贪吃蛇,并简单说明了实现方式,这一节将进行具体的实现。下面是具体代码的下载地址,如果对我的描述能力感到捉急,可以考虑直接先看看代码,嘿嘿。
http://download.csdn.net/detail/fukainankai/7326431 

0积分下载是必须的,另外,无论是代码、程序还是游戏的内容,有任何建议,都欢迎大家给我留言,再另外,小明的开发Q群欢迎各位爱好者的加入:69788620


(2). 代码实现

1. 实现准备

在实现之前,我们有必要定义一些有价值的宏。具体如下,它们的名字就可以看出它们的作用。
#define WIN_WIDTH600#define WIN_HEIGHT800#define MAX_WIDTH18#define MAX_HEIGHT24#define IMAGE_COUNT10#define TEAM_SIZE5#define SAFE_DELETE(p) do {if (p){ delete p; p = NULL;}} while (false);
然后,我们还需要定义一个方向的枚举类型,用来表示队伍前进的方向。
enum Direction{North = 0,South,East,West,};

再然后定义一个用于表示一个块(好吧,我们称之为一个Hero或者说角色)的结构。相信大家在看完需求后,这个结构的内容应该比较了解了。
struct Role{int x;int y;int nRoleId;int nValue;Role():x(0),y(0),nRoleId(0),nValue(1){;}};


2. 队伍的实现

作为队伍,它的属性应该包括前进的方向,各个队员Role的属性值。
而成员函数应该包括初始化、前进方向的设置函数以及前进这三个。
为了实现,将一些简单的功能提取出来。
CouldGoAhead 用于判断是否能够前进,判断条件为队长(第一个块)已经到达最北处,且方向为朝北,到达最南处且方向朝南等等。
IsSolid 用于判断是否已经被占据,未被占据包括两个条件:1. 该坐标处于地图内部 2.该坐标处没有队伍成员
Init 初始化,主要是初始化队伍的属性。

3. 地图的实现

准备全局一个指定长宽的三维数组,第一层表示测试数据的index,第二层表示高度,第三层表示宽度。之所以先写高度,后写宽度,是为了让我们的数据看起来和表现的效果很相同。
在CGame类初始化时,将全局的三维数组拷贝到当前的地图数据中。
memcpy(m_map, g_TestMap[nMapIndex], MAX_WIDTH*MAX_HEIGHT);
在CGame显示的时候,在需要刷新显示的时候,我们需要重新刷新一下地图。
当显示新块需要变更的时候,只需要通过更改m_map来进行修改。


4. 消息的处理

首先,我们需要在WndProc中收集一下按键消息:
case WM_KEYDOWN:g_game.DealMsg(wParam, lParam);break;
处理一下,其实有效的参数只有wParam,处理方法如下;
switch(wParam){case VK_UP:m_team.SetDirection(North);break;case VK_DOWN:m_team.SetDirection(South);break;case VK_LEFT:m_team.SetDirection(West);break;case VK_RIGHT:m_team.SetDirection(East);break;}
处理完毕后,需要进行一次刷新。

5. 新块产生的实现

有了地图,产生一个新块似乎并不是什么难事,只需要更新一下数据就好
void CGame::CreateNewBlock(){int x = rand()%MAX_WIDTH;int y = rand()%MAX_HEIGHT;int nRoleId = rand()%IMAGE_COUNT;m_map[x][y] = nRoleId;}

产生新块前,还需要进行一些清除工作。
void CGame::ClearBlock(){int x=0;int y=0;for (int i=0; i<TEAM_SIZE; i++){x = m_team.m_TeamMember[i].x;y = m_team.m_TeamMember[i].y;if (m_map[x][y] != 0){m_map[x][y] = 0;CreateNewBlock();}}}


(3). 下期预告

1. 需求变更

开发过程中,我们总是有可能会增加新的需求,所以我们在开发过程中,最好为这些新增的需求留有足够的缓冲空间,使得在增加新内容时,不会增加太大的工作量,甚至重新开发。以后的开发中,我们将会逐渐的添加新的需求,原生态地展现这个小游戏的开发过程。
现在,我们进行第一次需求变更,变更内容如下:
(1)需要一个完整的GUI(Graphical User Interface)包括开始游戏(继续游戏),载入游戏(保存游戏),退出游戏(返回菜单),帮助。
(2)暂停游戏,并且弹出GUI。
(3)实现状态机,完善代码。
(4)游戏保存机制。

这次添加的内容比较多,

2. 消灭臭虫(Bug)

不存在bug的程序就像无菌室,可能有,但是很难存在于我们的生活中,但是,我们得尽量爱惜干净不是?所以下回,我们将将解决几个Bug。

3. 重构分析和重构

如果你已经看过了代码,相信一定不喜欢这样的结构,因为它看起来让人很不喜欢,具体有哪些让人讨厌,又该怎样进行调整,下节我们将会进行重构分析和具体的重构工作。


没有人有耐心听你讲完自己的故事,因为每个人都有自己的话要说;

没有人喜欢听你抱怨生活,因为每个人都有自己的苦痛;

世人多半寂寞,这世界愿意倾听,习惯沉默的人,难得几个。

人一切的痛苦,本质上都是对自己的无能的愤怒。

0 0
原创粉丝点击