0

I am trying to make a sprite follow my finger using velocity so it doesn't phase through other sprite nodes, or push them around. I just want the sprite node, aka the ball, to simply hit the other sprite node and either bounce off or just simply hit it and sit there until its moved again.

At the moment I am using location based movement:

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in: self)
            ball.position.x = location.x
            ball.position.y = location.y
            print("x: \(ball.position.x), y: \(ball.position.y)")
        }
    }

how can I make it so it doesn't move around other sprite nodes and actually reacts with categoryBitMask elements?

I'm new to this whole thing. Hopefully you understand :)

REST OF MY CODE:

import SpriteKit
import GameplayKit

class GameScene: SKScene {

var ball = SKSpriteNode()
var danger1 = SKSpriteNode()
var danger2 = SKSpriteNode()
var goal = SKSpriteNode()


override func didMove(to view: SKView) {

    ball = self.childNode(withName: "ball") as! SKSpriteNode
    danger1 = self.childNode(withName: "danger1") as! SKSpriteNode
    danger2 = self.childNode(withName: "danger2") as! SKSpriteNode
    goal = self.childNode(withName: "goal") as! SKSpriteNode

    let border = SKPhysicsBody(edgeLoopFrom: self.frame)
    border.friction = 0
    border.restitution = 0

    danger1.physicsBody = SKPhysicsBody()
    danger1.physicsBody?.categoryBitMask = PhysicsCategories.dangerCategory
    danger2.physicsBody = SKPhysicsBody()
    danger2.physicsBody?.categoryBitMask = PhysicsCategories.dangerCategory

    ball.physicsBody = SKPhysicsBody()
    ball.physicsBody?.categoryBitMask = PhysicsCategories.ballCategory
    ball.physicsBody?.contactTestBitMask = PhysicsCategories.dangerCategory
    ball.physicsBody?.collisionBitMask = PhysicsCategories.none

    goal.physicsBody = SKPhysicsBody(circleOfRadius: goal.size.width/2)
    goal.physicsBody?.categoryBitMask = PhysicsCategories.goalCategory

    danger1.physicsBody?.isDynamic = true
    ball.physicsBody?.isDynamic = true
    goal.physicsBody?.isDynamic = true
    danger2.physicsBody?.isDynamic = true
    danger2.physicsBody!.affectedByGravity = false
    danger1.physicsBody!.affectedByGravity = false
    goal.physicsBody!.affectedByGravity = false
    ball.physicsBody!.affectedByGravity = false
    setupPhysics()

}
func setupPhysics() {
    physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
    physicsWorld.contactDelegate = self
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        let location = touch.location(in: self)
        ball.position.x = location.x
        ball.position.y = location.y
        print("x: \(ball.position.x), y: \(ball.position.y)")
    }
}

override func update(_ currentTime: TimeInterval) {
    // Called before each frame is rendered
}
}

extension GameScene: SKPhysicsContactDelegate {



func didBegin(_ contact: SKPhysicsContact) {
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

    if contactMask == PhysicsCategories.ballCategory | PhysicsCategories.dangerCategory {
        ball.position = CGPoint(x: 0, y: 550)
    } else if contactMask == PhysicsCategories.ballCategory | PhysicsCategories.goalCategory {
        print("Goal!")
    }
}

}
Schmob
  • 9
  • 3
  • Hi - What do you mean by how can I make it so it doesn't move around other sprite nodes'? When you drag the ball into another object, what do you want to happen? If you want the ball to bounce off or just stop, then you will have to 'drop' the ball. It looks as though the ball simply moves to where your finger is - is that right? Usually you have to 'touch' the ball to pick it up before dragging it. – Steve Ives Dec 13 '18 at 15:17
  • Well, when I drag the ball, it phases though other sprite nodes instead of actually colliding with them. It just like "floats"? through the other sprite nodes. It will also push some objects around the scene, which I don't want. The collisions wont actual print the statements too. – Schmob Dec 13 '18 at 16:03
  • Give all the sprites that the ball can interact with a collisionBitMask equal to the balls category. Then if you don't want the items the ball can hit to move in response to the ball colliding you can always just set their physics bodies to nil. E.G. danger1.physicsBody = nil – Cameron Porter Dec 13 '18 at 20:55
  • @Schmob OK - stop using the word 'phases' - it implies somewthing weird :-). It's just not colliding with those objects so moves through them - why wouldn't it? The objects that it pushes around? It's colliding with those, so check your bit mask definitions. – Steve Ives Dec 14 '18 at 09:23
  • @CameronPorter If you delete the physics body for a node then nothing can collide with it and no contacts will be registered. To prevent nodes from moving when 'hit', the correct thing to do is to turn off the relevant bit in the object's `collisionBitMask`. – Steve Ives Dec 14 '18 at 09:25

1 Answers1

0

Try commenting out this line:

ball.physicsBody?.collisionBitMask = PhysicsCategories.none

which prevents the ball from colliding with anything, i.e. it is unaffected by collisions with any object. Note - this does NOT mean that other objects are unaffected by collision with the ball. collision are 2-way - given 2 node A and B, you have to define if A collides with B and if B collides with A. This isn;t necessary for contact - it's enough to define that A contacts B. If it's actually b that moves into A, didBegin() will still get called. you don't have to define that B contact A also.

You haven't appeared to set the collisionBitMask on any other physics body, which means those will collide with everything.

this explains why the ball moves through the wall - because it isn't colliding with it, although every other object should get pushed around by the ball.

Try putting a:

print("Contact") 

as the first line of your didBegin() to see if any contacts are being registered.

If you want to drag sprites with your finger then making them bounce off (collide with) other sprites can be tricky, because dragging implies that you want to set their position manually and bouncing off implies that your want the sprites to be moved by the Sprite-Kit engine and the 2 are not really compatible.

It's probably worth pointing our that 'collisions' are sprites bouncing off each other and are handled by the SK engine. The collisionBitMask controls what objects bounce off each other.

'Contacts' are just a way to get notified when 2 objects touch. They are controlled by the contactTestBitMask.

Both contact and collisions rely on the categoryBitMAsk

My step-by-step guide for collisions and contacts: https://stackoverflow.com/a/51041474/1430420

And a guide to collision and contactTest bit masks: https://stackoverflow.com/a/40596890/1430420

Manipulating bit masks to turn individual collision and contacts off and on. https://stackoverflow.com/a/46495864/1430420

Steve Ives
  • 7,894
  • 3
  • 24
  • 55