Cocos2dx游戏开发系列笔记7:一个简单的跑酷游戏《萝莉快跑》的消化(附下载)
懒骨头(http://blog.csdn.net/iamlazybone QQ124774397 青岛 )
或许有天
我们羡慕和崇拜的人
因为我们的努力
也会来了解我们
说不定
还会成为好友
骨头喜欢这样与哲哲共勉
多少个夜晚
一张长长的书桌上
哲哲在左边认真的做着可爱的独特的手作
骨头在右边噼里啪啦敲着自己真正喜欢的代码
中间的pad放部电影 || 放首歌 || 放段《一席》
这就是我们刚认识时憧憬的日子
所以现在是很幸福了
继续!
《喵汪大战》原作者:bill_man http://my.csdn.net/bill_man
昨晚那个游戏已经成功运行在了手机上,接下来,好好看看代码。
AppDelegate.cpp类
常规的东西,设置FPS,设置是否显示FPS,生成菜单场景类Scene,然后让导演类加载第一个场景。
GameMenuScene.cpp类
大部分工作都在init里,设置背景:
CCSize size = CCDirector::sharedDirector()->getWinSize(); //菜单背景CCSprite* bg = CCSprite::create("MainMenu.png");bg->setScale(0.5);bg->setPosition( ccp(size.width/2, size.height/2) );this->addChild(bg, 0,0);
加载几个按钮,到CCMenu上,然后将CCMenu加载到Scene中
//按钮CCMenuItemImage *newGameItem = CCMenuItemImage::create("newGameA.png", "newGameB.png",this,menu_selector(GameMenu::menuNewGameCallback));newGameItem->setScale(0.5);newGameItem->setPosition(ccp(size.width / 2 + 40,size.height / 2 - 20));newGameItem->setEnabled(false);CCMenuItemImage *continueItem = CCMenuItemImage::create("continueA.png", "continueB.png",this,menu_selector(GameMenu::menuContinueCallback));continueItem->setScale(0.5);continueItem->setPosition(ccp(size.width / 2 + 40,size.height / 2 - 60));continueItem->setEnabled(false);CCMenuItemImage *aboutItem = CCMenuItemImage::create("aboutA.png", "aboutB.png",this,menu_selector(GameMenu::menuAboutCallback));aboutItem->setScale(0.5);aboutItem->setPosition(ccp(size.width / 2 + 40,size.height / 2 - 100));aboutItem->setEnabled(false);soundItem = CCMenuItemImage::create("sound-on-A.png", "sound-on-B.png",this,menu_selector(GameMenu::menuSoundCallback));soundItem->setScale(0.5);soundItem->setEnabled(false);soundItem->setPosition(ccp(40,40));CCMenu* mainmenu = CCMenu::create(newGameItem,continueItem,aboutItem,soundItem,NULL);mainmenu->setPosition(ccp(0,0));this->addChild(mainmenu,1,3);
初始化背景音乐:
//初始化声音SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic("background.mp3");SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.5);SimpleAudioEngine::sharedEngine()->playBackgroundMusic("background.mp3");
然后在onEnter方法里,让菜单按钮从无放大至正常大小
void GameMenu::onEnter(){CCLayer::onEnter();CCSize size = CCDirector::sharedDirector()->getWinSize();CCNode* mainmenu = this->getChildByTag(3);mainmenu->setScale(0);mainmenu->runAction(CCSequence::create(CCScaleTo::create(0.5,1),CCCallFunc::create(this, callfunc_selector(GameMenu::menuEnter)),NULL));
}
使用getChildByTag()方法取得mainNenu。这也正是为何addChild()时,要加入tag参数了。
CCSequence::create()里,CCScaleTo动作执行完之后,调用GameMenu类的menuEnter方法
然后通过mainmenu->getChildren();方法获取按钮组,遍历一下,设置为可用。
然后紧跟着一些callBack方法,也就是按钮事件
void GameMenu::menuNewGameCallback(CCObject* pSender)
{CCDirector::sharedDirector()->setDepthTest(true);CCDirector::sharedDirector()->replaceScene(CCTransitionPageTurn::create(0.5,GameMain::scene(), false));
}
最后是控制背景音乐的方法
void GameMenu::menuSoundCallback(CCObject* pSender)
{//设置声音if(! issound){soundItem->setNormalImage(CCSprite::create("sound-on-A.png"));soundItem->setDisabledImage(CCSprite::create("sound-on-B.png"));SimpleAudioEngine::sharedEngine()->playBackgroundMusic("background.mp3", true);issound = true;}else{soundItem->setNormalImage(CCSprite::create("sound-off-A.png"));soundItem->setDisabledImage(CCSprite::create("sound-off-B.png"));SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();issound = false;}
}
再来看看关于界GameAboutScene.cpp
【插一句:setDepthTest:设置深度测试——可以用于自动处理遮挡关系】
这个类里,在init方法中贴几个CCSprite,加一个CCMenuItemImage及点击事件即可。没什么特别的。
GameObjStar.cpp星星类
本身继承自CCNode,有一个设置是否可见的方法
void GameObjStar::set_visable(bool var){_visable = var;this->setVisible(var);
}
在onEnter方法中初始化一下:缩放至一半大小,设置是否可见,设置尺寸。
void GameObjStar::onEnter(){CCNode::onEnter();//星星初始化this->setContentSize(CCSizeMake(36.5,35.5));CCSprite* star = CCSprite::create("star.png");star->setScale(0.5);_visable = true;addChild(star,1);
}
GameMark.cpp分数类
也是继承自CCNode,同样在onEnter方法里初始化,前面的socre是一个固定的CCSprite,后面是5个CCSprite,根据每个位数来动态修改图片
void GameMark::onEnter()
{CCNode::onEnter();CCSize size = CCDirector::sharedDirector()->getWinSize(); this->setContentSize(size);// bits = CCArray::create(5);bits=new CCArray(5);CCSprite *title= CCSprite::create("score.png");title->setPosition(ccp(size.width/2 + 120,size.height - 15));title->setScale(0.5);addChild(title);for(int i = 0;i < 5;i ++){CCSprite * shu = CCSprite::create("shu.png");ui = shu->getTexture();shu->setScale(0.5);shu->setTextureRect(CCRectMake(234,0,26,31));shu->setPosition(ccp(size.width - 15 - i * 15,size.height - 15));bits->addObject(shu);addChild(shu);}bits->retain();mark = 0;
}
bits->retain();// 应该是防止数组被回收
下面是按位设置数字,这种自定义rect的舒适化CCSprite的方式是第一次出现,其他的没什么了。
setTextureRect(CCRectMake((temp - 1) * 26,0,26,31));
void GameMark::addnumber(int var){//按位设置数字mark += var;int temp = mark % 10;if(temp > 0){((CCSprite *)bits->objectAtIndex(0))->setTexture(ui);((CCSprite *)bits->objectAtIndex(0))->setTextureRect(CCRectMake((temp - 1) * 26,0,26,31)); }else{((CCSprite *)bits->objectAtIndex(0))->setTexture(ui);((CCSprite *)bits->objectAtIndex(0))->setTextureRect(CCRectMake(234,0,26,31)); }temp = (mark % 100) / 10;if(temp > 0){((CCSprite *)bits->objectAtIndex(0))->setTexture(ui);((CCSprite *)bits->objectAtIndex(1))->setTextureRect(CCRectMake((temp - 1) * 26,0,26,31)); }else{((CCSprite *)bits->objectAtIndex(0))->setTexture(ui);((CCSprite *)bits->objectAtIndex(1))->setTextureRect(CCRectMake(234,0,26,31)); }temp = (mark % 1000) / 100;
再来看下萝莉类GameObjHero.cpp
首先在void GameObjHero::onEnter()方法里初始化。
接受触摸:
pDirector->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
初始化萝莉:
mainsprite = CCSprite::create("s_1.png");//动画CCAnimation * animation = CCAnimation::create();animation->addSpriteFrameWithFileName("s_1.png");animation->addSpriteFrameWithFileName("s_2.png");animation->addSpriteFrameWithFileName("s_3.png");animation->addSpriteFrameWithFileName("s_4.png");animation->addSpriteFrameWithFileName("s_5.png");animation->addSpriteFrameWithFileName("s_6.png");animation->setDelayPerUnit(0.1f);animation->setRestoreOriginalFrame(true);//运行奔跑动画mainsprite->runAction(CCRepeatForever::create(CCAnimate::create(animation)));
上面这种添加动画的方式,是骨头第一次遇到。
首先创建CCAnimation,然后设置每一帧的图片,然后设置每帧的延迟时间,设置播放完动画后是否回到第一帧。
然后是构造一个循环播放的CCRepeatForever动画,添加到精灵上。
里面有个设置状态方法:
switch(state){case 1://跳跃this->stopAllActions();mainsprite->stopAllActions();mainsprite->setTexture(jump);this->runAction(CCSequence::create(CCJumpBy::create(2.5,ccp(0,0),100,1),CCCallFunc::create(this, callfunc_selector(GameObjHero::jumpend)),NULL));break;case 2://受伤this->stopAllActions();mainsprite->stopAllActions();mainsprite->setTexture(hurt);this->runAction(CCSequence::create(CCBlink::create(3, 10),CCCallFunc::create(this, callfunc_selector(GameObjHero::hurtend)),NULL));((GameMain *)this->getParent())->setover();break;
跳跃,则运行CCJumpBy动画,受伤则运行CCBlink动画,就是一闪一闪的,并且在动画结束分别调用相应的方法。
然后是GameObjMap.cpp地图类
void GameObjMap::bg1change(){//运动出屏幕重设位置,运动CCSprite * bg = (CCSprite *)this->getChildByTag(0);bg->setPosition(ccp(480,320));bg->runAction(CCSequence::create(CCMoveBy::create(4,ccp(-960,0)),CCCallFunc::create(this, callfunc_selector(GameObjMap::bg1change)),NULL));for(int i = 0;i < 5;i ++){((GameObjStar *)stars1->objectAtIndex(i))->set_visable(true);}
}
void GameObjMap::bg2change(){//运动出屏幕重设位置,运动CCSprite * bg = (CCSprite *)this->getChildByTag(1);bg->setPosition(ccp(480,320));bg->runAction(CCSequence::create(CCMoveBy::create(4,ccp(-960,0)),CCCallFunc::create(this, callfunc_selector(GameObjMap::bg2change)),NULL));for(int i = 0;i < 5;i ++){((GameObjStar *)stars2->objectAtIndex(i))->set_visable(true);}
}
楼上两个方法作用是背景循环,callfunc_selector方法调用的是对方,一对好机油!
bg1->runAction(CCSequence::create(CCMoveBy::create(2,ccp(-480,0)),CCCallFunc::create(this, callfunc_selector(GameObjMap::bg1change)),NULL));bg2->runAction(CCSequence::create(CCMoveBy::create(4,ccp(-960,0)),CCCallFunc::create(this, callfunc_selector(GameObjMap::bg2change)),NULL));
其实整个背景地图的宽度是两倍的可视屏幕宽度,即480*2=960,这样的地图有两套,两套地图的动画在第一次运行时正好差半个周期,而且是互相调用,呈现出来的效果就是一直循环下去。恩,懂了。
然后在两套地图上绘制植物、草地等元素。
最后是核心逻辑类:GameMainScene.cpp
首先在初始化方法里,把游戏的所有元素都实例化一下,比如萝莉,比如地图,比如分数星星等。
最主要的循环方法:
scheduleUpdate();
void GameMain::update(float time){}
在update里面判断是否跟星星相撞,
bool GameMain::isCollion(CCPoint p1,CCPoint p2,int w1,int h1,int w2,int h2){if(abs(p1.x - p2.x) < w1 + w2 && abs(p1.y - p2.y) < h1 + h2){return true;}return false;
};
判断是否是掉落状态:
void GameMain::isherodrop(){CCPoint p1 = (map->getChildByTag(0))->getPosition();CCPoint p2 = (map->getChildByTag(1))->getPosition(); int temp;if(p1.x <= 100 && (p1.x + 480) >= 100){temp = (100 - p1.x) / 64;if(bg1shu[temp] == -1){hero->setState(2);}}else{temp = (100 - p2.x) / 64;if(bg2shu[temp] == -1){hero->setState(2);} }
}
上面方法比较难懂,大意就是根据当前地图的x值位置,来取得主角所站的位置有没有石头,没有的话即掉落。
temp = (100 - p1.x) / 64;
100是因为萝莉站在x=100的位置,所以要得到萝莉所在位置是否为空,即
bg2shu[temp] == -1
地图是这样添加的
//星星,植物等大图素的添加
for(int i = 0;i < 7;i ++){ //960/8=120
也就是说在960像素宽度的背景图上,可以放8个宽度等于120的元素。
static const short bg1shu[] = {-1,1,0,2,-1,1,2,3};
static const short bg2shu[] = {3,3,-1,3,-1,3,3,-1};
然后根据 数组的值来放置元素,-1时为空。
本篇完结 点此下载
http://download.csdn.net/detail/iamlazybone/6632923
好了,《萝莉快跑》的例子到此算是消化了大部分了。
看3遍不如自己动手敲1遍,赶紧去噼里啪啦一下吧:)
大家晚安。
------------------- 飞船起飞--------------------
Cocos2dx游戏开发系列笔记13:一个横版拳击游戏Demo-中
Cocos2dx游戏开发系列笔记12:一个横版拳击游戏Demo-上
Cocos2dx游戏开发系列笔记11:解刨《战神传说》完结篇
Cocos2dx游戏开发系列笔记10:解刨《战神传说》
Cocos2dx游戏开发系列笔记9:android手机上运行《战神传说》,并解决横竖屏即分辨率自适应问题
Cocos2dx游戏开发系列笔记8:开搞一个射击游戏《战神传说》//就个打飞机的
Cocos2dx游戏开发系列笔记7:一个简单的跑酷游戏《萝莉快跑》的消化(附下载)
Cocos2dx游戏开发系列笔记6:怎样让《萝莉快跑》的例子运行在vs和手机上
Cocos2dx游戏开发系列笔记5:继续润色《忍者飞镖射幽灵》
Cocos2dx游戏开发系列笔记4:怎样新加一个Scene类?
Cocos2dx游戏开发系列笔记3:牛刀小试->忍者飞镖射幽灵的Demo
Cocos2dx游戏开发系列笔记2:一个刚创建的cocos2dx中的demo里都有什么
Cocos2dx游戏开发系列笔记1:一个崭新的开始,cocos2dx2.2+ndkr9+Cygwin+vs2012游戏开发环境搭建
最后,骨头介绍一下陪在身边的哲哲(右边就是低调的哲哲)
哲哲,小名 YIYI ,手工爱好者,文艺范,手艺人,《YiYiの妙舍》创始人,很有自己想法。
Cocos2dx游戏开发系列笔记7:一个简单的跑酷游戏《萝莉快跑》的消化(附下载)相关推荐
- Cocos2dx游戏开发系列笔记7:一个简单的跑酷游戏《萝莉快跑》的消化(附下载)...
2019独角兽企业重金招聘Python工程师标准>>> 或许有天 我们羡慕和崇拜的人 因为我们的努力 也会来了解我们 说不定 还会成为好友 骨头喜欢这样与哲哲共勉 多少个夜晚 一张长 ...
- Cocos2dx游戏开发系列笔记8:开搞一个射击游戏《战神传说》//就个打飞机的
2019独角兽企业重金招聘Python工程师标准>>> 又是一个愉快的夜晚 还是那张长长的工作桌 哲哲在左边做一个香云纱手包 骨头在这里噼里啪啦的解刨 pad里放着<赢在中国& ...
- Cocos2dx游戏开发系列笔记6:怎样让《萝莉快跑》的例子运行在vs和手机上
2019独角兽企业重金招聘Python工程师标准>>> 感谢听D同学赞助的Demo. 那怎样让它运行在vs中呢: 1 使用cocos2d-x-2.2\tools\project-cr ...
- Cocos2dx游戏开发系列笔记3:牛刀小试-忍者飞镖射幽灵的Demo
2019独角兽企业重金招聘Python工程师标准>>> 就是这个例子,应该很简单,主要用到的有:精灵的移动,触摸,碰撞检测. 赶紧搞定,待会还要陪哲哲来几局爱消除. 首先在Scene ...
- Cocos2dx游戏开发系列笔记5:继续润色《忍者飞镖射幽灵》
2019独角兽企业重金招聘Python工程师标准>>> 周末了,哲哲在旁边看<爸爸去哪>,骨头继续玩cocos2dx, 首先,如果你新加了CPP和H文件,记得修改项目目录 ...
- Cocos2dx游戏开发系列笔记5:继续润色《忍者飞镖射幽灵》(VS2013快捷键)
懒骨头(http://blog.csdn.net/iamlazybone QQ124774397 青岛 ) 周末了,哲哲在旁边看<爸爸去哪>,骨头继续玩cocos2dx, 源码下载 ht ...
- Cocos2dx游戏开发系列笔记9:android手机上运行《战神传说》,并解决横竖屏即分辨率自适应问题
转载:http://blog.csdn.net/iamlazybone/article/details/17191539 懒骨头(http://blog.csdn.net/iamlazybone Q ...
- Cocos2dx游戏开发系列笔记10:解刨《战神传说》
2019独角兽企业重金招聘Python工程师标准>>> 有点困了,从桌子换到床上,刚要开敲,豆瓣电台传来的传来奇怪的歌声"马的-马的-" 看看歌词,应该是&quo ...
- Cocos2dx游戏开发系列笔记11:解刨《战神传说》完结篇
懒骨头(http://blog.csdn.net/iamlazybone QQ:124774397 ) 两点: 1 感谢 net19880504 同学,在上篇提到:想让骨头继续写<战神传说> ...
最新文章
- 一个java高级工程师的进阶之路【转】
- leetcode 74 java_【LeetCode】74. Search a 2D Matrix
- Hibernate中的实体映射
- 34 多线程同步之Event
- maven的内部属性
- Centos常用系统命令
- Java - I/O
- 梯度下降法、随机梯度下降法、批量梯度下降法及牛顿法、拟牛顿法、共轭梯度法
- WinSocket模型的探讨——完成端口模型
- 零基础学python难吗-Python课程学习难不难?零基础可以学习Python吗?
- C++基础教程之数据是如何封装的
- Sequelize多表联合查询案例
- 实现Unity2D游戏中跳跃功能和相关问题解决
- 做软件工程师需要具备怎样的能力和素质
- java 抽奖系统源码_基于jsp的抽奖系统-JavaEE实现抽奖系统 - java项目源码
- 用X64 Native tools command promt for vs安装ROS
- CString类详细介绍
- SAP 常用BAPI
- ip白名单实现java
- summernote网页编辑器嵌入视频
热门文章
- 5. 求cosx计算公式
- android 计步器 开发,Android计步器开发
- vue-cli和Element-UI搭配web前端
- 腾讯云服务器php设置,Windows 腾讯云服务器的 PHP 配置
- Navicat连接腾讯云服务器的MySQL
- html css js中分号的使用
- java爬取新浪微博带有“展开全文”的完整微博文本
- mysql查询名字相同数据排列出来_mysql 的sql语句来查找重复数据,并让其都显示出来?...
- php 跳转邮箱,JS点击跳转登陆邮箱功能简单的实现方法
- 2022年哈尔滨工业大学计算机考研复试分数线多少