cocos2d-x v3.2 FlappyBird 各个类对象具体代码分析(7)

今天我们介绍最后两个类

GameOverLayer类

GameLayer类

GameLayer类是整个游戏中最重要的类,因为是整个游戏的中央系统,控制着各个类(层)之间的交互,这个类中实现了猪脚小鸟和它的敌人(管道和草地- . -)碰撞检测,说道物理引擎的碰撞检测,我也是第一次接触,也没多大难度,就直接调用了cocos2d-x的接口,这个类就是游戏的主场景,游戏就是在这里进行的。

GameOverLayer类,游戏结束后一些分数的显示,还有就是奖牌的实现(楼主写的很简单......),这边比较有意思的就是加分效果的实现,这个楼主以前在写AS3的时候经常用到,最后就是两个按钮,一个重新开始按钮,一个排名按钮,排名按钮没有写功能,这个要跟手机的游戏中心配合。这边放一张游戏结束后的图片:

差不多了,这个游戏所有的类都介绍的差不多了,游戏的源码和图片:

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);

	//游戏结束后,计分板要从屏幕底部向上运动出现
	//动画结束后要显示分数和两个按钮(在回调函数里)
	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();

	//排名和再来一次按钮
	//计分板和gameover精灵执行完动画后,出现按钮
	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));

	//两个按钮坐标的设定
	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));

	//把按钮放到菜单中去
	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()));
}

//排名按钮的回调,这里没写,因为这里要调用的是手机游戏中心的资料
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);

}
时间: 2024-08-30 02:42:29

cocos2d-x v3.2 FlappyBird 各个类对象具体代码分析(7)的相关文章

cocos2d-x v3.2 FlappyBird 各个类对象具体代码分析(6)

今天我们要讲三个类,这三个类应该算比较简单的 HelpLayer类 NumberLayer类 GetLocalScore类 HelpLayer类,主要放了两个图形精灵上去,一个是游戏的名字,一个是提示游戏怎么玩的,就一张图: NumberLayer类,涉及到自定义字体的制作,我们提取出来的资源里,有很多数字图片: 现在我们要把它们做成这样子的: 这个跟游戏图片资源差不多,做成这样就可以直接拿来用,省了很多事情,那怎么做了,这里我们要用到一个叫软件,具体使用方法和过程,我这里就不介绍了,大家直接戳

cocos2d-x v3.2 FlappyBird 各个类对象具体代码分析(5)

今天介绍的是管道层 PipeLayer.h PipeLayer.cpp 管道层主要实现的是管道从右边往左边平移,结束后移除,而且管道还要长短高低不一样,然后就是如何判断小鸟通过一个管道.先说管道的平移,这个很简单,用一个函数把两跟管道封装好,让它moveby或者moveto好了,平移结束后,用一个回调函数移除自己就够了,当然封装好管道后,我们要把每一个管道放到一个数组里,方便管理嘛:然后就是管道高低不一样这里用一张图表示: 最后就是小鸟通过管道判断,这里我们是判断一个完整的管道是否通过屏幕中心线

cocos2d-x v3.2 FlappyBird 各个类对象具体代码分析(1)

好久没写博客了,今天早上起来不知怎么的就打开了csdn,工作简历也投了好几家,都石沉大海,在学校也闲着没事,就打算把以前写的Flappy Bird里面的一些代码分析发出来. Flappy Bird 网上也有很多的教程,我其中的有些代码也是参考网上的,不能算是完全原创吧,但是也有很大一部分代码都是按照我自己的想法,设计写出来的,接触cocos2d-x已经差不多有一年了,从以前的2x到现在的3x,改变了很多东西,作为一个新手我还有很多东西要去学习. 开始前有几点注意事项要说明: 1)我的Flappy

cocos2d-x v3.2 FlappyBird 各个类对象具体代码分析(4)

今天要讲的使我们猪脚类 SpriteBird.h SpriteBird.cpp 猪脚类要注意的是三种状态的切换,和单点触控侦听的设置,还有就是小鸟在飞行的过程中,头部会上下的摆动,物理模型这里就不说了,小鸟头部的摆动是靠小鸟Y轴的速度来判定的,当小鸟向上飞的时候,速度是正的,所以头部摆动的旋转角度也是向上,当小鸟下落的时候,速度是负的,所以头部摆动的旋转角度是向下的. 小鸟的三种状态: 下面是代码 //SpriteBird.h #pragma once #include "cocos2d.h&q

cocos2d-x v3.2 FlappyBird 各个类对象具体代码分析(3)

今天介绍两个比较简单的类 GameBegin.h LandLayer.h 需要注意的有两点,一个是草地的滚动,还有一个是物理模型,都在LandLayer.h中实现,分析都在代码注释中. 先上GameBegin场景的效果图 这张图可以解析为 背景图的添加 游戏名字 小鸟以及小鸟飞行动画 按钮 草地(草地是会滚动的) //GameBegin.h #pragma once #include "cocos2d.h" class GameBegin:public cocos2d::Layer {

面向对象--多继承&amp;派生类对象内存布局分析&amp;各基类指针所指向的位置分析

背景 原文链接:ordeder  http://blog.csdn.net/ordeder/article/details/25477363 关于非虚函数的成员函数的调用机制,可以参考: http://blog.csdn.net/yuanyirui/article/details/4594805 成员函数的调用涉及到面向对象语言的反射机制. 虚函数表机制可以查看下面这个blog: http://blog.csdn.net/haoel/article/details/1948051 总结为: 其一

黑马程序员_类对象创建代码的执行顺序测试总结

class StaticCode { // 类的非静态成员变量(实例变量)定义语句: // 作用:用来存储对象的特有数据的成员变量. // 运行:当类对象被创建时就执行,按照顺序自上而下执行,和构造代码块平级.(即当有多个构造函数 // 代码块和多个非静态成员变量时,JVM按照自上而下的顺序来执行所有语句,包括构造代码块里的代码 // 和非静态成员的声明.) // 存储位置:非静态变量位于堆内存中的对象实体中. int num = 3; // 构造代码块 { System.out.println

java 类对象使用

在学习反射机制时,总结一下获得类对象方式: 第一种方式:通过类本身来获得对象 Class<?> classname = this.getClass(); 或者this.class 第二种方式:通过子类的实例获取父类对象 ClassName cn = new ClassName(); UserClass = cn.getClass(); Class<?> SubUserClass = UserClass.getSuperclass(); 第三种方式:通过类名加.class获取对象 C

C++实现根据类名动态生成类对象

在开发后台服务的过程中,我们常常需要从数据库中取数据,并将数据缓存在本地中,另外,我们的服务还需要有更新数据的能力:包括定时的主动更新以及数据库数据更新时服务收到通知的被动更新. 之前在需要用到以上功能的时候,模仿着组内通用的数据Cache部分的代码来写,十分方便,基本上只需要自己写两个类:一个是取数据并缓存数据的类XXXData,一个是扇出数据的类XXXFetcher. 在需要使用数据的时候,通过: FetcherFactory::getFetcher<XXXFetcher>() 即可获取一