2014-02-07 39 views
0

我正在使用Sprite Kit編寫基於物理學的遊戲。我能夠處理主角和加電之間的聯繫。正如預期的那樣,屏幕上的電源消失,我的型號被更新並播放聲音。但是,角色在接通電源時會改變方向。這是不希望的。我希望讓角色能夠通過權力,而不會因碰撞而改變角色。這裏是我的一些代碼,讓我知道如果你需要更多的幫助。Sprite Kit - 字符和通電碰撞/接觸檢測,不改變字符方向

所有這些都是爲Xamarin.iOS編寫的。但是代碼與Objective-C計數器部分幾乎完全相同。讓我知道是否需要進一步解釋。並提前感謝您的幫助!

編輯:此外,這是在參考了遊戲,我在這個問題討論了建設:

Sprite Kit - Create arch path for SKSpriteNode given a swipe gesture

**的代碼! **

我的碰撞位枚舉:

public enum COLLISION_BITS : uint 
    { 
     Character = 1 << 0, 
     Background = 1 << 1, 
     Ground = 1 << 2, 
     BadGuy = 1 << 3, 
     PowerUp = 1 << 4, 
     Fan = 1 << 5 
    } 

我的角色對象設置:

public Character (SizeF size, PointF position) : base("character") 
    { 
     this.Name = CHARACTER_NAME; 
     this.Size = size; 
     this.Position = position; 
     this.PhysicsBody = SKPhysicsBody.BodyWithRectangleOfSize (this.Size); 
     this.PhysicsBody.Dynamic = true; 
     this.PhysicsBody.AffectedByGravity = true; 
     this.PhysicsBody.AllowsRotation = false; 
     this.PhysicsBody.Mass = 1.0f; 
     this.PhysicsBody.SetCategoryBitMask (COLLISION_BITS.Character); 
     this.PhysicsBody.SetContactTestBitMask (COLLISION_BITS.Ground); 
     this.PhysicsBody.SetContactTestBitMask (COLLISION_BITS.BadGuy, false); 
     this.PhysicsBody.SetContactTestBitMask (COLLISION_BITS.PowerUp, false); 
     this.PhysicsBody.SetContactTestBitMask (COLLISION_BITS.Fan, false); 
    } 

我的上電對象設置:

private void SetupPowerUp(SizeF size, PointF position) 
    { 
     this.Size = size; 
     this.Position = position; 

     this.PhysicsBody = SKPhysicsBody.BodyWithRectangleOfSize (this.Size); 
     this.PhysicsBody.Dynamic = false; 
     this.PhysicsBody.AffectedByGravity = false; 
     this.PhysicsBody.AllowsRotation = false; 
     this.PhysicsBody.Mass = 0f; 
     this.PhysicsBody.SetCategoryBitMask (COLLISION_BITS.PowerUp); 
    } 

,我把我的位擴展方法處理:

public static void SetContactTestBitMask(this SKPhysicsBody body, COLLISION_BITS bits, bool overwrite = true) 
    { 
     if (body == null) return; 

     if (overwrite) { 
      body.ContactTestBitMask = (uint)bits; 
     } else { 
      body.ContactTestBitMask |= (uint)bits; 
     } 
    } 

    public static void SetCategoryBitMask(this SKPhysicsBody body, COLLISION_BITS bits, bool overwrite = true) 
    { 
     if (body == null) return; 

     if (overwrite) { 
      body.CategoryBitMask = (uint)bits; 
     } else { 
      body.CategoryBitMask |= (uint)bits; 
     } 
    } 

    public static bool IsOfCategory(this SKPhysicsBody body, COLLISION_BITS bits, bool matchAll = false) 
    { 
     if (body == null) return false; 

     if (matchAll) { 
      return (body.CategoryBitMask & (uint)bits) == (uint)bits; 
     } else { 
      return (body.CategoryBitMask & (uint)bits) > 0; 
     } 
    } 

最後,我DidBeginContact方法:

public void HandleDidBeginContact(object sender, EventArgs args) 
    { 
     var contact = (SKPhysicsContact)sender; 
     SKPhysicsBody firstBody, secondBody; 

     if (contact.BodyA.CategoryBitMask < contact.BodyB.CategoryBitMask) { 
      firstBody = contact.BodyA; 
      secondBody = contact.BodyB; 
     } else { 
      firstBody = contact.BodyB; 
      secondBody = contact.BodyA; 
     } 

     // collected power up 
     if (firstBody.IsOfCategory(COLLISION_BITS. Character) && secondBody.IsOfCategory(COLLISION_BITS.PowerUp)) { 

      secondBody.Node.RemoveFromParent(); 
      GameModel.GatheredPowerUp(); 
      PowerUpCollisionSoundPlayer.Play(); 
     } 

     // other collision stuff for the other objects in the screen... 
     // ... 
    } 

回答

2

你設置的類別和聯繫回調位掩碼,但你似乎並不被設置collisionBitMask - 它保持它的默認值,所以你的角色被設置爲與任何東西碰撞並改變接觸方向。

嘗試明確設置玩家的碰撞位掩碼(可能在Xamarin中爲this.PhysicsBody.setCollisionBitMask?),指出該玩家應與其進行物理碰撞的所有類別,並省略其應通過的類別(PowerUp)。

+0

完美,就是這樣。我假設collisionBitMask的默認值是它不會與任何東西相沖突。儘管如此,仍然對collisionBitMask和contactTestBitMask的區別有點困惑。但是這幫助我讓它工作。謝謝! – Mike

1

還有3屬性SKPhysicsBody

categoryBitMask財產
collisionBitMask財產
contactTestBitMask財產

在你的情況,你想邏輯碰撞不是物理碰撞
所以,像你這樣,你需要設置contactTestBitMask但你也需要設置collisionBitMask到對象的categoryBitMask兩者SKPhysicsBody動態(this.PhysicsBody.Dynamic = true;但它是默認值,所以你可以忽略它)。我寫了你簡單的構造代碼(它更容易理解),但你可以將它調整到你的結構(使用內部/外部方法)。

碰撞位枚舉:

public enum COLLISION_BITS : uint 
{ 
    Character = 1 << 0, 
    Background = 1 << 1, 
    Ground = 1 << 2, 
    BadGuy = 1 << 3, 
    PowerUp = 1 << 4, 
    Fan = 1 << 5 
} 

Character對象設置:

public Character (SizeF size, PointF position) : base("character") 
{ 
    this.Name = CHARACTER_NAME; 
    this.Size = size; 
    this.Position = position; 
    this.PhysicsBody = SKPhysicsBody.BodyWithRectangleOfSize (this.Size); 
    this.PhysicsBody.AffectedByGravity = true; 
    this.PhysicsBody.AllowsRotation = false; 
    this.PhysicsBody.Mass = 1.0f; 
    this.PhysicsBody.CategoryBitMask = COLLISION_BITS.Character; 
    this.PhysicsBody.CollisionBitMask = COLLISION_BITS.Character; 
    this.PhysicsBody.ContactTestBitMask = COLLISION_BITS.PowerUp; 
} 

的上電對象設置:

private void SetupPowerUp(SizeF size, PointF position) 
{ 
    this.Size = size; 
    this.Position = position; 

    this.PhysicsBody = SKPhysicsBody.BodyWithRectangleOfSize (this.Size); 
    this.PhysicsBody.AffectedByGravity = false; 
    this.PhysicsBody.AllowsRotation = false; 
    this.PhysicsBody.Mass = 0f; 
    this.PhysicsBody.CategoryBitMask = COLLISION_BITS.PowerUp; 
    this.PhysicsBody.CollisionBitMask = COLLISION_BITS.PowerUp; 
    this.PhysicsBody.ContactTestBitMask = COLLISION_BITS.Character; 
} 
+0

感謝您的詳盡解答和代碼。瞭解不同類型的碰撞(邏輯與物理)是很好的。 – Mike