Skip to content

Instantly share code, notes, and snippets.

@josephspurrier
Created May 4, 2016 19:23
Show Gist options
  • Save josephspurrier/60bb9d75dabfb8398396d2a1ae7646c8 to your computer and use it in GitHub Desktop.
Save josephspurrier/60bb9d75dabfb8398396d2a1ae7646c8 to your computer and use it in GitHub Desktop.
Flappy Bird in Swift
//
// GameScene.swift
// Flappy Bird
//
// Created on 4/20/16.
// Copyright (c) 2016 Joseph Spurrier. All rights reserved.
//
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var score = 0
var scoreLabel = SKLabelNode()
var gameoverLabel = SKLabelNode()
var bird = SKSpriteNode()
var bg = SKSpriteNode()
var pipe1 = SKSpriteNode()
var pipe2 = SKSpriteNode()
var movingObjects = SKSpriteNode()
var labelContainer = SKSpriteNode()
enum ColliderType: UInt32 {
case Bird = 1
case Object = 2
case Gap = 4
}
var gameOver = false
override func didMoveToView(view: SKView) {
/* Setup your scene here */
self.physicsWorld.contactDelegate = self
self.addChild(movingObjects)
self.addChild(labelContainer)
// Bird
let birdTexture = SKTexture(imageNamed: "flappy1.png")
let birdTexture2 = SKTexture(imageNamed: "flappy2.png")
let animation = SKAction.animateWithTextures([birdTexture, birdTexture2], timePerFrame: 0.1)
let makeBirdFlap = SKAction.repeatActionForever(animation)
bird = SKSpriteNode(texture: birdTexture)
bird.physicsBody = SKPhysicsBody(circleOfRadius: birdTexture.size().height/2)
bird.physicsBody!.dynamic = true
bird.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
bird.physicsBody?.allowsRotation = false
bird.runAction(makeBirdFlap)
bird.physicsBody!.categoryBitMask = ColliderType.Bird.rawValue
bird.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
bird.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
makeBackground()
// Score label
scoreLabel.fontName = "Helvetica"
scoreLabel.fontSize = 60
scoreLabel.text = "0"
scoreLabel.position = CGPointMake(CGRectGetMidX(self.frame), self.frame.size.height - 70)
// Positions
bird.zPosition = 7
scoreLabel.zPosition = 15
// Add the objects to the screen
self.addChild(bird)
self.addChild(scoreLabel)
_ = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: #selector(GameScene.makePipes), userInfo: nil, repeats: true)
}
func makeBackground() {
// Ground
let ground = SKNode()
ground.position = CGPointMake(0, 0)
ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width, 1))
ground.physicsBody!.dynamic = false
ground.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
ground.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
ground.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
// Background(s)
let bgTexture = SKTexture(imageNamed: "bg.png")
let movebg = SKAction.moveByX(-bgTexture.size().width, y: 0, duration: 9)
let replacebg = SKAction.moveByX(bgTexture.size().width, y: 0, duration: 0)
let movebgForever = SKAction.repeatActionForever(SKAction.sequence([movebg,replacebg]))
for var i: CGFloat = 0; i<3; i++ {
bg = SKSpriteNode(texture: bgTexture)
bg.position = CGPoint(x: bgTexture.size().width/2 + bgTexture.size().width * i, y: CGRectGetMidY(self.frame))
bg.size.height = self.frame.height
bg.runAction(movebgForever)
bg.zPosition = 3
movingObjects.addChild(bg)
}
ground.zPosition = 5
movingObjects.addChild(ground)
}
func makePipes() {
// Pipes
let gapHeight = bird.size.height * 4
let movementAmount = arc4random() % UInt32(self.frame.size.height / 2)
let pipeOffset = CGFloat(movementAmount) - self.frame.size.height / 4
let movePipes = SKAction.moveByX(-self.frame.size.width * 2, y: 0, duration: NSTimeInterval(self.frame.size.width / 100))
let removePipes = SKAction.removeFromParent()
let moveAndRemovePipes = SKAction.sequence([movePipes, removePipes])
let pipeTexture1 = SKTexture(imageNamed: "pipe1.png")
pipe1 = SKSpriteNode(texture: pipeTexture1)
pipe1.position = CGPoint(x: CGRectGetMidX(self.frame) + self.frame.size.width, y: CGRectGetMidY(self.frame) + pipeTexture1.size().height/2 + gapHeight / 2 + pipeOffset)
pipe1.runAction(moveAndRemovePipes)
pipe1.physicsBody = SKPhysicsBody(rectangleOfSize: pipeTexture1.size())
pipe1.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
pipe1.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
pipe1.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
pipe1.physicsBody!.dynamic = false
let pipeTexture2 = SKTexture(imageNamed: "pipe2.png")
pipe2 = SKSpriteNode(texture: pipeTexture2)
pipe2.position = CGPoint(x: CGRectGetMidX(self.frame) + self.frame.size.width, y: CGRectGetMidY(self.frame) - pipeTexture2.size().height/2 - gapHeight / 2 + pipeOffset)
pipe2.runAction(moveAndRemovePipes)
pipe2.physicsBody = SKPhysicsBody(rectangleOfSize: pipeTexture2.size())
pipe2.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
pipe2.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
pipe2.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
pipe2.physicsBody!.dynamic = false
pipe1.zPosition = 8
pipe2.zPosition = 8
movingObjects.addChild(pipe1)
movingObjects.addChild(pipe2)
let gap = SKNode()
gap.position = CGPoint(x: CGRectGetMidX(self.frame) + self.frame.size.width, y: CGRectGetMidY(self.frame) + pipeOffset)
gap.runAction(moveAndRemovePipes)
gap.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(pipe1.size.width, gapHeight))
gap.physicsBody!.dynamic = false
gap.physicsBody!.categoryBitMask = ColliderType.Gap.rawValue
gap.physicsBody!.contactTestBitMask = ColliderType.Bird.rawValue
gap.physicsBody!.collisionBitMask = ColliderType.Gap.rawValue
movingObjects.addChild(gap)
}
func didBeginContact(contact: SKPhysicsContact) {
if contact.bodyA.categoryBitMask == ColliderType.Gap.rawValue || contact.bodyB.categoryBitMask == ColliderType.Gap.rawValue {
score += 1
//print(score)
scoreLabel.text = String(score)
} else {
if gameOver == false {
gameOver = true
self.speed = 0
gameoverLabel.fontName = "Helvetica"
gameoverLabel.fontSize = 30
gameoverLabel.text = "Game Over! Tap to play again."
gameoverLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
gameoverLabel.zPosition = 20
labelContainer.addChild(gameoverLabel)
}
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
if gameOver == false {
bird.physicsBody!.velocity = CGVectorMake(0,0)
bird.physicsBody!.applyImpulse(CGVectorMake(0, 50))
} else {
score = 0
scoreLabel.text = "0"
bird.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
bird.physicsBody?.velocity = CGVectorMake(0, 0)
movingObjects.removeAllChildren()
makeBackground()
labelContainer.removeAllChildren()
self.speed = 1
gameOver = false
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment