多层中的 SpriteKit 物理实体碰撞
Posted
技术标签:
【中文标题】多层中的 SpriteKit 物理实体碰撞【英文标题】:SpriteKit Physics Bodies Collisions in Multiple Layers 【发布时间】:2014-12-16 02:36:13 【问题描述】:好的,所以我正在为太空爆破游戏编写代码,而且除了这些关键问题之外,一切似乎都很顺利。
首先,我添加了一艘宇宙飞船(带有 PhysicsBody)作为 self 的子节点(GameScene)。
然后我添加了一个背景层作为节点,也作为 self 的子节点,在飞船后面,并通过操纵杆控制在飞船后面移动背景来模拟运动。
我添加了一个带有边界物理 Edge Loop 主体的节点,这样背景就不会超出船,并将该节点添加为 bgLayer 的子节点。
我有宇宙飞船要射击的物体,但我希望它们像背景一样移动,所以我将它们添加为 bgLayer 的子对象。
当然,飞船开火时我需要激光,所以我添加了这个以及 bgLayer 的一个子节点。
_spaceship.physicsBody = (custom physicsBody code);
[self addChild:_spaceship];
_bgLayer = [SKNode node];
[self addChild:_bgLayer];
_bounds = [SKNode node];
_bounds.physicsBody = (physicsBody edgeLoop code);
[_bgLayer addChild:_bounds];
_otherObjects.physicsBody = (custom physicsBody code);
[_bgLayer addChild:_otherObjects];
_laser.physicsBody = (custom physicsBody code);
[_bgLayer addChild:_laser];
一切都很好,背景没有移动到飞船之外,其他物体随着背景的移动而移动,并且激光在被召唤时会发射。
我的第一个大难题是当我的激光发射时,它不会随着背景的移动而移动,而是背景在它后面移动。我可能会凑合,但如果激光总是与船平行移动,那看起来很有趣。这对我来说似乎很奇怪,因为我将激光添加为 _bgLayer 的子项。
其次,我的激光器的physicsBody 似乎无法识别EdgeLoop 体,而是直接穿过它。此外,我的宇宙飞船的physicsBody 似乎可以识别EdgeLoop 主体,但它不能识别其他属于_bgLayer 子对象的对象。
不是同一层子级的物理实体是否可以相互识别? 为什么我的激光与同一层的其他子激光的行为不同?
【问题讨论】:
物理引擎中没有层。每个场景有一个物理世界。您只需要设置碰撞类别之类的东西,并确保设置所有定义对象是否以及如何参与物理的东西。 我很抱歉没有在我的编码示例中添加这个,但我确实为它们设置了类别和碰撞位掩码,但激光似乎忽略了这些设置。 【参考方案1】:通过改变位置来移动世界会影响
-
拥有物理身体的孩子
没有物理身体的孩子
通过施加力/脉冲或通过设置其速度来移动世界
-
没有物理身体的孩子
除了通过设置速度来移动世界,您可以向世界添加一个相机(带有物理体的SKNode
),通过设置速度来移动相机,然后将世界的位置更新为中心相机。您可以在didFinishUpdate
方法中将相机居中。
【讨论】:
我很抱歉没有在我的编码示例中添加这个,但我确实使用 setVelocity 方法设置了激光。我的激光确实与我提到的其他物体相互作用,但与 edgeLoop 没有相互作用。你最后的评论让我很感兴趣。我可以简单地从激光矢量的 dx 和 dy 中减去背景矢量的 dx 和 dy 吗? 实际上,如果将激光添加到世界节点,它应该可以适当移动而无需任何调整。 我也是这么想的。但是,它仍然相对于场景而不是 _bgLayer 节点移动。 激光是子弹还是光流(即线)?我已经用子弹实现了滚动背景,当我滚动背景图像时,子弹会正确移动。例如,如果我向背景图像中的目标射击,无论我滚动多少背景,子弹都会朝着该目标移动。 它更像是一颗子弹。给我一分钟,我会发布我的激光代码。【参考方案2】:-(void)fireLaser
_laser = [SKSpriteNode spriteNodeWithImageNamed: [NSString stringWithFormat:@"blueLaser"]];;
_laser.zRotation = _spaceShip.zRotation;
CGVector rotationVector = RadiansToVector(_spaceShip.zRotation);
_laser.position = (Custom code for positioning the laser just in front of the spaceship);
_laser.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_laser.size];
[_bgLayer addChild:_laser];
_laser.physicsBody.velocity = CGVectorMake(rotationVector.dx * LASER_SPEED, rotationVector.dy * LASER_SPEED);
[self fireLaser] 在触摸特定 SpriteNode 时在 touchesBegan 中调用。 激光发射得很漂亮,但不会随着背景滚动,而是相对于宇宙飞船移动。使用 PhysicsBody 滚动背景,当操纵杆移动时调用 setVelocity 方法,从而模拟宇宙飞船的运动,而实际上宇宙飞船永远不会离开屏幕的中心。物理类别可防止背景物理主体与任何物体发生碰撞。 LASER_SPEED 只是一个静态常量浮点数。
【讨论】:
以上是关于多层中的 SpriteKit 物理实体碰撞的主要内容,如果未能解决你的问题,请参考以下文章