[cocos2d-x]box2d的简单应用

box2d创建简单的入门示例:

实现功能:

1.实现刚体的创建

2.能够创建自定义的精灵刚体

3.精灵之间的相互碰撞

工具的使用:

要创建一个 自定义的刚体精灵(不规则形状),就要用到一个工具PhysicalEditor,下载地址:http://yun.baidu.com/share/link?shareid=1782518146&uk=1209145999&third=0

我们将图片添加到工程中,但要确保图片精灵周围是透明的才行,然后选择Exporter->Box2D generic(PLIST),最后直接publish就可以了,然后将plist文件和原图片资源一起导入到工程的Resource下。

操作步骤:

1.导入外部的GLES-Render类

2.主场景类:

class QueryCallback : public b2QueryCallback
{
public:
    b2Vec2 m_point;
    b2Fixture * m_fixture;

    QueryCallback(const b2Vec2 & point)
    {
        m_point = point;
        m_fixture = NULL;
    }
    bool ReportFixture(b2Fixture * fixture)
    {
        b2Body * body = fixture->GetBody();
        if (body->GetType() == b2_dynamicBody)
        {
            bool inside = fixture->TestPoint(m_point);
            if(inside)
            {
                m_fixture = fixture;
                return false;
            }
        }
        return true;
    }

};

class SecondScene : public CCLayer
{
public:
    ~SecondScene();
    SecondScene();

    static CCScene* scene();

    void initPhysics();
    void addNewSpriteAtPosition(CCPoint p);

    virtual void draw();
    void update(float dt);

    void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
    void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);
    void ccTouchesEnded(CCSet* touches, CCEvent* event);

    bool MouseDown(const b2Vec2 & p);
    void MouseMove(const b2Vec2 & p);
    void MouseUp();

private:
    GLESDebugDraw * m_debugDraw;
    b2World * world;
    CCTexture2D * m_pSpriteTexture;
    b2MouseJoint * m_mouseJoint;  //鼠标关节节点
    b2Body * m_groundBody;
};
#endif /* defined(__box2dDemo__SecondHelloScene__) */

cpp

#include "SecondHelloScene.h"
#include "SimpleAudioEngine.h"
#include "GLES-Render.h"
#include "GB2ShapeCache-x.h"
#include "ContactListener.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;
//}
//
//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_obAnchorPointInPoints.x;
//        y += m_obAnchorPointInPoints.y;
//    }
//
//    // Make matrix
//    float radians = m_pBody->GetAngle();
//    float c = cosf(radians);
//    float s = sinf(radians);
//
//    if( ! m_obAnchorPointInPoints.equals(CCPointZero) ){
//        x += c*-m_obAnchorPointInPoints.x + -s*-m_obAnchorPointInPoints.y;
//        y += s*-m_obAnchorPointInPoints.x + c*-m_obAnchorPointInPoints.y;
//    }
//
//    // Rot, Translate Matrix
//    m_sTransform = CCAffineTransformMake( c,  s,
//                                         -s,    c,
//                                         x,    y );
//
//    return m_sTransform;
//}

SecondScene::SecondScene()
{
    setTouchEnabled( true );
    setAccelerometerEnabled( true );

    CCSize s = CCDirector::sharedDirector()->getWinSize();
    this->initPhysics();

    addNewSpriteAtPosition(ccp(s.width / 2, s.height / 2));

//    CCSpriteBatchNode *parent = CCSpriteBatchNode::create("blocks.png", 100);
//    m_pSpriteTexture = parent->getTexture();
//
//    addChild(parent, 0, kTagParentNode);
//
//
//    addNewSpriteAtPosition(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();
}

SecondScene::~SecondScene()
{
    delete world;
    world = NULL;

    //delete m_debugDraw;
}

void SecondScene::initPhysics()
{
    //添加自定义的精灵
    GB2ShapeCache::sharedGB2ShapeCache()->addShapesWithFile("zhizhu.plist");

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    b2Vec2 gravity;
    gravity.Set(0.0f, -10.0f);
    world = new b2World(gravity);

    b2BodyDef bodydef;
    m_groundBody = world->CreateBody(&bodydef);

    world->SetAllowSleeping(true);

    world->SetContinuousPhysics(false);//隧道效应,穿透,true表示不能穿透

    //接触监听,碰撞检测
    b2ContactListener *contactListener = new ContactListener();
    world->SetContactListener(contactListener);

    //静态刚体
    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(5, 1);

    b2Body* 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 SecondScene::draw()
{
    CCLayer::draw();

    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );

    kmGLPushMatrix();

    world->DrawDebugData();

    kmGLPopMatrix();
}

void SecondScene::addNewSpriteAtPosition(CCPoint p)
{

    string name = "alien";
    CCSprite * sprite = CCSprite::create((name + ".png").c_str());
    sprite->setPosition(p);
    this->addChild(sprite);

//    CCSprite * sp = CCSprite::create("Icon.png");
//    sp->setPosition(CCPointMake(100, 100));
//    this->addChild(sp);

    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
    bodyDef.userData = sprite;

    b2Body *body = world->CreateBody(&bodyDef);

    // Define another box shape for our dynamic body.
    //通过vertexHelper工具生成多边形
    b2PolygonShape dynamicBox;
//    b2Vec2 verts[] = {
//        b2Vec2(-12.8f / PTM_RATIO, 50.9f / PTM_RATIO),
//        b2Vec2(-48.8f / PTM_RATIO, 2.3f / PTM_RATIO),
//        b2Vec2(-30.7f / PTM_RATIO, -37.9f / PTM_RATIO),
//        b2Vec2(28.8f / PTM_RATIO, -18.9f / PTM_RATIO),
//        b2Vec2(30.8f / PTM_RATIO, 16.9f / PTM_RATIO),
//        b2Vec2(20.8f / PTM_RATIO, 44.9f / PTM_RATIO)
//    };
//    dynamicBox.Set(verts, 6);
    //dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box

//    b2FixtureDef fixtureDef;
//    fixtureDef.shape = &dynamicBox;
//    fixtureDef.density = 1.0f;//密度
//    fixtureDef.friction = 0.3f;//摩擦
//    fixtureDef.restitution = 0.5f;//恢复,也可看成弹性系数
//
//
//    body->CreateFixture(&fixtureDef);

    GB2ShapeCache * sc = GB2ShapeCache::sharedGB2ShapeCache();
    sc->addFixturesToBody(body, name);
    sprite->setAnchorPoint(sc->anchorPointForShape(name));
}

void SecondScene::update(float dt)
{
    int velocityIterations = 8;
    int positionIterations = 1;

    world->Step(dt, velocityIterations, positionIterations);

    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()) );//CC_RADIANS_TO_DEGREES弧度转角度
        }
    }
}

CCScene* SecondScene::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();

    // add layer as a child to scene
    CCLayer* layer = new SecondScene();
    scene->addChild(layer);
    layer->release();

    return scene;
}

void SecondScene::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent)
{
    CCSetIterator it;
    CCTouch * touch;
    for(it = pTouches->begin(); it != pTouches->end(); it++)
    {
        touch = (CCTouch *)(*it);
        if(!touch)
            break;
        CCPoint location = touch->getLocation();

        if(!this->MouseDown(b2Vec2(location.x / PTM_RATIO, location.y / PTM_RATIO)))
        {
            this->addNewSpriteAtPosition(location);
        }
    }
}

void SecondScene::ccTouchesMoved(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent)
{
    CCSetIterator it;
    CCTouch * touch;
    for(it = pTouches->begin(); it != pTouches->end(); it++)
    {
        touch = (CCTouch *)(*it);
        if(!touch)
            break;
        CCPoint location = touch->getLocation();

        this->MouseMove(b2Vec2(location.x / PTM_RATIO,location.y / PTM_RATIO));
    }
}

void SecondScene::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
    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);

        addNewSpriteAtPosition( location );
    }
    this->MouseUp();
}

bool SecondScene::MouseDown(const b2Vec2 &p)
{
    if(m_mouseJoint != NULL)
    {
        return false;
    }

    b2AABB aabb;
    b2Vec2 d;
    d.Set(0.001f, 0.001f);
    aabb.lowerBound = p - d;
    aabb.upperBound = p + d;

    QueryCallback callback(p);

    world->QueryAABB(&callback, aabb);

    if (callback.m_fixture)
    {
        b2Body * body = callback.m_fixture->GetBody();
        b2MouseJointDef md;
        md.bodyA = m_groundBody;  //m_groundBody需要在上面init方法里定义一下
        md.bodyB = body;
        md.target = p;
        md.maxForce = 1000.0f * body->GetMass();
        m_mouseJoint = (b2MouseJoint *)world->CreateJoint(&md);
        body->SetAwake(true);
        return true;
    }

    return true;
}

void SecondScene::MouseMove(const b2Vec2 &p)
{
    if(m_mouseJoint)
    {
        m_mouseJoint->SetTarget(p);
    }
}

void SecondScene::MouseUp()
{
    if(m_mouseJoint)
    {
        world->DestroyJoint(m_mouseJoint);
        m_mouseJoint = NULL;
    }
}

3.碰撞检测类(ContactListener)

#ifndef __box2dDemo__ContactListener__
#define __box2dDemo__ContactListener__

//碰撞检测
#include <iostream>

#include "cocos2d.h"
#include "Box2D.h"

using namespace cocos2d;

class ContactListener : public b2ContactListener
{
    void BeginContact(b2Contact * contact);
    void EndContact(b2Contact *contact);
};

#endif /* defined(__box2dDemo__ContactListener__) */

cpp

#include "ContactListener.h"

void ContactListener::BeginContact(b2Contact *contact)
{
    b2Body *bodyA = contact->GetFixtureA()->GetBody();
    b2Body *bodyB = contact->GetFixtureB()->GetBody();
    CCSprite *spriteA = (CCSprite *)bodyA->GetUserData();
    CCSprite *spriteB = (CCSprite *)bodyB->GetUserData();

    if (spriteA != NULL && spriteB != NULL) {
        spriteA->setColor(ccMAGENTA);
        spriteB->setColor(ccMAGENTA);
    }
}

void ContactListener::EndContact(b2Contact *contact)
{
    b2Body *bodyA = contact->GetFixtureA()->GetBody();
    b2Body *bodyB = contact->GetFixtureB()->GetBody();
    CCSprite *spriteA = (CCSprite *)bodyA->GetUserData();
    CCSprite *spriteB = (CCSprite *)bodyB->GetUserData();

    if (spriteA != NULL && spriteB != NULL) {
        spriteA->setColor(ccWHITE);
        spriteB->setColor(ccWHITE);
    }
}

运行效果:

cocos2d-x游戏开发QQ交流群:280818155

备注:加入者必须修改:地区-昵称,很少有动态的将定期清理

时间: 2024-08-03 20:36:42

[cocos2d-x]box2d的简单应用的相关文章

Android下2d物理引擎Box2d用法简单实例_Android

本文实例讲述了Android下2d物理引擎Box2d用法.分享给大家供大家参考.具体如下: 程序运行的时候需要加载Jbox2d的库,可到以下地址下载(使用的是不带渲染部分的库jbox2d-2.0.1-library-only.jar): http://sourceforge.net/projects/jbox2d/ package com.test; import org.jbox2d.collision.AABB; import org.jbox2d.collision.CircleDef;

Android下2d物理引擎Box2d用法简单实例

本文实例讲述了Android下2d物理引擎Box2d用法.分享给大家供大家参考.具体如下: 程序运行的时候需要加载Jbox2d的库,可到以下地址下载(使用的是不带渲染部分的库jbox2d-2.0.1-library-only.jar): http://sourceforge.net/projects/jbox2d/ package com.test; import org.jbox2d.collision.AABB; import org.jbox2d.collision.CircleDef;

ios-cocos2D的Box2d项目中弹球问题

问题描述 cocos2D的Box2d项目中弹球问题 做到第二个弹球时,弹球没有弹起来,穿过地板了.不知道怎么解决?第二个弹球和第一个弹球完全一样啊.请好心人帮忙看看. 代码: #import ""HelloWorldLayer.h""@implementation HelloWorldLayer+ (id)scene { CCScene *scene = [CCScene node]; HelloWorldLayer *layer = [HelloWorldLaye

Visual Studio 2012下Box2D开发环境设置

Cocos2d-x 3.x默认情况下采用的物理引擎是Chipmunk如果我们要使用Box2D引擎需要进行一些设置和调整而且不同的开发平台下这些设置也有所不同.由于本书在此之前介绍的都是基于微软的Visual Studio 2012下开发的Win32平台所以这一节我们介绍Visual Studio 2012下Box2D开发环境设置.这些需要设置和调整的方面包括如下在解决方案中添加libBox2D库工程.添加libBox2D库引用.开启Box2D预编译开关. 1.在解决方案中添加libBox2D库首

【IOS-COCOS2D游戏开发之十一】使用BOX2D物理系统以及在COCOS2D框架添加BOX2D物理系统LIB包的方法

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/iphone-cocos2d/474.html 上一节讲述了粒子的相关问题,当然啦,不示弱,今天继续将物理系统给大家进行简单的介绍和讲述: 首先先介绍,如何在cocos2d中加入box2d开发lib包,因为一般使用cocos2d引擎进行开发游戏时,大家创建项目都会选用cocos2d框架,而不是直接采用物理系统的cocos2d框架,但是后期忽然

【COCOS2D-HTML5 开发之一】新建HTML5项目及简单阐述与COCOS2D/X引擎关系

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/cocos2d-html5/1463.html             真的是有一段时间没写博了,这段时间呢,发生的事情真的挺多,另外自己呢也闲来做了一些自己的喜欢的东西,主要做的还是基于Mac系统的Cocoa框架的各种编辑器吧.(对了,今年初也出了自己第二本书<iOS游戏编程之从零开始-Cocos2d-x与cocos2d引擎游戏开发>)

《Cocos2D-x权威指南》——1.1 什么是Cocos2D

1.1 什么是Cocos2D 大家认识并且熟悉Cocos2D,应该是从App Store上几款非常火爆的游戏开始的,但是实际上Cocos2D引擎最早并非是为iOS(iPhone Operating System,苹果移动设备操作系统)设计的.最早它是一款用Python语言开发的游戏引擎,后来使用Objective-C被移植为iOS平台的Cocos2D- iPhone版本.不仅如此,Cocos2D被移植成各个版本,形成了庞大的Cocos2D家族.1.1.1 Cocos2D的特点 Cocos2D是一

当 iOS 游戏开发像做份沙拉那么简单

写在所有之前:这个工具更适合没有编码基础又喜欢折腾的设计师们,并不一定适合开发者. 当你有一个好的游戏创意却因没有代码基础而搁浅时,是不是很期待一款这样的软件,让iOS游戏开发变得像做份沙拉那么简单?现在GameSaladInc.就为我们提供了这样一个便利的开发工具GameSalad.   简单介绍一下GameSalad:这是一款可视化编程的游戏引擎,使用者无需编码就能为iPhone, iPad, Mac和Web来设计,发布和分销原创游戏,简单易上手,很适合交互和视觉.开发完成的游戏可以通过云端

Cocos2D iOS之旅:如何写一个敲地鼠游戏(一):高清屏显示和UIKit

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流之用,请勿进行商业用途.同时,转载时不要移除本申明.如产生任何纠纷,均与本博客所有人.发表该翻译稿之人无任何关系.谢谢合作! 原文由Ray Wunderlich写成,地址在: http://www.raywenderlich.com/2560/cocos2d-tutorial-for-ios-how