您好,登錄后才能下訂單哦!
本站文章均為 李華明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
- //
- // Created by 華明 李 on 11-9-14.
- // Himi
- //
- // Import the interfaces
- #import "HelloWorldLayer.h"
- #define PTM_RATIO 32
- // enums that will be used as tags
- enum {
- kTagTileMap = 1,
- kTagAnimation1 = 1,
- };
- // HelloWorldLayer implementation
- @implementation HelloWorldLayer
- +(CCScene *) scene
- {
- CCScene *scene = [CCScene node];
- HelloWorldLayer *layer = [HelloWorldLayer node];
- [scene addChild: layer];
- return scene;
- }
- // on "init" you need to initialize your instance
- -(id) init
- {
- //初始化中,在屏幕上創建了物理世界,并且創建了在屏幕四周創建了剛體防止物理世界中的剛體超屏
- //最后并且調用一個tick方法用于讓物理世界不斷的去模擬
- if( (self=[super init])) {
- self.isTouchEnabled = YES;
- self.isAccelerometerEnabled = YES;
- CGSize screenSize = [CCDirector sharedDirector].winSize;
- CCLOG(@"Screen width %0.2f screen height %0.2f",screenSize.width,screenSize.height);
- // Define the gravity vector.
- b2Vec2 gravity;
- gravity.Set(0.0f, -10.0f);
- bool doSleep = true;
- world = new b2World(gravity, doSleep);
- world->SetContinuousPhysics(true);
- // Debug Draw functions
- m_debugDraw = new GLESDebugDraw( PTM_RATIO );
- world->SetDebugDraw(m_debugDraw);
- uint32 flags = 0;
- flags += b2DebugDraw::e_shapeBit;
- m_debugDraw->SetFlags(flags);
- b2BodyDef groundBodyDef;
- groundBodyDef.position.Set(0, 0); // bottom-left corner
- b2Body* groundBody = world->CreateBody(&groundBodyDef);
- b2PolygonShape groundBox;
- // bottom
- groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(screenSize.width/PTM_RATIO,0));
- groundBody->CreateFixture(&groundBox,0);
- // top
- groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO));
- groundBody->CreateFixture(&groundBox,0);
- // left
- groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(0,0));
- groundBody->CreateFixture(&groundBox,0);
- // right
- groundBox.SetAsEdge(b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,0));
- groundBody->CreateFixture(&groundBox,0);
- CCLabelTTF *label = [CCLabelTTF labelWithString:@"Himi" fontName:@"Marker Felt" fontSize:32];
- [self addChild:label z:0];
- label.position = ccp( screenSize.width/2, screenSize.height-50);
- [self schedule: @selector(tick:)];
- }
- return self;
- }
- //Box2d調試模式,因為物理世界是看不到摸不到的,那么物理世界中的剛體其實也一樣無法看到,
- //但是為了便于開發調試,Box2d提供了調試類,主要作用是能將物理世界的所有剛體、關節等都利用線條框出來,
- //這樣便于設置你的Body與Sprite之間的位置關系 ----
- -(void) draw
- {
- glDisable(GL_TEXTURE_2D);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- world->DrawDebugData();
- // restore default GL states
- glEnable(GL_TEXTURE_2D);
- glEnableClientState(GL_COLOR_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- }
- //---添加一個剛體,首先需要創建剛體的皮膚,可以理解這個皮膚是剛體的屬性,然后利用皮膚包裝出一個剛體
- -(void) addNewSpriteWithCoords:(CGPoint)p sp:(CCSprite*)sprite
- {
- CCLOG(@"Add sprite %0.2f x %02.f",p.x,p.y);
- sprite.position = ccp( p.x, p.y);
- 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);
- b2PolygonShape dynamicBox;
- dynamicBox.SetAsBox(.9f, .9f);
- b2FixtureDef fixtureDef;
- fixtureDef.shape = &dynamicBox;
- fixtureDef.density = 1.0f;
- fixtureDef.friction = 0.3f;
- body->CreateFixture(&fixtureDef);
- //給body施加一個力
- b2Vec2 force = body->GetWorldVector(b2Vec2(1000.0f, 600.0f));
- b2Vec2 point = body->GetWorldPoint(b2Vec2(0.4f, 0.4f));
- body->ApplyForce(force, point);//----------備注1 Himi
- }
- //此方法中,首先是讓物理世界進行物理模擬,然后不斷的遍歷物理世界中的剛體運動軌跡復制給對應的精靈
- -(void) tick: (ccTime) dt
- {
- int32 velocityIterations = 8;
- int32 positionIterations = 1;
- world->Step(dt, velocityIterations, positionIterations);
- for (b2Body* b = world->GetBodyList(); b; bb = b->GetNext())
- {
- if (b->GetUserData() != NULL) {
- //Synchronize the AtlasSprites position and rotation with the corresponding body
- CCSprite *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 *)touches withEvent:(UIEvent *)event
- {
- for( UITouch *touch in touches ) {
- CGPoint location = [touch locationInView: [touch view]];
- location = [[CCDirector sharedDirector] convertToGL: location];
- CCSprite *sprite =[CCSprite spriteWithFile:@"icon.png"];
- [self addChild:sprite];
- [self addNewSpriteWithCoords: location sp:sprite];
- }
- }
- - (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
- {
- static float prevX=0, prevY=0;
- //#define kFilterFactor 0.05f
- #define kFilterFactor 1.0f // don't use filter. the code is here just as an example
- float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;
- float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;
- prevX = accelX;
- prevY = accelY;
- b2Vec2 gravity( -accelY * 10, accelX * 10);
- world->SetGravity( gravity );
- }
- - (void) dealloc
- {
- delete world;
- world = NULL;
- delete m_debugDraw;
- [super dealloc];
- }
- @end
這里我只是對重要的方法進行的說明,主要修改的一點地方在備注1這里,我這里對每次玩家觸摸屏幕的地方創建的剛體都進行施加了一個力,讓剛體進行運動,那么這個運動的軌跡也會根據你設置的物理世界的重力方向發生改變,當前項目中,重力方向垂直下落,沒有X軸的變化;
還要注意一點,由于box2d是c++代碼,那么如果你使用box2d的話,首先把你的Delegate.m的類改成Delegate.mm,還有你使用box2d相關代碼的實現類(.m)格式的類要改成(.mm)格式才可,這樣編譯器就會知道是混合代碼,否則都當成object-c進行編譯就會報錯;
運行截圖如下:
從圖中可以看出,在icon圖的周圍包圍著線段,這個就是Box2d提供的調試繪制,將本無形的剛體繪制出來了;
這里我不得不說一些童鞋,例如之前我寫過Android上的一個自己隨手的物理系統小球的例子,我在博文中寫了要觸屏才創建小球,但是很多童鞋問我項目運行起來沒效果有問題,我就崩潰了。。。你們讓我
源碼不傳了,大家可以直接創建一個cocos2d-box2d的項目,然后將HelloWorldLayer.mm中代碼換成我上面的代碼即可~
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。