【问题标题】:SKSpriteNode losing velocity upon collisionSKSpriteNode 在碰撞时失去速度
【发布时间】:2016-08-29 17:01:49
【问题描述】:

我正在制作一个 iOS 应用程序,但遇到了一些物理问题。从下面的 .GIF 可以看出,当我旋转六边形并且球以一定角度撞击矩形时,它会失去一些速度并且不会反弹得那么高。这是因为分享here的原因(主要是因为我限制了小球的水平位置,它只是在击球时使用垂直速度,从而失去速度)。

我终其一生都无法找到解决此问题的解决方案。有人有什么想法吗??

Ball 节点代码:

func createBallNode(ballColor: String) -> SKSpriteNode {
    let ball = SKSpriteNode(imageNamed: ballColor)
    ball.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame)+30)
    ball.zPosition = 1

    ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width/2)
    ball.physicsBody?.affectedByGravity = true
    ball.physicsBody?.restitution = 1
    ball.physicsBody?.linearDamping = 0
    ball.physicsBody?.friction = 0

    ball.physicsBody?.categoryBitMask = ColliderType.Ball.rawValue
    ball.physicsBody?.contactTestBitMask = ColliderType.Rect.rawValue
    ball.physicsBody?.collisionBitMask = ColliderType.Rect.rawValue

    let centerX = ball.position.x
    let range = SKRange(lowerLimit: centerX, upperLimit: centerX)

    let constraint = SKConstraint.positionX(range)
    ball.constraints = [constraint]

    return ball
}

【问题讨论】:

  • 您是否尝试过您发布的链接中的解决方案?似乎对我有意义?为什么它没有帮助您解决问题?
  • @hamobi 它没有解决我的问题。当从矩形的一个角度反弹时,球仍然会失去高度。
  • 你确定你需要使用碰撞来完成你想要完成的事情吗?看起来你只是想移动球下的六边形并匹配颜色..为什么不做一个永不改变的重复弹跳动作
  • @hamobi 那绝对是理想的!不知道我将如何实现它以使其看起来更逼真。当我之前尝试过时,动作非常用力和波涛汹涌。看起来一点也不自然。

标签: ios iphone swift xcode sprite-kit


【解决方案1】:

是的,问题可能是球在未完全“对齐”时撞击六边形造成的。在这种情况下,球会失去垂直速度而转向水平轴。

既然你想要一个“离散逻辑”,我相信在这种情况下你应该避免物理(至少对于弹跳部分)。重复一个垂直移动球的SKAction 会容易得多。

示例

我准备了一个简单的例子

class GameScene: SKScene {

    override func didMove(to view: SKView) {
        super.didMove(to: view)
        let ball = createBallNode()
        self.addChild(ball)
    }

    func createBallNode() -> SKSpriteNode {
        let ball = SKSpriteNode(imageNamed: "ball")
        ball.position = CGPoint(x: frame.midX, y: frame.minY + ball.frame.height / 2)

        let goUp = SKAction.move(by: CGVector(dx: 0, dy: 600), duration: 1)
        goUp.timingMode = .easeOut

        let goDown = SKAction.move(by: CGVector(dx: 0, dy: -600), duration: 1)
        goDown.timingMode = .easeIn

        let goUpAndDown = SKAction.sequence([goUp, goDown])
        let forever = SKAction.repeatForever(goUpAndDown)
        ball.run(forever)
        return ball
    }
}

更新

如果您需要在每次球接触六边形底部时执行检查,您可以使用此代码

class GameScene: SKScene {

    override func didMove(to view: SKView) {
        super.didMove(to: view)
        let ball = createBallNode()
        self.addChild(ball)
    }

    func createBallNode() -> SKSpriteNode {
        let ball = SKSpriteNode(imageNamed: "ball")
        ball.position = CGPoint(x: frame.midX, y: frame.minY + ball.frame.height / 2)

        let goUp = SKAction.move(by: CGVector(dx: 0, dy: 600), duration: 1)
        goUp.timingMode = .easeOut

        let goDown = SKAction.move(by: CGVector(dx: 0, dy: -600), duration: 1)
        goDown.timingMode = .easeIn

        let check = SKAction.customAction(withDuration: 0) { (node, elapsedTime) in
            self.ballTouchesBase()
        }

        let goUpAndDown = SKAction.sequence([goUp, goDown, check])
        let forever = SKAction.repeatForever(goUpAndDown)
        ball.run(forever)
        return ball
    }

    private func ballTouchesBase() {
        print("The ball touched the base")
    }
}

正如您现在所见,每次球位于 y 坐标下方时,都会调用方法 ballTouchesBase。这是添加六边形颜色检查的正确位置。

【讨论】:

  • 是的,我同意。他可能需要也可能不需要物理,这取决于他想要完成的工作。
  • 我认为这也是最简单的。但是,当我尝试使用 SKActions 时,球的运动非常“强迫”,看起来一点也不现实……:/我想做的只是让球从底部矩形反弹,如果球颜色匹配矩形,球改变颜色,你需要再次旋转到当前颜色。
  • @JimmyLee:那是因为您需要正确设置timingMode 属性。看看我的代码。
  • @appzYourLife 正在查看它。
  • @appzYourLife 好的,我非常接近......只需要找出 SKAction.move(by: CGVector(dx: 0, dy: 600), duration: 1) 部分的正确数字。 .
猜你喜欢
  • 1970-01-01
  • 2018-09-03
  • 1970-01-01
  • 1970-01-01
  • 2017-05-21
  • 2015-10-06
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多