1
votes

I am working on an iPhone game. Basically if hero hits an obstacle gave over. Now I want add jump ability to my hero. But when I use "physicsBody = SKPhysicsBody(rectangleOfSize: size)" for the ground, as soon as game starts and hero appears on the ground "func didBeginContact(contact: SKPhysicsContact){ gameOver() }" method makes game over.Here is my implementations of hero, ground and gamescene. Can you guys please help me to make hero jump and land on the ground. Thanks in advance.

//  AKHero.swift
//  Run Hero

  import Foundation
  import SpriteKit
  class AKHero: SKSpriteNode{

var body:SKSpriteNode!
var arm: SKSpriteNode!
var leftFoot: SKSpriteNode!
var rightFoot: SKSpriteNode!
var leftpupil: SKSpriteNode!
var rightpupil: SKSpriteNode!

var isUpsideDown = false

init(){
    let size = CGSizeMake(35, 45)
    super.init(texture: nil, color: UIColor.clearColor(), size: size)

    loadAppearance()
    loadPhysicsBoadyWithsize(size)

}

   func loadPhysicsBoadyWithsize(size: CGSize){

    physicsBody = SKPhysicsBody(rectangleOfSize: size)

    physicsBody?.categoryBitMask = heroCategory
    physicsBody?.contactTestBitMask = obstacleCategory
    physicsBody?.usesPreciseCollisionDetection = true
    physicsBody?.affectedByGravity = false
}


   func jump(){

    self.physicsBody?.applyImpulse(CGVectorMake(0, 15))
    physicsBody?.affectedByGravity = true


}
//  GameScene.swift
//  Run Hero

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

var movingGround: AKMovingGround!
var hero: AKHero!
var cloudGenerator: AKCloudGenerator!
var obstacleGenerator: AKObstacleGenerator!
var coinGenerator: AKCoinGenerator!
var isStarted = false
var isGameOver = false

override func didMoveToView(view: SKView) {
    backgroundColor = UIColor(red: 159.0/255.0, green: 201.0/255.0 ,       blue: 244.0/255.0 , alpha: 1.0)

 func addMovingGround(){
     movingGround = AKMovingGround(size: CGSizeMake(view!.frame.width, kAKGroundHeight))
    movingGround.position = CGPointMake(0, view!.frame.size.height/2)
    addChild(movingGround)

}

//add hero
func addHero(){
    hero = AKHero()
    hero.position = CGPointMake(70, movingGround.position.y + movingGround.frame.size.height/2 + hero.frame.size.height/2)
    addChild(hero)
    hero.breathe()
}
func addPhysicsWorld() {
    physicsWorld.contactDelegate = self

}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

    if isGameOver {

        restart()
    }

    else if !isStarted {

        start()

    }
    else{
       hero.flipHero()
      //hero.jump()

    }
}


// MARK: - SKPhysicsContactDelegate
func didBeginContact(contact: SKPhysicsContact) {

    if !isGameOver{
    println("didBeginContact")
    gameOver()
    }
}
//
//  AKMovingGround.swift
//  Run Hero
//
//  Created by Alican Karamil on 24/08/15.
//  Copyright (c) 2015 Alican Karamil. All rights reserved.
//

import Foundation
import SpriteKit
class AKMovingGround: SKSpriteNode{

    let NUMBER_OF_SEGMENTS = 20
    let COLOR_ONE = UIColor(red: 88.0/255.0, green: 148.0/255, blue: 87.0/255.0, alpha: 1.0)
    let COLOR_TWO = UIColor(red: 120.0/255.0, green:195.0/255.0, blue: 118.0/255.0, alpha: 1.0)

    init (size: CGSize){
        super.init(texture: nil, color: UIColor.brownColor(), size: CGSizeMake(size.width*2, size.height))
        anchorPoint = CGPointMake(0, 1.5)
        //anchorPoint = CGPointMake(0, 0.5)

        for var i = 0; i < NUMBER_OF_SEGMENTS; i++ {
            var segmentColor: UIColor!
            if i % 2 == 0{
            segmentColor=COLOR_ONE
            }else{
            segmentColor=COLOR_TWO
            }
            let segment = SKSpriteNode(color: segmentColor, size: CGSizeMake(self.size.width/CGFloat(NUMBER_OF_SEGMENTS), self.size.height))
            segment.anchorPoint = CGPointMake(0.0, 0.5)
            segment.position = CGPointMake(CGFloat(i)*segment.size.width, 0)
            addChild(segment)
        }

    }

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


    func start(){
        let moveleft = SKAction.moveByX(-frame.size.width/2, y: 0, duration: 1.0)
        let resetPosition = SKAction.moveToX(0, duration: 0.0)
        let moveSequence = SKAction.sequence([moveleft, resetPosition])
        //runAction(moveSequence, completion: nil)
        runAction(SKAction.repeatActionForever(moveSequence))

    }

    func stop(){

    removeAllActions()
   }


 }
1
You should put some conditional logic in didBeginContact. Right now if the game starts, your hero touches the scene boundary and didBeginContact is getting called and that causes game to finish. In didBeginContact, you should define touching what finishes the game and what not.neo

1 Answers

1
votes

Your problem is that didBeginContact() hasn't been assigned a specific contact, so any contact at all gets rendered into that function, including between the player and the ground.

To fix this, you'll have to create specific categoryBitMasks. For more information on that, check out the Apple Docs. When you've done that, you'll need to specify which categoryBitMasks you want to detect collisions with, on the player. That way, if it hits the ground, nothing happens, but if it hits the obstacle, game over. To do this, you'll have to specify the player's physicsBody?.categoryBitMask, then set its physicsBody?.contactTestBitMask and its physicsBody?.collisionBitMask.

In didBeginContact(), specify which contact to look for with if-statements. Try and see if this Youtube video helps you. Or maybe this one.