1. 程式人生 > >cocos2d-x中box2d的關節

cocos2d-x中box2d的關節

//
//  HelloWorldScene.cpp
//  Box2dDemo
//
//  Created by gaocong on 13-6-24.
//  Copyright __MyCompanyName__ 2013年. All rights reserved.
//
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
#include "GLES-Render.h"

using namespace cocos2d;
using namespace CocosDenshion;

#define PTM_RATIO 32

enum {
    kTagParentNode = 1,
};

PhysicsSprite::PhysicsSprite()
: m_pBody(NULL)
{
    
}

void PhysicsSprite::setPhysicsBody(b2Body * body)
{
    m_pBody = body;
}

// this method will only get called if the sprite is batched.
// return YES if the physics values (angles, position ) changed
// If you return NO, then nodeToParentTransform won't be called.
bool PhysicsSprite::isDirty(void)
{
    return true;
}

//returns the transform matrix according the Chipmunk Body values
//CCAffineTransform PhysicsSprite::nodeToParentTransform(void)
//{
//    b2Vec2 pos  = m_pBody->GetPosition();
//
//    float x = pos.x * PTM_RATIO;
//    float y = pos.y * PTM_RATIO;
//
//    if ( isIgnoreAnchorPointForPosition() ) {
//        x += m_tAnchorPointInPoints.x;
//        y += m_tAnchorPointInPoints.y;
//    }
//
//    // Make matrix
//    float radians = m_pBody->GetAngle();
//    float c = cosf(radians);
//    float s = sinf(radians);
//
//    if( ! CCPoint::CCPointEqualToPoint(m_tAnchorPointInPoints, CCPointZero) ){
//        x += c*-m_tAnchorPointInPoints.x + -s*-m_tAnchorPointInPoints.y;
//        y += s*-m_tAnchorPointInPoints.x + c*-m_tAnchorPointInPoints.y;
//    }
//
//    // Rot, Translate Matrix
//    m_tTransform = CCAffineTransformMake( c,  s,
//        -s,    c,
//        x,    y );
//
//    return m_tTransform;
//}

HelloWorld::HelloWorld()
{
    setTouchEnabled( true );
    setAccelerometerEnabled( true );
    
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    // init physics
    this->initPhysics();
    
    CCSpriteBatchNode *parent = CCSpriteBatchNode::create("blocks.png", 100);
    m_pSpriteTexture = parent->getTexture();
    
    addChild(parent, 0, kTagParentNode);
    
    
    // addDynamicBody(ccp(s.width/2, s.height/2));
//    addDistanceJoint(ccp(s.width/2, s.height/2));
//    addRevoluteJoint(ccp(s.width/2, s.height/2));
//    addPrismaticJoint(ccp(s.width/2, s.height/2));
//    addPulleyJoint(ccp(s.width/2, s.height/2));
    addGearJoint(ccp(s.width/2, s.height/2));
    
    CCLabelTTF *label = CCLabelTTF::create("Tap screen", "Marker Felt", 32);
    addChild(label, 0);
    label->setColor(ccc3(0,0,255));
    label->setPosition(ccp( s.width/2, s.height-50));
    
    scheduleUpdate();
}

HelloWorld::~HelloWorld()
{
    delete world;
    world = NULL;
    
    //delete m_debugDraw;
}

void HelloWorld::initPhysics()
{
    
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    
    b2Vec2 gravity;
    gravity.Set(0.0f, -10.0f);
    world = new b2World(gravity);
    
    // Do we want to let bodies sleep?
    world->SetAllowSleeping(true);
    
    world->SetContinuousPhysics(true);
    
    world->SetContactListener(this);
    
    GLESDebugDraw* m_debugDraw = new GLESDebugDraw( PTM_RATIO );
    world->SetDebugDraw(m_debugDraw);
    
    uint32 flags = 0;
    flags += b2Draw::e_shapeBit;
    flags += b2Draw::e_jointBit;
    flags += b2Draw::e_aabbBit;
    flags += b2Draw::e_pairBit;
    flags += b2Draw::e_centerOfMassBit;
    m_debugDraw->SetFlags(flags);
    
    
    // Define the ground body.
    b2BodyDef groundBodyDef;
    groundBodyDef.position.Set(0, 0); // bottom-left corner
    
    // Call the body factory which allocates memory for the ground body
    // from a pool and creates the ground box shape (also from a pool).
    // The body is also added to the world.
    groundBody = world->CreateBody(&groundBodyDef);
    
    // Define the ground box shape.
    b2EdgeShape groundBox;
    
    // bottom
    
    groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO,0));
    groundBody->CreateFixture(&groundBox,0);
    
    // top
    groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));
    groundBody->CreateFixture(&groundBox,0);
    
    // left
    groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(0,0));
    groundBody->CreateFixture(&groundBox,0);
    
    // right
    groundBox.Set(b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,0));
    groundBody->CreateFixture(&groundBox,0);
}

void HelloWorld::draw()
{
    //
    // IMPORTANT:
    // This is only for debug purposes
    // It is recommend to disable it
    //
    CCLayer::draw();
    
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
    
    kmGLPushMatrix();
    
    world->DrawDebugData();
    
    kmGLPopMatrix();
}


b2Body * HelloWorld::addNewSpriteAtPositionAndType(CCPoint p, b2BodyType type)
{
    
    b2BodyDef bodyDef;
    bodyDef.type = type;
    bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
    b2Body *body = world->CreateBody(&bodyDef);
    
    // Define another box shape for our dynamic body.
    b2PolygonShape dynamicBox;
    dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box
    
    // Define the dynamic body fixture.
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicBox;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.3f;
    body->CreateFixture(&fixtureDef);
    
    bodyAddSprite(body);
    return body;
}

//在body上新增精靈
void HelloWorld::bodyAddSprite(b2Body * body)
{
    CCNode* parent = getChildByTag(kTagParentNode);
    
    //We have a 64x64 sprite sheet with 4 different 32x32 images.  The following code is
    //just randomly picking one of the images
    int idx = (CCRANDOM_0_1() > .5 ? 0:1);
    int idy = (CCRANDOM_0_1() > .5 ? 0:1);
    PhysicsSprite *sprite = new PhysicsSprite();
    sprite->initWithTexture(m_pSpriteTexture, CCRectMake(PTM_RATIO * idx,PTM_RATIO * idy,PTM_RATIO,PTM_RATIO));
    sprite->autorelease();
    
    parent->addChild(sprite);
    
    sprite->setPosition( CCPointMake( body->GetPosition().x, body->GetPosition().y) );
    
    sprite->setPhysicsBody(body);
    body->SetUserData(sprite);
}

//距離關節
void HelloWorld::addDistanceJoint(CCPoint p)
{
    b2Body *body = addNewSpriteAtPositionAndType(p, b2_staticBody);
    
    b2Body *body2 = addNewSpriteAtPositionAndType(ccpAdd(p, ccp(PTM_RATIO, PTM_RATIO)), b2_dynamicBody);
    
    b2DistanceJointDef jointDef;
    //方法一
    jointDef.Initialize(body, body2, body->GetWorldCenter(), body2->GetWorldCenter());
    //方法二
//    jointDef.bodyA = body;
//    jointDef.bodyB = body2;
//    jointDef.length = 2;
    world->CreateJoint(&jointDef);
    
}

//旋轉關節
void HelloWorld::addRevoluteJoint(CCPoint p)
{
    b2Body *body = addNewSpriteAtPositionAndType(p, b2_staticBody);
    
    b2Body *body2 = addNewSpriteAtPositionAndType(ccpAdd(p, ccp(PTM_RATIO, PTM_RATIO)), b2_dynamicBody);
    
    
    b2RevoluteJointDef jointDef;
    jointDef.Initialize(body, body2,  body2->GetWorldCenter());
    jointDef.lowerAngle = -0.25f * b2_pi; // -45 degrees
    jointDef.upperAngle = 0.5f * b2_pi; // 90 degrees
    jointDef.enableLimit = true;
    jointDef.maxMotorTorque = 10.0f;
    jointDef.motorSpeed = 1.0f;
    jointDef.enableMotor = true;
    world->CreateJoint(&jointDef);
}

//移動關節
void HelloWorld::addPrismaticJoint(CCPoint p)
{
    b2Body *body = addNewSpriteAtPositionAndType(p, b2_staticBody);
    
    b2Body *body2 = addNewSpriteAtPositionAndType(ccpAdd(p, ccp(PTM_RATIO, -PTM_RATIO)), b2_dynamicBody);
    
    
    b2PrismaticJointDef jointDef;
    b2Vec2 worldAxis(1.0f, -1.0f);//可以移動的方向
    jointDef.Initialize(body, body2,  body2->GetWorldCenter(), worldAxis);
    jointDef.lowerTranslation = -2.0f;
    jointDef.upperTranslation = 4.0f;
    jointDef.enableLimit = true;
    jointDef.motorSpeed = 0.0f;
    jointDef.enableMotor = true;
    world->CreateJoint(&jointDef);
}

//滑輪關節
void HelloWorld::addPulleyJoint(CCPoint p)
{
    b2Body *body = addNewSpriteAtPositionAndType(p, b2_dynamicBody);
    
    b2Body *body2 = addNewSpriteAtPositionAndType(ccpAdd(p, ccp(PTM_RATIO, -PTM_RATIO)), b2_dynamicBody);
    
    b2Vec2 anchor1 = body->GetWorldCenter();
    b2Vec2 anchor2 = body2->GetWorldCenter();    
    
    b2Vec2 groundAnchor1(anchor1.x, anchor1.y + 2.0f);//滑輪的位置
    b2Vec2 groundAnchor2(anchor2.x, anchor2.y + 4.0f);
    
    float32 ratio = 0.5f;//比率
    b2PulleyJointDef jointDef;
    
    jointDef.Initialize(body, body2, groundAnchor1, groundAnchor2, anchor1, anchor2, ratio);

    world->CreateJoint(&jointDef);
}

//齒輪關節
void HelloWorld::addGearJoint(CCPoint p)
{
    b2Body *body = addNewSpriteAtPositionAndType(p, b2_dynamicBody);

    b2Body *body2 = addNewSpriteAtPositionAndType(ccpAdd(p, ccp(PTM_RATIO, 0)), b2_dynamicBody);
    
    //通過地面生成一個旋轉關節
    b2RevoluteJointDef jd1;
    jd1.bodyA = groundBody;
    jd1.bodyB = body;
    jd1.localAnchorA = groundBody->GetLocalPoint(body->GetPosition());
    jd1.localAnchorB = body->GetLocalPoint(body->GetPosition());
    jd1.referenceAngle = body->GetAngle() - groundBody->GetAngle();
    b2RevoluteJoint* joint1 = (b2RevoluteJoint*)world->CreateJoint(&jd1);
    
    //通過地面生成一個移動關節
    b2PrismaticJointDef jd3;
    jd3.Initialize(groundBody, body2, body2->GetPosition(), b2Vec2(0.0f, 1.0f));
    jd3.lowerTranslation = -5.0f;
    jd3.upperTranslation = 5.0f;
    jd3.enableLimit = true;
    b2PrismaticJoint *joint2 = (b2PrismaticJoint*)world->CreateJoint(&jd3);
    
    //通過旋轉關節和移動關節生成一個齒輪關節
    b2GearJointDef jointDef3;
    jointDef3.bodyA = body;
    jointDef3.bodyB = body2;
    jointDef3.joint1 = joint1;
    jointDef3.joint2 = joint2;
    jointDef3.ratio = 4.0f;//比率
    world->CreateJoint(&jointDef3);    
}




void HelloWorld::BeginContact(b2Contact* contact)
{
    CCSprite * sp1 = (CCSprite *)contact->GetFixtureA()->GetBody()->GetUserData();
    CCSprite * sp2 = (CCSprite *)contact->GetFixtureB()->GetBody()->GetUserData();
    if (sp1 != NULL && sp2 != NULL) {
        sp1->setColor(ccRED);
        sp2->setColor(ccRED);
    }
}

void HelloWorld::update(float dt)
{
    //It is recommended that a fixed time step is used with Box2D for stability
    //of the simulation, however, we are using a variable time step here.
    //You need to make an informed choice, the following URL is useful
    //http://gafferongames.com/game-physics/fix-your-timestep/
    
    int velocityIterations = 8;
    int positionIterations = 1;
    
    // Instruct the world to perform a single step of simulation. It is
    // generally best to keep the time step and iterations fixed.
    world->Step(dt, velocityIterations, positionIterations);
    
    //Iterate over the bodies in the physics world
    for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
    {
        if (b->GetUserData() != NULL) {
            //Synchronize the AtlasSprites position and rotation with the corresponding body
            CCSprite* myActor = (CCSprite*)b->GetUserData();
            myActor->setPosition( CCPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO) );
            myActor->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
        }
    }
}

//滑鼠關節
void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
    CCTouch * touch = (CCTouch*)pTouches->anyObject();
    //判斷滑鼠是否點在了剛體上。
    CCPoint mousePt = touch->getLocation();
    b2Body *pBody = world->GetBodyList();//獲得所有剛體
    for(; pBody != NULL; pBody = pBody->GetNext())
    {
        b2Fixture *pFixture = pBody->GetFixtureList();//獲的每個剛體的所有Fixture,因為類似於ground就有好幾個Fixture
        for(;pFixture != NULL;pFixture = pFixture->GetNext())
        {
            b2Vec2 mouseVec;
            mouseVec.Set(mousePt.x/PTM_RATIO, mousePt.y/PTM_RATIO);
            if(pFixture->TestPoint(mouseVec))//判斷滑鼠點是否在這個剛體上
            {
                //建立滑鼠關節.
                b2MouseJointDef md;
                md.bodyA=groundBody;//一般為世界邊界
                md.bodyB=pBody;//需要拖動的物體
                md.target=mouseVec;//指定拖動的座標
                md.collideConnected=true; //是否進行碰撞檢測
                md.maxForce=1000.0f*pBody->GetMass(); //給一個拖動的力
                mouseJoint=(b2MouseJoint*)world->CreateJoint(&md);//建立
                pBody->SetAwake(true);//將剛體喚醒,原來可能睡眠了,會少一幀
                return ;
            }  
        }  
    }
}
void HelloWorld::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)
{
    if(mouseJoint == NULL )
        return;
    
    CCTouch * touch = (CCTouch*)pTouches->anyObject();
    b2Vec2 vecMouse;
    vecMouse.Set((touch->getLocation().x)/PTM_RATIO, (touch->getLocation().y)/PTM_RATIO);
    //控制滑鼠關節,改變關節位置.
    mouseJoint->SetTarget(vecMouse);
}


void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
    //銷燬關節.
    if(mouseJoint != NULL)
    {
        world->DestroyJoint(mouseJoint);
        mouseJoint = NULL;
    }
    
    //    //Add a new body/atlas sprite at the touched location
    //    CCSetIterator it;
    //    CCTouch* touch;
    //
    //    for( it = touches->begin(); it != touches->end(); it++)
    //    {
    //        touch = (CCTouch*)(*it);
    //
    //        if(!touch)
    //            break;
    //
    //        CCPoint location = touch->getLocationInView();
    //
    //        location = CCDirector::sharedDirector()->convertToGL(location);
    //
    //        addNewSpriteAtPositionAndType( location, b2_dynamicBody );
    //    }
}




CCScene* HelloWorld::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();
    
    // add layer as a child to scene
    CCLayer* layer = new HelloWorld();
    scene->addChild(layer);
    layer->release();
    
    return scene;
}

相關推薦

cocos2d-xbox2d關節

// // HelloWorldScene.cpp // Box2dDemo // // Created by gaocong on 13-6-24. // Copyright __MyCompanyName__ 2013年. All rights reserved

實例介紹Cocos2d-xBox2D物理引擎:碰撞檢測

函數實現 pda creates pty blank oid rtu and 重構 在Box2D中碰撞事件通過實現b2ContactListener類函數實現,b2ContactListener是Box2D提供的抽象類,它的抽象函數:virtual void BeginC

實例介紹Cocos2d-xBox2D物理引擎:HelloBox2D

pre all align 討論 響應 算法 站點 virtual origin 我們通過一個實例介紹一下。在Cocos2d-x 3.x中使用Box2D物理引擎的開發過程,熟悉這些API的使用。這個實例執行後的場景如圖所看到的,當場景啟動後,玩家能夠觸摸點擊屏幕,每次觸

例項介紹Cocos2d-xBox2D物理引擎:碰撞檢測

在Box2D中碰撞事件通過實現b2ContactListener類函式實現,b2ContactListener是Box2D提供的抽象類,它的抽象函式:virtual void BeginContact(b2Contact* contact)。兩個物體開始接觸時會響應,但只調用

Cocos2d-xVector<T>容器以及實例介紹

top 宋體 hello 操作符 模板類 log ins bsp main Vector<T> 是Cocos2d-x 3.x推出的列表容器,因此它所能容納的是Ref及子類所創建的對象指針,其中的T是模板,表示能夠放入到容器中的類型,在Cocos2d-x 3.x

cocos2d-x XML解析與數據存儲

lba false 網上 unsigned failed popu new ccm cfile 一不小心就玩了一周的遊戲了。哎。玩的時候時間過得總是這麽快。。。 於是今天決定看一下之前不怎麽非常熟悉的XML;(之前做遊戲時數據的儲存用到過XML,但這塊是還有一個同事在做

linux下開發,解決cocos2d-x編譯出現的一個小問題, undefined reference to symbol &#39;pthread_create@@GLIBC_2.2.5&#39;

water span x86 code bject data- ace 技術分享 inux 解決cocos2d-x中編譯出現的一個小問題 對於cocos2d-x 2.×中編譯中,若頭文件裏引入了#include "cocos-ext.h",在進行C++編譯的時候會遇到例

Cocos2d-XMenu的綜合運用

cond edi ros log 程序 cal coo 項目 綜合 今天將曾經寫的代碼和項目集成到了一個菜單中,能夠通過菜單切換到曾經做的項目 程序的project文件夾 主要代碼分析: LessonMenu.h中實現創建菜單,遍歷菜單通過菜單切換

Cocos2d-X的聲音和音效

循環 volume tid ng- cocos2d pop sin 返回值 source 在玩遊戲時都會有各種遊戲音,如啟動遊戲時會有背景音,勝利或者失敗會有一些音效。在Cocos2d-X中能夠使用CocosDenshion實現各種聲音 在使用CocosDensh

cocos2d-x 選單類

選單相關類包含:選單類和選單項類,選單類圖,從類圖可見Menu類繼承於Layer。   選單項類圖,從圖中可見所有的選單項都是從BaseMenuItem繼承而來的,BaseMenuItem是抽象類,具體使用時是使用它的6個子類。 說明如下:   MenuItem       最基本的選單

Cocos2d-x的4種佈局

Cocos2d-x中一共有4種佈局:ABSOLUTE(絕對佈局)、HORIZONTAL(水平佈局)、VERTICAL(垂直佈局)和RELATIVE(相對佈局)。 注意,只有在絕對佈局內部,元件使用setPosition()方法來指定其位置。另外三種佈局中的元件,setP

卡通渲染Cocos2d-x的實現(描邊與對物體表面顏色的色階化)

卡通渲染Cocos2d-x中的實現 在一些型別的遊戲中,使用卡通渲染能夠將原有模型的一些細節剝離,使原本比較寫實的模型變得卡通化。在這裡,我向大家介紹簡單介紹一下如何在Cocos2d-x中實現卡通渲染。 事實上,卡通渲染具體來說,可以分為兩個部分:描邊與對物體表面顏色的

cocos2d-x解決點選事件上層響應,下層不響應

解決方案是重寫一個Layer,加在上下層中間,即可只響應上層事件,阻斷了下層的事件,設定優先順序,程式碼如下 #ifndef _TouchBlockLayer_H_ #define _TouchBlockLayer_H_ class TouchBlockLayer:

Cocos2d-x 的Sleep 和USleep

                Cocos2d-x跨平臺,但是這個Sleep延時需要區分平臺 (不知道是不是我自己沒有找到),還是

Cocos2d-xVector容器以及例項介紹

Vector<T> 是Cocos2d-x 3.x推出的列表容器,因此它所能容納的是Ref及子類所建立的物件指標,其中的T是模板,表示能夠放入到容器中的型別,在Cocos2d-x 3.x中T表

Cocos2d-x替換動畫(Armature)的節點與粒子

     Cocos2d-x遊戲開發中常用到骨骼動畫Armature,Armature不僅佔用資源不大(相對於幀動畫來說),而且還能新增幀事件,它還自帶有動畫的播放、停止、迴圈事件等。      廢話少說,直入主題。拿到一個骨骼動畫的時候,我們往往會有這樣的需求:在情況A

Cocos2d-x 載入骨骼動畫資源

Cocos Studio是一套基於Cocos2d-x的免費遊戲開發工具集,它能幫助開發者快速建立遊戲資源,將大部分繁瑣的遊戲開發工作使用編輯器來快速製作,進一步幫助遊戲開發者減短開發週期、提高開發效率。 Cocos Studio本身不光只是針對骨骼動畫的編輯而設計的,它還提供了UI、場景和資料等資訊的編

cocos2d-x的動作分析

在cocos2d-x中動作的執行排程是受cocos2d-x的全域性定時器控制的,當初始完導演後便已經啟動用於管理動作的update定時器。 bool CCDirector::init(void) { ... m_pActionManager = new CCAct

談一談Cocos2d-x的某些“大小”

這裡說的“大小”,包括了以下一些內容: (1).視窗的大小 (2).解析度的大小 (3).影幕的大小 (4).視口的大小 (5).裁剪區域的大小 我們先來看(1),視窗的大小 視窗的大小,即是Windows窗體大小。我們以HelloCpp為例,開啟main.cpp,。找到

cocos2d-x場景間的引數保持和傳遞(方法整理)

有時為了在場景間傳遞引數,象一些狀態資訊比如音樂的AudioID等,整理一下場景間引數傳遞的方式 方式一、使用全域性變數 利用全域性變數的方式對變數進行場景間的傳遞,簡單且粗暴。可以定義一個類專門來存放需要傳遞的引數,在各場景類中只需要include一下就可以直接對全域性變