【问题标题】:Prevent the parent node from being affected by child physics body in SpriteKit防止父节点受到SpriteKit中子物理体的影响
【发布时间】:2014-09-26 02:39:52
【问题描述】:

我是一名长期的 Web 开发人员,但这是我第一次制作游戏或使用 Objective C。到目前为止,我真的(真的!)喜欢使用 Objective C 并且在我的游戏上已经取得了很大进展。提前感谢您的帮助!

我正在尝试让 3 个 SKSpriteNode 的尖刺球在英雄被拾取后围绕我的英雄船(见图)旋转一圈。在我将物理体添加到球之前,所有的外观和动画都很棒,这是必需的,这样它们才能与怪物发生碰撞。我希望英雄飞船不受附加物理实体的影响,以便英雄移动可以保持平稳和恒定——我正在移动英雄:

    [self.heroShip.physicsBody applyForce:CGVectorMake(moveByX, moveByY)];.

这里没有物理实体。我将 3 个子节点附加到锚节点,将锚节点附加到英雄船,然后旋转锚。下面的动画看起来和我想要的完全一样。

    SKSpriteNode * spikeballAnchor = [[SKSpriteNode alloc] init];

    SKSpriteNode * spikeball1   = [SKSpriteNode spriteNodeWithImageNamed:@"spikeball"];
    spikeball1.name             = HERO_SPIKEBALL;
    spikeball1.position         = CGPointMake(100, 0);
    [spikeballAnchor addChild:spikeball1];

    SKSpriteNode * spikeball2   = [SKSpriteNode spriteNodeWithImageNamed:@"spikeball"];
    spikeball2.name             = HERO_SPIKEBALL;
    spikeball2.position         = CGPointMake(-50, 86);
    [spikeballAnchor addChild:spikeball2];

    SKSpriteNode * spikeball3   = [SKSpriteNode spriteNodeWithImageNamed:@"spikeball"];
    spikeball3.name             = HERO_SPIKEBALL;
    spikeball3.position         = CGPointMake(-50, -86);
    [spikeballAnchor addChild:spikeball3];

    [spikeballAnchor runAction:[SKAction repeatActionForever:[SKAction rotateByAngle:(M_PI_2 * 2) duration:1]]];

    [self.heroShip addChild:spikeballAnchor];

但尖刺球需要与敌方怪物相撞!当我将以下物理体添加到尖刺球时,它会迅速飞出轨道。

    SKSpriteNode * spikeball1   = [SKSpriteNode spriteNodeWithImageNamed:@"spikeball"];
    spikeball1.name             = HERO_SPIKEBALL;
    spikeball1.position         = CGPointMake(100, 0);
    spikeball1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:spikeball1.size];
    spikeball1.physicsBody.categoryBitMask    = spikeballCategory;
    spikeball1.physicsBody.contactTestBitMask = monsterCategory;
    spikeball1.physicsBody.collisionBitMask   = defaultCategory;
    [spikeballAnchor addChild:spikeball1];

好的。因此,我几乎尝试了所有我能想到的东西,并在网上搜索了解决方案。给出我尝试过的所有示例会占用大量空间,因此我将进行总结。

我尝试将锚定为物理体,将尖刺球固定在锚上,然后将锚固定在英雄身上。没有运气。

我尝试在锚点和球之间创建 SKPhysicsJointLimit、SKPhysicsJointPin 和 SKPhysicsJointFixed。在所有这些钻机中,尖刺球的物理特性使船离开。我尝试将锚和球的质量设置为零。奇怪的是,即使没有质量,它们似乎仍然会影响船的运动。此外,我尝试将物理体的摩擦、线性阻尼和角度阻尼设置为零。

此外,只有在设置物理体之前添加子节点时,关节似乎才起作用。

以下是我得到的最接近/最好的结果(例如一个钉球),但我无法让球的旋转不影响船!当我运行此程序时,球不会始终如一地旋转(船的运动加速并减慢围绕关节的旋转),并且球的运动会使船的运动停止,从而对船产生不良的钟摆效应。这需要在 2 和 1 球被摧毁时使用。

    SKSpriteNode * spikeballAnchor = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(10, 10)];
    [self.heroShip addChild:spikeballAnchor];
    spikeballAnchor.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:spikeballAnchor.size];
    spikeballAnchor.physicsBody.pinned = true;
    spikeballAnchor.name = HERO_SPIKEBALL;

    SKSpriteNode * spikeball1   = [SKSpriteNode spriteNodeWithImageNamed:@"spikeball"];
    spikeball1.name             = HERO_SPIKEBALL;
    spikeball1.position         = CGPointMake(100, 0);
    [spikeballAnchor addChild:spikeball1];
    spikeball1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:spikeball1.size];
    spikeball1.physicsBody.categoryBitMask    = spikeballCategory;
    spikeball1.physicsBody.contactTestBitMask = monsterCategory;
    spikeball1.physicsBody.collisionBitMask   = defaultCategory;

    [spikeballAnchor runAction:[SKAction repeatActionForever:[SKAction rotateByAngle:(M_PI_2 * 2) duration:1]]];

    SKPhysicsJointFixed * joint = [SKPhysicsJointFixed jointWithBodyA:spikeballAnchor.physicsBody bodyB:spikeball1.physicsBody anchor:spikeballAnchor.position];
    [self.physicsWorld addJoint:joint];

我曾考虑尝试独立于船移动锚及其子节点,但我担心它们会不同步,并且如果锚不是英雄的孩子。但是,如果我能保持他们的立场完全同步,那就不会破坏交易。

很抱歉这么冗长。非常感谢任何帮助!

// Collision Bits

static const int defaultCategory            = 0;
static const int projectileCategory         = 1;
static const int spikeballCategory          = 2;
static const int monsterCategory            = 3;
static const int heroCategory               = 4;
static const int pickupCategory             = 5;
static const int boundariesCategory         = 50;

【问题讨论】:

  • 由于您希望 Spike Balls 的物理体检测接触而不是碰撞,因此您需要将 collisionBitMask 设置为 0。另外,您是如何声明类别位掩码值的?
  • 是的。我将“defaultCategory”常量设置为 0。我会将我的 bitMask 添加到帖子中。我想我找到了一个可行的解决方案。将质量设置为spikeball1.physicsBody.mass = 0.000001f; 会使对飞船的影响完全不明显。有人可以向我解释为什么将质量设置为零会完全停止母英雄船的运动吗? spikeball1.physicsBody.mass = 0.000000f;
  • 为了记录,有人删除了他们建议我实际上尝试独立于英雄船移动尖刺球锚并保持其位置同步的回复:- (void) didSimulatePhysics { self.spikeballAnchor.position = self.heroShip.position; }。我还没有尝试过,但这似乎是另一个很好的解决方案。他们建议我将英雄船和锚都附加到单独的 SKNode 层,这样我就可以在船被破坏时同时移除它们。感谢发布该内容的用户!
  • 最好将工作解决方案发布为答案并接受它。您也可以回答自己的问题。

标签: objective-c sprite-kit game-physics


【解决方案1】:

不是一个问题的答案,所以有点离题,但我在您的代码中看到另一个问题:您的类别是相交的,因为它们被用作位掩码。我的意思是,您的monsterCategory 包括spikeballCategoryprojectileCategory,因为在二进制3 = 1 | 2 中。

  monsterCategory      3   0b00000011  
  projectileCategory   1   0b00000001  
  spikeballCategory    2   0b00000010  

所以你可能会注意到你的尖刺球可以像怪物一样行动,反之亦然,而射弹可以像怪物一样行动,反之亦然。

【讨论】:

  • 是的,我在示例中看到了这一点。我需要修复它。这个项目被搁置了,而我正在完成一些其他的事情。当我把它捡起来时,我会看看这个。谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多