1

I'm making a game where the the player is suppose to avoid obstacles and collect points. One slight problem though. When the player collides with the points(another SKSpriteNode), the player bounces a little bit. I want it to just "go through" without it being affected by the collision.

This is the player class:

import SpriteKit

struct ColliderType {
static let Player: UInt32 = 1
static let Swan: UInt32 = 2
static let Branch: UInt32 = 3
static let Score: UInt32 = 4
static let Wall1: UInt32 = 5
static let Wall2: UInt32 = 6
}

class Player: SKSpriteNode {

func initialize() {
    self.name = "Player"
    self.zPosition = 4
    self.setScale(0.3)
    self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    self.physicsBody = SKPhysicsBody(circleOfRadius: self.size.height / 
2 - 5)
    self.physicsBody?.affectedByGravity = false
    self.physicsBody?.restitution = 0
    self.physicsBody?.categoryBitMask = ColliderType.Player
    self.physicsBody?.collisionBitMask = ColliderType.Swan | 
ColliderType.Branch | ColliderType.Wall1 | ColliderType.Wall2
    self.physicsBody?.contactTestBitMask = ColliderType.Swan | 
ColliderType.Score | ColliderType.Branch | ColliderType.Wall1 | 
ColliderType.Wall2


}

}

This is the GameplayScene:

import SpriteKit

class GameplayScene: SKScene, SKPhysicsContactDelegate {

var player = Player()

var swan = SKSpriteNode()

var frog = SKSpriteNode()

var egg = SKSpriteNode()

var branch = SKSpriteNode()

var scoreLabel = SKLabelNode()
var score = 0

var gameStarted = false
var isAlive = false

var press = SKSpriteNode()

var touched: Bool = false

var location = CGPoint.zero

override func didMove(to view: SKView) {
    initialize()
}

override func update(_ currentTime: TimeInterval) {

    if isAlive {
        moveBackgrounds()
    }

    if (touched) {
        moveNodeToLocation()
    }
}

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

    if gameStarted == false {
        isAlive = true
        gameStarted = true
        press.removeFromParent()
        spawnSwans()
        spawnEggs()
        spawnBranches()
    }

    touched = true
    for touch in touches {
        location = touch.location(in:self)
    }

    for touch in touches {

        let location = touch.location(in: self)

        if atPoint(location).name == "Retry" {
            self.removeAllActions()
            self.removeAllChildren()
            initialize()
        }

        if atPoint(location).name == "Quit" {
            let mainMenu = MainMenuScene(fileNamed: "MainMenuScene")
            mainMenu!.scaleMode = .aspectFill
            self.view?.presentScene(mainMenu!, transition: 
SKTransition.fade(withDuration: TimeInterval(1)))
        }

    }

}

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

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

    for touch in touches {
        location = touch.location(in: self)
    }
}

func didBegin(_ contact: SKPhysicsContact) {

    var firstBody = SKPhysicsBody()
    var secondBody = SKPhysicsBody()

    if contact.bodyA.node?.name == "Player" {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }

    if firstBody.node?.name == "Player" && secondBody.node?.name == 
"Egg" {
        incrementScore()
        secondBody.node?.removeFromParent()
    } else if firstBody.node?.name == "Player" && secondBody.node?.name 
== "Swan" {
        if isAlive {
            playerDied()
            firstBody.node?.removeFromParent()
        }
    } else if firstBody.node?.name == "Player" && secondBody.node?.name 
== "Branch" {
        if isAlive {
            playerDied()
            firstBody.node?.removeFromParent()
        }
    } else if firstBody.node?.name == "Player" && secondBody.node?.name 
== "Wall1" {
        if isAlive {
            playerDied()
            firstBody.node?.removeFromParent()
        }
    } else if firstBody.node?.name == "Player" && secondBody.node?.name 
== "Wall2" {
        if isAlive {
            playerDied()
            firstBody.node?.removeFromParent()
        }
    }


}

func initialize() {

    gameStarted = false
    isAlive = false
    score = 0

    physicsWorld.contactDelegate = self

    createInstructions()
    createPlayer()
    createBackgrounds()
    createWall1()
    createWall2()
    createLabel()
}

func createInstructions() {
    press = SKSpriteNode(imageNamed: "Press")
    press.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    press.position = CGPoint(x: 0, y: 100)
    press.setScale(0.4)
    press.zPosition = 10
    self.addChild(press)
}

func createPlayer() {
    player = Player(imageNamed: "Player")
    player.initialize()
    player.position = CGPoint(x: 0, y: 0)
    self.addChild(player)
}

func createBackgrounds() {
    for i in 0...2 {
        let bg = SKSpriteNode(imageNamed: "BG")
        bg.name = "BG"
        bg.anchorPoint = CGPoint(x: 0.5, y: 0.5 )
        bg.position = CGPoint(x: 0, y: CGFloat(i) * bg.size.height)
        self.addChild(bg)
    }
}

func createWall1() {
    for i in 0...2 {
        let wall = SKSpriteNode(imageNamed: "Wall1")
        wall.name = "Wall1"
        wall.zPosition = 4
        wall.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        wall.position = CGPoint(x: -(self.frame.size.width / 2) + 23, 
y: CGFloat(i) * wall.size.height)
        wall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 
wall.size.width - 30, height: wall.size.height))
        wall.physicsBody?.affectedByGravity = false
        wall.physicsBody?.isDynamic = false
        wall.physicsBody?.categoryBitMask = ColliderType.Wall1
        self.addChild(wall)
    }
}

func createWall2() {
    for i in 0...2 {
        let wall = SKSpriteNode(imageNamed: "Wall2")
        wall.name = "Wall2"
        wall.zPosition = 4
        wall.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        wall.position = CGPoint(x: (self.frame.size.width / 2) - 23, y: 
CGFloat(i) * wall.size.height)
        wall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 
wall.size.width - 30, height: wall.size.height))
        wall.physicsBody?.affectedByGravity = false
        wall.physicsBody?.isDynamic = false
        wall.physicsBody?.categoryBitMask = ColliderType.Wall2
        self.addChild(wall)
    }
}

func moveBackgrounds() {

    enumerateChildNodes(withName: "BG", using: ({
        (node, error) in

        node.position.y -= 5

        if node.position.y < -(self.frame.height) {
            node.position.y += self.frame.height * 3
        }

    }))

    enumerateChildNodes(withName: "Wall1", using: ({
        (node, error) in

        node.position.y -= 5

        if node.position.y < -(self.frame.height) {
            node.position.y += self.frame.height * 3
        }

    }))

    enumerateChildNodes(withName: "Wall2", using: ({
        (node, error) in

        node.position.y -= 5

        if node.position.y < -(self.frame.height) {
            node.position.y += self.frame.height * 3
        }

    }))
}

func createSwans() {

    swan = SKSpriteNode(imageNamed: "Swan")
    swan.name = "Swan"

    swan.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    swan.position = CGPoint(x: 0, y: 300)
    swan.zPosition = 5
    swan.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 
swan.size.width - 50, height: swan.size.height - 50))
    swan.physicsBody?.categoryBitMask = ColliderType.Swan
    swan.physicsBody?.affectedByGravity = false
    swan.physicsBody?.isDynamic = false

    swan.position.y = self.size.height + 100
    swan.position.x = CGFloat.randomBetweenNumbers(firstNum: -255, 
secondNum: 255)

    self.addChild(swan)

    let destination = self.frame.height * 2
    let move = SKAction.moveTo(y: -destination, duration: 
TimeInterval(10))
    let remove = SKAction.removeFromParent()

    swan.run(SKAction.sequence([move, remove]), withKey: "MoveSwans")


}

func spawnSwans() {

    let spawn = SKAction.run({ () -> Void in
        self.createSwans()
    })

    let delay = SKAction.wait(forDuration: TimeInterval(0.8))
    let sequence = SKAction.sequence([spawn, delay])

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnSwans")
}

func createBranches() {
    let branch = SKSpriteNode(imageNamed: "Branch")
    branch.name = "Branch"

    branch.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    branch.position = CGPoint(x: 0, y: 500)
    branch.zPosition = 4
    branch.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 
branch.size.width - 30, height: branch.size.height - 30))
    branch.physicsBody?.categoryBitMask = ColliderType.Branch
    branch.physicsBody?.affectedByGravity = false
    branch.physicsBody?.isDynamic = false
    branch.position.y = self.frame.height + 500
    branch.position.x = CGFloat.randomBetweenNumbers(firstNum: -228, 
secondNum: 228)

    self.addChild(branch)

    let destination = self.size.height / 1.5
    let move = SKAction.moveTo(y: -destination, duration: 
TimeInterval(10))
    let remove = SKAction.removeFromParent()

    branch.run(SKAction.sequence([move, remove]), withKey: 
"MoveBranches")
}

func spawnBranches() {
    let spawn = SKAction.run({ () -> Void in
        self.createBranches()
    })

    let delay = SKAction.wait(forDuration: TimeInterval(1.5))
    let sequence = SKAction.sequence([spawn, delay])

    self.run(SKAction.repeatForever(sequence), withKey: 
"SpawnBranches")
}

func createEggs() {

    let egg = SKSpriteNode(imageNamed: "Egg")
    egg.name = "Egg"

    egg.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    egg.position = CGPoint(x: 0, y: 500)
    egg.zPosition = 3
    egg.setScale(0.3)
    egg.physicsBody = SKPhysicsBody(circleOfRadius: egg.size.height / 2 
- 5)
    egg.physicsBody?.categoryBitMask = ColliderType.Score
    egg.physicsBody?.collisionBitMask = 0
    egg.physicsBody?.affectedByGravity = false
    egg.physicsBody?.restitution = 0
    egg.physicsBody?.isDynamic = false

    egg.position.y = self.frame.height + 500
    egg.position.x = CGFloat.randomBetweenNumbers(firstNum: -250, 
secondNum: 250)

    self.addChild(egg)

    let destination = self.size.height / 2
    let move = SKAction.moveTo(y: -destination, duration: 
TimeInterval(10))
    let remove = SKAction.removeFromParent()

    egg.run(SKAction.sequence([move, remove]), withKey: "MoveEggs")

}
//testa göra likadant med createCrocodiles och spawnCrocodiles som du 
gör med createScore och spawnScore
func spawnEggs() {

    let spawn = SKAction.run({ () -> Void in
        self.createEggs()
    })

    let delay = SKAction.wait(forDuration: TimeInterval(3))
    let sequence = SKAction.sequence([spawn, delay])

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnEggs")
}

func createLabel() {
    scoreLabel.zPosition = 7
    scoreLabel.position = CGPoint(x: 0, y: -300)
    scoreLabel.fontName = "Bradley Hand"
    scoreLabel.fontSize = 120
    scoreLabel.text = "0"
    self.addChild(scoreLabel)
}

func incrementScore() {
    score += 1
    scoreLabel.text = String(score)
}

func playerDied() {

    self.removeAction(forKey: "SpawnSwans")
    self.removeAction(forKey: "SpawnBranches")
    self.removeAction(forKey: "SpawnEggs")

    for child in children {
        if child.name == "Swan" {
            child.removeAction(forKey: "MoveSwans")
        } else if child.name == "Branch" {
            child.removeAction(forKey: "MoveBranches")
        } else if child.name == "Egg" {
            child.removeAction(forKey: "MoveEggs")
        }
    }

    isAlive = false

    let highscore = GameManager.instance.getHighscore()

    if highscore < score {
        GameManager.instance.setHighscore(highscore: score)
    }

    let retry = SKSpriteNode(imageNamed: "Retry")
    let quit = SKSpriteNode(imageNamed: "Quit")

    retry.name = "Retry"
    retry.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    retry.position = CGPoint(x: -150, y: 0)
    retry.zPosition = 8
    retry.setScale(0)

    quit.name = "Quit"
    quit.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    quit.position = CGPoint(x: 150, y: 0)
    quit.zPosition = 8
    quit.setScale(0)

    let scaleUp = SKAction.scale(to: 1, duration: TimeInterval(0.5))

    retry.run(scaleUp)
    quit.run(scaleUp)

    self.addChild(retry)
    self.addChild(quit)


}

func moveNodeToLocation() {
    // Compute vector components in direction of the touch
    var dx = location.x - player.position.x
    // How fast to move the node. Adjust this as needed
    let speed:CGFloat = 0.08
    // Scale vector
    dx = dx * speed
    player.position = CGPoint(x:player.position.x+dx, y: 0)
}

}
Flinigan
  • 105
  • 10

1 Answers1

0

I see your problem here, So if I understand right, you want to be able to pick up a power up or a coin without it colliding with your player.

In this case you just need to remove the item you don't want to collide with from your players collisionBitMask and vice versa as that's what determines what collides with what. You can still check contact with it using contactBitMask. Also here is a link explaining collisionBitMasks in detail How does collisionBitMask work? Swift/SpriteKit !

hyper0009
  • 236
  • 1
  • 11
  • Yes exactly, thats what I want. The only problem is that I don't even have the "coin" in my players collisionBitMask, only in the contactBitMask. I have also tried putting in ".physicsbody.collisionBitMask = 0" in both the player and the coin to match these up. But I still get that small collision, even though it's not that bad it's still annoying. – Flinigan Jun 30 '17 at 13:32