使用新的Sprite kit制作球体游戏

5

我正在尝试使用新的Sprite Kit在iOS 7上制作一个简单的永远弹跳的球体。 我设置了重力:

 scene.physicsWorld.gravity=CGVectorMake(0, -9);

关于球体,我进行了如下设置:

ball.physicsBody=[SKPhysicsBody bodyWithCircleOfRadius:17];
ball.physicsBody.mass=1;
ball.physicsBody.restitution=1;
ball.physicsBody.linearDamping=0;
ball.physicsBody.angularDamping=0;

这里的Ball只是一个SKSpriteNode。 但我有一个问题:每次它反弹回来时,它的位置会变得越来越高。在几分钟内,球几乎到达了屏幕顶部。 有人能帮忙解决这个问题吗?我只想让球每次反弹回到相同的位置(例如屏幕中间)。 谢谢。


尝试将向量(0,-9)改为(0,9),并告诉我发生了什么。 - erdekhayser
同样的问题,但现在球从屏幕顶部弹起(就像地面在顶部一样)。 - Alexander
这正是我认为会发生的事情。你是说每次弹跳,球都会弹得更高? - erdekhayser
没错,但我想让它以相同的高度弹跳。就像无限弹跳一样。 - Alexander
你有其他物体吗?如果有,它们的摩擦和恢复值设置为多少?你会对球施加任何力或以其他方式改变速度吗? - CodeSmile
显示剩余2条评论
2个回答

15

这里可能有两个问题:

  1. 当球弹跳时,涉及到两个物体的碰撞:球和它反弹的边缘环。为了在碰撞中不损失能量,你可能需要让两个物体都没有摩擦和恢复力。

  2. 即使这样做,很多物理引擎(包括SpriteKit)也会因为浮点舍入误差而遇到困难。我发现,当我希望一个物体在碰撞后保持恒定速度时,最好是强制它这样做 - 使用didEndContact:didSimulatePhysics处理程序来重置移动物体的速度,使其以与碰撞前相同的速度运动(但方向相反)。

如果只有一个球在上下弹跳,则可以轻松重置速度:只需取反速度向量的垂直分量即可:

ball.physicsBody.velocity = CGVectorMake(0, -ball.physicsBody.velocity.dy);
如果你要在一个倾斜的表面上弹跳,需要进行稍微复杂的计算:将速度向量归一化(即缩放使其大小为1.0),得到碰撞后的方向,然后再将其缩放以达到所需的速度。当我进行这种向量运算时,我喜欢将向量转换为GLKVector2,以便使用GLKit框架中的快速数学函数。
GLKVector2 velocity = GLKVector2Make(ball.physicsBody.velocity.dx, ball.physicsBody.velocity.dy);
GLKVector2 direction = GLKVector2Normalize(velocity);
GLKVector2 newVelocity = GLKVector2MultiplyScalar(direction, newSpeed);
ball.physicsBody.velocity = CGVectorMake(newVelocity.x, newVelocity.y);

谢谢!现在我也认为很多物理引擎都存在浮点数舍入误差的问题,就像你提到的那样。 - Alexander
所以第一次我尝试在didSimulatePhysics方法中对球进行限制,例如如果球的y位置高于305,我将其更改为300,但我认为这不是正确的做法。所以我决定遵循您的建议,在碰撞后将球的速度设置为负值,但与之前相同的值,并且它有效。 - Alexander
实际上,对我来说,在球上将恢复设置为1,在挡板上将其设置为0是有效的。 - Mariusz

0

很奇怪,但如果我设置:

 ball.physicsBody.linearDamping=0.02f;

看起来球的弹跳高度没有改变。


如果您长时间运行它,请查看是否会变慢。任何线性阻尼都可能导致它变慢。 - erdekhayser
我知道,但它并没有失去它的“能量”,我等了很久,大约30-40分钟。 - Alexander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接