1
votes

I am making a simple platform game using SpriteKit. The game is detecting when the player hits the ground with func didBegin, but for some reason the boolean playerTouchingGround(in my Player class) is not changing to true. I initialized the var playerTouchingGround to true and the player can jump once, but it cannot jump again. The output console prints "hit ground; left ground; hit ground". I don't understand what I am doing wrong. I am probably over looking something simple.

Here is my GameScene code

import SpriteKit
import GameplayKit

class GameScene: SKScene{

let player: Player!
let ground: Ground!
let controller: ControllerNode!

let contactManager = Player()


// MARK: - Init


override init(size: CGSize) {

    player = Player()
    ground = Ground(size: size)
    controller = ControllerNode(position: CGPoint(x:0, y: 0))

    super.init(size: size)

    self.physicsWorld.contactDelegate = contactManager

    setup()

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}



// MARK: - Setup

func setup() {


    // Background Color
    self.backgroundColor = UIColor.white


    // Adding Player
    addChild(player)
    player.position.x = size.width/2
    player.position.y = size.height/2


    // Adding Ground
    addChild(ground)
    ground.position.x = size.width/2
    ground.position.y = size.height/4


    // Adding ControllerNode
    addChild(controller)

}


override func update(_ currentTime: TimeInterval) {
    // Called before each frame is rendered
    player.movement(directions: self.controller!.pressedDirections())

}
}

Here is my Player class code

import SpriteKit
enum CharacterMovement : Int {

case Up
case Right
case Down
case Left

}

enum ColliderType: UInt32 {

case player = 1
case ground = 2
}

class Player: SKSpriteNode, SKPhysicsContactDelegate {


var tick = 0


var currentMovement: CharacterMovement?


var lastMovement: CharacterMovement?


var contactMask: Int = 0

var playerTouchingGround = true

// MARK: - Init

init() {



    let playerSize = CGSize(width: 30, height: 60)

    super.init(texture: nil, color: UIColor.cyan, size: playerSize)

    lastMovement = .Right

    self.zPosition = 10

    setup()

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}


// MARK: - Setup

func setup() {


    physicsBody = SKPhysicsBody(rectangleOf: size)
    physicsBody?.usesPreciseCollisionDetection = true
    physicsBody?.categoryBitMask = ColliderType.player.rawValue
    physicsBody?.collisionBitMask = ColliderType.ground.rawValue
    physicsBody?.contactTestBitMask = ColliderType.ground.rawValue
    physicsBody?.allowsRotation = false
    physicsBody?.restitution = 0
    physicsBody?.isDynamic = true

}

func didBegin(_ contact: SKPhysicsContact) {

    print("hit ground")
    playerTouchingGround = true


}




func movement(directions: [ControllerInput]) {



    // if (directions.index(of: .Up) != nil) && (touchingGround == true){

    if (directions.index(of: .Up) != nil) && (playerTouchingGround) {


        physicsBody?.applyImpulse(CGVector(dx: 0, dy: 30))
        playerTouchingGround = false
        currentMovement = .Up
        print("left ground")
    }

    if directions.index(of: .Right) != nil {

        physicsBody?.applyImpulse(CGVector(dx: 1, dy: 0))
        currentMovement = .Right
    }

    if directions.index(of: .Left) != nil {

        physicsBody?.applyImpulse(CGVector(dx: -1, dy: 0))
        currentMovement = .Left
    }

    if currentMovement != nil {
        lastMovement = currentMovement
    }

    if !directions.isEmpty && self.currentMovement != nil {
        // Player Animations
    }
    else {
        currentMovement = nil
    }

    tick += 1
    if tick > 60 {
        tick = 0
    }

}

}

Here is my Ground class code

import SpriteKit

class Ground: SKSpriteNode {


// MARK: - Init

init(size: CGSize) {

    let groundSize = CGSize(width: size.width, height: 20)

    super.init(texture: nil, color: UIColor.black, size: groundSize)

    setup()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}


// MARK: - Setup

func setup() {

    physicsBody = SKPhysicsBody(rectangleOf: size)
    physicsBody?.categoryBitMask = ColliderType.ground.rawValue
    physicsBody?.usesPreciseCollisionDetection = true
    physicsBody?.isDynamic = false
    physicsBody?.restitution = 0
    physicsBody?.categoryBitMask = ColliderType.ground.rawValue
    physicsBody?.collisionBitMask = ColliderType.player.rawValue
    physicsBody?.contactTestBitMask = ColliderType.player.rawValue

}
}
1

1 Answers

1
votes

Your problem is you are creating multiple Player objects.

Everytime you call Player(), you create a brand new player.

This means contactManager and player are not the same instance

let contactManager = Player()  //<---Alright a player


// MARK: - Init


override init(size: CGSize) {

    player = Player()// <-----Uh oh, a new player, need to fix this
    ground = Ground(size: size)
    controller = ControllerNode(position: CGPoint(x:0, y: 0))

    super.init(size: size)

    self.physicsWorld.contactDelegate = contactManager

    setup()

}