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__) */
#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; } }
#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__) */
#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
备注:加入者必须修改:地区-昵称,很少有动态的将定期清理