看了童晶老师在知乎上的专栏,决定写一下,这是链接地址:
https://zhuanlan.zhihu.com/p/24826034?refer=c2game
1.知识准备
我使用的EasyX 是一种针对 C++ 的图形库,可以帮助 C++语言初学者快速上手图形和游戏编程。由于我以前实习期间用过CocosStudio编写打飞机的小游戏,使用EasyX的时候还是很轻松的。
除了我加的一段死亡音乐,其余全部采用链接中给出的素材。
我把EasyX的教程浏览了一遍,这个知识点是以前学习过程中一直忽略的,贴出来:
http://www.easyx.cn/skills/View.aspx?id=23
- NOT
表示“取反”,将二进制位的1变0、0变1。
C语言用符号 ~ 表示。
如:
二进制: ~1101 = 0010
用十进制表示就是:~13 = 2 - AND
表示“并且”,只有两数的对应二进制位都为1,结果的二进制位才为1;否则,结果的二进制位为0。
C语言用符号 & 表示。
如:
二进制:1101 & 0110 = 0100
用十进制表示就是:13 & 6 = 4 - OR
表示“或者”,两数的对应二进制位只要有一个是1,结果的二进制位就是1;否则,结果的二进制位为0。
C语言用符号 | 表示。
如:
二进制:0101 | 0110 = 0111
用十进制表示就是:5 | 6 = 7 - XOR
表示“异或”,两数的对应二进制位不同,结果的二进制位为1;相同,结果的二进制位为0。
C语言用符号 ^ 表示。
如:
二进制:0101 ^ 1110 = 1011
还有位图的知识我也不太了解,留到以后解决了
2.编写代码
浏览了一下童晶老师给的代码,感觉不太看的懂别人的逻辑,就自己尝试写了一下。
下面讲解一下核心代码:
#define SPACE 750//上下两个柱子的间距
#define WIDTH 350
#define HIGH 600
#define STONEWIDTH 140//柱子宽度
#define BIRDWIDTH 33
#define BIRDHIGH 30
宏定义,分别是柱子间距(注意!这里是上下两个柱子图片的左上角坐标的间距。开始我还以为是上柱子下端和下柱子上端的间距,出了bug。。。。),画面宽度,画面长度,柱子宽度,鸟的宽度,鸟的长度。
IMAGE backGround,bird1[4],bird2[4],stoneUp1,stoneUp2,stoneUp3,stoneUp4,stoneDown1,stoneDown2,stoneDown3,stoneDown4,score1[10],score2[10],last; int i,k,score,flag; int birdX,birdY; int stone1DownX,stone1DownY,stone2DownX,stone2DownY;
其余变量
#pragma comment(lib,"Winmm.lib")
导入winmm库,播放音乐需要
void main()
{
while(1)
{
initialize();
mciSendString("pause music2", NULL, 0, NULL);
while(1)
{
k++;
if(k%2==0)//控制鸟扇翅膀的速度
i++;
updateWithoutInput();
updateWithInput();
if((birdX+BIRDWIDTH)>stone1DownX&&birdX
if((birdY+BIRDHIGH)>stone1DownY)
{
die();
break;
}
else
flag=1;
if(birdY<(stone1DownY-150))
{
die();
break;
}
else
flag=1;
}
if((birdX+BIRDWIDTH)>stone2DownX&&birdXstone2DownY)
{
die();
break;
}
else
flag=1;
if(birdY<(stone2DownY-150))
{
die();
break;
}
else
flag=1;
}
if(birdY<0||(birdY+BIRDHIGH)>HIGH)
{
die();
break;
}
show(1);
Sleep(60); //保证足够的刷新频率
}
}
getch();
closegraph();
}
这是main()函数,整个程序接近三百行,非常简单,都写在了一个文件里面。难道是我贴的代码太长了,格式也不统一,如果有朋友看见可以教我怎么贴代码,贴代码还是不方便。
main()里面主要就是三个函数:
updateWithoutInput();(数据更新,如小鸟下落,柱子的生成和左移)
updateWithInput();(按空格键小鸟上飞70像素)
show();(绘制图形)
其他代码我就不贴了,现在讲我编码过程中遇到的两个困难:
1.集中绘制图形
BeginBatchDraw();// 开启批量绘图模式
FlushBatchDraw(); //集中绘制
一般画面中物体不止一个,如果随着程序运行多次绘制的话会出现画面闪烁卡顿的情况,影响效率。因此,许多图形库都会有集中绘制图形的方法。以上语句,第一句开启批量绘图模式。之后的putImage等语句并不会马上起作用,直到第二句的集中绘制语句出现才开始绘制。
但我在编码中忘了这一茬,一直纳闷为什么putimage不起作用。。。。
2.意外跪掉
在我编写完小鸟与柱子碰撞检测的代码之后,测试中总是出现小鸟没有碰到柱子就gg的情况,我十分不解。
最后只好用这样的办法把小鸟的坐标和柱子的坐标显示出来比较
outtextxy(100,50, _T(48+birdY/100)); outtextxy(108,50, _T(48+birdY/10%10)); outtextxy(116,50, _T(48+birdY%10));
outtextxy(150,50, _T(48+((stone1DownY-150)/100)));
outtextxy(158,50, _T(48+((stone1DownY-150)/10%10)));
outtextxy(166,50, _T(48+((stone1DownY-150)%10)));
outtextxy(196,50, _T(48+((stone2DownY-150)/100)));
outtextxy(204,50, _T(48+((stone2DownY-150)/10%10)));
outtextxy(212,50, _T(48+((stone2DownY-150)%10)));`
但是仍然发现不了问题。为什么数据是正常的但是就是有bug呢?
其实这三个函数的顺序比较重要,show()要在最后。小鸟的坐标与柱子碰撞以后不能立即gameover,要把画面绘制完再转入gameover界面。
updateWithoutInput();
updateWithInput();
show();
这是修改之后的:
最终的游戏界面:
GAMEOVER: