How to Clone Flappy Bird in Swift

download How to Clone Flappy Bird in Swift

of 109

  • date post

    29-Oct-2014
  • Category

    Mobile

  • view

    8
  • download

    2

Embed Size (px)

description

 

Transcript of How to Clone Flappy Bird in Swift

  • 1. How To CloneFlappyBirdinSwift

2. A little introduction 3. Who Am I?@giordanoscalzohttps://github.com/gscalzo 4. Who Am I?@giordanoscalzohttps://github.com/gscalzoA developer 5. Who Am I?@giordanoscalzohttps://github.com/gscalzoAn iOS developer 6. Who Am I?@giordanoscalzohttps://github.com/gscalzoA Swift beginner 7. How to implement Hello World in Swift? 8. println("Hello, World!") 9. println("Hello, World!")Not exciting :-( 10. far to be perfect 11. but it was fun 12. instructions 13. git clonehttp://github.com/gscalzo/FlappySwift.git 14. ./setup 15. ./setup 1./setup 2./setup 3... 16. walking skeleton./setup 1 17. class GameScene: SKScene {private var screenNode: SKSpriteNode!override func didMoveToView(view: SKView) {// ...} 18. override func didMoveToView(view: SKView) {screenNode = SKSpriteNode(color: UIColor.clearColor(), size: self.size)addChild(screenNode)let backgroundNode = SKSpriteNode(imageNamed: "background")backgroundNode.anchorPoint = CGPointZerobackgroundNode.position = CGPointZeroscreenNode.addChild(backgroundNode)let groundNode = SKSpriteNode(imageNamed: "ground")groundNode.anchorPoint = CGPointZerogroundNode.position = CGPointZeroscreenNode.addChild(groundNode)} 19. parallax layers./setup 2 20. override func didMoveToView(view: SKView) {//...Background(textureNamed: "background").addTo(screenNode).start()Ground(textureNamed: "ground").addTo(screenNode).start()} 21. protocol Startable {func start() -> Startablefunc stop() -> Startable} 22. class Background {private var parallaxNode: ParallaxNode!private let textureName: Stringinit(textureNamed textureName: String) {}func addTo(parentNode: SKSpriteNode!) -> Background {return self}} 23. init(textureNamed textureName: String) {self.textureName = textureName}func addTo(parentNode: SKSpriteNode!) -> Background {let width = parentNode.size.widthlet height = parentNode.size.heightparallaxNode = ParallaxNode(width: width,height: height,textureNamed: textureName).addTo(parentNode)return self} 24. extension Background : Startable {func start() -> Startable {parallaxNode.start(duration: 20.0)return self}func stop() -> Startable {parallaxNode.stop()return self}} 25. class Ground {private var parallaxNode: ParallaxNode!private let textureName: Stringinit(textureNamed textureName: String) {}func addTo(parentNode: SKSpriteNode!) -> Ground {return self}} 26. init(textureNamed textureName: String) {self.textureName = textureName}func addTo(parentNode: SKSpriteNode!) -> Ground {let width = parentNode.size.widthlet height = CGFloat(60.0)parallaxNode = ParallaxNode(width: width,height: height,textureNamed: textureName).zPosition(5).addTo(parentNode)return self} 27. extension Ground : Startable {func start() -> Startable {parallaxNode.start(duration: 5.0)return self}func stop() -> Startable {parallaxNode.stop()return self}} 28. How to implement ParallaxNode? 29. class ParallaxNode {private let node: SKSpriteNode!init(width: CGFloat, height: CGFloat, textureNamed: String) {}private func createNode(textureNamed: String, x: CGFloat) -> SKNode {}func zPosition(zPosition: CGFloat) -> ParallaxNode {}func addTo(parentNode: SKSpriteNode) -> ParallaxNode {}func start(#duration: NSTimeInterval) {}func stop() {}} 30. init(width: CGFloat, height: CGFloat, textureNamed: String) {let size = CGSizeMake(2*width, height)node = SKSpriteNode(color: UIColor.whiteColor(), size: size)node.anchorPoint = CGPointZeronode.position = CGPointZeronode.addChild(createNode(textureNamed, x: 0))node.addChild(createNode(textureNamed, x: width))} 31. private func createNode(textureNamed: String, x: CGFloat) -> SKNode {let node = SKSpriteNode(imageNamed: textureNamed, normalMapped: true)node.anchorPoint = CGPointZeronode.position = CGPoint(x: x, y: 0)return node} 32. func zPosition(zPosition: CGFloat) -> ParallaxNode {node.zPosition = zPositionreturn self}func addTo(parentNode: SKSpriteNode) -> ParallaxNode {parentNode.addChild(node)return self}func stop() {node.removeAllActions()} 33. func start(#duration: NSTimeInterval) {node.runAction(SKAction.repeatActionForever(SKAction.sequence([SKAction.moveToX(-node.size.width/2.0, duration: duration),SKAction.moveToX(0, duration: 0)])))} 34. Our hero./setup 3 35. override func didMoveToView(view: SKView) {physicsWorld.gravity = CGVector(dx: 0, dy: -3)//...bird = Bird(textureNames: ["bird1", "bird2"]).addTo(screenNode)bird.position = CGPointMake(30.0, 400.0)bird.start()} 36. class Bird {private let node: SKSpriteNode!private let textureNames: [String]var position : CGPoint {set { node.position = newValue }get { return node.position }}init(textureNames: [String]) {self.textureNames = textureNamesnode = createNode()}func addTo(scene: SKSpriteNode) -> Bird{scene.addChild(node)return self}} 37. extension Bird {private func createNode() -> SKSpriteNode {let birdNode = SKSpriteNode(imageNamed: textureNames.first!)birdNode.setScale(1.8)birdNode.zPosition = 2.0birdNode.physicsBody = SKPhysicsBody(rectangleOfSize: birdNode.size)birdNode.physicsBody!.dynamic = truereturn birdNode}} 38. extension Bird : Startable {func start() -> Startable {animate()return self}func stop() -> Startable {node.physicsBody!.dynamic = falsenode.removeAllActions()return self}} 39. private func animate(){let animationFrames = textureNames.map { texName inSKTexture(imageNamed: texName)}node.runAction(SKAction.repeatActionForever(SKAction.animateWithTextures(animationFrames, timePerFrame: 0.1)))} 40. func update() {switch node.physicsBody!.velocity.dy {case let dy where dy > 30.0:node.zRotation = (3.14/6.0)case let dy where dy < -100.0:node.zRotation = -1*(3.14/4.0)default:node.zRotation = 0.0}} 41. Bird Physics 101 42. Impulse 43. func flap() {node.physicsBody!.velocity = CGVector(dx: 0, dy: 0)node.physicsBody!.applyImpulse(CGVector(dx: 0, dy: 6))} 44. Pipes! 45. Pipes!./setup 4 46. class GameScene: SKScene {override func didMoveToView(view: SKView) {//...Pipes(textureNames: ["pipeTop.png", "pipeBottom.png"]).addTo(screenNode).start()} 47. class Pipes {// class let createActionKey = "createActionKey" // class variables not yet supportedprivate class var createActionKey : String { get {return "createActionKey"} }private var parentNode: SKSpriteNode!private let textureNames: [String]init(textureNames: [String]) {self.textureNames = textureNames}func addTo(parentNode: SKSpriteNode) -> Pipes {self.parentNode = parentNodereturn self}} 48. func start() -> Startable {let createAction = SKAction.repeatActionForever(SKAction.sequence([SKAction.runBlock {self.createNewPipe()},SKAction.waitForDuration(3)]) )parentNode.runAction(createAction, withKey: Pipes.createActionKey)return self} 49. func stop() -> Startable {parentNode.removeActionForKey(Pipes.createActionKey)let pipeNodes = parentNode.children.filter { (node: AnyObject?) -> Bool in(node as SKNode).name == PipePair.kind}for pipe in pipeNodes {pipe.removeAllActions()}return self} 50. private func createNewPipe() {PipePair(textures: textureNames, centerY: centerPipes()).addTo(parentNode).start()}private func centerPipes() -> CGFloat {return parentNode.size.height/2 - 100 + 20 * CGFloat(arc4random_uniform(10))} 51. class PipePair {// class let kind = "PIPES" // class variables not yet supportedclass var kind : String { get {return "PIPES"} }private let gapSize: CGFloat = 50private var pipesNode: SKNode!private var finalOffset: CGFloat!private var startingOffset: CGFloat! 52. init(textures: [String], centerY: CGFloat){pipesNode = SKNode()pipesNode.name = PipePair.kindlet pipeTop = createPipe(imageNamed: textures[0])let pipeTopPosition = CGPoint(x: 0, y: centerY + pipeTop.size.height/2 + gapSize)pipeTop.position = pipeTopPositionpipesNode.addChild(pipeTop)let pipeBottom = createPipe(imageNamed: textures[1])let pipeBottomPosition = CGPoint(x: 0 , y: centerY - pipeBottom.size.height/2 - gapSize)pipeBottom.position = pipeBottomPositionpipesNode.addChild(pipeBottom)let gapNode = createGap(size: CGSize(width: pipeBottom.size.width,height: gapSize*2))gapNode.position = CGPoint(x: 0, y: centerY)pipesNode.addChild(gapNode)finalOffset = -pipeBottom.size.width/2startingOffset = -finalOffset} 53. func start() {pipesNode.runAction(SKAction.sequence([SKAction.moveToX(finalOffset, duration: 6.0),SKAction.removeFromParent()]))} 54. private func createPipe(#imageNamed: String) -> SKSpriteNode {let pipeNode = SKSpriteNode(imageNamed: imageNamed)return pipeNode}private func createGap(#size: CGSize) -> SKSpriteNode {let gapNode = SKSpriteNode(color: UIColor.clearColor(),size: size)return gapNode} 55. Contact./setup 5 56. enum BodyType : UInt32 {case bird = 1 // (1 SKPhysicsBody {let body = SKPhysicsBody(rectangleOfSize: size)builderClosure(body)return body}} 60. class Ground {func addTo(parentNode: SKSpriteNode!) -> Ground {//...groundBody.physicsBody = SKPhysicsBody.rectSize(size) { body inbody.dynamic = falsebody.affectedByGravity = falsebody.categoryBitMask = BodyType.ground.toRaw()body.collisionBitMask = BodyType.ground.toRaw()} 61. extension PipePair {private func createPipe(#imageNamed: String) -> SKSpriteNode {pipeNode.physicsBody = SKPhysicsBody.rectSize(pipeNode.size) {body inbody.dynamic = falsebody.affectedByGravity = falsebody.categoryBitMask = BodyType.pipe.toRaw()body.collisionBitMask = BodyType.pipe.toRaw()}}private func createGap(#size: CGSize) -> SKSpriteNode {gapNode.physicsBody = SKPhysicsBody.rectSize(size) {body inbody.dynamic = falsebody.affectedByGravity = falsebody.categoryBitMask = BodyType.gap.toRaw()body.collisionBitMask = BodyType.gap.toRaw()}}} 62. extension GameScene: SKPhysicsContactDelegate {func didBeginContact(contact: SKPhysicsContact!) {}func didEndContact(contact: SKPhysicsContact!) {}} 63. func didBeginContact(contact: SKPhysicsContact!) {let contactMask = contact.bodyA.categoryBitMask |contact.bodyB.categoryBitMaskswitch (contactMask) {case BodyType.pi