Cocos2d-x 2.3.3版 FlappyBird

Cocos2d-x 2.3.3版 FlappyBird

本篇博客基于Cocos2d-x 2.3.3, 介绍如何开发一款之前很火的一款游戏FlappyBird。本篇博客内容大纲如下:

1. 如何创建Cocos2d-x 2.3.3 项目

2. 初始化Box2d物理世界,并模拟物理世界

3. 如何添加小鸟到物理世界

4. 如何添加地板

5. 添加水管

6. 碰撞检测

7. 本文总结

效果图:

1. 如何创建Cocos2d-x 2.3.3

本篇博客是基于Cocos2d-x 2.3.3,初学者可以选择这个版本学习,也可以从3.x版本学习,但版本差异较大。

用命令行进入目录D:\cocos2d-x-2.2.3\tools\project-creator,敲入以下命令创建项目:

python create_project.py -project FlappyBirdCpp -package com.wwj.flappybird -language cpp

创建了名为FlappyBirdCpp的Cocos2d-x项目,包名为com.wwj.flappybird,开发语言为c++

2. 初始化Box2d物理世界,并模拟物理世界

Cocos2d-x使用了Box2d物理引擎来模拟物理世界,它还支持Chipmunk物理引擎,这里我们使用Box2d来为我们创建一个看似比较真实的世界。

// -10表示重力加速度方向为向下
	world = new b2World(b2Vec2(0, -10));
// 模拟物理世界
	// Box2D建议的迭代次数是速度阶段8次,位置阶段3次
	world->Step(dt, 8, 3);

3. 如何添加小鸟到物理世界

小鸟在Cocos2d-x就是一个Sprite(精灵),我们知道精灵是需要添加到层当中的,我们还要设置我们小鸟在物理世界的刚体。关于Box2d相关的概念,笔者在这里不详细说,读者可以自己找百度老师,学习更多关于Box2d的知识。

我们定义以下方法:

/**
* 添加小鸟
*
*/
void HelloWorld::addBird()
{
	// 创建小鸟
	bird = B2Sprite::create("bird.png");
	// 获取内容大小
	CCSize size = bird->getContentSize();

	// 刚体属性
	b2BodyDef bodyDef;
	// 动态刚体
	bodyDef.type = b2_dynamicBody;
	// 设置初始位置
	bodyDef.position = b2Vec2(screenSize.width/2/RATIO, screenSize.height/2/RATIO);
	// 创建一个小鸟刚体
	b2Body *birdBody = world->CreateBody(&bodyDef);

	// 隐形形状
	b2PolygonShape birdShape;
	// 设置为盒子,参数为内容的半宽半高
	birdShape.SetAsBox(size.width/2/RATIO, size.height/2/RATIO);

	// 材料属性
	b2FixtureDef birdFixtureDef;
	// 形状
	birdFixtureDef.shape = &birdShape;
	// 添加地表物体
	birdBody->CreateFixture(&birdFixtureDef);

	// 设置度量比例
	bird->setPTMRatio(RATIO);
	// 设置小鸟刚体
	bird->setB2Body(birdBody);
	// 添加小鸟到层中
	addChild(bird);

}

4. 如何添加地板

地板跟小鸟也是类似的,只是设置地板刚体的类型为静态的,因为它相对静止的也不受重力影响。

/**
* 添加地板
*/
void HelloWorld::addGround()
{
	// 地板精灵
	B2Sprite *ground = B2Sprite::create("ground.png");
	// 得到地板内容的大小
	CCSize size = ground->getContentSize();

	// 用于初始化刚体在物理世界的一些属性,比如位置,类型
	b2BodyDef bDef;
	// 静态的刚体
	bDef.type = b2_staticBody;
	// 设置位置
	bDef.position = b2Vec2(size.width/2/RATIO, size.height/2/RATIO);
	// 创建刚体
	b2Body *groundBody = world->CreateBody(&bDef);

	// 形状
	b2PolygonShape groundShape;
	// 设置为矩形
	groundShape.SetAsBox(size.width/2/RATIO, size.height/2/RATIO);
	// 材料定制器
	b2FixtureDef groundFixtureDef;
	// 设置形状
	groundFixtureDef.shape = &groundShape;
	// 创建定制器
	groundBody->CreateFixture(&groundFixtureDef);
	// 为精灵设置刚体
	ground->setB2Body(groundBody);
	// 设置度量比例
	ground->setPTMRatio(RATIO);
	// 添加地板到层当中
	addChild(ground);

}

5. 添加水管

我们玩FlappyBird的时候,会知道水管高低不同,然后是从右往左运动的,这就需要我们随机设置上下两根水管的位置了,并且不停的添加水管。

/ 添加运动的水管
void HelloWorld::addBar(float dt) {
	// 随机生成偏移量
	float offset = -rand() %5;

	// 创建向下水管的精灵
	B2Sprite *down_bar = B2Sprite::create("down_bar.png");
	// 得到水管的大小
	CCSize down_bar_size = down_bar->getContentSize();

	// 下水管
	b2BodyDef down_bar_body_def;
	// 运动学物体,但不受重力影响
	down_bar_body_def.type = b2_kinematicBody;
	// 设置下水管的位置
	down_bar_body_def.position = b2Vec2(screenSize.width/RATIO + 2, down_bar_size.height/RATIO/2 +offset);
	// 线性速度,从右往左移动
	down_bar_body_def.linearVelocity = b2Vec2(-5,0);
	// 创建刚体
	b2Body *down_bar_body = world->CreateBody(&down_bar_body_def);

	// 隐形形状
	b2PolygonShape down_bar_shape;
	// 设置为盒子,参数为内容的半宽半高
	down_bar_shape.SetAsBox(down_bar_size.width/2/RATIO, down_bar_size.height/2/RATIO);
	// 声明定制器
	b2FixtureDef down_bar_fixture_def;
	// 定制器形状
	down_bar_fixture_def.shape = &down_bar_shape;
	// 为刚体创建定制器
	down_bar_body->CreateFixture(&down_bar_fixture_def);

	// 设置精灵刚体
	down_bar->setB2Body(down_bar_body);
	// 设置度量
	down_bar->setPTMRatio(RATIO);

	// 上水管
	B2Sprite *up_bar = B2Sprite::create("up_bar.png");
	// 获得内容大小
	CCSize up_bar_size = up_bar->getContentSize();

	b2BodyDef up_bar_body_def;
	// 运动学物体,但不受重力影响
	up_bar_body_def.type = b2_kinematicBody;
	// 设置水管位置
	up_bar_body_def.position = b2Vec2(screenSize.width/RATIO+2, down_bar_size.height/RATIO+offset+2+up_bar_size.height/2/RATIO);
	up_bar_body_def.linearVelocity = b2Vec2(-5, 0);
	b2Body *up_bar_body = world->CreateBody(&up_bar_body_def);

	// 隐形形状
	b2PolygonShape up_bar_shape;
	// 设置为盒子形状,参数为半宽半高
	up_bar_shape.SetAsBox(up_bar_size.width/2/RATIO, up_bar_size.height/2/RATIO);
	b2FixtureDef up_bar_fixture_def;
	up_bar_fixture_def.shape = &up_bar_shape;
	up_bar_body->CreateFixture(&up_bar_fixture_def);
	up_bar->setB2Body(up_bar_body);
	up_bar->setPTMRatio(RATIO);

	barContainer->addChild(down_bar);
	barContainer->addChild(up_bar);

}

6. 添加碰撞检测

这里需要说一下如何让小鸟运动,我们需要设置屏幕的监听事件,并且让小鸟有一个向上的线性速度,点击屏幕的时候小鸟向上运动,松开则下坠。

我们需要重写方法:

virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);

实现:

// 触摸事件开始
void HelloWorld::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent) {
	bird->getB2Body()->SetLinearVelocity(b2Vec2(0, 5));
}

接下来讲碰撞检测,这个我们同样也要设置监听器,我们设置的是物理世界的事件监听。

// 添加碰撞监听
	world->SetContactListener(this);

然后重写以下方法:

 virtual void BeginContact(b2Contact* contact);

void HelloWorld::BeginContact(b2Contact *contact) {
	// 发生碰撞,则弹出对话框
	if (contact->GetFixtureA()->GetBody()->GetUserData() == bird ||
		contact->GetFixtureB()->GetBody()->GetUserData() == bird) {
			stopGame();
			CCMessageBox("游戏失败","游戏失败");
	}

}

7. 本文总结

以上内容就是开发一款FlappyBird的简单Demo,读者可以在这个的基础上实现更丰富的功能,笔者觉得不想一步到位把所有东西介绍完毕。最重要的还是思路,把基本的东西掌握了,然后就可以按照这样的思路去做一个这样的东西。

可以到以下地址下载源码:https://github.com/devilWwj/eoeFlappyBird

下面是完整实现:

HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "Box2D\Box2D.h"// 引入Box2D物理引擎
#include "B2Sprite.h"	

// 定义物理世界的比例
#define RATIO 48.0f
class HelloWorld : public cocos2d::CCLayer,public b2ContactListener
{
public:
    // Here‘s a difference. Method ‘init‘ in cocos2d-x returns bool, instead of returning ‘id‘ in cocos2d-iphone
    virtual bool init();  

    // there‘s no ‘id‘ in cpp, so we recommend returning the class instance pointer
    static cocos2d::CCScene* scene();

    // a selector callback
    void menuCloseCallback(CCObject* pSender);

    // implement the "static node()" method manually
    CREATE_FUNC(HelloWorld);

	virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
	 virtual void BeginContact(b2Contact* contact);

	// 重写update方法
	virtual void update(float dt);

	// 声明物理世界引用
	b2World *world;
	B2Sprite *bird;
	CCSize screenSize;
	CCSprite *barContainer;

private:
	// 添加小鸟
	void addBird();
	// 初始化物理世界
	void initWorld();
	// 添加地板
	void addGround();
	// 添加水管
	void addBar(float dt);
	// 添加一个容器
	void addBarContainer();
	// 开始游戏
	void startGame(float dt);
	// 结束游戏
	void stopGame();
};

#endif // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp

#include "HelloWorldScene.h"

USING_NS_CC;

CCScene* HelloWorld::scene()
{
	// ‘scene‘ is an autorelease object
	CCScene *scene = CCScene::create();

	// ‘layer‘ is an autorelease object
	HelloWorld *layer = HelloWorld::create();

	// add layer as a child to scene
	scene->addChild(layer);

	// return the scene
	return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
	//////////////////////////////
	// 1. super init first
	if ( !CCLayer::init() )
	{
		return false;
	}
	// 获取屏幕大小
	screenSize = CCDirector::sharedDirector()->getVisibleSize();
	initWorld();
	addBird();
	addBarContainer();
	addGround();

	// 设置可点击
	setTouchEnabled(true);
	//scheduleUpdate();
	//schedule(schedule_selector(HelloWorld::addBar), 1);
	// 3秒之后执行
	scheduleOnce(schedule_selector(HelloWorld::startGame),3);
	return true;
}

/**
* 添加小鸟
*
*/
void HelloWorld::addBird()
{
	// 创建小鸟
	bird = B2Sprite::create("bird.png");
	// 获取内容大小
	CCSize size = bird->getContentSize();

	// 刚体属性
	b2BodyDef bodyDef;
	// 动态刚体
	bodyDef.type = b2_dynamicBody;
	// 设置初始位置
	bodyDef.position = b2Vec2(screenSize.width/2/RATIO, screenSize.height/2/RATIO);
	// 创建一个小鸟刚体
	b2Body *birdBody = world->CreateBody(&bodyDef);

	// 隐形形状
	b2PolygonShape birdShape;
	// 设置为盒子,参数为内容的半宽半高
	birdShape.SetAsBox(size.width/2/RATIO, size.height/2/RATIO);

	// 材料属性
	b2FixtureDef birdFixtureDef;
	// 形状
	birdFixtureDef.shape = &birdShape;
	// 添加地表物体
	birdBody->CreateFixture(&birdFixtureDef);

	// 设置度量比例
	bird->setPTMRatio(RATIO);
	// 设置小鸟刚体
	bird->setB2Body(birdBody);
	// 添加小鸟到层中
	addChild(bird);

}
// 初始化物理世界
void HelloWorld::initWorld()
{
	// -10表示重力加速度方向为向下
	world = new b2World(b2Vec2(0, -10));
	// 添加碰撞监听
	world->SetContactListener(this);
} 

// 更新
void HelloWorld::update(float dt)
{
	// 模拟物理世界
	// Box2D建议的迭代次数是速度阶段8次,位置阶段3次
	world->Step(dt, 8, 3);
	CCSprite *s;

	// 遍历销毁
	for (b2Body *b = world->GetBodyList(); b!= NULL; b=b->GetNext()) {
		if (b->GetPosition().x<-3) {
			s = (CCSprite*)b->GetUserData();
			if (s != NULL) {
				s->removeFromParent();
				CCLog("Remove");
			}
			world->DestroyBody(b);
		}
	}
}

/**
* 添加地板
*/
void HelloWorld::addGround()
{
	// 地板精灵
	B2Sprite *ground = B2Sprite::create("ground.png");
	// 得到地板内容的大小
	CCSize size = ground->getContentSize();

	// 用于初始化刚体在物理世界的一些属性,比如位置,类型
	b2BodyDef bDef;
	// 静态的刚体
	bDef.type = b2_staticBody;
	// 设置位置
	bDef.position = b2Vec2(size.width/2/RATIO, size.height/2/RATIO);
	// 创建刚体
	b2Body *groundBody = world->CreateBody(&bDef);

	// 形状
	b2PolygonShape groundShape;
	// 设置为矩形
	groundShape.SetAsBox(size.width/2/RATIO, size.height/2/RATIO);
	// 材料定制器
	b2FixtureDef groundFixtureDef;
	// 设置形状
	groundFixtureDef.shape = &groundShape;
	// 创建定制器
	groundBody->CreateFixture(&groundFixtureDef);
	// 为精灵设置刚体
	ground->setB2Body(groundBody);
	// 设置度量比例
	ground->setPTMRatio(RATIO);
	// 添加地板到层当中
	addChild(ground);

}

// 触摸事件开始
void HelloWorld::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent) {
	bird->getB2Body()->SetLinearVelocity(b2Vec2(0, 5));
}

// 添加运动的水管
void HelloWorld::addBar(float dt) {
	// 随机生成偏移量
	float offset = -rand() %5;

	// 创建向下水管的精灵
	B2Sprite *down_bar = B2Sprite::create("down_bar.png");
	// 得到水管的大小
	CCSize down_bar_size = down_bar->getContentSize();

	// 下水管
	b2BodyDef down_bar_body_def;
	// 运动学物体,但不受重力影响
	down_bar_body_def.type = b2_kinematicBody;
	// 设置下水管的位置
	down_bar_body_def.position = b2Vec2(screenSize.width/RATIO + 2, down_bar_size.height/RATIO/2 +offset);
	// 线性速度,从右往左移动
	down_bar_body_def.linearVelocity = b2Vec2(-5,0);
	// 创建刚体
	b2Body *down_bar_body = world->CreateBody(&down_bar_body_def);

	// 隐形形状
	b2PolygonShape down_bar_shape;
	// 设置为盒子,参数为内容的半宽半高
	down_bar_shape.SetAsBox(down_bar_size.width/2/RATIO, down_bar_size.height/2/RATIO);
	// 声明定制器
	b2FixtureDef down_bar_fixture_def;
	// 定制器形状
	down_bar_fixture_def.shape = &down_bar_shape;
	// 为刚体创建定制器
	down_bar_body->CreateFixture(&down_bar_fixture_def);

	// 设置精灵刚体
	down_bar->setB2Body(down_bar_body);
	// 设置度量
	down_bar->setPTMRatio(RATIO);

	// 上水管
	B2Sprite *up_bar = B2Sprite::create("up_bar.png");
	// 获得内容大小
	CCSize up_bar_size = up_bar->getContentSize();

	b2BodyDef up_bar_body_def;
	// 运动学物体,但不受重力影响
	up_bar_body_def.type = b2_kinematicBody;
	// 设置水管位置
	up_bar_body_def.position = b2Vec2(screenSize.width/RATIO+2, down_bar_size.height/RATIO+offset+2+up_bar_size.height/2/RATIO);
	up_bar_body_def.linearVelocity = b2Vec2(-5, 0);
	b2Body *up_bar_body = world->CreateBody(&up_bar_body_def);

	// 隐形形状
	b2PolygonShape up_bar_shape;
	// 设置为盒子形状,参数为半宽半高
	up_bar_shape.SetAsBox(up_bar_size.width/2/RATIO, up_bar_size.height/2/RATIO);
	b2FixtureDef up_bar_fixture_def;
	up_bar_fixture_def.shape = &up_bar_shape;
	up_bar_body->CreateFixture(&up_bar_fixture_def);
	up_bar->setB2Body(up_bar_body);
	up_bar->setPTMRatio(RATIO);

	barContainer->addChild(down_bar);
	barContainer->addChild(up_bar);

}

// 运动条的容器
void HelloWorld::addBarContainer()
{
	barContainer = CCSprite::create();

	addChild(barContainer);
}

// 开始游戏
void HelloWorld::startGame(float dt) {
	scheduleUpdate();
	schedule(schedule_selector(HelloWorld::addBar),1);
}

// 结束游戏
void HelloWorld::stopGame() {
	unscheduleUpdate();
	unschedule(schedule_selector(HelloWorld::addBar));

}

void HelloWorld::BeginContact(b2Contact *contact) {
	// 发生碰撞,则弹出对话框
	if (contact->GetFixtureA()->GetBody()->GetUserData() == bird ||
		contact->GetFixtureB()->GetBody()->GetUserData() == bird) {
			stopGame();
			CCMessageBox("游戏失败","游戏失败");
	}

}

void HelloWorld::menuCloseCallback(CCObject* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
	CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
#else
	CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
	exit(0);
#endif
#endif
}

Cocos2d-x 2.3.3版 FlappyBird

时间: 2024-08-18 14:00:18

Cocos2d-x 2.3.3版 FlappyBird的相关文章

c#版flappybird 未完全实现

这些天开始在深圳找工作,想着把从前有些淡忘的技术再温故下.看到尊敬的<传智播客>有一期公开课,讲的是用c#编写flappybird小游戏,也就自己搜了下游戏资源,也来试试看. 其实用到的技术就是传智播客讲的.只不过项目结构和一些逻辑稍微修改了下,更加符合原游戏的特点. --------再次声明:非本人独创方案------------ 导入资源 窗体背景设置为background图片382*681,然后在窗体上加个picturebox,放入road图片,大小拉伸. 而后加三个timer,依次设置

Cocos2d之Node类详解之ZOrder详解

一.声明 笔者以cocos2d框架的cocos2d-x-3.3rc0版本源码做分析.本文属于笔者原创,允许转载和分享,但请注明文章出处. 二.简介 ZOrder ZOrder顾名思义就是节点(Node对象)在Z轴上的排序,这样一来ZOrder越小就越优先显示.每个节点(Node对象)可以持有多个子节点,组成节点树(关于节点树的介绍查看<Cocos2d之Node类详解之节点树>一文).ZOder表示了节点树中每个子节点显示的优先级.值得注意的是,节点树中子节点的ZOder可能会一样,这种情况下父

游戏开发热门技术浅析

最近手游开发很热,今天我们来看看目前比较主流的手机游戏开发技术,以下仅仅是个人了解的皮毛,为想了解和步入游戏行业的朋友做一参考. cocos2d 我们先来看一幅图: 要看懂这幅图就先要了解一下cocos2d的生命历程,下面我来做一下简要的归纳和介绍吧. 2005年,Ricardo和朋友萌生了用Python语言 "一星期编写一个游戏"的想法.在2005-2007年间,他们设计了许多种这样的游戏.值得注意的是,每次在设计一个新的游戏时,其游戏引擎都是重新开发的. 2008年2月,他们在阿根

cocos2d横版游戏之摇杆控制

以上是一个控制摇杆,分为一个底座和摇杆小圈圈,我们的目的是通过算出摇杆小圈跟底座中心的偏移来控制任务的走向,我们计算出一个偏移量来,然后在场景update(foat dt)...每一帧的位置上加上这个偏移量,不停的播放行走动画(当然人物的朝向要对),就可以达到控制任务行走的效果了,这一点你可能一下子就会想到高中学过的向量的加减处理了......坐标象限....之类的. void DirectionControlButton::controlTargetMove(CCTouch *pTouch){

cocos2dx实例开发之flappybird(入门版)

cocos2dx社区里有个系列博客完整地复制原版flappybird的所有特性,不过那个代码写得比较复杂,新手学习起来有点捉摸不透,这里我写了个简单的版本.演示如下: 创建项目 VS2013+cocos2dx 3.2创建win32项目,由于只是学习,所以没有编译为安卓.ios或者WP平台的可执行文件. 最终的项目工程结构如下: 很简单,只有三个类,预加载类,游戏主场景类,应用代理类,新手刚入门喜欢将很多东西都写在尽量少的类里面. 游戏设计 游戏结构如下,游戏包含预加载场景和主场景,主场景中包含背

cocos2d-x笔记3 : 3.0正式版调用CocoStudio

cocos2d已经有一万个新建工程的方式和一万个API改动了,而且相互不兼容...触控科技的程序员真心不怕被打哦... 网上搜到的做法大多已经不行了,原因在上一段哦... 同样都是3.0,Alpha版.Bata版.Rc版.正式版,它们调用CocoStudio的方法都不一样哦...(求超越哦...) 记录一下3.0正式版使用CocoStudio的方法,是正式版,也就是最新版哦.(当然,只相对本周而言哦...) 一.添加库: 1.右击解决方案 -> 添加 -> 现有项目 2.进入项目目录的coco

cocos2d 播放GIF动画类

cocos2d 播放GIF动画类 以前项目中曾经用到过,后来因为GIF图像的质量较差,被弃用了,把公司名字去掉分享下,根据网上资料改编的cocos2d-iphone版的. // // CCSpriteGif.h // // Created by Yuming on 13-1-23. // Copyright 2013年 __MyCompanyName__. All rights reserved. // // 本类需要导入ImageIO.framework #import <Foundation

SDL版Flappy bird代码分享

用SDL编写的Flappy bird电脑版. 请大家尊重原创,转载或者用到其中的函数请注明出处,以及作者(五十风) main.cpp /*************************************************************** * 版权所有 (C)2014, 五十风 * * 文件名称:main.cpp * 内容摘要:FlappyBird主函数文件 * 其它说明:无 * 当前版本:v1.2 * 作 者:五十风 * 完成日期:2014.11.4 * 代替版本:v1

使用 Cocos2d 3.1.1 创建 Windows Phone 8 游戏开发环境

cocos2d-x 是目前流行的游戏游戏开发框架,目前最新的版本是 3.1.1, 网上有些教程已经比较老了,本文将会介绍如何使用最新的 3.1.1 创建 Windows Phone 8 开发环境. 本文假设你已经安装了 VS2012 或者 VS2013,并且已经安装了 Windows Phone8 的 SDK. 一.下载和安装 Cocos2d-x 官网地址:http://www.cocos2d-x.org/ 点击菜单栏中的 Download, 进入下载页面. 我们下载最新的 V3.1.1,新版功