2
votes

This is my first time making a game in iOS so naturally I came across a couple of problems. I've managed to solve them but now that it comes to the collision part between mario and the pipes I'm having some trouble:

What I would like to do:

When mario collides with the pipes, he will have to jump over them to get to the other side. If he does not then the pipes will continue to 'push' him to the edge of the screen where the game will end.

What actually happens:

No collision is detected whatsoever.

Here is the code below:

import SpriteKit
import GameplayKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    var mario = SKSpriteNode()

    enum ColliderType: UInt32 {

        case Mario = 1
        case Object = 2
    }

    func addPipes() {

        let pipetexture = SKTexture(imageNamed: "pipes")

        let pipes = SKSpriteNode(texture: pipetexture)

        let setScale = CGFloat(arc4random_uniform(19) + 15)

        pipes.setScale(setScale) //min 15, max 19

        pipes.position = CGPoint(x: self.frame.maxX, y: self.frame.minY)

        let movePipes = SKAction.move(by: CGVector(dx: -5 * self.frame.width, dy: 0), duration: TimeInterval(self.frame.width/100))

        let removePipes = SKAction.removeFromParent()

        let moveAndRemovePipes = SKAction.sequence([movePipes, removePipes])

        pipes.zPosition = +1

        pipes.physicsBody = SKPhysicsBody(rectangleOf: pipes.size)

        pipes.physicsBody!.isDynamic = false

        pipes.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
        pipes.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
        pipes.physicsBody!.collisionBitMask = ColliderType.Mario.rawValue

        self.addChild(pipes)

        pipes.run(moveAndRemovePipes)

    }

    func didBegin(_ contact: SKPhysicsContact) {
        print("contact")
    }

    override func didMove(to view: SKView) {

        self.physicsWorld.contactDelegate = self

        _ = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.addPipes), userInfo: nil, repeats: true)

        let marioTexture = SKTexture(imageNamed: "mariorun0.png")
        let marioTexture2 = SKTexture(imageNamed: "mariorun1.png")
        let marioTexture3 = SKTexture(imageNamed: "mariorun2.png")

        let animation = SKAction.animate(with: [marioTexture, marioTexture2, marioTexture3], timePerFrame: 0.1)

        let makeMarioRun = SKAction.repeatForever(animation)

        mario = SKSpriteNode(texture: marioTexture)

        mario.setScale(10)

        mario.position = CGPoint(x: -(self.frame.size.width/3.5), y: -(self.frame.size.height/2.8))

        mario.run(makeMarioRun)

        mario.physicsBody = SKPhysicsBody(rectangleOf: mario.size)

        mario.physicsBody!.isDynamic = false

        mario.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
        mario.physicsBody!.categoryBitMask = ColliderType.Mario.rawValue
        mario.physicsBody!.collisionBitMask = ColliderType.Object.rawValue

        self.addChild(mario)


        addPipes()

        mario.zPosition = +2

    }

}

I have also implemented a jump function that works perfectly. My problem is that I cannot get a collision detection between the pipes and mario.

I have tried setting the z position for both sprites to the same value without any luck.

My initial worry was that the images were to small and hence a collision would be near impossible to detect. But since I am scaling up both nodes and using the physics body of the scaled up images then there wouldn't be a problem, but that doesn't help either.

Thanks for your help in advance.

1
This line of code is unnecessary : pipes.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue. Firstly this means that the pipes notify upon contact with themselves, but you can just remove this line as you've correctly set Mario to contact the pipes, so it's not necessary to have the pipes contact Mario. You have set the collisions correctly.Steve Ives

1 Answers

1
votes

physicsBody!.isDynamic = false means that no physics activity will happen to this body. Other bodies can interact with it, but it will not interact with anything.

This makes sense for a pipe to have, because a pipe never moves, so there is no reason to be dynamic. (Your world should be moving, not the pipe, if you are doing a flappy bird-esc game)

Now for Mario, this does not make sense. Mario is a moving entity, so he will be interacting with the physics world around in. To fix your issue, you need to make him dynamic with mario.physicsBody!.isDynamic = true