【iOS-Cocos2d游戏开发之十一】使用Box2d物理系统以及在cocos2d框架添加Box2d物理系统lib包的方法
本站文章均为李华明Himi原创,转载务必在明显处注明:
转载自【黑米GameDev街区】原文链接:http://www.himigame.com/iphone-cocos2d/474.html
上一节讲述了粒子的相关问题,当然啦,不示弱,今天继续将物理系统给大家进行简单的介绍和讲述;
首先先介绍,如何在cocos2d中加入box2d开发lib包,因为一般使用cocos2d引擎进行开发游戏时,大家创建项目都会选用cocos2d框架,而不是直接采用物理系统的cocos2d框架,但是后期忽然需要在项目中使用物理系统(这种情况很经常发生,至于为什么,童鞋们都懂得~),OK,首先创建一个普通的cocos2d项目;
OK,加入box2d->lib步骤如下:
1. 首先将box2d的lib包拷贝到刚创建的项目下,然后右键项目的libs文件夹进行导入项目中;(如果你没有box2d的lib包,那就新建一个cocos2d-box2d的项目就有了)
2.双击你的项目名默认打开配置信息窗口,点击Build Settings标签,然后在页面中找到”Search Paths“一栏,然后在“User Header Search Paths”中添加“xx/libs”;这里的XX是你的项目名称;紧接着在“User Header Search Paths”一项的上面设置“Always Serch Paths”的选项 为YES,默认为NO;这里务必要设置;
3.最后commadn+B (我用的xcode For lion)编译项目代码,如果提示编译成功,OK,可以使用啦;
下面我来给大家简单的介绍以下如何在cocos2d中使用Box2d物理系统,虽然关于Box2d的相关资料和教程很少,但是这里我也不会很详细的介绍和解释,因为我即将上市的Android游戏开发书籍中已经对Box2d进行了很详细的讲解和两个物理小游戏实战,所以这里就大概的介绍下一些重要的方法;
便于讲解,这里我直接使用Xcode直接创建一个cocos2d-Box2d的项目,然后简单的修改:
////HelloWorldLayer.mm//Box2dProject////Createdby华明李on11-9-14.//Himi////Importtheinterfaces#import"HelloWorldLayer.h"#definePTM_RATIO32//enumsthatwillbeusedastagsenum{kTagTileMap=1,kTagAnimation1=1,};//HelloWorldLayerimplementation@implementationHelloWorldLayer+(CCScene*)scene{CCScene*scene=[CCScenenode];HelloWorldLayer*layer=[HelloWorldLayernode];[sceneaddChild:layer];returnscene;}//on"init"youneedtoinitializeyourinstance-(id)init{//初始化中,在屏幕上创建了物理世界,并且创建了在屏幕四周创建了刚体防止物理世界中的刚体超屏//最后并且调用一个tick方法用于让物理世界不断的去模拟if((self=[superinit])){self.isTouchEnabled=YES;self.isAccelerometerEnabled=YES;CGSizescreenSize=[CCDirectorsharedDirector].winSize;CCLOG(@"Screenwidth%0.2fscreenheight%0.2f",screenSize.width,screenSize.height);//Definethegravityvector.b2Vec2gravity;gravity.Set(0.0f,-10.0f);booldoSleep=true;world=newb2World(gravity,doSleep);world->SetContinuousPhysics(true);//DebugDrawfunctionsm_debugDraw=newGLESDebugDraw(PTM_RATIO);world->SetDebugDraw(m_debugDraw);uint32flags=0;flags+=b2DebugDraw::e_shapeBit;m_debugDraw->SetFlags(flags);b2BodyDefgroundBodyDef;groundBodyDef.position.Set(0,0);//bottom-leftcornerb2Body*groundBody=world->CreateBody(&groundBodyDef);b2PolygonShapegroundBox;//bottomgroundBox.SetAsEdge(b2Vec2(0,0),b2Vec2(screenSize.width/PTM_RATIO,0));groundBody->CreateFixture(&groundBox,0);//topgroundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO),b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO));groundBody->CreateFixture(&groundBox,0);//leftgroundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO),b2Vec2(0,0));groundBody->CreateFixture(&groundBox,0);//rightgroundBox.SetAsEdge(b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO),b2Vec2(screenSize.width/PTM_RATIO,0));groundBody->CreateFixture(&groundBox,0);CCLabelTTF*label=[CCLabelTTFlabelWithString:@"Himi"fontName:@"MarkerFelt"fontSize:32];[selfaddChild:labelz:0];label.position=ccp(screenSize.width/2,screenSize.height-50);[selfschedule:@selector(tick:)];}returnself;}//Box2d调试模式,因为物理世界是看不到摸不到的,那么物理世界中的刚体其实也一样无法看到,//但是为了便于开发调试,Box2d提供了调试类,主要作用是能将物理世界的所有刚体、关节等都利用线条框出来,//这样便于设置你的Body与Sprite之间的位置关系-----(void)draw{glDisable(GL_TEXTURE_2D);glDisableClientState(GL_COLOR_ARRAY);glDisableClientState(GL_TEXTURE_COORD_ARRAY);world->DrawDebugData();//restoredefaultGLstatesglEnable(GL_TEXTURE_2D);glEnableClientState(GL_COLOR_ARRAY);glEnableClientState(GL_TEXTURE_COORD_ARRAY);}//---添加一个刚体,首先需要创建刚体的皮肤,可以理解这个皮肤是刚体的属性,然后利用皮肤包装出一个刚体-(void)addNewSpriteWithCoords:(CGPoint)psp:(CCSprite*)sprite{CCLOG(@"Addsprite%0.2fx%02.f",p.x,p.y);sprite.position=ccp(p.x,p.y);b2BodyDefbodyDef;bodyDef.type=b2_dynamicBody;bodyDef.position.Set(p.x/PTM_RATIO,p.y/PTM_RATIO);//将精灵信息赋值给刚体皮肤,这样就能让精灵的运动轨迹与这个即将创建出的刚体在物理世界中的运动轨迹同步bodyDef.userData=sprite;b2Body*body=world->CreateBody(&bodyDef);b2PolygonShapedynamicBox;dynamicBox.SetAsBox(.9f,.9f);b2FixtureDeffixtureDef;fixtureDef.shape=&dynamicBox;fixtureDef.density=1.0f;fixtureDef.friction=0.3f;body->CreateFixture(&fixtureDef);//给body施加一个力b2Vec2force=body->GetWorldVector(b2Vec2(1000.0f,600.0f));b2Vec2point=body->GetWorldPoint(b2Vec2(0.4f,0.4f));body->ApplyForce(force,point);//----------备注1Himi}//此方法中,首先是让物理世界进行物理模拟,然后不断的遍历物理世界中的刚体运动轨迹复制给对应的精灵-(void)tick:(ccTime)dt{int32velocityIterations=8;int32positionIterations=1;world->Step(dt,velocityIterations,positionIterations);for(b2Body*b=world->GetBodyList();b;bb=b->GetNext()){if(b->GetUserData()!=NULL){//SynchronizetheAtlasSpritespositionandrotationwiththecorrespondingbodyCCSprite*myActor=(CCSprite*)b->GetUserData();myActor.position=CGPointMake(b->GetPosition().x*PTM_RATIO,b->GetPosition().y*PTM_RATIO);myActor.rotation=-1*CC_RADIANS_TO_DEGREES(b->GetAngle());}}}//---触屏将添加一个body和精灵,位置为玩家触屏的坐标-(void)ccTouchesEnded:(NSSet*)toucheswithEvent:(UIEvent*)event{for(UITouch*touchintouches){CGPointlocation=[touchlocationInView:[touchview]];location=[[CCDirectorsharedDirector]convertToGL:location];CCSprite*sprite=[CCSpritespriteWithFile:@"icon.png"];[selfaddChild:sprite];[selfaddNewSpriteWithCoords:locationsp:sprite];}}-(void)accelerometer:(UIAccelerometer*)accelerometerdidAccelerate:(UIAcceleration*)acceleration{staticfloatprevX=0,prevY=0;//#definekFilterFactor0.05f#definekFilterFactor1.0f//don'tusefilter.thecodeisherejustasanexamplefloataccelX=(float)acceleration.x*kFilterFactor+(1-kFilterFactor)*prevX;floataccelY=(float)acceleration.y*kFilterFactor+(1-kFilterFactor)*prevY;prevX=accelX;prevY=accelY;b2Vec2gravity(-accelY*10,accelX*10);world->SetGravity(gravity);}-(void)dealloc{deleteworld;world=NULL;deletem_debugDraw;[superdealloc];}@end
这里我只是对重要的方法进行的说明,主要修改的一点地方在备注1这里,我这里对每次玩家触摸屏幕的地方创建的刚体都进行施加了一个力,让刚体进行运动,那么这个运动的轨迹也会根据你设置的物理世界的重力方向发生改变,当前项目中,重力方向垂直下落,没有X轴的变化;
还要注意一点,由于box2d是c++代码,那么如果你使用box2d的话,首先把你的Delegate.m的类改成Delegate.mm,还有你使用box2d相关代码的实现类(.m)格式的类要改成(.mm)格式才可,这样编译器就会知道是混合代码,否则都当成object-c进行编译就会报错;
运行截图如下:
从图中可以看出,在icon图的周围包围着线段,这个就是Box2d提供的调试绘制,将本无形的刚体绘制出来了;
这里我不得不说一些童鞋,例如之前我写过Android上的一个自己随手的物理系统小球的例子,我在博文中写了要触屏才创建小球,但是很多童鞋问我项目运行起来没效果有问题,我就崩溃了。。。你们让我
源码不传了,大家可以直接创建一个cocos2d-box2d的项目,然后将HelloWorldLayer.mm中代码换成我上面的代码即可~
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。