├── 0-For-Instructor ├── 1-Overview.key ├── 2-Demo.markdown ├── 3-LabImages │ └── SCNSceneRendererDelegate.png ├── 3-LabInstructions.markdown ├── 4-ChallengeInstructions.markdown └── 5-Conclusion.key ├── 1-Starter ├── 1-Overview.pdf └── SCNFrogger-1 │ ├── SCNFrogger.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── SCNFrogger.xccheckout │ └── xcuserdata │ │ └── kim.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── SCNFrogger.xcscheme │ │ └── xcschememanagement.plist │ ├── SCNFrogger │ ├── AppDelegate.swift │ ├── Array2D.swift │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Constants.swift │ ├── EarlyGameBoy.ttf │ ├── GameLevel.swift │ ├── GameScene.swift │ ├── GameViewController.swift │ ├── HandNode.swift │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-40.png │ │ │ ├── Icon-40@2x-1.png │ │ │ ├── Icon-40@2x.png │ │ │ ├── Icon-40@3x.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-76.png │ │ │ ├── Icon-76@2x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-Small@2x-1.png │ │ │ ├── Icon-Small@2x.png │ │ │ └── Icon-Small@3x.png │ │ ├── rwdevcon-bg.imageset │ │ │ ├── Contents.json │ │ │ └── rwdevcon-bg.png │ │ └── rwdevcon-logo.imageset │ │ │ ├── Contents.json │ │ │ └── rwdevcon-logo.png │ ├── Info.plist │ ├── LabelNode.swift │ ├── LaunchScreen.xib │ ├── SKTUtils │ │ ├── CGFloat+Extensions.swift │ │ ├── CGPoint+Extensions.swift │ │ ├── CGVector+Extensions.swift │ │ ├── Int+Extensions.swift │ │ ├── SKAction+Extensions.swift │ │ ├── SKAction+SpecialEffects.swift │ │ ├── SKColor+Extensions.swift │ │ ├── SKNode+Extensions.swift │ │ ├── SKTAudio.swift │ │ ├── SKTEffects.swift │ │ ├── SKTTimingFunctions.swift │ │ └── Vector3.swift │ └── assets.scnassets │ │ ├── Models │ │ ├── car.dae │ │ └── frog.dae │ │ ├── Sounds │ │ └── jump.wav │ │ └── Textures │ │ ├── hand.png │ │ ├── hand@2x.png │ │ ├── hand_click.png │ │ ├── hand_click@2x.png │ │ └── model_texture.tga │ └── SCNFroggerTests │ ├── Info.plist │ └── SCNFroggerTests.swift ├── 2-Demo ├── 2-Demo.html └── SCNFrogger-2 │ ├── SCNFrogger.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── SCNFrogger.xccheckout │ └── xcuserdata │ │ └── kim.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── SCNFrogger.xcscheme │ │ └── xcschememanagement.plist │ ├── SCNFrogger │ ├── AppDelegate.swift │ ├── Array2D.swift │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Constants.swift │ ├── EarlyGameBoy.ttf │ ├── GameLevel.swift │ ├── GameScene.swift │ ├── GameViewController.swift │ ├── HandNode.swift │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-40.png │ │ │ ├── Icon-40@2x-1.png │ │ │ ├── Icon-40@2x.png │ │ │ ├── Icon-40@3x.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-76.png │ │ │ ├── Icon-76@2x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-Small@2x-1.png │ │ │ ├── Icon-Small@2x.png │ │ │ └── Icon-Small@3x.png │ │ ├── rwdevcon-bg.imageset │ │ │ ├── Contents.json │ │ │ └── rwdevcon-bg.png │ │ └── rwdevcon-logo.imageset │ │ │ ├── Contents.json │ │ │ └── rwdevcon-logo.png │ ├── Info.plist │ ├── LabelNode.swift │ ├── LaunchScreen.xib │ ├── SKTUtils │ │ ├── CGFloat+Extensions.swift │ │ ├── CGPoint+Extensions.swift │ │ ├── CGVector+Extensions.swift │ │ ├── Int+Extensions.swift │ │ ├── SKAction+Extensions.swift │ │ ├── SKAction+SpecialEffects.swift │ │ ├── SKColor+Extensions.swift │ │ ├── SKNode+Extensions.swift │ │ ├── SKTAudio.swift │ │ ├── SKTEffects.swift │ │ ├── SKTTimingFunctions.swift │ │ └── Vector3.swift │ └── assets.scnassets │ │ ├── Models │ │ ├── car.dae │ │ └── frog.dae │ │ ├── Sounds │ │ └── jump.wav │ │ └── Textures │ │ ├── hand.png │ │ ├── hand@2x.png │ │ ├── hand_click.png │ │ ├── hand_click@2x.png │ │ └── model_texture.tga │ └── SCNFroggerTests │ ├── Info.plist │ └── SCNFroggerTests.swift ├── 3-Lab ├── 3-LabImages │ └── SCNSceneRendererDelegate.png ├── 3-LabInstructions.html └── SCNFrogger-3 │ ├── SCNFrogger.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── SCNFrogger.xccheckout │ └── xcuserdata │ │ └── kim.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── SCNFrogger.xcscheme │ │ └── xcschememanagement.plist │ ├── SCNFrogger │ ├── AppDelegate.swift │ ├── Array2D.swift │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Constants.swift │ ├── EarlyGameBoy.ttf │ ├── GameLevel.swift │ ├── GameScene.swift │ ├── GameViewController.swift │ ├── HandNode.swift │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-40.png │ │ │ ├── Icon-40@2x-1.png │ │ │ ├── Icon-40@2x.png │ │ │ ├── Icon-40@3x.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-76.png │ │ │ ├── Icon-76@2x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-Small@2x-1.png │ │ │ ├── Icon-Small@2x.png │ │ │ └── Icon-Small@3x.png │ │ ├── rwdevcon-bg.imageset │ │ │ ├── Contents.json │ │ │ └── rwdevcon-bg.png │ │ └── rwdevcon-logo.imageset │ │ │ ├── Contents.json │ │ │ └── rwdevcon-logo.png │ ├── Info.plist │ ├── LabelNode.swift │ ├── LaunchScreen.xib │ ├── SKTUtils │ │ ├── CGFloat+Extensions.swift │ │ ├── CGPoint+Extensions.swift │ │ ├── CGVector+Extensions.swift │ │ ├── Int+Extensions.swift │ │ ├── SKAction+Extensions.swift │ │ ├── SKAction+SpecialEffects.swift │ │ ├── SKColor+Extensions.swift │ │ ├── SKNode+Extensions.swift │ │ ├── SKTAudio.swift │ │ ├── SKTEffects.swift │ │ ├── SKTTimingFunctions.swift │ │ └── Vector3.swift │ └── assets.scnassets │ │ ├── Models │ │ ├── car.dae │ │ └── frog.dae │ │ ├── Sounds │ │ └── jump.wav │ │ └── Textures │ │ ├── hand.png │ │ ├── hand@2x.png │ │ ├── hand_click.png │ │ ├── hand_click@2x.png │ │ └── model_texture.tga │ └── SCNFroggerTests │ ├── Info.plist │ └── SCNFroggerTests.swift ├── 4-Challenge ├── 4-ChallengeInstructions.html └── SCNFrogger-4 │ ├── SCNFrogger.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── SCNFrogger.xccheckout │ └── xcuserdata │ │ └── kim.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── SCNFrogger.xcscheme │ │ └── xcschememanagement.plist │ ├── SCNFrogger │ ├── AppDelegate.swift │ ├── Array2D.swift │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Constants.swift │ ├── EarlyGameBoy.ttf │ ├── GameLevel.swift │ ├── GameScene.swift │ ├── GameViewController.swift │ ├── HandNode.swift │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-40.png │ │ │ ├── Icon-40@2x-1.png │ │ │ ├── Icon-40@2x.png │ │ │ ├── Icon-40@3x.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-76.png │ │ │ ├── Icon-76@2x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-Small@2x-1.png │ │ │ ├── Icon-Small@2x.png │ │ │ └── Icon-Small@3x.png │ │ ├── rwdevcon-bg.imageset │ │ │ ├── Contents.json │ │ │ └── rwdevcon-bg.png │ │ └── rwdevcon-logo.imageset │ │ │ ├── Contents.json │ │ │ └── rwdevcon-logo.png │ ├── Info.plist │ ├── LabelNode.swift │ ├── LaunchScreen.xib │ ├── SKTUtils │ │ ├── CGFloat+Extensions.swift │ │ ├── CGPoint+Extensions.swift │ │ ├── CGVector+Extensions.swift │ │ ├── Int+Extensions.swift │ │ ├── SKAction+Extensions.swift │ │ ├── SKAction+SpecialEffects.swift │ │ ├── SKColor+Extensions.swift │ │ ├── SKNode+Extensions.swift │ │ ├── SKTAudio.swift │ │ ├── SKTEffects.swift │ │ ├── SKTTimingFunctions.swift │ │ └── Vector3.swift │ └── assets.scnassets │ │ ├── Models │ │ ├── car.dae │ │ └── frog.dae │ │ ├── Sounds │ │ └── jump.wav │ │ └── Textures │ │ ├── hand.png │ │ ├── hand@2x.png │ │ ├── hand_click.png │ │ ├── hand_click@2x.png │ │ └── model_texture.tga │ └── SCNFroggerTests │ ├── Info.plist │ └── SCNFroggerTests.swift ├── 5-Conclusion └── 5-Conclusion.pdf ├── LICENSE ├── README.md └── screenshot.png /0-For-Instructor/1-Overview.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/0-For-Instructor/1-Overview.key -------------------------------------------------------------------------------- /0-For-Instructor/3-LabImages/SCNSceneRendererDelegate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/0-For-Instructor/3-LabImages/SCNSceneRendererDelegate.png -------------------------------------------------------------------------------- /0-For-Instructor/5-Conclusion.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/0-For-Instructor/5-Conclusion.key -------------------------------------------------------------------------------- /1-Starter/1-Overview.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/1-Overview.pdf -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger.xcodeproj/project.xcworkspace/xcshareddata/SCNFrogger.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 6DE4669D-839D-4A6C-935D-D50EE5C00229 9 | IDESourceControlProjectName 10 | SCNFrogger 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | C45253657BF1B0A67E13F808D5E653AC34B147B3 14 | https://github.com/devindazzle/SceneKitFrogger.git 15 | 16 | IDESourceControlProjectPath 17 | 1-Starter/SCNFrogger-1/SCNFrogger.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | C45253657BF1B0A67E13F808D5E653AC34B147B3 21 | ../../../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/devindazzle/SceneKitFrogger.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | C45253657BF1B0A67E13F808D5E653AC34B147B3 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | C45253657BF1B0A67E13F808D5E653AC34B147B3 36 | IDESourceControlWCCName 37 | SceneKitFrogger 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger.xcodeproj/xcuserdata/kim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger.xcodeproj/xcuserdata/kim.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SCNFrogger.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 3BE6195A1A2DCDBA00ED80D7 16 | 17 | primary 18 | 19 | 20 | 3BE619711A2DCDBA00ED80D7 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(application: UIApplication) { 22 | // 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. 23 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 24 | } 25 | 26 | func applicationDidEnterBackground(application: UIApplication) { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(application: UIApplication) { 32 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | func applicationDidBecomeActive(application: UIApplication) { 36 | // 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. 37 | } 38 | 39 | func applicationWillTerminate(application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Array2D.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Array2D.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | class Array2D { 10 | 11 | var cols: Int, rows: Int 12 | var data: [Int] 13 | 14 | init(cols columnCount: Int, rows rowCount: Int, value defaultValue: Int) { 15 | self.cols = columnCount 16 | self.rows = rowCount 17 | data = Array(count: cols * rows, repeatedValue: defaultValue) 18 | } 19 | 20 | subscript(column: Int, row: Int) -> Int { 21 | get { 22 | return data[cols * row + column] 23 | } 24 | set { 25 | data[cols * row + column] = newValue 26 | } 27 | } 28 | 29 | func columnCount() -> Int { 30 | return self.cols 31 | } 32 | 33 | func rowCount() -> Int { 34 | return self.rows 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/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 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | enum GameState { 10 | case WaitingForFirstTap 11 | case Playing 12 | case GameOver 13 | case RestartLevel 14 | } 15 | 16 | 17 | enum MoveDirection { 18 | case Forward 19 | case Backward 20 | case Left 21 | case Right 22 | } 23 | 24 | 25 | struct PhysicsCategory { 26 | static let None: Int = 0 27 | static let Player: Int = 0b1 // 1 28 | static let Car: Int = 0b10 // 2 29 | static let Obstacle: Int = 0b100 // 4 30 | } -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/EarlyGameBoy.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/EarlyGameBoy.ttf -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/GameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SceneKit 10 | import SpriteKit 11 | 12 | class GameViewController: UIViewController { 13 | 14 | var scnView: SCNView { 15 | get { 16 | return self.view as SCNView 17 | } 18 | } 19 | 20 | override func viewDidAppear(animated: Bool) { 21 | 22 | super.viewDidAppear(animated) 23 | 24 | // Set up the SCNView 25 | scnView.backgroundColor = UIColor(red: 100.0/255.0, green: 149.0/255.0, blue: 237.0/255.0, alpha: 1.0) 26 | scnView.showsStatistics = true 27 | scnView.allowsCameraControl = true 28 | scnView.antialiasingMode = SCNAntialiasingMode.Multisampling2X 29 | scnView.overlaySKScene = SKScene(size: view.bounds.size) 30 | scnView.playing = true 31 | 32 | // Set up the scene 33 | let scene = GameScene(view: scnView) 34 | scene.rootNode.hidden = true 35 | scene.physicsWorld.contactDelegate = scene 36 | 37 | // Start playing the scene 38 | scnView.scene = scene 39 | scnView.delegate = scene 40 | scnView.scene!.rootNode.hidden = false 41 | scnView.play(self) 42 | } 43 | 44 | 45 | override func shouldAutorotate() -> Bool { 46 | return true 47 | } 48 | 49 | 50 | override func prefersStatusBarHidden() -> Bool { 51 | return true 52 | } 53 | 54 | 55 | override func supportedInterfaceOrientations() -> Int { 56 | return Int(UIInterfaceOrientationMask.Portrait.rawValue) 57 | } 58 | 59 | 60 | override func didReceiveMemoryWarning() { 61 | super.didReceiveMemoryWarning() 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/HandNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HandNode.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SpriteKit 10 | 11 | class HandNode : SKNode { 12 | 13 | override init() { 14 | 15 | super.init() 16 | 17 | name = "Tutorial" 18 | 19 | // Load textures 20 | let handTexture = SKTexture(imageNamed:"assets.scnassets/Textures/hand.png") 21 | handTexture.filteringMode = SKTextureFilteringMode.Nearest 22 | let handTextureClick = SKTexture(imageNamed:"assets.scnassets/Textures/hand_click.png") 23 | handTextureClick.filteringMode = SKTextureFilteringMode.Nearest 24 | 25 | // Create animation 26 | let handAnimation = SKAction.animateWithTextures([handTexture, handTextureClick], timePerFrame:0.5) 27 | 28 | // Create a sprite node abd animate it 29 | let handSprite = SKSpriteNode(texture: handTexture) 30 | handSprite.xScale = 2.0 31 | handSprite.yScale = 2.0 32 | handSprite.runAction(SKAction.repeatActionForever(handAnimation)) 33 | 34 | addChild(handSprite) 35 | } 36 | 37 | 38 | required init?(coder aDecoder: NSCoder) { 39 | fatalError("init(coder:) has not been implemented") 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-Small@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-Small@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-40@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-40@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-60@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-60@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "29x29", 41 | "idiom" : "ipad", 42 | "filename" : "Icon-Small.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "Icon-Small@2x-1.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "40x40", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-40.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-40@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "76x76", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-76.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "76x76", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-76@2x.png", 73 | "scale" : "2x" 74 | } 75 | ], 76 | "info" : { 77 | "version" : 1, 78 | "author" : "xcode" 79 | } 80 | } -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "rwdevcon-bg.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/rwdevcon-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/rwdevcon-bg.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "rwdevcon-logo.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/rwdevcon-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/rwdevcon-logo.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.raywenderlich.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UIAppFonts 26 | 27 | EarlyGameBoy.ttf 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UIStatusBarHidden 38 | 39 | UISupportedInterfaceOrientations 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/LabelNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LabelNode.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SpriteKit 10 | 11 | class LabelNode : SKLabelNode { 12 | 13 | init(position: CGPoint, size: CGFloat, color: SKColor, text: String, name: String) { 14 | super.init() 15 | 16 | self.name = name 17 | self.text = text 18 | self.position = position 19 | 20 | fontName = "Early-Gameboy" 21 | fontSize = size 22 | fontColor = color 23 | } 24 | 25 | required init?(coder aDecoder: NSCoder) { 26 | fatalError("init(coder:) has not been implemented") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/LaunchScreen.xib: -------------------------------------------------------------------------------- 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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/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, 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) % twoπ 97 | if (angle >= π) { 98 | angle = angle - twoπ 99 | } 100 | if (angle <= -π) { 101 | angle = angle + twoπ 102 | } 103 | return angle 104 | } 105 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/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.startIndex) ? range.startIndex : ((self >= range.endIndex) ? range.endIndex - 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) 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, 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.endIndex - range.startIndex))) + range.startIndex 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 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/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: NSTimeInterval, performAction action: SKAction) -> SKAction { 30 | return SKAction.sequence([SKAction.waitForDuration(delay), action]) 31 | } 32 | 33 | /** 34 | * Performs a block after the specified delay. 35 | */ 36 | public class func afterDelay(delay: NSTimeInterval, runBlock block: dispatch_block_t) -> SKAction { 37 | return SKAction.afterDelay(delay, performAction: SKAction.runBlock(block)) 38 | } 39 | 40 | /** 41 | * Removes the node from its parent after the specified delay. 42 | */ 43 | public class func removeFromParentAfterDelay(delay: NSTimeInterval) -> SKAction { 44 | return SKAction.afterDelay(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: NSTimeInterval, originalPosition: CGPoint) -> SKAction { 51 | return SKAction.customActionWithDuration(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 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/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: NSTimeInterval) -> SKAction { 35 | let oldPosition = node.position 36 | let newPosition = oldPosition + amount 37 | 38 | let effect = SKTMoveEffect(node: node, duration: duration, startPosition: newPosition, endPosition: oldPosition) 39 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 40 | 41 | return SKAction.actionWithEffect(effect) 42 | } 43 | 44 | /** 45 | * Creates a screen rotation animation. 46 | * 47 | * @param node You usually want to apply this effect to a pivot node that is 48 | * centered in the scene. You cannot apply the effect to an SKScene. 49 | * @param angle The angle in radians. 50 | * @param oscillations The number of oscillations; 10 is a good value. 51 | * @param duration How long the effect lasts. Shorter is better. 52 | */ 53 | public class func screenRotateWithNode(node: SKNode, angle: CGFloat, oscillations: Int, duration: NSTimeInterval) -> SKAction { 54 | let oldAngle = node.zRotation 55 | let newAngle = oldAngle + angle 56 | 57 | let effect = SKTRotateEffect(node: node, duration: duration, startAngle: newAngle, endAngle: oldAngle) 58 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 59 | 60 | return SKAction.actionWithEffect(effect) 61 | } 62 | 63 | /** 64 | * Creates a screen zoom animation. 65 | * 66 | * @param node You usually want to apply this effect to a pivot node that is 67 | * centered in the scene. You cannot apply the effect to an SKScene. 68 | * @param amount How much to scale the node in the X and Y directions. 69 | * @param oscillations The number of oscillations; 10 is a good value. 70 | * @param duration How long the effect lasts. Shorter is better. 71 | */ 72 | public class func screenZoomWithNode(node: SKNode, amount: CGPoint, oscillations: Int, duration: NSTimeInterval) -> SKAction { 73 | let oldScale = CGPoint(x: node.xScale, y: node.yScale) 74 | let newScale = oldScale * amount 75 | 76 | let effect = SKTScaleEffect(node: node, duration: duration, startScale: newScale, endScale: oldScale) 77 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 78 | 79 | return SKAction.actionWithEffect(effect) 80 | } 81 | 82 | /** 83 | * Causes the scene background to flash for duration seconds. 84 | */ 85 | public class func colorGlitchWithScene(scene: SKScene, originalColor: SKColor, duration: NSTimeInterval) -> SKAction { 86 | return SKAction.customActionWithDuration(duration) {(node, elapsedTime) in 87 | if elapsedTime < CGFloat(duration) { 88 | scene.backgroundColor = SKColorWithRGB(Int.random(0...255), Int.random(0...255), Int.random(0...255)) 89 | } else { 90 | scene.backgroundColor = originalColor 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/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 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/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: NSTimeInterval, runBlock block: dispatch_block_t) { 43 | runAction(SKAction.sequence([SKAction.waitForDuration(delay), SKAction.runBlock(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 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/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 = NSBundle.mainBundle().URLForResource(filename, withExtension: nil) 39 | if (url == nil) { 40 | println("Could not find file: \(filename)") 41 | return 42 | } 43 | 44 | var error: NSError? = nil 45 | backgroundMusicPlayer = AVAudioPlayer(contentsOfURL: url, error: &error) 46 | if let player = backgroundMusicPlayer { 47 | player.numberOfLoops = -1 48 | player.prepareToPlay() 49 | player.play() 50 | } else { 51 | println("Could not create audio player: \(error!)") 52 | } 53 | } 54 | 55 | public func pauseBackgroundMusic() { 56 | if let player = backgroundMusicPlayer { 57 | if player.playing { 58 | player.pause() 59 | } 60 | } 61 | } 62 | 63 | public func resumeBackgroundMusic() { 64 | if let player = backgroundMusicPlayer { 65 | if !player.playing { 66 | player.play() 67 | } 68 | } 69 | } 70 | 71 | public func playSoundEffect(filename: String) { 72 | let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil) 73 | if (url == nil) { 74 | println("Could not find file: \(filename)") 75 | return 76 | } 77 | 78 | var error: NSError? = nil 79 | soundEffectPlayer = AVAudioPlayer(contentsOfURL: url, error: &error) 80 | if let player = soundEffectPlayer { 81 | player.numberOfLoops = 0 82 | player.prepareToPlay() 83 | player.play() 84 | } else { 85 | println("Could not create audio player: \(error!)") 86 | } 87 | } 88 | } 89 | 90 | private let SKTAudioInstance = SKTAudio() 91 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Sounds/jump.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Sounds/jump.wav -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Textures/hand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Textures/hand.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Textures/hand@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Textures/hand@2x.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Textures/hand_click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Textures/hand_click.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Textures/hand_click@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Textures/hand_click@2x.png -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Textures/model_texture.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/1-Starter/SCNFrogger-1/SCNFrogger/assets.scnassets/Textures/model_texture.tga -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFroggerTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.raywenderlich.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /1-Starter/SCNFrogger-1/SCNFroggerTests/SCNFroggerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SCNFroggerTests.swift 3 | // SCNFroggerTests 4 | // 5 | // Created by Kim Pedersen on 02/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class SCNFroggerTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger.xcodeproj/project.xcworkspace/xcshareddata/SCNFrogger.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 6DE4669D-839D-4A6C-935D-D50EE5C00229 9 | IDESourceControlProjectName 10 | SCNFrogger 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | C45253657BF1B0A67E13F808D5E653AC34B147B3 14 | https://github.com/devindazzle/SceneKitFrogger.git 15 | 16 | IDESourceControlProjectPath 17 | 2-Demo/SCNFrogger-2/SCNFrogger.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | C45253657BF1B0A67E13F808D5E653AC34B147B3 21 | ../../../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/devindazzle/SceneKitFrogger.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | C45253657BF1B0A67E13F808D5E653AC34B147B3 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | C45253657BF1B0A67E13F808D5E653AC34B147B3 36 | IDESourceControlWCCName 37 | SceneKitFrogger 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger.xcodeproj/xcuserdata/kim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger.xcodeproj/xcuserdata/kim.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SCNFrogger.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 3BE6195A1A2DCDBA00ED80D7 16 | 17 | primary 18 | 19 | 20 | 3BE619711A2DCDBA00ED80D7 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(application: UIApplication) { 22 | // 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. 23 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 24 | } 25 | 26 | func applicationDidEnterBackground(application: UIApplication) { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(application: UIApplication) { 32 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | func applicationDidBecomeActive(application: UIApplication) { 36 | // 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. 37 | } 38 | 39 | func applicationWillTerminate(application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Array2D.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Array2D.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | class Array2D { 10 | 11 | var cols: Int, rows: Int 12 | var data: [Int] 13 | 14 | init(cols columnCount: Int, rows rowCount: Int, value defaultValue: Int) { 15 | self.cols = columnCount 16 | self.rows = rowCount 17 | data = Array(count: cols * rows, repeatedValue: defaultValue) 18 | } 19 | 20 | subscript(column: Int, row: Int) -> Int { 21 | get { 22 | return data[cols * row + column] 23 | } 24 | set { 25 | data[cols * row + column] = newValue 26 | } 27 | } 28 | 29 | func columnCount() -> Int { 30 | return self.cols 31 | } 32 | 33 | func rowCount() -> Int { 34 | return self.rows 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/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 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | enum GameState { 10 | case WaitingForFirstTap 11 | case Playing 12 | case GameOver 13 | case RestartLevel 14 | } 15 | 16 | 17 | enum MoveDirection { 18 | case Forward 19 | case Backward 20 | case Left 21 | case Right 22 | } 23 | 24 | 25 | struct PhysicsCategory { 26 | static let None: Int = 0 27 | static let Player: Int = 0b1 // 1 28 | static let Car: Int = 0b10 // 2 29 | static let Obstacle: Int = 0b100 // 4 30 | } -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/EarlyGameBoy.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/EarlyGameBoy.ttf -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/GameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SceneKit 10 | import SpriteKit 11 | 12 | class GameViewController: UIViewController { 13 | 14 | var scnView: SCNView { 15 | get { 16 | return self.view as SCNView 17 | } 18 | } 19 | 20 | override func viewDidAppear(animated: Bool) { 21 | 22 | super.viewDidAppear(animated) 23 | 24 | // Set up the SCNView 25 | scnView.backgroundColor = UIColor(red: 100.0/255.0, green: 149.0/255.0, blue: 237.0/255.0, alpha: 1.0) 26 | scnView.showsStatistics = true 27 | scnView.antialiasingMode = SCNAntialiasingMode.Multisampling2X 28 | scnView.overlaySKScene = SKScene(size: view.bounds.size) 29 | scnView.playing = true 30 | 31 | // Set up the scene 32 | let scene = GameScene(view: scnView) 33 | scene.rootNode.hidden = true 34 | scene.physicsWorld.contactDelegate = scene 35 | 36 | // Start playing the scene 37 | scnView.scene = scene 38 | scnView.delegate = scene 39 | scnView.scene!.rootNode.hidden = false 40 | scnView.play(self) 41 | } 42 | 43 | 44 | override func shouldAutorotate() -> Bool { 45 | return true 46 | } 47 | 48 | 49 | override func prefersStatusBarHidden() -> Bool { 50 | return true 51 | } 52 | 53 | 54 | override func supportedInterfaceOrientations() -> Int { 55 | return Int(UIInterfaceOrientationMask.Portrait.rawValue) 56 | } 57 | 58 | 59 | override func didReceiveMemoryWarning() { 60 | super.didReceiveMemoryWarning() 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/HandNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HandNode.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SpriteKit 10 | 11 | class HandNode : SKNode { 12 | 13 | override init() { 14 | 15 | super.init() 16 | 17 | name = "Tutorial" 18 | 19 | // Load textures 20 | let handTexture = SKTexture(imageNamed:"assets.scnassets/Textures/hand.png") 21 | handTexture.filteringMode = SKTextureFilteringMode.Nearest 22 | let handTextureClick = SKTexture(imageNamed:"assets.scnassets/Textures/hand_click.png") 23 | handTextureClick.filteringMode = SKTextureFilteringMode.Nearest 24 | 25 | // Create animation 26 | let handAnimation = SKAction.animateWithTextures([handTexture, handTextureClick], timePerFrame:0.5) 27 | 28 | // Create a sprite node abd animate it 29 | let handSprite = SKSpriteNode(texture: handTexture) 30 | handSprite.xScale = 2.0 31 | handSprite.yScale = 2.0 32 | handSprite.runAction(SKAction.repeatActionForever(handAnimation)) 33 | 34 | addChild(handSprite) 35 | } 36 | 37 | 38 | required init?(coder aDecoder: NSCoder) { 39 | fatalError("init(coder:) has not been implemented") 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-Small@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-Small@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-40@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-40@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-60@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-60@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "29x29", 41 | "idiom" : "ipad", 42 | "filename" : "Icon-Small.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "Icon-Small@2x-1.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "40x40", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-40.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-40@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "76x76", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-76.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "76x76", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-76@2x.png", 73 | "scale" : "2x" 74 | } 75 | ], 76 | "info" : { 77 | "version" : 1, 78 | "author" : "xcode" 79 | } 80 | } -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "rwdevcon-bg.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/rwdevcon-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/rwdevcon-bg.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "rwdevcon-logo.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/rwdevcon-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/rwdevcon-logo.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.raywenderlich.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UIAppFonts 26 | 27 | EarlyGameBoy.ttf 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UIStatusBarHidden 38 | 39 | UISupportedInterfaceOrientations 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/LabelNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LabelNode.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SpriteKit 10 | 11 | class LabelNode : SKLabelNode { 12 | 13 | init(position: CGPoint, size: CGFloat, color: SKColor, text: String, name: String) { 14 | super.init() 15 | 16 | self.name = name 17 | self.text = text 18 | self.position = position 19 | 20 | fontName = "Early-Gameboy" 21 | fontSize = size 22 | fontColor = color 23 | } 24 | 25 | required init?(coder aDecoder: NSCoder) { 26 | fatalError("init(coder:) has not been implemented") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/LaunchScreen.xib: -------------------------------------------------------------------------------- 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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/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, 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) % twoπ 97 | if (angle >= π) { 98 | angle = angle - twoπ 99 | } 100 | if (angle <= -π) { 101 | angle = angle + twoπ 102 | } 103 | return angle 104 | } 105 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/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.startIndex) ? range.startIndex : ((self >= range.endIndex) ? range.endIndex - 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) 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, 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.endIndex - range.startIndex))) + range.startIndex 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 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/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: NSTimeInterval, performAction action: SKAction) -> SKAction { 30 | return SKAction.sequence([SKAction.waitForDuration(delay), action]) 31 | } 32 | 33 | /** 34 | * Performs a block after the specified delay. 35 | */ 36 | public class func afterDelay(delay: NSTimeInterval, runBlock block: dispatch_block_t) -> SKAction { 37 | return SKAction.afterDelay(delay, performAction: SKAction.runBlock(block)) 38 | } 39 | 40 | /** 41 | * Removes the node from its parent after the specified delay. 42 | */ 43 | public class func removeFromParentAfterDelay(delay: NSTimeInterval) -> SKAction { 44 | return SKAction.afterDelay(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: NSTimeInterval, originalPosition: CGPoint) -> SKAction { 51 | return SKAction.customActionWithDuration(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 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/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: NSTimeInterval) -> SKAction { 35 | let oldPosition = node.position 36 | let newPosition = oldPosition + amount 37 | 38 | let effect = SKTMoveEffect(node: node, duration: duration, startPosition: newPosition, endPosition: oldPosition) 39 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 40 | 41 | return SKAction.actionWithEffect(effect) 42 | } 43 | 44 | /** 45 | * Creates a screen rotation animation. 46 | * 47 | * @param node You usually want to apply this effect to a pivot node that is 48 | * centered in the scene. You cannot apply the effect to an SKScene. 49 | * @param angle The angle in radians. 50 | * @param oscillations The number of oscillations; 10 is a good value. 51 | * @param duration How long the effect lasts. Shorter is better. 52 | */ 53 | public class func screenRotateWithNode(node: SKNode, angle: CGFloat, oscillations: Int, duration: NSTimeInterval) -> SKAction { 54 | let oldAngle = node.zRotation 55 | let newAngle = oldAngle + angle 56 | 57 | let effect = SKTRotateEffect(node: node, duration: duration, startAngle: newAngle, endAngle: oldAngle) 58 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 59 | 60 | return SKAction.actionWithEffect(effect) 61 | } 62 | 63 | /** 64 | * Creates a screen zoom animation. 65 | * 66 | * @param node You usually want to apply this effect to a pivot node that is 67 | * centered in the scene. You cannot apply the effect to an SKScene. 68 | * @param amount How much to scale the node in the X and Y directions. 69 | * @param oscillations The number of oscillations; 10 is a good value. 70 | * @param duration How long the effect lasts. Shorter is better. 71 | */ 72 | public class func screenZoomWithNode(node: SKNode, amount: CGPoint, oscillations: Int, duration: NSTimeInterval) -> SKAction { 73 | let oldScale = CGPoint(x: node.xScale, y: node.yScale) 74 | let newScale = oldScale * amount 75 | 76 | let effect = SKTScaleEffect(node: node, duration: duration, startScale: newScale, endScale: oldScale) 77 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 78 | 79 | return SKAction.actionWithEffect(effect) 80 | } 81 | 82 | /** 83 | * Causes the scene background to flash for duration seconds. 84 | */ 85 | public class func colorGlitchWithScene(scene: SKScene, originalColor: SKColor, duration: NSTimeInterval) -> SKAction { 86 | return SKAction.customActionWithDuration(duration) {(node, elapsedTime) in 87 | if elapsedTime < CGFloat(duration) { 88 | scene.backgroundColor = SKColorWithRGB(Int.random(0...255), Int.random(0...255), Int.random(0...255)) 89 | } else { 90 | scene.backgroundColor = originalColor 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/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 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/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: NSTimeInterval, runBlock block: dispatch_block_t) { 43 | runAction(SKAction.sequence([SKAction.waitForDuration(delay), SKAction.runBlock(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 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/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 = NSBundle.mainBundle().URLForResource(filename, withExtension: nil) 39 | if (url == nil) { 40 | println("Could not find file: \(filename)") 41 | return 42 | } 43 | 44 | var error: NSError? = nil 45 | backgroundMusicPlayer = AVAudioPlayer(contentsOfURL: url, error: &error) 46 | if let player = backgroundMusicPlayer { 47 | player.numberOfLoops = -1 48 | player.prepareToPlay() 49 | player.play() 50 | } else { 51 | println("Could not create audio player: \(error!)") 52 | } 53 | } 54 | 55 | public func pauseBackgroundMusic() { 56 | if let player = backgroundMusicPlayer { 57 | if player.playing { 58 | player.pause() 59 | } 60 | } 61 | } 62 | 63 | public func resumeBackgroundMusic() { 64 | if let player = backgroundMusicPlayer { 65 | if !player.playing { 66 | player.play() 67 | } 68 | } 69 | } 70 | 71 | public func playSoundEffect(filename: String) { 72 | let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil) 73 | if (url == nil) { 74 | println("Could not find file: \(filename)") 75 | return 76 | } 77 | 78 | var error: NSError? = nil 79 | soundEffectPlayer = AVAudioPlayer(contentsOfURL: url, error: &error) 80 | if let player = soundEffectPlayer { 81 | player.numberOfLoops = 0 82 | player.prepareToPlay() 83 | player.play() 84 | } else { 85 | println("Could not create audio player: \(error!)") 86 | } 87 | } 88 | } 89 | 90 | private let SKTAudioInstance = SKTAudio() 91 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Sounds/jump.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Sounds/jump.wav -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Textures/hand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Textures/hand.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Textures/hand@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Textures/hand@2x.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Textures/hand_click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Textures/hand_click.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Textures/hand_click@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Textures/hand_click@2x.png -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Textures/model_texture.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/2-Demo/SCNFrogger-2/SCNFrogger/assets.scnassets/Textures/model_texture.tga -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFroggerTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.raywenderlich.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /2-Demo/SCNFrogger-2/SCNFroggerTests/SCNFroggerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SCNFroggerTests.swift 3 | // SCNFroggerTests 4 | // 5 | // Created by Kim Pedersen on 02/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class SCNFroggerTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /3-Lab/3-LabImages/SCNSceneRendererDelegate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/3-LabImages/SCNSceneRendererDelegate.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger.xcodeproj/project.xcworkspace/xcshareddata/SCNFrogger.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 6DE4669D-839D-4A6C-935D-D50EE5C00229 9 | IDESourceControlProjectName 10 | SCNFrogger 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | C45253657BF1B0A67E13F808D5E653AC34B147B3 14 | https://github.com/devindazzle/SceneKitFrogger.git 15 | 16 | IDESourceControlProjectPath 17 | 3-Lab/SCNFrogger-3/SCNFrogger.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | C45253657BF1B0A67E13F808D5E653AC34B147B3 21 | ../../../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/devindazzle/SceneKitFrogger.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | C45253657BF1B0A67E13F808D5E653AC34B147B3 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | C45253657BF1B0A67E13F808D5E653AC34B147B3 36 | IDESourceControlWCCName 37 | SceneKitFrogger 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger.xcodeproj/xcuserdata/kim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger.xcodeproj/xcuserdata/kim.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SCNFrogger.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 3BE6195A1A2DCDBA00ED80D7 16 | 17 | primary 18 | 19 | 20 | 3BE619711A2DCDBA00ED80D7 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(application: UIApplication) { 22 | // 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. 23 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 24 | } 25 | 26 | func applicationDidEnterBackground(application: UIApplication) { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(application: UIApplication) { 32 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | func applicationDidBecomeActive(application: UIApplication) { 36 | // 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. 37 | } 38 | 39 | func applicationWillTerminate(application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Array2D.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Array2D.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | class Array2D { 10 | 11 | var cols: Int, rows: Int 12 | var data: [Int] 13 | 14 | init(cols columnCount: Int, rows rowCount: Int, value defaultValue: Int) { 15 | self.cols = columnCount 16 | self.rows = rowCount 17 | data = Array(count: cols * rows, repeatedValue: defaultValue) 18 | } 19 | 20 | subscript(column: Int, row: Int) -> Int { 21 | get { 22 | return data[cols * row + column] 23 | } 24 | set { 25 | data[cols * row + column] = newValue 26 | } 27 | } 28 | 29 | func columnCount() -> Int { 30 | return self.cols 31 | } 32 | 33 | func rowCount() -> Int { 34 | return self.rows 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/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 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | enum GameState { 10 | case WaitingForFirstTap 11 | case Playing 12 | case GameOver 13 | case RestartLevel 14 | } 15 | 16 | 17 | enum MoveDirection { 18 | case Forward 19 | case Backward 20 | case Left 21 | case Right 22 | } 23 | 24 | 25 | struct PhysicsCategory { 26 | static let None: Int = 0 27 | static let Player: Int = 0b1 // 1 28 | static let Car: Int = 0b10 // 2 29 | static let Obstacle: Int = 0b100 // 4 30 | } -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/EarlyGameBoy.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/EarlyGameBoy.ttf -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/GameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SceneKit 10 | import SpriteKit 11 | 12 | class GameViewController: UIViewController { 13 | 14 | var scnView: SCNView { 15 | get { 16 | return self.view as SCNView 17 | } 18 | } 19 | 20 | override func viewDidAppear(animated: Bool) { 21 | 22 | super.viewDidAppear(animated) 23 | 24 | // Set up the SCNView 25 | scnView.backgroundColor = UIColor(red: 100.0/255.0, green: 149.0/255.0, blue: 237.0/255.0, alpha: 1.0) 26 | scnView.showsStatistics = true 27 | scnView.antialiasingMode = SCNAntialiasingMode.Multisampling2X 28 | scnView.overlaySKScene = SKScene(size: view.bounds.size) 29 | scnView.playing = true 30 | 31 | // Set up the scene 32 | let scene = GameScene(view: scnView) 33 | scene.rootNode.hidden = true 34 | scene.physicsWorld.contactDelegate = scene 35 | 36 | // Start playing the scene 37 | scnView.scene = scene 38 | scnView.delegate = scene 39 | scnView.scene!.rootNode.hidden = false 40 | scnView.play(self) 41 | } 42 | 43 | 44 | override func shouldAutorotate() -> Bool { 45 | return true 46 | } 47 | 48 | 49 | override func prefersStatusBarHidden() -> Bool { 50 | return true 51 | } 52 | 53 | 54 | override func supportedInterfaceOrientations() -> Int { 55 | return Int(UIInterfaceOrientationMask.Portrait.rawValue) 56 | } 57 | 58 | 59 | override func didReceiveMemoryWarning() { 60 | super.didReceiveMemoryWarning() 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/HandNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HandNode.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SpriteKit 10 | 11 | class HandNode : SKNode { 12 | 13 | override init() { 14 | 15 | super.init() 16 | 17 | name = "Tutorial" 18 | 19 | // Load textures 20 | let handTexture = SKTexture(imageNamed:"assets.scnassets/Textures/hand.png") 21 | handTexture.filteringMode = SKTextureFilteringMode.Nearest 22 | let handTextureClick = SKTexture(imageNamed:"assets.scnassets/Textures/hand_click.png") 23 | handTextureClick.filteringMode = SKTextureFilteringMode.Nearest 24 | 25 | // Create animation 26 | let handAnimation = SKAction.animateWithTextures([handTexture, handTextureClick], timePerFrame:0.5) 27 | 28 | // Create a sprite node abd animate it 29 | let handSprite = SKSpriteNode(texture: handTexture) 30 | handSprite.xScale = 2.0 31 | handSprite.yScale = 2.0 32 | handSprite.runAction(SKAction.repeatActionForever(handAnimation)) 33 | 34 | addChild(handSprite) 35 | } 36 | 37 | 38 | required init?(coder aDecoder: NSCoder) { 39 | fatalError("init(coder:) has not been implemented") 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-Small@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-Small@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-40@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-40@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-60@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-60@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "29x29", 41 | "idiom" : "ipad", 42 | "filename" : "Icon-Small.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "Icon-Small@2x-1.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "40x40", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-40.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-40@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "76x76", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-76.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "76x76", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-76@2x.png", 73 | "scale" : "2x" 74 | } 75 | ], 76 | "info" : { 77 | "version" : 1, 78 | "author" : "xcode" 79 | } 80 | } -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "rwdevcon-bg.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/rwdevcon-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/rwdevcon-bg.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "rwdevcon-logo.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/rwdevcon-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/rwdevcon-logo.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.raywenderlich.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UIAppFonts 26 | 27 | EarlyGameBoy.ttf 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UIStatusBarHidden 38 | 39 | UISupportedInterfaceOrientations 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/LabelNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LabelNode.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SpriteKit 10 | 11 | class LabelNode : SKLabelNode { 12 | 13 | init(position: CGPoint, size: CGFloat, color: SKColor, text: String, name: String) { 14 | super.init() 15 | 16 | self.name = name 17 | self.text = text 18 | self.position = position 19 | 20 | fontName = "Early-Gameboy" 21 | fontSize = size 22 | fontColor = color 23 | } 24 | 25 | required init?(coder aDecoder: NSCoder) { 26 | fatalError("init(coder:) has not been implemented") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/LaunchScreen.xib: -------------------------------------------------------------------------------- 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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/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, 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) % twoπ 97 | if (angle >= π) { 98 | angle = angle - twoπ 99 | } 100 | if (angle <= -π) { 101 | angle = angle + twoπ 102 | } 103 | return angle 104 | } 105 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/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.startIndex) ? range.startIndex : ((self >= range.endIndex) ? range.endIndex - 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) 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, 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.endIndex - range.startIndex))) + range.startIndex 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 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/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: NSTimeInterval, performAction action: SKAction) -> SKAction { 30 | return SKAction.sequence([SKAction.waitForDuration(delay), action]) 31 | } 32 | 33 | /** 34 | * Performs a block after the specified delay. 35 | */ 36 | public class func afterDelay(delay: NSTimeInterval, runBlock block: dispatch_block_t) -> SKAction { 37 | return SKAction.afterDelay(delay, performAction: SKAction.runBlock(block)) 38 | } 39 | 40 | /** 41 | * Removes the node from its parent after the specified delay. 42 | */ 43 | public class func removeFromParentAfterDelay(delay: NSTimeInterval) -> SKAction { 44 | return SKAction.afterDelay(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: NSTimeInterval, originalPosition: CGPoint) -> SKAction { 51 | return SKAction.customActionWithDuration(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 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/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: NSTimeInterval) -> SKAction { 35 | let oldPosition = node.position 36 | let newPosition = oldPosition + amount 37 | 38 | let effect = SKTMoveEffect(node: node, duration: duration, startPosition: newPosition, endPosition: oldPosition) 39 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 40 | 41 | return SKAction.actionWithEffect(effect) 42 | } 43 | 44 | /** 45 | * Creates a screen rotation animation. 46 | * 47 | * @param node You usually want to apply this effect to a pivot node that is 48 | * centered in the scene. You cannot apply the effect to an SKScene. 49 | * @param angle The angle in radians. 50 | * @param oscillations The number of oscillations; 10 is a good value. 51 | * @param duration How long the effect lasts. Shorter is better. 52 | */ 53 | public class func screenRotateWithNode(node: SKNode, angle: CGFloat, oscillations: Int, duration: NSTimeInterval) -> SKAction { 54 | let oldAngle = node.zRotation 55 | let newAngle = oldAngle + angle 56 | 57 | let effect = SKTRotateEffect(node: node, duration: duration, startAngle: newAngle, endAngle: oldAngle) 58 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 59 | 60 | return SKAction.actionWithEffect(effect) 61 | } 62 | 63 | /** 64 | * Creates a screen zoom animation. 65 | * 66 | * @param node You usually want to apply this effect to a pivot node that is 67 | * centered in the scene. You cannot apply the effect to an SKScene. 68 | * @param amount How much to scale the node in the X and Y directions. 69 | * @param oscillations The number of oscillations; 10 is a good value. 70 | * @param duration How long the effect lasts. Shorter is better. 71 | */ 72 | public class func screenZoomWithNode(node: SKNode, amount: CGPoint, oscillations: Int, duration: NSTimeInterval) -> SKAction { 73 | let oldScale = CGPoint(x: node.xScale, y: node.yScale) 74 | let newScale = oldScale * amount 75 | 76 | let effect = SKTScaleEffect(node: node, duration: duration, startScale: newScale, endScale: oldScale) 77 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 78 | 79 | return SKAction.actionWithEffect(effect) 80 | } 81 | 82 | /** 83 | * Causes the scene background to flash for duration seconds. 84 | */ 85 | public class func colorGlitchWithScene(scene: SKScene, originalColor: SKColor, duration: NSTimeInterval) -> SKAction { 86 | return SKAction.customActionWithDuration(duration) {(node, elapsedTime) in 87 | if elapsedTime < CGFloat(duration) { 88 | scene.backgroundColor = SKColorWithRGB(Int.random(0...255), Int.random(0...255), Int.random(0...255)) 89 | } else { 90 | scene.backgroundColor = originalColor 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/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 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/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: NSTimeInterval, runBlock block: dispatch_block_t) { 43 | runAction(SKAction.sequence([SKAction.waitForDuration(delay), SKAction.runBlock(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 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/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 = NSBundle.mainBundle().URLForResource(filename, withExtension: nil) 39 | if (url == nil) { 40 | println("Could not find file: \(filename)") 41 | return 42 | } 43 | 44 | var error: NSError? = nil 45 | backgroundMusicPlayer = AVAudioPlayer(contentsOfURL: url, error: &error) 46 | if let player = backgroundMusicPlayer { 47 | player.numberOfLoops = -1 48 | player.prepareToPlay() 49 | player.play() 50 | } else { 51 | println("Could not create audio player: \(error!)") 52 | } 53 | } 54 | 55 | public func pauseBackgroundMusic() { 56 | if let player = backgroundMusicPlayer { 57 | if player.playing { 58 | player.pause() 59 | } 60 | } 61 | } 62 | 63 | public func resumeBackgroundMusic() { 64 | if let player = backgroundMusicPlayer { 65 | if !player.playing { 66 | player.play() 67 | } 68 | } 69 | } 70 | 71 | public func playSoundEffect(filename: String) { 72 | let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil) 73 | if (url == nil) { 74 | println("Could not find file: \(filename)") 75 | return 76 | } 77 | 78 | var error: NSError? = nil 79 | soundEffectPlayer = AVAudioPlayer(contentsOfURL: url, error: &error) 80 | if let player = soundEffectPlayer { 81 | player.numberOfLoops = 0 82 | player.prepareToPlay() 83 | player.play() 84 | } else { 85 | println("Could not create audio player: \(error!)") 86 | } 87 | } 88 | } 89 | 90 | private let SKTAudioInstance = SKTAudio() 91 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Sounds/jump.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Sounds/jump.wav -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Textures/hand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Textures/hand.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Textures/hand@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Textures/hand@2x.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Textures/hand_click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Textures/hand_click.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Textures/hand_click@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Textures/hand_click@2x.png -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Textures/model_texture.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/3-Lab/SCNFrogger-3/SCNFrogger/assets.scnassets/Textures/model_texture.tga -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFroggerTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.raywenderlich.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /3-Lab/SCNFrogger-3/SCNFroggerTests/SCNFroggerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SCNFroggerTests.swift 3 | // SCNFroggerTests 4 | // 5 | // Created by Kim Pedersen on 02/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class SCNFroggerTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger.xcodeproj/project.xcworkspace/xcshareddata/SCNFrogger.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 6DE4669D-839D-4A6C-935D-D50EE5C00229 9 | IDESourceControlProjectName 10 | SCNFrogger 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | C45253657BF1B0A67E13F808D5E653AC34B147B3 14 | https://github.com/devindazzle/SceneKitFrogger.git 15 | 16 | IDESourceControlProjectPath 17 | 4-Challenge/SCNFrogger-4/SCNFrogger.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | C45253657BF1B0A67E13F808D5E653AC34B147B3 21 | ../../../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/devindazzle/SceneKitFrogger.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | C45253657BF1B0A67E13F808D5E653AC34B147B3 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | C45253657BF1B0A67E13F808D5E653AC34B147B3 36 | IDESourceControlWCCName 37 | SceneKitFrogger 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger.xcodeproj/xcuserdata/kim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger.xcodeproj/xcuserdata/kim.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SCNFrogger.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 3BE6195A1A2DCDBA00ED80D7 16 | 17 | primary 18 | 19 | 20 | 3BE619711A2DCDBA00ED80D7 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(application: UIApplication) { 22 | // 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. 23 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 24 | } 25 | 26 | func applicationDidEnterBackground(application: UIApplication) { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(application: UIApplication) { 32 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | func applicationDidBecomeActive(application: UIApplication) { 36 | // 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. 37 | } 38 | 39 | func applicationWillTerminate(application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Array2D.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Array2D.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | class Array2D { 10 | 11 | var cols: Int, rows: Int 12 | var data: [Int] 13 | 14 | init(cols columnCount: Int, rows rowCount: Int, value defaultValue: Int) { 15 | self.cols = columnCount 16 | self.rows = rowCount 17 | data = Array(count: cols * rows, repeatedValue: defaultValue) 18 | } 19 | 20 | subscript(column: Int, row: Int) -> Int { 21 | get { 22 | return data[cols * row + column] 23 | } 24 | set { 25 | data[cols * row + column] = newValue 26 | } 27 | } 28 | 29 | func columnCount() -> Int { 30 | return self.cols 31 | } 32 | 33 | func rowCount() -> Int { 34 | return self.rows 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/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 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | enum GameState { 10 | case WaitingForFirstTap 11 | case Playing 12 | case GameOver 13 | case RestartLevel 14 | } 15 | 16 | 17 | enum MoveDirection { 18 | case Forward 19 | case Backward 20 | case Left 21 | case Right 22 | } 23 | 24 | 25 | struct PhysicsCategory { 26 | static let None: Int = 0 27 | static let Player: Int = 0b1 // 1 28 | static let Car: Int = 0b10 // 2 29 | static let Obstacle: Int = 0b100 // 4 30 | } -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/EarlyGameBoy.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/EarlyGameBoy.ttf -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/GameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.swift 3 | // RWDevConSceneKitFinal 4 | // 5 | // Created by Kim Pedersen on 24/11/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SceneKit 10 | import SpriteKit 11 | 12 | class GameViewController: UIViewController { 13 | 14 | var scnView: SCNView { 15 | get { 16 | return self.view as SCNView 17 | } 18 | } 19 | 20 | override func viewDidAppear(animated: Bool) { 21 | 22 | super.viewDidAppear(animated) 23 | 24 | // Set up the SCNView 25 | scnView.backgroundColor = UIColor(red: 100.0/255.0, green: 149.0/255.0, blue: 237.0/255.0, alpha: 1.0) 26 | scnView.showsStatistics = true 27 | scnView.antialiasingMode = SCNAntialiasingMode.Multisampling2X 28 | scnView.overlaySKScene = SKScene(size: view.bounds.size) 29 | scnView.playing = true 30 | 31 | // Set up the scene 32 | let scene = GameScene(view: scnView) 33 | scene.rootNode.hidden = true 34 | scene.physicsWorld.contactDelegate = scene 35 | 36 | // Start playing the scene 37 | scnView.scene = scene 38 | scnView.delegate = scene 39 | scnView.scene!.rootNode.hidden = false 40 | scnView.play(self) 41 | } 42 | 43 | 44 | override func shouldAutorotate() -> Bool { 45 | return true 46 | } 47 | 48 | 49 | override func prefersStatusBarHidden() -> Bool { 50 | return true 51 | } 52 | 53 | 54 | override func supportedInterfaceOrientations() -> Int { 55 | return Int(UIInterfaceOrientationMask.Portrait.rawValue) 56 | } 57 | 58 | 59 | override func didReceiveMemoryWarning() { 60 | super.didReceiveMemoryWarning() 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/HandNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HandNode.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SpriteKit 10 | 11 | class HandNode : SKNode { 12 | 13 | override init() { 14 | 15 | super.init() 16 | 17 | name = "Tutorial" 18 | 19 | // Load textures 20 | let handTexture = SKTexture(imageNamed:"assets.scnassets/Textures/hand.png") 21 | handTexture.filteringMode = SKTextureFilteringMode.Nearest 22 | let handTextureClick = SKTexture(imageNamed:"assets.scnassets/Textures/hand_click.png") 23 | handTextureClick.filteringMode = SKTextureFilteringMode.Nearest 24 | 25 | // Create animation 26 | let handAnimation = SKAction.animateWithTextures([handTexture, handTextureClick], timePerFrame:0.5) 27 | 28 | // Create a sprite node abd animate it 29 | let handSprite = SKSpriteNode(texture: handTexture) 30 | handSprite.xScale = 2.0 31 | handSprite.yScale = 2.0 32 | handSprite.runAction(SKAction.repeatActionForever(handAnimation)) 33 | 34 | addChild(handSprite) 35 | } 36 | 37 | 38 | required init?(coder aDecoder: NSCoder) { 39 | fatalError("init(coder:) has not been implemented") 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-Small@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-Small@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-40@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-40@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-60@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-60@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "29x29", 41 | "idiom" : "ipad", 42 | "filename" : "Icon-Small.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "Icon-Small@2x-1.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "40x40", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-40.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-40@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "76x76", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-76.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "76x76", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-76@2x.png", 73 | "scale" : "2x" 74 | } 75 | ], 76 | "info" : { 77 | "version" : 1, 78 | "author" : "xcode" 79 | } 80 | } -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "rwdevcon-bg.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/rwdevcon-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/rwdevcon-bg.imageset/rwdevcon-bg.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "rwdevcon-logo.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/rwdevcon-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/Images.xcassets/rwdevcon-logo.imageset/rwdevcon-logo.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.raywenderlich.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UIAppFonts 26 | 27 | EarlyGameBoy.ttf 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UIStatusBarHidden 38 | 39 | UISupportedInterfaceOrientations 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/LabelNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LabelNode.swift 3 | // SCNFrogger 4 | // 5 | // Created by Kim Pedersen on 11/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import SpriteKit 10 | 11 | class LabelNode : SKLabelNode { 12 | 13 | init(position: CGPoint, size: CGFloat, color: SKColor, text: String, name: String) { 14 | super.init() 15 | 16 | self.name = name 17 | self.text = text 18 | self.position = position 19 | 20 | fontName = "Early-Gameboy" 21 | fontSize = size 22 | fontColor = color 23 | } 24 | 25 | required init?(coder aDecoder: NSCoder) { 26 | fatalError("init(coder:) has not been implemented") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/LaunchScreen.xib: -------------------------------------------------------------------------------- 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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/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, 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) % twoπ 97 | if (angle >= π) { 98 | angle = angle - twoπ 99 | } 100 | if (angle <= -π) { 101 | angle = angle + twoπ 102 | } 103 | return angle 104 | } 105 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/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.startIndex) ? range.startIndex : ((self >= range.endIndex) ? range.endIndex - 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) 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, 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.endIndex - range.startIndex))) + range.startIndex 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 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/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: NSTimeInterval, performAction action: SKAction) -> SKAction { 30 | return SKAction.sequence([SKAction.waitForDuration(delay), action]) 31 | } 32 | 33 | /** 34 | * Performs a block after the specified delay. 35 | */ 36 | public class func afterDelay(delay: NSTimeInterval, runBlock block: dispatch_block_t) -> SKAction { 37 | return SKAction.afterDelay(delay, performAction: SKAction.runBlock(block)) 38 | } 39 | 40 | /** 41 | * Removes the node from its parent after the specified delay. 42 | */ 43 | public class func removeFromParentAfterDelay(delay: NSTimeInterval) -> SKAction { 44 | return SKAction.afterDelay(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: NSTimeInterval, originalPosition: CGPoint) -> SKAction { 51 | return SKAction.customActionWithDuration(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 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/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: NSTimeInterval) -> SKAction { 35 | let oldPosition = node.position 36 | let newPosition = oldPosition + amount 37 | 38 | let effect = SKTMoveEffect(node: node, duration: duration, startPosition: newPosition, endPosition: oldPosition) 39 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 40 | 41 | return SKAction.actionWithEffect(effect) 42 | } 43 | 44 | /** 45 | * Creates a screen rotation animation. 46 | * 47 | * @param node You usually want to apply this effect to a pivot node that is 48 | * centered in the scene. You cannot apply the effect to an SKScene. 49 | * @param angle The angle in radians. 50 | * @param oscillations The number of oscillations; 10 is a good value. 51 | * @param duration How long the effect lasts. Shorter is better. 52 | */ 53 | public class func screenRotateWithNode(node: SKNode, angle: CGFloat, oscillations: Int, duration: NSTimeInterval) -> SKAction { 54 | let oldAngle = node.zRotation 55 | let newAngle = oldAngle + angle 56 | 57 | let effect = SKTRotateEffect(node: node, duration: duration, startAngle: newAngle, endAngle: oldAngle) 58 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 59 | 60 | return SKAction.actionWithEffect(effect) 61 | } 62 | 63 | /** 64 | * Creates a screen zoom animation. 65 | * 66 | * @param node You usually want to apply this effect to a pivot node that is 67 | * centered in the scene. You cannot apply the effect to an SKScene. 68 | * @param amount How much to scale the node in the X and Y directions. 69 | * @param oscillations The number of oscillations; 10 is a good value. 70 | * @param duration How long the effect lasts. Shorter is better. 71 | */ 72 | public class func screenZoomWithNode(node: SKNode, amount: CGPoint, oscillations: Int, duration: NSTimeInterval) -> SKAction { 73 | let oldScale = CGPoint(x: node.xScale, y: node.yScale) 74 | let newScale = oldScale * amount 75 | 76 | let effect = SKTScaleEffect(node: node, duration: duration, startScale: newScale, endScale: oldScale) 77 | effect.timingFunction = SKTCreateShakeFunction(oscillations) 78 | 79 | return SKAction.actionWithEffect(effect) 80 | } 81 | 82 | /** 83 | * Causes the scene background to flash for duration seconds. 84 | */ 85 | public class func colorGlitchWithScene(scene: SKScene, originalColor: SKColor, duration: NSTimeInterval) -> SKAction { 86 | return SKAction.customActionWithDuration(duration) {(node, elapsedTime) in 87 | if elapsedTime < CGFloat(duration) { 88 | scene.backgroundColor = SKColorWithRGB(Int.random(0...255), Int.random(0...255), Int.random(0...255)) 89 | } else { 90 | scene.backgroundColor = originalColor 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/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 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/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: NSTimeInterval, runBlock block: dispatch_block_t) { 43 | runAction(SKAction.sequence([SKAction.waitForDuration(delay), SKAction.runBlock(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 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/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 = NSBundle.mainBundle().URLForResource(filename, withExtension: nil) 39 | if (url == nil) { 40 | println("Could not find file: \(filename)") 41 | return 42 | } 43 | 44 | var error: NSError? = nil 45 | backgroundMusicPlayer = AVAudioPlayer(contentsOfURL: url, error: &error) 46 | if let player = backgroundMusicPlayer { 47 | player.numberOfLoops = -1 48 | player.prepareToPlay() 49 | player.play() 50 | } else { 51 | println("Could not create audio player: \(error!)") 52 | } 53 | } 54 | 55 | public func pauseBackgroundMusic() { 56 | if let player = backgroundMusicPlayer { 57 | if player.playing { 58 | player.pause() 59 | } 60 | } 61 | } 62 | 63 | public func resumeBackgroundMusic() { 64 | if let player = backgroundMusicPlayer { 65 | if !player.playing { 66 | player.play() 67 | } 68 | } 69 | } 70 | 71 | public func playSoundEffect(filename: String) { 72 | let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil) 73 | if (url == nil) { 74 | println("Could not find file: \(filename)") 75 | return 76 | } 77 | 78 | var error: NSError? = nil 79 | soundEffectPlayer = AVAudioPlayer(contentsOfURL: url, error: &error) 80 | if let player = soundEffectPlayer { 81 | player.numberOfLoops = 0 82 | player.prepareToPlay() 83 | player.play() 84 | } else { 85 | println("Could not create audio player: \(error!)") 86 | } 87 | } 88 | } 89 | 90 | private let SKTAudioInstance = SKTAudio() 91 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Sounds/jump.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Sounds/jump.wav -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Textures/hand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Textures/hand.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Textures/hand@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Textures/hand@2x.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Textures/hand_click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Textures/hand_click.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Textures/hand_click@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Textures/hand_click@2x.png -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Textures/model_texture.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/4-Challenge/SCNFrogger-4/SCNFrogger/assets.scnassets/Textures/model_texture.tga -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFroggerTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.raywenderlich.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /4-Challenge/SCNFrogger-4/SCNFroggerTests/SCNFroggerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SCNFroggerTests.swift 3 | // SCNFroggerTests 4 | // 5 | // Created by Kim Pedersen on 02/12/14. 6 | // Copyright (c) 2014 RWDevCon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class SCNFroggerTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /5-Conclusion/5-Conclusion.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/5-Conclusion/5-Conclusion.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Kim Pedersen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SCNFrogger 2 | =============== 3 | A 3D Frogger / Crossy Road clone made with Scene Kit and Swift. 4 | 5 | Source Code for my tutorial on Scene Kit at [RWDevCon](http://www.rwdevcon.com) February 6th-7th, 2015 in Washington DC. 6 | 7 | ![SCNFrogger](screenshot.png) 8 | 9 | Contains all the steps and materials used during the conference: 10 | 11 | **0-For-Instructor:** All the presentations and markdown files. 12 | 13 | **1-Starter:** The starter project. 14 | 15 | **2-Demo:** The finished Demo project after going through the steps in [Demo Instructions](https://github.com/devindazzle/SceneKitFrogger/blob/master/0-For-Instructor/2-Demo.markdown) 16 | 17 | **3-Lab:** The finished project after completing the Lab via the [lab instructions](https://github.com/devindazzle/SceneKitFrogger/blob/master/0-For-Instructor/3-LabInstructions.markdown) 18 | 19 | **4-Challenge:** The finished project after completing the Challenge via the [challenge instructions](https://github.com/devindazzle/SceneKitFrogger/blob/master/0-For-Instructor/4-ChallengeInstructions.markdown) 20 | 21 | If you just want to see the final result, you should open the project in the "4-Challenge" folder. 22 | 23 | If you find this useful or have any questions or comments, reach out to me on Twitter [@twofly3](https://twitter.com/twofly3) 24 | 25 | The models included in the project is created using the open-source voxel editor [Magica Voxel](https://voxel.codeplex.com) and cleaned up in [Blender](http://www.blender.org). -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devindazzle/SceneKitFrogger/5da7da0c7e7dc9f914aa30f65350e90cab35bafd/screenshot.png --------------------------------------------------------------------------------