cocos2d-x for android:SimpleGame分析
cocos2d-x for android:SimpleGame分析
作为cocos2d-x的标配DEMO,SimpleGame可算是给入门学cocos2d-x的俺们这些新手门学习的对象了,那么来分析分析,把几个关键的代码记录下来。
设置游戏读取资源的目录
CCFileUtils::sharedFileUtils()->setResourceDirectory("sd");
默认路径是Resource目录
设置游戏的分辨率大小
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(480, 320, kResolutionNoBorder);
也可以不设置,自动去获取
创建精灵
CCSprite *player=CCSprite::create("Player.png",CCRectMake(,,,));
player->setPosition(ccp(
origin.x+player->getContentSize().width/, //X轴为:0+游戏角色的宽度/2
winVisibleSize.height/ + player->getContentSize().height/) //y轴为:指定的屏幕分辨率/2+游戏角色的高/2
);
this->addChild(player);
如果你希望精灵在图层初始化的时候就产生,那么精灵的创建最好把它放在于图层(CCLayer)的init函数中。
创建精灵时,需要为精灵指定位置(position),可接收的参数是CCPoint类型,CCPoint 是一个存放x、y轴数据的对象
使用时间选择器刷新游戏
this->schedule(schedule_selector(HelloWorld::gameLogic),1.0);
调用CCNodes的schedule(SEL_SCHEDULE selector, float interval)方法,这是一个自定义的时间选择器,以秒为单位。这里以秒为单位,每秒产生一个怪物
设置可接受触摸(Touch)事件
在场景初始化时,设置可接受触摸
this->setTouchEnabled(true);
然后,注册一个触摸事件的分发函数
void HelloWorld::registerWithTouchDispatcher(){
CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this,);
}
通过以上的做法,游戏即可在ccTouchesEnded回调函数里面得到触摸反馈。
移动精灵
上面每一秒钟刷新游戏,产生一个游戏怪物,方法位于HelloWold::addTarget,移动精灵的代码是
CCFiniteTimeAction* actionMove = CCMoveTo::create( (float)actualDuration,
ccp( - target->getContentSize().width/, actualY) );
CCFiniteTimeAction* actionMoveDone = CCCallFuncN::create( this,
callfuncN_selector(HelloWorld::spriteMoveFinished));
target->runAction( CCSequence::create(actionMove, actionMoveDone, NULL) );
actionMove:设置精灵移动方向和移动速度
actionMoveDone:精灵移动完成后执行可执行的回调函数为 spriteMoveFinished,当游戏移动到屏幕边界外,即回收该对象
然后通过精灵的runAction设置,精灵移动
上面代码,怪物的产生位置定在x的最右边,move方向从右到左到消息,需要设置x轴的最小值并且完全可以将怪物移动出屏幕即可,故x轴这里设置移动代码: (0 - target->getContentSize().width/2 ),y轴不变,随机从出来那一刻起一直不变做横向移动。
控制游戏角色发射飞镖
上面有提到设置图层可授受触摸 ,接下来我们要通过触摸让游戏主角发射飞镖消灭不断产生的怪物。代码见下方
得到触摸点坐标
CCTouch* touch = (CCTouch*)( touches->anyObject() );
CCPoint location = touch->getLocation();
每接受触摸一次产生一个飞镖
CCSize winSize = CCDirector::sharedDirector()->getVisibleSize();
CCSprite *projectile = CCSprite::create("Projectile.png", CCRectMake(, , , ));
projectile->setPosition( ccp(, winSize.height/2+projectile->getContentSize().height/2) );//角色x轴为0+角色的宽度,故飞镖的x轴应和角色有交接,使用户看起来飞镖是从角色身上发出来的
飞镖移动方向
float offX=location.x - projectile->getPosition().x;
float offY=location.y - projectile->getPosition().y; if(offX <=)return; this->addChild(projectile); float realX=winSize.width+(projectile->getContentSize().width/);//飞镖的横向方向跟游戏怪物一样,也是要移动出游戏界面并回收的(如果碰到怪物也要回收)
float ratio = offY/offX;//偏移量
float realY=(realX*ratio)+projectile->getPosition().y;//飞镖的竖向方向应是飞镖的横向方向*触摸点的偏移量每帧偏移的数值+当前飞镖所在位置的y轴
CCPoint realDest =ccp(realX,realY);
控制飞镖移动
projectile->runAction(CCSequence::create(
CCMoveTo::create(1.0,realDest),//参数1.移动速度。参数2.移动的x、y轴
CCCallFuncN::create(this,callfuncN_selector(HelloWorld::spriteMoveFinished)),//设置回调函数
NULL
));
飞镖与怪物的碰撞检测
这里需要在图层初始化的时候设置一个时间选择器,监听每帧的游戏变化
this->schedule(schedule_selector(HelloWorld::updateGame));
这时委托函数updateGame就启到每帧监听的作用了,代码如下
void HelloWorld::updateGame(float dt){
CCArray *projectileToDelete =new CCArray;
CCObject* it=NULL;
CCObject* jt = NULL;
CCARRAY_FOREACH(_projectiles,it){ //循环每一个飞镖
CCSprite *projectile=dynamic_cast<CCSprite*>(it);
CCRect projectileRect =CCRectMake(
projectile->getPosition().x - (projectile->getContentSize().width/),
projectile->getPosition().y-(projectile->getContentSize().height/),
projectile->getContentSize().width,
projectile->getContentSize().height);
CCArray* targetsToDelete=new CCArray;
CCARRAY_FOREACH(_targets, jt)//循环每一个敌人
{
CCSprite *target = dynamic_cast<CCSprite*>(jt);
CCRect targetRect = CCRectMake(
target->getPosition().x - (target->getContentSize().width/),
target->getPosition().y - (target->getContentSize().height/),
target->getContentSize().width,
target->getContentSize().height);
if (projectileRect.intersectsRect(targetRect)) //这里做矩形交集检测,如果两者有产生交集则将需要删除的敌人存放于数组里面
{
targetsToDelete->addObject(target);
}
}
CCARRAY_FOREACH(targetsToDelete, jt)//循环需要删除的敌人
{
CCSprite *target = dynamic_cast<CCSprite*>(jt);
_targets->removeObject(target); //将敌人从产生的敌人数组里面删除
this->removeChild(target, true);//从图层删除
_projectilesDestroyed++; //累积
if (_projectilesDestroyed >= ) //当满足消灭一定数量的敌人时,则执行游戏场景切换或者什么的blablabla
{
///
}
}
if(targetsToDelete->count() > ){ //如果有存在需要删除的敌人,则同时将与敌人交集的飞镖存入需要删除的飞镖数组
projectileToDelete->addObject(projectile);
}
targetsToDelete->release();
}
//remove projectile
CCARRAY_FOREACH(projectileToDelete,it){ //最后循环飞镖将飞镖删除掉
CCSprite *projectile =dynamic_cast<CCSprite*>(it);
_projectiles->removeObject(projectile);
this->removeChild(projectile,true);
}
projectileToDelete->release();
//end
}
根据上面,逻辑并不复杂,注意一下当前飞镖与敌人数组之间的关系即可。
播放游戏音效
无论是游戏背景音效也好,忍者发射飞镖那一刹那时的声音也好,好的游戏都要加上特殊的音效效果才能使游戏更加引人入胜。 cocos2d-x游戏引擎当然也有相关的音乐播放接口。从网上找到的一段话:
cocos2d-iphone里包含cocosDenshion库,里面从底到高提供三层接口:CDSoundEngine->CDAudioManager->SimpleAudioEngine,但整个库完全依赖于OpenAL来实现。关于OpenAL,它不是Khronos Group的标准,而是Creative公司的一个开源库,可以软实现或硬件实现。目前硬件实现了OpenAL的好像就只有苹果的产品,因此在其他平台上,我们无法提供cocosDenshion底层的支持,但我们是支持顶层的,它是开发者最常用到的一层。
那么如何添加音效呢?
添加背景音
CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("background-music-aac.wav",true);//设置背景音循环
添加发射飞镖音效
CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("pew-pew-lei.wav",false);
这里发射飞镖音效需要注意一个问题就是,如果这样写在Touch里面,第一次让音效播放是无效的,原因是播放音效需要预加载,不然第一次点击是不会出声音的,之后才会。不知道这是引擎硬性要求的么?解决办法是在图层初始化的时候让音效预加载一次
CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadEffect("pew-pew-lei.wav");
关于场景切换
觉得这方面没什么要说的,该说的网上都有,尤其是nowpaper 这篇文章 ,讲得很形象,可以去看看。
SimpleGame里面的场景切换类,对应是GameOverScene.cpp,该文件是判断游戏结束时,切换到该界面提示用户失败或者成功。这里有一点需要特点注意的是
GameOverScene *gameOverScene=GameOverScene::create();
gameOverScene->getLayer()->getLabel()->setString("you win!!!");
CCDirector::sharedDirector()->replaceScene(gameOverScene);
上面红色代码这块,比较难懂,这句话可以这么理解:通过GameOverScene头文件中的CC_SYNTHESIZE_READONLY宏定义生成getLayer方法,该方法返回GameOverLayer类型,然后再通过CC_SYNTHESIZE_READONLY 宏定义生成getLabel方法,返回cocos2d::CCLabelTTF类型,最后调用CCLabelTTF成员里面的setString ,该_label在初始化GameOverLayer的时候就己经this->addChild(_label) ,会不会这样就相当于传参数到另一个CCScene呢?呵呵!
#define CC_SYNTHESIZE_READONLY(varType, varName, funName)\
protected: varType varName;\
public: virtual varType get##funName(void) const { return varName; } //这里组合得到方法名和返回类型
来源:http://www.cnblogs.com/TerryBlog/archive/2012/10/30/2746150.html
cocos2d-x for android:SimpleGame分析的更多相关文章
- Android多线程分析之五:使用AsyncTask异步下载图像
Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...
- Android多线程分析之四:MessageQueue的实现
Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...
- Android多线程分析之三:Handler,Looper的实现
Android多线程分析之三:Handler,Looper的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多 ...
- Android多线程分析之二:Thread的实现
Android多线程分析之二:Thread的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多线程分析之一 ...
- Android多线程分析之一:使用Thread异步下载图像
Android多线程分析之一:使用Thread异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 打算整理一下对 Android F ...
- Android Launcher分析和修改13——实现Launcher编辑模式(1) 壁纸更换
已经很久没更新Launcher系列文章,今天不分析源码,讲讲如何在Launcher里面添加桌面设置的功能.目前很多第三方Launcher或者定制Rom都有简单易用的桌面设置功能.例如小米MIUI的La ...
- Android Launcher分析和修改9——Launcher启动APP流程
本来想分析AppsCustomizePagedView类,不过今天突然接到一个临时任务.客户反馈说机器界面的图标很难点击启动程序,经常点击了没有反应,Boss说要优先解决这问题.没办法,只能看看是怎么 ...
- 正确使用Android性能分析工具——TraceView
http://blog.jobbole.com/78995/ 首页 最新文章 IT 职场 前端 后端 移动端 数据库 运维 其他技术 - 导航条 - 首页 最新文章 IT 职场 前端 - Ja ...
- Android架构分析之Android消息处理机制(二)
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本号:4.4.2 在上一篇文章中我们看了一个使用Handler处理Message消息的样例,本文我们 ...
随机推荐
- 如何在jmeter中调用自己写的java工具包
本文介绍在jmeter中调用自己写java工具包,并非直接继承jmeter提供的java sample request接口. 工具/原料 jmeter eclipse 方法/步骤 通常用jmeter做 ...
- oracle连接数据
1.源代码 string connString = "User ID=scott;Password=yanhong;Data Source=(DESCRIPTION = (ADDRESS_L ...
- Java学习笔记之:Java Map集合
一.介绍 通常来说,Map是一个由键值对组成的数据结构,且在集合中每个键是唯一的. 二.笔记 /** * Map:接口. 不是collection的子类 key -value 键值对 key唯一不能重 ...
- Java-马士兵设计模式学习笔记-总结
<马士兵设计模式学习>学习了以下模式: 1.装饰者模式(例子:水管工,木工) 2.策略模式(例子:老师用职称比大小.学生用成绩比大小) 3.简单工厂模式(例子:VechileFactory ...
- 通过xrdp实现远程桌面连接Windows Azure linux虚拟机
本文以Oracle Linux 6.4虚拟机为示例(22及3389端口必须打开,分别用于SSH及RDP连接) 1.在安装xrdp之前,首先需要安装一些必要的包,如: # yum -y install ...
- HDOJ ——统计难题
统计难题 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)Total Submi ...
- js判断是移动端还是pc端
运行页面的时候,执行到js会判断来自于移动端还是pc端,如果是移动端则跳转制定链接地址,这样在手机端会有额外的不必要浪费的加载时间 var browser={ versions:function(){ ...
- 《c程序设计语言》读书笔记--多个空格变为一个空格
#include <stdio.h> int main() { int c; int flag = 0; while((c = getchar()) != EOF) { if(c == ' ...
- 每天一个小算法(Shell sort5)
希尔排序的关键在于步长的选取. 希尔排序的复杂度比较复杂,主要跟步长的选择有关,大概是 O(n logn^2),一般认为就是介于 O(n^2) 和 O(n logn) 之间.最好步长比较复杂,一般第一 ...
- AOJ - 2224 Save your cat(最小生成树)
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=45524 NY在自己的花园里养了很多猫.有一天,一个巫婆在N个点设置了魔法,然 ...