您的位置:首页 > 其它

物理引擎Box2D 入门

2014-08-11 18:46 330 查看
原理:创建精灵,图片为ball.png球,创建刚体用框架与精灵连接,通过触摸设置精灵的坐标update会实时更新坐标 

HelloWorld.h 头文件


#ifndef __HELLOWORLD_SCENE_H__

#define __HELLOWORLD_SCENE_H__

#include "tinyxml2\tinyxml2.h"  

#include "cocos2d.h"

#include "Box2D\Box2D.h"

USING_NS_CC;

using namespace tinyxml2;

class HelloWorld : public cocos2d::Layer, public b2ContactListener

{

public:

b2World *world;

float deltaTime;        

Sprite *ball;

float ballX;                   //精灵X坐标

float ballY;
//精灵Y坐标

int dragOffsetStartX;   //拖动开始X坐标

int dragOffsetEndX;     //拖动结束X坐标

int dragOffsetStartY;   //拖动开始Y

int dragOffsetEndY;     //拖动结束Y

b2Body *ballBody;

b2Body *ballBody2;

b2CircleShape ballShape;

b2BodyDef ballBodyDef;

void update(float dt);

b2Body *floorBody;
//墙体

void createBall();      //创建球

void defineBall();      //创建物理球体 方法

void connectJoint();
//关节连接

void addWall(float w, float h, float px, float py); //墙体

b2MouseJoint *m_mouseJoint;

    // there's no 'id' in cpp, so we recommend returning the class instance pointer

    static cocos2d::Scene* createScene();

    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone

    virtual bool init();  

    

    // a selector callback

    void menuCloseCallback(cocos2d::Ref* pSender);

    

    // implement the "static create()" method manually

    CREATE_FUNC(HelloWorld);

void makeXML(const char *fileName);

void parseXML(const char *fileName);

bool onTouchBegan(Touch* touch, Event* event);

void onTouchMoved(Touch* touch, Event* event);

void onTouchEnded(Touch* touch, Event* event);

};

#endif // __HELLOWORLD_SCENE_H__
 
 HelloWorld.cpp 文件

#include "HelloWorldScene.h"

#define SCALE_RATIO 32

USING_NS_CC;

Scene* HelloWorld::createScene()

{

    // 'scene' is an autorelease object

    auto scene = Scene::create();

    

    // 'layer' is an autorelease object

    auto 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 ( !Layer::init() )

    {

        return false;
    }

b2Vec2 gravity = b2Vec2(0.0f, -10.0f);

world = new b2World(gravity);

CCSize visibleSize = CCDirector::getInstance()->getVisibleSize();

// 1 单点触摸事件监听器

EventListenerTouchOneByOne *eventTouch = EventListenerTouchOneByOne::create();

eventTouch->setSwallowTouches(true);
//设置是否想下传递触摸   

// 2 绑定触摸事件 

eventTouch->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this); // 触摸开始时触发 

eventTouch->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this); // 触摸移动时触发 

eventTouch->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this); // 触摸结束时触发 

// 3 添加监听器 

_eventDispatcher->addEventListenerWithSceneGraphPriority(eventTouch, this);

createBall();

//createBall(ballBody2);

//创建墙体(宽,高,X,Y)

addWall(visibleSize.width, 10, (visibleSize.width/2), visibleSize.height);
 //CEILING 

addWall(visibleSize.width, 10, (visibleSize.width / 2), 0);
 //FLOOR 

addWall(10, visibleSize.height, 0, (visibleSize.height / 2));
 //LEFT

addWall(10, visibleSize.height, visibleSize.width, (visibleSize.height / 2));
 //RIGHT

scheduleUpdate();

return true;



//创建球

void HelloWorld::createBall(){

//创建球

dragOffsetStartX = 0;

dragOffsetEndX = 0;

dragOffsetStartY = 0;

dragOffsetEndY = 0;

ballX = 500;

ballY = 200;

ball = Sprite::create("ball.png");

ball->setPosition(CCPoint(ballX, ballY));

this->addChild(ball);

//定义形状

ballShape.m_radius = 45 / SCALE_RATIO;
 //定义球形形状 半径

//定义框架

b2FixtureDef ballFixture;
 //球框架

ballFixture.density = 10;
 //框架密度

ballFixture.friction = 1.0f;
 //摩擦系数

ballFixture.restitution = 0.6f;
 //恢复 回弹

ballFixture.shape = &ballShape;
 //给框架定义形状

//定义刚体

ballBodyDef.type = b2_dynamicBody;
 //设置为动态刚体

ballBodyDef.userData = ball;
 //用户数据,ball为Sprite精灵

ballBodyDef.position.Set(ball->getPositionX() / SCALE_RATIO, ball->getPositionY() / SCALE_RATIO); //定义刚体的位置 (和精灵ball的位置相同)

//创建刚体

ballBody = world->CreateBody(&ballBodyDef);  //用世界对象来创建一个物体.

ballBody->CreateFixture(&ballFixture);       //为刚体设置框架 可以为刚体添加多个框架,但每一个都会导致总重量的增加

ballBody->SetGravityScale(10);               //对象对环境重力的作用比例
}

//模拟物理 这里实时更新了 球体精灵触摸后的新的坐标,设置精灵的坐标后,刚体会获取精灵的坐标

void HelloWorld::update(float dt){

//这两个值通常建议设置为10,更低的迭代值会让你牺牲一些准确性,相反的为你的程序提升一部分性能。

int positionIterations = 10;
//位置迭代

int velocityIterations = 10;
//速度迭代

world->Step(dt, velocityIterations, positionIterations) ;//box2d是用step来实现动画的

//遍历世界中的物体

for (b2Body *body = world->GetBodyList(); body !=NULL; body=body->GetNext()){

if (body->GetUserData())  //获取用户数据指针,体内提供了定义。

{

CCSprite *sprite = (CCSprite *)body->GetUserData();

sprite->setPosition(ccp(body->GetPosition().x * SCALE_RATIO, body->GetPosition().y * SCALE_RATIO)); //设置精灵的位置并转换单位

sprite->setRotation(-1 * CC_RADIANS_TO_DEGREES(body->GetAngle()));
//设置节点的旋转(angle)角度 宏定义:将弧度转换成度

}

world->ClearForces();

world->DrawDebugData();

}


//定义墙体

void HelloWorld::addWall(float w, float h, float px, float py){

//定义形状

b2PolygonShape floorShape;
//地面多边形定义

floorShape.SetAsBox(w / SCALE_RATIO, h / SCALE_RATIO);
//长和宽为1.0f 的一半 实际要乘以2

//定义框架

b2FixtureDef floorFixture;

floorFixture.density = 10;
//密度

floorFixture.friction = 0.8f;
//摩擦系数

floorFixture.restitution = 0.3f;
//回弹

floorFixture.shape = &floorShape;
    //给框架定义形状

//定义刚体

b2BodyDef floorBodyDef;

floorBodyDef.position.Set(px / SCALE_RATIO, py / SCALE_RATIO);  //给刚体设置位置

//创建刚体

b2Body *floorBody = world->CreateBody(&floorBodyDef);

floorBody->CreateFixture(&floorFixture);

}

bool HelloWorld::onTouchBegan(Touch* touch, Event* event)

{

dragOffsetStartX = touch->getLocation().x;

dragOffsetStartY = touch->getLocation().y;

ballX = touch->getLocation().x;

ballY = touch->getLocation().y;

return true;

}

void HelloWorld::onTouchMoved(Touch* touch, Event* event)

{

}

void HelloWorld::onTouchEnded(Touch* touch, Event* event)

{

dragOffsetEndX = touch->getLocation().x;

dragOffsetEndY = touch->getLocation().y;

float dragDistanceX = dragOffsetStartX - dragOffsetEndX;

float dragDistanceY = dragOffsetStartY - dragOffsetEndY;

ballBody->SetLinearVelocity(b2Vec2((dragDistanceX*10) / SCALE_RATIO, (dragDistanceY*10) / SCALE_RATIO));

ball->setPosition(CCPoint(ballX, ballY));

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: