当前位置: 首页 > news >正文

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
}


版权声明:本文博客原创文章,博客,未经同意,不得转载。

转载于:https://www.cnblogs.com/mengfanrong/p/4728244.html

相关文章:

  • LeetCode Implement Stack using Queues
  • Web前端学习-第六课HTML篇
  • C# 跨线程呼叫控制
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • Unity3d之流光效果
  • mysql 的 存储结构(储存引擎)
  • DP_ural_Metro
  • 手把手教你整合 SpringMvc+Spring+MyBatis+Maven
  • oracle根据pid查询出正在执行的执行语句
  • 国内最简单的短视频SDK
  • 【转】vxworks的default boot line说明
  • vector的reserve和resize(转)
  • 心跳多少寿命长
  • UI中的界面之间的值传递 一
  • [POJ3067]Japan
  • 【译】JS基础算法脚本:字符串结尾
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • Babel配置的不完全指南
  • exports和module.exports
  • extract-text-webpack-plugin用法
  • jQuery(一)
  • Linux各目录及每个目录的详细介绍
  • Mysql优化
  • Protobuf3语言指南
  • python docx文档转html页面
  • Redis 中的布隆过滤器
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • Vue全家桶实现一个Web App
  • 编写高质量JavaScript代码之并发
  • 当SetTimeout遇到了字符串
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 新版博客前端前瞻
  • 正则表达式小结
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • Hibernate主键生成策略及选择
  • 翻译 | The Principles of OOD 面向对象设计原则
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • 函数计算新功能-----支持C#函数
  • #1014 : Trie树
  • #Linux(make工具和makefile文件以及makefile语法)
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • (06)Hive——正则表达式
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (C语言)字符分类函数
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (ibm)Java 语言的 XPath API
  • (第二周)效能测试
  • (附源码)计算机毕业设计ssm电影分享网站
  • (三) diretfbrc详解
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • ***利用Ms05002溢出找“肉鸡
  • .java 9 找不到符号_java找不到符号