├── .DS_Store
├── panda.zip
├── Flappy Bird
├── .DS_Store
├── Flappy Bird
│ ├── .DS_Store
│ ├── Actions.sks
│ ├── Resources
│ │ ├── Art.zip
│ │ ├── Sounds
│ │ │ ├── pop.wav
│ │ │ ├── coin.wav
│ │ │ ├── ding.wav
│ │ │ ├── whack.wav
│ │ │ ├── falling.wav
│ │ │ ├── flapping.wav
│ │ │ └── hitGround.wav
│ │ ├── Art
│ │ │ ├── sprites.atlas
│ │ │ │ ├── OK.png
│ │ │ │ ├── Bird0.png
│ │ │ │ ├── Bird1.png
│ │ │ │ ├── Bird2.png
│ │ │ │ ├── Bird3.png
│ │ │ │ ├── Logo.png
│ │ │ │ ├── OK@2x.png
│ │ │ │ ├── Pause.png
│ │ │ │ ├── Play.png
│ │ │ │ ├── Rate.png
│ │ │ │ ├── Ready.png
│ │ │ │ ├── Score.png
│ │ │ │ ├── Share.png
│ │ │ │ ├── Button.png
│ │ │ │ ├── Cloud1.png
│ │ │ │ ├── Cloud2.png
│ │ │ │ ├── Cloud3.png
│ │ │ │ ├── Ground.png
│ │ │ │ ├── Logo@2x.png
│ │ │ │ ├── Play@2x.png
│ │ │ │ ├── Rate@2x.png
│ │ │ │ ├── Bird0@2x.png
│ │ │ │ ├── Bird1@2x.png
│ │ │ │ ├── Bird2@2x.png
│ │ │ │ ├── Bird3@2x.png
│ │ │ │ ├── Button@2x.png
│ │ │ │ ├── CactusTop.png
│ │ │ │ ├── Cloud1@2x.png
│ │ │ │ ├── Cloud2@2x.png
│ │ │ │ ├── Cloud3@2x.png
│ │ │ │ ├── GameOver.png
│ │ │ │ ├── Ground@2x.png
│ │ │ │ ├── Pause@2x.png
│ │ │ │ ├── Ready@2x.png
│ │ │ │ ├── Score@2x.png
│ │ │ │ ├── Scorecard.png
│ │ │ │ ├── Share@2x.png
│ │ │ │ ├── Sombrero.png
│ │ │ │ ├── ButtonRight.png
│ │ │ │ ├── ButtonSquare.png
│ │ │ │ ├── CactusBottom.png
│ │ │ │ ├── CactusTop@2x.png
│ │ │ │ ├── GameOver@2x.png
│ │ │ │ ├── Scorecard@2x.png
│ │ │ │ ├── Sombrero@2x.png
│ │ │ │ ├── button_learn.png
│ │ │ │ ├── ButtonRight@2x.png
│ │ │ │ ├── ButtonSquare@2x.png
│ │ │ │ ├── CactusBottom@2x.png
│ │ │ │ └── button_learn@2x.png
│ │ │ └── backgrounds.atlas
│ │ │ │ ├── Tutorial.png
│ │ │ │ ├── Background.png
│ │ │ │ ├── Tutorial@2x.png
│ │ │ │ └── Background@2x.png
│ │ └── SKTUtils
│ │ │ ├── SKColor+Extensions.swift
│ │ │ ├── SKAction+Extensions.swift
│ │ │ ├── Int+Extensions.swift
│ │ │ ├── Vector3.swift
│ │ │ ├── SKTAudio.swift
│ │ │ ├── CGFloat+Extensions.swift
│ │ │ ├── SKNode+Extensions.swift
│ │ │ ├── SKAction+SpecialEffects.swift
│ │ │ ├── SKTEffects.swift
│ │ │ ├── CGVector+Extensions.swift
│ │ │ ├── CGPoint+Extensions.swift
│ │ │ └── SKTTimingFunctions.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── icon_120.png
│ │ │ ├── icon_180.png
│ │ │ └── Contents.json
│ │ └── Spaceship.imageset
│ │ │ ├── Spaceship.png
│ │ │ └── Contents.json
│ ├── Class
│ │ ├── MGBird.swift
│ │ └── BitMaskType.swift
│ ├── Info.plist
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── GameViewController.swift
│ ├── AppDelegate.swift
│ └── GameScene.swift
└── Flappy Bird.xcodeproj
│ ├── xcuserdata
│ └── ZBKF001.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── Flappy Bird.xcscheme
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── ZBKF001.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ └── project.pbxproj
└── README.md
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/.DS_Store
--------------------------------------------------------------------------------
/panda.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/panda.zip
--------------------------------------------------------------------------------
/Flappy Bird/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/.DS_Store
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/.DS_Store
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Actions.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Actions.sks
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art.zip
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Sounds/pop.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Sounds/pop.wav
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Sounds/coin.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Sounds/coin.wav
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Sounds/ding.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Sounds/ding.wav
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Sounds/whack.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Sounds/whack.wav
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Sounds/falling.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Sounds/falling.wav
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Sounds/flapping.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Sounds/flapping.wav
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Sounds/hitGround.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Sounds/hitGround.wav
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/OK.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/OK.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird0.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird1.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird2.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird3.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Logo.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/OK@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/OK@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Pause.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Play.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Rate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Rate.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Ready.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Ready.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Score.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Score.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Share.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Button.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud1.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud2.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud3.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Ground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Ground.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Logo@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Logo@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Play@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Play@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Rate@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Rate@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird0@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird0@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird1@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird2@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird2@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird3@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Bird3@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Button@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Button@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/CactusTop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/CactusTop.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud1@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud2@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud2@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud3@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Cloud3@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/GameOver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/GameOver.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Ground@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Ground@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Pause@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Pause@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Ready@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Ready@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Score@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Score@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Scorecard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Scorecard.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Share@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Share@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Sombrero.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Sombrero.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/backgrounds.atlas/Tutorial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/backgrounds.atlas/Tutorial.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/ButtonRight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/ButtonRight.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/ButtonSquare.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/ButtonSquare.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/CactusBottom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/CactusBottom.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/CactusTop@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/CactusTop@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/GameOver@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/GameOver@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Scorecard@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Scorecard@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Sombrero@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/Sombrero@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/button_learn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/button_learn.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Assets.xcassets/AppIcon.appiconset/icon_120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Assets.xcassets/AppIcon.appiconset/icon_120.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Assets.xcassets/AppIcon.appiconset/icon_180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Assets.xcassets/AppIcon.appiconset/icon_180.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/backgrounds.atlas/Background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/backgrounds.atlas/Background.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/backgrounds.atlas/Tutorial@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/backgrounds.atlas/Tutorial@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/ButtonRight@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/ButtonRight@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/ButtonSquare@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/ButtonSquare@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/CactusBottom@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/CactusBottom@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/button_learn@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/sprites.atlas/button_learn@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Assets.xcassets/Spaceship.imageset/Spaceship.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Assets.xcassets/Spaceship.imageset/Spaceship.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/Art/backgrounds.atlas/Background@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird/Resources/Art/backgrounds.atlas/Background@2x.png
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird.xcodeproj/xcuserdata/ZBKF001.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird.xcodeproj/project.xcworkspace/xcuserdata/ZBKF001.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LYM-mg/MGFlappy-Bird/HEAD/Flappy Bird/Flappy Bird.xcodeproj/project.xcworkspace/xcuserdata/ZBKF001.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Assets.xcassets/Spaceship.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "Spaceship.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Class/MGBird.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MGBird.swift
3 | // Flappy Bird
4 | //
5 | // Created by i-Techsys.com on 16/12/22.
6 | // Copyright © 2016年 i-Techsys. All rights reserved.
7 | // SKSpriteNode(imageNamed: "Bird0")
8 |
9 | import SpriteKit
10 |
11 | //class MGBird: SKSpriteNode {
12 | // init() {
13 | // super.init(texture: <#T##SKTexture?#>, size: <#T##CGSize#>)
14 | // }
15 | //
16 | // required init?(coder aDecoder: NSCoder) {
17 | // fatalError("init(coder:) has not been implemented")
18 | // }
19 | //}
20 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird.xcodeproj/xcuserdata/ZBKF001.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Flappy Bird.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | C0F7BFF01DFC128600948E16
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Class/BitMaskType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BitMaskType.swift
3 | // Flappy Bird
4 | //
5 | // Created by i-Techsys.com on 16/12/12.
6 | // Copyright © 2016年 i-Techsys. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | struct 物理层 {
12 | static let 无: UInt32 = 0
13 | static let 游戏角色: UInt32 = 0b1 // 1
14 | static let 障碍物: UInt32 = 0b10 // 2
15 | static let 地面: UInt32 = 0b100 // 4
16 | }
17 |
18 | enum 图层: CGFloat {
19 | case 背景
20 | case 障碍物
21 | case 前景
22 | case 游戏角色
23 | case UI
24 | }
25 |
26 | enum 游戏状态 {
27 | case 主菜单
28 | case 教程
29 | case 游戏
30 | case 跌落
31 | case 显示分数
32 | case 结束🔚
33 | }
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MGFlappy-Bird
2 | 飞翔的小鸟
3 |
4 | # 一、愤怒的小鸟
5 | # - 去下载源码和去AppStore评价APP
6 | 
7 |
8 | # - 开始游戏
9 | 
10 |
11 | # - 换肤(只需要解压项目的文件夹Art替换即可)
12 | 
13 | 
14 | ***
15 |
16 | # 二、panda
17 | - 
18 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "60x60",
35 | "idiom" : "iphone",
36 | "filename" : "icon_120.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "60x60",
41 | "idiom" : "iphone",
42 | "filename" : "icon_180.png",
43 | "scale" : "3x"
44 | }
45 | ],
46 | "info" : {
47 | "version" : 1,
48 | "author" : "xcode"
49 | }
50 | }
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UIStatusBarHidden
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/SKColor+Extensions.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Razeware LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import SpriteKit
24 |
25 | public func SKColorWithRGB(r: Int, g: Int, b: Int) -> SKColor {
26 | return SKColor(red: CGFloat(r)/255.0, green: CGFloat(g)/255.0, blue: CGFloat(b)/255.0, alpha: 1.0)
27 | }
28 |
29 | public func SKColorWithRGBA(r: Int, g: Int, b: Int, a: Int) -> SKColor {
30 | return SKColor(red: CGFloat(r)/255.0, green: CGFloat(g)/255.0, blue: CGFloat(b)/255.0, alpha: CGFloat(a)/255.0)
31 | }
32 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/GameViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameViewController.swift
3 | // Flappy Bird
4 | //
5 | // Created by i-Techsys.com on 16/12/10.
6 | // Copyright © 2016年 i-Techsys. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SpriteKit
11 | import GameplayKit
12 |
13 |
14 | class GameViewController: UIViewController {
15 | override func viewWillLayoutSubviews() {
16 | super.viewWillLayoutSubviews()
17 |
18 | if let sk视图 = self.view as? SKView {
19 | if sk视图.scene == nil {
20 | // 创建场景
21 | let 长宽比 = sk视图.bounds.size.height / sk视图.bounds.size.width
22 | let 场景 = GameScene(size:CGSize(width: 320, height: 320 * 长宽比))
23 | sk视图.showsFPS = true
24 | sk视图.showsNodeCount = true
25 | sk视图.showsPhysics = true
26 | sk视图.ignoresSiblingOrder = true
27 |
28 | 场景.scaleMode = .aspectFill
29 |
30 | sk视图.presentScene(场景)
31 | }
32 | }
33 | }
34 |
35 | }
36 |
37 | //class GameViewController: UIViewController {
38 | //
39 | // override func viewDidLoad() {
40 | // super.viewDidLoad()
41 | //
42 | // if let view = self.view as! SKView? {
43 | // if let scene = SKScene(fileNamed: "GameScene") {
44 | // scene.scaleMode = .aspectFill
45 | // view.presentScene(scene)
46 | // }
47 | //
48 | // view.ignoresSiblingOrder = true
49 | // view.showsFPS = true
50 | // view.showsNodeCount = true
51 | // view.ignoresSiblingOrder = true
52 | // }
53 | // }
54 | //
55 | // override func didReceiveMemoryWarning() {
56 | // super.didReceiveMemoryWarning()
57 | // // Release any cached data, images, etc that aren't in use.
58 | // }
59 | //
60 | // override var prefersStatusBarHidden: Bool {
61 | // return true
62 | // }
63 | //}
64 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Flappy Bird
4 | //
5 | // Created by i-Techsys.com on 16/12/10.
6 | // Copyright © 2016年 i-Techsys. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/SKAction+Extensions.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Razeware LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import SpriteKit
24 |
25 | public extension SKAction {
26 | /**
27 | * Performs an action after the specified delay.
28 | */
29 | public class func afterDelay(delay: TimeInterval, performAction action: SKAction) -> SKAction {
30 | return SKAction.sequence([SKAction.wait(forDuration: delay), action])
31 | }
32 |
33 | /**
34 | * Performs a block after the specified delay. dispatch_block_t
35 | */
36 | public class func afterDelay(delay: TimeInterval, runBlock block:@escaping (() -> ())) -> SKAction {
37 | return SKAction.afterDelay(delay: delay, performAction: SKAction.run(block))
38 | }
39 |
40 | /**
41 | * Removes the node from its parent after the specified delay.
42 | */
43 | public class func removeFromParentAfterDelay(delay: TimeInterval) -> SKAction {
44 | return SKAction.afterDelay(delay: delay, performAction: SKAction.removeFromParent())
45 | }
46 |
47 | /**
48 | * Creates an action to perform a parabolic jump.
49 | */
50 | public class func jumpToHeight(height: CGFloat, duration: TimeInterval, originalPosition: CGPoint) -> SKAction {
51 | return SKAction.customAction(withDuration: duration) {(node, elapsedTime) in
52 | let fraction = elapsedTime / CGFloat(duration)
53 | let yOffset = height * 4 * fraction * (1 - fraction)
54 | node.position = CGPoint(x: originalPosition.x, y: originalPosition.y + yOffset)
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/Int+Extensions.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Razeware LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import CoreGraphics
24 |
25 | public extension Int {
26 | /**
27 | * Ensures that the integer value stays with the specified range.
28 | */
29 | public func clamped(range: Range) -> Int {
30 | return (self < range.lowerBound) ? range.lowerBound : ((self >= range.upperBound) ? range.upperBound - 1: self)
31 | }
32 |
33 | /**
34 | * Ensures that the integer value stays with the specified range.
35 | */
36 | public mutating func clamp(range: Range) -> Int {
37 | self = clamped(range: range)
38 | return self
39 | }
40 |
41 | /**
42 | * Ensures that the integer value stays between the given values, inclusive.
43 | */
44 | public func clamped(v1: Int, _ v2: Int) -> Int {
45 | let min = v1 < v2 ? v1 : v2
46 | let max = v1 > v2 ? v1 : v2
47 | return self < min ? min : (self > max ? max : self)
48 | }
49 |
50 | /**
51 | * Ensures that the integer value stays between the given values, inclusive.
52 | */
53 | public mutating func clamp(v1: Int, _ v2: Int) -> Int {
54 | self = clamped(v1: v1, v2)
55 | return self
56 | }
57 |
58 | /**
59 | * Returns a random integer in the specified range.
60 | */
61 | public static func random(range: Range) -> Int {
62 | return Int(arc4random_uniform(UInt32(range.upperBound - range.lowerBound))) + range.lowerBound
63 | }
64 |
65 | /**
66 | * Returns a random integer between 0 and n-1.
67 | */
68 | public static func random(n: Int) -> Int {
69 | return Int(arc4random_uniform(UInt32(n)))
70 | }
71 |
72 | /**
73 | * Returns a random integer in the range min...max, inclusive.
74 | */
75 | public static func random(_ min: Int, max: Int) -> Int {
76 | assert(min < max)
77 | return Int(arc4random_uniform(UInt32(max - min + 1))) + min
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/Vector3.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Razeware LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import CoreGraphics
24 |
25 | public struct Vector3: Equatable {
26 | var x: CGFloat
27 | var y: CGFloat
28 | var z: CGFloat
29 |
30 | public init(x: CGFloat, y: CGFloat, z: CGFloat) {
31 | self.x = x
32 | self.y = y
33 | self.z = z
34 | }
35 | }
36 |
37 | public func == (lhs: Vector3, rhs: Vector3) -> Bool {
38 | return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z
39 | }
40 |
41 | extension Vector3 {
42 | /**
43 | * Returns true if all the vector elements are equal to the provided value.
44 | */
45 | public func equalToScalar(value: CGFloat) -> Bool {
46 | return x == value && y == value && z == value
47 | }
48 |
49 | /**
50 | * Returns the magnitude of the vector.
51 | **/
52 | public func length() -> CGFloat {
53 | return sqrt(x*x + y*y + z*z)
54 | }
55 |
56 | /**
57 | * Normalizes the vector and returns the result as a new vector.
58 | */
59 | public func normalized() -> Vector3 {
60 | let scale = 1.0/length()
61 | return Vector3(x: x * scale, y: y * scale, z: z * scale)
62 | }
63 |
64 | /**
65 | * Normalizes the vector described by this Vector3 object.
66 | */
67 | public mutating func normalize() {
68 | let scale = 1.0/length()
69 | x *= scale
70 | y *= scale
71 | z *= scale
72 | }
73 |
74 | /**
75 | * Calculates the dot product of two vectors.
76 | */
77 | public static func dotProduct(left: Vector3, right: Vector3) -> CGFloat {
78 | return left.x * right.x + left.y * right.y + left.z * right.z
79 | }
80 |
81 | /**
82 | * Calculates the cross product of two vectors.
83 | */
84 | public static func crossProduct(left: Vector3, right: Vector3) -> Vector3 {
85 | let crossProduct = Vector3(x: left.y * right.z - left.z * right.y,
86 | y: left.z * right.x - left.x * right.z,
87 | z: left.x * right.y - left.y * right.x)
88 | return crossProduct
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/SKTAudio.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Razeware LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import AVFoundation
24 |
25 | /**
26 | * Audio player that uses AVFoundation to play looping background music and
27 | * short sound effects. For when using SKActions just isn't good enough.
28 | */
29 | public class SKTAudio {
30 | public var backgroundMusicPlayer: AVAudioPlayer?
31 | public var soundEffectPlayer: AVAudioPlayer?
32 |
33 | public class func sharedInstance() -> SKTAudio {
34 | return SKTAudioInstance
35 | }
36 |
37 | public func playBackgroundMusic(filename: String) {
38 | let url = Bundle.main.url(forResource: filename, withExtension: nil)
39 | if (url == nil) {
40 | print("Could not find file: \(filename)")
41 | return
42 | }
43 |
44 | var error: NSError? = nil
45 | do {
46 | backgroundMusicPlayer = try AVAudioPlayer(contentsOf: url!)
47 | } catch let error1 as NSError {
48 | error = error1
49 | backgroundMusicPlayer = nil
50 | }
51 | if let player = backgroundMusicPlayer {
52 | player.numberOfLoops = -1
53 | player.prepareToPlay()
54 | player.play()
55 | } else {
56 | print("Could not create audio player: \(error!)")
57 | }
58 | }
59 |
60 | public func pauseBackgroundMusic() {
61 | if let player = backgroundMusicPlayer {
62 | if player.isPlaying {
63 | player.pause()
64 | }
65 | }
66 | }
67 |
68 | public func resumeBackgroundMusic() {
69 | if let player = backgroundMusicPlayer {
70 | if !player.isPlaying {
71 | player.play()
72 | }
73 | }
74 | }
75 |
76 | public func playSoundEffect(filename: String) {
77 | let url = Bundle.main.url(forResource: filename, withExtension: nil)
78 | if (url == nil) {
79 | print("Could not find file: \(filename)")
80 | return
81 | }
82 |
83 | var error: NSError? = nil
84 | do {
85 | soundEffectPlayer = try AVAudioPlayer(contentsOf: url!)
86 | } catch let error1 as NSError {
87 | error = error1
88 | soundEffectPlayer = nil
89 | }
90 | if let player = soundEffectPlayer {
91 | player.numberOfLoops = 0
92 | player.prepareToPlay()
93 | player.play()
94 | } else {
95 | print("Could not create audio player: \(error!)")
96 | }
97 | }
98 | }
99 |
100 | private let SKTAudioInstance = SKTAudio()
101 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/CGFloat+Extensions.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Razeware LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import CoreGraphics
24 |
25 | /** The value of π as a CGFloat */
26 | let π = CGFloat(M_PI)
27 |
28 | public extension CGFloat {
29 | /**
30 | * Converts an angle in degrees to radians.
31 | */
32 | public func degreesToRadians() -> CGFloat {
33 | return π * self / 180.0
34 | }
35 |
36 | /**
37 | * Converts an angle in radians to degrees.
38 | */
39 | public func radiansToDegrees() -> CGFloat {
40 | return self * 180.0 / π
41 | }
42 |
43 | /**
44 | * Ensures that the float value stays between the given values, inclusive.
45 | */
46 | public func clamped(v1: CGFloat, _ v2: CGFloat) -> CGFloat {
47 | let min = v1 < v2 ? v1 : v2
48 | let max = v1 > v2 ? v1 : v2
49 | return self < min ? min : (self > max ? max : self)
50 | }
51 |
52 | /**
53 | * Ensures that the float value stays between the given values, inclusive.
54 | */
55 | public mutating func clamp(v1: CGFloat, _ v2: CGFloat) -> CGFloat {
56 | self = clamped(v1: v1, v2)
57 | return self
58 | }
59 |
60 | /**
61 | * Returns 1.0 if a floating point value is positive; -1.0 if it is negative.
62 | */
63 | public func sign() -> CGFloat {
64 | return (self >= 0.0) ? 1.0 : -1.0
65 | }
66 |
67 | /**
68 | * Returns a random floating point number between 0.0 and 1.0, inclusive.
69 | */
70 | public static func random() -> CGFloat {
71 | return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
72 | }
73 |
74 | /**
75 | * Returns a random floating point number in the range min...max, inclusive.
76 | */
77 | public static func random(min: CGFloat, max: CGFloat) -> CGFloat {
78 | assert(min < max)
79 | return CGFloat.random() * (max - min) + min
80 | }
81 |
82 | /**
83 | * Randomly returns either 1.0 or -1.0.
84 | */
85 | public static func randomSign() -> CGFloat {
86 | return (arc4random_uniform(2) == 0) ? 1.0 : -1.0
87 | }
88 | }
89 |
90 | /**
91 | * Returns the shortest angle between two angles. The result is always between
92 | * -π and π.
93 | */
94 | public func shortestAngleBetween(angle1: CGFloat, angle2: CGFloat) -> CGFloat {
95 | let twoπ = π * 2.0
96 | var angle = (angle2 - angle1).truncatingRemainder(dividingBy: twoπ)
97 | if (angle >= π) {
98 | angle = angle - twoπ
99 | }
100 | if (angle <= -π) {
101 | angle = angle + twoπ
102 | }
103 | return angle
104 | }
105 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird.xcodeproj/xcuserdata/ZBKF001.xcuserdatad/xcschemes/Flappy Bird.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/SKNode+Extensions.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Razeware LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import SpriteKit
24 |
25 | public extension SKNode {
26 |
27 | /** Lets you treat the node's scale as a CGPoint value. */
28 | public var scaleAsPoint: CGPoint {
29 | get {
30 | return CGPoint(x: xScale, y: yScale)
31 | }
32 | set {
33 | xScale = newValue.x
34 | yScale = newValue.y
35 | }
36 | }
37 |
38 | /**
39 | * Runs an action on the node that performs a closure or function after
40 | * a given time.
41 | */
42 | public func afterDelay(delay: TimeInterval, runBlock block: @escaping (() -> ())) {
43 | run(SKAction.sequence([SKAction.wait(forDuration: delay), SKAction.run(block)]))
44 | }
45 |
46 | /**
47 | * Makes this node the frontmost node in its parent.
48 | */
49 | public func bringToFront() {
50 | if let parent = self.parent{
51 | removeFromParent()
52 | parent.addChild(self)
53 | }
54 | }
55 |
56 | /**
57 | * Orients the node in the direction that it is moving by tweening its
58 | * rotation angle. This assumes that at 0 degrees the node is facing up.
59 | *
60 | * @param velocity The current speed and direction of the node. You can get
61 | * this from node.physicsBody.velocity.
62 | * @param rate How fast the node rotates. Must have a value between 0.0 and
63 | * 1.0, where smaller means slower; 1.0 is instantaneous.
64 | */
65 | public func rotateToVelocity(velocity: CGVector, rate: CGFloat) {
66 | // Determine what the rotation angle of the node ought to be based on the
67 | // current velocity of its physics body. This assumes that at 0 degrees the
68 | // node is pointed up, not to the right, so to compensate we subtract π/4
69 | // (90 degrees) from the calculated angle.
70 | let newAngle = atan2(velocity.dy, velocity.dx) - π/2
71 |
72 | // This always makes the node rotate over the shortest possible distance.
73 | // Because the range of atan2() is -180 to 180 degrees, a rotation from,
74 | // -170 to -190 would otherwise be from -170 to 170, which makes the node
75 | // rotate the wrong way (and the long way) around. We adjust the angle to
76 | // go from 190 to 170 instead, which is equivalent to -170 to -190.
77 | if newAngle - zRotation > π {
78 | zRotation += π * 2.0
79 | } else if zRotation - newAngle > π {
80 | zRotation -= π * 2.0
81 | }
82 |
83 | // Use the "standard exponential slide" to slowly tween zRotation to the
84 | // new angle. The greater the value of rate, the faster this goes.
85 | zRotation += (newAngle - zRotation) * rate
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/SKAction+SpecialEffects.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Razeware LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import SpriteKit
24 |
25 | public extension SKAction {
26 | /**
27 | * Creates a screen shake animation.
28 | *
29 | * @param node The node to shake. You cannot apply this effect to an SKScene.
30 | * @param amount The vector by which the node is displaced.
31 | * @param oscillations The number of oscillations; 10 is a good value.
32 | * @param duration How long the effect lasts. Shorter is better.
33 | */
34 | public class func screenShakeWithNode(node: SKNode, amount: CGPoint, oscillations: Int, duration: TimeInterval) -> SKAction {
35 | let oldPosition = node.position
36 | let newPosition = oldPosition + amount
37 | let effect = SKTMoveEffect(node: node, duration: duration, startPosition: newPosition, endPosition: oldPosition)
38 | effect.timingFunction = SKTCreateShakeFunction(oscillations: oscillations)
39 |
40 | return SKAction.actionWithEffect(effect: effect)
41 | }
42 |
43 | /**
44 | * Creates a screen rotation animation.
45 | *
46 | * @param node You usually want to apply this effect to a pivot node that is
47 | * centered in the scene. You cannot apply the effect to an SKScene.
48 | * @param angle The angle in radians.
49 | * @param oscillations The number of oscillations; 10 is a good value.
50 | * @param duration How long the effect lasts. Shorter is better.
51 | */
52 | public class func screenRotateWithNode(node: SKNode, angle: CGFloat, oscillations: Int, duration: TimeInterval) -> SKAction {
53 | let oldAngle = node.zRotation
54 | let newAngle = oldAngle + angle
55 |
56 | let effect = SKTRotateEffect(node: node, duration: duration, startAngle: newAngle, endAngle: oldAngle)
57 | effect.timingFunction = SKTCreateShakeFunction(oscillations: oscillations)
58 |
59 | return SKAction.actionWithEffect(effect: effect)
60 | }
61 |
62 | /**
63 | * Creates a screen zoom animation.
64 | *
65 | * @param node You usually want to apply this effect to a pivot node that is
66 | * centered in the scene. You cannot apply the effect to an SKScene.
67 | * @param amount How much to scale the node in the X and Y directions.
68 | * @param oscillations The number of oscillations; 10 is a good value.
69 | * @param duration How long the effect lasts. Shorter is better.
70 | */
71 | public class func screenZoomWithNode(node: SKNode, amount: CGPoint, oscillations: Int, duration: TimeInterval) -> SKAction {
72 | let oldScale = CGPoint(x: node.xScale, y: node.yScale)
73 | let newScale = oldScale * amount
74 |
75 | let effect = SKTScaleEffect(node: node, duration: duration, startScale: newScale, endScale: oldScale)
76 | effect.timingFunction = SKTCreateShakeFunction(oscillations: oscillations)
77 |
78 | return SKAction.actionWithEffect(effect: effect)
79 | }
80 |
81 | /**
82 | * Causes the scene background to flash for duration seconds.
83 | */
84 | public class func colorGlitchWithScene(scene: SKScene, originalColor: SKColor, duration: TimeInterval) -> SKAction {
85 | return SKAction.customAction(withDuration: duration) {(node, elapsedTime) in
86 | if elapsedTime < CGFloat(duration) {
87 | scene.backgroundColor = SKColorWithRGB(r: Int.random(0, max: 255), g: Int.random(0, max: 255), b: Int.random(0, max: 255))
88 | // SKColorWithRGB(Int.random(0...255), g: Int.random(0...255), b: Int.random(0...255))
89 | } else {
90 | scene.backgroundColor = originalColor
91 | }
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/SKTEffects.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Razeware LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import SpriteKit
24 |
25 | /**
26 | * Allows you to perform actions with custom timing functions.
27 | *
28 | * Unfortunately, SKAction does not have a concept of a timing function, so
29 | * we need to replicate the actions using SKTEffect subclasses.
30 | */
31 | public class SKTEffect {
32 | unowned var node: SKNode
33 | var duration: TimeInterval
34 | public var timingFunction: ((CGFloat) -> CGFloat)?
35 |
36 | public init(node: SKNode, duration: TimeInterval) {
37 | self.node = node
38 | self.duration = duration
39 | timingFunction = SKTTimingFunctionLinear
40 | }
41 |
42 | public func update(t: CGFloat) {
43 | // subclasses implement this
44 | }
45 | }
46 |
47 | /**
48 | * Moves a node from its current position to a new position.
49 | */
50 | public class SKTMoveEffect: SKTEffect {
51 | var startPosition: CGPoint
52 | var delta: CGPoint
53 | var previousPosition: CGPoint
54 |
55 | public init(node: SKNode, duration: TimeInterval, startPosition: CGPoint, endPosition: CGPoint) {
56 | previousPosition = node.position
57 | self.startPosition = startPosition
58 | delta = endPosition - startPosition
59 | super.init(node: node, duration: duration)
60 | }
61 |
62 | public override func update(t: CGFloat) {
63 | // This allows multiple SKTMoveEffect objects to modify the same node
64 | // at the same time.
65 | let newPosition = startPosition + delta*t
66 | let diff = newPosition - previousPosition
67 | previousPosition = newPosition
68 | node.position += diff
69 | }
70 | }
71 |
72 | /**
73 | * Scales a node to a certain scale factor.
74 | */
75 | public class SKTScaleEffect: SKTEffect {
76 | var startScale: CGPoint
77 | var delta: CGPoint
78 | var previousScale: CGPoint
79 |
80 | public init(node: SKNode, duration: TimeInterval, startScale: CGPoint, endScale: CGPoint) {
81 | previousScale = CGPoint(x: node.xScale, y: node.yScale)
82 | self.startScale = startScale
83 | delta = endScale - startScale
84 | super.init(node: node, duration: duration)
85 | }
86 |
87 | public override func update(t: CGFloat) {
88 | let newScale = startScale + delta*t
89 | let diff = newScale / previousScale
90 | previousScale = newScale
91 | node.xScale *= diff.x
92 | node.yScale *= diff.y
93 | }
94 | }
95 |
96 | /**
97 | * Rotates a node to a certain angle.
98 | */
99 | public class SKTRotateEffect: SKTEffect {
100 | var startAngle: CGFloat
101 | var delta: CGFloat
102 | var previousAngle: CGFloat
103 |
104 | public init(node: SKNode, duration: TimeInterval, startAngle: CGFloat, endAngle: CGFloat) {
105 | previousAngle = node.zRotation
106 | self.startAngle = startAngle
107 | delta = endAngle - startAngle
108 | super.init(node: node, duration: duration)
109 | }
110 |
111 | public override func update(t: CGFloat) {
112 | let newAngle = startAngle + delta*t
113 | let diff = newAngle - previousAngle
114 | previousAngle = newAngle
115 | node.zRotation += diff
116 | }
117 | }
118 |
119 | /**
120 | * Wrapper that allows you to use SKTEffect objects as regular SKActions.
121 | */
122 | public extension SKAction {
123 | public class func actionWithEffect(effect: SKTEffect) -> SKAction {
124 | return SKAction.customAction(withDuration: effect.duration) { node, elapsedTime in
125 | var t = elapsedTime / CGFloat(effect.duration)
126 |
127 | if let timingFunction = effect.timingFunction {
128 | t = timingFunction(t) // the magic happens here
129 | }
130 |
131 | effect.update(t: t)
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/CGVector+Extensions.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Razeware LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import CoreGraphics
24 | import SpriteKit
25 |
26 | public extension CGVector {
27 | /**
28 | * Creates a new CGVector given a CGPoint.
29 | */
30 | public init(point: CGPoint) {
31 | self.init(dx: point.x, dy: point.y)
32 | }
33 |
34 | /**
35 | * Given an angle in radians, creates a vector of length 1.0 and returns the
36 | * result as a new CGVector. An angle of 0 is assumed to point to the right.
37 | */
38 | public init(angle: CGFloat) {
39 | self.init(dx: cos(angle), dy: sin(angle))
40 | }
41 |
42 | /**
43 | * Adds (dx, dy) to the vector.
44 | */
45 | public mutating func offset(_ dx: CGFloat, dy: CGFloat) -> CGVector {
46 | self.dx += dx
47 | self.dy += dy
48 | return self
49 | }
50 |
51 | /**
52 | * Returns the length (magnitude) of the vector described by the CGVector.
53 | */
54 | public func length() -> CGFloat {
55 | return sqrt(dx*dx + dy*dy)
56 | }
57 |
58 | /**
59 | * Returns the squared length of the vector described by the CGVector.
60 | */
61 | public func lengthSquared() -> CGFloat {
62 | return dx*dx + dy*dy
63 | }
64 |
65 | /**
66 | * Normalizes the vector described by the CGVector to length 1.0 and returns
67 | * the result as a new CGVector.
68 | public */
69 | func normalized() -> CGVector {
70 | let len = length()
71 | return len>0 ? self / len : CGVector.zero
72 | }
73 |
74 | /**
75 | * Normalizes the vector described by the CGVector to length 1.0.
76 | */
77 | public mutating func normalize() -> CGVector {
78 | self = normalized()
79 | return self
80 | }
81 |
82 | /**
83 | * Calculates the distance between two CGVectors. Pythagoras!
84 | */
85 | public func distanceTo(vector: CGVector) -> CGFloat {
86 | return (self - vector).length()
87 | }
88 |
89 | /**
90 | * Returns the angle in radians of the vector described by the CGVector.
91 | * The range of the angle is -π to π; an angle of 0 points to the right.
92 | */
93 | public var angle: CGFloat {
94 | return atan2(dy, dx)
95 | }
96 | }
97 |
98 | /**
99 | * Adds two CGVector values and returns the result as a new CGVector.
100 | */
101 | public func + (left: CGVector, right: CGVector) -> CGVector {
102 | return CGVector(dx: left.dx + right.dx, dy: left.dy + right.dy)
103 | }
104 |
105 | /**
106 | * Increments a CGVector with the value of another.
107 | */
108 | public func += ( left: inout CGVector, right: CGVector) {
109 | left = left + right
110 | }
111 |
112 | /**
113 | * Subtracts two CGVector values and returns the result as a new CGVector.
114 | */
115 | public func - (left: CGVector, right: CGVector) -> CGVector {
116 | return CGVector(dx: left.dx - right.dx, dy: left.dy - right.dy)
117 | }
118 |
119 | /**
120 | * Decrements a CGVector with the value of another.
121 | */
122 | public func -= (left: inout CGVector, right: CGVector) {
123 | left = left - right
124 | }
125 |
126 | /**
127 | * Multiplies two CGVector values and returns the result as a new CGVector.
128 | */
129 | public func * (left: CGVector, right: CGVector) -> CGVector {
130 | return CGVector(dx: left.dx * right.dx, dy: left.dy * right.dy)
131 | }
132 |
133 | /**
134 | * Multiplies a CGVector with another.
135 | */
136 | public func *= (left: inout CGVector, right: CGVector) {
137 | left = left * right
138 | }
139 |
140 | /**
141 | * Multiplies the x and y fields of a CGVector with the same scalar value and
142 | * returns the result as a new CGVector.
143 | */
144 | public func * (vector: CGVector, scalar: CGFloat) -> CGVector {
145 | return CGVector(dx: vector.dx * scalar, dy: vector.dy * scalar)
146 | }
147 |
148 | /**
149 | * Multiplies the x and y fields of a CGVector with the same scalar value.
150 | */
151 | public func *= (vector: inout CGVector, scalar: CGFloat) {
152 | vector = vector * scalar
153 | }
154 |
155 | /**
156 | * Divides two CGVector values and returns the result as a new CGVector.
157 | */
158 | public func / (left: CGVector, right: CGVector) -> CGVector {
159 | return CGVector(dx: left.dx / right.dx, dy: left.dy / right.dy)
160 | }
161 |
162 | /**
163 | * Divides a CGVector by another.
164 | */
165 | public func /= (left: inout CGVector, right: CGVector) {
166 | left = left / right
167 | }
168 |
169 | /**
170 | * Divides the dx and dy fields of a CGVector by the same scalar value and
171 | * returns the result as a new CGVector.
172 | */
173 | public func / (vector: CGVector, scalar: CGFloat) -> CGVector {
174 | return CGVector(dx: vector.dx / scalar, dy: vector.dy / scalar)
175 | }
176 |
177 | /**
178 | * Divides the dx and dy fields of a CGVector by the same scalar value.
179 | */
180 | public func /= (vector: inout CGVector, scalar: CGFloat) {
181 | vector = vector / scalar
182 | }
183 |
184 | /**
185 | * Performs a linear interpolation between two CGVector values.
186 | */
187 | public func lerp(_ start: CGVector, end: CGVector, t: CGFloat) -> CGVector {
188 | return CGVector(dx: start.dx + (end.dx - start.dx)*t, dy: start.dy + (end.dy - start.dy)*t)
189 | }
190 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/CGPoint+Extensions.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Razeware LLC
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import CoreGraphics
24 | import SpriteKit
25 |
26 | public extension CGPoint {
27 | /**
28 | * Creates a new CGPoint given a CGVector.
29 | */
30 | public init(vector: CGVector) {
31 | self.init(x: vector.dx, y: vector.dy)
32 | }
33 |
34 | /**
35 | * Given an angle in radians, creates a vector of length 1.0 and returns the
36 | * result as a new CGPoint. An angle of 0 is assumed to point to the right.
37 | */
38 | public init(angle: CGFloat) {
39 | self.init(x: cos(angle), y: sin(angle))
40 | }
41 |
42 | /**
43 | * Adds (dx, dy) to the point.
44 | */
45 | public mutating func offset(_ dx: CGFloat, dy: CGFloat) -> CGPoint {
46 | x += dx
47 | y += dy
48 | return self
49 | }
50 |
51 | /**
52 | * Returns the length (magnitude) of the vector described by the CGPoint.
53 | */
54 | public func length() -> CGFloat {
55 |
56 | return sqrt(x*x + y*y)
57 | }
58 |
59 | /**
60 | * Returns the squared length of the vector described by the CGPoint.
61 | */
62 | public func lengthSquared() -> CGFloat {
63 | return x*x + y*y
64 | }
65 |
66 | /**
67 | * Normalizes the vector described by the CGPoint to length 1.0 and returns
68 | * the result as a new CGPoint.
69 | */
70 | func normalized() -> CGPoint {
71 | let len = length()
72 | return len>0 ? self / len : CGPoint.zero
73 | }
74 |
75 | /**
76 | * Normalizes the vector described by the CGPoint to length 1.0.
77 | */
78 | public mutating func normalize() -> CGPoint {
79 | self = normalized()
80 | return self
81 | }
82 |
83 | /**
84 | * Calculates the distance between two CGPoints. Pythagoras!
85 | */
86 | public func distanceTo(point: CGPoint) -> CGFloat {
87 | return (self - point).length()
88 | }
89 |
90 | /**
91 | * Returns the angle in radians of the vector described by the CGPoint.
92 | * The range of the angle is -π to π; an angle of 0 points to the right.
93 | */
94 | public var angle: CGFloat {
95 | return atan2(y, x)
96 | }
97 | }
98 |
99 | /**
100 | * Adds two CGPoint values and returns the result as a new CGPoint.
101 | */
102 | public func + (left: CGPoint, right: CGPoint) -> CGPoint {
103 | return CGPoint(x: left.x + right.x, y: left.y + right.y)
104 | }
105 |
106 | /**
107 | * Increments a CGPoint with the value of another.
108 | */
109 | public func += ( left: inout CGPoint, right: CGPoint) {
110 | left = left + right
111 | }
112 |
113 | /**
114 | * Adds a CGVector to this CGPoint and returns the result as a new CGPoint.
115 | */
116 | public func + (left: CGPoint, right: CGVector) -> CGPoint {
117 | return CGPoint(x: left.x + right.dx, y: left.y + right.dy)
118 | }
119 |
120 | /**
121 | * Increments a CGPoint with the value of a CGVector.
122 | */
123 | public func += ( left: inout CGPoint, right: CGVector) {
124 | left = left + right
125 | }
126 |
127 | /**
128 | * Subtracts two CGPoint values and returns the result as a new CGPoint.
129 | */
130 | public func - (left: CGPoint, right: CGPoint) -> CGPoint {
131 | return CGPoint(x: left.x - right.x, y: left.y - right.y)
132 | }
133 |
134 | /**
135 | * Decrements a CGPoint with the value of another.
136 | */
137 | public func -= ( left: inout CGPoint, right: CGPoint) {
138 | left = left - right
139 | }
140 |
141 | /**
142 | * Subtracts a CGVector from a CGPoint and returns the result as a new CGPoint.
143 | */
144 | public func - (left: CGPoint, right: CGVector) -> CGPoint {
145 | return CGPoint(x: left.x - right.dx, y: left.y - right.dy)
146 | }
147 |
148 | /**
149 | * Decrements a CGPoint with the value of a CGVector.
150 | */
151 | public func -= ( left: inout CGPoint, right: CGVector) {
152 | left = left - right
153 | }
154 |
155 | /**
156 | * Multiplies two CGPoint values and returns the result as a new CGPoint.
157 | */
158 | public func * (left: CGPoint, right: CGPoint) -> CGPoint {
159 | return CGPoint(x: left.x * right.x, y: left.y * right.y)
160 | }
161 |
162 | /**
163 | * Multiplies a CGPoint with another.
164 | */
165 | public func *= ( left: inout CGPoint, right: CGPoint) {
166 | left = left * right
167 | }
168 |
169 | /**
170 | * Multiplies the x and y fields of a CGPoint with the same scalar value and
171 | * returns the result as a new CGPoint.
172 | */
173 | public func * (point: CGPoint, scalar: CGFloat) -> CGPoint {
174 | return CGPoint(x: point.x * scalar, y: point.y * scalar)
175 | }
176 |
177 | /**
178 | * Multiplies the x and y fields of a CGPoint with the same scalar value.
179 | */
180 | public func *= ( point: inout CGPoint, scalar: CGFloat) {
181 | point = point * scalar
182 | }
183 |
184 | /**
185 | * Multiplies a CGPoint with a CGVector and returns the result as a new CGPoint.
186 | */
187 | public func * (left: CGPoint, right: CGVector) -> CGPoint {
188 | return CGPoint(x: left.x * right.dx, y: left.y * right.dy)
189 | }
190 |
191 | /**
192 | * Multiplies a CGPoint with a CGVector.
193 | */
194 | public func *= ( left: inout CGPoint, right: CGVector) {
195 | left = left * right
196 | }
197 |
198 | /**
199 | * Divides two CGPoint values and returns the result as a new CGPoint.
200 | */
201 | public func / (left: CGPoint, right: CGPoint) -> CGPoint {
202 | return CGPoint(x: left.x / right.x, y: left.y / right.y)
203 | }
204 |
205 | /**
206 | * Divides a CGPoint by another.
207 | */
208 | public func /= ( left: inout CGPoint, right: CGPoint) {
209 | left = left / right
210 | }
211 |
212 | /**
213 | * Divides the x and y fields of a CGPoint by the same scalar value and returns
214 | * the result as a new CGPoint.
215 | */
216 | public func / (point: CGPoint, scalar: CGFloat) -> CGPoint {
217 | return CGPoint(x: point.x / scalar, y: point.y / scalar)
218 | }
219 |
220 | /**
221 | * Divides the x and y fields of a CGPoint by the same scalar value.
222 | */
223 | public func /= ( point: inout CGPoint, scalar: CGFloat) {
224 | point = point / scalar
225 | }
226 |
227 | /**
228 | * Divides a CGPoint by a CGVector and returns the result as a new CGPoint.
229 | */
230 | public func / (left: CGPoint, right: CGVector) -> CGPoint {
231 | return CGPoint(x: left.x / right.dx, y: left.y / right.dy)
232 | }
233 |
234 | /**
235 | * Divides a CGPoint by a CGVector.
236 | */
237 | public func /= ( left: inout CGPoint, right: CGVector) {
238 | left = left / right
239 | }
240 |
241 | /**
242 | * Performs a linear interpolation between two CGPoint values.
243 | */
244 | public func lerp(_ start: CGPoint, end: CGPoint, t: CGFloat) -> CGPoint {
245 | return CGPoint(x: start.x + (end.x - start.x)*t, y: start.y + (end.y - start.y)*t)
246 | }
247 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/Resources/SKTUtils/SKTTimingFunctions.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Timing functions for SKTEffects. Based on Robert Penner's easing equations
3 | * http://robertpenner.com/easing/ and https://github.com/warrenm/AHEasing
4 | *
5 | * Copyright (c) 2013-2014 Razeware LLC
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | import Foundation
27 | import CoreGraphics
28 |
29 | public func SKTTimingFunctionLinear(t: CGFloat) -> CGFloat {
30 | return t
31 | }
32 |
33 | public func SKTTimingFunctionQuadraticEaseIn(t: CGFloat) -> CGFloat {
34 | return t * t
35 | }
36 |
37 | public func SKTTimingFunctionQuadraticEaseOut(t: CGFloat) -> CGFloat {
38 | return t * (2.0 - t)
39 | }
40 |
41 | public func SKTTimingFunctionQuadraticEaseInOut(t: CGFloat) -> CGFloat {
42 | if t < 0.5 {
43 | return 2.0 * t * t
44 | } else {
45 | let f = t - 1.0
46 | return 1.0 - 2.0 * f * f
47 | }
48 | }
49 |
50 | func SKTTimingFunctionCubicEaseIn(t: CGFloat) -> CGFloat {
51 | return t * t * t
52 | }
53 |
54 | func SKTTimingFunctionCubicEaseOut(t: CGFloat) -> CGFloat {
55 | let f = t - 1.0
56 | return 1.0 + f * f * f
57 | }
58 |
59 | public func SKTTimingFunctionCubicEaseInOut(t: CGFloat) -> CGFloat {
60 | if t < 0.5 {
61 | return 4.0 * t * t * t
62 | } else {
63 | let f = t - 1.0
64 | return 1.0 + 4.0 * f * f * f
65 | }
66 | }
67 |
68 | public func SKTTimingFunctionQuarticEaseIn(t: CGFloat) -> CGFloat {
69 | return t * t * t * t
70 | }
71 |
72 | public func SKTTimingFunctionQuarticEaseOut(t: CGFloat) -> CGFloat {
73 | let f = t - 1.0
74 | return 1.0 - f * f * f * f
75 | }
76 |
77 | public func SKTTimingFunctionQuarticEaseInOut(t: CGFloat) -> CGFloat {
78 | if t < 0.5 {
79 | return 8.0 * t * t * t * t
80 | } else {
81 | let f = t - 1.0
82 | return 1.0 - 8.0 * f * f * f * f
83 | }
84 | }
85 |
86 | public func SKTTimingFunctionQuinticEaseIn(t: CGFloat) -> CGFloat {
87 | return t * t * t * t * t
88 | }
89 |
90 | public func SKTTimingFunctionQuinticEaseOut(t: CGFloat) -> CGFloat {
91 | let f = t - 1.0
92 | return 1.0 + f * f * f * f * f
93 | }
94 |
95 | func SKTTimingFunctionQuinticEaseInOut(t: CGFloat) -> CGFloat {
96 | if t < 0.5 {
97 | return 16.0 * t * t * t * t * t
98 | } else {
99 | let f = t - 1.0
100 | return 1.0 + 16.0 * f * f * f * f * f
101 | }
102 | }
103 |
104 | public func SKTTimingFunctionSineEaseIn(t: CGFloat) -> CGFloat {
105 | return sin((t - 1.0) * π/2) + 1.0
106 | }
107 |
108 | public func SKTTimingFunctionSineEaseOut(t: CGFloat) -> CGFloat {
109 | return sin(t * π/2)
110 | }
111 |
112 | public func SKTTimingFunctionSineEaseInOut(t: CGFloat) -> CGFloat {
113 | return 0.5 * (1.0 - cos(t * π))
114 | }
115 |
116 | public func SKTTimingFunctionCircularEaseIn(t: CGFloat) -> CGFloat {
117 | return 1.0 - sqrt(1.0 - t * t)
118 | }
119 |
120 | public func SKTTimingFunctionCircularEaseOut(t: CGFloat) -> CGFloat {
121 | return sqrt((2.0 - t) * t)
122 | }
123 |
124 | public func SKTTimingFunctionCircularEaseInOut(t: CGFloat) -> CGFloat {
125 | if t < 0.5 {
126 | return 0.5 * (1.0 - sqrt(1.0 - 4.0 * t * t))
127 | } else {
128 | return 0.5 * sqrt(-4.0 * t * t + 8.0 * t - 3.0) + 0.5
129 | }
130 | }
131 |
132 | public func SKTTimingFunctionExponentialEaseIn(t: CGFloat) -> CGFloat {
133 | return (t == 0.0) ? t : pow(2.0, 10.0 * (t - 1.0))
134 | }
135 |
136 | public func SKTTimingFunctionExponentialEaseOut(t: CGFloat) -> CGFloat {
137 | return (t == 1.0) ? t : 1.0 - pow(2.0, -10.0 * t)
138 | }
139 |
140 | public func SKTTimingFunctionExponentialEaseInOut(t: CGFloat) -> CGFloat {
141 | if t == 0.0 || t == 1.0 {
142 | return t
143 | } else if t < 0.5 {
144 | return 0.5 * pow(2.0, 20.0 * t - 10.0)
145 | } else {
146 | return 1.0 - 0.5 * pow(2.0, -20.0 * t + 10.0)
147 | }
148 | }
149 |
150 | public func SKTTimingFunctionElasticEaseIn(t: CGFloat) -> CGFloat {
151 | return sin(13.0 * π/2 * t) * pow(2.0, 10.0 * (t - 1.0))
152 | }
153 |
154 | public func SKTTimingFunctionElasticEaseOut(t: CGFloat) -> CGFloat {
155 | return sin(-13.0 * π/2 * (t + 1.0)) * pow(2.0, -10.0 * t) + 1.0
156 | }
157 |
158 | public func SKTTimingFunctionElasticEaseInOut(t: CGFloat) -> CGFloat {
159 | if t < 0.5 {
160 | return 0.5 * sin(13.0 * π * t) * pow(2.0, 20.0 * t - 10.0)
161 | } else {
162 | return 0.5 * sin(-13.0 * π * t) * pow(2.0, -20.0 * t + 10.0) + 1.0
163 | }
164 | }
165 |
166 | public func SKTTimingFunctionBackEaseIn(t: CGFloat) -> CGFloat {
167 | let s: CGFloat = 1.70158
168 | return ((s + 1.0) * t - s) * t * t
169 | }
170 |
171 | public func SKTTimingFunctionBackEaseOut(t: CGFloat) -> CGFloat {
172 | let s: CGFloat = 1.70158
173 | let f = 1.0 - t
174 | return 1.0 - ((s + 1.0) * f - s) * f * f
175 | }
176 |
177 | public func SKTTimingFunctionBackEaseInOut(t: CGFloat) -> CGFloat {
178 | let s: CGFloat = 1.70158
179 | if t < 0.5 {
180 | let f = 2.0 * t
181 | return 0.5 * ((s + 1.0) * f - s) * f * f
182 | } else {
183 | let f = 2.0 * (1.0 - t)
184 | return 1.0 - 0.5 * ((s + 1.0) * f - s) * f * f
185 | }
186 | }
187 |
188 | public func SKTTimingFunctionExtremeBackEaseIn(t: CGFloat) -> CGFloat {
189 | return (t * t - sin(t * π)) * t
190 | }
191 |
192 | public func SKTTimingFunctionExtremeBackEaseOut(t: CGFloat) -> CGFloat {
193 | let f = 1.0 - t
194 | return 1.0 - (f * f - sin(f * π)) * f
195 | }
196 |
197 | public func SKTTimingFunctionExtremeBackEaseInOut(t: CGFloat) -> CGFloat {
198 | if t < 0.5 {
199 | let f = 2.0 * t
200 | return 0.5 * (f * f - sin(f * π)) * f
201 | } else {
202 | let f = 2.0 * (1.0 - t)
203 | return 1.0 - 0.5 * (f * f - sin(f * π)) * f
204 | }
205 | }
206 |
207 | public func SKTTimingFunctionBounceEaseIn(t: CGFloat) -> CGFloat {
208 | return 1.0 - SKTTimingFunctionBounceEaseOut(t: 1.0 - t)
209 | }
210 |
211 | public func SKTTimingFunctionBounceEaseOut(t: CGFloat) -> CGFloat {
212 | if t < 1.0 / 2.75 {
213 | return 7.5625 * t * t
214 | } else if t < 2.0 / 2.75 {
215 | let f = t - 1.5 / 2.75
216 | return 7.5625 * f * f + 0.75
217 | } else if t < 2.5 / 2.75 {
218 | let f = t - 2.25 / 2.75
219 | return 7.5625 * f * f + 0.9375
220 | } else {
221 | let f = t - 2.625 / 2.75
222 | return 7.5625 * f * f + 0.984375
223 | }
224 | }
225 |
226 | public func SKTTimingFunctionBounceEaseInOut(t: CGFloat) -> CGFloat {
227 | if t < 0.5 {
228 | return 0.5 * SKTTimingFunctionBounceEaseIn(t: t * 2.0)
229 | } else {
230 | return 0.5 * SKTTimingFunctionBounceEaseOut(t: t * 2.0 - 1.0) + 0.5
231 | }
232 | }
233 |
234 | public func SKTTimingFunctionSmoothstep(t: CGFloat) -> CGFloat {
235 | return t * t * (3 - 2 * t)
236 | }
237 |
238 | public func SKTCreateShakeFunction(oscillations: Int) -> (CGFloat) -> CGFloat {
239 | return {t in -pow(2.0, -10.0 * t) * sin(t * π * CGFloat(oscillations) * 2.0) + 1.0}
240 | }
241 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird/GameScene.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameScene.swift
3 | // Flappy Bird
4 | //
5 | // Created by i-Techsys.com on 16/12/10.
6 | // Copyright © 2016年 i-Techsys. All rights reserved.
7 | // // 多边形工具 - http://stackoverflow.com/questions/19040144 Skite
8 |
9 | import SpriteKit
10 | import GameplayKit
11 |
12 | class GameScene: SKScene {
13 | // MARK: - 属性
14 | let 游戏世界 = SKNode()
15 | var 游戏区域起始点: CGFloat = 0
16 | var 游戏区域的高度: CGFloat = 0
17 | let 主角 = SKSpriteNode(imageNamed: "Bird0")
18 | let 帽子🎩 = SKSpriteNode(imageNamed: "Sombrero")
19 |
20 | // MARK: - 变动属性
21 | var 上一次更新时间: TimeInterval = 0
22 | var dt: TimeInterval = 0
23 |
24 | let k重力: CGFloat = -400.0
25 | let k上冲速度: CGFloat = 200
26 | var 速度 = CGPoint.zero
27 | let k前景地面数 = 2
28 | let k前景移动速度: CGFloat = -150.0
29 | let k底部障碍物的最小乘数: CGFloat = 0.1
30 | let k底部障碍物的最大乘数: CGFloat = 0.6
31 | let k缺口参数: CGFloat = 3.5
32 | let k首次生成障碍延迟时间: TimeInterval = 1.75
33 | let k每次生成障碍延迟时间: TimeInterval = 1.5
34 |
35 | let k留白: CGFloat = 20
36 | let k字体名字 = "AmericanTypewriter-Bold"
37 | var 得分标签: SKLabelNode!
38 | var 当前分数 = 0
39 | let k动画延迟 = 0.3
40 | let k角色动画总帧数 = 4
41 |
42 | var 主角撞击了地面布尔类型: Bool = false
43 | var 主角撞击了障碍物布尔类型: Bool = false
44 | var 当前游戏状态: 游戏状态 = .主菜单
45 |
46 | // MARK: - 创建音效
47 | let 叮的音效 = SKAction.playSoundFileNamed("ding.wav", waitForCompletion: false)
48 | let 拍打的音效 = SKAction.playSoundFileNamed("flapping.wav", waitForCompletion: false)
49 | let 摔倒的音效 = SKAction.playSoundFileNamed("whack.wav", waitForCompletion: false)
50 | let 下落的音效 = SKAction.playSoundFileNamed("falling.wav", waitForCompletion: false)
51 | let 撞击地面的音效 = SKAction.playSoundFileNamed("hitGround.wav", waitForCompletion: false)
52 | let 砰的音效 = SKAction.playSoundFileNamed("pop.wav", waitForCompletion: false)
53 | let 得分的音效 = SKAction.playSoundFileNamed("coin.wav", waitForCompletion: false)
54 |
55 | override func didMove(to view: SKView) {
56 | // 设置物理引擎代理
57 | physicsWorld.contactDelegate = self
58 |
59 | // 关掉重力
60 | physicsWorld.gravity = CGVector.zero
61 |
62 | addChild(游戏世界)
63 |
64 | 切换到主菜单()
65 | }
66 |
67 | // MARK: - 游戏流程
68 | fileprivate func 创建障碍物(_ 图片名: String) -> SKSpriteNode {
69 | let 障碍物 = SKSpriteNode(imageNamed: 图片名)
70 | 障碍物.zPosition = 图层.障碍物.rawValue
71 | 障碍物.userData = NSMutableDictionary()
72 |
73 | let offsetX = 障碍物.size.width * 障碍物.anchorPoint.x
74 | let offsetY = 障碍物.size.height * 障碍物.anchorPoint.y
75 | let path = CGMutablePath()
76 | path.move(to: CGPoint(x: 4 - offsetX, y: 0 - offsetY), transform: CGAffineTransform.identity)
77 | path.addLine(to: CGPoint(x: 7 - offsetX, y: 307 - offsetY), transform: CGAffineTransform.identity)
78 | path.addLine(to: CGPoint(x: 47 - offsetX, y: 308 - offsetY), transform: CGAffineTransform.identity)
79 | path.addLine(to: CGPoint(x: 48 - offsetX, y: 1 - offsetY), transform: CGAffineTransform.identity)
80 | path.closeSubpath()
81 |
82 | 障碍物.physicsBody = SKPhysicsBody(polygonFrom: path)
83 | 障碍物.physicsBody?.categoryBitMask = 物理层.障碍物
84 | 障碍物.physicsBody?.collisionBitMask = 0
85 | 障碍物.physicsBody?.contactTestBitMask = 物理层.游戏角色
86 |
87 | return 障碍物
88 | }
89 |
90 | fileprivate func 生成障碍物() {
91 | let 底部障碍物 = 创建障碍物("CactusBottom")
92 | 底部障碍物.name = "底部障碍物"
93 | let 起始X坐标 = size.width + 底部障碍物.size.width/2
94 | let Y最小坐标 = (游戏区域起始点 - 底部障碍物.size.height/2) + 游戏区域的高度*k底部障碍物的最小乘数
95 | let Y最大坐标 = (游戏区域起始点 - 底部障碍物.size.height/2) + 游戏区域的高度*k底部障碍物的最大乘数
96 |
97 | 底部障碍物.position = CGPoint(x: 起始X坐标, y: CGFloat.random(min: Y最小坐标, max: Y最大坐标))
98 | 游戏世界.addChild(底部障碍物)
99 |
100 | let 顶部障碍物 = 创建障碍物("CactusTop")
101 | 顶部障碍物.name = "顶部障碍物"
102 | 顶部障碍物.zPosition = CGFloat(180).degreesToRadians()
103 | 顶部障碍物.position = CGPoint(x: 起始X坐标, y: 底部障碍物.position.y + 底部障碍物.size.height/2 + 顶部障碍物.size.height/2 + 主角.size.height*k缺口参数)
104 | 游戏世界.addChild(顶部障碍物)
105 |
106 | let X轴移动距离 = -(size.width + 底部障碍物.size.width)
107 | let 移动持续时间 = X轴移动距离 / k前景移动速度
108 |
109 | let 移动的动作序列 = SKAction.sequence([
110 | SKAction.moveBy(x: X轴移动距离, y: 0, duration: TimeInterval(移动持续时间)),
111 | SKAction.removeFromParent()
112 | ])
113 | 底部障碍物.run(移动的动作序列)
114 | 顶部障碍物.run(移动的动作序列)
115 | }
116 |
117 | fileprivate func 无限重生障碍物() {
118 | let 首次延迟 = SKAction.wait(forDuration: k首次生成障碍延迟时间)
119 | let 重生障碍 = SKAction.run(生成障碍物)
120 | let 每次重生间隔 = SKAction.wait(forDuration: k每次生成障碍延迟时间)
121 | let 重生的动作队列 = SKAction.sequence([重生障碍,每次重生间隔])
122 | let 无限重生 = SKAction.repeatForever(重生的动作队列)
123 | let 总的动作队列 = SKAction.sequence([首次延迟,无限重生])
124 | run(总的动作队列, withKey: "重生")
125 | }
126 |
127 | // MARK: - Touch Begin
128 | override func touchesBegan(_ touches: Set, with event: UIEvent?) {
129 | guard let 点击 = touches.first else { return }
130 |
131 | let 点击位置 = 点击.location(in: self)
132 |
133 | switch 当前游戏状态 {
134 | case .主菜单:
135 | if 点击位置.y < size.height * 0.15 {
136 | 去学习()
137 | } else if 点击位置.x < size.width/2 {
138 | 切换到教程状态()
139 | } else {
140 | 去评价()
141 | }
142 | break
143 | case .教程:
144 | 切换到游戏状态()
145 | break
146 | case .游戏:
147 | // 增加上冲速度
148 | 主角飞一下()
149 | break
150 | case .跌落:
151 | break
152 | case .显示分数:
153 | break
154 | case .结束🔚:
155 | 切换到新游戏()
156 | break
157 | }
158 | }
159 |
160 | fileprivate func 主角飞一下() {
161 | // 播放音效
162 | run(拍打的音效)
163 | 速度 = CGPoint(x: 0, y: k上冲速度)
164 |
165 | /// 帽子的动画
166 | let 向上移动 = SKAction.moveBy(x: 0, y: 12, duration: 0.15)
167 | 向上移动.timingMode = .easeInEaseOut
168 | let 向下移动 = 向上移动.reversed()
169 | 帽子🎩.run(SKAction.sequence([向上移动, 向下移动]))
170 | }
171 |
172 |
173 | // MARK: - 更新
174 | override func update(_ 当前时间: TimeInterval) {
175 | if 上一次更新时间 > 0 {
176 | dt = 当前时间 - 上一次更新时间
177 | }else {
178 | dt = 0
179 | }
180 | 上一次更新时间 = 当前时间
181 |
182 | switch 当前游戏状态 {
183 | case .主菜单:
184 |
185 | break
186 | case .教程:
187 | // 切换到游戏状态()
188 | break
189 | case .游戏:
190 | 更新主角()
191 | 更新前景()
192 | 撞击了地面的检查()
193 | 撞击了障碍物的检查()
194 | 更新得分()
195 | break
196 | case .跌落:
197 | 更新主角()
198 | 撞击了地面的检查()
199 | break
200 | case .显示分数:
201 | break
202 | case .结束🔚:
203 | 切换到新游戏()
204 | break
205 | }
206 | }
207 |
208 | fileprivate func 更新主角() {
209 | let 加速度 = CGPoint(x: 0, y: k重力)
210 | 速度 = 速度 + 加速度 * CGFloat(dt)
211 | 主角.position = 主角.position + 速度 * CGFloat(dt)
212 |
213 | // 检测撞击地面时让其停留在地面上
214 | if 主角.position.y - 主角.size.height/2 < 游戏区域起始点 {
215 | 主角.position = CGPoint(x: 主角.position.x, y: 主角.size.height/2 + 游戏区域起始点)
216 | }
217 | }
218 |
219 | fileprivate func 更新前景() {
220 | 游戏世界.enumerateChildNodes(withName: "前景") { (匹配单位, _) in
221 | if let 前景 = 匹配单位 as? SKSpriteNode {
222 | let 地面的移动速度 = CGPoint(x: self.k前景移动速度, y: 0)
223 | 前景.position += 地面的移动速度 * CGFloat(self.dt)
224 |
225 | if 前景.position.x < -前景.size.width {
226 | 前景.position += CGPoint(x: 前景.size.width*CGFloat(self.k前景地面数), y: 0)
227 | }
228 | }
229 | }
230 | }
231 | }
232 |
233 | // MARK: - 设置的相关方法
234 | extension GameScene {
235 | fileprivate func 设置教程() {
236 | let 教程 = SKSpriteNode(imageNamed: "Tutorial")
237 | 教程.position = CGPoint(x: size.width * 0.5 , y: 游戏区域的高度 * 0.4 + 游戏区域起始点)
238 | 教程.name = "教程"
239 | 教程.zPosition = 图层.UI.rawValue
240 | 游戏世界.addChild(教程)
241 |
242 | let 准备 = SKSpriteNode(imageNamed: "Ready")
243 | 准备.position = CGPoint(x: size.width * 0.5, y: 游戏区域的高度 * 0.7 + 游戏区域起始点)
244 | 准备.name = "教程"
245 | 准备.zPosition = 图层.UI.rawValue
246 | 游戏世界.addChild(准备)
247 |
248 | let 向上移动 = SKAction.moveBy(x: 0, y: 50, duration: 0.4)
249 | 向上移动.timingMode = .easeInEaseOut
250 | let 向下移动 = 向上移动.reversed()
251 |
252 | 主角.run(SKAction.repeatForever(SKAction.sequence([
253 | 向上移动,向下移动
254 | ])), withKey: "起飞")
255 |
256 | var 角色贴图组: Array = []
257 |
258 | for i in 0.. 最高分() {
343 | 设置最高分(最高分: 当前分数)
344 | }
345 |
346 | let 记分板 = SKSpriteNode(imageNamed: "ScoreCard")
347 | 记分板.position = CGPoint(x: size.width/2, y: size.height/2)
348 | 记分板.zPosition = 图层.UI.rawValue
349 | 游戏世界.addChild(记分板)
350 |
351 | let 当前分数标签 = SKLabelNode(fontNamed: k字体名字)
352 | 当前分数标签.fontColor = SKColor(red: 101.0/255.0, green: 71.0/255.0, blue: 73.0/255.0, alpha: 1.0)
353 | 当前分数标签.position = CGPoint(x: -记分板.size.width / 4, y: -记分板.size.height / 3)
354 | 当前分数标签.text = "\(当前分数)"
355 | 当前分数标签.zPosition = 图层.UI.rawValue
356 | 记分板.addChild(当前分数标签)
357 |
358 | let 最高分标签 = SKLabelNode(fontNamed: k字体名字)
359 | 最高分标签.fontColor = SKColor(red: 101.0/255.0, green: 71.0/255.0, blue: 73.0/255.0, alpha: 1.0)
360 | 最高分标签.position = CGPoint(x: 记分板.size.width / 4, y: -记分板.size.height / 3)
361 | 最高分标签.text = "\(最高分())"
362 | 最高分标签.zPosition = 图层.UI.rawValue
363 | 记分板.addChild(最高分标签)
364 |
365 | let 游戏结束 = SKSpriteNode(imageNamed: "GameOver")
366 | 游戏结束.position = CGPoint(x: size.width/2, y: size.height/2 + 记分板.size.height/2 + k留白 + 游戏结束.size.height/2)
367 | 游戏结束.zPosition = 图层.UI.rawValue
368 | 游戏世界.addChild(游戏结束)
369 |
370 | let ok按钮 = SKSpriteNode(imageNamed: "Button")
371 | ok按钮.position = CGPoint(x: size.width/4, y: size.height/2 - 记分板.size.height/2 - k留白 - ok按钮.size.height/2)
372 | ok按钮.zPosition = 图层.UI.rawValue
373 | 游戏世界.addChild(ok按钮)
374 |
375 | let ok = SKSpriteNode(imageNamed: "OK")
376 | ok.position = CGPoint.zero
377 | ok.zPosition = 图层.UI.rawValue
378 | ok按钮.addChild(ok)
379 |
380 | let 分享按钮 = SKSpriteNode(imageNamed: "ButtonRight")
381 | 分享按钮.position = CGPoint(x: size.width * 0.75, y: size.height/2 - 记分板.size.height/2 - k留白 - 分享按钮.size.height/2)
382 | 分享按钮.zPosition = 图层.UI.rawValue
383 | 游戏世界.addChild(分享按钮)
384 |
385 | let 分享 = SKSpriteNode(imageNamed: "Share")
386 | 分享.position = CGPoint.zero
387 | 分享.zPosition = 图层.UI.rawValue
388 | 分享按钮.addChild(分享)
389 |
390 | 游戏结束.setScale(0)
391 | 游戏结束.alpha = 0
392 | let 动画组 = SKAction.group([
393 | SKAction.fadeIn(withDuration: k动画延迟),
394 | SKAction.scale(to: 1.0, duration: k动画延迟)
395 | ])
396 | 动画组.timingMode = .easeInEaseOut
397 |
398 | 游戏结束.run(SKAction.sequence([
399 | SKAction.wait(forDuration: k动画延迟),
400 | 动画组
401 | ]))
402 |
403 | 记分板.position = CGPoint(x: size.width / 2, y: -记分板.size.height/2)
404 | let 向上移动的动画 = SKAction.move(to: CGPoint(x: size.width / 2, y: size.height / 2), duration: k动画延迟)
405 | 向上移动的动画.timingMode = .easeInEaseOut
406 | 记分板.run(SKAction.sequence([
407 | SKAction.wait(forDuration: k动画延迟 * 2),
408 | 向上移动的动画
409 | ]))
410 |
411 | ok按钮.alpha = 0
412 | 分享按钮.alpha = 0
413 |
414 | let 渐变动画 = SKAction.sequence([
415 | SKAction.wait(forDuration: k动画延迟 * 3),
416 | SKAction.fadeIn(withDuration: k动画延迟)
417 | ])
418 | ok按钮.run(渐变动画)
419 | 分享按钮.run(渐变动画)
420 |
421 | let 声音特效 = SKAction.sequence([
422 | SKAction.wait(forDuration: k动画延迟),
423 | 砰的音效,
424 | SKAction.wait(forDuration: k动画延迟),
425 | 砰的音效,
426 | SKAction.wait(forDuration: k动画延迟),
427 | 砰的音效,
428 | SKAction.run(切换到结束状态)
429 | ])
430 |
431 | run(声音特效)
432 | }
433 |
434 | func 设置主菜单() {
435 |
436 | // logo
437 |
438 | let logo = SKSpriteNode(imageNamed: "Logo")
439 | logo.position = CGPoint(x: size.width/2, y: size.height * 0.8)
440 | logo.name = "主菜单"
441 | logo.zPosition = 图层.UI.rawValue
442 | 游戏世界.addChild(logo)
443 |
444 | // 开始游戏按钮
445 |
446 | let 开始游戏按钮 = SKSpriteNode(imageNamed: "Button")
447 | 开始游戏按钮.position = CGPoint(x: size.width * 0.25, y: size.height * 0.25)
448 | 开始游戏按钮.name = "主菜单"
449 | 开始游戏按钮.zPosition = 图层.UI.rawValue
450 | 游戏世界.addChild(开始游戏按钮)
451 |
452 | let 游戏 = SKSpriteNode(imageNamed: "Play")
453 | 游戏.position = CGPoint.zero
454 | 开始游戏按钮.addChild(游戏)
455 |
456 | // 评价按钮
457 |
458 | let 评价按钮 = SKSpriteNode(imageNamed: "Button")
459 | 评价按钮.position = CGPoint(x: size.width * 0.75, y: size.height * 0.25)
460 | 评价按钮.zPosition = 图层.UI.rawValue
461 | 评价按钮.name = "主菜单"
462 | 游戏世界.addChild(评价按钮)
463 |
464 | let 评价 = SKSpriteNode(imageNamed: "Rate")
465 | 评价.position = CGPoint.zero
466 | 评价按钮.addChild(评价)
467 |
468 | // 学习按钮
469 |
470 | let 学习 = SKSpriteNode(imageNamed: "button_learn")
471 | 学习.position = CGPoint(x: size.width * 0.5, y: 学习.size.height/2 + k留白)
472 | 学习.name = "主菜单"
473 | 学习.zPosition = 图层.UI.rawValue
474 | 游戏世界.addChild(学习)
475 |
476 | // 学习按钮的动画
477 | let 放大动画 = SKAction.scale(to: 1.02, duration: 0.75)
478 | 放大动画.timingMode = .easeInEaseOut
479 |
480 | let 缩小动画 = SKAction.scale(to: 0.98, duration: 0.75)
481 | 缩小动画.timingMode = .easeInEaseOut
482 |
483 | 学习.run(SKAction.repeatForever(SKAction.sequence([
484 | 放大动画,缩小动画
485 | ])), withKey: "主菜单")
486 | }
487 | }
488 |
489 | extension GameScene: SKPhysicsContactDelegate {
490 | func didEnd(_ 碰撞双方: SKPhysicsContact) {
491 | let 被撞对象 = 碰撞双方.bodyA.categoryBitMask ==
492 | 物理层.游戏角色 ? 碰撞双方.bodyB : 碰撞双方.bodyA
493 |
494 | if 被撞对象.categoryBitMask == 物理层.地面 {
495 | 主角撞击了地面布尔类型 = true
496 | }
497 | if 被撞对象.categoryBitMask == 物理层.障碍物 {
498 | 主角撞击了地面布尔类型 = true
499 | 主角撞击了障碍物布尔类型 = true
500 | }
501 |
502 | }
503 |
504 | func didBegin(_ contact: SKPhysicsContact) {
505 |
506 | }
507 | }
508 |
509 |
510 | // MARK: - 游戏状态
511 | extension GameScene {
512 | fileprivate func 撞击了障碍物的检查() {
513 | if 主角撞击了障碍物布尔类型 {
514 | 主角撞击了障碍物布尔类型 = false
515 | 切换到跌落状态()
516 | }
517 | }
518 |
519 | /// 更新得分
520 | func 更新得分() {
521 | 游戏世界.enumerateChildNodes(withName: "顶部障碍物") { (匹配单位, _) in
522 | if let 障碍物 = 匹配单位 as? SKSpriteNode {
523 | if let 已通过 = 障碍物.userData?["已通过"] as? NSNumber {
524 | if 已通过.boolValue {
525 | return // 已经计算过一次得分了
526 | }
527 | }
528 |
529 | if self.主角.position.x > (障碍物.position.x + 障碍物.size.width/2) {
530 | self.当前分数 += 1
531 | self.得分标签.text = "\(self.当前分数)"
532 | self.run(self.得分的音效)
533 |
534 | 障碍物.userData?["已通过"] = NSNumber(value: true)
535 | }
536 | }
537 | }
538 | }
539 |
540 |
541 | fileprivate func 停止重生障碍物() {
542 | removeAction(forKey: "重生")
543 | 游戏世界.enumerateChildNodes(withName: "底部障碍物") { (匹配单位, _) in
544 | 匹配单位.removeAllActions()
545 | }
546 | 游戏世界.enumerateChildNodes(withName: "顶部障碍物") { (匹配单位, _) in
547 | 匹配单位.removeAllActions()
548 | }
549 | }
550 |
551 | fileprivate func 撞击了地面的检查() {
552 | if 主角撞击了地面布尔类型 {
553 | 主角撞击了地面布尔类型 = false
554 | 速度 = CGPoint.zero
555 | 主角.zRotation = CGFloat(-90).degreesToRadians()
556 | 主角.position = CGPoint(x: 主角.position.x, y: 游戏区域起始点 + 主角.size.width/2)
557 |
558 | run(撞击地面的音效)
559 | 切换到显示分数的状态()
560 | }
561 | }
562 |
563 | // MARK: - 切换状态
564 | /// 切换到跌落状态
565 | fileprivate func 切换到跌落状态() {
566 | 当前游戏状态 = .跌落
567 |
568 | run(SKAction.sequence([
569 | 摔倒的音效,
570 | SKAction.wait(forDuration: 0.1),
571 | 下落的音效
572 | ]))
573 |
574 | 主角.removeAllActions()
575 | 停止重生障碍物()
576 | }
577 |
578 | fileprivate func 切换到显示分数的状态() {
579 | 当前游戏状态 = .显示分数
580 | 主角.removeAllActions()
581 | 停止重生障碍物()
582 | 设置记分板()
583 | }
584 |
585 | fileprivate func 切换到主菜单() {
586 | 当前游戏状态 = .主菜单
587 |
588 | 设置背景()
589 | 设置前景()
590 | 设置主角🐦()
591 | 设置帽子🎩()
592 | 设置主菜单()
593 | }
594 |
595 |
596 | fileprivate func 切换到教程状态() {
597 | 当前游戏状态 = .教程
598 |
599 | 游戏世界.enumerateChildNodes(withName: "主菜单") { (匹配单位, _) in
600 | 匹配单位.run(SKAction.sequence([
601 | SKAction.fadeOut(withDuration: 0.05),
602 | SKAction.removeFromParent() ]))
603 | }
604 |
605 | 设置得分标签()
606 | 设置教程()
607 | }
608 |
609 | fileprivate func 切换到游戏状态() {
610 | 当前游戏状态 = .游戏
611 |
612 | 游戏世界.enumerateChildNodes(withName: "教程") { (匹配单位, _) in
613 | 匹配单位.run(SKAction.sequence([
614 | SKAction.fadeOut(withDuration: 0.05),
615 | SKAction.removeFromParent() ]))
616 | }
617 |
618 | 无限重生障碍物()
619 | 主角飞一下()
620 | }
621 | }
622 |
623 | // MARK: 分数
624 | extension GameScene {
625 |
626 | func 最高分() -> Int {
627 | return UserDefaults.standard.integer(forKey: "最高分")
628 | }
629 |
630 | func 设置最高分(最高分: Int) {
631 | UserDefaults.standard.set(最高分, forKey: "最高分")
632 | UserDefaults.standard.synchronize()
633 | }
634 |
635 | func 切换到新游戏() {
636 | run(砰的音效)
637 |
638 | let 新的游戏场景 = GameScene.init(size: size)
639 | let 切换特效 = SKTransition.fade(with: SKColor.black, duration: 0.05)
640 | view?.presentScene(新的游戏场景, transition: 切换特效)
641 | }
642 |
643 | func 切换到结束状态() {
644 | 当前游戏状态 = .结束🔚
645 | }
646 | }
647 |
648 | // MARK: - 其他 https://github.com/LYM-mg/MGFlappy-Bird
649 | extension GameScene {
650 | fileprivate func 去学习() {
651 | let 学习代码网址 = "https://github.com/LYM-mg/MGFlappy-Bird"
652 | guard let url = URL(string: 学习代码网址) else { return }
653 | if UIApplication.shared.canOpenURL(url) {
654 | UIApplication.shared.openURL(url)
655 | }
656 | }
657 |
658 | fileprivate func 去评价() {
659 | let appStore网址 = "http://itunes.apple.com/app/id1077251372?mt=8"
660 | guard let url = URL(string: appStore网址) else { return }
661 | if UIApplication.shared.canOpenURL(url) {
662 | UIApplication.shared.openURL(url)
663 | }
664 | }
665 | }
666 |
--------------------------------------------------------------------------------
/Flappy Bird/Flappy Bird.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | C09C0B431DFEBEAB006E2E9B /* BitMaskType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C09C0B421DFEBEAB006E2E9B /* BitMaskType.swift */; };
11 | C0D88D531E0C077B002630B5 /* MGBird.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0D88D521E0C077B002630B5 /* MGBird.swift */; };
12 | C0F7BFF51DFC128600948E16 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7BFF41DFC128600948E16 /* AppDelegate.swift */; };
13 | C0F7BFF91DFC128600948E16 /* Actions.sks in Resources */ = {isa = PBXBuildFile; fileRef = C0F7BFF81DFC128600948E16 /* Actions.sks */; };
14 | C0F7BFFB1DFC128600948E16 /* GameScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7BFFA1DFC128600948E16 /* GameScene.swift */; };
15 | C0F7BFFD1DFC128600948E16 /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7BFFC1DFC128600948E16 /* GameViewController.swift */; };
16 | C0F7C0001DFC128600948E16 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C0F7BFFE1DFC128600948E16 /* Main.storyboard */; };
17 | C0F7C0021DFC128600948E16 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C0F7C0011DFC128600948E16 /* Assets.xcassets */; };
18 | C0F7C0051DFC128600948E16 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C0F7C0031DFC128600948E16 /* LaunchScreen.storyboard */; };
19 | C0F7C0581DFC194400948E16 /* backgrounds.atlas in Resources */ = {isa = PBXBuildFile; fileRef = C0F7C0411DFC194400948E16 /* backgrounds.atlas */; };
20 | C0F7C0591DFC194400948E16 /* sprites.atlas in Resources */ = {isa = PBXBuildFile; fileRef = C0F7C0421DFC194400948E16 /* sprites.atlas */; };
21 | C0F7C0661DFC194400948E16 /* coin.wav in Resources */ = {isa = PBXBuildFile; fileRef = C0F7C0511DFC194400948E16 /* coin.wav */; };
22 | C0F7C0671DFC194400948E16 /* ding.wav in Resources */ = {isa = PBXBuildFile; fileRef = C0F7C0521DFC194400948E16 /* ding.wav */; };
23 | C0F7C0681DFC194400948E16 /* falling.wav in Resources */ = {isa = PBXBuildFile; fileRef = C0F7C0531DFC194400948E16 /* falling.wav */; };
24 | C0F7C0691DFC194400948E16 /* flapping.wav in Resources */ = {isa = PBXBuildFile; fileRef = C0F7C0541DFC194400948E16 /* flapping.wav */; };
25 | C0F7C06A1DFC194400948E16 /* hitGround.wav in Resources */ = {isa = PBXBuildFile; fileRef = C0F7C0551DFC194400948E16 /* hitGround.wav */; };
26 | C0F7C06B1DFC194400948E16 /* pop.wav in Resources */ = {isa = PBXBuildFile; fileRef = C0F7C0561DFC194400948E16 /* pop.wav */; };
27 | C0F7C06C1DFC194400948E16 /* whack.wav in Resources */ = {isa = PBXBuildFile; fileRef = C0F7C0571DFC194400948E16 /* whack.wav */; };
28 | C0F7C07A1DFC207000948E16 /* CGFloat+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C06E1DFC207000948E16 /* CGFloat+Extensions.swift */; };
29 | C0F7C07B1DFC207000948E16 /* CGPoint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C06F1DFC207000948E16 /* CGPoint+Extensions.swift */; };
30 | C0F7C07C1DFC207000948E16 /* CGVector+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C0701DFC207000948E16 /* CGVector+Extensions.swift */; };
31 | C0F7C07D1DFC207000948E16 /* Int+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C0711DFC207000948E16 /* Int+Extensions.swift */; };
32 | C0F7C07E1DFC207000948E16 /* SKAction+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C0721DFC207000948E16 /* SKAction+Extensions.swift */; };
33 | C0F7C07F1DFC207000948E16 /* SKAction+SpecialEffects.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C0731DFC207000948E16 /* SKAction+SpecialEffects.swift */; };
34 | C0F7C0801DFC207000948E16 /* SKColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C0741DFC207000948E16 /* SKColor+Extensions.swift */; };
35 | C0F7C0811DFC207000948E16 /* SKNode+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C0751DFC207000948E16 /* SKNode+Extensions.swift */; };
36 | C0F7C0821DFC207000948E16 /* SKTAudio.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C0761DFC207000948E16 /* SKTAudio.swift */; };
37 | C0F7C0831DFC207000948E16 /* SKTEffects.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C0771DFC207000948E16 /* SKTEffects.swift */; };
38 | C0F7C0841DFC207000948E16 /* SKTTimingFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C0781DFC207000948E16 /* SKTTimingFunctions.swift */; };
39 | C0F7C0851DFC207000948E16 /* Vector3.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F7C0791DFC207000948E16 /* Vector3.swift */; };
40 | /* End PBXBuildFile section */
41 |
42 | /* Begin PBXFileReference section */
43 | C09C0B421DFEBEAB006E2E9B /* BitMaskType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BitMaskType.swift; sourceTree = ""; };
44 | C0D88D521E0C077B002630B5 /* MGBird.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGBird.swift; sourceTree = ""; };
45 | C0F7BFF11DFC128600948E16 /* MG Bird.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "MG Bird.app"; sourceTree = BUILT_PRODUCTS_DIR; };
46 | C0F7BFF41DFC128600948E16 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
47 | C0F7BFF81DFC128600948E16 /* Actions.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Actions.sks; sourceTree = ""; };
48 | C0F7BFFA1DFC128600948E16 /* GameScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameScene.swift; sourceTree = ""; };
49 | C0F7BFFC1DFC128600948E16 /* GameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = ""; };
50 | C0F7BFFF1DFC128600948E16 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
51 | C0F7C0011DFC128600948E16 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
52 | C0F7C0041DFC128600948E16 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
53 | C0F7C0061DFC128600948E16 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
54 | C0F7C0411DFC194400948E16 /* backgrounds.atlas */ = {isa = PBXFileReference; lastKnownFileType = folder.skatlas; path = backgrounds.atlas; sourceTree = ""; };
55 | C0F7C0421DFC194400948E16 /* sprites.atlas */ = {isa = PBXFileReference; lastKnownFileType = folder.skatlas; path = sprites.atlas; sourceTree = ""; };
56 | C0F7C0511DFC194400948E16 /* coin.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = coin.wav; sourceTree = ""; };
57 | C0F7C0521DFC194400948E16 /* ding.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = ding.wav; sourceTree = ""; };
58 | C0F7C0531DFC194400948E16 /* falling.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = falling.wav; sourceTree = ""; };
59 | C0F7C0541DFC194400948E16 /* flapping.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = flapping.wav; sourceTree = ""; };
60 | C0F7C0551DFC194400948E16 /* hitGround.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = hitGround.wav; sourceTree = ""; };
61 | C0F7C0561DFC194400948E16 /* pop.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = pop.wav; sourceTree = ""; };
62 | C0F7C0571DFC194400948E16 /* whack.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = whack.wav; sourceTree = ""; };
63 | C0F7C06E1DFC207000948E16 /* CGFloat+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGFloat+Extensions.swift"; sourceTree = ""; };
64 | C0F7C06F1DFC207000948E16 /* CGPoint+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGPoint+Extensions.swift"; sourceTree = ""; };
65 | C0F7C0701DFC207000948E16 /* CGVector+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGVector+Extensions.swift"; sourceTree = ""; };
66 | C0F7C0711DFC207000948E16 /* Int+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Int+Extensions.swift"; sourceTree = ""; };
67 | C0F7C0721DFC207000948E16 /* SKAction+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SKAction+Extensions.swift"; sourceTree = ""; };
68 | C0F7C0731DFC207000948E16 /* SKAction+SpecialEffects.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SKAction+SpecialEffects.swift"; sourceTree = ""; };
69 | C0F7C0741DFC207000948E16 /* SKColor+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SKColor+Extensions.swift"; sourceTree = ""; };
70 | C0F7C0751DFC207000948E16 /* SKNode+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SKNode+Extensions.swift"; sourceTree = ""; };
71 | C0F7C0761DFC207000948E16 /* SKTAudio.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SKTAudio.swift; sourceTree = ""; };
72 | C0F7C0771DFC207000948E16 /* SKTEffects.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SKTEffects.swift; sourceTree = ""; };
73 | C0F7C0781DFC207000948E16 /* SKTTimingFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SKTTimingFunctions.swift; sourceTree = ""; };
74 | C0F7C0791DFC207000948E16 /* Vector3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vector3.swift; sourceTree = ""; };
75 | /* End PBXFileReference section */
76 |
77 | /* Begin PBXFrameworksBuildPhase section */
78 | C0F7BFEE1DFC128600948E16 /* Frameworks */ = {
79 | isa = PBXFrameworksBuildPhase;
80 | buildActionMask = 2147483647;
81 | files = (
82 | );
83 | runOnlyForDeploymentPostprocessing = 0;
84 | };
85 | /* End PBXFrameworksBuildPhase section */
86 |
87 | /* Begin PBXGroup section */
88 | C09C0B411DFEBE6F006E2E9B /* Class */ = {
89 | isa = PBXGroup;
90 | children = (
91 | C09C0B421DFEBEAB006E2E9B /* BitMaskType.swift */,
92 | C0D88D521E0C077B002630B5 /* MGBird.swift */,
93 | );
94 | path = Class;
95 | sourceTree = "";
96 | };
97 | C0F7BFE81DFC128600948E16 = {
98 | isa = PBXGroup;
99 | children = (
100 | C0F7BFF31DFC128600948E16 /* Flappy Bird */,
101 | C0F7BFF21DFC128600948E16 /* Products */,
102 | );
103 | sourceTree = "";
104 | };
105 | C0F7BFF21DFC128600948E16 /* Products */ = {
106 | isa = PBXGroup;
107 | children = (
108 | C0F7BFF11DFC128600948E16 /* MG Bird.app */,
109 | );
110 | name = Products;
111 | sourceTree = "";
112 | };
113 | C0F7BFF31DFC128600948E16 /* Flappy Bird */ = {
114 | isa = PBXGroup;
115 | children = (
116 | C0F7C03F1DFC194400948E16 /* Resources */,
117 | C09C0B411DFEBE6F006E2E9B /* Class */,
118 | C0F7BFF41DFC128600948E16 /* AppDelegate.swift */,
119 | C0F7BFF81DFC128600948E16 /* Actions.sks */,
120 | C0F7BFFA1DFC128600948E16 /* GameScene.swift */,
121 | C0F7BFFC1DFC128600948E16 /* GameViewController.swift */,
122 | C0F7BFFE1DFC128600948E16 /* Main.storyboard */,
123 | C0F7C0011DFC128600948E16 /* Assets.xcassets */,
124 | C0F7C0031DFC128600948E16 /* LaunchScreen.storyboard */,
125 | C0F7C0061DFC128600948E16 /* Info.plist */,
126 | );
127 | path = "Flappy Bird";
128 | sourceTree = "";
129 | };
130 | C0F7C03F1DFC194400948E16 /* Resources */ = {
131 | isa = PBXGroup;
132 | children = (
133 | C0F7C0401DFC194400948E16 /* Art */,
134 | C0F7C06D1DFC207000948E16 /* SKTUtils */,
135 | C0F7C0501DFC194400948E16 /* Sounds */,
136 | );
137 | path = Resources;
138 | sourceTree = "";
139 | };
140 | C0F7C0401DFC194400948E16 /* Art */ = {
141 | isa = PBXGroup;
142 | children = (
143 | C0F7C0411DFC194400948E16 /* backgrounds.atlas */,
144 | C0F7C0421DFC194400948E16 /* sprites.atlas */,
145 | );
146 | path = Art;
147 | sourceTree = "";
148 | };
149 | C0F7C0501DFC194400948E16 /* Sounds */ = {
150 | isa = PBXGroup;
151 | children = (
152 | C0F7C0511DFC194400948E16 /* coin.wav */,
153 | C0F7C0521DFC194400948E16 /* ding.wav */,
154 | C0F7C0531DFC194400948E16 /* falling.wav */,
155 | C0F7C0541DFC194400948E16 /* flapping.wav */,
156 | C0F7C0551DFC194400948E16 /* hitGround.wav */,
157 | C0F7C0561DFC194400948E16 /* pop.wav */,
158 | C0F7C0571DFC194400948E16 /* whack.wav */,
159 | );
160 | path = Sounds;
161 | sourceTree = "";
162 | };
163 | C0F7C06D1DFC207000948E16 /* SKTUtils */ = {
164 | isa = PBXGroup;
165 | children = (
166 | C0F7C06E1DFC207000948E16 /* CGFloat+Extensions.swift */,
167 | C0F7C06F1DFC207000948E16 /* CGPoint+Extensions.swift */,
168 | C0F7C0701DFC207000948E16 /* CGVector+Extensions.swift */,
169 | C0F7C0711DFC207000948E16 /* Int+Extensions.swift */,
170 | C0F7C0721DFC207000948E16 /* SKAction+Extensions.swift */,
171 | C0F7C0731DFC207000948E16 /* SKAction+SpecialEffects.swift */,
172 | C0F7C0741DFC207000948E16 /* SKColor+Extensions.swift */,
173 | C0F7C0751DFC207000948E16 /* SKNode+Extensions.swift */,
174 | C0F7C0761DFC207000948E16 /* SKTAudio.swift */,
175 | C0F7C0771DFC207000948E16 /* SKTEffects.swift */,
176 | C0F7C0781DFC207000948E16 /* SKTTimingFunctions.swift */,
177 | C0F7C0791DFC207000948E16 /* Vector3.swift */,
178 | );
179 | path = SKTUtils;
180 | sourceTree = "";
181 | };
182 | /* End PBXGroup section */
183 |
184 | /* Begin PBXNativeTarget section */
185 | C0F7BFF01DFC128600948E16 /* Flappy Bird */ = {
186 | isa = PBXNativeTarget;
187 | buildConfigurationList = C0F7C0091DFC128600948E16 /* Build configuration list for PBXNativeTarget "Flappy Bird" */;
188 | buildPhases = (
189 | C0F7BFED1DFC128600948E16 /* Sources */,
190 | C0F7BFEE1DFC128600948E16 /* Frameworks */,
191 | C0F7BFEF1DFC128600948E16 /* Resources */,
192 | );
193 | buildRules = (
194 | );
195 | dependencies = (
196 | );
197 | name = "Flappy Bird";
198 | productName = "Flappy Bird";
199 | productReference = C0F7BFF11DFC128600948E16 /* MG Bird.app */;
200 | productType = "com.apple.product-type.application";
201 | };
202 | /* End PBXNativeTarget section */
203 |
204 | /* Begin PBXProject section */
205 | C0F7BFE91DFC128600948E16 /* Project object */ = {
206 | isa = PBXProject;
207 | attributes = {
208 | LastSwiftUpdateCheck = 0800;
209 | LastUpgradeCheck = 0800;
210 | ORGANIZATIONNAME = "i-Techsys";
211 | TargetAttributes = {
212 | C0F7BFF01DFC128600948E16 = {
213 | CreatedOnToolsVersion = 8.0;
214 | ProvisioningStyle = Automatic;
215 | };
216 | };
217 | };
218 | buildConfigurationList = C0F7BFEC1DFC128600948E16 /* Build configuration list for PBXProject "Flappy Bird" */;
219 | compatibilityVersion = "Xcode 3.2";
220 | developmentRegion = English;
221 | hasScannedForEncodings = 0;
222 | knownRegions = (
223 | en,
224 | Base,
225 | );
226 | mainGroup = C0F7BFE81DFC128600948E16;
227 | productRefGroup = C0F7BFF21DFC128600948E16 /* Products */;
228 | projectDirPath = "";
229 | projectRoot = "";
230 | targets = (
231 | C0F7BFF01DFC128600948E16 /* Flappy Bird */,
232 | );
233 | };
234 | /* End PBXProject section */
235 |
236 | /* Begin PBXResourcesBuildPhase section */
237 | C0F7BFEF1DFC128600948E16 /* Resources */ = {
238 | isa = PBXResourcesBuildPhase;
239 | buildActionMask = 2147483647;
240 | files = (
241 | C0F7C06C1DFC194400948E16 /* whack.wav in Resources */,
242 | C0F7C0001DFC128600948E16 /* Main.storyboard in Resources */,
243 | C0F7C0661DFC194400948E16 /* coin.wav in Resources */,
244 | C0F7C0021DFC128600948E16 /* Assets.xcassets in Resources */,
245 | C0F7C0581DFC194400948E16 /* backgrounds.atlas in Resources */,
246 | C0F7C0051DFC128600948E16 /* LaunchScreen.storyboard in Resources */,
247 | C0F7C06A1DFC194400948E16 /* hitGround.wav in Resources */,
248 | C0F7C06B1DFC194400948E16 /* pop.wav in Resources */,
249 | C0F7C0591DFC194400948E16 /* sprites.atlas in Resources */,
250 | C0F7C0671DFC194400948E16 /* ding.wav in Resources */,
251 | C0F7C0691DFC194400948E16 /* flapping.wav in Resources */,
252 | C0F7BFF91DFC128600948E16 /* Actions.sks in Resources */,
253 | C0F7C0681DFC194400948E16 /* falling.wav in Resources */,
254 | );
255 | runOnlyForDeploymentPostprocessing = 0;
256 | };
257 | /* End PBXResourcesBuildPhase section */
258 |
259 | /* Begin PBXSourcesBuildPhase section */
260 | C0F7BFED1DFC128600948E16 /* Sources */ = {
261 | isa = PBXSourcesBuildPhase;
262 | buildActionMask = 2147483647;
263 | files = (
264 | C0F7BFFB1DFC128600948E16 /* GameScene.swift in Sources */,
265 | C0D88D531E0C077B002630B5 /* MGBird.swift in Sources */,
266 | C0F7C07B1DFC207000948E16 /* CGPoint+Extensions.swift in Sources */,
267 | C0F7C0841DFC207000948E16 /* SKTTimingFunctions.swift in Sources */,
268 | C0F7C0831DFC207000948E16 /* SKTEffects.swift in Sources */,
269 | C0F7C07F1DFC207000948E16 /* SKAction+SpecialEffects.swift in Sources */,
270 | C0F7C07C1DFC207000948E16 /* CGVector+Extensions.swift in Sources */,
271 | C0F7C07E1DFC207000948E16 /* SKAction+Extensions.swift in Sources */,
272 | C0F7C0801DFC207000948E16 /* SKColor+Extensions.swift in Sources */,
273 | C0F7BFFD1DFC128600948E16 /* GameViewController.swift in Sources */,
274 | C09C0B431DFEBEAB006E2E9B /* BitMaskType.swift in Sources */,
275 | C0F7C07D1DFC207000948E16 /* Int+Extensions.swift in Sources */,
276 | C0F7C0811DFC207000948E16 /* SKNode+Extensions.swift in Sources */,
277 | C0F7C0821DFC207000948E16 /* SKTAudio.swift in Sources */,
278 | C0F7C07A1DFC207000948E16 /* CGFloat+Extensions.swift in Sources */,
279 | C0F7C0851DFC207000948E16 /* Vector3.swift in Sources */,
280 | C0F7BFF51DFC128600948E16 /* AppDelegate.swift in Sources */,
281 | );
282 | runOnlyForDeploymentPostprocessing = 0;
283 | };
284 | /* End PBXSourcesBuildPhase section */
285 |
286 | /* Begin PBXVariantGroup section */
287 | C0F7BFFE1DFC128600948E16 /* Main.storyboard */ = {
288 | isa = PBXVariantGroup;
289 | children = (
290 | C0F7BFFF1DFC128600948E16 /* Base */,
291 | );
292 | name = Main.storyboard;
293 | sourceTree = "";
294 | };
295 | C0F7C0031DFC128600948E16 /* LaunchScreen.storyboard */ = {
296 | isa = PBXVariantGroup;
297 | children = (
298 | C0F7C0041DFC128600948E16 /* Base */,
299 | );
300 | name = LaunchScreen.storyboard;
301 | sourceTree = "";
302 | };
303 | /* End PBXVariantGroup section */
304 |
305 | /* Begin XCBuildConfiguration section */
306 | C0F7C0071DFC128600948E16 /* Debug */ = {
307 | isa = XCBuildConfiguration;
308 | buildSettings = {
309 | ALWAYS_SEARCH_USER_PATHS = NO;
310 | CLANG_ANALYZER_NONNULL = YES;
311 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
312 | CLANG_CXX_LIBRARY = "libc++";
313 | CLANG_ENABLE_MODULES = YES;
314 | CLANG_ENABLE_OBJC_ARC = YES;
315 | CLANG_WARN_BOOL_CONVERSION = YES;
316 | CLANG_WARN_CONSTANT_CONVERSION = YES;
317 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
318 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
319 | CLANG_WARN_EMPTY_BODY = YES;
320 | CLANG_WARN_ENUM_CONVERSION = YES;
321 | CLANG_WARN_INFINITE_RECURSION = YES;
322 | CLANG_WARN_INT_CONVERSION = YES;
323 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
324 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
325 | CLANG_WARN_UNREACHABLE_CODE = YES;
326 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
327 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
328 | COPY_PHASE_STRIP = NO;
329 | DEBUG_INFORMATION_FORMAT = dwarf;
330 | ENABLE_STRICT_OBJC_MSGSEND = YES;
331 | ENABLE_TESTABILITY = YES;
332 | GCC_C_LANGUAGE_STANDARD = gnu99;
333 | GCC_DYNAMIC_NO_PIC = NO;
334 | GCC_NO_COMMON_BLOCKS = YES;
335 | GCC_OPTIMIZATION_LEVEL = 0;
336 | GCC_PREPROCESSOR_DEFINITIONS = (
337 | "DEBUG=1",
338 | "$(inherited)",
339 | );
340 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
341 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
342 | GCC_WARN_UNDECLARED_SELECTOR = YES;
343 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
344 | GCC_WARN_UNUSED_FUNCTION = YES;
345 | GCC_WARN_UNUSED_VARIABLE = YES;
346 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
347 | MTL_ENABLE_DEBUG_INFO = YES;
348 | ONLY_ACTIVE_ARCH = YES;
349 | SDKROOT = iphoneos;
350 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
351 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
352 | };
353 | name = Debug;
354 | };
355 | C0F7C0081DFC128600948E16 /* Release */ = {
356 | isa = XCBuildConfiguration;
357 | buildSettings = {
358 | ALWAYS_SEARCH_USER_PATHS = NO;
359 | CLANG_ANALYZER_NONNULL = YES;
360 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
361 | CLANG_CXX_LIBRARY = "libc++";
362 | CLANG_ENABLE_MODULES = YES;
363 | CLANG_ENABLE_OBJC_ARC = YES;
364 | CLANG_WARN_BOOL_CONVERSION = YES;
365 | CLANG_WARN_CONSTANT_CONVERSION = YES;
366 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
367 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
368 | CLANG_WARN_EMPTY_BODY = YES;
369 | CLANG_WARN_ENUM_CONVERSION = YES;
370 | CLANG_WARN_INFINITE_RECURSION = YES;
371 | CLANG_WARN_INT_CONVERSION = YES;
372 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
373 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
374 | CLANG_WARN_UNREACHABLE_CODE = YES;
375 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
376 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
377 | COPY_PHASE_STRIP = NO;
378 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
379 | ENABLE_NS_ASSERTIONS = NO;
380 | ENABLE_STRICT_OBJC_MSGSEND = YES;
381 | GCC_C_LANGUAGE_STANDARD = gnu99;
382 | GCC_NO_COMMON_BLOCKS = YES;
383 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
384 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
385 | GCC_WARN_UNDECLARED_SELECTOR = YES;
386 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
387 | GCC_WARN_UNUSED_FUNCTION = YES;
388 | GCC_WARN_UNUSED_VARIABLE = YES;
389 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
390 | MTL_ENABLE_DEBUG_INFO = NO;
391 | SDKROOT = iphoneos;
392 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
393 | VALIDATE_PRODUCT = YES;
394 | };
395 | name = Release;
396 | };
397 | C0F7C00A1DFC128600948E16 /* Debug */ = {
398 | isa = XCBuildConfiguration;
399 | buildSettings = {
400 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
401 | INFOPLIST_FILE = "Flappy Bird/Info.plist";
402 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
403 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
404 | PRODUCT_BUNDLE_IDENTIFIER = "i-Techsys.com.Flappy-Bird";
405 | PRODUCT_NAME = "MG Bird";
406 | SWIFT_VERSION = 3.0;
407 | };
408 | name = Debug;
409 | };
410 | C0F7C00B1DFC128600948E16 /* Release */ = {
411 | isa = XCBuildConfiguration;
412 | buildSettings = {
413 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
414 | INFOPLIST_FILE = "Flappy Bird/Info.plist";
415 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
416 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
417 | PRODUCT_BUNDLE_IDENTIFIER = "i-Techsys.com.Flappy-Bird";
418 | PRODUCT_NAME = "MG Bird";
419 | SWIFT_VERSION = 3.0;
420 | };
421 | name = Release;
422 | };
423 | /* End XCBuildConfiguration section */
424 |
425 | /* Begin XCConfigurationList section */
426 | C0F7BFEC1DFC128600948E16 /* Build configuration list for PBXProject "Flappy Bird" */ = {
427 | isa = XCConfigurationList;
428 | buildConfigurations = (
429 | C0F7C0071DFC128600948E16 /* Debug */,
430 | C0F7C0081DFC128600948E16 /* Release */,
431 | );
432 | defaultConfigurationIsVisible = 0;
433 | defaultConfigurationName = Release;
434 | };
435 | C0F7C0091DFC128600948E16 /* Build configuration list for PBXNativeTarget "Flappy Bird" */ = {
436 | isa = XCConfigurationList;
437 | buildConfigurations = (
438 | C0F7C00A1DFC128600948E16 /* Debug */,
439 | C0F7C00B1DFC128600948E16 /* Release */,
440 | );
441 | defaultConfigurationIsVisible = 0;
442 | defaultConfigurationName = Release;
443 | };
444 | /* End XCConfigurationList section */
445 | };
446 | rootObject = C0F7BFE91DFC128600948E16 /* Project object */;
447 | }
448 |
--------------------------------------------------------------------------------