Search code examples
iosswifttimercollisionscoring

Scoring Method for Swift & Spawning objects


I cannot seem to work out how to get my scoring to work...

the concept of the game is birds will come in on the right hand side, and when they reach the left hand side i want my score to increment by 1.

In Obj_c i would have done something like

if (bird.enter.x < 0) {
    score++
}

but in swift sprite kit I'm not to sure how to do it...

Another problem I'm having is that i have to use a timer to get my "Enemy Birds" to spawn (the birds going from right to left)

(every 1 second the timer runs the spawn enemy function) but in Obj_c i would have spawned say 3/4 at different x co-ordinates and like the previous code when the bird was < 0 px i would CGPointMake() back over to the other side of the screen so they are on a constant loop

Any ideas of doing this in swift? My code is as follows: its in bit of a weird layout:

import SpriteKit





class GameScene: SKScene, SKPhysicsContactDelegate {

var bg = SKSpriteNode()             // Create Background
var bird = SKSpriteNode()           // Create User Bird
var scoreLabel = SKLabelNode()      // Create Score Label
var score: Int = 0                  // Create Score Integer
var enemyBird = SKSpriteNode()      // Create Enemy Bird

var birdGroup:UInt32 = 1            // Bird Collision Group
var objectGroup:UInt32 = 2          // Enemy Collision Group
var scoreGroup:UInt32 = 3           // Score Collision Group
var gameOver = 0                    // Game Over function
var movingObjects = SKNode()        // ??
var gameOverLabel = SKLabelNode()   // Game over label
var labelHolder = SKSpriteNode()    // Holds Label - Game Over
var Menu = 0


/* Put Bird in and animate */
var birdTexture = SKTexture(imageNamed: "bird_img_1.png")
var birdTexture2 = SKTexture(imageNamed: "bird_img_2.png")
var birdTexture3 = SKTexture(imageNamed: "bird_img_3.png")
var birdTexture4 = SKTexture(imageNamed: "bird_img_4.png")

var birdDeadTexture = SKTexture(imageNamed: "bird_img_dead.png")

var finalSpawn: CGFloat = 0.0


/* ------------------------------------ Main Setup ------------------------------------------ */


override func didMoveToView(view: SKView) {
    /* Setup your scene here */

    println("Moved to Game Scene")


    movingObjects.speed = 0




    /* Call Functions */
    backgroundImage()
    enemySpawn()



    /* Set up deletates and physics and timer */
    self.physicsWorld.contactDelegate = self
    self.physicsWorld.gravity = CGVectorMake(0, -5)
    self.addChild(movingObjects)
    self.addChild(labelHolder)


    /*  Load Score Text */

    scoreLabel.fontName = "Helvetica"
    scoreLabel.fontSize = 60
    scoreLabel.text = "0"
    scoreLabel.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)+self.frame.size.height*0.3)
    self.addChild(scoreLabel)


    enemyBird.position = CGPointMake(self.frame.width+200, 500)
    movingObjects.addChild(enemyBird)



    bird = SKSpriteNode(texture: birdTexture)
    bird.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
    // Make bird smaller
    bird.size.height = bird.size.height/12
    bird.size.width = bird.size.width/11
    // Animate Bird
    var animation = SKAction.animateWithTextures([birdTexture, birdTexture2, birdTexture3, birdTexture4], timePerFrame: 0.08)
    var makeBirdFlap = SKAction.repeatActionForever(animation)
    bird.runAction(makeBirdFlap)
    // Load Physics
    // birdPhysics()
    // Run bird animation
    bird.zPosition = 10


    self.addChild(bird)


    /* Introduce ground and top into the scene */
    // Create Ground
    var ground = SKSpriteNode()
    ground.position = CGPointMake(CGRectGetMidX(self.frame), self.frame.size.height/100 * 16)
    ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width, 1))
    ground.physicsBody?.dynamic = false
    ground.physicsBody?.categoryBitMask = objectGroup
    // Add Ground to scene
    self.addChild(ground)

    // Create Top
    var top = SKSpriteNode()
    top.position = CGPointMake(0, self.frame.size.height)
    top.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width, 1))
    top.physicsBody?.dynamic = false
    top.physicsBody?.categoryBitMask = objectGroup
    // Add Top to scene
    self.addChild(top)


}








/* ------------------------------------ Spawning Enemy Birds ------------------------------------------ */








/* Create and Spawn enemy birds */
func enemySpawn() {





    let height = self.frame.size.height                             // screen height as variable
    let width = self.frame.size.width                               // screen width as variable

    var bottomBarHeight = self.frame.size.height*0.16               // bottom bar height
    var spawningPoint = height - bottomBarHeight                    // screen height - 16%

    var randSpawn = arc4random_uniform(UInt32(spawningPoint))       // random number between 0 and 645
    finalSpawn = CGFloat(randSpawn) + bottomBarHeight           // add 16% (bottombarheight to the random number
    println(Int(finalSpawn))





    if (enemyBird.position.y > frame.size.height) {
        enemyBird.position.y = frame.size.height - 100
    }

    if (enemyBird.position.y < self.frame.size.width * 0.16) {
        enemyBird.position.y = self.frame.size.width + 0.18
    }




   // Create enemy bird
    var enemyBirdTexture = SKTexture(imageNamed: "enemy_img_2.png")

   // enemyBird.position = CGPointMake(self.frame.width+200, 500)
    enemyBird = SKSpriteNode(texture: enemyBirdTexture)
    enemyBird.size.height = enemyBird.size.height/12
    enemyBird.size.width = enemyBird.size.width/11
    enemyBird.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(enemyBird.size.width/1.1, enemyBird.size.height/1.1))
    enemyBird.physicsBody?.dynamic = false
    enemyBird.physicsBody?.categoryBitMask = objectGroup

   // BIRD LOOP - ONLY RUNNING ONCE???        

    let startPoint = CGPointMake(self.frame.width+200, finalSpawn)
    let endPoint = CGPointMake(0, finalSpawn)
    let moveToEndAction = SKAction.moveTo(endPoint, duration: 2)
    let resetTostartAction = SKAction.moveTo(startPoint, duration: 0)
    let moveToEndThenStartAgain = SKAction.repeatActionForever(SKAction.sequence([moveToEndAction,resetTostartAction]))

    enemyBird.runAction(SKAction.repeatActionForever(moveToEndThenStartAgain))

}











/* ------------------------------------ Other Parts ------------------------------------------ */








func backgroundImage() {

    /* Put Background Image In */

    // Create Background Texture
    var bgTexture = SKTexture(imageNamed: "bg.png")
    // Link bg variable to texture
    bg = SKSpriteNode(texture: bgTexture)
    // Position thr bg image
    bg.position = CGPoint(x: CGRectGetMidX(self.frame), y: self.frame.height/2)
    bg.size.height = self.frame.height

    // Move background image left
    var moveBg = SKAction.moveByX(-bgTexture.size().width, y: 0, duration: 9)
    var replaceBg = SKAction.moveByX(bgTexture.size().width, y: 0, duration: 0)
    var moveBgForever = SKAction.repeatActionForever(SKAction.sequence([moveBg, replaceBg]))

    // Keep world never ending
    for var i:CGFloat = 0; i < 3; i++ {

        // Position Background
        bg = SKSpriteNode(texture: bgTexture)
        bg.position = CGPoint(x: bgTexture.size().width/2 + bgTexture.size().width * i, y: CGRectGetMidY(self.frame))

        // Stretch background full height of screen
        bg.size.height = self.frame.height

        // Run the action to move BG
        bg.runAction(moveBgForever)

        self.addChild(bg)
    }
}










/* ------------------------------------ Create Bird Physics ------------------------------------------ */








func birdPhysics() {
    /* Give bird physics */
    // Give bird physics
    bird.physicsBody = SKPhysicsBody(circleOfRadius: bird.size.height/3)
    bird.physicsBody?.mass = 0.2
    bird.physicsBody?.dynamic = true
    bird.physicsBody?.allowsRotation = false
    bird.physicsBody?.categoryBitMask = birdGroup
    bird.physicsBody?.collisionBitMask = objectGroup
    bird.physicsBody?.contactTestBitMask = objectGroup


}









/* ------------------------------------ If contact is found ------------------------------------------ */










func didBeginContact(contact: SKPhysicsContact) {
    if contact.bodyA.categoryBitMask == objectGroup || contact.bodyB.categoryBitMask == objectGroup {


        bird.removeAllActions()
        bird.texture = birdDeadTexture
        let action = SKAction.rotateByAngle(CGFloat(-M_PI), duration:1)
        bird.runAction(SKAction.repeatActionForever(action))


        if gameOver == 0 {
            movingObjects.speed = 0
            gameOver = 1
            movingObjects.removeAllChildren()// Remove all enemies
            gameOverLabel.fontName = "Helvetica"
            gameOverLabel.fontSize = 25
            gameOverLabel.text = "Tap to retry!"
            gameOverLabel.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)*1.5)
            labelHolder.addChild(gameOverLabel)
            gameOverLabel.zPosition = 9


        }
    }
}












/* ------------------------------------ When user touches the screen ------------------------------------------ */






override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    /* Called when a touch begins */




    if (Menu == 0) {
        movingObjects.speed = 1
        birdPhysics()
        let action = SKAction.rotateByAngle(CGFloat(-M_PI), duration:1)
        bird.runAction(SKAction.repeatActionForever(action))

    }




    if (gameOver == 0) {                                                                            // Runs if game is not over
        bird.physicsBody?.velocity = CGVectorMake(0, 0)
        bird.physicsBody?.applyImpulse(CGVectorMake(0, 80))
        Menu = 1    // Number on right is jump height


    } else {                                                                                        // Runs if game is over
        score = 0                                                                                   // Score int is 0
        scoreLabel.text = "0"                                                                       // Score Label is 0
        bird.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))         // Position Bird in center
        bird.physicsBody?.velocity = CGVectorMake(0,0)                                              // Cannot make bird jump
        labelHolder.removeAllChildren()                                                             // Removes all labels
        gameOver = 0                                                                                // Sets game over to 0 so game will run
        movingObjects.speed = 1
        bird.texture = birdTexture
        // Animate Bird
        var animation = SKAction.animateWithTextures([birdTexture, birdTexture2, birdTexture3, birdTexture4], timePerFrame: 0.08)
        var makeBirdFlap = SKAction.repeatActionForever(animation)
        bird.runAction(makeBirdFlap)

        let height = self.frame.size.height
        let width = self.frame.size.width



            var gameScene: GameScene = GameScene(size: CGSizeMake(width, height))
            var spriteView: SKView = self.view as SKView!
            var trans :SKTransition = SKTransition.crossFadeWithDuration(0.5)
            spriteView.presentScene(gameScene, transition: trans)

    }
}







override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */

    if (enemyBird.position.x == 0) {

        score = score + 1
        scoreLabel.text = "\(score)"
    }


    if (enemyBird.position.y > frame.size.height) {
        enemyBird.position.y = frame.size.height - enemyBird.size.height
    }  
}    }

Solution

  • You can increase the score like

    if (bird.position.x < 0)
    {
        score++
    }
    

    And to loop the animation of enemy birds, you can make a looping SKAction from one end to other end. For example like this

    let startPoint = CGPointMake(0, 200)
    let endPoint = CGPointMake(self.frame.width, 200)
    
    let moveToEndAction = SKAction.moveTo(endPoint, duration: 2)
    let resetTostartAction = SKAction.moveTo(startPoint, duration: 0)
    
    let moveToEndThenStartAgain = SKAction.repeatActionForever(SKAction.sequence([moveToEndAction,resetTostartAction]))
    
    node.runAction(SKAction.repeatActionForever(moveToEndThenStartAgain))
    

    To start at a random height each time, you can use

    let maxHeight:UInt32 = 400
    let startPoint = CGPointMake(0, CGFloat(arc4random() % maxHeight))
    
    let moveToEndAction = SKAction.moveByX(self.frame.width, y: 0, duration: 1.0)
    let resetTostartAction = SKAction.runBlock { () -> Void in
    
        let randomHeight = CGFloat(arc4random() % maxHeight)
        self.playButton.position = CGPointMake(startPoint.x,randomHeight)
    }
    
    let moveToEndThenStartAgain = SKAction.repeatActionForever(SKAction.sequence([moveToEndAction,resetTostartAction]))
    
    enemyBird.runAction(SKAction.repeatActionForever(moveToEndThenStartAgain))
    

    You can change maxHeight as required.