zoukankan      html  css  js  c++  java
  • 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);
    
    }
    
    



  • 相关阅读:
    readLine读取socket流的时候产生了阻塞
    Netty开发UDP协议
    Netty关闭客户端
    GIT 回退出错 Unlink of file 'xx' failed. Should I try again? (y/n) 解决办法
    linux 安全狗安装问题
    linux连接mysql命令
    CentOS7 64位下MySQL5.7安装与配置(YUM)
    nginx已经启动 无法访问页面
    Linux系统下我的/etc/sysconfig/路径下无iptables文件
    CentOS 7 下安装 Nginx
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5261764.html
Copyright © 2011-2022 走看看