Jimmy Lee
Jimmy Lee

Reputation: 215

SKSpriteNode losing velocity upon collision

I am making an iOS app and running into some problems with physics. As you can tell by the .GIF below, when I rotate the hexagon and the ball hits the rectangle at an angle, it loses some of its velocity and doesn't bounce as high. This is because of the reason shared here (basically because I am constraining the balls horizontal position, it's only using the vertical velocity when hitting an angle, thus losing speed).

I cannot for the life of me figure out a solution to fix this problem. Does anybody have any ideas??

Code for 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
}

enter image description here

Upvotes: 4

Views: 309

Answers (1)

Luca Angeletti
Luca Angeletti

Reputation: 59496

Yes, the problem is probably causes by the ball hitting the hexagon when it is not perfectly "aligned". In this case the ball loses vertical speed in favour of the horizontal axis.

Since you want a "discrete logic" I believe in this scenario your should avoid physics (at least for the bouncing part). It would be much easier repeating an SKAction that moves the ball vertically.

Example

I prepared a simple example

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

enter image description here

Update

If you need to perform a check every time the ball touches the base of the Hexagon you can use this code

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

As you can see now the method ballTouchesBase is called every time the ball is a te lower y coordinate. This is the right place to add a check for the color of your hexagon.

Upvotes: 1

Related Questions