本文介绍一款纵版射击游戏的实现,开发环境:
win7
vs2012
cocos2d-x3.0final
android adt
android ndk r9
首先看下最后的效果:
(图1,微信飞机大战运行效果)
源码下载地址:http://download.csdn.net/detail/sdhjob/7513863
一、游戏资源准备
menu.png |
|
about.png 关于界面 |
|
help.png 帮助界面 |
|
background3.png 游戏场景的 |
|
end.png | |
bullet.pngaaa.pngccc.png | 子弹和敌机文件 |
爆炸效果 |
二、Cocos2d-x3.0项目创建和VS2012编译
2.1进入命令提示符输入:
cocos new -p com.xdl.game -d c:/users/administrator/desktop/game2014 -l cpp planegame
2.2 然后进入桌面/game2014/planegame/proj.win32
2.3使用vs2012打开
planegame.sln
2.4 按F5编译运行项目,将会出现HelloWorld的界面
2.5.把所有的资源拷贝到桌面/game2014/planegame/Resources目录下(处理图片还有3个声音文件)
3.1.修改HelloWorldScene,在init方法中添加3个菜单条目:
autogameItem=MenuItemFont::create("StartGame",CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));
autohelpItem=MenuItemFont::create("Help",51); font-family:Arial; font-size:14px; line-height:26px"> autoaboutItem=MenuItemFont::create("About",51); font-family:Arial; font-size:14px; line-height:26px"> gameItem->setPosition(Point(origin.x + visibleSize.width/2- closeItem->getContentSize().width/2,200));
helpItem->setPosition(Point(origin.x + visibleSize.width/2- closeItem->getContentSize().width/2,150));
aboutItem->setPosition(Point(origin.x + visibleSize.width/2- closeItem->getContentSize().width/2,100));
gameItem->setColor(Color3B::BLACK);
helpItem->setColor(Color3B::BLACK);
aboutItem->setColor(Color3B::BLACK);
gameItem->setTag(11);
helpItem->setTag(12);
aboutItem->setTag(13);
3.2 修改菜单的回调方法MenuCallBackvoidHelloWorld::menuCloseCallback(Ref* pSender)
{ MenuItem * nowItem=(MenuItem *)pSender;
SimpleAudioEngine::getInstance()->playEffect("select.wav"); //播放音乐
switch(nowItem->getTag())
{
case10:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
break;
case11://game
Director::getInstance()->replaceScene(GameScene::createScene());@H_404_265@
case12://help
Director::getInstance()->replaceScene( TransitionFlipY::create(1,HelpScene::createScene()));@H_404_265@
@H_404_265@break;
case13://about
404_265@
break;
}
这样通过导演对象实现场景跳转。
3.3 在帮助,关于场景实现跳转回来
需要在项目中添加3个.h文件和3个.cpp文件,保存到Classes目录下(注意目录,不要保存错了)
HelpScene.h
HelpScene.cpp
GameScene.h
GameScene.cpp
AboutScene.h
AboutScene.cpp
若想在帮助和关于场景跳转回来需要加入触摸消息处理,见HelpScene的init方法:
boolHelpScene::init(){
if(!Layer::init())
{
returnfalse;
autospbk=Sprite::create("help.png");
spbk->setPosition(Point::ZERO);
spbk->setAnchorPoint(Point::ZERO);
this->addChild(spbk);
EventListenerTouchOneByOne * touch=EventListenerTouchOneByOne::create();@H_404_265@
touch->onTouchBegan=[](Touch * touch,Event * event){@H_404_265@
returntrue;@H_404_265@
};@H_404_265@
touch->onTouchMoved=[](Touch * touch,Event * event){@H_404_265@
Director::getInstance()->replaceScene( HelloWorld::createScene());@H_404_265@
_eventDispatcher->addEventListenerWithSceneGraPHPriority(touch,this);@H_404_265@
returntrue;
}
四、游戏场景背景滚动
4.1首先在GameScene的init方法添加背景层,代码如下:
autospbk=Sprite::create("background4.png");
spbk->setTag(10);
autospbk02=Sprite::create("background4.png");
spbk02->setAnchorPoint(Point::ZERO);
spbk02->setPosition(Point::ZERO);
spbk02->setPositionY(spbk->getPositionY()+680);@H_404_265@
this->addChild(spbk02);
spbk02->setTag(11);
为什么要添加2遍呢?因为要实现循环的贴图效果,4.2 在init方法计划任务
this->schedule(schedule_selector(GameScene::moveBackground),0.01);
4.3 处理计划任务 void GameScene::moveBackground(floatt){
autospbk=this->getChildByTag(10);
autospbk02=this->getChildByTag(11);
spbk->setPositionY(spbk->getPositionY()-1);
if(spbk->getPositionY()<-680)
spbk->setPositionY(0);
spbk02->setPositionY(spbk->getPositionY()+680);
}
这样就形成了循环贴图的效果,游戏游戏是横版的,还有将这种循环贴图通过多层实现场景纵深效果(近处图层移动快,远处移动慢)当背景相对屏幕向下移动,飞机相对屏幕不懂,但飞机相对背景则向上飞行(好多游戏的主角其实一直在屏幕中间)
五、飞机动画和触摸控制
5.1 在init方法创建飞机动画
autospPlane=Sprite::create();
spPlane->setTag(110);
spPlane->setPosition(Point(160,240));
this->addChild(spPlane);
Vector<SpriteFrame*> allframe;//保存动画的每一帧
for(inti=0;i<4;i++)
SpriteFrame * sf=SpriteFrame::create("player.png",Rect(i*47,0,47,56));
allframe.pushBack(sf);
Animation * ani=Animation::createWithSpriteFrames(allframe,0.1);
spPlane->runAction(RepeatForever::create(Animate::create(ani)));
5.2 通过触摸控制飞机移动 EventListenerTouchOneByOne * event=EventListenerTouchOneByOne::create();event->setSwallowTouches(true);
event->onTouchBegan=CC_CALLBACK_2(GameScene::onTouchBegan,this);
event->onTouchMoved=CC_CALLBACK_2(GameScene::onTouchMoved,51); font-family:Arial; font-size:14px; line-height:26px"> event->onTouchEnded=CC_CALLBACK_2(GameScene::onTouchEnded,51); font-family:Arial; font-size:14px; line-height:26px"> _eventDispatcher->addEventListenerWithSceneGraPHPriority(event,this);
-------在GameScene中添加以下方法
boolGameScene::onTouchBegan(Touch *touch,Event *unused_event){
px=touch->getLocation().x;
py=touch->getLocation().y;
voidGameScene::onTouchMoved(Touch *touch,51); font-family:Arial; font-size:14px; line-height:26px"> intmx=(touch->getLocation().x-px);
intmy=(touch->getLocation().y-py);
autospPlane=this->getChildByTag(110);
spPlane->runAction(MoveBy::create(0,Point(mx,my)));
py=touch->getLocation().y;
voidGameScene::onTouchEnded(Touch *touch,51); font-family:Arial; font-size:14px; line-height:26px"> 这样就实现了在屏幕滑动改变飞机坐标。
六、子弹发射
6.1 在GameScene中添加成员Vector用来保存所有的子弹层
Vector<Sprite *> allBullet;
6.2 计划任务,定时产生子弹和移动子弹
this->schedule(schedule_selector(GameScene::newBullet),0.5);
this->schedule(schedule_selector(GameScene::moveBullet),0.01
6.3 实现产生子弹的方法和移动子弹的方法void GameScene::newBullet(floatt){
autospPlane=this->getChildByTag(110);
Sprite * bullet=Sprite::create("bullet3.png");
bullet->setPosition(spPlane->getPosition());
this->addChild(bullet);
this->allBullet.pushBack(bullet);
void GameScene::moveBullet(floatt){
for(inti=0;i<allBullet.size();i++)
{autonowbullet=allBullet.at(i);
nowbullet->setPositionY(nowbullet->getPositionY()+3);
if(nowbullet->getPositionY()>Director::getInstance()->getWinSize().height)
{
nowbullet->removeFromParent();
allBullet.era@R_403_401@bject(nowbullet);
i--;
七、敌机实现
敌机实现与子弹实现类似,只不过一个是向上飞,一个是向下飞。
7.1在GameScene中添加成员Vector用来保存所有的子弹层
Vector<Sprite *> allEnemy;
7.2 添加产生敌机的任务
this->schedule(schedule_selector(GameScene::newEnemy),51); font-family:Arial; font-size:14px; line-height:26px"> this->schedule(schedule_selector(GameScene::moveEnemy),0.01)
7.3 实现敌机任务方法,这里产生2种不同类型的敌机
void GameScene::newEnemy(floatt){
Sprite * enemy=nullptr;
intnum=rand()%10;//随机数0-9@H_404_265@
if(num>=3)
enemy=Sprite::create("aaa.png");
enemy->setTag(1000);
}
else
{ enemy=Sprite::create("ccc.png");
enemy->setTag(2000);
enemy->setPosition(Point(rand()%300+10,500));
this->addChild(enemy);
this->allEnemy.pushBack(enemy);
void GameScene::moveEnemy(floatt){
for(inti=0;i<allEnemy.size();i++)
{autonowenemy=allEnemy.at(i);
nowenemy->setPositionY(nowenemy->getPositionY()-3);
if(nowenemy->getPositionY()<0)
nowenemy->removeFromParent();
allEnemy.era@R_403_401@bject(nowenemy);
八、碰撞检测和加分
8.1 添加和引擎主线程fps一致的任务处理方法update
this->scheduleUpdate();
8.2 实现碰撞检测游戏逻辑 voidGameScene::update(floatt){Rect rp(spPlane->getPositionX(),spPlane->getPositionY(),47,56);
for(inti=0;i<allEnemy.size();i++)
Rect er(nowenemy->getPositionX(),nowenemy->getPositionY(),40,50);
if(rp.intersectsRect(er))
{ //爆炸
newBomb(spPlane->getPositionX(),spPlane->getPositionY());
//移除敌机
allEnemy.era@R_403_401@bject(nowenemy);
i--;
//播放音乐
SimpleAudioEngine::getInstance()->playEffect("explo.wav");
//停止所有任务和动作
//Director::getInstance()->getActionManager()->pauseAllRunningActions();
this->pauseSchedulerAndActions();
autospover=Sprite::create("end.png");
spover->setPosition(Point::ZERO);
spover->setAnchorPoint(Point::ZERO);
this->addChild(spover);
autoact=Sequence::create(
DelayTime::create(2),//等待2秒
CallFunc::create(this,callfunc_selector(GameScene::jumpToMenu)),//执行跳转方法
NULL
);
this->runAction(act);
//敌机和子弹碰撞检测
for(intj=0;j<allBullet.size();j++)
{autonowbullet=allBullet.at(j);
Rect br(nowbullet->getPositionX(),nowbullet->getPositionY(),20,20);
if(er.intersectsRect(br))
{//修改分数
Label * labscore=(Label*)this->getChildByTag(120);
score+=nowenemy->getTag();
//爆炸效果
newBomb(nowbullet->getPositionX(),nowbullet->getPositionY());
//粒子效果
autops=ParticleSystemQuad::create("bomb.plist");
ps->setPosition(Point(nowbullet->getPositionX(),nowbullet->getPositionY()));
this->addChild(ps);
labscore->setString(String::createWithFormat("score:%d",score)->_string);
//移除子弹层
nowbullet->removeFromParent();
allBullet.era@R_403_401@bject(nowbullet);
//移除敌机层
nowenemy->removeFromParent();
//音效
SimpleAudioEngine::getInstance()->playEffect("explo.wav");
break;
}
当碰撞检测到,在飞机位置产生一个新的爆炸效果层,播放动画,动画播放完成自动删除自己。
voidGameScene::newBomb(intx,int y)
Vector<SpriteFrame*> allframe;
for(inti=0;i<7;i++)
SpriteFrame * sf=SpriteFrame::create("boom.png",Rect(i*44,0,44,47));
0.03
);autosprite=Sprite::create();
Action * act=Sequence::create(
Animate::create(ani),//动画
CCCallFuncN::create(sprite@H_404_265@,callfuncN_selector(GameScene::killMe)),//调用自删除方法
NULL);
this->addChild(sprite);
sprite->setPosition(Point(x,y));
sprite->runAction(act);
voidGameScene::killMe(Node *pSender@H_404_265@)//自删除 pSender就是sprite这里是CallFunN,会传递节点过来
pSender->removeFromParentAndCleanup(true);
十、粒子特效和音乐播放
10.1 首先使用粒子编辑器编辑粒子文件bomb.plist(详见源码)
10.2 载入粒子层
this->addChild(ps);
(如果粒子层也需要自删除,可以参考爆炸效果)10.3 播放音乐和音效
首先要引入声音处理头文件和命名空间
#include"SimpleAudioEngine.h"
usingnamespaceCocosDenshion;
然后就可以使用1条语句来播放音乐和音效了SimpleAudioEngine::getInstance()->playBackgroundMusic("game.mp3",true); //播放背景音乐
SimpleAudioEngine::getInstance()->playEffect("explo.wav"); //播放音效
十一、判定死亡
在Update方法中,目前只加入了当敌机和飞机碰撞则死亡,实际游戏中可能有多有条件
如:敌机子弹和飞机碰撞、时间计数等,
}
voidGameScene::jumpToMenu()//ï◊™µΩ÷˜≤Àµ•
{
SimpleAudioEngine::getInstance()->stopBackgroundMusic();
Director::getInstance()->replaceScene(HelloWorld::createScene());
}
十二、移植到Android平台
12.1 eclipse导入项目
在VS2012中开发好项目之后,使用adt工具(ecplise)导入项目,import
桌面\game2014\plangame\proj.android
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cocos2dcpp_shared
LOCAL_MODULE_FILENAME := libcocos2dcpp
LOCAL_SRC_FILES := hellocpp/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/GameScene.cpp \
../../Classes/HelpScene.cpp \
../../Classes/HelloWorldScene.cpp \
../../Classes/AboutScene.cpp@H_404_265@
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes
LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
LOCAL_WHOLE_STATIC_LIBRARIES += Box2d_static
include $(BUILD_SHARED_LIBRARY)
$(call import-module,2d)
$(call import-module,audio/android)
$(call import-module,Box2D)
12.3 进入cmd命令提示符
进入项目目录
cd c:/Users/Administrator/Desktop/game2014/planegame
编译当前项目
cocos compile -p android
(等吧。。。最后会在c:/Users/Administrator/Desktop/game2014/planegame/proj.android/libs/armsabi/生成一个.so文件, 成功了!)
12.4 拷贝Cocos2d-x android库文件
到 c:/Users/Administrator/Desktop/game2014/planegame/cocos/2d/platform/android/java/src/ 拷贝org文件夹到
c:/Users/Administrator/Desktop/game2014/planegame/proj.android/src 目录
在adt中刷新项目(这时候项目的错误会消除)
12.5 打包项目
使用手机数据线连接电脑,开启调试模式
可以直接通过run,来把该项目安装到手机,
之后使用android打包向导打包生成apk。
原文链接:https://www.f2er.com/cocos2dx/344215.html