2011-07-05 53 views
1

我有一個地面物體和矛形物體(動態)。當按下按鈕時,線速度會施加在矛上。它工作正常,但有時會卡在地上。這種情況大部分時間發生(不總是),當矛矛的一側與地面直線相撞時。我附上一些圖像,以便你們得到的圖片: enter image description hereBox2D動態物體卡住(iPhone)

這裏我的代碼:

#import "HelloWorldLayer.h" 

#define PTM_RATIO 32 


@implementation HelloWorldLayer 

+(CCScene *) scene{ 
    CCScene *scene = [CCScene node]; 

    HelloWorldLayer *layer = [HelloWorldLayer node]; 
    [scene addChild: layer]; 

    return scene; 
} 

-(id) init { 

    if((self=[super init])) { 

     isSimulating = NO; 

     CGSize winSize = [CCDirector sharedDirector].winSize; 

     self.isAccelerometerEnabled = YES; 
     self.isTouchEnabled = YES; 

     // Create sprite and add it to the layer 
     _spear = [CCSprite spriteWithFile:@"image_SPEAR.png"]; 
     _spear.position = ccp(40, 30); 

     [self addChild:_spear]; 


     label = [CCLabelTTF labelWithString:@"Hello World" fontName:@"Marker Felt" fontSize:20]; 
     CGSize size = [[CCDirector sharedDirector] winSize]; 
     label.position = ccp(size.width /2 , size.height/2); 
     [self addChild: label]; 

     CCMenuItem *starMenuItem = [CCMenuItemImage 
            itemFromNormalImage:@"ball.png" selectedImage:@"ball.png" 
            target:self selector:@selector(starButtonTapped:)]; 
     starMenuItem.position = ccp(60, 250); 
     CCMenu *starMenu = [CCMenu menuWithItems:starMenuItem, nil]; 
     starMenu.position = CGPointZero; 
     [self addChild:starMenu]; 


     // Create a world 
     b2Vec2 gravity = b2Vec2(0.0f, -20.0f); 
     bool doSleep = true; 
     _world = new b2World(gravity, doSleep); 

     // Create edges around the entire screen 
     b2BodyDef groundBodyDef; 
     groundBodyDef.position.Set(0,0); 
     b2Body *groundBody = _world->CreateBody(&groundBodyDef); 
     b2PolygonShape groundBox; 
     b2FixtureDef boxShapeDef; 
     boxShapeDef.shape = &groundBox; 
     groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(winSize.width/PTM_RATIO, 0)); 
     groundBody->CreateFixture(&boxShapeDef); 
     groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(0, winSize.height/PTM_RATIO)); 
     groundBody->CreateFixture(&boxShapeDef); 
     groundBox.SetAsEdge(b2Vec2(0, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO)); 
     groundBody->CreateFixture(&boxShapeDef); 
     groundBox.SetAsEdge(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, 0)); 
     groundBody->CreateFixture(&boxShapeDef); 
     boxShapeDef.friction = 0.3f; 


     [self setup]; 

    } 
    return self; 
} 

- (void)setup { 

    NSLog(@"Setting up..."); 
    //set the sprite's initial position 
    _spear.position = ccp(40, 30); 
    _spear.rotation = 0.0f; 


    //row 1, col 1 
    int num = 7; 
    b2Vec2 verts[] = { 
     b2Vec2(-36.0f/PTM_RATIO, -2.7f/PTM_RATIO), 
     b2Vec2(20.1f/PTM_RATIO, -2.1f/PTM_RATIO), 
     b2Vec2(24.4f/PTM_RATIO, -4.6f/PTM_RATIO), 
     b2Vec2(36.7f/PTM_RATIO, -1.4f/PTM_RATIO), 
     b2Vec2(23.9f/PTM_RATIO, 2.7f/PTM_RATIO), 
     b2Vec2(20.7f/PTM_RATIO, 0.0f/PTM_RATIO), 
     b2Vec2(-36.0f/PTM_RATIO, -0.5f/PTM_RATIO) 
    }; 






    // Create spear body and shape 
    b2BodyDef spearBodyDef; 
    spearBodyDef.type = b2_dynamicBody; 
    spearBodyDef.position.Set(40.0/PTM_RATIO, 30.0/PTM_RATIO); 
    //spearBodyDef.angle = 45.0 * (180.0f/b2_pi); 
    spearBodyDef.userData = _spear; 
    _spearBody = _world->CreateBody(&spearBodyDef); 

    b2PolygonShape spearShape; 
    spearShape.Set(verts, num); 

    b2FixtureDef spearShapeDef; 
    spearShapeDef.shape = &spearShape; 
    spearShapeDef.density = 0.75f; 
    spearShapeDef.friction = 0.2f; 
    spearShapeDef.restitution = 0.2f; 
    _spearBody->CreateFixture(&spearShapeDef); 

} 


- (void)starButtonTapped:(id)sender { 

    if (isSimulating) { 
     NSLog(@"Not simulating now..."); 

     [self unschedule:@selector(tick:)]; 
     _world->DestroyBody(_spearBody); 
     _spearBody = NULL; 
     [self setup]; 
    } else { 
     NSLog(@"Simulating now..."); 
     [self schedule:@selector(tick:)]; 

     float angle = _spearBody->GetAngle(); 

     b2Vec2 force; 
     force.Set(cos(angle) * 15.0f , sin(angle) * 15.0f); 
     _spearBody->SetLinearVelocity(force); 
    } 
    isSimulating = !isSimulating; 

} 

- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 

    if (!isSimulating) { 

     UITouch* touch = [touches anyObject]; 
     CGPoint location = [touch locationInView: [touch view]]; 
     location = [[CCDirector sharedDirector] convertToGL: location]; 

     float angleRadians = atanf((float)location.y/(float)location.x); 
     float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians); 

     _spear.rotation = -1 * angleDegrees; 
     _spearBody->SetTransform(_spearBody->GetPosition(), angleRadians); 

     [label setString:[NSString stringWithFormat:@"Angle: %f X: %f Y:%f", angleDegrees, location.x, location.y]]; 
     NSLog(@"%@", @"touched"); 

    } 

} 



- (void)tick:(ccTime) dt { 
    _world->Step(dt, 10, 10); 
    for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {  
     if (b->GetUserData() != NULL) { 
      CCSprite *ballData = (CCSprite *)b->GetUserData(); 
      ballData.position = ccp(b->GetPosition().x * PTM_RATIO, 
            b->GetPosition().y * PTM_RATIO); 
      ballData.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()); 
     }   
    } 
} 

- (void) dealloc { 
    delete _world; 
    _world = NULL; 

    [super dealloc]; 
} 
@end 

我猜測它與摩擦和賠償的事,但我已經嘗試了很多的價值並沒有什麼的使這種行爲消失。謝謝。

**更新:**我想通了這是什麼原因。每當它被困住時,矛就會出現在地面之外。每次。但是,爲什麼它首先會脫離地面呢?這是一張顯示這個的圖像。在底部,矛在身體外部: enter image description here

回答

1

你的矛形狀不是凸形的。我強烈建議你使用Box2D的調試繪製功能來檢查每一個東西。 http://www.iforce2d.net/b2dtut/debug-draw

這裏是多邊形的,其實就是出像 - 線條指定什麼,陰影部分是你得到了什麼:

enter image description here

+0

您好,感謝您的答覆。我一回到家就會解決這個問題,但是你認爲它會解決卡住的問題嗎?謝謝。 – user635064

+0

我沒有看到任何其他問題,但我並沒有真的太細緻。無論如何,先試試這個。 – iforce2d

+0

嘿,那確實是問題所在。謝謝。 – user635064

1

其實Box2D中有一個迭代求解。所以模擬的質量直接取決於迭代量。在製作Step時,嘗試增加位置和/或速度迭代。同時檢查你是否使用了固定的時間步長(通常它會給出更好的結果)。而且你的矛也會迅速移動,嘗試啓用連續物理並將矛身設置爲子彈(b2BodyDef屬性)。

3

嘗試關閉睡覺......

bool doSleep = false; 
_world = new b2World(gravity, doSleep); 

是我在基於Box2D的遊戲之一也有類似的問題,這個「功能」是什麼原因造成的。

+0

謝謝,它解決了我在其中一個遊戲中遇到的問題,那就是我試圖在靜態地面上移動一個動態物體 –

+0

肯定地幫助我解決GravityScale中的一個問題。 –

2

注意,在cocos2d的最新版本,你需要使用以下,以防止粘連行爲:

_world->SetAllowSleeping(false);