Cocos2d 之FlyBird开发---GamePlay类
| 版权声明:本文为博主原创文章,未经博主允许不得转载。
这个是游戏的核心部分:(FlyBird游戏重中之重)
- 创建一个物理世界(世界设置重力加速度)
- 在物理世界中添加一个动态的刚体(小鸟)
- 在物理世界中添加一个静态的刚体(地板)和一个顶部边界(Edge)
- 在物理世界中添加一对浮动的刚体(Pipe),并设置线速度
- 设置每次点击屏幕小鸟上升的加速度
- 碰撞检测,判断游戏是否结束
下面贴上代码:
GamePlay.h
- #ifndef _GAME_PLAY_H_
- #define _GAME_PLAY_H_
- #define PTM_RATIO 32
- #include "cocos2d.h"
- #include "Box2D\Box2D.h"
- #include "SimpleAudioEngine.h"
- //背景音乐平台控制
- #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
- #define MUSIC_FILE "music/background.wav"
- #elif (CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
- #define MUSIC_FILE "music/background.ogg"
- #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
- #define MUSIC_FILE "music/background.caf"
- #else
- #define MUSIC_FILE "music/background.mp3"
- #endif // CC_PLATFOR_WIN32
- USING_NS_CC;
- using namespace CocosDenshion;
- class GamePlay : public cocos2d::Layer, public b2ContactListener
- {
- private:
- cocos2d::Sprite* backgroundA;
- cocos2d::Sprite* backgroundB;
- cocos2d::Sprite* ready;
- cocos2d::Sprite* tutorial;
- cocos2d::Sprite* bird;
- cocos2d::Sprite* land;
- cocos2d::Sprite* num;
- cocos2d::Sprite* upPipe;
- cocos2d::Sprite* downPipe;
- cocos2d::Sprite* pipeContainer;
- cocos2d::Sprite* model;
- cocos2d::Sprite* gameEnd;
- cocos2d::LabelTTF* score;
- cocos2d::LabelTTF* best;
- cocos2d::MenuItemImage* play;
- cocos2d::MenuItemImage* exit;
- b2World* world;
- b2Body* birdBody;
- b2Body* landBody;
- b2Body* downBody;
- b2Body* upBody;
- int bestScore;
- int times = 0;
- private:
- void replaceBackground(int);
- void tipInformation();
- void addBird();
- void addLand();
- void addPipe(float dt);
- void gameBegin(float dt);
- void gameOver();
- void timeAnimate();
- void upperBoundary();
- //int birdSelect(float);
- public:
- static cocos2d::Scene* createScene();
- virtual bool init();
- void initPhysicsWorld();
- virtual void update(float);
- /// Called when two fixtures begin to touch.
- virtual void BeginContact(b2Contact* contact);
- /** Callback function for multiple touches began.
- *
- * @param touches Touches information.
- * @param unused_event Event information.
- * @js NA
- */
- virtual void onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event);
- void goPlay(cocos2d::Ref* pSender);
- void goExit();
- CREATE_FUNC(GamePlay);
- };
- #endif // _GAME_PLAY_H_
GamePlay.cpp
- #include "GamePlay.h"
- #include "GameUnit.h"
- #include "GameData.h"
- unit u3;
- cocos2d::Scene* GamePlay::createScene()
- {
- auto scene = Scene::create();
- auto layer = GamePlay::create();
- scene->addChild(layer);
- return scene;
- }
- bool GamePlay::init()
- {
- if (!Layer::init())
- {
- return false;
- }
- SimpleAudioEngine::getInstance()->playBackgroundMusic(MUSIC_FILE, true);
- this->initPhysicsWorld();
- this->replaceBackground(1);
- this->tipInformation();
- this->upperBoundary();
- this->addLand();
- this->addBird();
- this->timeAnimate();
- //this->addPipe();
- //设置多点触屏事件的监听器
- auto listener = EventListenerTouchAllAtOnce::create();
- listener->onTouchesBegan = CC_CALLBACK_2(GamePlay::onTouchesBegan, this);
- //注册监听器
- _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
- //设置物理世界监听
- world->SetContactListener(this);
- scheduleOnce(schedule_selector(GamePlay::gameBegin), 3);
- //scheduleUpdate();
- return true;
- }
- void GamePlay::initPhysicsWorld()
- {
- //设置重力加速度为9.8;方向向下
- b2Vec2 gravity;
- gravity.Set(0.0f, -9.8f);
- //创建一个新的物理世界
- world = new b2World(gravity);
- //设置是否允许物体休眠
- world->SetAllowSleeping(true);
- //连续物理测试,防止发生非子弹特性的物体发生穿透现象
- world->SetContinuousPhysics(true);
- }
- void GamePlay::timeAnimate()
- {
- num = Sprite::create("bird/n1.png");
- num->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
- u3.winOrigin().y + (4 * u3.winSize().height) / 5));
- num->setScale(2);
- auto repeat = Repeat::create(Animate::create(u3.gameAnimate(4)), 1);
- num->runAction(repeat);
- this->addChild(num, 1);
- }
- void GamePlay::replaceBackground(int flag)
- {
- switch (flag)
- {
- case 1:
- backgroundA = Sprite::create("background/light.png");
- backgroundA->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
- u3.winOrigin().y + u3.winSize().height / 2));
- backgroundA->setScale(u3.scaleX(backgroundA, u3.winSize()),
- u3.scaleY(backgroundA, u3.winSize()));
- this->addChild(backgroundA, 0);
- break;
- case 2:
- backgroundB = Sprite::create("background/night.png");
- backgroundB->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
- u3.winOrigin().y + u3.winSize().height / 2));
- backgroundB->setScale(u3.scaleX(backgroundB, u3.winSize()),
- u3.scaleY(backgroundB, u3.winSize()));
- this->addChild(backgroundB, 0);
- break;
- default:
- break;
- }
- }
- void GamePlay::tipInformation()
- {
- ready = Sprite::create("logo/text_ready.png");
- ready->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
- u3.winOrigin().y + u3.winSize().height - 3*ready->getContentSize().height));
- ready->setScale(2);
- this->addChild(ready, 1);
- tutorial = Sprite::create("logo/tutorial.png");
- tutorial->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
- u3.winOrigin().y + u3.winSize().height / 2));
- tutorial->setScale(2);
- this->addChild(tutorial, 1);
- //exit
- exit = MenuItemImage::create(
- "button/exit_f.png",
- "button/exit_b.png",
- CC_CALLBACK_0(GamePlay::goExit, this)
- );
- Menu* menu = Menu::create(exit, NULL);
- menu->setPosition(Vec2(u3.winOrigin().x + exit->getContentSize().width / 2,
- u3.winOrigin().y + exit->getContentSize().height / 2));
- this->addChild(menu, 7);
- }
- void GamePlay::addBird()
- {
- bird = Sprite::create("bird/littleBird.png");
- bird->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 3,
- u3.winOrigin().y + u3.winSize().height - 5 * (ready->getContentSize().height)));
- bird->setScale(1.5);
- auto repeat = RepeatForever::create(Animate::create(u3.gameAnimate(1)));
- bird->runAction(repeat);
- this->addChild(bird, 1);
- //创建刚体
- b2BodyDef birdBodyDef;
- birdBodyDef.type = b2_dynamicBody;
- birdBodyDef.position.Set(bird->getPosition().x / PTM_RATIO,
- bird->getPosition().y / PTM_RATIO);
- //将刚体,精灵与世界关联起来
- birdBody = world->CreateBody(&birdBodyDef);
- birdBody->SetUserData(bird);
- //定义一个盒子
- b2PolygonShape birdBox;
- birdBox.SetAsBox(bird->getContentSize().width / 3 / PTM_RATIO,
- bird->getContentSize().height / 3 / PTM_RATIO);
- //夹具
- b2FixtureDef fixtureDef;
- //设置夹具的形状
- fixtureDef.shape = &birdBox;
- birdBody->CreateFixture(&fixtureDef);
- }
- void GamePlay::update(float dt)
- {
- world->Step(dt, 8, 3);
- for (b2Body* bb = world->GetBodyList(); bb; bb = bb->GetNext())
- {
- if (bb->GetUserData() != nullptr)
- {
- Sprite* sprite = (Sprite*)bb->GetUserData();
- //设置精灵的当前的位置,通过取得精灵的位置乘上相应的像素,这里的PTM_RATIO为32个像素为1m,就可以判断出精灵的位置处于物理世界的何处
- sprite->setPosition(Vec2(bb->GetPosition().x*PTM_RATIO,
- bb->GetPosition().y*PTM_RATIO));
- //设置精灵的角度偏转
- sprite->setRotation(0);
- }
- }
- }
- void GamePlay::onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event)
- {
- birdBody->SetLinearVelocity(b2Vec2(0, 5));
- //birdBody->SetLinearVelocity(b2Vec2(1, 5));
- }
- //添加地面
- void GamePlay::addLand()
- {
- //地板也是物理世界的一个刚体,是一个静态的刚体
- land = Sprite::create("background/land.png");
- land->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
- u3.winOrigin().y + land->getContentSize().height / 2));
- land->setScaleX(u3.winSize().width / 1.5*land->getContentSize().width);
- land->setScaleY(u3.winSize().height / (land->getContentSize().height * 3));
- this->addChild(land, 4);
- //创建刚体
- b2BodyDef landBodyDef;
- landBodyDef.type = b2_staticBody;
- landBodyDef.position.Set(u3.winSize().width / 2 / PTM_RATIO,
- land->getPosition().y / PTM_RATIO);
- landBody = world->CreateBody(&landBodyDef);
- landBody->SetUserData(land);
- b2PolygonShape landShape;
- landShape.SetAsBox(u3.winSize().width / 2 / PTM_RATIO,
- backgroundA->getContentSize().height / 2 / PTM_RATIO);
- //1.4*land->getContentSize().height / PTM_RATIO
- b2FixtureDef landFixtureDef;
- landFixtureDef.shape = &landShape;
- landBody->CreateFixture(&landFixtureDef);
- }
- void GamePlay::upperBoundary()
- {
- b2BodyDef upperBodyDef;
- //左下角
- upperBodyDef.position.Set(0, 0);
- //创建地面物体
- b2Body* upperBody = world->CreateBody(&upperBodyDef);
- //定义一个有边的形状
- b2EdgeShape upperBox;
- //顶部边界线
- upperBox.Set(b2Vec2(0, u3.winSize().height / PTM_RATIO),
- b2Vec2(u3.winSize().width / PTM_RATIO, u3.winSize().height / PTM_RATIO));
- upperBody->CreateFixture(&upperBox, 0);
- }
- void GamePlay::addPipe(float dt)
- {
- times++;
- float randPipe = -rand() % 3;
- //down bar
- downPipe = Sprite::create("pipe/down.png");
- downPipe->setScaleY(u3.winSize().height / (downPipe->getContentSize().height*1.5));
- this->addChild(downPipe, 3);
- b2BodyDef downBodyDef;
- downBodyDef.position = b2Vec2(u3.winSize().width / PTM_RATIO + 2,
- downPipe->getContentSize().height / 2 / PTM_RATIO + randPipe);
- // + land->getContentSize().height / PTM_RATIO
- downBodyDef.type = b2_kinematicBody;
- //修改速度可以提升游戏的难度
- downBodyDef.linearVelocity = b2Vec2(-2, 0);
- downBody = world->CreateBody(&downBodyDef);
- downBody->SetUserData(downPipe);
- b2PolygonShape downShape;
- downShape.SetAsBox(downPipe->getContentSize().width / 2 / PTM_RATIO,
- 1.6*downPipe->getContentSize().height / PTM_RATIO);
- b2FixtureDef downPipeFixture;
- downPipeFixture.shape = &downShape;
- downBody->CreateFixture(&downPipeFixture);
- upPipe = Sprite::create("pipe/upPipe.png");
- upPipe->setScaleY(u3.winSize().height / (upPipe->getContentSize().height*1.5));
- this->addChild(upPipe, 3);
- b2BodyDef upBodyDef;
- upBodyDef.position = b2Vec2(u3.winSize().width / PTM_RATIO + 2,
- downPipe->getContentSize().height / PTM_RATIO + randPipe + 3 +2*upPipe->getContentSize().height / PTM_RATIO);
- //
- upBodyDef.type = b2_kinematicBody;
- //修改速度可以提升游戏的难度
- upBodyDef.linearVelocity = b2Vec2(-2, 0);
- upBody = world->CreateBody(&upBodyDef);
- upBody->SetUserData(upPipe);
- b2PolygonShape upShape;
- upShape.SetAsBox(upPipe->getContentSize().width / 2 / PTM_RATIO,
- 1.6*upPipe->getContentSize().height / PTM_RATIO);
- b2FixtureDef upPipeFixture;
- upPipeFixture.shape = &upShape;
- upBody->CreateFixture(&upPipeFixture);
- }
- void GamePlay::gameOver()
- {
- //显示Game Over的Logo
- gameEnd = Sprite::create("logo/gameOver.png");
- gameEnd->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
- u3.winOrigin().y + u3.winSize().height - 3*gameEnd->getContentSize().height));
- gameEnd->setScale(2);
- this->addChild(gameEnd, 5);
- //显示奖章牌
- model = Sprite::create("logo/score_panel.png");
- model->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
- u3.winOrigin().y + u3.winSize().height / 2));
- model->setScale(u3.winSize().width / 1.5 / model->getContentSize().width,
- u3.winSize().height / 4.5 / model->getContentSize().height);
- this->addChild(model, 5);
- //奖章
- Sprite* award = Sprite::create("logo/medals1.png");
- award->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2 - model->getContentSize().width*0.6,
- u3.winOrigin().y + u3.winSize().height / 2));
- award->setScale(3);
- this->addChild(award, 6);
- //显示成绩
- score = LabelTTF::create("0", "Arial", 16);
- score->setPosition(Vec2(u3.winOrigin().x + (u3.winSize().width / 3) * 2,
- u3.winOrigin().y + u3.winSize().height / 2 + award->getContentSize().height));
- this->addChild(score, 7);
- //设置字体的颜色为黑色,并将成绩显示在panel面板上
- score->setColor(Color3B(0, 0, 0));
- score->setString(__String::createWithFormat("%5d", times - 1)->getCString());
- bestScore = GameData::getGameData();
- best = LabelTTF::create("0", "Arial", 16);
- best->setPosition(Vec2(u3.winOrigin().x + (u3.winSize().width / 3) * 2,
- u3.winOrigin().y + u3.winSize().height / 2 - 1.5*award->getContentSize().height));
- this->addChild(best, 7);
- best->setColor(Color3B(0, 0, 0));
- best->setString(__String::createWithFormat("%5d", bestScore - 1)->getCString());
- GameData::keepGameData(times);
- unscheduleUpdate();
- unschedule(schedule_selector(GamePlay::addPipe));
- }
- void GamePlay::gameBegin(float dt)
- {
- ready->setVisible(false);
- tutorial->setVisible(false);
- num->setVisible(false);
- scheduleUpdate();
- //修改时间可以提升游戏的难易程度
- schedule(schedule_selector(GamePlay::addPipe), 2);
- }
- void GamePlay::BeginContact(b2Contact* contact)
- {
- if (contact->GetFixtureA()->GetBody() == birdBody || contact->GetFixtureB()->GetBody() == birdBody)
- {
- this->gameOver();
- play = MenuItemImage::create(
- "button/play.png",
- "button/play.png",
- CC_CALLBACK_1(GamePlay::goPlay, this)
- );
- play->setPosition(Vec2(u3.winOrigin().x + u3.winSize().width / 2,
- u3.winOrigin().y + u3.winSize().height / 3));
- Menu* menu = Menu::create(play, NULL);
- menu->setPosition(Vec2::ZERO);
- menu->setScale(1.5);
- this->addChild(menu, 6);
- }
- }
- void GamePlay::goPlay(cocos2d::Ref* pSender)
- {
- times = 0;
- Director::getInstance()->replaceScene(TransitionFadeTR::create(1,
- GamePlay::createScene()));
- }
- void GamePlay::goExit()
- {
- times = 0;
- unscheduleUpdate();
- unschedule(schedule_selector(GamePlay::addPipe));
- Director::getInstance()->end();
- }
函数功能详见:http://www.cnblogs.com/geore/p/5800009.html
效果图:
Cocos2d 之FlyBird开发---GamePlay类的更多相关文章
- Cocos2d 之FlyBird开发---MainMenu类
| 版权声明:本文为博主原创文章,未经博主允许不得转载. MainMenu类主要实现的是游戏主界面的布局,它相当于一个港口,有开向各处的航道,而游戏中的MainMenu则是有跳转到各个场景的一个集 ...
- Cocos2d 之FlyBird开发---GameUnit类
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 这节来实现GameUnit类中的一些函数方法,其实这个类一般是一个边写边完善的过程,因为一般很难一次性想全所有的能够供多个类共用的方法.下 ...
- Cocos2d 之FlyBird开发---GameData类
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 现在是大数据的时代,绝大多数的游戏也都离不开游戏数据的控制,简单的就是一般记录游戏的得分情况,高端大气上档次一点的就是记录和保存各方面的游 ...
- Cocos2d 之FlyBird开发---GameScore类
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 这个类主要实现的是,显示历次成绩中的最好成绩.当然我写的这个很简洁,还可以写的更加的丰富.下面贴上代码: GameScore.h #ifn ...
- Cocos2d 之FlyBird开发---GameAbout类
| 版权声明:本文为博主原创文章,未经博主允许不得转载.(笔者才疏学浅,如有错误,请多多指教) 一般像游戏关于的这种界面中,主要显示的是游戏的玩法等. GameAbout.h #ifndef _G ...
- Cocos2d之FlyBird开发---简介
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 开发FlyBird其实非常的简单,在游戏的核心部分,我们需要实现的只有: 创建一个物理世界(世界设置重力加速度) 在物理世界中添加一个动态 ...
- JAVA串口开发帮助类分享-及写在马年末
摘要: 在系统集成开发过程中,存在着各式的传输途径,其中串口经常因其安全性高获得了数据安全传输的重用,通过串口传输可以从硬件上保证数据传输的单向性,这是其它介质所不具备的物理条件.下面我就串口java ...
- iOS cocos2d 2游戏开发实战(第3版)书评
2013是游戏爆发的一年,手游用户也是飞速暴增.虽然自己不做游戏,但也是时刻了解手机应用开发的新动向.看到CSDN的"写书评得技术图书赢下载分"活动,就申请了一本<iOS c ...
- (转载)实例详解Android快速开发工具类总结
实例详解Android快速开发工具类总结 作者:LiJinlun 字体:[增加 减小] 类型:转载 时间:2016-01-24我要评论 这篇文章主要介绍了实例详解Android快速开发工具类总结的相关 ...
随机推荐
- sqlserver创建索引语句
CREATE INDEX PersonIndex ON 表名 (字段名) DROP INDEX PersonIndex ON 表名
- git 命令图解
git 命令图解 初始化版本库 git config user.name "lsgx" git config user.email "lsgxthink@163.co ...
- 20191114PHP验证码
<?phpob_clean();$img=imagecreate(40,20);$back=imagecolorallocate($img,200,200,200); $blue=imageco ...
- Ubuntu系统安装配置tensorflow开发环境
Ubuntu系统安装 下载ubuntu iso 选择目前最新的版本是 Ubuntu 18.04 LTS .下载地址: 官网:https://www.ubuntu.com/download/deskto ...
- 安卓构架组件——向项目添加组件(Adding Components to your Project)
在开始之前,建议阅读 应用架构指南. Before getting started, we recommend reading the Architecture Components Guide to ...
- 形象生动的SpringBoot和SpringMVC的区别
spring boot只是一个配置工具,整合工具,辅助工具. springmvc是框架,项目中实际运行的代码 Spring 框架就像一个家族,有众多衍生产品例如 boot.security.jpa等等 ...
- shell简单的菜单功能
- smbcontrol - 向smbd或nmbd进程发送消息
总览smbcontrol [ -i ] smbcontrol [ 目标 ] [ 消息类型 ] [ 参数 ] 描述这个工具是是Samba组件的一部分. smbcontrol是个很小的程序,用它可以向系统 ...
- MyEclipse创建maven项目时报: org.apache.maven.archiver.MavenArchiver.getManifest 错误
创建项目报错,如图: 原因就是maven的配置文件不是最新的,MyEclipse2014解决方法: 1.help ->Install New sitie... 2.点击add 3.填写name和 ...
- Shell05--函数应用
目录 Shell05---函数应用 1. 函数基本概述 2. 函数基本使用 3. 函数参数传递 4. 函数状态返回 5. 函数场景示例 Shell05---函数应用 1. 函数基本概述 01. 什么是 ...