精灵套件-角色和电源碰撞/接触检测不改变角色的方向



我正在使用Sprite Kit编写一个基于物理的游戏。我能够处理主角和通电之间的联系。屏幕上的电源被取消,我的型号被更新,声音被播放,正如预期的那样。但是,角色在接触电源时会改变方向。这是不可取的。我想让角色直接通过通电,而不是因为碰撞而改变路线。这是我的一些代码,如果你需要更多帮助,请告诉我。

所有这些都是用C#为Xamarin.iOS编写的。但代码与Objective-C计数器部分几乎完全相同。如果我需要进一步解释,请告诉我。并提前感谢您的帮助!

编辑:此外,这是参考我在这个问题中讨论的游戏:

精灵套件-在给定滑动手势的情况下为SKSpriteNode创建拱形路径

**致代码!**

我的冲突位枚举:

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...
// ...
}

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

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

SKPhysicsBody3个属性

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
} 

字符对象设置:

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

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