0
votes

I'm trying to create a billiards game with SpriteKit but am having a problem when it comes to the physics part of it. I'm trying to set it up so when a ball hits another ball the ball being hit bounces off and eventually slows down and stops just like in billiards. I'm using the .sks file and have all three balls using a bounding circle body type with their friction, lin. damping and ang. damping set to 0. The restitution is set to 1. As of right now when a ball is touched it moves incredibly slow and when two balls hit each other they just kind of slide against each other. It's like there is no velocity. This is my code so far:

   let blueBallName = "blueBall"
    let orangeBallName = "orangeBall"
    let pokeBallName = "pokeBall"

    let blueBallCategory : UInt32 = 0x1 << 0
    let orangeBallCategory : UInt32 = 0x1 << 1
    let pokeBallCategory : UInt32 = 0x1 << 2
    let borderCategory : UInt32 = 0x1 << 3


    class PoolScene: SKScene, SKPhysicsContactDelegate {

      var ballPoke : SKSpriteNode?
      var ballBlue : SKSpriteNode?
      var ballOrange : SKSpriteNode?

      var isFingerOnBlueBall = false


      override func didMove(to view: SKView) {

        let borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
        borderBody.friction = 0
        self.physicsBody = borderBody

        self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
        physicsWorld.contactDelegate = self

        ballBlue = childNode(withName: blueBallName) as? SKSpriteNode
        ballOrange = childNode(withName: orangeBallName) as? SKSpriteNode
        ballPoke = childNode(withName: pokeBallName) as? SKSpriteNode


        ballBlue?.physicsBody?.categoryBitMask = blueBallCategory
        ballOrange?.physicsBody?.categoryBitMask = orangeBallCategory
        ballPoke?.physicsBody?.categoryBitMask = pokeBallCategory
        borderBody.categoryBitMask = borderCategory


      }

      //Determines which ball user is touching
      override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        let touch = touches.first
    let touchLocation = touch!.location(in: self)

    if let body = physicsWorld.body(at: touchLocation) {
      if body.node!.name == blueBallName {
        print("Blue ball touched")
        isFingerOnBlueBall = true

        let dragBallAction = SKAction.move(to: CGPoint(x: touchLocation.x, y: touchLocation.y), duration: 0.5)

        ballBlue?.run(dragBallAction)


      }
    }
  }
      }

          override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

            isFingerOnBlueBall = false

          }

      func didBegin(_ contact: SKPhysicsContact) {
        // 1.
        var firstBody: SKPhysicsBody
        var secondBody: SKPhysicsBody
        // 2.
        if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
          firstBody = contact.bodyA
          secondBody = contact.bodyB
        } else {
          firstBody = contact.bodyB
          secondBody = contact.bodyA
        }
        // 3.
        if firstBody.categoryBitMask == blueBallCategory && secondBody.categoryBitMask == orangeBallCategory {
          print("Hit Orange ball. First contact has been made.")
        }
      }
    }
1
Yea, I tried the replies to that question but they didn't workSwiftyJD

1 Answers

2
votes

The action you're doing is just the MoveTo action so your sprite will just try and move there constantly. Try doing the SKAction apply force, this will apply a force to the ball in the direction you want it to move to but will not 'force' it to go to on particular location in your scene, the physics engine should take care of the rest. Aside from that, I dont see that you set collision bit masks to any of your balls, if you want them to collide with eachother you should set for example blueBall.collisionBitMask = orangeBallCategory and vice versa, although this may not be necessary for something simple like this yet so it may work without it.