Swift + Physics:碰撞时错误的angular度计算

我有一个简单的SpriteKit应用程序与墙壁和一个球。 两个都设置了SKPhysicsBody

当我向一个方向施加一个力时,我认为球在碰撞时以相同的angular度在墙上reflection,而在相反的方向上。

但有时我看到这个angular度很奇怪。 我玩了很多所有的physicsBody属性,但无法修复它。 有时第一reflection看起来不错,但是第三或第六reflection有时候是错误的。

我从不同的post看,人们有点自我计算“正确的方向”。 但是我无法想象SpriteKits物理引擎是不行的。

检查我的附加图像,了解我的意思。 有人可以帮忙吗? 我不想开始使用Swift的Box2d,因为这看起来对于我来说很难融入到Swift中。

SpriteKit exxted和实际发生的事情

这是我的GameScene.swift文件中的physicsWorld init,其中所有元素都添加到了:

 self.physicsWorld.gravity = CGVectorMake(0, 0) 

添加我所有的代码会太多,所以我添加了重要的部分。 希望它足以进行分析。 像球,墙的所有元素都是SKSpriteNode

这是球的physicsBody代码:

 self.physicsBody = SKPhysicsBody(circleOfRadius: Constants.Config.playersize+self.node.lineWidth) self.physicsBody?.restitution = 1 self.physicsBody?.friction = 0 self.physicsBody?.linearDamping = 1 self.physicsBody?.allowsRotation = false self.physicsBody?.categoryBitMask = Constants.Config.PhysicsCategory.Player self.physicsBody?.collisionBitMask = Constants.Config.PhysicsCategory.Wall | Constants.Config.PhysicsCategory.Enemy self.physicsBody?.contactTestBitMask = Constants.Config.PhysicsCategory.Wall | Constants.Config.PhysicsCategory.Enemy 

这是墙的物理学体:

 el = SKSpriteNode(color: UIColor.blueColor(), size: CGSize(width: Constants.Config.wallsize, height: Constants.Config.wallsize)) el.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: Constants.Config.wallsize, height: Constants.Config.wallsize)) el.physicsBody?.dynamic = false el.physicsBody?.categoryBitMask = Constants.Config.PhysicsCategory.Wall el.physicsBody?.collisionBitMask = Constants.Config.PhysicsCategory.Player el.physicsBody?.contactTestBitMask = Constants.Config.PhysicsCategory.Player 

最后,我只是把球的physicsBody上的applyImpulse函数physicsBody物理模拟。

另外检查我附加的第二个图像/ gif。 它显示了一个简单的skphysics应用程序没有任何特殊参数化的边缘碰撞问题。 只是一个有一个球的矩形,一个向量作为冲动应用。

在这里输入图像说明

下面是我使用appzYourLife解决scheme完整的非工作代码。

 class GameScene: SKScene { private var ball:SKShapeNode! override func didMoveToView(view: SKView) { let screen = UIScreen.mainScreen().bounds let p = UIBezierPath() p.moveToPoint(CGPointMake(0,0)) p.addLineToPoint(CGPointMake(screen.width,0)) p.addLineToPoint(CGPointMake(screen.width, screen.height)) p.addLineToPoint(CGPointMake(0,screen.height)) p.closePath() let shape = SKShapeNode(path: p.CGPath) shape.physicsBody = SKPhysicsBody(edgeLoopFromPath: p.CGPath) shape.physicsBody?.affectedByGravity = false shape.physicsBody?.dynamic = false shape.strokeColor = UIColor.blackColor() self.addChild(shape) ball = SKShapeNode(circleOfRadius: 17) ball.name = "player" ball.position = CGPoint(x: 20, y: 20) ball.fillColor = UIColor.yellowColor() ball.physicsBody = SKPhysicsBody(circleOfRadius: 17) ball.physicsBody?.angularDamping = 0 ball.physicsBody?.linearDamping = 0 ball.physicsBody?.restitution = 1 ball.physicsBody?.friction = 0 ball.physicsBody?.allowsRotation = false self.addChild(ball) self.ball.physicsBody?.applyImpulse(CGVector(dx: 2.4, dy: 9.7)) } 

我刚刚意识到我的球精灵的质量和密度是零。 为什么? 即使设置它保持在零。

 Since i cannot imagine this is some unknown bug in SpriteKits physics engine, i very hope someone can help me here as this is a full stopper for me. 

这是 SpriteKits物理引擎中的(已知的)错误。 但是有时候玩这些值会让这个bug消失,例如,每次碰到墙壁时都要试着改变球的速度(即使是小的值)。

这里列出了另一个解决scheme: Swift中的SpriteKit物理学 – 球滑向墙而不是reflection

(和你一样的问题,从2014年起,仍然没有修复)

SpriteKit工作正常

我创build了一个简单的项目,它工作正常。

在这里输入图像说明

问题

正如@Sulthan已经在评论中build议,我认为你的代码中的问题是这一行

 el.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: Constants.Config.wallsize, height: Constants.Config.wallsize)) 

这里不是为你的场景创build物理边界,而是创build一个矩形的物理体,它与Ball的物理体重叠,产生不切实际的行为。

要创build我的场景的物理边界,我只是使用这个

 physicsBody = SKPhysicsBody(edgeLoopFromRect: frame) 

完整的代码

顺便说一下,这是我的项目的完整代码

 class GameScene: SKScene { override func didMoveToView(view: SKView) { let ball = Ball() ball.position = CGPoint(x:frame.midX, y:frame.midY) addChild(ball) physicsBody = SKPhysicsBody(edgeLoopFromRect: frame) ball.physicsBody!.applyImpulse(CGVector(dx:50, dy:70)) physicsWorld.gravity = CGVector(dx:0, dy:0) } } class Ball: SKSpriteNode { init() { let texture = SKTexture(imageNamed: "ball") super.init(texture: texture, color: .clearColor(), size: texture.size()) let physicsBody = SKPhysicsBody(circleOfRadius: texture.size().width/2) physicsBody.restitution = 1 physicsBody.friction = 0 physicsBody.linearDamping = 0 physicsBody.allowsRotation = false self.physicsBody = physicsBody } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } 

我也在scene.scaleMode = .ResizeFill使用了scene.scaleMode = .ResizeFill