上周,我做了一个基于 cocos2d-x 的飞机大战的游戏,因为我刚学cocos2d-x没多久,所以这个飞机大战很多都是看着别人的教程,再加上自己的一些想法,来做的。
下面我想说一说我的思路。
飞机大战有三个场景:
- LayerGameStart(游戏开始)
- LayerGameMain(游戏进行中)
- LayerGameOver(游戏结束)
一、游戏开始场景(LayerGameStart)
其中,游戏开始和游戏结束是比较简单的,那我就先从简单的说起,
首先说下游戏开始场景。我们在这个场景里面只需要做一下工作:
- 预加载一些资源(声音,图片缓存,这些资源都是全局的)
- 注意要将同一类资源放在一起,便于管理
- 检测游戏游戏的本地存数数据中是否有游戏最高分(UserDefault)
在这个场景,我只想说下如果检测游戏的最高分
具体实现如下:
//判断分数是否已经被存储
bool LayerGameStart::isSaveFile()
{
//用一个bool值作为标志,如果有则表示分数已经被存储
if (!UserDefault::getInstance()->getBoolForKey("isSaveFileXml"))
{
//如果没有就设置标志并置为真
UserDefault::getInstance()->setBoolForKey("isSaveFileXml",true);
//设置最高分,默认值为0
UserDefault::getInstance()->setIntegerForKey("HightestScore",0);
flush的作用是将数据写入到xml文件中。flush()在windows下是空的。。。呵呵。。。
UserDefault::getInstance()->flush();
return false;
}
else
return true;
}
void LayerGameStart::getHightestScore()
{
if (isSaveFile())
{
//在这里设置历史最高得分
LayerGameOver::_hightestScore =
UserDefault::getInstance()->getIntegerForKey("HightestScore",0);
}
}
然后只需要将 getHightestScore( ) 函数放在 LayerGameStart 的 init( ) 函数中即可。
二、游戏结束场景(LayerGameOver)
游戏结束场景也很容易,主要实现下面的功能:
- 显示本局游戏的得分
- 显示历史最高分
- 设置“返回游戏”按钮,和“退出”按钮
其中显示本局所得分数,也是比较好实现的,需要注意的是,如何将主场景(LayerGameMain)中的分数传递到游戏结束场景中去。做法如下:
static LayerGameOver * create(int score);
static cocos2d::Scene * scene(int score);
bool init(int score);
在创建场景时将分数传入,即在 init( ) 函数中传入分数,因为 init 在 create 有被调用,而 create 函数又在 scene 函数中被调用,所以这三个函数都有参数了。在切换场景的时候直接将分数传递过来就行。
然后就是显示历史最高分,显示历史最高分需要在游戏结束场景的 class 中添加一个静态成员变量
static int _hightestScore;//用于存到本地,记得要在class外进行初始化!
cocos2d::Label * hightestScore;//用于显示
具体实现如下:
//显示历史最高分
Value strHightestScore(_hightestScore);
hightestScore = Label::createWithBMFont("font/font.fnt",strHightestScore.asString());
hightestScore->setColor(Color3B(30,50,240));
hightestScore->setAnchorPoint(Point::ANCHOR_MIDDLE_LEFT);
hightestScore->setPosition(Point(150,winSize.height-40));
this->addChild(hightestScore);
返回和退出按钮就很简单了,就是设置两个图片作为按钮 (MenuItemSprite )backItem 和 exitItem 然后将这两个精灵添加到 Menu 中去:Menu * menu = Menu::create(backItem, exitItem, nullptr); 这两个按钮点击的回调函数也很简单,返回就是切换到游戏开始场景,退出就是直接退出程序 exit(1);
三、游戏主场景
游戏主场景就是最重要也最难的,主要有一下功能:
添加游戏背景并让游戏背景滚动起来
添加玩家飞机
1.飞机的动作行为(闪三次后播放自身帧动画,要方便控制,扩大其BoundingBox)
2.飞机不能飞出屏幕
3.由于其他层也需要飞机的位置,为了方便其他层获得飞机,将其设计为单例getInstance( )
4.玩家飞机自身爆炸的动画(因为爆炸后要切换到游戏结束场景,所以要在这里将本局游戏得分传到结束场景)添加子弹
1.首先得拿到玩家飞机的位置(因为子弹是从玩家飞机发出的)
2.设置定时器来产生子弹
3.让子弹飞~
4.子弹的行为:与敌机碰撞或者什么也没碰撞到——飞出屏幕外
5.将子弹放在一个容器里面,便于碰撞检测
6.不只有单发子弹还有多发子弹(MultiBullets)添加敌机
1.首先有一个敌机类Enemy,用于产生所有敌机(小敌机,中敌机,打敌机)
2.敌机产生的位置(屏幕上方,随机产生)
3.敌机消失在屏幕下方
4.与子弹和玩家飞机发生碰撞
5.敌机爆炸动画,玩家得分。添加道具
1.在玩游戏时,会用道具出现(从屏幕上方,随机出现)
2.道具有两种:炸弹和双发子弹(bigBoom,multiBullets)
3.道具行为:与玩家飞机碰撞或者什么也没碰到——掉到屏幕外
4.炸弹可以让当前屏幕中所有敌机爆
5.双发子弹增加玩家飞机的威力(第一次吃到会变成双发子弹,以后再吃到不会再加子弹而是直接给玩家加100分)添加控制层
1.更新玩家得分
2.实现游戏的暂停和继续的功能(添加屏蔽层)
怎么样,头晕了吗?要加这么多层,实现这么多功能。。。还有一些我没写(一时想不起来)
我也不准备,每个都详细说明了,我就说说实现这些功能需要注意的地方吧,也是我觉得比较难的地方。。。
1. 如何实现屏幕滚动:
我在这里其实只用了一个背景图,但是把它加载了两次,然后让两个图片一起向下移动,具体过程请看下图
代码实现如下:
//添加背景
void LayerGameMain::addBackground()
{
SimpleAudioEngine::getInstance()->playBackgroundMusic("sound/game_music.wav",true);
auto bg1 = Sprite::createWithSpriteFrameName("background.png");
bg1->setTag(BG1);
bg1->setAnchorPoint(Point::ZERO);
bg1->setPosition(Point(0,0));
this->addChild(bg1);
auto bg2 = Sprite::createWithSpriteFrameName("background.png");
bg2->setTag(BG2);
bg2->setAnchorPoint(Point::ZERO);
bg2->setPosition(0,bg1->getContentSize().height - 5);//为了不留空隙
this->addChild(bg2);
//利用帧循环来实现背景滚动
this->