共有回帖数 0 个
-
上节课中 我们已经实现了人物的移动,大家的可以发现,人物可以移动,但是却不能推动箱子,还能穿过障碍物和箱子。这节课,我们的人物,就是解决这两个问题,推动箱子,还有障碍物检测。
在这之前不得不先说一个问题,随着程序代码越来越多,我们一个文件中代码已经很长了,这样不利于代码的阅读和维护,所以这节课我们决定将代码 按照功能来分成不同的文件,类似模块化编程,每个功能就是一个模块。
如何把代码放到多个文件呢?
把代码的申明部分放到,头文件中,实现部分 放到源文件中。
比如,关于箱子操作的函数以及箱子的结构体定义,我们就放在 box.h中 函数的具体功能实现就放在 box.c 中。
人物操作 就放在 person.h 和 person.c中。其他的也是 类似。
头文件如何写?
我们看看例子,下面是 box.h 的所有内容
#ifndef _BOX_H_
#define _BOX_H_
#include config.h
//定义箱子结构体
typedef struct{
int x;
int y;
char flag;
int state;
} box_t;
//设置箱子位置
void set_box(box_t*, int x, int y);
//移动箱子,返回0表示成功移动,返回非0表示不能移动
int move_box(box_t*, dir_t);
//根据地图坐标获取指定box
box_t* get_box(int x, int y);
#endif
-----------------------------------------
#ifndef _BOX_H_
#define _BOX_H_
.............
#endif
-----------------------------------------
这段代码,作用是防止头文件被重复的包含,重复包含,这些函数就会被重复的申明,编译器将报错。
第一行 检测 如果这个 常量 _BOX_H_ 没有被定义了,就定义这个变量,然后 下面的函数声明 就会被编译进去,这样的话,如果第二次再包含了这个头文件,会再次检测 这个常量 _BOX_H_是否被定义的时候 ,由于已经定义过了,这段函数声明 就不会被编译进去,保证了这段头文件代码 只能被包含一次。
我把一些公共的类型都定义在 config.h 头文件中,在每个文件中都包含,比如 kdir 这些枚举类型就是声明在 config.h中。
好了,头文件有了,接下来看对应的源文件 box.c
代码地址:http://codepad.org/Zf2cbHTx
这个文件 都是头文件中函数的一些功能实现代码。
还有一个要注意的就是 can_move 函数 他前面有个 static 这个的作用是 把这个函数的作用域 限制在 文件域中,什么意思呢,就是这个函数 只能给本文件的函数访问。这样做有什么好处呢?好处就是 你可以在其他地方有同样函数名的函数,而不会重复定义。
注意我们这里没有直接包含box.h 因为 我们包含了 config.h 我们在 config.h中包含了 所有的 头文件。我们来看看config.h中都有什么:
代码链接:http://codepad.org/z06yQZLH
具体的可以看上面的注释,主要就看extern这个关键字的作用。
还有 全局变量和全局的枚举类型 需要放在头文件之前,因为这些头文件里面使用了这些类型,如果放在后面,会导致找不大这些类型。
好了,box的所有功能都写在 box.h 和 box.c文件中了,我们要使用他的功能 只需要引入 box.h 然后把box.c一起编译进程序就可以了,具体编译,后面会讲。
*****************************************************************
***来总结一下,多文件的程序都需要注意的事情:***
1.除非真的需要,否则不要在头文件中定义变量,最好是在源文件中定义好,头文件中,做一个外部声明。原因,看上面 config.h中对 extern的注释。
2.源文件中,确定只提供给内部使用的函数都加上 static 关键词修饰。
3.使用 #ifndef指令 保证头文件只能被包含一次。
4.把要提供给外部访问的函数声明写在头文件中。
********************************************************************
障碍物检测
上节课的人物可以穿过箱子和障碍物,那么如何让他无法穿过呢?
其实只需要对人物前方的物体做一个检测:
那么,什么情况是可以移动呢?
-----------------------------------------------------------------------------------------
第一,空旷的地面,肯定是可以移动。
第二,目标点,就是箱子要移动到的位置的那个点,是可以移动上去的。
第三,前面是箱子的时候,得分情况了。这个后面移动箱子的时候会讲。
-----------------------------------------------------------------------------------------
那么我们只需要写一个函数来检测是否可以移动即可,比如就叫 can_move
int can_move(person_t* person, dir_t dir)
返回值就设定为 int类型 返回0 表示不能移动,否则 表示可以移动,返回值 自己定,只要你记得返回什么表示可以移动即可。
person表示 人,他记录了人的位置信息, dir 是方向,根据方向和人的坐标 就可以知道 人即将走的地方 是什么东西,根据这个东西,我们就可以判断人物 是否可以移动。
那么就可以用如下的代码来检测:
在这之前获取到人物即将走的位置的 坐标
switch(map[person-y+y][person-x+x])
{
case OBJ_WALL: //是墙
case OBJ_OBS: //是障碍物
return 0; //不能移动 -----通过这个返回值 就可以让人 不能移动。
case OBJ_BOX:
case OBJ_SUCCESS:
这里进行 对箱子的处理,后面具体看代码。
************************************************************************************
如何移动箱子
头文件会写了,咱们再来说说移动箱子,移动箱子的思路是这样。
首先,人物被用户控制可以移动,每次移动都检测人物的前方 可否移动,也写了一个函数 can_move来判断是否可以移动,根据返回值来判断,可以移动就执行移动操作。
************************************************************************************
那么,什么情况是可以移动呢?前面说过,重复一下
第一,空旷的地面,肯定是可以移动。
第二,目标点,就是箱子要移动到的位置的那个点,是可以移动上去的。
第三,前面是箱子的时候,得分情况了。
**************************************************************************************
前面是箱子的时候,要先看 箱子是不是可以移动,箱子可以移动,人就可以移动,箱子无法移动,人当然也就无法移动。
所以,我们把箱子是否可以移动的事情,交给箱子模块去做。我们人物的模块,只需要尝试移动一下箱子,看看是不是移动成功就可以了。
代码如下:
//获取要推动的箱子
box_t* b1 = get_box(person-x+x, person-y+y);
//如果获取到了,并且返回成功,则可以移动,move_box 返回0表示成功
if(b1!=NULL && move_box(b1, dir)==0)
{
return 1;
} else {
return 0;
}
根据人物前方的坐标 来遍历检测出 前方的是哪一个箱子,然后移动他,move_box就是 试图移动他,根据函数返回值来判断是否移动成功,具体可以看person.c 文件中的 can_move 函数。
移动箱子的功能就讲述完毕了。
好了,接下来就是编译部分了。
编译命令可以直接用 gcc -I. *.c 来编译
-I. 是什么意思呢?
这是指定include的搜索目录,一个点 就表示 当前目录,大家注意看就会发现 我的 config.h 是用 #include config.h 还有 config.h里面的 box.h 等 都是这样的方式,为何我不用双引号的方式呢?
因为考虑到以后代码的目录结构可能会变化,比如 我创建一个 include目录 来放头文件,创建一个 src目录放 源文件。那我如果用的是 双引号,我不得改代码吗? 而我用 #include config.h 的方式,我只要用 -I指定一下新的 include目录即可 ,比如 gcc -I ./include *.c 这样就找到了,无需修改代码。
好了,上面其实是最笨的方式,更好的方式 是使用 Makefile来编译程序,他可以方便你创建无限小到无限大的项目。
我就不讲Makefile如何使用,我留给大家课后去学,下面是Makefile的教程
makefile的语法及写法一,二,三集合
http://www.zixue7.com/forum.php?mod=viewthread&tid=1615&fromuid=1
(出处: 自学去 )
注意 在linux下的是 make命令 而在mingw中 是 mingw32-make
学会了makefile语法之后,大家还可以去学 cmake 工具的使用,他可以更加方便。
好了 代码就分析到这里,后面我们会讲解,推箱子游戏的成功判断,退步等等功能。
整个项目打包文件: 见下方百度网盘附件
如果失效,可以在下面的链接下载:
http://www.zixue7.com/thread-16874-1-1.html
注:如发现文章错误万望指正如果有什么看不明白的,也欢迎在自学去留言回复
楼主 2015-08-21 17:54 回复
Copyright © 2010~2015 直线网 版权所有,All Rights Reserved.沪ICP备10039589号
意见反馈 |
关于直线 |
版权声明 |
会员须知