0
votes

Updated my Code below.

I am trying to detect an SKNode that is used to track the score. It is the child of the obstacle that moves right to left on the screen so it moves with the obstacle Node.

The problem is that I can't detect the collision with the score node after a certain speed. In my game the speed increases every time the score node is contacted and it works up to a certain speed and then the collision with the score node is not detected.

I have tried using the usesPreciseCollisionDetection = true but get the same problem.

I need to increase the speed of the obstacles and reduce the wait time between spawning the next obstacle. what ends up happing with some of my previous attempts, where I increase the speed every time the score node is contacted, is the speed increases but the spawning time doesn't decrease so it creates a gap because the obstacle moves fast enough and goes off screen and the next one isn't spawned yet.

this is the code for the increase speed when contact score node

var speedOfObstacle = 3.0
var speedOfSpawn = 1.0

override func didMove(to view: SKView) {
     DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
          self.run(SKAction.repeatForever(
              SKAction.sequence([
                  SKAction.run(self.addObstacle),
                  SKAction.wait(forDuration: self.speedOfSpawn)
              ])
          ))
    }
}

//** The above SKAction.wait(forDuration: self.speedOfSpawn) determines the spawn time or delay from repeating this sequence. I need to decrease this speedofSpawn But it doesn't change from initial amount of 1.0

func addObstacle() {
  //Obstacle Code. Implement the SpeedofObstale. 
}

func didBegin(_ contact: SKPhysicsContact) {
    var dogBody: SKPhysicsBody
    var otherBody: SKPhysicsBody
    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        dogBody = contact.bodyA
        otherBody = contact.bodyB
    } else {
        dogBody = contact.bodyB
        otherBody = contact.bodyA
    }

    if dogBody.categoryBitMask == dogSpriteCategory && otherBody.categoryBitMask == obstacleCategory {
        //   print("dog hit obstacle")
    } else if dogBody.categoryBitMask == dogSpriteCategory && otherBody.categoryBitMask == scoreCategory {
        print("dog hit score")

        score += 1
        scoreLabelNode.text = String(score)

        if speedOfObstacle >= 0.7 {
            speedOfObstacle -= 0.03
            print("speed of obstacle is \(speedOfObstacle)")
            speedOfSpawn -= 0.01
            print("speed of spawn  \(speedOfSpawn)")
        }
    }
}

with the contact score node code the speedOfObstacle decreases from the 3.0 but the wait time for speedOfSpawn does not change from the initial amount of 1.0 .

The speedOfObstacle is used in the addObstacle func, didBegin(_contact), and the viewDidLoad. . The speedOfSpawn is used in the didBegin(_contact) and the viewDidLoad.

Any help on how I can either detect the score node collision at high speed or any way to increase the speed of the obstacle and the frequency of spawning the obstacle would be appreciated.

Thank you,

Updated Code. As answered by bg2b.

I have changed my code and below is what I changed.

enter code here

//replaced the repeat for ever code in view did load with

override func didMove(to view: SKView) {
    let initialDelay = 1.0
    run(SKAction.sequence([.wait(forDuration: initialDelay), .run { self.addObstacle() }]))

}

// then added this in the addObstacle func
//obstacle physics
//obstacle movement
addChild(obstacle)
let nextDelay = speedOfSpawn
run(SKAction.sequence([.wait(forDuration: nextDelay), .run { self.addObstacle() }]))

and put this in the did begin contact. // same as above just two if statements instead of one.

the speedOfSpawn and speedOfObstacle are declared at the top.

score += 1
scoreLabelNode.text = String(score)
scoreLabelNode.physicsBody?.usesPreciseCollisionDetection = true

if speedOfObstacle >= 1.0 {
    speedOfObstacle -= 0.09
    print("speed of obstacle is \(speedOfObstacle)")
}
if speedOfSpawn >= 0.40 {
    speedOfSpawn -= 0.03
    print("speed of spawn  \(speedOfSpawn)")
}
2
I suggest never use DispatchQueue.main.asyncAfter in a game and manage the spawn out of repeat forever as bg2b suggested - Simone Pistecchia

2 Answers

1
votes

I'm not sure about the collision issues, but for the spawning, you're making an action in didMove and then not altering that action. That is, when you write

SKAction.wait(forDuration: self.speedOfSpawn)

you're creating an SKAction that waits for a number of seconds given by the expression self.speedOfSpawn. But if you then change speedOfSpawn, the constructed action isn't made again. If you want to do something with a varying delay, one way is to not do a repeatForever but to put the scheduling of each repetition within the action that is repeating. E.g.,

func spawn() {
  // spawn an enemy
  ...
  // schedule next spawn
  let nextDelay = ... // some computation of when to spawn next
  run(SKAction.sequence([.wait(forDuration: nextDelay), .run { self.spawn() }]))
}

override func didMove(to view: SKView) {
  let initialDelay = 1.0
  run(SKAction.sequence([.wait(forDuration: initialDelay), .run { self.spawn() }]))
}
-1
votes

Here is another way you can control your spawning. It eliminates the need for a "speedOfSpawn" variable, and instead use the internal timing mechanics. You basically are making the spawn action go faster and faster.

override func didMove(to view: SKView) {
   self.run(SKAction.repeatForever(
              SKAction.sequence([
                  SKAction.run(self.addObstacle),
                  SKAction.wait(forDuration: 1.0)
              ])
          ,forKey:"Spawning")
}

func didBegin(_ contact: SKPhysicsContact) {
    var dogBody: SKPhysicsBody
    var otherBody: SKPhysicsBody
    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        dogBody = contact.bodyA
        otherBody = contact.bodyB
    } else {
        dogBody = contact.bodyB
        otherBody = contact.bodyA
    }

    if dogBody.categoryBitMask == dogSpriteCategory && otherBody.categoryBitMask == obstacleCategory {
        //   print("dog hit obstacle")
    } else if dogBody.categoryBitMask == dogSpriteCategory && otherBody.categoryBitMask == scoreCategory {
        print("dog hit score")

        score += 1
        scoreLabelNode.text = String(score)

        if speedOfObstacle >= 0.7 {
            speedOfObstacle -= 0.03
            print("speed of obstacle is \(speedOfObstacle)")
            self.action(forKey:"Spawning")?.speed += 0.01
        }
    }
}

The problem with collision is you are essentially playing God when you use SKAction's. I would recommend using the physics velocity to move your object, not SKActions.

You are also using precision on your scoreLabelNode ..... I believe you want to use the parent's node, since that should have the physics body on it.