Cocos2d-x 3.5制作《逮兔子》教程分享
二、创建工程
下载好Cocos2d-x并解压,打开终端执行以下脚本创建工程:
XXXXXX/cocos2d-x/tools/cocos2d-console/bin/cocos new FindRabbit -p com.yourcompany.FindRabbit -l cpp -d XXXXXX
第一个XXXXXX为引擎源码所在文件夹路径,第二个XXXXXX为工程目录所在文件夹路径。
执行完脚本后找到FindRabbit文件夹并打开,再打开文件夹proj.ios_mac,文件FindRabbit.xcodeproj即为工程文件,打开能看到如下项目目录:
在Classes文件夹下添加游戏源码,Resources文件夹下是游戏用到的资源,包括字体、声音、图片等。
三、创建菜单场景
在Resources文件夹下创建图片文件夹images,将背景图片bg_game.jpg放到images文件夹下(Finder中操作)。然后从Xcode的工程导航视图里添加images文件夹,右键Resources,选择"Add Files To 'FindRabbit'…",进行如下选择:
注意红框部分,如果选择的是第一项,Resources下的images文件夹为黄色,选择第二项则为蓝色。源码中引用蓝色文件夹下的文件时须带上完整路径,这点在随后的源码体现。
Xcode工程导航视图中,右键Classes选择"New File…",创建一个"C++ File",取名字MenuScene,注意勾选"Also create a header file"。在Classes下创建一个文件夹MenuScene,将该文件创建到MenuScene文件夹下(当然也可以直接创建在Classes文件夹下,建议另外创建一个,实在不想让不同场景的源码混在一块儿)。然后在Xcode工程导航视图中再次右键Classes选择"New Group",将新创建的黄色文件夹改名为"MenuScene",把MenuScene.h和MenuScene.m拖进MenuScene文件夹里。
MenuScene.h里添加如下代码:
红框里的代码是新加的,其他的是系统自动生成的。MenuScene.m里暂时可以不添加任何代码即可编译通过。
目前游戏运行后显示的是HelloWorldScene,是系统自动生成的。要想让游戏启动即显示MenuScene,须修改AppDelegate.cpp的代码。
将AppDelegate.cpp里的HelloWorldScene头文件引用改成MenuScene的头文件引用,然后将"HelloWorld::createScene();"改为"MenuScene::create();"。这时HelloWorldScene.h和HelloWorldScene.m就没用了,可以删掉了,删到垃圾桶里吧,哈哈。不过这时编译报错,原因是MenuScene的init方法未实现,MenuScene.cpp里添加如下代码:
好了,这时就可以编译通过了。不过运行后什么也没有,除了FPS信息黑乎乎一屏,因为MenuScene里什么也没有。
四、菜单场景
1、游戏是竖屏游戏,先修改一下设备方向:
2、显示背景:
为简单起见,菜单场景只显示背景和开始按钮。背景层比较简单,直接在MenuScene.cpp中写就行,代码如下:
用图片bg_game.jpg文件创建一个Sprite,设置到屏幕中间,并通过addChild显示在当前场景中。注意图片路径"images/bg_game.jpg",images是蓝色文件夹,所以这里得是相对当前工程的完整路径。
运行后能看到图片了,不过有黑边呀。iPhone6上四周都有,iPad上只左右两边。像Android那种各种屏幕分辨率,指不定啥样呢。设备屏幕尺寸样式太多了,怎么办呢?在AppDelegate.cpp的方法applicationDidFinishLaunching里,glview赋值成功后加一句代码:
1
|
glview->setDesignResolutionSize(480,800,ResolutionPolicy::EXACT_FIT);
|
3、显示按钮
菜单场景中一般会有多个按钮,创建一个菜单控制层,叫MenuCtrlLayer吧。右键Classes选择"New File…",创建一个叫MenuCtrlLayer的"C++ File"。MenuCtrlLayer.h需要添加的代码如下:
clickStartGame是响应"开始游戏"按钮的,由于只在该类内部使用,设置为private的。最好这样做吧,尽管设置为public不会影响游戏本身。
MenuCtrlLayer.cpp中的实现如下:
先创建一个Label,用这个Label再创建一个菜单项MenuItemLabel,用这个菜单项再创建一个Menu,将这个Menu添加到当前Layer上。MenuItemLabel直接添加到当前Layer上也能看到该按钮,不过无法响应点击哈。
运行无法看到该按钮。还差一步,还没将MenuCtrlLayer添加到MenuScene上呢。MenuScene.cpp中的代码修改如下(两处红框为新增加的代码):
运行效果如下:
让按钮动起来,MenuItemLabel执行Action:
红框中的代码是新加的。让menuItemLabel执行RepeatForever,即无限重复的Action。无限重复什么呢?无限重复一个Sequence的Action,Sequence是一个Action序列,多个Action顺次执行。顺次执行两个ScaleTo,一个是0.5秒缩小到0.8,另一个是0.5秒放大到1.2,NULL表示后边没有了。运行后看一下效果吧。
五、游戏场景
1、创建游戏场景
参考创建菜单场景的方法,创建游戏场景GameScene。
点击"开始游戏"按钮,怎么打开游戏场景GameScene呢?在菜单控制层MenuCtrlLayer的按钮响应方法clickStartGame中添加代码(不要忘了先引用,"#include "GameScene.h""):
运行,点击"开始游戏"按钮,打开了GameScene(GameScene的背景图片与MenuScene的相同),有个动画效果的噢。刚添加的那句代码意思是:0.3秒把场景替换成GameScene。TransitionSplitCols是替换场景时的动画效果,有很多效果的,自行测试。
菜单场景可以进入游戏场景了,下面进入正文:设计游戏场景。
2、创建游戏场景所需的层
需要哪些层呢?
(1)得有个返回按钮用于返回菜单场景,游戏控制层GameCtrlLayer。GameCtrlLayer.cpp如下:
返回按钮位于左上角。这时只要在GameScene的init方法中添加上GameCtrlLayer,两个场景就可以切换了:
(2)得有个游戏区域,叫游戏层GameLayer。GameLayer.h如下:
配带了一个叫GameLayerDelegate的类,该类有一个纯虚函数叫gameLayerGameOver,而GameLayer中有一个GameLayerDelegate的变量m_delegate。为什么要这么设计呢?因为游戏结束只有游戏层GameLayer知道,而游戏结束后要显示游戏结束层GameOverLayer,但GameLayer和GameOverLayer又是同级的。在GameLayer.cpp中实例化GameOverLayer然后展现固然没错,但这样的话,场景中的各个层就需要相互引用了。GameLayer中要实例化GameOverLayer,而GameOverLayer中重新开始时又需要调用GameLayer的重新开始游戏的方法,层越多就越容易乱。所以,强烈建议场景中的所有层独立开发,不得相互引用。有什么事需要让其他层处理,通过相应的Delegate告知可以处理这件事的类,谁呢?GameScene啊,场景含多个层,各个层之间的通信自然交给GameScene最合适不过啊。所以,各个层有事件需要其他层配合,通过相应的Delegate交由GameScene处理,即GameScene继承各个层配带的Delegate。
(3)游戏结束的展现,叫游戏结束层GameOverLayer。GameOverLayer.h如下:
GameOverLayer配带了一个叫GameOverLayerDelegate的代理。再强烈建议一下:场景中的所有层独立开发,不得相互引用。有什么事需要让其他层处理,通过相应的Delegate告知可以处理这件事的类,谁呢?GameScene啊,场景含多个层,各个层之间的通信自然交给GameScene最合适不过啊。所以,各个层有事件需要其他层配合,通过相应的Delegate交由GameScene处理,即GameScene继承各个层配带的Delegate。宁可花点时间多写点代码,也不要图方便把关系搞乱了,不然后期维护起来消耗的时间精力比这点时间这点精力多多了。
3、GameScene协调三个层
GameScene.h如下:
GameScene.cpp如下:
我们发现,游戏场景部分的整体架构已经出来了。剩下的工作就是具体实现GameLayer和GameOverLayer了。
4、先从简单的开始吧,GameOverLayer。先从这层开始,不只是因为简单,而是体会一下各层分别开发的思想。GameOverLayer的init方法这样实现:
运行一下看看效果:
效果还不错咧。再来实现一下gameOver方法:
效果怎么样呢?得加句测试代码试才行。加在哪里呢?不能真玩游戏等结果哈,游戏层GameLayer还没开始开发呢。加在GameScene的init方法中:
修改nowScore和bestScore的值即可测试GameOverLayer在不同游戏结果时的显示效果。
有点难看哈。
5、游戏层GameLayer。
GameLayer还是比较复杂的,需要另外创建一个兔子矩阵类和兔子单元类,游戏场景部分的类结构如下:
GameLayer中,至少有一个开始游戏的方法startGame,游戏开始时做一些准备工作,需要考虑游戏结束后的重新开始的处理,即重置兔子矩阵。另一个方法就是gameOver,游戏结束后的后续处理工作,如与历史最佳成绩比较以决定是否将新成绩保存为历史最佳成绩。第三个比较重新的方法就是处理点击事件,判断是否点到兔子矩阵,再由兔子矩阵RabbitMatrix判断是点到"免"字还是"兔"字。
当然,还得在GameLayer中显示当前逮到兔子数目,显示当前关卡,具体实现细看源码吧。
源码下载:逮兔子源码