cocos2d_x_08_游戏_FlappyBird

最终效果图:

环境版本:cocos2d-x-3.3beta0 使用内置的物理引擎

计时器没有添加,可参考【cocos2d_x_06_游戏_一个都不能死

主场景

//
//  FlappyBirdScene.h
//  01_cocos2d-x
//
//  Created by beyond on 14-10-7.
//
//

#ifndef ___1_cocos2d_x__FlappyBirdScene__
#define ___1_cocos2d_x__FlappyBirdScene__

#include "cocos2d.h"

#include "FlappyBird.h"
#include "Floor.h"
#include "TopBar.h"
#include "BottomBar.h"

USING_NS_CC;
// 注意 这儿,继承的是 Layer
class FlappyBirdScene : public cocos2d::Layer
{
private:
    // 屏幕尺寸
    Size winSize;
    // 小鸟
    FlappyBird *bird;
    // 地板
    Floor *floor;
    // 顶部圆管
    TopBar *topBar;
    // 底部圆管
    BottomBar *bottomBar;

    // 用一个Node 包装起来 所有的圆管,因为圆管在后面,要最先添加;然后才添加floor
    Node *_barContainer;

private:

    // 每隔 随机的时间,创建并添加一个圆管
    void addTopBar();
    void addBottomBar();

    // 临时变量,用于累计 记录 流逝的时间
    int tempTimeDelta;
    // 总共的时间间隔 (即 时间delta累计到 该间隔时,创建并添加一个圆管)
    int totalIntervalTime;

    // 每添加一个新的障碍物之后,需重置 用于累计 记录 流逝的时间 的变量
    void resetTempTimeDelta();

public:
    // c++里面没有id类型, 所以 返回类的实例对象的 指针
    static cocos2d::Scene* createScene();
    // 以下是 不同点:cocos2d-x的 'init' 方法 返回 bool
    // 而cocos2d-iphone 返回 'id' 类型
    virtual bool init();
    // 宏 自动实现 "静态的 create()方法"
    CREATE_FUNC(FlappyBirdScene);

    // 时钟方法
    // 在场景的时钟方法中,更新\控制  每一个游戏控制器的时钟方法
    virtual void update(float dt);

    // 添加小鸟
    void addBird();
    // 添加地板
    void addFloor();

};

#endif /* defined(___1_cocos2d_x__FlappyBirdScene__) */
//
//  FlappyBirdScene.cpp
//  01_cocos2d-x
//
//  Created by beyond on 14-10-7.
//
//

#include "FlappyBirdScene.h"
#include "GameOverScene.h"

USING_NS_CC;
Scene* FlappyBirdScene::createScene()
{
    // 'scene' 自动释放
    // 使用cocos2d 内置的物理引擎
    auto scene = Scene::createWithPhysics();
    // 显示 调试用的 刚体 边线
    // scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
    // 调整重力加速度
    scene->getPhysicsWorld()->setGravity(Vec2(0, -1000));

    // 'layer' 自动释放
    auto layer = FlappyBirdScene::create();
    // 将图层 添加到场景中
    scene->addChild(layer);
    // 返回 填充好图层的 场景
    return scene;
}

// 在 "init" 方法中,实例化自己要用的精灵对象
bool FlappyBirdScene::init()
{
    // 1. 调用父类的init , cpp 没有super,直接写父类名
    if ( !Layer::init() ) return false;
    // 屏幕尺寸
    winSize = Director::getInstance()->getVisibleSize();

    // 2.添加小鸟
    addBird();
    // 2.添加地板
    addFloor();

    // 初始化时,添加一个新的圆管
    tempTimeDelta = totalIntervalTime;

    // 开启消息调度
    scheduleUpdate();
    // ********************************************
    // 物理碰撞检测 「PhysicsContact」
    auto listener = EventListenerPhysicsContact::create();
    // 开始碰撞 游戏结束
    listener->onContactBegin = [this](PhysicsContact & contact){

        // 取消 消息调度
        this->unscheduleUpdate();
        // 切换至Game Over场景
        Director::getInstance()->replaceScene(GameOverScene::createScene());
        return true;
    };
    // 向事件分发器,注册listener
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
    // ********************************************
    // 用户单点触摸 jump high 【TouchOneByOne】
    auto touchListener = EventListenerTouchOneByOne::create();
    // 开始触摸 原地 跳一下
    touchListener->onTouchBegan = [this](Touch * t,Event * e){
        // 每点一下,原地跳一下
        bird->getPhysicsBody()->setVelocity(Vec2(0, 400));
        log(">>>click<<<");
        return false;
    };
    // 向事件分发器,注册listener
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener, this);
    return true;
}

// 在 "init" 方法中,添加小鸟
void FlappyBirdScene::addBird()
{
    //**************************************
    bird = FlappyBird::create();
    // 屏幕中间
    bird->setPosition(winSize.width/2, winSize.height/2);
    // 添加到Layer
    addChild(bird);
}
// 在 "init" 方法中,添加地板
void FlappyBirdScene::addFloor()
{
    //**************************************
    floor = Floor::create();
    // 屏幕底部
    floor->setPosition(winSize.width/2, floor->getContentSize().height/2);
    // 添加到Layer
    addChild(floor);
}
#pragma mark - 时钟方法
void FlappyBirdScene::update(float dt)
{
    // 每隔一段时间,添加 上圆管和下圆管
    // 临时变量,用于累计 记录 流逝的时间
    tempTimeDelta++;
    // 总共的时间间隔 (即 时间delta累计到 该间隔时,创建并添加一个障碍物)
    if (tempTimeDelta >= totalIntervalTime)
    {
        // 每添加一个新的障碍物之后,需重置 用于累计 记录 流逝的时间 的变量
        resetTempTimeDelta();
        // 每隔 随机的时间,创建并添加一个障碍物
        addBottomBar();
        addTopBar();

    }
}
// 每添加一个新的障碍物之后,需重置 用于累计 记录 流逝的时间 的变量
void FlappyBirdScene::resetTempTimeDelta()
{
    tempTimeDelta = 0;
    totalIntervalTime = (rand()%50) + 20;
}
// 创建 并 添加 底部圆管  (在随机的 时间 间隔 之后 )
void FlappyBirdScene::addBottomBar()
{
    bottomBar = BottomBar::create();
    addChild(bottomBar);
    // 屏幕外
    bottomBar->setPositionX(winSize.width );
    // 注意 底部圆管的y值是 在地板之上
    // 即 bottomBar的半高
    bottomBar->setPositionY(bottomBar->getContentSize().height/2 + floor->getContentSize().height);
}
// 创建 并 添加 顶部圆管  (在随机的 时间 间隔 之后 )
void FlappyBirdScene::addTopBar()
{
    // 开口大小 为 70 ~ 130
    int margin = (rand()%60) + 70;

    topBar = TopBar::create();
    addChild(topBar);
    // 屏幕外
    topBar->setPositionX(winSize.width );
    // 注意 顶部圆管的y值是
    // 即 底部圆管的高 + 400 + 自己的半高 + 地板的高
    topBar->setPositionY(topBar->getContentSize().height/2 + margin +bottomBar->getContentSize().height +floor->getContentSize().height);
}

封闭的精灵

Bird

//
//  FlappyBird.h
//  01_cocos2d-x
//
//  Created by beyond on 14-10-7.
//
//

#ifndef ___1_cocos2d_x__FlappyBird__
#define ___1_cocos2d_x__FlappyBird__

#include <cocos2d.h>

USING_NS_CC;

class FlappyBird:public Sprite {

public:
    // 宏,静态的create方法,内部会调用init方法
    CREATE_FUNC(FlappyBird);
    virtual bool init();

};

#endif /* defined(___1_cocos2d_x__FlappyBird__) */

//
//  FlappyBird.cpp
//  01_cocos2d-x
//
//  Created by beyond on 14-10-7.
//
//

#include "FlappyBird.h"

bool FlappyBird::init()
{
    // 父类的init方法
    Sprite::init();
    // 执行 帧动画 一直拍打翅膀 扑腾着飞 RepeatForever
    setTexture("bird.png");
    // 图片的尺寸
    Size s = Size(34, 34);
    // 精灵的大小
    setContentSize(s);

    // 设置物理世界的刚体body
    setPhysicsBody(PhysicsBody::createBox(s));
    // 刚体不允许 旋转
    getPhysicsBody()->setRotationEnable(false);
    // 重要~~~若想参与 碰撞,必须绑定一个碰撞标识
    getPhysicsBody()->setContactTestBitmask(1);

    return true;
}

地板Floor

//
//  Floor.h
//  01_cocos2d-x
//
//  Created by beyond on 14-10-7.
//
//  地板

#ifndef ___1_cocos2d_x__Floor__
#define ___1_cocos2d_x__Floor__

#include <cocos2d.h>

USING_NS_CC;

class Floor:public Sprite {

public:
    // 宏,静态的create方法,内部会调用init方法
    CREATE_FUNC(Floor);
    virtual bool init();

};

#endif /* defined(___1_cocos2d_x__Floor__) */

//
//  Floor.cpp
//  01_cocos2d-x
//
//  Created by beyond on 14-10-7.
//
//

#include "Floor.h"

bool Floor::init()
{
    // 父类的init方法
    Sprite::init();
    // 地板图片
    setTexture("floor.png");
    // 图片的尺寸
    Size s = Size(640, 208);
    // 精灵的大小
    setContentSize(s);

    // 设置物理世界的刚体body
    setPhysicsBody(PhysicsBody::createBox(s));
    // 刚体不允许 旋转
    getPhysicsBody()->setRotationEnable(false);
    // 重要~~~若想参与 碰撞,必须绑定一个碰撞标识
    getPhysicsBody()->setContactTestBitmask(1);
    // 不是动态的刚体 即:是静态的刚体
    getPhysicsBody()->setDynamic(false);

    // *****************************
    // 播放帧动画
    // 容器,数组,里面存放的是精灵帧
    Vector<SpriteFrame*> vec;
    SpriteFrame *frame1 = SpriteFrame::create("floor.png", Rect(0, 0, 640, 208));
    SpriteFrame *frame2 = SpriteFrame::create("floor2.png", Rect(0, 0, 640, 208));
    // 将小精灵帧  加入容器
    vec.pushBack(frame1);
    vec.pushBack(frame2);
    // 创建 Animation
    Animation *animation = Animation::createWithSpriteFrames(vec,0.1f);
    // 创建 Animate
    Animate *animate = Animate::create(animation);
    // 执行序列帧动画
    Sequence *seq = Sequence::create(animate,animate->reverse(), NULL);
    runAction(RepeatForever::create(seq));

    return true;
}

TopBar和BottomBar还可以抽取

//
//  TopBar.h
//  01_cocos2d-x
//
//  Created by beyond on 14-10-7.
//
//  圆管 内部分为上圆管和下圆管

#ifndef ___1_cocos2d_x__TopBar__
#define ___1_cocos2d_x__TopBar__

#include <cocos2d.h>

USING_NS_CC;

class TopBar:public Sprite {
public:
    // 宏,静态的create方法,内部会调用init方法
    CREATE_FUNC(TopBar);
    virtual bool init();
    // 时钟方法,内部会 让 障碍物不断地向左移动
    void update(float dt);
};

#endif /* defined(___1_cocos2d_x__TopBar__) */

//
//  TopBar.cpp
//  01_cocos2d-x
//
//  Created by beyond on 14-10-7.
//
//

#include "TopBar.h"

bool TopBar::init()
{
    // 父类的init方法
    Sprite::init();

    setTexture("top_bar2.png");
    // 图片的尺寸
    Size s = Size(52, 450);
    // 精灵的大小
    setContentSize(s);

    // 设置物理世界的刚体body
    setPhysicsBody(PhysicsBody::createBox(s));
    // 刚体不允许 旋转
    getPhysicsBody()->setRotationEnable(false);
    // 重要~~~若想参与 碰撞,必须绑定一个碰撞标识
    getPhysicsBody()->setContactTestBitmask(1);
    // 不是动态的刚体 即:是静态的刚体
    getPhysicsBody()->setDynamic(false);
    // ***************************************
    // 开启时钟方法
    scheduleUpdate();
    return true;
}
#pragma mark - 时钟方法
// 时钟方法,内部会 让 障碍物不断地向左移动
void TopBar::update(float dt)
{
    this->setPositionX(getPositionX()-20);
    // 移动到屏幕外边时,就停止消息调度,并且移除
    if (getPositionX()<0)
    {
        log("remove top bar");
        unscheduleUpdate();
        removeFromParent();
    }
}

//
//  BottomBar.h
//  01_cocos2d-x
//
//  Created by beyond on 14-10-7.
//
//  圆管 内部分为上圆管和下圆管

#ifndef ___1_cocos2d_x__BottomBar__
#define ___1_cocos2d_x__BottomBar__

#include <cocos2d.h>

USING_NS_CC;

class BottomBar:public Sprite {
public:
    // 宏,静态的create方法,内部会调用init方法
    CREATE_FUNC(BottomBar);
    virtual bool init();

    // 时钟方法,内部会 让 底部圆管 不断地向左移动
    void update(float dt);

};

#endif /* defined(___1_cocos2d_x__BottomBar__) */

//
//  BottomBar.cpp
//  01_cocos2d-x
//
//  Created by beyond on 14-10-7.
//
//

#include "BottomBar.h"

bool BottomBar::init()
{
    // 父类的init方法
    Sprite::init();

    setTexture("bottom_bar.png");
    // 图片的尺寸
    Size s = Size(52, 319);
    // 精灵的大小
    setContentSize(s);

    // 设置物理世界的刚体body
    setPhysicsBody(PhysicsBody::createBox(s));
    // 刚体不允许 旋转
    getPhysicsBody()->setRotationEnable(false);
    // 重要~~~若想参与 碰撞,必须绑定一个碰撞标识
    getPhysicsBody()->setContactTestBitmask(1);
    // 不是动态的刚体 即:是静态的刚体
    getPhysicsBody()->setDynamic(false);
    // ***************************************
    // 开启时钟方法
    scheduleUpdate();
    return true;
}
#pragma mark - 时钟方法
// 时钟方法,内部会 让 障碍物不断地向左移动
void BottomBar::update(float dt)
{
    this->setPositionX(getPositionX()-20);
    // 移动到屏幕外边时,就停止消息调度,并且移除
    if (getPositionX()<0)
    {
        unscheduleUpdate();
        removeFromParent();
    }
}

时间: 2025-01-15 07:37:32

cocos2d_x_08_游戏_FlappyBird的相关文章

20170913自制猜数字游戏

/* 猜数字:系统随机生成一个四位数,请根据下列判断猜出来 A:数值正确,位置正确 B:数值正确,位置不正确 C:数值不正确 */ #include<stdio.h> #include<time.h> #include<stdlib.h> #pragma warning (disable:4996) #define pUCharHead unsigned char * //以数组形式返回n个无重复的随机数,范围可指定[min,max] pUCharHead GenNoR

洛谷P1199 三国游戏

题目描述 小涵很喜欢电脑游戏,这些天他正在玩一个叫做<三国>的游戏. 在游戏中,小涵和计算机各执一方,组建各自的军队进行对战.游戏中共有 N 位武将(N为偶数且不小于 4),任意两个武将之间有一个"默契值",表示若此两位武将作为一对组合作战时,该组合的威力有多大.游戏开始前,所有武将都是自由的(称为自由武将,一旦某个自由武将被选中作为某方军队的一员,那么他就不再是自由武将了),换句话说,所谓的自由武将不属于任何一方. 游戏开始,小涵和计算机要从自由武将中挑选武将组成自己的军

游戏开发 系统app开发游戏定制开发找谁

梦幻珍珠港理财拆分游戏系统软件开发怎么做?找[江生:185-2911-8412 微电]. 梦幻珍珠港拆分游戏平台开发.梦幻珍珠港理财全网模式开发.梦幻珍珠港收益模式介绍开发. 梦幻珍珠港拆分游戏系统源码搭建平台!!我们是软件开发,玩家勿扰!非平台客服,玩家勿扰!] 游戏规则: 一.开发新会员要从您的库房扣除3 03颗珍珠,体系扣除5颗珍珠,新会员有298颗珍珠. 二.推荐老友,推荐人能够得到第一代会员的2%,第二代会员的1%,第三代会员的0.5%,一代的收益就是5.96颗珍珠奖赏(可转换为等量可

游戏服务器开发需要学习的技术

一,游戏服务器编程语言的选择 所谓的游戏服务器编程语言其实有很多,基本上任何一种语言都可以作为游戏服务器的编程语言.这需要根据自己游戏的类型和要求加以选择.比如C++,Java ,Erlang,go等等.目前我用过的只有C++和Java.但是以Java为主.所以接下来就以自己的经验,谈谈以Java为核心的游戏服务器开发技术体系. Java目前作为游戏服务器开发语言已经很是普遍.但是大多数是作为页游或手游的服务器,而端游戏一般选择C++,因为端游对服务器的性能要求相对比较高一些.两种语言各有利弊.

赛码网算法: 格子游戏

格子游戏 题目描述 有n个格子,从左到右放成一排,编号为1-n.共有m次操作,有3种操作类型:1.修改一个格子的权值,2.求连续一段格子权值和,3.求连续一段格子的最大值.对于每个2.3操作输出你所求出的结果. 输入输入第一行两个整数,n表示格子个数,m表示操作次数,n和m中间用空格隔开:接下来输入n行,每行一个整数表示一个格子的权值接下来输入m行,每行有三个整数,中间用空格隔开:第一个是选择的操作类型1-3,第二和第三个整数是操作格子的编号.样例输入3 37892 1 33 1 32 1 2输

【BZOJ4945】[Noi2017]游戏 2-SAT

[BZOJ4945][Noi2017]游戏 题目描述 题解:2-SAT学艺不精啊! 这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起! 因为x要么不是A要么不是B,所以直接2^8枚举所有x就行了.然后就变成了一个2-SAT问题.假设有两场游戏1,2,分别可以使用的地图为A1,A2,B1,B2,如果有一个限制是1 A 2 A,那么选A1就必须选A2,然后我这个沙茶就开开心心的拿了55分. 为什么不对?我建出来的图显然不对偶啊!考虑逆否命题,选A1就必须选

“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛 B

<神无月>作为盛大游戏2017年的全新原创大作,其开发团队在自研实力强大的传世工作室基础之上,还有美树本晴彦等日本一线知名画师及日本游戏音乐大师崎元仁加盟参与制作.目前正在不限号内测中,有很多玩家进入到神无月的世界中. 在神无月中,有着玩家之间切磋的排位赛,其段位主要分为五大段位,从低到高依次为:新兵.菁英.战将.统帅.王者.每个玩家只有从新兵段位慢慢努力,一点点晋级才能到达王者段位.成为一个王者是每一个玩家的追求和心愿. 假设神无月的段位系统如下: 从低到高的段位依次简记为:D.C.B.A.

P1070 道路游戏

题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依次将这 n 个机器人工厂编号为1~n,因为马路是环形的,所以第 n 个机器人工厂和第 1 个机器人工厂是由一段马路连接在一起的.小新将连接机器人工厂的这 n 段马路也编号为 1~n,并规定第 i 段马路连接第 i 个机器人工厂和第 i+1 个机器人工厂(1≤i≤n-1),第 n 段马路连接第 n 个机器人工厂和第 1个机器人

这个必须有,用真实社交游戏遏制“蓝鲸”

要遏制"蓝鲸"这类死亡游戏带来的强迫症式体验,建议采取"以毒攻毒"的"替代疗法".比如让玩家在社交基础上获得更有成就感的游戏体验,真正达到治本的效果. 文/张书乐 人民网.人民邮电报专栏作者,著有<微博运营完全自学手册> 曾有人总结过玩家患上游戏强迫症的状态:套装.成就全收集:地图.场景全探索:射击游戏打了两枪就换子弹:地图上的箱子必须全部开启:将NPC全部对话一遍:一分钟一存档:精心创造一个独特角色:场景内物品全破坏:见到新游戏就下