Cocos2d-x 3.x学习笔记:猩先生带你打飞机(五)敌我碰撞处理、分数计算、音乐播放

下面先是介绍下这一节要使用到的相关cocos2d-x的技术
一、粒子特效
粒子特效是什么,这个就百度百度,我只理解到它就是个很酷炫的效果。在cocos2d-x中使用粒子特效很简单,其实他也就是个Node,创建和使用都跟精灵差不多。另外,粒子特效一般用一个plist来描述,就是一个plist做后缀的xml文件,他描述了粒子的特性,可以自定义粒子,创建粒子特效的时候,加载这个plist文件即可。 下面是代码

auto * particleSystem = ParticleSystemQuad::create("particle_texture.plist");       //使用plist文件创建粒子特效
particleSystem ->setPosition(vec1);                        //设置粒子特效显示的位置
this->addChild(particleSystem );                            //添加到当前的层

二、数据持久化
在cocos2d-x中,数据存储有很多种方式,一种是sqlit,轻量级的数据库,不过数据量小的话使用UserDefault是非常方便的,当然还有其他的方式,这里就不介绍了,我也不熟哈。UserDefault,在项目中我就是用他来存储用户的分数和最高分数的,存储一些游戏设置啊基本上都用他的。其实他也就是个map,只是用了xml文件来存储,使用方面跟map也是极其相似。当第一次调用UserDefault::getInstance(); 时将会在系统中创建一个UserDefault.xml文件,注意是系统中创建,也就是说用户可见,也是可以操作的。其实用户的敏感数据放在这里是非常危险的,非常危险!比如现在的最高分,用户修改了那数据就是作假,这游戏追求高分就没意义了。但是我找了半天发现系统文件目录下并没有这个文件,不知道是不是cocos2d-x采用了些手段隐藏起来了,不过不影响我们使用,不可见本该是它的属性。 下面是使用代码

UserDefault * userDefault = UserDefault::getInstance();        //第一次调用即创建UserDefualt.xml文件
userDefault->setIntegerForKey("topscore",score);                  //存value,索引是key,每种类型都有对应的get、set方法,跟map一样,有一个key和value
userDefault->getIntegerForKey("topscore");                            //根据key来拿value

三、播放音乐
播放音乐cocos2d-x也帮我们做了相关的工作,以至于我们想播放音乐时,只需一行代码,对没错,不要998,只要001!so,现在播放音乐这一块只剩下:我们该在where播放音乐,又是在where停止音乐。这个跟我们的游戏逻辑有相当大的联系。暂时还没踩到这个坑,这个只能在游戏中调试调试再调试了。注意:音乐最好是wav格式,我试着播放mp3格式,发现会延迟几秒钟才能播放音乐,所以最好是用工具转下格式。另外一个话题就是音乐缓冲,就是在我们还未开始游戏前,我们得把他缓冲好,要不然下次播放音乐的时候在加载音乐会很卡,小音乐就算了。所以一般的做法就是在游戏开始初始化的时候,即AppDelegate::applicationDidFinishLaunching()中进行preload,预先读取。对了,写这些代码前要把#include “SimpleAudioEngine.h”,还有那些类的命名空间是CocosDenshion,不想每次都用命名空间去调用类就直接using namespace CocosDenshion吧。
下面看代码

SimpleAudioEngine::getInstance()->preloadBackgroundMusic("sounds/game_music.wav");            //预读背景音乐
 SimpleAudioEngine::getInstance()->preloadEffect("sounds/game_over.wav");                                   //预读音效
SimpleAudioEngine::getInstance()->playEffect("sounds/game_over.wav");                                         //播放音效,一次性,播完即止
 SimpleAudioEngine::getInstance()->playBackgroundMusic("sounds/game_music.wav");                //播放背景音乐,循环播放
SimpleAudioEngine::getInstance()->stopBackgroundMusic("sounds/game_music.wav");                //停止播放背景音乐

四、游戏逻辑的实现
好吧,下面就开始我们打飞机的正题。
经过之前的一番啪啪啪(敲代码的声音,别想歪了),现在我们已经可以捕捉到碰撞的事件了。这时我们只要在捕捉函数里面做工作就好了,就是万事俱备只差碰撞处理了。
处理,我们该处理些什么呢?
首先子弹与敌机碰撞时,播放敌机被击爆的音乐,计算所得的分数,引爆敌机,就是播放一个敌机爆炸的动画,再移除动画。然后移除Vector中的敌机和子弹,最后从层中移除两者。
然后是我机与敌机碰撞,先播放我机被击爆的音乐,修改游戏状态(游戏已经结束),停止所有的定时器,造成全屏停止的效果,再播放两者爆炸效果,再从层中移除敌机和我机,存储游戏的分数并刷新最高纪录,这里使用到的cocos2d的UserDefualt类,等下介绍如何使用。最后就是跳转到游戏结束场景。
下面来实现这些逻辑。
先声明一切用到的变量和函数
在GameScene.h中声明如下代码:

int score;         //游戏所得分数
virtual void onEnter();     //层进入时调用方法,碰撞事件监听在此处声明定义
void planeBomb(cocos2d::Vec2 vec,int tag);    //飞机爆炸动画
void bombRemove(Node * sprite);                         //飞机爆炸动画播放完之后的回调函数
void stopAllSchedule();         //停止所有的定时器
void gameOver();                     //游戏结束逻辑

下面是碰撞事件的处理,具体的逻辑是当两个可以互相碰撞的实体碰撞后,触发onContactBegin事件,然后通过捕捉的参数PhysicsContact类获取到相关的信息。碰撞一般是两个实体进行碰撞的,我们可以通过contact.getShapeA()->getBody()->getNode();和contact.getShapeA()->getBody()->getNode();来获取两个碰撞的实体(就是一个节点啦,游戏里是我机、敌机或子弹精灵)。然后就是判断是哪种碰撞,是我机和敌机,或者是敌机和子弹,然后进行不同的处理。
敌机和子弹碰撞处理:
先是判断碰撞的是哪种飞机,有大的小的,加分不同。

//层进入的时候会调用函数,进行物理世界的碰撞监听
void GameScene::onEnter()
{
 Layer::onEnter();            //注意层的生命周期相关的函数一定要先调用父类的,否则会无效。

 auto listener = EventListenerPhysicsContact::create();                //创建一个监听器

 listener -> onContactBegin = [=](PhysicsContact& contact)        //这里使用了个lambda,可以理解为匿名函数,具体的用法百度吧,(>_<)
 {
  auto spriteA = (Sprite *)contact.getShapeA()->getBody()->getNode();                //获取到节点是我们最关心的事,获取到了他们就任我们宰割了,嘿嘿
  auto spriteB = (Sprite *)contact.getShapeB()->getBody()->getNode();
  int tag1 = spriteA->getTag();
  int tag2 = spriteB->getTag();
  Vec2 vec1 = spriteA->getPosition();
  Vec2 vec2 = spriteB->getPosition();
  //敌机和子弹碰撞碰撞
  if(tag1 + tag2 == 210 || tag1 + tag2 == 211)  //敌机105104 子弹106 我机103
  {
    SimpleAudioEngine::getInstance()->playEffect("sounds/use_bomb.wav");
   //加分,如果是104则是小敌机500分,105是大敌机1000if(tag1 == 104 || tag2 == 104)
   {
    score += 500;
   }
   else
   {
    score += 1000;
   }
   auto scoreSpire = (Label *)this->getChildByTag(100);                                            //根据tag获取分数Node,并修改显示的分数 
   scoreSpire->setString(String::createWithFormat("分数:%d",score)->_string); //启动粒子特效 //auto * system = ParticleSystemQuad::create("particle_texture.plist"); //使用自定义的粒子特效,就一个plict为后缀的xml文件 //auto system = ParticleExplosion::create(); //使用cocos2d自带的粒子特效 if(tag1 == 104 || tag1 == 105) { //移除敌机和子弹 enemyList.eraSEObject(spriteA); bulletList.eraSEObject(spriteB); system->setPosition(vec1);
    //启动动画
    this->planeBomb(vec1,tag1);
   }
   else
   {
    enemyList.eraSEObject(spriteB);
    bulletList.eraSEObject(spriteA);
    //启动动画
    this->planeBomb(vec2,tag2);
    system->setPosition(vec2);
   }

   //粒子特效加入层中
   //this->addChild(system);
  }
  //敌机与我机碰撞
  else if(tag1 + tag2 == 207 || tag1+tag2 == 208)
  {
   SimpleAudioEngine::getInstance()->playEffect("sounds/game_over.wav");
   //修改游戏状态为结束状态3
   status = 3;
   stopAllSchedule();     //停止所有的定时器
   if(tag1 == 103)        //游戏结束逻辑
   {
    this->planeBomb(vec2,tag2);
    this->planeBomb(vec1,tag1);
   }
   else
   {
    this->planeBomb(vec1,tag1);
    this->planeBomb(vec2,tag2);
   }
   //使用UserDefault存储些用户数据分数,用法比较简单,map的使用方法,
   UserDefault * userDefault = UserDefault::getInstance();
   int topscore = userDefault->getIntegerForKey("topscore");
   if(topscore < score)
   {
    userDefault->setIntegerForKey("topscore",score);
   }
   else
    userDefault->setIntegerForKey("topscore",topscore);
   userDefault->setIntegerForKey("currentscore",score);

  }
  else{}        //这里处理了敌机和敌机碰撞的bug

  return true;
 };

 //注册监听器
 Eventdispatcher * eventdispatcher = Director::getInstance()->getEventdispatcher();
 eventdispatcher ->addEventListenerWithSceneGraPHPriority(listener,this);

}

游戏碰撞处理完。
下面就是处理里面调用了一些自定义函数

//飞机爆动画 ,只需要知道是哪个飞机,和位置,即可
void GameScene::planeBomb(Vec2 vec,int tag)//爆炸效果
{
 float timeDelay = 0.1;
 Vector<SpriteFrame*> animationframe;
 if(tag == 104)  //小敌机动画帧
 {
  for(int i=1;i<5;i++)
  {
   auto string = cocos2d::__String::createWithFormat("enemy1_down%d.png",i);
   SpriteFrame * sf=SpriteFrame::create(string->getCString(),Rect(0,0,57,43));
   animationframe.pushBack(sf);
  }
 }
 else if(tag == 105)        //大飞机
 {
   for(int i=1;i<5;i++)
  {
   auto string = cocos2d::__String::createWithFormat("enemy2_down%d.png",69,95));
   animationframe.pushBack(sf);
  }
 }
 else            //我机爆炸就游戏结束了,给个潇洒的特写,将动画延迟到0.5秒一帧
 {
  timeDelay = 0.5;
   for(int i=1;i<5;i++)
  {
   auto string = cocos2d::__String::createWithFormat("hero_blowup_n%d.png",102,126));
   animationframe.pushBack(sf);
  }
 }
 Animation * ani=Animation::createWithSpriteFrames(animationframe,timeDelay);
 auto blanksprite=Sprite::create();
 blanksprite->setTag(tag);    
//参数中的回调函数会在动画播放完后调用
 Action * act=Sequence::create(Animate::create(ani),CCCallFuncN::create(blanksprite,callfuncN_selector(GameScene::bombRemove)),NULL);
 this->addChild(blanksprite);
 blanksprite->setPosition(vec);
 blanksprite->runAction(act);
}
//移除动画
void GameScene::bombRemove(Node * sprite)//删除自己
{
 sprite->removeFromParentAndCleanup(true);
 if (sprite->getTag() == 103)            //当移除了我机爆炸的动画,那就是游戏结束了。
 {
  SimpleAudioEngine::getInstance()->stopBackgroundMusic("sounds/game_music.wav");
  gameOver();         //游戏结束逻辑
 }
}

好,下面看看效果

游戏结束后,应该是跳到显示分数和最高分,还有继续游戏,退出游戏的场景,下一节就实现他。完结篇了哇。
源码下载:源码3

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是