cocos2d-x v3.2 FlappyBird 各个类对象详细代码分析(7)
今天我们介绍最后两个类
GameOverLayer类
GameLayer类
GameLayer类是整个游戏中最重要的类,由于是整个游戏的中央系统,控制着各个类(层)之间的交互,这个类中实现了猪脚小鸟和它的敌人(管道和草地- . -)碰撞检測。说道物理引擎的碰撞检測。我也是第一次接触。也没多大难度。就直接调用了cocos2d-x的接口。这个类就是游戏的主场景,游戏就是在这里进行的。
GameOverLayer类。游戏结束后一些分数的显示。还有就是奖牌的实现(楼主写的非常easy......),这边比較有意思的就是加分效果的实现。这个楼主曾经在写AS3的时候经经常使用到。最后就是两个button。一个又一次開始button,一个排名button。排名button没有写功能,这个要跟手机的游戏中心配合。这边放一张游戏结束后的图片:
差点儿相同了。这个游戏全部的类都介绍的差点儿相同了。游戏的源代码和图片:
http://download.csdn.net/detail/u011373759/7941891
以下是这两个类的源代码分析,谢谢大家,结束
//GameOverLayer.h
#pragma once
#include "cocos2d.h" class GameOverLayer:public cocos2d::Layer
{
public:
GameOverLayer();
~GameOverLayer();
bool init();
//回调函数
void callBack();
//再来一次
void gameAgain();
//获取排名
void getRank();
//显示分数
void showScore(float);
CREATE_FUNC(GameOverLayer);
private:
//计分板精灵
cocos2d::Sprite * box;
//终于分数label
cocos2d::Label * numberLabel;
int score;
int highScore;
};
//GameOverLayer.cpp
#include "GameOverLayer.h"
#include "define.h"
#include "GameLayer.h"
#include "NumberLayer.h"
#include "GetLocalScore.h"
USING_NS_CC; GameOverLayer::GameOverLayer()
{ } GameOverLayer::~GameOverLayer()
{
} bool GameOverLayer::init()
{
if (!Layer::init())
{
return false;
}
auto origin=Director::getInstance()->getVisibleOrigin();
auto visibleSize=Director::getInstance()->getVisibleSize(); //历史最高分
highScore=GetLocalScore::getInstance()->getHighScore(); //计分板
box=Sprite::createWithSpriteFrameName("score_panel.png");
box->setPosition(Point(origin.x+visibleSize.width/2,origin.y-visibleSize.height/2));
this->addChild(box); //游戏结束后,计分板要从屏幕底部向上运动出现
//动画结束后要显示分数和两个button(在回调函数里)
auto moveto=MoveTo::create(SCORECARD_SHOW_TIME,Point(origin.x+visibleSize.width/2,origin.y+visibleSize.height*0.5));
auto callback=CallFuncN::create(CC_CALLBACK_0(GameOverLayer::callBack,this));
auto sequence=Sequence::create(moveto,callback,NULL);
box->runAction(sequence);
//动画的声音
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sounds/sfx_swooshing.mp3"); //gameover 字
auto gameover=Sprite::createWithSpriteFrameName("text_game_over.png");
gameover->setPosition(Point(origin.x+visibleSize.width/2,origin.y+visibleSize.height+gameover->getContentSize().height/2)); //gameover精灵也要运行同样的动画,只是它是从上到下运动
auto moveto2=MoveTo::create(SCORECARD_SHOW_TIME,Point(origin.x+visibleSize.width/2,origin.y+visibleSize.height*0.7)); gameover->runAction(moveto2); this->addChild(gameover); return true;
} void GameOverLayer::callBack()
{
log("callback");
auto origin=Director::getInstance()->getVisibleOrigin();
auto visibleSize=Director::getInstance()->getVisibleSize(); //排名和再来一次button
//计分板和gameover精灵运行完动画后,出现button
auto again=Sprite::createWithSpriteFrameName("button_play.png");
auto menuAgain=MenuItemSprite::create(again,again,CC_CALLBACK_0(GameOverLayer::gameAgain,this)); auto rank=Sprite::createWithSpriteFrameName("button_score.png");
auto menuRank=MenuItemSprite::create(rank,rank,CC_CALLBACK_0(GameOverLayer::getRank,this)); //两个button坐标的设定
int l=(visibleSize.width-again->getContentSize().width*2)/3; menuAgain->setPosition(Point(origin.x+l+again->getContentSize().width/2,origin.y+visibleSize.height*0.3));
menuRank->setPosition(Point(origin.x+visibleSize.width-l-again->getContentSize().width/2,origin.y+visibleSize.height*0.3)); //把button放到菜单中去
auto menu=Menu::create(menuAgain,menuRank,NULL);
menu->setAnchorPoint(Point::ANCHOR_BOTTOM_LEFT);
menu->setPosition(Point::ZERO); this->addChild(menu); //分数显示
score=0;
auto str=__String::createWithFormat("%d",score);
numberLabel=Label::createWithBMFont("font2.fnt",str->getCString());
numberLabel->setPosition(Point(origin.x+visibleSize.width/2+65,origin.y+visibleSize.height*0.5+10));
this->addChild(numberLabel); //当分数大于0时运行一个分数从0到n的动画
if (NumberLayer::getInstance()->getScore()>0)
{
this->schedule(schedule_selector(GameOverLayer::showScore),ADDSCORE_FRE);
} //历史最高分
auto str1=__String::createWithFormat("%d",highScore);
auto highScoreLabel=Label::createWithBMFont("font2.fnt",str1->getCString());
highScoreLabel->setPosition(Point(origin.x+visibleSize.width/2+65,origin.y+visibleSize.height*0.5-30));
this->addChild(highScoreLabel); //假设当前分数大于历史最高分。则会出现new的字样
if (NumberLayer::getInstance()->getScore()>highScore)
{
GetLocalScore::getInstance()->setHighScore(NumberLayer::getInstance()->getScore());
auto picNew=Sprite::createWithSpriteFrameName("new.png");
picNew->setPosition(Point(origin.x+visibleSize.width/2+37,origin.y+visibleSize.height*0.5-4));
this->addChild(picNew);
} //奖牌显示
//这边的奖牌显示是自己定的
//各个奖牌之间要达到多少分数请看define.h
int l2=(visibleSize.width-box->getContentSize().width)/2;
if (NumberLayer::getInstance()->getScore()<MEDALS_0)
{
return;
}
Sprite * medals;
if (NumberLayer::getInstance()->getScore()>=MEDALS_0&&NumberLayer::getInstance()->getScore()<MEDALS_1)
{
medals=Sprite::createWithSpriteFrameName("medals_0.png"); }
if (NumberLayer::getInstance()->getScore()>=MEDALS_1&&NumberLayer::getInstance()->getScore()<MEDALS_2)
{
medals=Sprite::createWithSpriteFrameName("medals_1.png");
}
if (NumberLayer::getInstance()->getScore()>=MEDALS_2&&NumberLayer::getInstance()->getScore()<MEDALS_3)
{
medals=Sprite::createWithSpriteFrameName("medals_2.png");
}
if (NumberLayer::getInstance()->getScore()>=MEDALS_3)
{
medals=Sprite::createWithSpriteFrameName("medals_3.png");
}
medals->setPosition(Point(origin.x+l2+54,origin.y+visibleSize.height*0.49));
this->addChild(medals);
} //再来一次。场景切换
void GameOverLayer::gameAgain()
{
Director::getInstance()->replaceScene(TransitionFade::create(CHANGESCENE_TIME,GameLayer::createScene()));
} //排名button的回调。这里没写,由于这里要调用的是手机游戏中心的资料
void GameOverLayer::getRank()
{
log("get rank");
} //分数显示动画
void GameOverLayer::showScore( float )
{
score++;
auto str=__String::createWithFormat("%d",score);
numberLabel->setString(str->getCString());
if (score==NumberLayer::getInstance()->getScore())
{
this->unschedule(schedule_selector(GameOverLayer::showScore));
}
}
//GameLayer.h
#pragma once
#include "cocos2d.h"
#include "SpriteBird.h" class GameLayer:public cocos2d::Layer
{
public:
GameLayer();
~GameLayer();
static cocos2d::Scene * createScene();
bool init();
//游戏開始
void startGame();
CREATE_FUNC(GameLayer);
private:
//猪脚层
SpriteBird * bird;
//物理碰撞侦听
cocos2d::EventListenerPhysicsContact * contactListener;
};
//GameLayer.cpp
#include "GameLayer.h"
#include "define.h"
#include "HelpLayer.h"
#include "PipeLayer.h"
#include "LandLayer.h"
#include "NumberLayer.h"
#include "GameOverLayer.h"
USING_NS_CC;
GameLayer::GameLayer()
{
} GameLayer::~GameLayer()
{
} cocos2d::Scene * GameLayer::createScene()
{
//注意我们这边创造的是物理场景
auto scene=Scene::createWithPhysics();
//增加了重力。GRAVITY的值为(0,-980)
//跟我们的世界重力加速度是一样的,比較真实
scene->getPhysicsWorld()->setGravity(GRAVITY);
auto gameLayer=GameLayer::create();
scene->addChild(gameLayer);
return scene;
} bool GameLayer::init()
{
if (!Layer::init())
{
return false;
} auto origin=Director::getInstance()->getVisibleOrigin();
auto visibleSize=Director::getInstance()->getVisibleSize(); //背景图片。依据时间载入晚上和白天的图片
time_t t=time(NULL);
tm * lt=localtime(&t);
int hour=lt->tm_hour; Sprite * bg; if (hour>=6&&hour<=17)
{
bg=Sprite::createWithSpriteFrameName("bg_day.png");
}
else
{
bg=Sprite::createWithSpriteFrameName("bg_night.png");
} bg->setPosition(Point(origin.x+visibleSize.width/2,origin.y+visibleSize.height/2));
this->addChild(bg); //以下就是我们前几章讲的各个类的实例的运用了
//这个游戏就像贴纸一样,一层一层叠起来,各层运行各层的逻辑
//靠这个游戏层来控制各层的之间的交互 //草底层
auto landLayer=LandLayer::create();
landLayer->setAnchorPoint(Point::ANCHOR_BOTTOM_LEFT);
landLayer->setPosition(Point::ZERO);
this->addChild(landLayer,2); //帮助界面
auto helpLayer=HelpLayer::create();
helpLayer->setAnchorPoint(Point::ANCHOR_BOTTOM_LEFT);
helpLayer->setPosition(Point::ZERO);
this->addChild(helpLayer); //管子层
auto pipeLayer=PipeLayer::create();
pipeLayer->setAnchorPoint(Point::ANCHOR_BOTTOM_LEFT);
pipeLayer->setPosition(Point::ZERO);
this->addChild(pipeLayer,1); //主角
bird=SpriteBird::createBird();
bird->setAnchorPoint(Point::ANCHOR_BOTTOM_LEFT);
bird->setPosition(Point::ZERO);
this->addChild(bird,2); bird->changeState(ACTION_STATE_IDLE); //这里创建了触控侦听
//当玩家点击屏幕时,游戏開始。并移除这个侦听
auto listener=EventListenerTouchOneByOne::create();
listener->setSwallowTouches(false);
listener->onTouchBegan=[=](Touch * t,Event * e)
{
log("GameLayer touch begin"); return true;
};
listener->onTouchEnded=[=](Touch * t,Event * e)
{
pipeLayer->startPipe();
startGame(); _eventDispatcher->removeEventListener(listener);
}; _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this); //碰撞检測侦听
contactListener=EventListenerPhysicsContact::create();
contactListener->onContactBegin=[=](const PhysicsContact& contact)
{
log("1111111111111111111111111");
//当检測到碰撞的时候,播放hit声音
//小鸟要么撞到草地,要么撞到管道
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sounds/sfx_hit.mp3");
//管道停止运动
pipeLayer->stopPipe();
//草地停止运动
landLayer->stopLand();
//小鸟改变状态
bird->changeState(ACTION_STATE_DIE);
//移除积分器
this->removeChild(NumberLayer::getInstance()); //游戏结束后计分板出现
auto scorecard=GameOverLayer::create();
scorecard->setAnchorPoint(Point::ANCHOR_BOTTOM_LEFT);
scorecard->setPosition(Point::ZERO);
this->addChild(scorecard,99); _eventDispatcher->removeEventListener(contactListener);
return true;
}; _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener,this); return true;
} void GameLayer::startGame()
{
//游戏開始,小鸟转换到飞行状态
bird->changeState(ACTION_STATE_FLY);
//增加积分器并初始化
NumberLayer::getInstance()->initScore();
this->addChild(NumberLayer::getInstance(),10); }
cocos2d-x v3.2 FlappyBird 各个类对象详细代码分析(7)的更多相关文章
- cocos2d-x v3.2 FlappyBird 各个类对象详细代码分析(6)
今天我们要讲三个类,这三个类应该算比較简单的 HelpLayer类 NumberLayer类 GetLocalScore类 HelpLayer类,主要放了两个图形精灵上去,一个是游戏的名字,一个是提示 ...
- C++ 类对象内存模型分析
编译环境:Windows10 + VS2015 1.空类占用的内存空间 类占内存空间是只类实例化后占用内存空间的大小,类本身是不会占内存空间的.用sizeof计算类的大小时,实际上是计算该类实例化后对 ...
- Android开发之dp转像素,像素转换为dp工具类,详细代码,带有源文件下载地址。
import android.content.Context; /** * @author 官网:http://blog.csdn.net/qq_21376985 * * David编写: 微博:ht ...
- C++派生类中如何初始化基类对象(五段代码)
今天收到盛大的面试,问我一个问题,关于派生类中如何初始化基类对象,我在想派生类对于构造函数不都是先构造基类对象,然后在构造子类对象,但是如果我们在成员初始化列表先初始化派生类的私有成员,在函数内去调用 ...
- C++ 类对象和 指针的区别
C++ 类对象和 指针的区别 C++ 类对象和 指针的区别 转自:http://blog.csdn.net/ym19860303/article/details/8557746 指针的情况 class ...
- Android 通过 Intent 传递类对象或list对象
(转:http://www.cnblogs.com/shaocm/archive/2013/01/08/2851248.html) Android中Intent传递类对象提供了两种方式一种是 通过实现 ...
- NSLog(@"%@",类对象); 默认输出类名
NSLog()函数输出Objective-c对象时,输出的是该对象的description方法的返回值.也就是说,以下两行代码作用完全一样(假设p是指向任何对象的指针变量). NSLog(@" ...
- WPF整理-XAML构建后台类对象
1.XAML 接触WPF的第一眼就是XAML---XAML是用来描绘界面的.其实不然! "Actually, XAML has nothing to do with UI. It's mer ...
- class中new与未new的区别 类对象占用空间--转载
转载自http://blog.sina.com.cn/shuiwuhendeboke 颗颗的博客 (1)作用域不同 不用new:作用域限制在定义类对象的方法中,当方法结束时,类对象也被系统释放了 ...
随机推荐
- HDU_2068_RPG错排
Problem Description 今年暑假杭电ACM集训队第一次组成女生队,其中有一队叫RPG,但做为集训队成员之一的野骆驼竟然不知道RPG三个人具体是谁谁.RPG给他机会让他猜猜,第一次猜:R ...
- BetWeen和模糊查询
--区分大小写性能比较低select * from Students where Age >1 and Age <4select * from Students where Age bet ...
- colorful-记录好看的颜色
p { float: left; width: 100px; height: 100px; border: 1px solid black; margin: 5px; text-align: cent ...
- 如何安装Git到MAC OS X
这里介绍两种方式:一,使用Git command-line二,使用GUI工具SourceTree,功能很强大,很方便 在进行安装前,要说一下,Git和SVN一样,都需要创建一个服务器的,他们都可以创建 ...
- C# 导出word文档及批量导出word文档(3)
在初始化WordHelper时,要获取模板的相对路径.获取文档的相对路径多个地方要用到,比如批量导出时要先保存文件到指定路径下,再压缩打包下载,所以专门写了个关于获取文档的相对路径的类. #regio ...
- 武汉科技大学ACM:1010: 电话号码
Problem Description LXD打算换个手机号码,但是他去营业厅选号码的时候却把移动的客服小姐烦得不行,因为他太挑三捡四啦.对于一个手机号的后六位数字(前面五位他就无所谓了),LXD有很 ...
- centos 6.5 安装阿里云的一键安装包(nginx+php5.4+mysql5.1)
安装阿里云提供的Linux一键安装web环境全攻略,本想着会有最复杂 ,没想到阿里云工程师提供的包没有任何限制(开始以为只能在阿里去的主机上使用).开源的精神就是好(注:我是伸手党). 环境 vmw ...
- JavaScript实现回车键切换输入框焦点
用JavaScript实现回车键切换输入框焦点的功能,不是回车换行哦,在Textarea中,回车换行是默认功能,不过若要在textarea中使用 回车切换输入框焦点功能的话,回车换行就要失效了,不过i ...
- 光盘卡在MacBook里退不出来咋办?
如果光盘推不出来了怎么办?很多同学想到的是:上针!不过这招对MacBook Pro毫无用处,因为没有给你插针的地方,没有机械按键,只有键盘右上角一个推出的快捷键,不过在光盘卡在光驱里时,按此健基本无效 ...
- RSA 加密
iOS开发教程-iOS中的RSA加解密 在移动应用开发中常常遇到数据传输安全性的问题,尤其是在账户安全以及支付场景中的订单数据.或支付信息的传输中,正规的公司一定会要求对数据进行加密,当然有创业初期的 ...