让子弹飞是我非常喜欢的一款游戏。今天的目标就是利用cocos2dx 3.0 和box2d 打造一款这样的类型游戏的Demo版。本来cocos2dx 3.0 已经封装了physicals模块,可是我在使用的过程中遇到了一些问题,比方子弹速度过快时候会出屏等,所以就认为还是直接封装box2d API来完毕这款Demo。


我主要封装了两个类,一个叫Box2dHandler, 这个类继承自Node和b2ContactListener, 是用来和box2d打交道的。能够用来创建方形,圆形的静态或者动态刚体。创建物理世界,以及处理碰撞的检測重任都交给这个类了。另外一个类叫B2Sprite, 也继承自Node,本来是想继承自Sprite的,可是在实现过程中发现有问题。就改成继承自Node。它的功能是用来粘合cocos2dx和Box2D, 起到一个中间的桥梁作用。这里要感谢一下<<cocos2d-x高级开发教程>>一书,这两个类基本从它移植而来,可是原书使用的是2.0版本号。所以还是要做一些改动。


好了,闲话到此为止。上代码。

首先是Box2dHandler。

#ifndef __BOX2DHANDLER_H__
#define __BOX2DHANDLER_H__

#include "cocos2d.h"
#include "Box2D.h"
#include "Box2dHandlerDelegate.h"
#include "B2Sprite.h"

USING_NS_CC;

enum shape
{
	box=1,
	circle=2,
};

class Box2dHandler : public cocos2d::Node, public b2ContactListener
{

private:
	b2World *m_world;
	typedef std::pair<b2Fixture*, b2Fixture*> MyContact;
	std::set<MyContact> m_contacts;
public:
	bool init();
	bool initBox2D();
	void addBodyForSprite(B2Sprite* sprite, double density = 1.0, double friction = 0.9, double restituion = 0.1, shape type=box);
	void addFixtureForSprite(B2Sprite* sprite, double density = 1.0, double friction = 0.9, double restituion = 0.1, shape type=box);
	void addStaticBodyForSprite(B2Sprite* sprite, double density = 0.0);
	void dealCollision();

public:
	virtual void BeginContact(b2Contact * contact);
	virtual void EndContact(b2Contact * contact);

	static Box2dHandler * handler();
	//void draw();
	void update(float dt);
	CC_SYNTHESIZE(Box2dHandlerDelegate*, m_delegate,  Delegate);
	
};

#endif // __BOX2DHANDLER_H__

熟悉box2d的话,非常easy看清楚这个类就是封装了主要的Box2D操作。包含创建刚体,以及监听碰撞。


接下来是实现代码。


简单解释下:

Box2dHandler * Box2dHandler::handler() 
构造函数,内存管理交给cocos2dx

bool Box2dHandler::initBox2D()
设置好重力场,创建物理世界m_world, 以及定义好屏幕边界为可碰撞的静态刚体。

void Box2dHandler::addBodyForSprite(B2Sprite* sprite, double density, double friction, double restitution, shape type)

创建动态刚体,有方形和圆形两种选择。

void Box2dHandler::addFixtureForSprite(B2Sprite* sprite, double density, double friction, double restitution, shape type)

为刚体创建外观并设置刚体属性。

void Box2dHandler::update(float dt)
更新物理世界,并同步刚体位置到cocos2dx中精灵,当中的桥梁就是B2Sprite。

void Box2dHandler::BeginContact(b2Contact * contact)
void Box2dHandler::EndContact(b2Contact* contact)
物理碰撞检測的回调方法。

void Box2dHandler::dealCollision()
自己定义的碰撞处理方法。


就这么多。非常easy明了。接下来看看B2Sprite的代码


主要内容在这里

CC_SYNTHESIZE_READONLY(Sprite*, m_sprite, B2Sprite);
CC_SYNTHESIZE(b2Body*, m_b2Body, B2Body); // 物理实际的“物体”
我们能够看到B2Sprite一方面挂接了一个Sprite用于显示刚体,另外一方面有挂接了一个刚体对象m_b2Body, 所以它就起着一个桥梁的作用。


实现代码就不给出了。由于都是些细节性的方法,是用来写这个Demo的。大家全然能够依据自己须要来封装自己的B2Sprite版本号。


好了完毕了这两个类的封装。接下来就是完毕我们的Demo了。


我建立一个叫HelloWorldScene的Layer来承载这个游戏Demo。

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "Box2D.h"
#include "VisibleRect.h"
#include "cocos-ext.h"
#include "Box2dHandler.h"
using namespace cocos2d;

enum {
    kTagParentNode = 1,
	kTagBulletParentNode=2,
	kTagHandler = 3,
	kTagFloor = 100,
	kTagFloor2 = 101,
	kTagRedEnemy = 102,
	kTagBlueEnemy = 103,
	kTagYellowEnemy = 104,
	kTagBulletBase = 500,
};


class HelloWorld : public cocos2d::Layer, public Box2dHandlerDelegate
{
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
       static cocos2d::Scene* createScene();
        HelloWorld();
	~HelloWorld();

	// Touch process
	 bool onTouchBegan(Touch* touch, Event* pEvent);
	 void onTouchEnded(Touch* touch, Event* pEvent);

	 virtual void CollisionEvent(B2Sprite*, B2Sprite*);
	 void HelloWorld::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity);

};

#endif // __HELLOWORLD_SCENE_H__

我将创建刚体的任务都放在构造函数中,CollisionEvent是处理碰撞的回调方法。LauchBomb是发射子弹的方法。

接下来看实现。



HelloWorld::HelloWorld() 
中我放置了两个镜头刚体作为floor, 然后在上面放了几个敌人。当然,假设要做一个正式的游戏,关卡数据要在外面编辑好,然后读取进来。这里只写个Demo,就没有编辑关卡了。

void HelloWorld::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity)
创建了一个子弹刚体。这种方法在每次触摸屏幕都会触发。

  void HelloWorld::CollisionEvent(B2Sprite*a, B2Sprite*b)
碰撞检測回调方法,这里做的处理是: 假设子弹和敌人产生碰撞,假设敌人在子弹坐标,就给它一个水平向左的冲量,反之给它一个向右的冲量,让它掉下平台。


能够看到,真正的Demo代码是很少的。


接下来上图。

让子弹飞Demo版


设计一颗子弹

让子弹飞Demo版



让子弹飞Demo版


好了,这就是本章的所有内容。源代码已经上传到群 216208142 空间,有须要的读者能够加群来获取。



相关文章:

  • 2021-04-23
  • 2021-06-28
  • 2021-09-26
  • 2022-01-14
  • 2022-12-23
  • 2021-04-06
  • 2021-07-14
猜你喜欢
  • 2021-09-04
  • 2021-06-15
  • 2022-12-23
  • 2022-01-15
  • 2021-04-04
  • 2022-12-23
  • 2022-01-03
相关资源
相似解决方案