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

时间:2016-08-07 15:46:06

标签: ios swift sprite-kit physics

我有一个简单的SpriteKit应用程序,带有墙壁和球。两者都设置为SKPhysicsBody

当我向一个方向施加一个力时,我希望球在碰撞时以相同的角度在墙壁上反射,但方向相反。

但有时我看到角度很奇怪。我玩了很多physicsBody属性,但无法解决它。有时第一次反射看起来很好,但第三次或第六次反射,有时第一次反射是错误的角度。

我从不同的帖子中读到,人们有点自我计算"正确的方向"。但我无法想象SpriteKits物理引擎无法做到这一点。

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

SpriteKit expexted and what is actually happening

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

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

添加我的所有代码会太多,所以我添加了重要的部分。希望它足以分析。所有元素,如球,墙都是SKSpriteNode&#39>

这是球的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函数,使其在物理模拟中移动。

还要检查我附加的第二张图片/ gif。它使用简单的skphysics应用程序显示边缘碰撞问题,没有任何特殊参数化。只是一个带有球的矩形,一个矢量用作冲动。

enter image description here

使用appzYourLife中的解决方案继承我的完整非工作代码。

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))
}

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

2 个答案:

答案 0 :(得分:5)

SpriteKit工作正常

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

enter image description here

问题

正如 @Sulthan 已在评论中提出,我认为代码中的问题就是这一行

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

在这里,您不是为场景创建物理边框,而是创建一个矩形物理主体,它与Ball的物理主体重叠,产生不切实际的行为。

要创建场景的物理边框,我只需使用此

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内使用了GameViewController.swift

答案 1 :(得分:4)

<p:tooltip escaped="false" globalSelector="a,:input,:button,span" />

它是 SpriteKits物理引擎中的(已知)错误。但有时只是玩这些值会使这个错误消失 - 例如,每当它撞到墙壁时尝试改变球的速度(即使是很小的值)。

此处列出了另一种解决方案: SpriteKit physics in Swift - Ball slides against wall instead of reflecting

(与你的问题相同,已经从2014年开始,仍未解决..)