Sprite Kit - 字符和上电冲突/接触检测,不改变字符方向

时间:2014-02-07 23:23:33

标签: c# ios7 xamarin.ios xamarin sprite-kit

我正在使用Sprite Kit编写一个基于物理的游戏。我能够处理主角和电源之间的联系。从屏幕上移除加电,我的模型更新并播放声音,正如预期的那样。但是,角色在接通电源时会改变方向。这是不希望的。我想让角色在通电时通过,并且不会因为碰撞而改变它。以下是我的一些代码,如果您需要更多帮助,请告诉我。

所有这些都是用C#中的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);
    }

我的PowerUp对象设置:

    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 个答案:

答案 0 :(得分:2)

您正在设置类别并联系回调位掩码,但您似乎没有设置collisionBitMask - 它保持默认值,因此您的角色设置为与任何东西发生碰撞并改变方向联系。

尝试明确设置玩家的碰撞位掩码(可能是Xamarin中的this.PhysicsBody.setCollisionBitMask?),说明此玩家应该与之进行物理碰撞的所有类别,并省略它应该通过的类别(PowerUp)。

答案 1 :(得分:1)

SKPhysicsBody 3个属性

categoryBitMask property
collisionBitMask 属性
contactTestBitMask 属性

在您的情况下,您需要逻辑碰撞 而不是物理碰撞
因此,与您一样,您需要设置contactTestBitMask,但您还需要将collisionBitMask设置为对象的categoryBitMask,并将SKPhysicsBody设置为动态({{ 1}}但它是默认值,所以你可以忽略它。)

我给你写了简单的构造代码(它更容易理解),但你可以将它改编为你的结构(使用内部/外部方法)。

碰撞位枚举:

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
} 

PowerUp对象设置:

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;
}