Search code examples
swiftsprite-kitgamekittouchesbegansknode

swift - Jump only when landed


I'm looking to restrict my character (cat), to only jump when it's either on the ground (dummy SKNode), or when on the tree (treeP SKNode).

Currently I don't have any restrictions to touchesBegan and as a result the cat is able to fly through the air if the user clicks in quick succession, whilst this could be useful in other games it's not welcome here.

If anyone could help me I'd be really happy.

What i would like to do but have no experience would be to enable a click (jump), if the cat was in contact with either dummy or tree and likewise disable clicks if not in contact with either dummy or tree.

Here is everything that may be of use....

class GameScene: SKScene, SKPhysicsContactDelegate {

let catCategory: UInt32 = 1 << 0
let treeCategory: UInt32 = 1 << 1
let worldCategory: UInt32 = 1 << 1

override func didMoveToView(view: SKView) {

// part of cat code    

    cat = SKSpriteNode(texture: catTexture1)
    cat.position = CGPoint(x: self.frame.size.width / 2.2, y: self.frame.size.height / 7.0 )
    cat.physicsBody?.categoryBitMask = catCategory
    cat.physicsBody?.collisionBitMask = crowCategory | worldCategory
    cat.physicsBody?.contactTestBitMask = crowCategory | contact2Category

// part of the ground code

    var dummy = SKNode()
    dummy.position = CGPointMake(0, groundTexture.size().height / 2)
    dummy.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width, groundTexture.size().height))
    dummy.physicsBody!.dynamic = false
    dummy.physicsBody?.categoryBitMask = worldCategory
    dummy.physicsBody?.collisionBitMask = 0
    dummy.physicsBody?.contactTestBitMask = 0
    moving.addChild(dummy)

// part of the tree code

func spawnTrees() {
    var treeP = SKNode()
    treeP.position = CGPointMake( self.frame.size.width + treeTexture1.size().width * 2, 0 );
    treeP.zPosition = -10; 
    var height = UInt32( self.frame.size.height / 4 )
    var y = arc4random() % height;
    var tree1 = SKSpriteNode(texture: treeTexture1)
    tree1.position = CGPointMake(0.0, CGFloat(y))
    tree1.physicsBody = SKPhysicsBody(rectangleOfSize: tree1.size)
    tree1.physicsBody?.dynamic = false
    tree1.physicsBody?.categoryBitMask = treeCategory;
    tree1.physicsBody?.collisionBitMask = 0
    tree1.physicsBody?.contactTestBitMask = 0
    treeP.addChild(tree1)

    treeP.runAction(moveAndRemoveTrees)

    trees.addChild(treeP)

}

// all of touchesBegan

override func  touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
    /* Called when a touch begins */


    if (moving.speed > 0){
        cat.physicsBody!.velocity = CGVectorMake(0, 0)
        cat.physicsBody!.applyImpulse(CGVectorMake(0, 20))

                } else if (canRestart) {
                    self.resetScene()
    }

}

Solution

  • I recently had this problem. This is how I fixed it. In the game scene create this variable:

        var ableToJump = true
    

    Then in the update method put this code:

        if cat.physicsBody?.velocity.dy == 0 {
    ableToJump = true
        }
        else {
    ableToJump = false
        }
    

    The above code will work because the update method is ran every frame of the game. Every frame it checks if your cat is moving on the y axis. If you do not have an update method, just type override func update and it should autocomplete.

    Now the last step is put this code in the touchesBegan:

        if ableToJump == true {
    cat.physicsBody!.applyImpulse(CGVectorMake(0,40))
     }
    

    Note: You may have to tinker with the impulse to get desired jump height