SKSpriteKit maintaining constant velocity after co

2019-09-05 02:07发布

问题:

I am attempting to make my first iOS app and currently running into an issue.

In my game, when the ball bounces I want it to bounce back to the same height and with the same velocity. Currently it does that just fine. However, when I rotate the hexagon and it hits an angle, it ends up losing speed and not bouncing to the same height.

So my question is: How do I force the ball to maintain the same velocity upon collision?

Here is the code for my Ball node:

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
}

Below is a GIF explaining the problem in a visual form:

回答1:

The issue is that if the ball collides at an angle, its total velocity is split between the vertical and horizontal components of the new velocity vector. Because you constrained the motion of the ball's horizontal position, the horizontal velocity is lost and the ball doesn't bounce as high.

One possible solution is to override didSimulatePhysics in your scene, and check if the ball's velocity is not sufficient to make it reach the desired height. If it isn't, increase its velocity so it will.

let neededVelocity = sqrt(2 * physicsWorld.gravity.dy * (intendedHeight - ball.posiiton.y))
if ball.physicsBody.velocity.dy < neededVelocity && ball.physicsBody.velocity.dy > 0 {
    ball.physicsBody.velocity = CGVector(dx: 0, dy: neededVelocity)
}


回答2:

I'm not sure if you are still looking for an answer, but...

If you always want the ball to bounce on the same vertical, then why don't you:

  • Create a single horizontal SKShapeNode where the bottom line of your hexagon is.
  • Set the fill and stroke color to 'clear'.
  • Set physics body for it - so that the ball will bounce on it.
  • Remove physic bodies from your colored hexagon shapes.

This'll avoid any 'bouncing on angles' issues.

If you want to detect contact with the relevant hex shape, you could keep track of what is at the bottom, or:

  • Move the new physics box 1 point down.
  • Add contact mask to your hexagon shapes (not 'collision') so you get contacts but no physical collision.