Cocos2dx(1) Box2d Demo
Box2d 介绍:http://www.cnblogs.com/TS-qrt/articles/Box2DEx.html
链接参考:http://www.cnblogs.com/andyque/archive/2011/05/27/2059453.html
http://www.cnblogs.com/andyque/archive/2011/05/27/2059460.html
为了创建一个body对象,你需要做很多事情--首先,创建一个body定义结构,然后是body对象,再指定一个shap,再是fixture定义,然后再创建一个fixture对象。下面会一个一个解释刚刚这些东西。
- 你首先创建一个body定义结构体,用以指定body的初始属性,比如位置或者速度。
- 一旦创建好body结构体后,你就可以调用world对象来创建一个body对象了。
- 然后,你为body对象定义一个shape,用以指定你想要仿真的物体的几何形状。
- 接着创建一个fixture定义,同时设置之前创建好的shape为fixture的一个属性,并且设置其它的属性,比如质量或者摩擦力。
- 最后,你可以使用body对象来创建fixture对象,通过传入一个fixture的定义结构就可以了。
- 请注意,你可以往单个body对象里面添加很多个fixture对象。这个功能在你创建特别复杂的对象的时候非常有用。比如自行车,你可能要创建2个轮子,车身等等,这些fixture可以用关节连接起来。
b2BodyDef:
b2BodyDef.type=b2Body.b2_staticBody 是默认值,表示静态的对象; b2BodyDef.type=b2Body.b2_dynamicBody; 当无这句而设置质量 b2FixtureDef.density=1时 表示其质量为0,也就是说他是静态不能动的物体; 当有“b2BodyDef.type=b2Body.b2_dynamicBody”这一句时,b2FixtureDef.density=1 表示其质量为1,即没有这句时质量为0,有了这一句才可以自己设置动态对象的质量.
b2BodyDef bodyDef;
ballBodyDef.type = b2_dynamicBody; //表示非静态对象
bodyDef.position.Set(0.0f, 4.0f); //确定位置 bodyDef.userData = &myActor; //数据 bodyDef.angle = 0.25f * b2_pi; //旋转角度
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox; //形状 fixtureDef.density = 1.0f; //密度 fixtureDef.friction = 0.3f; //摩擦 fixtureDef.userData = myData; //数据
fixtureDef.restitution =0.8f; // 回复力。它的范围也是0到1.0. 0意味着对象碰撞之后不会反弹,1意味着是完全弹性碰撞,会以同样的速度反弹。
Demo
|-GLES-Render.h/cpp (Box2d测试调用,引擎自带,具体查看以上链接)
|-HelloWorldScene.h/cpp
GLES-Render.h
/* * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com * * iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef RENDER_H #define RENDER_H #include "Box2D/Box2D.h" #include "cocos2d.h" struct b2AABB; // This class implements debug drawing callbacks that are invoked // inside b2World::Step. class GLESDebugDraw : public b2Draw { float32 mRatio; cocos2d::CCGLProgram* mShaderProgram; GLint mColorLocation; void initShader( void ); public: GLESDebugDraw(); GLESDebugDraw( float32 ratio ); virtual void DrawPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color); virtual void DrawSolidPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color); virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color); virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color); virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color); virtual void DrawTransform(const b2Transform& xf); virtual void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color); virtual void DrawString(int x, int y, const char* string, ...); virtual void DrawAABB(b2AABB* aabb, const b2Color& color); }; #endif
GLES-Render.cpp
/* * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com * * iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include "GLES-Render.h" #include "cocos2d.h" #include <stdio.h> #include <stdarg.h> #include <string.h> USING_NS_CC; GLESDebugDraw::GLESDebugDraw() : mRatio( 1.0f ) { this->initShader(); } GLESDebugDraw::GLESDebugDraw( float32 ratio ) : mRatio( ratio ) { this->initShader(); } void GLESDebugDraw::initShader( void ) { mShaderProgram = CCShaderCache::sharedShaderCache()->programForKey(kCCShader_Position_uColor); mColorLocation = glGetUniformLocation( mShaderProgram->getProgram(), "u_color"); } void GLESDebugDraw::DrawPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color) { mShaderProgram->use(); mShaderProgram->setUniformsForBuiltins(); b2Vec2* vertices = new b2Vec2[vertexCount]; for( int i=0;i<vertexCount;i++) { vertices[i] = old_vertices[i]; vertices[i] *= mRatio; } mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1); glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices); glDrawArrays(GL_LINE_LOOP, 0, vertexCount); CC_INCREMENT_GL_DRAWS(1); CHECK_GL_ERROR_DEBUG(); delete[] vertices; } void GLESDebugDraw::DrawSolidPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color) { mShaderProgram->use(); mShaderProgram->setUniformsForBuiltins(); b2Vec2* vertices = new b2Vec2[vertexCount]; for( int i=0;i<vertexCount;i++) { vertices[i] = old_vertices[i]; vertices[i] *= mRatio; } mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r*0.5f, color.g*0.5f, color.b*0.5f, 0.5f); glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices); glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount); mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1); glDrawArrays(GL_LINE_LOOP, 0, vertexCount); CC_INCREMENT_GL_DRAWS(2); CHECK_GL_ERROR_DEBUG(); delete[] vertices; } void GLESDebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) { mShaderProgram->use(); mShaderProgram->setUniformsForBuiltins(); const float32 k_segments = 16.0f; int vertexCount=16; const float32 k_increment = 2.0f * b2_pi / k_segments; float32 theta = 0.0f; GLfloat* glVertices = new GLfloat[vertexCount*2]; for (int i = 0; i < k_segments; ++i) { b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta)); glVertices[i*2]=v.x * mRatio; glVertices[i*2+1]=v.y * mRatio; theta += k_increment; } mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1); glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices); glDrawArrays(GL_LINE_LOOP, 0, vertexCount); CC_INCREMENT_GL_DRAWS(1); CHECK_GL_ERROR_DEBUG(); delete[] glVertices; } void GLESDebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) { mShaderProgram->use(); mShaderProgram->setUniformsForBuiltins(); const float32 k_segments = 16.0f; int vertexCount=16; const float32 k_increment = 2.0f * b2_pi / k_segments; float32 theta = 0.0f; GLfloat* glVertices = new GLfloat[vertexCount*2]; for (int i = 0; i < k_segments; ++i) { b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta)); glVertices[i*2]=v.x * mRatio; glVertices[i*2+1]=v.y * mRatio; theta += k_increment; } mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r*0.5f, color.g*0.5f, color.b*0.5f, 0.5f); glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices); glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount); mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1); glDrawArrays(GL_LINE_LOOP, 0, vertexCount); // Draw the axis line DrawSegment(center,center+radius*axis,color); CC_INCREMENT_GL_DRAWS(2); CHECK_GL_ERROR_DEBUG(); delete[] glVertices; } void GLESDebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) { mShaderProgram->use(); mShaderProgram->setUniformsForBuiltins(); mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1); GLfloat glVertices[] = { p1.x * mRatio, p1.y * mRatio, p2.x * mRatio, p2.y * mRatio }; glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices); glDrawArrays(GL_LINES, 0, 2); CC_INCREMENT_GL_DRAWS(1); CHECK_GL_ERROR_DEBUG(); } void GLESDebugDraw::DrawTransform(const b2Transform& xf) { b2Vec2 p1 = xf.p, p2; const float32 k_axisScale = 0.4f; p2 = p1 + k_axisScale * xf.q.GetXAxis(); DrawSegment(p1, p2, b2Color(1,0,0)); p2 = p1 + k_axisScale * xf.q.GetYAxis(); DrawSegment(p1,p2,b2Color(0,1,0)); } void GLESDebugDraw::DrawPoint(const b2Vec2& p, float32 size, const b2Color& color) { mShaderProgram->use(); mShaderProgram->setUniformsForBuiltins(); mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1); // glPointSize(size); GLfloat glVertices[] = { p.x * mRatio, p.y * mRatio }; glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices); glDrawArrays(GL_POINTS, 0, 1); // glPointSize(1.0f); CC_INCREMENT_GL_DRAWS(1); CHECK_GL_ERROR_DEBUG(); } void GLESDebugDraw::DrawString(int x, int y, const char *string, ...) { // NSLog(@"DrawString: unsupported: %s", string); //printf(string); /* Unsupported as yet. Could replace with bitmap font renderer at a later date */ } void GLESDebugDraw::DrawAABB(b2AABB* aabb, const b2Color& color) { mShaderProgram->use(); mShaderProgram->setUniformsForBuiltins(); mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, 1); GLfloat glVertices[] = { aabb->lowerBound.x * mRatio, aabb->lowerBound.y * mRatio, aabb->upperBound.x * mRatio, aabb->lowerBound.y * mRatio, aabb->upperBound.x * mRatio, aabb->upperBound.y * mRatio, aabb->lowerBound.x * mRatio, aabb->upperBound.y * mRatio }; glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices); glDrawArrays(GL_LINE_LOOP, 0, 8); CC_INCREMENT_GL_DRAWS(1); CHECK_GL_ERROR_DEBUG(); }
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "Box2D\Box2D.h" class HelloWorld : public cocos2d::CCLayer { public: // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::CCScene* scene(); // a selector callback void menuCloseCallback(CCObject* pSender); // implement the "static node()" method manually CREATE_FUNC(HelloWorld); private: b2World *m_pWorld; b2Body *m_pBody; cocos2d::CCSprite *m_pBall; virtual void draw(); //DebugDraw void update(float dt); }; #endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
#include "HelloWorldScene.h" #include "GLES-Render.h" #define PTM_RATIO 32.0 //像素/米 USING_NS_CC; CCScene* HelloWorld::scene() { // 'scene' is an autorelease object CCScene *scene = CCScene::create(); // 'layer' is an autorelease object HelloWorld *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 ( !CCLayer::init() ) { return false; } CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); //create a back_ball(circle) m_pBall = CCSprite::create("box2d/back_ball.png"); this->addChild(m_pBall);//box2d //create a world ------------------------------ b2Vec2 gravity = b2Vec2(0.0f, -9.8f); m_pWorld = new b2World(gravity); m_pWorld->SetAllowSleeping(true); //允许睡觉,允许睡眠,可以提高物理世界中物体的处理效率,只有在发生碰撞时才唤醒该对象 m_pWorld->SetContinuousPhysics(true); //开启连续物理测试 //create a ground b2BodyDef groundBodyDef; //1 groundBodyDef.position.Set(0, 0); b2Body *groundBody = m_pWorld->CreateBody(&groundBodyDef); //2 b2EdgeShape groundShape; //3 b2FixtureDef groundFixtureDef; groundFixtureDef.shape = &groundShape; //4 bottom groundShape.Set(b2Vec2(0,0), b2Vec2(visibleSize.width/PTM_RATIO, 0)); groundBody->CreateFixture(&groundFixtureDef); // left groundShape.Set(b2Vec2(0,0), b2Vec2(0, visibleSize.height/PTM_RATIO)); groundBody->CreateFixture(&groundFixtureDef); // up groundShape.Set(b2Vec2(0, visibleSize.height/PTM_RATIO), b2Vec2(visibleSize.width/PTM_RATIO, visibleSize.height/PTM_RATIO)); groundBody->CreateFixture(&groundFixtureDef); // right groundShape.Set(b2Vec2(visibleSize.width/PTM_RATIO, visibleSize.height/PTM_RATIO), b2Vec2(visibleSize.width/PTM_RATIO, 0)); groundBody->CreateFixture(&groundFixtureDef); //create a body circle -------------------------------- //1.b2BodyDef b2BodyDef ballBodyDef; //创建一个body定义结构体 ballBodyDef.position.Set(8, visibleSize.height*0.8f/PTM_RATIO); ballBodyDef.type = b2_dynamicBody; //表示非静态Body,受重力影响 ballBodyDef.userData = m_pBall; //将CCSprite作为userData存入bodyDef中,在update定时器中处理 //2.b2Body b2Body *ballBody = m_pWorld->CreateBody(&ballBodyDef); //3. b2CircleShape && b2FixtureDef b2CircleShape ballShape; b2FixtureDef ballFixtureDef; //刚体材质属性和形状等, ballFixtureDef.density = 1.0f; //密度 ballFixtureDef.friction = 0.2f; //摩擦力 ballFixtureDef.restitution = 0.8f; //回复力,影响弹性系数 ballFixtureDef.shape = &ballShape; //形状 ballShape.m_radius = m_pBall->getContentSize().width*0.5f/PTM_RATIO; ballBody->CreateFixture(&ballFixtureDef); //================================ //DebugDraw GLESDebugDraw* m_pDebugDraw = new GLESDebugDraw(PTM_RATIO); m_pWorld->SetDebugDraw(m_pDebugDraw); uint32 flags = 0; flags += b2Draw::e_shapeBit; m_pDebugDraw->SetFlags(flags); this->scheduleUpdate(); return true; } void HelloWorld::menuCloseCallback(CCObject* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); #else CCDirector::sharedDirector()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif #endif } //DebugDraw void HelloWorld::draw() { CCNode::draw(); ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position); kmGLPushMatrix(); m_pWorld->DrawDebugData(); kmGLPopMatrix(); } void HelloWorld::update(float dt) { int32 velocityIterations = 8; int32 positionIterations = 2; /*Box2d是通过定期调用step来更新动画的,第一个参数为时间步,第二个 参数是速度迭代次数,推荐8次,第三个参数是位置迭代*/ m_pWorld->Step(dt, velocityIterations, positionIterations); for(b2Body* b=m_pWorld->GetBodyList();b;b=b->GetNext()) { if(b->GetUserData() != NULL) { CCSprite* ballData = (CCSprite*)b->GetUserData(); ballData->setPosition(ccp(b->GetPosition().x*PTM_RATIO, b->GetPosition().y*PTM_RATIO)); ballData->setRotation(-1*CC_RADIANS_TO_DEGREES(b->GetAngle())); } } }
End, thank you!!
浙公网安备 33010602011771号