Skip to content

Commit fca7e86

Browse files
committed
Badger: Version 1.0, 2016-09-13
First release This sample demonstrates how to build a SceneKit-based game with advanced graphics.
1 parent bc16dc0 commit fca7e86

File tree

230 files changed

+3082
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

230 files changed

+3082
-0
lines changed

Badger/Badger.xcodeproj/project.pbxproj

+644
Large diffs are not rendered by default.
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
Copyright (C) 2016 Apple Inc. All Rights Reserved.
3+
See LICENSE.txt for this sample’s licensing information
4+
5+
Abstract:
6+
An extension on CAAnimation used to load animations from an SCNScene.
7+
*/
8+
9+
import SceneKit
10+
11+
// MARK: Core Animation
12+
13+
extension CAAnimation {
14+
class func animation(withSceneName name: String) -> CAAnimation {
15+
guard let scene = SCNScene(named: name) else {
16+
fatalError("Failed to find scene with name \(name).")
17+
}
18+
19+
var animation: CAAnimation?
20+
scene.rootNode.enumerateChildNodes { (child, stop) in
21+
guard let firstKey = child.animationKeys.first else { return }
22+
animation = child.animation(forKey: firstKey)
23+
stop.initialize(to: true)
24+
}
25+
26+
guard let foundAnimation = animation else {
27+
fatalError("Failed to find animation named \(name).")
28+
}
29+
30+
foundAnimation.fadeInDuration = 0.3
31+
foundAnimation.fadeOutDuration = 0.3
32+
foundAnimation.repeatCount = 1
33+
34+
return foundAnimation
35+
}
36+
}

Badger/Common/View.swift

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
Copyright (C) 2016 Apple Inc. All Rights Reserved.
3+
See LICENSE.txt for this sample’s licensing information
4+
5+
Abstract:
6+
An SCNView used to relay keyboard controls on OSX, and present
7+
setup the 2D overlay.
8+
*/
9+
10+
import GameKit
11+
12+
class View: SCNView {
13+
14+
// MARK: Mouse and Keyboard Events
15+
16+
#if os(OSX)
17+
var eventsDelegate: KeyboardEventsDelegate?
18+
19+
override func keyDown(with event: NSEvent) {
20+
guard let eventsDelegate = eventsDelegate, eventsDelegate.keyDown(in: self, with: event) else {
21+
super.keyDown(with: event)
22+
return
23+
}
24+
}
25+
26+
override func keyUp(with event: NSEvent) {
27+
guard let eventsDelegate = eventsDelegate, eventsDelegate.keyUp(in: self, with: event) else {
28+
super.keyUp(with: event)
29+
return
30+
}
31+
}
32+
#endif
33+
34+
// Resizing
35+
36+
#if os(iOS) || os(tvOS)
37+
override func layoutSubviews() {
38+
super.layoutSubviews()
39+
update2DOverlays()
40+
}
41+
#elseif os(OSX)
42+
override func setFrameSize(_ newSize: NSSize) {
43+
super.setFrameSize(newSize)
44+
update2DOverlays()
45+
}
46+
#endif
47+
48+
// MARK: Overlays
49+
50+
private let _overlayNode = SKNode()
51+
private let _scaleNode = SKNode()
52+
private let _collectedItemsCountLabel = SKLabelNode(fontNamed: "Superclarendon")
53+
54+
private func update2DOverlays() {
55+
_overlayNode.position = CGPoint(x: 0.0, y: bounds.size.height)
56+
}
57+
58+
func setup2DOverlay() {
59+
let w = bounds.size.width
60+
let h = bounds.size.height
61+
62+
// Setup the game overlays using SpriteKit.
63+
let skScene = SKScene(size: CGSize(width: w, height: h))
64+
skScene.scaleMode = .resizeFill
65+
66+
skScene.addChild(_scaleNode)
67+
_scaleNode.addChild(_overlayNode)
68+
_overlayNode.position = CGPoint(x: 0.0, y: h)
69+
70+
#if os(OSX)
71+
_scaleNode.xScale = layer!.contentsScale
72+
_scaleNode.yScale = layer!.contentsScale
73+
#endif
74+
75+
// The Bob icon.
76+
let bobSprite = SKSpriteNode(imageNamed: "BobHUD.png")
77+
bobSprite.position = CGPoint(x: 70, y:-50)
78+
bobSprite.xScale = 0.5
79+
bobSprite.yScale = 0.5
80+
_overlayNode.addChild(bobSprite)
81+
82+
_collectedItemsCountLabel.text = "x0"
83+
_collectedItemsCountLabel.horizontalAlignmentMode = .left
84+
_collectedItemsCountLabel.position = CGPoint(x: 135, y:-63)
85+
_overlayNode.addChild(_collectedItemsCountLabel)
86+
87+
// Assign the SpriteKit overlay to the SceneKit view.
88+
self.overlaySKScene = skScene
89+
skScene.isUserInteractionEnabled = false
90+
}
91+
92+
var collectedItemsCount = 0 {
93+
didSet {
94+
_collectedItemsCountLabel.text = "x\(collectedItemsCount)"
95+
}
96+
}
97+
98+
func didCollectItem() {
99+
collectedItemsCount = collectedItemsCount + 1
100+
}
101+
102+
func didCollectBigItem() {
103+
collectedItemsCount = collectedItemsCount + 10
104+
}
105+
106+
}
+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
Copyright (C) 2016 Apple Inc. All Rights Reserved.
3+
See LICENSE.txt for this sample’s licensing information
4+
5+
Abstract:
6+
Handles keyboard (macOS), touch (iOS) and controller (iOS, tvOS) input for controlling the game.
7+
*/
8+
9+
import GameKit
10+
11+
#if os(OSX)
12+
protocol KeyboardEventsDelegate {
13+
func keyDown(in view: NSView, with event: NSEvent) -> Bool
14+
func keyUp(in view: NSView, with event: NSEvent) -> Bool
15+
}
16+
17+
private enum KeyboardDirection: UInt16 {
18+
case left = 123
19+
case right = 124
20+
case down = 125
21+
case up = 126
22+
}
23+
24+
extension ViewController: KeyboardEventsDelegate {}
25+
#endif
26+
27+
extension ViewController {
28+
29+
// MARK: Game Controller Events
30+
31+
func setupGameControllers() {
32+
#if os(OSX)
33+
sceneView.eventsDelegate = self
34+
#endif
35+
36+
#if os(iOS) || os(tvOS)
37+
// Gesture recognizers
38+
let directions: [UISwipeGestureRecognizerDirection] = [.right, .left, .up, .down]
39+
for direction in directions {
40+
let gesture = UISwipeGestureRecognizer(target: self, action: #selector(didSwipe))
41+
gesture.direction = direction
42+
sceneView.addGestureRecognizer(gesture)
43+
}
44+
#endif
45+
}
46+
47+
@objc func handleControllerDidConnectNotification(_ notification: NSNotification) {
48+
let gameController = notification.object as! GCController
49+
registerCharacterMovementEvents(gameController)
50+
}
51+
52+
private func registerCharacterMovementEvents(_ gameController: GCController) {
53+
// An analog movement handler for D-pads and thumbsticks.
54+
let movementHandler: GCControllerDirectionPadValueChangedHandler = { [unowned self] dpad, _, _ in
55+
self.controllerDPad = dpad
56+
}
57+
58+
#if os(tvOS)
59+
60+
// Apple TV remote
61+
if let microGamepad = gameController.microGamepad {
62+
// Allow the gamepad to handle transposing D-pad values when rotating the controller.
63+
microGamepad.allowsRotation = true
64+
microGamepad.dpad.valueChangedHandler = movementHandler
65+
}
66+
67+
#endif
68+
69+
// Gamepad D-pad
70+
if let gamepad = gameController.gamepad {
71+
gamepad.dpad.valueChangedHandler = movementHandler
72+
}
73+
74+
// Extended gamepad left thumbstick
75+
if let extendedGamepad = gameController.extendedGamepad {
76+
extendedGamepad.leftThumbstick.valueChangedHandler = movementHandler
77+
}
78+
}
79+
80+
// MARK: Touch Events
81+
82+
#if os(iOS) || os(tvOS)
83+
func didSwipe(sender: UISwipeGestureRecognizer) {
84+
if startGameIfNeeded() {
85+
return
86+
}
87+
88+
switch sender.direction {
89+
case UISwipeGestureRecognizerDirection.up: jump()
90+
case UISwipeGestureRecognizerDirection.down: squat()
91+
case UISwipeGestureRecognizerDirection.left: leanLeft()
92+
case UISwipeGestureRecognizerDirection.right: leanRight()
93+
default: break
94+
}
95+
}
96+
#endif
97+
98+
// MARK: Keyboard Events
99+
100+
#if os(OSX)
101+
func keyDown(in view: NSView, with event: NSEvent) -> Bool {
102+
if event.isARepeat {
103+
return true
104+
}
105+
106+
if startGameIfNeeded() {
107+
return true
108+
}
109+
110+
if let direction = KeyboardDirection(rawValue: event.keyCode) {
111+
switch direction {
112+
case .up: jump()
113+
case .down: squat()
114+
case .left: leanLeft()
115+
case .right: leanRight()
116+
}
117+
return true
118+
}
119+
return false
120+
}
121+
122+
func keyUp(in view: NSView, with event: NSEvent) -> Bool {
123+
let direction = KeyboardDirection(rawValue: event.keyCode)
124+
return direction != nil ? true : false
125+
}
126+
#endif
127+
}

0 commit comments

Comments
 (0)