Sprite Kit物理碰撞问题 [英] Sprite Kit Physics Collision Issue

查看:182
本文介绍了Sprite Kit物理碰撞问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一些碰撞问题。我有两个相同大小和质量的物体。当一个人碰到另一个静止的时候,我会得到正确的行为(图像中的灰色区域)。当我有两个彼此相邻的对象时,行为不太正确。 Spritekit结果在左边。预期/需要的结果是正确的。

I'm having an issue with some collisions. I have two objects equal size and mass. When one collides into another that is at rest I get the correct behavior (grey area in image). When I have two objects that are next to each other the behavior isn't quite right. Spritekit result on the left. Expected/needed result on right.

我想我知道发生了什么,但不知道该怎么做。如果对象是一个质量两倍的对象,那么spritekit行为将是正确的,但它们是单独的对象,最上面的对象应该采用传入粒子的速度。看起来它把它们视为一个对象。

I think I know what is going on, but not sure what to do about it. If the object was one object with twice the mass then the spritekit behavior would be correct, but they are separate objects and the uppermost one should take the velocity of the incoming particle. It seems that it treats them as one object.

我试图在两个人碰到一个小间隙之后作弊和缩小半径,但事情变得全部弄乱。有人知道我能在这做什么吗?谢谢。

I've tried cheating and shrinking the radius after the two are touching to put a small gap, but then things get all messed up. Does someone know what I can do here? Thanks.

推荐答案

简介



这绝对可以做到,而且没有复杂的必要的计算。 SpriteKit完全能够处理这种碰撞。我觉得你在这里误解了物理学。在物理学中有一个简单的规则要记住你正在破碎。这里用现实生活中的术语来说:

Brief introduction

This can definitely be done, and there are no complex calculations necessary. SpriteKit is perfectly capable of handling this collision. I think you're misunderstanding the physics in play here. There is one simple rule to keep in mind in physics that you are breaking. Speaking in real-life terms here:

没有两个对象可以在空间中占据相同的点。这也适用于部分对象。 任何两个物体的任何部分都不能占据太空中的同一点。考虑到这一点,我们可以说无论两个物体有多近,它们之间总有一些空间。

No two objects can occupy the same point in space. This goes for parts of objects as well. No parts of any two objects can occupy the same point in space. With this in mind, we can say that no matter how close two objects are, there is always some space between them.

换句话说,彼此相邻的两个对象之间的空间量必须大于零。 无论多么无限空间很小,它仍然必须存在。

In other words, the amount of space between two objects next to each other must be greater than zero. No matter how infinitely small that space is, it still has to be there.

你的根本问题是你在蓝色圆圈之间留下零空间。假设圆的半径为30,顶部圆的y位置为400.

Your underlying problem is that you've left zero space between the blue circles. Let's assume the circles have a radius of 30 and the top circle has a y-position of 400.

您定位中间圆的数学可能是 topCircle.position.y - (topCircle.height + middleCircle.height)/ 2 。由于您的圆圈半径相同(在我们的示例中为30),您可能将其简化为 topCircle.y - CIRCLE_DIAMETER 。如果您绝对定位圆圈,这可能是您在脑中执行的计算。

Your math for positioning the middle circle is likely topCircle.position.y - (topCircle.height + middleCircle.height) / 2. Since your circles are all the same radius (30 in our example), you probably simplified that to topCircle.y - CIRCLE_DIAMETER. If you positioned the circles absolutely, this is probably the calculation you performed in your head.

使用任一等式,当您插入数字时,y位置第二球达到340.

With either equation, when you plug in the numbers, the y-position of the second ball comes out to 340.

第一个等式: 400 - (60 + 60)/ 2 = 340 < br>
第二个等式: 400 - 60 = 340

注意:第一个等式更灵活,可以让你使用任何大小的圆圈而不是统一尺寸

这就是问题所在。现在应该很清楚,顶部圆圈的底部占据空间中与中间圆圈顶部相同的点。

Herein lies the problem. It should be clear by now that the bottom of the top circle is occupying the same point in space as the top of the top of the middle circle.

顶部圆圈: 400 - 30 = 370

中圈: 340 + 30 = 370

之间的空格: | 370 - 370 | = 0

这两个物理实体试图在空间中占据相同的点,因此合并为一个体,给你行为你看到了。

The two physics bodies are attempting to occupy the same point in space, and thus have merged into one body, giving you the behavior you're seeing.

如果只是添加一个点(或者更少)圈子之间的空间,你将得到你想要的行为。

注意:还要确保将每个圆圈的物理体的恢复原状设置为1

With all that being said, if you simply add a point (or less) of space between the circles, you will get the behavior you desire.
(Note: also make sure to set the restitution of each circle's physics body to 1)

这适用于任意数量的圈子。这是一个简单的示例场景,其中1个圆圈与其他4个圆圈接触,表现出这种行为。我在iPhone 6上运行了这个:

This works with any number of circles. Here's a simple example scene with 1 circle contacting 4 others that exhibits this behavior. I ran this on an iPhone 6:

#import "GameScene.h"

@interface GameScene()

@property (strong, nonatomic) NSArray *nodes;

@end


@implementation GameScene

#pragma mark - View Lifecycle
-(void)didMoveToView:(SKView *)view
{
    self.backgroundColor = [SKColor blackColor];

    [self createNodes];
    [self positionNodes];
    [self addNodes];
}

#pragma mark - Setup
- (void)createNodes
{
    // You could use SKShapeNode as well
    self.nodes = @[[SKSpriteNode spriteNodeWithImageNamed:@"circle"],
                   [SKSpriteNode spriteNodeWithImageNamed:@"circle"],
                   [SKSpriteNode spriteNodeWithImageNamed:@"circle"],
                   [SKSpriteNode spriteNodeWithImageNamed:@"circle"],
                   [SKSpriteNode spriteNodeWithImageNamed:@"circle"]];

    // Use this if you don't have a 30-radius circle image at hand
//    self.nodes = @[[SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(60, 60)],
//                   [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(60, 60)],
//                   [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(60, 60)],
//                   [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(60, 60)],
//                   [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(60, 60)]];

    for(SKSpriteNode *node in self.nodes)
    {
        node.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:30];
        node.physicsBody.affectedByGravity = NO;
        node.physicsBody.restitution = 1;
    }
}

- (void)positionNodes
{
    SKSpriteNode *node = self.nodes.firstObject;
    node.position = CGPointMake(300, 400);

    for(NSInteger i = 1; i < self.nodes.count - 1; i++)
    {
        SKSpriteNode *prevNode = node;
        node = self.nodes[i];
        node.position = CGPointMake(300, prevNode.position.y - (prevNode.frame.size.height + node.frame.size.height) / 2 - 1);
    }

    node = self.nodes.lastObject;
    node.position = CGPointMake(300, 100);

    // Above created nodes at these positions:
    // (300, 400);
    // (300, 339);
    // (300, 278);
    // (300, 217);
    // (300, 100);
}

- (void)addNodes
{
    for(SKSpriteNode *node in self.nodes)
    {
        [self addChild:node];
    }
}

#pragma mark - Touch Events
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    SKSpriteNode *node = self.nodes.lastObject;
    [node.physicsBody applyImpulse:CGVectorMake(0, 20)];
}

@end

这篇关于Sprite Kit物理碰撞问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆