UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

[Solved] Day 62: Project 17. My objects are not colliding between them

Forums > 100 Days of Swift

I have a question: I have followed the instructions from video "Bring on the enemies: Timer, linearDamping, angularDamping" and after multiple failures (even I copied and pasted the code given in the lessons) my spaceship does not collision against the enemies (basket ball, hammers and tvs). It could be that Xcode has been updated and the missing code (or the different code) does not appear on the video?

How can I make my objects to collide between them? Thanks in advance for your help.

My code:

import SpriteKit

class GameScene: SKScene {
    // MARK: - Elements in screen
    var starfield: SKEmitterNode!
    var player: SKSpriteNode!
    var scoreLabel: SKLabelNode!

    // MARK: - Constants and variables
    var score = 0 {
        didSet {
            scoreLabel.text = "Score: \(score)"
        }
    }
    let possibleEnemies = ["ball", "hammer", "tv"]
    var isGameOver: Bool = false
    var gameTimer: Timer?

    // MARK: - didMove()
    override func didMove(to view: SKView) {
        loadNodes()
    }

    // MARK: - Load Nodes method
    func loadNodes() {
        backgroundColor = .black

        starfield = SKEmitterNode(fileNamed: "starfield")!
        starfield.position = CGPoint(x: 1024, y: 384)
        starfield.advanceSimulationTime(10)
        addChild(starfield)
        starfield.zPosition = -1

        player = SKSpriteNode(imageNamed: "player")
        player.position = CGPoint(x: 100, y: 384)
        player.physicsBody = SKPhysicsBody(texture: player.texture!, size: player.size)
        player.physicsBody?.contactTestBitMask = 1  // Allows collision with other objects
        addChild(player)

        scoreLabel = SKLabelNode(fontNamed: "Chalkduster")
        scoreLabel.position = CGPoint(x: 16, y: 16)
        scoreLabel.horizontalAlignmentMode = .left
        addChild(scoreLabel)

        score = 0

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

        gameTimer = Timer.scheduledTimer(timeInterval: 0.35, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
    }

    @objc func createEnemy() {
        guard let enemy = possibleEnemies.randomElement() else { return }

        let sprite = SKSpriteNode(imageNamed: enemy)
        sprite.position = CGPoint(x: 1200, y: Int.random(in: 50...736))
        addChild(sprite)

        sprite.physicsBody = SKPhysicsBody(texture: sprite.texture!, size: sprite.size)
        sprite.physicsBody?.categoryBitMask = 1
        sprite.physicsBody?.velocity = CGVector(dx: -500, dy: 0)  // starts movement from right to left at a constant speed of 500
        sprite.physicsBody?.angularVelocity = 5  // Spin in the air
        sprite.physicsBody?.linearDamping = 0    // Related to air friction. Since we're in space, it is 0. How fast things slow down over time
        sprite.physicsBody?.angularDamping = 0   // Related to air friction. Never stops spinning
    }

    // MARK: - update method
    override func update(_ currentTime: TimeInterval) {

    }
}

// MARK: - Extension: SKPhysicsContactDelegate
extension GameScene: SKPhysicsContactDelegate {

}

3      

Please refer to this link to check for the answer (basically is using a simulator with iOS 12.X.X).

3      

Hi guys,

The method is working - installing a simulator with iOS 12.x does its job.

I tested the game on my iPad (iOS 13.4) and everything works fine as well. Should we assume that it's just the simulator bug then?

3      

You may be using features introduced in versions later than iOS 12.4 and want to test in the simulator.

It looks like the simulator is failing to create the physics model for the player only. The ball, hammer and television are working properly. A couple of other options: 1- change the player image to be a one of the working images.
2- Generate a working sprite and place it off screen. Then use it to make a working physics model and assign that model to the player. You won't get the same pixel perfect collision detection. But the image will be correct

class GameScene: SKScene, SKPhysicsContactDelegate {
    var workingSprite: SKSpriteNode!      

 // make an instance of the working sprite and place it off screen
   override func didMove(to view: SKView) {
        workingSprite = SKSpriteNode(imageNamed: "tv")
        workingSprite.size = targetSize
        workingSprite.position = CGPoint(x: -200, y: -200)
        addChild(workingSprite)
        ....

   // now we make a sprite that is going to get a physics body
   @objc func createTarget() {
        guard let targetType = possibleTargets.randomElement() else { return }
        let targetSprite = SKSpriteNode(imageNamed: targetType)
        targetSprite.position = CGPoint(x: 40, y: Int.random(in: 60...708))
        addChild(targetSprite)

     targetSprite.physicsBody = SKPhysicsBody(texture: targetSprite.texture!, size: targetSprite.size)
     if targetSprite.physicsBody == nil {
     // since we don't have a physics body that we want, settle for one from the off screen sprite that we know works.
        targetSprite.physicsBody = SKPhysicsBody(texture: workingSprite.texture!, size: targetSprite.size)
     }

3      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.