From 46069aeb41cc75022c210f3cffbeceb5e2eaef07 Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Sun, 6 Oct 2019 22:07:32 +0100 Subject: [PATCH 01/10] Part 11 --- Source/Engine/Actor.swift | 25 ++++++++++ Source/Engine/Pushwall.swift | 62 ++++++++++++++++++++++++ Source/Engine/Renderer.swift | 23 +++++---- Source/Engine/Thing.swift | 1 + Source/Engine/Tilemap.swift | 17 ++++++- Source/Engine/Vector.swift | 6 ++- Source/Engine/World.swift | 42 ++++++++++++++-- Source/Rampage.xcodeproj/project.pbxproj | 4 ++ Source/Rampage/Map.json | 6 +-- 9 files changed, 165 insertions(+), 21 deletions(-) create mode 100644 Source/Engine/Pushwall.swift diff --git a/Source/Engine/Actor.swift b/Source/Engine/Actor.swift index f8e581f..217932c 100644 --- a/Source/Engine/Actor.swift +++ b/Source/Engine/Actor.swift @@ -41,6 +41,10 @@ public extension Actor { return rect.intersection(with: door.rect) } + func intersection(with pushwall: Pushwall) -> Vector? { + return rect.intersection(with: pushwall.rect) + } + func intersection(with world: World) -> Vector? { if let intersection = intersection(with: world.map) { return intersection @@ -50,6 +54,11 @@ public extension Actor { return intersection } } + for pushwall in world.pushwalls where pushwall.position != position { + if let intersection = intersection(with: pushwall) { + return intersection + } + } return nil } @@ -67,4 +76,20 @@ public extension Actor { attempts -= 1 } } + + func isStuck(in world: World) -> Bool { + // If outside map + if position.x < 1 || position.x > world.map.size.x - 1 || + position.y < 1 || position.y > world.map.size.y - 1 { + return true + } + // If stuck in a wall + if world.map[Int(position.x), Int(position.y)].isWall { + return true + } + // If stuck in pushwall + return world.pushwalls.contains(where: { + abs(position.x - $0.position.x) < 0.6 && abs(position.y - $0.position.y) < 0.6 + }) + } } diff --git a/Source/Engine/Pushwall.swift b/Source/Engine/Pushwall.swift new file mode 100644 index 0000000..2976520 --- /dev/null +++ b/Source/Engine/Pushwall.swift @@ -0,0 +1,62 @@ +// +// Pushwall.swift +// Engine +// +// Created by Nick Lockwood on 30/09/2019. +// Copyright © 2019 Nick Lockwood. All rights reserved. +// + +public struct Pushwall: Actor { + public let radius: Double = 0.5 + public let speed: Double = 0.25 + public var position: Vector + public var velocity: Vector + public let tile: Tile + + public init(position: Vector, tile: Tile) { + self.position = position + self.velocity = Vector(x: 0, y: 0) + self.tile = tile + } +} + +public extension Pushwall { + var isDead: Bool { return false } + + func billboards(facing viewpoint: Vector) -> [Billboard] { + let topLeft = rect.min, bottomRight = rect.max + let topRight = Vector(x: bottomRight.x, y: topLeft.y) + let bottomLeft = Vector(x: topLeft.x, y: bottomRight.y) + let textures = tile.textures + return [ + Billboard(start: topLeft, direction: Vector(x: 0, y: 1), length: 1, texture: textures[0]), + Billboard(start: topRight, direction: Vector(x: -1, y: 0), length: 1, texture: textures[1]), + Billboard(start: bottomRight, direction: Vector(x: 0, y: -1), length: 1, texture: textures[0]), + Billboard(start: bottomLeft, direction: Vector(x: 1, y: 0), length: 1, texture: textures[1]) + ].filter { billboard in + let ray = billboard.start - viewpoint + let faceNormal = billboard.direction.orthogonal + return ray.dot(faceNormal) < 0 + } + } + + var isMoving: Bool { + return velocity.x != 0 || velocity.y != 0 + } + + mutating func update(in world: inout World) { + if isMoving == false, let intersection = world.player.intersection(with: self) { + if abs(intersection.x) > abs(intersection.y) { + velocity = Vector(x: intersection.x > 0 ? speed : -speed, y: 0) + } else { + velocity = Vector(x: 0, y: intersection.y > 0 ? speed : -speed) + } + } + if let intersection = self.intersection(with: world), + abs(intersection.x) > 0.001 || abs(intersection.y) > 0.001 { + velocity = Vector(x: 0, y: 0) + position.x = position.x.rounded(.down) + 0.5 + position.y = position.y.rounded(.down) + 0.5 + } + } +} diff --git a/Source/Engine/Renderer.swift b/Source/Engine/Renderer.swift index 2a96bab..2a09f2e 100644 --- a/Source/Engine/Renderer.swift +++ b/Source/Engine/Renderer.swift @@ -26,16 +26,6 @@ public extension Renderer { let viewCenter = world.player.position + world.player.direction * focalLength let viewStart = viewCenter - viewPlane / 2 - // Sort sprites by distance - var spritesByDistance: [(distance: Double, sprite: Billboard)] = [] - for sprite in world.sprites { - let spriteDistance = (sprite.start - world.player.position).length - spritesByDistance.append( - (distance: spriteDistance, sprite: sprite) - ) - } - spritesByDistance.sort(by: { $0.distance > $1.distance }) - // Cast rays let columns = bitmap.width let step = viewPlane / Double(columns) @@ -95,8 +85,9 @@ public extension Renderer { bitmap[x, bitmap.height - 1 - y] = ceilingTexture[normalized: textureX, textureY] } - // Draw sprites - for (_, sprite) in spritesByDistance { + // Sort sprites by distance + var spritesByDistance: [(hit: Vector, distance: Double, sprite: Billboard)] = [] + for sprite in world.sprites { guard let hit = sprite.hitTest(ray) else { continue } @@ -104,6 +95,14 @@ public extension Renderer { if spriteDistance > wallDistance { continue } + spritesByDistance.append( + (hit: hit, distance: spriteDistance, sprite: sprite) + ) + } + spritesByDistance.sort(by: { $0.distance > $1.distance }) + + // Draw sprites + for (hit, spriteDistance, sprite) in spritesByDistance { let perpendicular = spriteDistance / distanceRatio let height = wallHeight / perpendicular * Double(bitmap.height) let spriteX = (hit - sprite.start).length / sprite.length diff --git a/Source/Engine/Thing.swift b/Source/Engine/Thing.swift index f202675..0a50c7a 100644 --- a/Source/Engine/Thing.swift +++ b/Source/Engine/Thing.swift @@ -11,4 +11,5 @@ public enum Thing: Int, Decodable { case player case monster case door + case pushwall } diff --git a/Source/Engine/Tilemap.swift b/Source/Engine/Tilemap.swift index 8b8b409..a474962 100644 --- a/Source/Engine/Tilemap.swift +++ b/Source/Engine/Tilemap.swift @@ -7,7 +7,7 @@ // public struct Tilemap: Decodable { - private let tiles: [Tile] + private(set) var tiles: [Tile] public let things: [Thing] public let width: Int } @@ -22,7 +22,8 @@ public extension Tilemap { } subscript(x: Int, y: Int) -> Tile { - return tiles[y * width + x] + get { return tiles[y * width + x] } + set { tiles[y * width + x] = newValue } } func tileCoords(at position: Vector, from direction: Vector) -> (x: Int, y: Int) { @@ -41,6 +42,18 @@ public extension Tilemap { return self[x, y] } + func closestFloorTile(to x: Int, _ y: Int) -> Tile? { + for y in max(0, y - 1) ... min(height - 1, y + 1) { + for x in max(0, x - 1) ... min(width - 1, x + 1) { + let tile = self[x, y] + if tile.isWall == false { + return tile + } + } + } + return nil + } + func hitTest(_ ray: Ray) -> Vector { var position = ray.origin let slope = ray.direction.x / ray.direction.y diff --git a/Source/Engine/Vector.swift b/Source/Engine/Vector.swift index 40ac090..2574477 100644 --- a/Source/Engine/Vector.swift +++ b/Source/Engine/Vector.swift @@ -6,7 +6,7 @@ // Copyright © 2019 Nick Lockwood. All rights reserved. // -public struct Vector { +public struct Vector: Equatable { public var x, y: Double public init(x: Double, y: Double) { @@ -24,6 +24,10 @@ public extension Vector { return (x * x + y * y).squareRoot() } + func dot(_ rhs: Vector) -> Double { + return x * rhs.x + y * rhs.y + } + static func + (lhs: Vector, rhs: Vector) -> Vector { return Vector(x: lhs.x + rhs.x, y: lhs.y + rhs.y) } diff --git a/Source/Engine/World.swift b/Source/Engine/World.swift index acb6d39..ea0d91a 100644 --- a/Source/Engine/World.swift +++ b/Source/Engine/World.swift @@ -7,8 +7,9 @@ // public struct World { - public let map: Tilemap + public private(set) var map: Tilemap public private(set) var doors: [Door] + public private(set) var pushwalls: [Pushwall] public private(set) var monsters: [Monster] public private(set) var player: Player! public private(set) var effects: [Effect] @@ -16,6 +17,7 @@ public struct World { public init(map: Tilemap) { self.map = map self.doors = [] + self.pushwalls = [] self.monsters = [] self.effects = [] reset() @@ -68,6 +70,14 @@ public extension World { doors[i] = door } + // Update pushwalls + for i in 0 ..< pushwalls.count { + var pushwall = pushwalls[i] + pushwall.update(in: &self) + pushwall.position += pushwall.velocity * timeStep + pushwalls[i] = pushwall + } + // Handle collisions for i in 0 ..< monsters.count { var monster = monsters[i] @@ -85,11 +95,20 @@ public extension World { monsters[i] = monster } player.avoidWalls(in: self) + + // Check for stuck actors + if player.isStuck(in: self) { + hurtPlayer(1) + } + for i in 0 ..< monsters.count where monsters[i].isStuck(in: self) { + hurtMonster(at: i, damage: 1) + } } var sprites: [Billboard] { let ray = Ray(origin: player.position, direction: player.direction) return monsters.map { $0.billboard(for: ray) } + doors.map { $0.billboard } + + pushwalls.flatMap { $0.billboards(facing: player.position) } } mutating func hurtPlayer(_ damage: Double) { @@ -125,6 +144,7 @@ public extension World { mutating func reset() { self.monsters = [] self.doors = [] + var pushwallCount = 0 for y in 0 ..< map.height { for x in 0 ..< map.width { let position = Vector(x: Double(x) + 0.5, y: Double(y) + 0.5) @@ -140,6 +160,20 @@ public extension World { precondition(y > 0 && y < map.height, "Door cannot be placed on map edge") let isVertical = map[x, y - 1].isWall && map[x, y + 1].isWall doors.append(Door(position: position, isVertical: isVertical)) + case .pushwall: + pushwallCount += 1 + if pushwalls.count >= pushwallCount { + let tile = pushwalls[pushwallCount - 1].tile + pushwalls[pushwallCount - 1] = Pushwall(position: position, tile: tile) + break + } + var tile = map[x, y] + if tile.isWall { + map[x, y] = .floor + } else { + tile = map.closestFloorTile(to: x, y) ?? .wall + } + pushwalls.append(Pushwall(position: position, tile: tile)) } } } @@ -148,8 +182,10 @@ public extension World { func hitTest(_ ray: Ray) -> Vector { var wallHit = map.hitTest(ray) var distance = (wallHit - ray.origin).length - for door in doors { - guard let hit = door.billboard.hitTest(ray) else { + let billboards = doors.map { $0.billboard } + + pushwalls.flatMap { $0.billboards(facing: ray.origin) } + for billboard in billboards { + guard let hit = billboard.hitTest(ray) else { continue } let hitDistance = (hit - ray.origin).length diff --git a/Source/Rampage.xcodeproj/project.pbxproj b/Source/Rampage.xcodeproj/project.pbxproj index 8dfcb18..b36890a 100644 --- a/Source/Rampage.xcodeproj/project.pbxproj +++ b/Source/Rampage.xcodeproj/project.pbxproj @@ -38,6 +38,7 @@ 01D09B0B22A7F7570052745A /* Textures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09B0A22A7F7570052745A /* Textures.swift */; }; 01D0F5D922F80E1600682CA1 /* RampageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D0F5D822F80E1600682CA1 /* RampageTests.swift */; }; 01D0F5F122FF095E00682CA1 /* Door.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D0F5F022FF095E00682CA1 /* Door.swift */; }; + 01E3963A2342758D00D02236 /* Pushwall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01E396392342758D00D02236 /* Pushwall.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -107,6 +108,7 @@ 01D0F5D822F80E1600682CA1 /* RampageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RampageTests.swift; sourceTree = ""; }; 01D0F5DA22F80E1600682CA1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 01D0F5F022FF095E00682CA1 /* Door.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Door.swift; sourceTree = ""; }; + 01E396392342758D00D02236 /* Pushwall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pushwall.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -184,6 +186,7 @@ 01D09B0222A4958E0052745A /* Input.swift */, 012A0C6122CC200D0068E8EF /* Monster.swift */, 01D09AFA22A485040052745A /* Player.swift */, + 01E396392342758D00D02236 /* Pushwall.swift */, 01D09B0422A5C9DB0052745A /* Ray.swift */, 01D09AFC22A4873B0052745A /* Rect.swift */, 01ADC63B22B957FD00DC8AAD /* Renderer.swift */, @@ -383,6 +386,7 @@ 01D09AF122A481AB0052745A /* Color.swift in Sources */, 012A0CA222D7AD0A0068E8EF /* Animation.swift in Sources */, 01D09B0522A5C9DB0052745A /* Ray.swift in Sources */, + 01E3963A2342758D00D02236 /* Pushwall.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/Rampage/Map.json b/Source/Rampage/Map.json index 55476d0..03719e2 100644 --- a/Source/Rampage/Map.json +++ b/Source/Rampage/Map.json @@ -5,7 +5,7 @@ 1, 0, 0, 2, 0, 0, 0, 1, 1, 4, 0, 3, 4, 0, 0, 3, 2, 0, 0, 0, 0, 0, 4, 3, - 1, 4, 0, 1, 1, 1, 0, 1, + 1, 4, 0, 1, 3, 1, 0, 1, 1, 0, 4, 2, 0, 0, 0, 1, 1, 0, 0, 1, 0, 4, 4, 1, 1, 3, 3, 1, 1, 3, 1, 1 @@ -13,9 +13,9 @@ "things": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 4, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 From 581360e6111d3940224c6ea3bf5fb3e9947a0318 Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Mon, 9 Mar 2020 17:18:08 +0200 Subject: [PATCH 02/10] Part 12 --- Source/Engine/Renderer.swift | 6 ++ Source/Engine/Switch.swift | 61 ++++++++++++++++++ Source/Engine/Textures.swift | 2 + Source/Engine/Thing.swift | 1 + Source/Engine/Tile.swift | 13 +++- Source/Engine/Tilemap.swift | 16 ++++- Source/Engine/World.swift | 57 +++++++++++++++- Source/Rampage.xcodeproj/project.pbxproj | 12 ++-- .../xcshareddata/xcschemes/Rampage.xcscheme | 22 +++---- .../elevatorBackWall.imageset/Contents.json | 21 ++++++ .../elevatorBackWall.png | Bin 0 -> 99 bytes .../elevatorCeiling.imageset/Contents.json | 21 ++++++ .../elevatorCeiling.png | Bin 0 -> 301 bytes .../elevatorFloor.imageset/Contents.json | 21 ++++++ .../elevatorFloor.imageset/elevatorFloor.png | Bin 0 -> 227 bytes .../elevatorSideWall.imageset/Contents.json | 21 ++++++ .../elevatorSideWall.png | Bin 0 -> 970 bytes .../switch1.imageset/Contents.json | 21 ++++++ .../switch1.imageset/switch1.png | Bin 0 -> 280 bytes .../switch2.imageset/Contents.json | 21 ++++++ .../switch2.imageset/switch2.png | Bin 0 -> 283 bytes .../switch3.imageset/Contents.json | 21 ++++++ .../switch3.imageset/switch3.png | Bin 0 -> 284 bytes .../switch4.imageset/Contents.json | 21 ++++++ .../switch4.imageset/switch4.png | Bin 0 -> 290 bytes Source/Rampage/Levels.json | 44 +++++++++++++ Source/Rampage/Map.json | 23 ------- Source/Rampage/ViewController.swift | 18 ++++-- Source/RampageTests/RampageTests.swift | 2 +- 29 files changed, 394 insertions(+), 51 deletions(-) create mode 100644 Source/Engine/Switch.swift create mode 100644 Source/Rampage/Assets.xcassets/elevatorBackWall.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/elevatorBackWall.imageset/elevatorBackWall.png create mode 100644 Source/Rampage/Assets.xcassets/elevatorCeiling.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/elevatorCeiling.imageset/elevatorCeiling.png create mode 100644 Source/Rampage/Assets.xcassets/elevatorFloor.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/elevatorFloor.imageset/elevatorFloor.png create mode 100644 Source/Rampage/Assets.xcassets/elevatorSideWall.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/elevatorSideWall.imageset/elevatorSideWall.png create mode 100644 Source/Rampage/Assets.xcassets/switch1.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/switch1.imageset/switch1.png create mode 100644 Source/Rampage/Assets.xcassets/switch2.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/switch2.imageset/switch2.png create mode 100644 Source/Rampage/Assets.xcassets/switch3.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/switch3.imageset/switch3.png create mode 100644 Source/Rampage/Assets.xcassets/switch4.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/switch4.imageset/switch4.png create mode 100644 Source/Rampage/Levels.json delete mode 100644 Source/Rampage/Map.json diff --git a/Source/Engine/Renderer.swift b/Source/Engine/Renderer.swift index 2a09f2e..638f5cd 100644 --- a/Source/Engine/Renderer.swift +++ b/Source/Engine/Renderer.swift @@ -64,6 +64,12 @@ public extension Renderer { let wallStart = Vector(x: Double(x), y: (Double(bitmap.height) - height) / 2 - 0.001) bitmap.drawColumn(textureX, of: wallTexture, at: wallStart, height: height) + // Draw switch + if let s = world.switch(at: tileX, tileY) { + let switchTexture = textures[s.animation.texture] + bitmap.drawColumn(textureX, of: switchTexture, at: wallStart, height: height) + } + // Draw floor and ceiling var floorTile: Tile! var floorTexture, ceilingTexture: Bitmap! diff --git a/Source/Engine/Switch.swift b/Source/Engine/Switch.swift new file mode 100644 index 0000000..88e4de4 --- /dev/null +++ b/Source/Engine/Switch.swift @@ -0,0 +1,61 @@ +// +// Switch.swift +// Engine +// +// Created by Nick Lockwood on 15/08/2019. +// Copyright © 2019 Nick Lockwood. All rights reserved. +// + +public enum SwitchState { + case off + case on +} + +public struct Switch { + public let position: Vector + public var state: SwitchState = .off + public var animation: Animation = .switchOff + + public init(position: Vector) { + self.position = position + } +} + +public extension Switch { + var rect: Rect { + return Rect( + min: position - Vector(x: 0.5, y: 0.5), + max: position + Vector(x: 0.5, y: 0.5) + ) + } + + mutating func update(in world: inout World) { + switch state { + case .off: + if world.player.rect.intersection(with: self.rect) != nil { + state = .on + animation = .switchFlip + } + case .on: + if animation.isCompleted { + animation = .switchOn + world.endLevel() + } + } + } +} + +public extension Animation { + static let switchOff = Animation(frames: [ + .switch1 + ], duration: 0) + static let switchFlip = Animation(frames: [ + .switch1, + .switch2, + .switch3, + .switch4 + ], duration: 0.4) + static let switchOn = Animation(frames: [ + .switch4 + ], duration: 0) +} diff --git a/Source/Engine/Textures.swift b/Source/Engine/Textures.swift index b74ffa6..ce4fd44 100644 --- a/Source/Engine/Textures.swift +++ b/Source/Engine/Textures.swift @@ -22,6 +22,8 @@ public enum Texture: String, CaseIterable { case monsterHurt, monsterDeath1, monsterDeath2, monsterDead case pistol case pistolFire1, pistolFire2, pistolFire3, pistolFire4 + case switch1, switch2, switch3, switch4 + case elevatorFloor, elevatorCeiling, elevatorSideWall, elevatorBackWall } public struct Textures { diff --git a/Source/Engine/Thing.swift b/Source/Engine/Thing.swift index 0a50c7a..63b197a 100644 --- a/Source/Engine/Thing.swift +++ b/Source/Engine/Thing.swift @@ -12,4 +12,5 @@ public enum Thing: Int, Decodable { case monster case door case pushwall + case `switch` } diff --git a/Source/Engine/Tile.swift b/Source/Engine/Tile.swift index 1e9b15b..23a04f2 100644 --- a/Source/Engine/Tile.swift +++ b/Source/Engine/Tile.swift @@ -12,14 +12,17 @@ public enum Tile: Int, Decodable { case crackWall case slimeWall case crackFloor + case elevatorFloor + case elevatorSideWall + case elevatorBackWall } public extension Tile { var isWall: Bool { switch self { - case .wall, .crackWall, .slimeWall: + case .wall, .crackWall, .slimeWall, .elevatorSideWall, .elevatorBackWall: return true - case .floor, .crackFloor: + case .floor, .crackFloor, .elevatorFloor: return false } } @@ -36,6 +39,12 @@ public extension Tile { return [.crackWall, .crackWall2] case .slimeWall: return [.slimeWall, .slimeWall2] + case .elevatorSideWall: + return [.elevatorSideWall, .elevatorSideWall] + case .elevatorBackWall: + return [.elevatorBackWall, .elevatorBackWall] + case .elevatorFloor: + return [.elevatorFloor, .elevatorCeiling] } } } diff --git a/Source/Engine/Tilemap.swift b/Source/Engine/Tilemap.swift index a474962..c50cf46 100644 --- a/Source/Engine/Tilemap.swift +++ b/Source/Engine/Tilemap.swift @@ -6,10 +6,24 @@ // Copyright © 2019 Nick Lockwood. All rights reserved. // -public struct Tilemap: Decodable { +public struct MapData: Decodable { + fileprivate let tiles: [Tile] + fileprivate let things: [Thing] + fileprivate let width: Int +} + +public struct Tilemap { private(set) var tiles: [Tile] public let things: [Thing] public let width: Int + public let index: Int + + public init(_ map: MapData, index: Int) { + self.tiles = map.tiles + self.things = map.things + self.width = map.width + self.index = index + } } public extension Tilemap { diff --git a/Source/Engine/World.swift b/Source/Engine/World.swift index ea0d91a..7e2639a 100644 --- a/Source/Engine/World.swift +++ b/Source/Engine/World.swift @@ -6,20 +6,28 @@ // Copyright © 2019 Nick Lockwood. All rights reserved. // +public enum WorldAction { + case loadLevel(Int) +} + public struct World { public private(set) var map: Tilemap public private(set) var doors: [Door] public private(set) var pushwalls: [Pushwall] + public private(set) var switches: [Switch] public private(set) var monsters: [Monster] public private(set) var player: Player! public private(set) var effects: [Effect] + public private(set) var isLevelEnded: Bool public init(map: Tilemap) { self.map = map self.doors = [] self.pushwalls = [] + self.switches = [] self.monsters = [] self.effects = [] + self.isLevelEnded = false reset() } } @@ -29,7 +37,7 @@ public extension World { return map.size } - mutating func update(timeStep: Double, input: Input) { + mutating func update(timeStep: Double, input: Input) -> WorldAction? { // Update effects effects = effects.compactMap { effect in guard effect.time < effect.duration else { @@ -40,6 +48,15 @@ public extension World { return effect } + // Check for level end + if isLevelEnded { + if effects.isEmpty { + effects.append(Effect(type: .fadeIn, color: .black, duration: 0.5)) + return .loadLevel(map.index + 1) + } + return nil + } + // Update player if player.isDead == false { var player = self.player! @@ -48,9 +65,10 @@ public extension World { player.position += player.velocity * timeStep self.player = player } else if effects.isEmpty { + player = nil reset() effects.append(Effect(type: .fadeIn, color: .red, duration: 0.5)) - return + return nil } // Update monsters @@ -78,6 +96,14 @@ public extension World { pushwalls[i] = pushwall } + // Update switches + for i in 0 ..< switches.count { + var s = switches[i] + s.animation.time += timeStep + s.update(in: &self) + switches[i] = s + } + // Handle collisions for i in 0 ..< monsters.count { var monster = monsters[i] @@ -103,6 +129,8 @@ public extension World { for i in 0 ..< monsters.count where monsters[i].isStuck(in: self) { hurtMonster(at: i, damage: 1) } + + return nil } var sprites: [Billboard] { @@ -141,9 +169,22 @@ public extension World { monsters[index] = monster } + mutating func endLevel() { + isLevelEnded = true + effects.append(Effect(type: .fadeOut, color: .black, duration: 2)) + } + + mutating func setLevel(_ map: Tilemap) { + let effects = self.effects + self = World(map: map) + self.effects = effects + } + mutating func reset() { self.monsters = [] self.doors = [] + self.switches = [] + self.isLevelEnded = false var pushwallCount = 0 for y in 0 ..< map.height { for x in 0 ..< map.width { @@ -174,6 +215,9 @@ public extension World { tile = map.closestFloorTile(to: x, y) ?? .wall } pushwalls.append(Pushwall(position: position, tile: tile)) + case .switch: + precondition(map[x, y].isWall, "Switch must be placed on a wall tile") + switches.append(Switch(position: position)) } } } @@ -219,4 +263,13 @@ public extension World { func isDoor(at x: Int, _ y: Int) -> Bool { return map.things[y * map.width + x] == .door } + + func `switch`(at x: Int, _ y: Int) -> Switch? { + guard map.things[y * map.width + x] == .switch else { + return nil + } + return switches.first(where: { + Int($0.position.x) == x && Int($0.position.y) == y + }) + } } diff --git a/Source/Rampage.xcodeproj/project.pbxproj b/Source/Rampage.xcodeproj/project.pbxproj index b36890a..a59ad8a 100644 --- a/Source/Rampage.xcodeproj/project.pbxproj +++ b/Source/Rampage.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 012A0CA222D7AD0A0068E8EF /* Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A0CA122D7AD0A0068E8EF /* Animation.swift */; }; 012DF10822E251CF00D52706 /* Effect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012DF10722E251CF00D52706 /* Effect.swift */; }; 01467C3E22E6F54600B5607D /* Easing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01467C3D22E6F54600B5607D /* Easing.swift */; }; + 015A23C9230586E3004CBB78 /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 015A23C8230586E3004CBB78 /* Switch.swift */; }; 016E41B3228E9A5B00ACF137 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016E41B2228E9A5B00ACF137 /* AppDelegate.swift */; }; 016E41B5228E9A5B00ACF137 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016E41B4228E9A5B00ACF137 /* ViewController.swift */; }; 016E41B8228E9A5B00ACF137 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 016E41B6228E9A5B00ACF137 /* Main.storyboard */; }; @@ -31,7 +32,7 @@ 01D09AFB22A485040052745A /* Player.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AFA22A485040052745A /* Player.swift */; }; 01D09AFD22A4873B0052745A /* Rect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AFC22A4873B0052745A /* Rect.swift */; }; 01D09AFF22A48E990052745A /* Tilemap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AFE22A48E990052745A /* Tilemap.swift */; }; - 01D09B0122A493A70052745A /* Map.json in Resources */ = {isa = PBXBuildFile; fileRef = 01D09B0022A493A70052745A /* Map.json */; }; + 01D09B0122A493A70052745A /* Levels.json in Resources */ = {isa = PBXBuildFile; fileRef = 01D09B0022A493A70052745A /* Levels.json */; }; 01D09B0322A4958E0052745A /* Input.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09B0222A4958E0052745A /* Input.swift */; }; 01D09B0522A5C9DB0052745A /* Ray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09B0422A5C9DB0052745A /* Ray.swift */; }; 01D09B0722A6E09B0052745A /* Rotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09B0622A6E09A0052745A /* Rotation.swift */; }; @@ -81,6 +82,7 @@ 012A0CA122D7AD0A0068E8EF /* Animation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Animation.swift; sourceTree = ""; }; 012DF10722E251CF00D52706 /* Effect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Effect.swift; sourceTree = ""; }; 01467C3D22E6F54600B5607D /* Easing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Easing.swift; sourceTree = ""; }; + 015A23C8230586E3004CBB78 /* Switch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Switch.swift; sourceTree = ""; }; 016E41AF228E9A5B00ACF137 /* Rampage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Rampage.app; sourceTree = BUILT_PRODUCTS_DIR; }; 016E41B2228E9A5B00ACF137 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 016E41B4228E9A5B00ACF137 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -99,7 +101,7 @@ 01D09AFA22A485040052745A /* Player.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Player.swift; sourceTree = ""; }; 01D09AFC22A4873B0052745A /* Rect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Rect.swift; sourceTree = ""; }; 01D09AFE22A48E990052745A /* Tilemap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tilemap.swift; sourceTree = ""; }; - 01D09B0022A493A70052745A /* Map.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = Map.json; sourceTree = ""; }; + 01D09B0022A493A70052745A /* Levels.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = Levels.json; sourceTree = ""; }; 01D09B0222A4958E0052745A /* Input.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Input.swift; sourceTree = ""; }; 01D09B0422A5C9DB0052745A /* Ray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ray.swift; sourceTree = ""; }; 01D09B0622A6E09A0052745A /* Rotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Rotation.swift; sourceTree = ""; }; @@ -164,7 +166,7 @@ 016E41B4228E9A5B00ACF137 /* ViewController.swift */, 01D09AF422A482450052745A /* UIImage+Bitmap.swift */, 016E41B6228E9A5B00ACF137 /* Main.storyboard */, - 01D09B0022A493A70052745A /* Map.json */, + 01D09B0022A493A70052745A /* Levels.json */, 016E41B9228E9A5E00ACF137 /* Assets.xcassets */, 016E41BB228E9A5E00ACF137 /* LaunchScreen.storyboard */, 016E41BE228E9A5E00ACF137 /* Info.plist */, @@ -191,6 +193,7 @@ 01D09AFC22A4873B0052745A /* Rect.swift */, 01ADC63B22B957FD00DC8AAD /* Renderer.swift */, 01D09B0622A6E09A0052745A /* Rotation.swift */, + 015A23C8230586E3004CBB78 /* Switch.swift */, 01D09B0A22A7F7570052745A /* Textures.swift */, 012A0C4C22C96E150068E8EF /* Tile.swift */, 01D09AFE22A48E990052745A /* Tilemap.swift */, @@ -329,7 +332,7 @@ files = ( 016E41BD228E9A5E00ACF137 /* LaunchScreen.storyboard in Resources */, 016E41BA228E9A5E00ACF137 /* Assets.xcassets in Resources */, - 01D09B0122A493A70052745A /* Map.json in Resources */, + 01D09B0122A493A70052745A /* Levels.json in Resources */, 016E41B8228E9A5B00ACF137 /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -368,6 +371,7 @@ 012DF10822E251CF00D52706 /* Effect.swift in Sources */, 012A0C6322CC200E0068E8EF /* Monster.swift in Sources */, 01D09B0B22A7F7570052745A /* Textures.swift in Sources */, + 015A23C9230586E3004CBB78 /* Switch.swift in Sources */, 01D09AFF22A48E990052745A /* Tilemap.swift in Sources */, 01D09AFD22A4873B0052745A /* Rect.swift in Sources */, 01ADC63C22B957FD00DC8AAD /* Renderer.swift in Sources */, diff --git a/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Rampage.xcscheme b/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Rampage.xcscheme index dcb99da..edd97b6 100644 --- a/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Rampage.xcscheme +++ b/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Rampage.xcscheme @@ -27,6 +27,15 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + @@ -39,17 +48,6 @@ - - - - - - - - Px#=Sf6CR5*=|lf4atFc5{mAVfh$L4m{;-XRlY1)7kRSRoUzgEIvZ1%)dL6e%gd z(b?FLSDkFXckh0Dxwq|y4Q3hvD9Xx-Lom}wQC1{JWS`)ZfmI+xkl7_c#yc`-7GF-r2;SC;q!DUg5?*JPe200000NkvXXu0mjfg7D zUR$gS@|!&;{)aCImRK%xzst91pAQkkN+YH{41xr0<2FX|{)4Z0RZ(WHkxrL)!`pU5 z6Aej>RwS8VE6VCxk)db@bI`-vBz4rIkDpXPVn@AehDMmVctF+<7~VSA=tKuQQ9V}I zZi3aq76J+82o%X~n%jk=j&yCYmu6iBBM9Gd)Z?JK;U;h?!@$&5N|6B}uq+K$Ov{4H zplrahZiv?^!HR8KcDV}1k1D*exNo<;*4URgIqHD(%+~ecaHtJeG|IMhSg+TmM!8%P zh*G|va#WPkd~u@S;XGm_wKa;d(UM zOK{33-1vm+oynEMkYvKMhZ%W@;})X{7$t3!Q({@Ez#4R`tuyt;-1wAOj=44COs+11 z(PeA@Y4yY;=0|R)gDVcx(Z{KncP0kAOTI12OA&aDPVu9+On%4Uya5kqTjs({7kvNo z==p^kzxXqMps@6n^XC5UlRHcAE`1I@bY2H9z7)!=p}bEn(w|q+k-S}jzu~=Y-h2EP D8?rR#s$KP?=NL8Y82d;mOylclA&A>dH3&n*X!%<{==Z zSQ6wH%mCDY7r1@#TLM&U=IP=XA~7{NL4mE~K!b*lgO3jrM}x|wh8Z(dHZgca1u;dk svP@7?;AK?rR#s$KP?=NL8Y82d;mOylclA&A>dH3&n*X!%<{==Z zSQ6wH%mCDY7r1@#TLM&U>FMGaA~7{NL4mE~K!b*l0}q#q0F#hIgAT(ZPcMbl2QD}T vI7snKU`=UokebhBVthn(fx{$?`AiIRB)JY6B}yIz8p7b|>gTe~DWM4ff5UWG literal 0 HcmV?d00001 diff --git a/Source/Rampage/Assets.xcassets/switch3.imageset/Contents.json b/Source/Rampage/Assets.xcassets/switch3.imageset/Contents.json new file mode 100644 index 0000000..fb7f1ef --- /dev/null +++ b/Source/Rampage/Assets.xcassets/switch3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "switch3.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/switch3.imageset/switch3.png b/Source/Rampage/Assets.xcassets/switch3.imageset/switch3.png new file mode 100644 index 0000000000000000000000000000000000000000..dd21889d57ee10b27e0d1735d40d33e33f5ce89b GIT binary patch literal 284 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1Ig?rR#s$KP?=NL8Y82d;mOylclA&A>dH3&n*X!%<{==Z zSQ6wH%mCDY7r1@#TLM&U<>}%WA~7{NL4mE~K!b*l0}q!<0k?-oN2jNk!s-bV7&;$b wY*JKUW;?;O#zCRkpLLexBcT8V&nfFVdQ&MBb@08q?#H2?qr literal 0 HcmV?d00001 diff --git a/Source/Rampage/Assets.xcassets/switch4.imageset/Contents.json b/Source/Rampage/Assets.xcassets/switch4.imageset/Contents.json new file mode 100644 index 0000000..8b12e2d --- /dev/null +++ b/Source/Rampage/Assets.xcassets/switch4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "switch4.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/switch4.imageset/switch4.png b/Source/Rampage/Assets.xcassets/switch4.imageset/switch4.png new file mode 100644 index 0000000000000000000000000000000000000000..0435c0a545f43cd4504dab04426870bb166036c4 GIT binary patch literal 290 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1Ig?rR#s$KP?=NL8Y82d;mOylclA&A>dH3&n*X!%<{==Z zSQ6wH%mCDY7r1@#TLM(<;OXKRA~7{NL4mE~K!b*l0}q!<0k?-oN2jNk!fFQ21sM}3 zFlZi1ZsXAwIHAC~p@@M|+fFnit;5@)Q6 Tilemap { - let jsonURL = Bundle.main.url(forResource: "Map", withExtension: "json")! +public func loadLevels() -> [Tilemap] { + let jsonURL = Bundle.main.url(forResource: "Levels", withExtension: "json")! let jsonData = try! Data(contentsOf: jsonURL) - return try! JSONDecoder().decode(Tilemap.self, from: jsonData) + let levels = try! JSONDecoder().decode([MapData].self, from: jsonData) + return levels.enumerated().map { Tilemap($0.element, index: $0.offset) } } public func loadTextures() -> Textures { @@ -30,7 +31,8 @@ class ViewController: UIViewController { private let panGesture = UIPanGestureRecognizer() private let tapGesture = UITapGestureRecognizer() private let textures = loadTextures() - private var world = World(map: loadMap()) + private let levels = loadLevels() + private lazy var world = World(map: levels[0]) private var lastFrameTime = CACurrentMediaTime() private var lastFiredTime = 0.0 @@ -81,7 +83,13 @@ class ViewController: UIViewController { ) let worldSteps = (timeStep / worldTimeStep).rounded(.up) for _ in 0 ..< Int(worldSteps) { - world.update(timeStep: timeStep / worldSteps, input: input) + if let action = world.update(timeStep: timeStep / worldSteps, input: input) { + switch action { + case .loadLevel(let index): + let index = index % levels.count + world.setLevel(levels[index]) + } + } } lastFrameTime = displayLink.timestamp diff --git a/Source/RampageTests/RampageTests.swift b/Source/RampageTests/RampageTests.swift index 7504500..84b7662 100644 --- a/Source/RampageTests/RampageTests.swift +++ b/Source/RampageTests/RampageTests.swift @@ -11,7 +11,7 @@ import Engine import Rampage class RampageTests: XCTestCase { - let world = World(map: loadMap()) + let world = World(map: loadLevels()[0]) let textures = loadTextures() func testRenderFrame() { From a72aab1b62b2610f6095e00e522241a1977891e1 Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Wed, 5 Feb 2020 09:10:36 +0000 Subject: [PATCH 03/10] Part 13 --- Source/Engine/Door.swift | 2 + Source/Engine/Monster.swift | 6 +- Source/Engine/Player.swift | 19 ++++++- Source/Engine/Pushwall.swift | 13 ++++- Source/Engine/Sounds.swift | 31 +++++++++++ Source/Engine/Switch.swift | 1 + Source/Engine/World.swift | 49 ++++++++++++++-- Source/Rampage.xcodeproj/project.pbxproj | 68 +++++++++++++++++++++++ Source/Rampage/SoundManager.swift | 60 ++++++++++++++++++++ Source/Rampage/Sounds/doorSlide.mp3 | Bin 0 -> 14016 bytes Source/Rampage/Sounds/monsterDeath.mp3 | Bin 0 -> 5880 bytes Source/Rampage/Sounds/monsterGroan.mp3 | Bin 0 -> 34203 bytes Source/Rampage/Sounds/monsterHit.mp3 | Bin 0 -> 9720 bytes Source/Rampage/Sounds/monsterSwipe.mp3 | Bin 0 -> 5004 bytes Source/Rampage/Sounds/pistolFire.mp3 | Bin 0 -> 13681 bytes Source/Rampage/Sounds/playerDeath.mp3 | Bin 0 -> 25939 bytes Source/Rampage/Sounds/playerWalk.mp3 | Bin 0 -> 38481 bytes Source/Rampage/Sounds/ricochet.mp3 | Bin 0 -> 8309 bytes Source/Rampage/Sounds/squelch.mp3 | Bin 0 -> 8712 bytes Source/Rampage/Sounds/switchFlip.mp3 | Bin 0 -> 3528 bytes Source/Rampage/Sounds/wallSlide.mp3 | Bin 0 -> 69985 bytes Source/Rampage/Sounds/wallThud.mp3 | Bin 0 -> 13398 bytes Source/Rampage/ViewController.swift | 33 +++++++++++ 23 files changed, 274 insertions(+), 8 deletions(-) create mode 100644 Source/Engine/Sounds.swift create mode 100644 Source/Rampage/SoundManager.swift create mode 100644 Source/Rampage/Sounds/doorSlide.mp3 create mode 100644 Source/Rampage/Sounds/monsterDeath.mp3 create mode 100644 Source/Rampage/Sounds/monsterGroan.mp3 create mode 100644 Source/Rampage/Sounds/monsterHit.mp3 create mode 100644 Source/Rampage/Sounds/monsterSwipe.mp3 create mode 100644 Source/Rampage/Sounds/pistolFire.mp3 create mode 100644 Source/Rampage/Sounds/playerDeath.mp3 create mode 100644 Source/Rampage/Sounds/playerWalk.mp3 create mode 100644 Source/Rampage/Sounds/ricochet.mp3 create mode 100644 Source/Rampage/Sounds/squelch.mp3 create mode 100644 Source/Rampage/Sounds/switchFlip.mp3 create mode 100644 Source/Rampage/Sounds/wallSlide.mp3 create mode 100644 Source/Rampage/Sounds/wallThud.mp3 diff --git a/Source/Engine/Door.swift b/Source/Engine/Door.swift index 2372e7f..d54a9da 100644 --- a/Source/Engine/Door.swift +++ b/Source/Engine/Door.swift @@ -72,6 +72,7 @@ public extension Door { case .closed: if world.player.intersection(with: self) != nil { state = .opening + world.playSound(.doorSlide, at: position) time = 0 } case .opening: @@ -82,6 +83,7 @@ public extension Door { case .open: if time >= closeDelay { state = .closing + world.playSound(.doorSlide, at: position) time = 0 } case .closing: diff --git a/Source/Engine/Monster.swift b/Source/Engine/Monster.swift index 1de258d..6201249 100644 --- a/Source/Engine/Monster.swift +++ b/Source/Engine/Monster.swift @@ -41,6 +41,7 @@ public extension Monster { if canSeePlayer(in: world) { state = .chasing animation = .monsterWalk + world.playSound(.monsterGroan, at: position) } case .chasing: guard canSeePlayer(in: world) else { @@ -67,11 +68,12 @@ public extension Monster { if animation.time - lastAttackTime >= attackCooldown { lastAttackTime = animation.time world.hurtPlayer(10) + world.playSound(.monsterSwipe, at: position) } case .hurt: if animation.isCompleted { - state = .idle - animation = .monsterIdle + state = .chasing + animation = .monsterWalk } case .dead: if animation.isCompleted { diff --git a/Source/Engine/Player.swift b/Source/Engine/Player.swift index e220676..3f62f43 100644 --- a/Source/Engine/Player.swift +++ b/Source/Engine/Player.swift @@ -22,12 +22,14 @@ public struct Player: Actor { public var state: PlayerState = .idle public var animation: Animation = .pistolIdle public let attackCooldown: Double = 0.25 + public let soundChannel: Int - public init(position: Vector) { + public init(position: Vector, soundChannel: Int) { self.position = position self.velocity = Vector(x: 0, y: 0) self.direction = Vector(x: 1, y: 0) self.health = 100 + self.soundChannel = soundChannel } } @@ -36,6 +38,10 @@ public extension Player { return health <= 0 } + var isMoving: Bool { + return velocity.x != 0 || velocity.y != 0 + } + var canFire: Bool { switch state { case .idle: @@ -46,14 +52,20 @@ public extension Player { } mutating func update(with input: Input, in world: inout World) { + let wasMoving = isMoving direction = direction.rotated(by: input.rotation) velocity = direction * input.speed * speed if input.isFiring, canFire { state = .firing animation = .pistolFire + world.playSound(.pistolFire, at: position) let ray = Ray(origin: position, direction: direction) if let index = world.pickMonster(ray) { world.hurtMonster(at: index, damage: 10) + world.playSound(.monsterHit, at: world.monsters[index].position) + } else { + let position = world.hitTest(ray) + world.playSound(.ricochet, at: position) } } switch state { @@ -65,6 +77,11 @@ public extension Player { animation = .pistolIdle } } + if isMoving, !wasMoving { + world.playSound(.playerWalk, at: position, in: soundChannel) + } else if !isMoving { + world.playSound(nil, at: position, in: soundChannel) + } } } diff --git a/Source/Engine/Pushwall.swift b/Source/Engine/Pushwall.swift index 2976520..0326f8c 100644 --- a/Source/Engine/Pushwall.swift +++ b/Source/Engine/Pushwall.swift @@ -12,11 +12,13 @@ public struct Pushwall: Actor { public var position: Vector public var velocity: Vector public let tile: Tile + public let soundChannel: Int - public init(position: Vector, tile: Tile) { + public init(position: Vector, tile: Tile, soundChannel: Int) { self.position = position self.velocity = Vector(x: 0, y: 0) self.tile = tile + self.soundChannel = soundChannel } } @@ -45,6 +47,7 @@ public extension Pushwall { } mutating func update(in world: inout World) { + let wasMoving = isMoving if isMoving == false, let intersection = world.player.intersection(with: self) { if abs(intersection.x) > abs(intersection.y) { velocity = Vector(x: intersection.x > 0 ? speed : -speed, y: 0) @@ -58,5 +61,13 @@ public extension Pushwall { position.x = position.x.rounded(.down) + 0.5 position.y = position.y.rounded(.down) + 0.5 } + if isMoving { + world.playSound(.wallSlide, at: position, in: soundChannel) + } else if !isMoving { + world.playSound(nil, at: position, in: soundChannel) + if wasMoving { + world.playSound(.wallThud, at: position) + } + } } } diff --git a/Source/Engine/Sounds.swift b/Source/Engine/Sounds.swift new file mode 100644 index 0000000..c264091 --- /dev/null +++ b/Source/Engine/Sounds.swift @@ -0,0 +1,31 @@ +// +// Sounds.swift +// Engine +// +// Created by Nick Lockwood on 11/11/2019. +// Copyright © 2019 Nick Lockwood. All rights reserved. +// + +public enum SoundName: String, CaseIterable { + case pistolFire + case ricochet + case monsterHit + case monsterGroan + case monsterDeath + case monsterSwipe + case doorSlide + case wallSlide + case wallThud + case switchFlip + case playerDeath + case playerWalk + case squelch +} + +public struct Sound { + public let name: SoundName? + public let channel: Int? + public let volume: Double + public let pan: Double + public let delay: Double +} diff --git a/Source/Engine/Switch.swift b/Source/Engine/Switch.swift index 88e4de4..fd98774 100644 --- a/Source/Engine/Switch.swift +++ b/Source/Engine/Switch.swift @@ -35,6 +35,7 @@ public extension Switch { if world.player.rect.intersection(with: self.rect) != nil { state = .on animation = .switchFlip + world.playSound(.switchFlip, at: position) } case .on: if animation.isCompleted { diff --git a/Source/Engine/World.swift b/Source/Engine/World.swift index 7e2639a..d69bdb0 100644 --- a/Source/Engine/World.swift +++ b/Source/Engine/World.swift @@ -8,6 +8,7 @@ public enum WorldAction { case loadLevel(Int) + case playSounds([Sound]) } public struct World { @@ -19,6 +20,7 @@ public struct World { public private(set) var player: Player! public private(set) var effects: [Effect] public private(set) var isLevelEnded: Bool + private var sounds: [Sound] = [] public init(map: Tilemap) { self.map = map @@ -130,7 +132,9 @@ public extension World { hurtMonster(at: i, damage: 1) } - return nil + // Play sounds + defer { sounds.removeAll() } + return .playSounds(sounds) } var sprites: [Billboard] { @@ -149,6 +153,10 @@ public extension World { effects.append(Effect(type: .fadeIn, color: color, duration: 0.2)) if player.isDead { effects.append(Effect(type: .fizzleOut, color: .red, duration: 2)) + playSound(.playerDeath, at: player.position) + if player.isStuck(in: self) { + playSound(.squelch, at: player.position) + } } } @@ -162,6 +170,10 @@ public extension World { if monster.isDead { monster.state = .dead monster.animation = .monsterDeath + playSound(.monsterDeath, at: monster.position) + if monster.isStuck(in: self) { + playSound(.squelch, at: monster.position) + } } else { monster.state = .hurt monster.animation = .monsterHurt @@ -169,6 +181,23 @@ public extension World { monsters[index] = monster } + mutating func playSound(_ name: SoundName?, at position: Vector, in channel: Int? = nil) { + let delta = position - player.position + let distance = delta.length + let dropOff = 0.5 + let volume = 1 / (distance * distance * dropOff + 1) + let delay = distance * 2 / 343 + let direction = distance > 0 ? delta / distance : player.direction + let pan = player.direction.orthogonal.dot(direction) + sounds.append(Sound( + name: name, + channel: channel, + volume: volume, + pan: pan, + delay: delay + )) + } + mutating func endLevel() { isLevelEnded = true effects.append(Effect(type: .fadeOut, color: .black, duration: 2)) @@ -186,6 +215,7 @@ public extension World { self.switches = [] self.isLevelEnded = false var pushwallCount = 0 + var soundChannel = 0 for y in 0 ..< map.height { for x in 0 ..< map.width { let position = Vector(x: Double(x) + 0.5, y: Double(y) + 0.5) @@ -194,7 +224,8 @@ public extension World { case .nothing: break case .player: - self.player = Player(position: position) + self.player = Player(position: position, soundChannel: soundChannel) + soundChannel += 1 case .monster: monsters.append(Monster(position: position)) case .door: @@ -205,7 +236,12 @@ public extension World { pushwallCount += 1 if pushwalls.count >= pushwallCount { let tile = pushwalls[pushwallCount - 1].tile - pushwalls[pushwallCount - 1] = Pushwall(position: position, tile: tile) + pushwalls[pushwallCount - 1] = Pushwall( + position: position, + tile: tile, + soundChannel: soundChannel + ) + soundChannel += 1 break } var tile = map[x, y] @@ -214,7 +250,12 @@ public extension World { } else { tile = map.closestFloorTile(to: x, y) ?? .wall } - pushwalls.append(Pushwall(position: position, tile: tile)) + pushwalls.append(Pushwall( + position: position, + tile: tile, + soundChannel: soundChannel + )) + soundChannel += 1 case .switch: precondition(map[x, y].isWall, "Switch must be placed on a wall tile") switches.append(Switch(position: position)) diff --git a/Source/Rampage.xcodeproj/project.pbxproj b/Source/Rampage.xcodeproj/project.pbxproj index a59ad8a..1fc0fcb 100644 --- a/Source/Rampage.xcodeproj/project.pbxproj +++ b/Source/Rampage.xcodeproj/project.pbxproj @@ -23,6 +23,21 @@ 016E41BD228E9A5E00ACF137 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 016E41BB228E9A5E00ACF137 /* LaunchScreen.storyboard */; }; 016E41D0228E9A8600ACF137 /* Engine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 016E41C9228E9A8600ACF137 /* Engine.framework */; }; 016E41D1228E9A8600ACF137 /* Engine.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 016E41C9228E9A8600ACF137 /* Engine.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 0199F56223E1A517003E3F08 /* monsterSwipe.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55523E1A517003E3F08 /* monsterSwipe.mp3 */; }; + 0199F56323E1A517003E3F08 /* pistolFire.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55623E1A517003E3F08 /* pistolFire.mp3 */; }; + 0199F56423E1A517003E3F08 /* wallSlide.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55723E1A517003E3F08 /* wallSlide.mp3 */; }; + 0199F56523E1A517003E3F08 /* doorSlide.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55823E1A517003E3F08 /* doorSlide.mp3 */; }; + 0199F56623E1A517003E3F08 /* playerWalk.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55923E1A517003E3F08 /* playerWalk.mp3 */; }; + 0199F56723E1A517003E3F08 /* monsterHit.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55A23E1A517003E3F08 /* monsterHit.mp3 */; }; + 0199F56823E1A517003E3F08 /* squelch.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55B23E1A517003E3F08 /* squelch.mp3 */; }; + 0199F56923E1A517003E3F08 /* ricochet.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55C23E1A517003E3F08 /* ricochet.mp3 */; }; + 0199F56A23E1A517003E3F08 /* monsterDeath.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55D23E1A517003E3F08 /* monsterDeath.mp3 */; }; + 0199F56B23E1A517003E3F08 /* playerDeath.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55E23E1A517003E3F08 /* playerDeath.mp3 */; }; + 0199F56C23E1A517003E3F08 /* monsterGroan.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55F23E1A517003E3F08 /* monsterGroan.mp3 */; }; + 0199F56D23E1A517003E3F08 /* switchFlip.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F56023E1A517003E3F08 /* switchFlip.mp3 */; }; + 0199F56E23E1A517003E3F08 /* wallThud.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F56123E1A517003E3F08 /* wallThud.mp3 */; }; + 0199F57023E1AFEA003E3F08 /* Sounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0199F56F23E1AFEA003E3F08 /* Sounds.swift */; }; + 0199F57423E242D4003E3F08 /* SoundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0199F57323E242D4003E3F08 /* SoundManager.swift */; }; 01ADC63C22B957FD00DC8AAD /* Renderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01ADC63B22B957FD00DC8AAD /* Renderer.swift */; }; 01ADC64022B9846B00DC8AAD /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01ADC63F22B9846B00DC8AAD /* World.swift */; }; 01D09AF122A481AB0052745A /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AF022A481AB0052745A /* Color.swift */; }; @@ -92,6 +107,21 @@ 016E41BE228E9A5E00ACF137 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 016E41C9228E9A8600ACF137 /* Engine.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Engine.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 016E41CC228E9A8600ACF137 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0199F55523E1A517003E3F08 /* monsterSwipe.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = monsterSwipe.mp3; sourceTree = ""; }; + 0199F55623E1A517003E3F08 /* pistolFire.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = pistolFire.mp3; sourceTree = ""; }; + 0199F55723E1A517003E3F08 /* wallSlide.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = wallSlide.mp3; sourceTree = ""; }; + 0199F55823E1A517003E3F08 /* doorSlide.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = doorSlide.mp3; sourceTree = ""; }; + 0199F55923E1A517003E3F08 /* playerWalk.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = playerWalk.mp3; sourceTree = ""; }; + 0199F55A23E1A517003E3F08 /* monsterHit.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = monsterHit.mp3; sourceTree = ""; }; + 0199F55B23E1A517003E3F08 /* squelch.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = squelch.mp3; sourceTree = ""; }; + 0199F55C23E1A517003E3F08 /* ricochet.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ricochet.mp3; sourceTree = ""; }; + 0199F55D23E1A517003E3F08 /* monsterDeath.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = monsterDeath.mp3; sourceTree = ""; }; + 0199F55E23E1A517003E3F08 /* playerDeath.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = playerDeath.mp3; sourceTree = ""; }; + 0199F55F23E1A517003E3F08 /* monsterGroan.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = monsterGroan.mp3; sourceTree = ""; }; + 0199F56023E1A517003E3F08 /* switchFlip.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = switchFlip.mp3; sourceTree = ""; }; + 0199F56123E1A517003E3F08 /* wallThud.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = wallThud.mp3; sourceTree = ""; }; + 0199F56F23E1AFEA003E3F08 /* Sounds.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sounds.swift; sourceTree = ""; }; + 0199F57323E242D4003E3F08 /* SoundManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoundManager.swift; sourceTree = ""; }; 01ADC63B22B957FD00DC8AAD /* Renderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Renderer.swift; sourceTree = ""; }; 01ADC63F22B9846B00DC8AAD /* World.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = ""; }; 01D09AF022A481AB0052745A /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; @@ -165,9 +195,11 @@ 016E41B2228E9A5B00ACF137 /* AppDelegate.swift */, 016E41B4228E9A5B00ACF137 /* ViewController.swift */, 01D09AF422A482450052745A /* UIImage+Bitmap.swift */, + 0199F57323E242D4003E3F08 /* SoundManager.swift */, 016E41B6228E9A5B00ACF137 /* Main.storyboard */, 01D09B0022A493A70052745A /* Levels.json */, 016E41B9228E9A5E00ACF137 /* Assets.xcassets */, + 0199F55423E1A517003E3F08 /* Sounds */, 016E41BB228E9A5E00ACF137 /* LaunchScreen.storyboard */, 016E41BE228E9A5E00ACF137 /* Info.plist */, ); @@ -195,6 +227,7 @@ 01D09B0622A6E09A0052745A /* Rotation.swift */, 015A23C8230586E3004CBB78 /* Switch.swift */, 01D09B0A22A7F7570052745A /* Textures.swift */, + 0199F56F23E1AFEA003E3F08 /* Sounds.swift */, 012A0C4C22C96E150068E8EF /* Tile.swift */, 01D09AFE22A48E990052745A /* Tilemap.swift */, 012A0C4E22C96E1F0068E8EF /* Thing.swift */, @@ -205,6 +238,26 @@ path = Engine; sourceTree = ""; }; + 0199F55423E1A517003E3F08 /* Sounds */ = { + isa = PBXGroup; + children = ( + 0199F55623E1A517003E3F08 /* pistolFire.mp3 */, + 0199F55F23E1A517003E3F08 /* monsterGroan.mp3 */, + 0199F55523E1A517003E3F08 /* monsterSwipe.mp3 */, + 0199F55A23E1A517003E3F08 /* monsterHit.mp3 */, + 0199F55D23E1A517003E3F08 /* monsterDeath.mp3 */, + 0199F55C23E1A517003E3F08 /* ricochet.mp3 */, + 0199F55923E1A517003E3F08 /* playerWalk.mp3 */, + 0199F55E23E1A517003E3F08 /* playerDeath.mp3 */, + 0199F55B23E1A517003E3F08 /* squelch.mp3 */, + 0199F55823E1A517003E3F08 /* doorSlide.mp3 */, + 0199F55723E1A517003E3F08 /* wallSlide.mp3 */, + 0199F56123E1A517003E3F08 /* wallThud.mp3 */, + 0199F56023E1A517003E3F08 /* switchFlip.mp3 */, + ); + path = Sounds; + sourceTree = ""; + }; 01D0F5D722F80E1600682CA1 /* RampageTests */ = { isa = PBXGroup; children = ( @@ -330,10 +383,23 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0199F56E23E1A517003E3F08 /* wallThud.mp3 in Resources */, + 0199F56623E1A517003E3F08 /* playerWalk.mp3 in Resources */, + 0199F56C23E1A517003E3F08 /* monsterGroan.mp3 in Resources */, + 0199F56523E1A517003E3F08 /* doorSlide.mp3 in Resources */, 016E41BD228E9A5E00ACF137 /* LaunchScreen.storyboard in Resources */, + 0199F56423E1A517003E3F08 /* wallSlide.mp3 in Resources */, + 0199F56323E1A517003E3F08 /* pistolFire.mp3 in Resources */, 016E41BA228E9A5E00ACF137 /* Assets.xcassets in Resources */, + 0199F56223E1A517003E3F08 /* monsterSwipe.mp3 in Resources */, 01D09B0122A493A70052745A /* Levels.json in Resources */, + 0199F56D23E1A517003E3F08 /* switchFlip.mp3 in Resources */, 016E41B8228E9A5B00ACF137 /* Main.storyboard in Resources */, + 0199F56A23E1A517003E3F08 /* monsterDeath.mp3 in Resources */, + 0199F56723E1A517003E3F08 /* monsterHit.mp3 in Resources */, + 0199F56823E1A517003E3F08 /* squelch.mp3 in Resources */, + 0199F56B23E1A517003E3F08 /* playerDeath.mp3 in Resources */, + 0199F56923E1A517003E3F08 /* ricochet.mp3 in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -359,6 +425,7 @@ buildActionMask = 2147483647; files = ( 01D09AF522A482450052745A /* UIImage+Bitmap.swift in Sources */, + 0199F57423E242D4003E3F08 /* SoundManager.swift in Sources */, 016E41B5228E9A5B00ACF137 /* ViewController.swift in Sources */, 016E41B3228E9A5B00ACF137 /* AppDelegate.swift in Sources */, ); @@ -375,6 +442,7 @@ 01D09AFF22A48E990052745A /* Tilemap.swift in Sources */, 01D09AFD22A4873B0052745A /* Rect.swift in Sources */, 01ADC63C22B957FD00DC8AAD /* Renderer.swift in Sources */, + 0199F57023E1AFEA003E3F08 /* Sounds.swift in Sources */, 012A0C9E22D47C220068E8EF /* Actor.swift in Sources */, 012A0C4F22C96E1F0068E8EF /* Thing.swift in Sources */, 01D09AF922A484B10052745A /* Vector.swift in Sources */, diff --git a/Source/Rampage/SoundManager.swift b/Source/Rampage/SoundManager.swift new file mode 100644 index 0000000..d2b7175 --- /dev/null +++ b/Source/Rampage/SoundManager.swift @@ -0,0 +1,60 @@ +// +// SoundManager.swift +// Rampage +// +// Created by Nick Lockwood on 11/11/2019. +// Copyright © 2019 Nick Lockwood. All rights reserved. +// + +import AVFoundation + +public class SoundManager: NSObject, AVAudioPlayerDelegate { + private var channels = [Int: (url: URL, player: AVAudioPlayer)]() + private var playing = Set() + + public static let shared = SoundManager() + + private override init() {} + + public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { + playing.remove(player) + } +} + +public extension SoundManager { + func activate() throws { + try AVAudioSession.sharedInstance().setActive(true) + } + + func preload(_ url: URL, channel: Int? = nil) throws -> AVAudioPlayer { + if let channel = channel, let (oldURL, oldSound) = channels[channel] { + if oldURL == url { + return oldSound + } + oldSound.stop() + } + return try AVAudioPlayer(contentsOf: url) + } + + func play(_ url: URL, channel: Int?, volume: Double, pan: Double) throws { + let player = try preload(url, channel: channel) + if let channel = channel { + channels[channel] = (url, player) + player.numberOfLoops = -1 + } + playing.insert(player) + player.delegate = self + player.volume = Float(volume) + player.pan = Float(pan) + player.play() + } + + func clearChannel(_ channel: Int) { + channels[channel]?.player.stop() + channels[channel] = nil + } + + func clearAll() { + channels.keys.forEach(clearChannel) + } +} diff --git a/Source/Rampage/Sounds/doorSlide.mp3 b/Source/Rampage/Sounds/doorSlide.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..901f50e8e88186bd8b18b70e7c6c7fe4c7e67e67 GIT binary patch literal 14016 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 literal 0 HcmV?d00001 diff --git a/Source/Rampage/Sounds/monsterDeath.mp3 b/Source/Rampage/Sounds/monsterDeath.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..57c95d1755de88f6c140730fe84c5dcd94d634c6 GIT binary patch literal 5880 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 literal 0 HcmV?d00001 diff --git a/Source/Rampage/Sounds/monsterGroan.mp3 b/Source/Rampage/Sounds/monsterGroan.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..c0f168597b28e0b9eb882c222b67f4730025685d GIT binary patch literal 34203 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 literal 0 HcmV?d00001 diff --git a/Source/Rampage/Sounds/monsterHit.mp3 b/Source/Rampage/Sounds/monsterHit.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..2e53bb394baf1e9c1292261d682eadb4d23013ca GIT binary patch literal 9720 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 AHvj+t literal 0 HcmV?d00001 diff --git a/Source/Rampage/Sounds/monsterSwipe.mp3 b/Source/Rampage/Sounds/monsterSwipe.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..3404c685a6b3a5aa593a17e8a3d78f51cc59067b GIT binary patch literal 5004 zcmdUzX*iVa+rY0`n_)0CG=#<&O9&xrGKLsqi5MZW?@Q?+DKhr46|%QccJU~AqRrN3 z3*kx0V~Ju!l1j%(>4=Y8Jia$o0lS(s`fz!o$IlS8(= zQJe&T$?+4>Cj?fZl@q8|^L3e&e!5=x@$#k^7s{EgFB*@tc=h z%=~6yi%-8<+v4YMpe=as60|b5KB%dxr+X3+`>%Z?BnrAc3&6^^>|iK63I03r|8;~m zC;EEFrBNrKUZI2B(l5w$N`Efy}PY>+=6N=X8^0$?^7#{T>GyjsnxI?kyBuV;uQ=b-O1OQ#>hDP*e$lDv3xV_}*K zgt;u%->(_ZrK!4$L65iDe0t=nJwkV}s6KFzvs<4EYZOg!%wAo&ez3Lcg7~or^vz-2 zYfFnauDB)btsZW$T34)`vsiV*cB;1(=$F7){z6^J+Tqf=w0GTbzSda?jP2ZVS8D+HW%_{4-K2>i&_*$x!A^l~)c`kaRIC(F38JbBAqN z)h9!JC&;f;^@DTZ+(JU-cV#XEL88zz{0+-v?;2a~&=%6tlE%o4DH0@&(W!_OZ`be8 z`8KcKR?EBwTv|lbrI!Y07SkRE-n6U40HlcepDTHuzAPjYMn~Id=|TDrdOQPp^c;f6=0G?8y(7I%-FKiPf@B}`Qzn6O)L24KUXY8 zc%;Qvo5jgQ7G-5Hg&lQ>Uw2+zCz;`7A&%cIfbJ8E5QDj#uub*oOteB=HVUu0!nJs9 z5J9**UCDrRpbZL}Nu57G_Z@4dbQUrq++^zsQH)gI+&xG5(d#*< z^%5rzpOvD&4Z}XPZP}sqqgn7B3cCv_E?_P{r`J`dE8Cri&!JtW;$`vKI{_=X1 zzEGh&{6tq5zw5fdZHkE}4VP{g@os&6!@W6vyu&qEPUp;?s^$FogtPGUA>U0CF^yNBlQ0UG_u#XQ%+9F@&P(hF8(wL0Ox$PPyzU9_K(s&`5doqAUQQh! zd@3=cF@4sW=q1lb7>%Tq@z-pxSX$eg7VVMYHuTE;+!b2cn2%as+5F_GK~~y=YqD=> zcwHUgO9X!0!a~HH##Su085-7^|URJJWW?p%C0_wtz7=&LAVd}I5y7QIq^N8 z0|qsCW0%?D#51RIv8*FcXx8qVS(J#Pyc^NKf`uhVe;kgc(je)Ovilx{c0nyg!4v6t z1cjv~r)d3hbt%4+tU}XI?KgrJrZ7(4NicPw#w*SbriP-{zP@d-fBoTq{NQabxYG#} zylr9%Y!``2-J^Xe%=qzEz9CugKm+%HClZ`}<#n|L8iQ}-OSl;&I8C;)o|2PxdT<0S zkys+6`qv;KQ`##snpw?F%f-ooc zXKv&jr9N2J%T`G_<^Z;J#uy;2&?xfPAD1?7V~7dN#6O|3=iYZu`cxE+6KjccTtc%0}ZX1}C=si3Me* zX7LaeMJWod;kyvxl$WJwXQ=&sVEx<5Qcr(+)|{|g=JVA9YYWScaW=!f!{q5=rNalJ z6H7;RRz8)6^=P8()Bq5|4avhFvue^ z&m$vvQHLfRIlhDWn`#Zy{7o$yzcgeDR)VzwiEjTWf=(-I#Dy-F9t#!=&~wdMwNM;i zI=R}vbmOf5hZ227jknjIINAi&l@vOyX_>uvs8auK*NfsGXRe-`e}Xy{aKen(w{cu5 z=%4evWt%11T6ohMQ0Ebf6@s z)?8U>tA4j*;64U!!fX-F{)MCFa`0motve&$lPsrx$*XF$r$y^}Pkj5bHwk5*uay4a z+osZ(=a|g|XStdnvLGD)a;cN!pV}uxD%}Rab`(5S!S2vomqxR&Yl&22Ty& zP`x9AjXlZkcO*_qYn_sV_iAO2Zp?*i>zbcRZ--sGb{0{x)Ek$|7i~Y=6wFsv7#Z^EP>^eAd{NmjavBT* zPb8L25hKg6XFAh{A(Z3JZyI{WRa`T|;KMj*v-PJm^F~Nx?EuerKROYQ$;LsWKvAGz zJPc>n{ka`m%dD;;xM;SrrUy5QQwof!e?jgOn1 z&lTA$;VD>E3)QnyF)yyo{HQ+Cps$~oTSi~=nm?S}8_fJW*{HQbQ1>G4MEa?>nG2tw zpR*cy^xe^GR;D1@>gjm4*C}&M@{p3b*vMl84$?Dz(M1}Lxu7y&udK>9S90C|14B#4 zzJj8BG2Ox_>3Xw!@!S4DQKMB(PUF7lVR^yR$%d$^a|W?vEC7U&76WL$KGF1vy+e2N z7z*4A_sya4_mdFRZ0Jo_LSaURw(1KG;O3fd_r8;u*R0+MqR@_EuLwnMeQyIYRO=$f z_Tpy`eXP1@QQEzuS}htEQqk zQxw^Z5+d9Z>+mC3Av3si028W}gPDC1f0K_sGkN@`0l zj3_@}gE)voAyQpkj#5}vuX&xev#23_%2@NC-SMt7u)%&M=dXL_9^fchGakxLFUSIU z`BLA~FaxRFxz*22OLEY+jscsh?E@|b=JpaGmT zWn3B|APV|>1o+VTub_~I#PlD2SSmV~zqPcGJAbZ?8=xOA@)Yc_6}F5humIFjW1`^U z&qsRx&d)6@arWQ6b+|mGrpD#h4d_&$S_6ShO8AY-(-)Rbj^zCKR3G@H>V+OPdr~+j?MN=WQanESTLdO}jEcpB$& z*xRX(`O#kdwmzS_t?U``V^2aOL+hql)n1tR0svRxcxtu=a@Tt3rytieWk_PNMZLkYB?#v9k%J?*($=;J{`;f%`8Uu^)B_(pG^cs zh5DaG7bF)oIehtfEV50oXER29A9FkR3VBxMwRnATw7F8#3HM9@r1zJiFjp8i@w#GH zHB;Ore4xP@M1lZ5s(8uNjdOp0Q={$BkmeH6=|}#$YKoJ zdfBG&^VU8Zn<%V|u^(C>){0QinC$n4!A=NRZevqP^!N|uYvoAAic6mpNBwj^N$eBK zdVGYOzQl(HKwzGO6gO=tIQz3%NcLAY<^(AA6(J&#{sK4@EJcus@yYfTl&bNM%ZGjj z9pE)AMDsCmgbby;p&fuJXoC=dNmM_E80c6~$Ka^Zr{&l%;}CvRR%Sa%BfesAI}vF$ z3s2@ZS3vRl<4Y_L#N6^G2{^$zl3`t^l(3up0Pukn{Q2wA`;6vNrC(x5*+}<*+2rBI zN4omFxDx^d6Y)_9M!NzXw_Rq;XMcqP3c0Lg0V_6%lnwY|{h4 zt_f1M3%9Dqjls{=d0lwTt_31=RZHFkMZmP8)k9UlW&~v*EM+LXr~9{lfeR~xpgaIZ z#NbJUXrwG}YqE8~0!RR8u>e2PV{#Ul_7vnt-0(lBC ZJa6-q{%`&NRmp!4a4_Wj+h+N$lUTi3tS{dJ!{=k%?s0TaUn?u7-RqNDt8Pt6JdhED>#99Y$S zUA-I}eObi>B?KjayW5Puf4Bd4F?IEF{&$7+-zEzH;-df|IXNREJ0G8fgq)m`nwplD zfvKsrwS$A3w|785NC+}IIx#UNBO@=bu&}hUvaYVNt*x`Ox3_<2XmoU9VtQ_FX=!DB z{o}{2tEhzTqx6{KG4+u){5haV`UE_u90XPliU`yf zY6AnX0J^6%c3*%BWP~y|r=ZN+R)(skR~d9rj1yiYoy`#$z8`)Tv0h`p1`3MR7XbjN zinc8vkZ=@bv>}E>jx4k}0VBnmpUh4XC=sp1o6U8Mj2r}14Pf@pJCQf1~{D~v)4rajmjb9B(TUO{AB^6qv*W)a|=Xngp$R5$?`>(P(3{u{w%v)9Sn1 zs6Jjyx}-?AuvjD}RU^N4Y*WyZ$85onPb{sdM5n|f6{xSia_DZu#D__V=^~ijTLnq* z^9v%Wqe=zY+`!j~ER5}@hSmE{RXeU{w#q}+B3>Ml>@}9AZreEz!wyEKnyQsh2hsiy z^)q`i%~$>`h`(LfcMc45zRi>JA;%+kpLGud0CnHyjujculvnYX;sen+)++aJyWjiX8D-ax#ns~4;r%Rn4xU=Y4dSnvswnXd>P&MGQ2q1~Y-`z*4Dx&d(}D?@HIWr1Q`JF*eu{^kAYRI_1M>(W~GhNyHwq>r)FqZ6M+}KsY9? zBv)rp>zj9(dR(`+7Mwg&7B8+$xx}JMEj@}oU@h@#mGkBJ(oZr=6g=GbT9}Die_*Q5 z|4wvbq_MX+j5k)e`hbmehW3diK^=IL}xwf)K++}z<-0;8xhcO1f zA+?E)k!9)QJ$-%bU%Zyu9zz~Z$Us0A-_%n~v zslMn`xnERz`9;l=s0!AQN3}aqy^6k5Q;;ov&5+$Ttf54dRl|-hEA6uw#%j20@oe>& zO`{z+^`p}%`7r$S!cgefhtt+=rE4KQKYjd`ECnTVIVQ%m`pOsn-iY-hAU74V`@4?N zX=KPZC-ECg*!a1b?;FaD$$ZPEFkRAgCf2!G51VJw+uL;Ki!QU~ooUzgw&9-m+S!eE z9p}I>zDFC2f=w`UG72H|0!zoIZ_7BrwTuA3O3#sZWEM-5tTG3W)}6B&V-u$6&}pUs z*zLUU$q18P+PP>N;K9Ltlr5(@<=7EEh@wXoSd#`e_v0NiCVg0>sYefLK%kMAIE$;1 znX8-q2+Ac!u1Q|%#Wp76&>Fa@cF``Vh?M2+syAxx!ky4nE$P@lwGJkT+#mChGbc@S z4;NmE6A>jcZm@haS0T%lSsnOFXSou4xd6;t$6M}wb+-5OlV&DNhmD0H=M{}d>oxql z`Y@bAuV(N-lV31wWFUf%@ohhAgM#9g}Wrg&zmRcDXL!qwyq zfwtyXZZ)EcWTVSdNxH2S2Ihw|5|`jnZaS{shx1JQ(kEld$s;iAz3)>q2{qfyCiTg~ zqi)?I^(?lYJ7gAd!8KZ_ANFfaDtT|kl}h+xvx@}tW1`f+@dJz zx{>!Fl1O_Z9G7oC>U5bq9804pdQz8+vwK1OBcI8l&{ef#4WZmAH?Q_bu#eoAyatyX z^g{u*ZYYy#T9YLMDaSYTMmsT$pa3&nqMa;4CoaDm{*W&>_CTL0{AUzfc$G^(rPBL; z3XYr!PAPnNywmgXC<;??>(I9t=kd0sxJnjzmp1YheYk;#e5SJJzy6ioyd}stbe*3D0gh4d>Zr=jYNEOQa_YVUamr)y z;^CG62WpXO(-qAS!Vq_#tfKO-#QptD6{@0w^U>yXwU0=z(w}u2J|x0v@qA59z9RNu zu2)XhLFcl)vDZXGDNI(eDSYdaafumaDErKqg7Ev0x|`g&@L6Dtu7R(TOei`?22tLT zV;}rLw~oO#Z4RPi8}+Q0Y@OYTc)ZHBMiiZ7V|#iVz`ZqrMTwugvE0O2#e~`VC_Z5X(qxgyHZg z1lHq?2Wb+|b6Rr2IwY;j#Y>cR>|hCxGD^$1OdbfmRf<*oXjyLO;P`y`Wq$3W(jG@6 zn2+U9m(puDZ-lz2v=9rJ>$TiFA|gw@=Rsx$?)b(0)wv;0s4-$l!r$62*S5i1$Hp|) zSYDdoRvg7o?=Vog(sWc^M)T=<`5Z4}Rj4dDjx^0J*HEhSvg@mMDja=aA+AlT0H>8z z0{~%4VNB>POldzm2t?<^)$&;_Vv)ioe#Id*SX~(7C=myr&Sf`HO9BvDx3qA_7+air z%&k0JIuPCqLH?+_HTzDHc#dF^Z6#&;#H<8 z|Ni+W9*@&{^YNKw_}#^^O+9F z>-Edh&7yZ~wMTf8J#y5k4fDU=yDE6C+mQLdegET*0wXoz=MP)zw%ExppQ*e62oL_&c?=X`F30M z6W0pev|3fVHqn!1w`&?5J&)w0Bhxr7%I4kHVlz#t9q(2Y2aS0~vKM^v@GpvjnOy6f ze@gCR!8cF^MFQJR<)lADP4DpJZnN~nPVEvv^?E}fQ+LJ83THutE*Yw7;i6)S z&S0aQoF0y@)Z-|=yLIRziy$du`^V2n{CD1({Hr{A@Np%6*_6g+9S8ljZ>iG?LvK9s zgzF#1Y(bqDRC7)Rt3>J-GQ>Q7ymEgcr7RYVBwJhI!%Yf-ufJ9vf4^hRs^Veo2~qm# zsPcz5`q3`cnp64<8&-hA_ghehqj{QqGW+j`dMce@O>X^~$+vH^m#lLl8pNX1?L=Wn z*@bZ;-O>IQy9NTL;Khq?Zbn4G>`5Ybn|vX*J(RMHcVXJilWN+TbDC!BljSD?SNPh# zR31E1UtYaDKCq}Teg9+KW5Dp~m&7Nl<3qK?qt2uX;+7jFP=L(vU8K>%)qOl*g_E&4 zn;)Pj#<7LmiLP>eB--E=45~6kiW+g~pMAvK8jKh;2v*5Fs-Rp)0{-qNwLhW}2OMmv zhrJR`b0aj<6APmr!tjYl`AgBlOy#c}{`lWAqL4H3adU%V;(FHg44|^y;Px0b&3{dC!py42u1R+;T&W7z zgUtzxIRJ4-Y;3B!>E!KI`UEllnKsvU^LCuM@kiGavTb-6#BLdg_=(C9iTNL4YeIq# z&h53tUw#W<@!tRJdGryuWKy2_o=AA5$`uUCDMl$*0o*%qOvM&J$=f)Yhsz5c-clu5uc_C`8k{kBd53rM{ z2@beY1sEoaO)D$I8B~oq9nOMOIs=jr8P_pHw$U=qtmF-Zqh@<^>*+Fz`@eXT-wy4U z#=obV8#NZ%|7uWpIYKWJyLOh48;o*GlAko@9PR6dCnX{();S-B@j)7b9eambz1|?I zte}8KNX$to)#I4T)HrXw0aNKI3>~FGVi_P#fY2EI0Lc`9HNo}VoU4xIFZz7ct^htf zK4^ttg$TAj!C>IlfK|_9N^SF~s#gmSWLXP#>AGu3q^C(UxLi3=Q$g%jUdja1O{$Hp zec!cK7cJ@>NVvqNt+id?qjf6nyuK_z1hp{w%^gwfe_7CaIwDSQZ^{N>Anwt^FLug4@$6{Yo`R=8@a}G@W%p)Q?W5kjF2(NM$n3B-@9FC|}JzFde>t zROpjLd{2A(zTd^BRYe$_Npk3$a*fAW!j~LBl6u%Y$YG|4%^{-b7;0<_c8aYnio)in zCfh1gFLq@*LDjlRw2Cm;Ig3#*d z{Q3O&XwOsOCdu>qF6tFY)ThAb^VWns0ASfmjr#3bFHww#5s9SZC^-dr{}uIfVjaUn zo3OFW>FwLlV{>sGD$!Nm#~Tf1YLl&&hw#L>Nkcc)R)PV% zajq+a3{_U}wTk;1pWp>yuQp%M?W1Mm1t5u(LCoG4ZH`}3$1jpziJ9>) zPHf>LLs@eJPdR5~Ih4KfJ8zm0?E`Rp^xSTrfoPJV>5;1jg==fe+js>6k%8{e!~d(kU|=&0!8NaO9%-42*XY zElar~UV)XI9t+-Z8OZ$J2J1_^uZX(jsqS_XmfBfjY? zx%OY3Y;(K5zjz6Lbo?tb6mn2SW(L9 zOm88ieoQc5`O?;21KpcWOP6|7tU)eb>>!{+qO8eB;WhMH!@|H<5m!h`q1eSu=I!(y zn?+NZE9J&l9@&Qi|7zPCg?bz(8br0CvNF6qeCF%$!fc+9F2ehGBgRaPwuN~J&yPQ- z{l_QUQN>fbuvoJ~g|Fve1wwWB3__4ACnvdfHdLr2Xv9t_s2c8Zw9S?Pp`*8nATY37 z!ANI7c@C6{zp@Mn^KE!d@&g&N+Lw@3mxE}v=60GIzHQe@pLlk&bo>&w`Ltb?tLMcd zNsd?IKjM#ZE=00px-TNLpYqkTG5Hl$jImSf39qC&JTTGk7~4Kts>LzHw__dUF_ot$ zwYi9I;3p)AE0XaE>g$I`(G@Zk>`C_@8O~Nl*WtOPx1emlir`Zz!eMSQH59q_hn#30 z=Bent+Ktc3>$GetxJ%%blL~k0U`;w-<2E(A-;#NoGZyZ|yh*tFvPLl50O?EsWB+%O zpRcL1nbTxNO)%-|e~ypQ@~R%fQ;N3`NKy=^&4A9coF3qc6Bn3c6DCPBR4JqEbL$D_ z6nqJ8Gd8`b(9Te@#{z4Z6SRP+iR|#-glIgwc}IEJJf}bCCTCCg#Izua>vTlJp2Dc?f&1dhL9gHY3q zCqX3S=y6Oqh%%PXb>^iP>C$O<$;5IZVYOjvWO6H6_)oDWFdX1G9~-(B0UqsdHwH3c z54Ega8&d`0Ka%tRmHs%~KwOy70GH9s4#lE`L0p#5A1qY%(Y6r4?Jkb-T;?Zl4(jChk~V zni9!?l6gr;;X)xTcWz5Sah0c=wp3zgSj$Q1h|1WU%I1p`WBZf6kWTG5+o!*sezu(% zy6-!$8%L*-83I`QR}IE?UCiGnsEq=?$JSVpZf5PC+0@m__)BqHb?T1Y#{)TL>W!4F z2l|8J*Rlic?A&0J#jvXG%Pa5S<^qg~vSi^h%a}Vsb7OewDLIN9VD+(QXXz=PIvPJG zbHZee%YU;eF6W{%LJ{2Y7NH~9Vp{XuyybAW5zz;mc4}tzZqpELjbDR{=3iGfz8_Tn zMX^Vmi_LP$I$leMQ_z;Qv32!7oW&CHBD9GHGH}XBTU<65!Hs|QsZvPDzb)$OV(q9j zMzIZ#$NS)o@a8Ny*U}tTwo9AF@b24Jm1l?uoID(hB_ST$#6tCTy;3eet?H3k&Ic z;O`no#vM4&~p2j_SPd}3wKFH(g+^29XIJ6_*Ca6#$eWzdDYSnv0A=j@dc9fP; zZjf+hl$968(-Nm`qCN!9fAdPiir36I=E-PFV^h!=lwE3zTjFneSy4KEN$NBu>s9CC zvuQ`S#`g}wVJ-C#Yi@`8y_4E|od;AimK*A!?c-n_J(}}+7r!3#D zMDr$Rz9sK5e9w5wg|&mu%kpiKZ~03t<8J5Dgms>99dN6r!#<~^KgnUeex6RT1Yo@0 zLUpV+ahQTY1mhQ#UF``^*eOl@Qqsx40~8Unkt*-;BBCjv$ejM0CY2x?3zqx-LXSxr zEhg>JIHPd_uF#Ik3r@y5WY!xqYA<8sI^M8LZ>=RvUR!w0juNbvY?>^5JL36cg0CUP zcjC`cLXcO4z*piWI_0J&<7@iy;Wr!e$Jbv}f`$b~#CcpxkpwTksYwoD?pSl;1nT8S z7{Pn0mmReg%#Zrg4)dEb9e#@yQSmC(<$*a>A1EQB2TcdpMF)DeWoy=$;8_QrR!+KM zr^^!opBAsP3=^`&4_=6X3EzlQUJ`fFc}9v=FHa5m+Q-tBJlNm#_Yo~+K2N(I_pxs9 zh*+WkD9*MDy(Ts`Gqrb(Mbf#Y)ik3%j^Eo$h)Ht8C+z{A!Cx(LCXOL7vl)iwiHQ}Z z`g~@u!T|6fs*UVCFvwhnYdKDu)p(%<)Qek^RFYaU*f1q!Su3VANxrmKWB!QI=uHCC zQkf5DEbN$5-Q8@`S?1dW_n#vTv4MWG=Dp`jXHqj|eP>?j7A^qcyNK)o|1Zy3Ejvoe zwH@~_rN;Wc+WWk&R*jn2^_UlW5Fb8@GES~D11@tU?2hr*&W%D=bh0}Ca#0|N$c~TS z$ChHnVdtL7$_V!}Hhs(3Ly2c1|9os!M&kkK;x~ zX35hf7F@}0Mbor07?TZ~)q0Tsh0`mOX4u}%vz{*CGt=+@C*GUOU2M_SobNt{@)?JP zUFhUJW#-;n`%YR#Q5?WsvplM^U~X2P* zBGkr5jzxK=u`!>OIYXYrB%Vw8)L=Vxg2XdNoz_RdLCi9%OzcUDkG}6~r_hVs!#5Ge zl6qZ#7B<0E>Z?gTiCv+5k7ek4c%N*aZe0Y|Z&AE@?oyWJ2)&{okEeD)FvZd~O4#sUl47(FQ@)-(`FF2f(bT_=vCzP7c2=w)@Ku!9P6OFCdOd3{( zC1S0A%oL9-hVCEJ6y7Y?oE{QObq7#ox@ZHmLVXEFhg;lgk}=Vm_}osAsQC}arvhUl zNqDA|TE~ui_wi4TNxV%e{%^elI^Zf#ib`%QZTzYJ153ucxy=44YZU{q?VOT^NS16X z)_Z zdK5dXxK@ak9B~cQN$8(wZZ2y@WU@vv9M1mM>(LeEd+fCLkk=uosg>))=3Awox`O5O zfy~4$YK29I1z)o4cU3k)Ef&OV0H$DHoe<@TGBF->AR1ZZH;ONGZ!ZBRi3+u_2iSM4 znzXU^p}3 z2)Dk2ZoZqu(&iLJao&jXsUj$tz&_D`MV3YtS{-2mi5c5Zs9BTfZFV^NFkJWtF#5Db zIm5K}0cgV81_^3yYwd|9)wOn35oqpRQpoY2wGmda>$hO%!r7lL^~%c? z;38DmoxrY9hu$zGc zo;;JV{l)lBLeRPThT*X2weRF)G!=oefu8oxVQGB3;wZfiA;~Kqi$``<7m}JU1!OjQ zN#xl5(*Y%s*PhAURwCwrTLxZZtD^%+RaKCFz+%07ZPfWd-5$F90bM%`f5 z4GB=cSRttJ*=BQ^7iI#2v>pt((Kw^9t`f(x{Nlbvj3%-C(3`BG(VCS*)Yi}J^tN!402*9hD7_KL`_ zT_;Bt`e=P(ohfcjV#)-W{IFEV*uTXPB>s#7f^q14!>z2XUhZD-#O-KMdEwr2gz!C+ zPNy0Dxued+#GibF>6fq87$UtEjNYgkqCPY9b+d#|wkMrYB7ihhzIui!ZbH$z#6jjPXr(&Ub&buHRQWXY5SN|3$c^HLPD8W~pR9GH2%3or#>%oYi4{!aW^MF)PvA6H zjyB5CX3zLp2Mu)|U?Ws7C7Y+5QRV#FtQItK(4m4`SiAPw1{l}=XcQGmVS*9Ii`w2d z#a6?9?~xv>s>Rz$=LA&8?RXT$JLZs3#>?Z(qZSgE`S-w_iT&Pv9^{Ak4Xy|F{-v0f zR;t6VaLZoZa&kpR?+h@JDY`jOhJHZ;obOs$eEW3b)B`!fD{*ke^qihq)1)a!gJy+{ zqSEG$SX)CPTkicu8BU1&Abik-+h39GpdFj*{d_H!zc`cam{rfvfP~(+UNVM$ULhzW zVob9`+P?+S_qmhfN_L-_{p**1-cUiHj?rVVVP+h2M(k^hu@y8vr@>hB%EON8%Pe{yp=rc=p%cOf zxs;&5Ovl6T^s_&Uu)TLeO}7U<9t$LP@eorh|D3X7A|!1OV2I%6(tjG(>C(NR!_}}9 z{S3lROI?z(tohSt!%&+^mU~P;-QY@0Bbt$g-N02e8_>spv_6Lf=zAC0PDPgD$bVaA zs6?gLllW16RAn4;(qieH2sZ=|adP+u!?|F&2wj{Vt>~PBN0<5W7&Xg-?0`OoGfn-+ zmN6Bnd6gXDg)NHr-0?R3)e~|!i9OEo@9r4#qCm7SS|3g-uS#Me!^I1uLt(=?gj>gw zFH2jm9n6rE4JI|Io?c_#XyblX=et{2A5A!+!=B(lP5?+NYj5K_Jw%P*rjlCoV?i{# zi+#5I9T?jr`1(ulQx@#368i9cZ}b8JpTpu}*25^I;qDia4Mz3}mh&9L+C058_2oAb z9^TpO@I|Q9%WNKD?|2haRYeM#yaqiszCG5BI>;hgX5tlA=bIaR@alBfOzY%jMT?w> z{}yXa5)r2_F4=RwcYhO(QviVe#rJ5`drquKy*uOV|A;HRa6;iKAyv7da5%N&##OFq zfX%**P`VO$G}^pp4Db2M?|9^ze1do!6NBEZW{rLcPL%B^t8D`Uo%$P3x!${ar4Mo#0t3H*u# z$@~Rmv*xDlcFJgI*gNid#slGFg0|f`7m5Q$F(m%GsvkFW2oYd@g)w~uL4ym zW~Y@vlQ#xDKu?2)xTd51Q$jCd$Kvs_5V`nb)%^DAGwg~8U(dXkGlW_d(0Ob#-+0z1 z68TJ)58s-foBY|ZTLM^tOb;kto4eowWVUUG?$MeF>Aju=AiTa;0%|#aY*5Owf8U`p z=#~;^S!9pVG>q)&Dd^=~p!yLo3-)y!;iK_IRP^IAyq?Hhd`|IgBTa8w*kw5I#WC9i z1qSEi*W9MUQ8%iOGWICuMAf>j!i($^GbmfhE%Sm-agi>tRF6|NR;JX!DGlCMW)-xb zZN^p~BJtFI^LPaZ`6@apwHQ8U{AmBMi>3%*rS|}E)ZWB-)WotkRx;n+iud6m@tFSU zi5{_KCF8Wb$_*8!s!EHmZvs82BvQhrZqMZ)d-=&$*EHci78>gv1Ye$)nadR&0`oKIBHzXV*b- znJ;_DfM04V`e-c#^P^)jL<3KaD5v^r-h30Su)Lyqx96?Lj4} z(C)&?D56IRcYF+EWd*BYNC4}>8WQUSZ(J(=ND3F;O7z)Vya=5_>dG;NowE;5;VmmN z%Q%ys4muXASh0|+#-$m4aC!qbU!B;mcVG~M* zS5;?&*O6&@^sgQQ>%#%?Q$FyiE0t9TZ2%Dd67k*Z^*ap8%}!-^b>c=#6YNqDeUDu&QibMq(oP zd-2c>-g_?7_cdDjcXUrR#Fm1SEH)ibfwuk+a+rzulQD0$o_?i%dJbTVI{?SU^oWPK zStGvNWUgf({nJYk5&iEU)Zq2Ut~5i-xzyX0Ht`P!b6&j=K&izQ6yqe|%%;X!7)>*k zx&15eK>@oT_xfN);6w#OwuJi+*Ga*s?{udqbO?#^xx7E&ha9@iV3AiEChGFryBYKQ zJK(%GzW9&VNU!=;qi8qkNRfk#9rjF>f~>W}YDG7RQ{5UaYq8qw`|wO@ z+(Sa-O=J-$SE><5|F2w4Imm=P3p`9zQ!KCM%h6RD6o0T%JBX8{;|{ zahYZ8py5UpYKlqi-pr}3qacflo7&`3TsM*?)7Z=b2%vZXg(Al(9xJ4s`<@4Uq{?qU zZYa91vXyA}P?8Q&)NGa)EU>lm1lA8$wwpJopsBQ?UQ&3n%jE9*6ToQBdy|2uDvLiu z22-%Y?#E14(NLgZXFAnhKx7&zpA=`@KGj~NVdocVp9RP{<)Hv>(Gq6L77Hb&?JbwW zwJE2nzW#l?L=mdqPdHS;Baq%C2Ny{?P6vYr>JZC}!HnTw(xq>wxdGR70hoHP5VSYS z+zNWBpP~oDW*bF0_(K&6ST8n^aB-dAWPTC&(aV$s=9u#eBpCAyE4$FW1g&*L>b)kxO(t9h zF9qjE^gg23YV9#AxTrZs)<69o)qsaZpZ=vX2*~2Bl{|GG}j5>iF}0y97v84_gj&6L(QX0=N~N!#T|L z`9fldAiob=eQrswpZ8r*zYz_1%1ze^1B%-Nq)_lov|=uDa5=K+4Jbwc_RZv`D-X0% zqp?Y0hGPzb8p(Dk2vUo72VQ`z#!I^h0G2L0SP*I1@;YFsgBk^|OES&fEma>eprUTX ziAIk=S_vKeGjh5mrc31Q3|fijY6b*`7=!{N)FpR6xH0@r!pp_yQ^&^eRxyduP(FP* zl+L;Hjc1rR_Ky-pfXj*1(W!pv+A%TBdWa_y0OXGNfTMf6aF9c_`W(fatTx32yD8*o z>~9?u>bWwV_z7|5%()8=;gC~*yqHxbfUdu%C=?FV|8pAT%J>30x%jMCma z?@MhA@e=E~%fRc{tN}z8tHxVek99-lBcZQWxrLM;zy zHNvreEJ%rSvV#A{zsmyv00j@8c$|BD9OPh!3R|(TeWgbnc$O-MTBWp2XcS3WQlb2vK5KXJ6!et5F??wp&>+|Q@|wfgUvtGBjN|K zR-jkUveFHwbhZA~ov8lhxA%jbd_{46HgK#xJytqwr*+Sf45vT>*iI7o>J{WB`B>0Z z;!{tFadd^0raYupF_N%-s`n>=I}z>^sg_>eYVepLnua$^ZOOnrW`#7b)KQSzb{|rC z+5)=AXF@9BQ9_W>tPqQ62Y+ym77~!+i*tblN5)b=ycpM6g>>NL)PtcFIBhx?uV=k9 z089_S7y}GTxBhzB;5|kCU;n=diW>cQxyKg-6muB4!s%eFsuA|$`gBzP{h|MZ^Lu<4 zpm;@27KO5LQ3JO8*@&?I5Ago`tM~Y(k$nIN{m(b7|9<8{0>J-Ge1xLfKj8moa`!&~ DLUs9b literal 0 HcmV?d00001 diff --git a/Source/Rampage/Sounds/playerDeath.mp3 b/Source/Rampage/Sounds/playerDeath.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..12efd3219c0efea28069d4de2769d04f95e5fb77 GIT binary patch literal 25939 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

)GSsV(+C8cWUIq&@RdeUi4-XJIQ2 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 literal 0 HcmV?d00001 diff --git a/Source/Rampage/Sounds/playerWalk.mp3 b/Source/Rampage/Sounds/playerWalk.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..1b4a6dabef4637988e151e131ace3678f6766ce0 GIT binary patch literal 38481 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ℑ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 av)xOdclWZ@y>unh2LNFGH=+NlhyNd6QwKKy literal 0 HcmV?d00001 diff --git a/Source/Rampage/Sounds/squelch.mp3 b/Source/Rampage/Sounds/squelch.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..11d0c2afc12e7c766ed8571408cd4487ad731c55 GIT binary patch literal 8712 zcmeI2XH-+q*6>e4fB*qPC`Q^p^hlEqB1-6?*GLhi_bMoYfC;?_O0ObSklsOx0)hw% zf~X);qzFh8MCrnL!@cWy*ZuTXG$1ZNybdg(1_fe#{htuk8hBln~UphjEbk7 zH%8w<*Uj78DF^_Mvs}-*{=cwr^L8QY8OdKX0PsivbYz6cTqJXuj3yZqGB?j~BjZoz zKACtjsbp%;ctPehnGrHy$jp=ZamFT@9Wr}lj>&*z$a691spxA+i%UvKP=x-Ed7m)+ zFpoq4QgUWT!NwToe-!_}{onBbcKgoc46krQ57N9Q`AOL2SlPd~eND$|zKZF>3 z0q_uqL&6x;SC)ED3;GI2Km7hH0 z2J)zp)Q4mW=0TIVM||{U*_qW!qziiFesw#q#QmXymqzW=T}0vo!Qj$TS-%0NUo8TX zl&>=`nCOBsD&F2v79sQfh&g%NCfb87PWxcyeDK3<(VSorPX4UnC+8I2GV!EwGqMfS zDudu2DD-8%$k}P<=v``b=?{4jJm~^g3v6WZ0Dw``28sabolN4h@MjT=htf)4j+{Y42u%rhLTX<`hd6s|tZU&4TlI zKws(pspJj_4<7`kA_}Rol0~?9ddZzfDyj58QUkX?sx#@!@l(8nwB>5h{QRYi^`JAE z;3~c5za;TnEC>jYYd<8+Uq~8N z*AXH9LQ!?It7N-$vr%p5#vDLH?F@cGm!E}T@LrwT5x&5 zxW=tfHdgl>arRQ%^#^=m7((9e``HqLYdG;AC~rvb845dvh^owTTL>( z2E5Gj^KY+6tVLGm^dwy~&^=P@5K|VwABBRuV$BjHlDiGm*lsG)MA(b6vDh-Df8e^i z-u0_Jr0&~Lkjr#qcg-&g>O(195vMtgykO+Lu;bl6`6``EzQPy6{$-evSn)}Qh&(0t z2WU0ehDsd%wOs$4OG5YpFYYmg!qpx$yO1gE!GQ1^KbALKuUyc+yq!b}xj4o8t5Y;< zQ+zq~54E`)Wq4e81>&r7t~)+>j&OG?y+0$Hjox>S-#>PXj+Q9g_YLDRv}j{7Qo4 zeF>K`Gj!TG_!`C59}&Df%fsn?73y&Nr-I$NxBl|0A9YNu(}P#G8|@q-OnEWV@|sRj z#eA@kM4s^Yn9HJuU1mcGzak9b1;#PcCjl{IDO;%0=BGPYL=5r;<>Z!%e7UQ_B_~R= zTUKf;6#yQcU6g}0>9cnB61$ia(#jRBa(`GddF%6K_gbHt@dG)ku+eZ0RH40U#%UL5 zGXqwVHy-iGlmvl6uQRsyGDy6VoVKmL^yH=C&yW^+Roi%ra4vm@=w5|qeJyMU1wVp4 zO>gN`bjrC9Qh5vUOoKHpbBRIGxBb4nt95Yr+ZyjzV|4n@$dyOOppMM+^SchtlHv@{ z%w*^(v(xF9Tr|}RpL+ng;@vf>Q3KxUPcUbm0 zWe6R+Z7&N#FV{s6?S>nNY}7}i0j;8f`V~)Yt-OF7OVcjm8hGOR?Po{BH)1DZbP!QL zsr~u+$CX7hz=7;|iUkVs?fz1P{LNHO(Q3rUy9}6~<3>jl>g>k}Z+W0XJg%5{3O25J zI{6PY7Ny3>>j$clbPuTLp}@g zJXGR|>+5xPP!=8s>gIPX-(zn|+mwTr%faAIo~H@h`;SBK4CWO!CwKPH z5eKdY@|jK3mBS}ylaYi=;O`}km%~9LVyQ&*ixRQ2f_wLZYn>U+6TXJ?YA={f`FJ~L zt*hjWLDJUh8a!`BA_<$px~`hZ8WSH>-(XfO<3%R^>=D6$f=`cq> zYWq_G$YGtO6q5PR*|5jm(qSfiIP)`{L=h%%<8X`JNV5C7l7t;VJMhjc0pUjaz#w9@ z9Xt0>_PV)B&h-ZmZXI=)EA&l!Igk24@qVu#By-??*{ETS%6XEl>vSRXmP$_%?io!l zm@*;o)ozTkBC;n1>UH8N2VARu3)iT_{!e(TVdv;eEK?wt`H{{ zF?S^l78n>O-D*=@Y;ogj)uzpOof)fXVpNXP;a>4^=s%!P<>|NYnLIwi08gJz65u2& z{ZyBKzjiGrC(Wk&VYP5ZOMYSrNQ@U4|#-zs+KeH83Tw9YY&H+Snc{K zH0iF{kd|2W`JjIsFb36fja_%dIn6xYwU#fLv;?$EuPKSGUR^(idC;G0n5iw;GvIHt>NL6PqVEmwNzjJqv%k?)DYiIaxh=Rjb8|iCtwfPBn+1UIkIU5YIH+HxSw1>jIDN=Ys=?!;#Y{ zz*Q9q$N&KA_cK3J0u(5P*~3M4Tcxn$5oHQN+AlW5WwZ;hMClWfib#4J%ulL^h?>=p z!fZdeFgORdBU)(FUO?CmdP?5X=^X9 zFIqjgw(;@Vsd>j{(k92$(|k}1ETsEs2ufe03Q#HNX0?-$}e(q!ttH2~rv(7b8 zo%xxO1pUbUZB_7mH-VDFOQ~0fra&aP3gJlFhSzxZ#Lo35McEdukC$+bTBw^_b8|U_ z17;6WoM0{21=G3MR4ANGG**3mMWbaq_B%Ie?cKk=v1)F9$6glNa-zCpOFpmw$k4p- zC8NcYiE&ZUi0Z9dc@0I4V!Ka<61Ge4Kpsf>_FZ34u;}3oGLDyE%qXyne|RS^4L-!Htq&7ZsUuuQMTZaST(tO+}6M5{@#itO4npJ{Wqb|UED zj0i@4i^Bg{OD5U!5$>RJ`H{v+J(j*mi_J`X%x#YH9Z^2fBf{kC(8$59Q^N3#VIsKN zbs}u?yu=GizPU0l_LYQjQ`+{dDzU2YF2S**X+68}9r1ir@)z!>ymJeb;IV}(D*(+n zKkK%5zFQ7*T+8nuNaHCKw1{>j{iYCCz{KL!pK&Q9f2YKA;3%7Ak_C(~57-G2-1yy6 z_IbMrzOgki!_WUrZmb(V8zf|~8pA1h5j4z~n^A==3e}rS`0v*JS^~!2g8N6ov>si9 zer1`Oeaidt-$T2=V>zbxjn8OqB0j*9`AGzXf}>S}E_4>3ZXJ=}|C$!CqDQixQ!I?b z;#LXarF57Iop3@1OOugt9zs|D0gu0z5!kLAfIU4?6F%KDHU)RtJ7hX8oD&M6e=3Ggx4t`W8H^QE=@3IJtuROYQegKLt6!t{rbAm36ITIhQBngJ*F_OQN8~&Dbro&q?!6Jwo#;AWDAwRG~dcBNSepsc5_= z2X)XTr$kNpx7RFpo>V(Q67^OPqJK-ANs?I^X#{%?o(bl~=>_HIwJljw%%sEskn>%HCNm;5z zSY`bp?Y$QhAM{gB=Cd7Jm9PEXq!h`{9;s1x)@7R&`8%^5=|oAZq%P&jih4dOY$n4c zENWZF!mq+lLO_DY)qPsQagt1S#x))w(#TBX8)w)u@TTOE)eQmr6nUS9ptZ*AUxOUt zmYbK4h<|HOzkwTTwapnU}Nh;kx&iu?uQvJd_y-JQl1ssO~nh!uAGreN625}#gHvZVgVLvQhYt9qqZImmf zyL^?TVk;D#D2EE9%81L>GqSi|;Kw06DDT4v)2DYwMJn&Gti#l_&7|1kqp8@tv+a;( zirC7kYO8ZU@OnCtS5Mo!bqhVQ9XCHru=xpU(i!ZA;J6pbcVL&UBP~HW9Fzn*zcTvL zt7Y|hhJ5ytl5~^c>u@LSbj`=`z=%g|Sg+Z=$M#9$qx$su&p*vHh}B#&N!5I8$p9&& zgmYVr;+cH4;a3@W?0+Sq2C+{%FcRGLS7;6ICVc8Dd#Pu*1|R{XRmr{CF1DhJ;A z3r~Ky@~!Ak>Sq*kSufG?1NF^HWppb~{x6&I#(WT*0WYXhM{B5|09yX1D!LEQF?{6( zVqpbh6kMfckMw>I=|`G~v8XV|(p=zMHHvkAZ1&M&xm`G_oJl3FR$Ha z%nPo-ADkHXh|Otj?Zf7cy^iCb`iaM;AHcH3H+*F-Bk7>wNllefoGm#F0fps+Ma^e& z6a6LOhcQ1R%jos3javN?O~@oxh^Yod9tu6ji7C)Im>0W1Djz^NVw^_!i+U^weaHY2 zxGEOSf6E%4gO#pY_)cwoUUEK4Z5wj#aS1d%3|*$h`8egaM7dP#lK4OcyuHU|W1cOZt)0H^VZ%VZ1* zvaRf;jPivTHyz-@LZ(ENE|Cj=xm@k9t=L-dep}a8EActuvHza( zX}|ey_38Z)(Sb%~o6Sa3FM;VcIR2K&R|p~fdfe?k%peC?&No7o@e)r<w=@(kxP> zg(Bh9W>U*4#ri&z9j;?@&pW0k*}bAz?z7?VT~N=8$X?x%qE~6SlPA1Tt@zv}!L8t9 z^0HR5aKKo@CiEz74~G0^I&4H6ff zi1Dll9dVObP4rF~-_2Xkx2;Mp?4Rb)sL8LY{MHx!+dF+-VzG;uZRcTSs#L-nG`=IZ zszYR6-uIjFUg51y2H)E)%N#WB(>oPD4i{#K-o0tF7TdadbmCz3FL#2!FFQQSA)d*n zsQPNVn>D`#V>SCC@!iIhMsPSZ?6AmFs)Qf!q5L%_H5YFEv+}&zE4)B=W%L(R={MPWkenbB>p|mzz z?Vlqn=YGAG7SmIGMaPQ{SkgsZNQQk=vr2II{GD)<`6unZ zbUDJ=-9<~E>1biQ)!&qx#jTEa&}(q(C7djHjr4-V@sc4eOK4t?8f+8?`5%+mdej-e_m8C zO%*B1H3uejP)AxUe>EinIJ=|R_ZJE?O%i45bhNHJe$92ewdq}#dKqV+Rn5z+R`6`( zN05e@EHAlo8llN9+1Mv?5tbU~2Swe|3zhOOI*jqxRV99Od_7sGqEPKiKd6SqY^Tus z{c0S4n4E7hlF22_qhx*fo(gw$zU-5)&T2*;D@EK}26{LxT)!^fSX)Tq{jfn`VCsXXj55iYEn~P=BZ!xW5Si}a=n_8&Z4Xx#orA@pSY@d z(~e5|H2c4u)rc?vg|_mPg&X?#wZ>?Ra<+qYg=8_LD2|<-mDB*# z=HisA1G|wBj)M{41?U_{T#CuHi%OFFHjn@;)U`RXI2S7NHGhfBZ4c#@)yrtVBS-gF z=6LE$daT4e>|xj>Qh^h*GQM7Rx>o*JuxkoDPS)RSINa|z8eJR4I`XRnOdb-wRGJ@} zM=(=@$5QxYCvUpa3{W+|Z7_Qi|sLbnl^oav|!^wdjT< zJ6k2i-W3%Haq!T|)#+M$sz;+#MtPFaIjXv4RR$^+V>{Ex$ZP0}{1S^Qw+dAPqQr`{ z_5!ZwDb9;jxE#9Y-V!9|0lAOeth~Y{t5vJ0d) zjrDWeu@QOkAxf_P1^`ojA-RTT;R**($@G)1e3BC40BtqQUI$?@Wz;L-MsfwPBnTY% zGM4JWd%-p15~e(C5jq?aEAxt1L&>^RAikdOW?<2$6b((ZutpUsorYVO169|qW|Vd# zn7h8L`D;bH6QODZ{Nw&T5*3F9Fz)XqX*4dFpyR$tt*u}m4J(z}9Oc)7NBLszUB|?4 z;H=x+2VOI>pE!R_AE@s^nqFwn)2t+S+A#N~v|anNyZ5m9XYlyustQbf2qpr@@b*Ng zsE}fMkYP|*Y{HET>QN9yE&mlo8*~oTRYwSwpcKY5H>xMdUb%2iz1Xb4&4sutPEVmZ zW_+mmHBE9lVCO}Ubi%%LdKK$#J9y#^K9iBGBd-#~WNR`{)F1MY|6lP#g2wQEa_wg~ zx(JCIgE&JE!2;SeoT0sf9$zv}7)-Z)I)_BkLr`r6 z(m#^bD2h!ibwnnGlP!cx)ij=1uv(!;{?`BSI9wtg*Mj4KSTxQ~kO~89LeRh>292T% z-hFRla|tW>lD1kXxiE+-CU31Ld%JnyQWrSM&q9JjSOvN!^0)gurlK$`!X!?fz~>2w z*DVEA7f?Zecj&_C!eD@W#8%v!On-I{^Y#`|GfjSKNVo4*$H7cdGc!#%McATd0x2pg z>b1XMk_R{mg3qp>D|CeG#+KS$rn1;U*GdI9KJ^(Hd4EZeUUcW^WtUIMyDkv?Bk*kx zEL;)}!yCVxh^_>W6K1U9VpltE z`*t~_gGfkyrZFgHIDYYC7$2W5-&mWIDe>?_lUQih-^Nvc>VLrF@73!{T0U2*Pca?o zcTJerI_mcC)h2iAv~o(^8u7K3bJ&g}uMvO;IKWM--y;s=zROq1zdb55l`r%EIO(5}qN9 zp2CU6{~AB*1yv8tbI!<4S$AGvg{bq+Vg{;f-4f8yIp1NmuCp!`p?M0hNEh9@JJQD4 zH{7P{>dHmHzW~nhrchGMFr|d>O6JtRh9ci&juM3T*kX~t$#s6Ts|e$E5v>lerH!R0 zP4dDVm?#7+aZK(IM4tQG`~Czd#jKmXsS z*@XY(%$`e(+qraaNt#R&Q~-Jo;DbO}F7QI&j&&LUFOHm7|Fi#pTRyYLm~q<@P$NOm z03(UIj-2NKBPc*m0x)m@2T1~8|7{!obNn-V?lNuzfEzhd;Q&C7A!ilxhx`Hnc}D;; WB=XA+|Jnb)Et{!mk!Sv21N=WI-OUOB literal 0 HcmV?d00001 diff --git a/Source/Rampage/Sounds/switchFlip.mp3 b/Source/Rampage/Sounds/switchFlip.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..4a880137c6a241a6f7c05f7092034574811df0c2 GIT binary patch literal 3528 zcmdUydo+|?7r@VqF~%4SQBv{{8J9GPLTJX!7$lL~$mJck*N}ul^}W?YqYzSVqmmIN zg(#QO#mF_6N~KaliM%d}ZWuh@V7-5TYkg~de|*1no^{Sy&tCiNv-f`X+7BX3=YanJ zD=0KjBqF=~NVfo~B~~n>zl7H^k;|kmQLs$yG962FEz`5i&=TL4nO+82LUfjl9d#FD zi@u3*gxIlvEPMrNUsR4}ynikbl zeyE_VKg>&A;`LF}(RxaKXhryeKjsKY?=IwnxQA}yxWuZ7BH zZv{Z|`Mc-c*;9uQp#n$dG%+1Z%bOtc{Y)lsARba!O=(KK(sN_3ow!P^HB01zkg~O_AIEn!`2-f}{|g=U zPT9GJsQ%XFIAf$GH*37kx@oLCTNi#A5M>ZF9^R2r6aM>Y1SWl?qH*KIE8B?R=+(LN z(fY^BdJ*JU?^I>hjOT9Tj1(&IJOD Bl*f9DqglpK*_72&4$+irsdtcT*iK!!AX+ z-A##*XkL-!=DbGR+jn-h=EaX^6^$ehQwvymt==gtzZkD;l5OzLDsZ9GhKX#|xypt} zWL%S9=k)wS6^ucI6&wkGE#KMw)ei#aZMK^>nE~94#L>AJ7)) z8Sk9?V$}w8A^|AOJHW2j`kVwZ0#?4Y_!#d@=be}kgBS^U32`0pv_6GyDVs<=l%A!T z`tj&MT=%}zff`OKe}ZNa?V1mcteUeWT|3(t*OGX~v00g+?<7}j@zW{pUUS};UR~Y7 zv=bqrxg&d6S-%|VMS(%%rneqyO4a`EK{ZXLvt*qSYir2JF9YGlJ*I7T;KQ(z~Fm7~}y2khNubj~t?|gs( z;^%%w;GZEBsipeo)MGe&J(X@EeOW`D)?f{k-ZBgmY^Y&|^}cCGH@}bkT1FdBzgfp= z=QCsn_p)Jv8>?m7ZO?}Iz~&+M!R!h9HT!$lNoC-62oKo&RXZD=^xiG&ZsTui@gM}q zkm!5B@v%~CeMpG#5JwM2|6%1duEfS~V88b&z=?9!FWfi-M)_aee^4n5M3v|mD=WXuH>nGyJ zUp+beoOaUz2YCDKkGv@#+dpRfvg7h?-@-Z|CecqBxHC7(-jnR0Wr#nV&J}g;Tj* zf{@NeAPd*sS$)W)qna8tRRd!nJ^*AKQ4|pvXm67!uWU}fHW88L9f-_un~n$g$W0;b z>J5J&Mn+o5=hpZlWI;^HdJVoVca|z%2n+&bP`WO$w)Z~1m)lEva9dL)v!~}<1Tlev zmfmI9y?TAZXU2s;Ph|#tdirVZs*&P|@~yG@gp$auYYrS37(z0tT|AzQWam}wZAw-t zifs-^-a0Zav)7aYVCWE54FXmK_0Dre1|egW?@Oqb_?P-r!QCCmtU{-bA6{D&giqHj zi}kx!^2;S{ViC3Iuk$Y=+C27xd9i>)N=C|d)~Bf|7l+pwE_4hq8F~+Ur%;H{pCb*U zPZ~RAa0EcB-*&zjhr&W9eC|%dppX#!8-h?l_VsFM=W4N)oI_uUdA+=33X zoaWY?H{M?Je^tM)S5-E@e4KuBw#f0#gzqz%dk`Q32Otj-G%};=1e1eDH%lPMoX=33 zGmE7xLzI)G>?3=9=$R5Znx4oEsSXw`0I)f)?W&)fw(Wzt`8HwM=PE;dzGsaA%So%< z;HKw;n$4+xwgQn@NX&`|STqBGl~-SBu`}M`b!C_3M1QMd&WXItU$+$o6H;aiMa5pE z94&aeB-F4eg@Rp5t0{_ZdILxYzn_V+K zIs!dY^Q2woz$g*mt_%W632F76Rk~e2 z#&_qxaSRRC*ivLnBHX}oK2RN6N?aO}^jTwN29fmY=bhU6S74w6P-eWfnQ~<>`;Hp@ zj&e^(+2|bRT6%UOLvl`QE*21QPbdJB`e^4PL`dg|CpfNI?bJE2x>d7o#N5nMi!df5pN`2wN3W>csM_&&?ealZl$A*-`cy`-MGZ{w9bREG>U32gg|b=k zfndZ@gK2Jr%nM2)MP2Hm(+0b6!CMOv8P_s7Doj!mHK&Vx6yY?Hi`m^dq=b`)+~>`F zP~f?Q6_-bWn6U*e6-fm4_mjM!$m80GO(+b}SD=%)O2yRdSVe3`9v-dj!bL_!2?bLC z2*6ySxrb@fwOCPD^RG9qh$_aSerfTrQVerImV}dITaN_!qR?yQlBhY}uGiC$~$d%Oz zY8P&ZY=r?Ztt=2%vCU9NPKYYR9LcB*3$12JU>@Hrj0mZzMUXm_?5oN9!(uWAPjgpV zW{eS-pRH}f&`l{#NcGaW$*DI`>v4WcKml@&P@)1fPdNl|eZwq(y+1JtGn`QD?tFh? z0tpn>W_~Uu0wn^GERpQ>X2b)QbsSN;HBZHfynH1#T+K<%5Sh2eGQ^rrC&no9;o|Pe zeu)m G>i;+7l&H)A literal 0 HcmV?d00001 diff --git a/Source/Rampage/Sounds/wallSlide.mp3 b/Source/Rampage/Sounds/wallSlide.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..6c5b15ffdf6586622059d7d68cde60e0642f0d11 GIT binary patch literal 69985 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 literal 0 HcmV?d00001 diff --git a/Source/Rampage/Sounds/wallThud.mp3 b/Source/Rampage/Sounds/wallThud.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..6105416c297f5390f2a41698c78c31eef5d528b1 GIT binary patch literal 13398 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 P@PFc;f4AiShU5PM9bZLp literal 0 HcmV?d00001 diff --git a/Source/Rampage/ViewController.swift b/Source/Rampage/ViewController.swift index 9c9cc0a..d29260f 100644 --- a/Source/Rampage/ViewController.swift +++ b/Source/Rampage/ViewController.swift @@ -26,6 +26,20 @@ public func loadTextures() -> Textures { }) } +public extension SoundName { + var url: URL? { + return Bundle.main.url(forResource: rawValue, withExtension: "mp3") + } +} + +func setUpAudio() { + for name in SoundName.allCases { + precondition(name.url != nil, "Missing mp3 file for \(name.rawValue)") + } + try? SoundManager.shared.activate() + _ = try? SoundManager.shared.preload(SoundName.allCases[0].url!) +} + class ViewController: UIViewController { private let imageView = UIImageView() private let panGesture = UIPanGestureRecognizer() @@ -43,6 +57,7 @@ class ViewController: UIViewController { return } + setUpAudio() setUpImageView() let displayLink = CADisplayLink(target: self, selector: #selector(update)) @@ -86,8 +101,26 @@ class ViewController: UIViewController { if let action = world.update(timeStep: timeStep / worldSteps, input: input) { switch action { case .loadLevel(let index): + SoundManager.shared.clearAll() let index = index % levels.count world.setLevel(levels[index]) + case .playSounds(let sounds): + for sound in sounds { + DispatchQueue.main.asyncAfter(deadline: .now() + sound.delay) { + guard let url = sound.name?.url else { + if let channel = sound.channel { + SoundManager.shared.clearChannel(channel) + } + return + } + try? SoundManager.shared.play( + url, + channel: sound.channel, + volume: sound.volume, + pan: sound.pan + ) + } + } } } } From b8784a459102a6561c2931a6264d57a6a607ac68 Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Mon, 10 Feb 2020 08:38:09 +0000 Subject: [PATCH 04/10] Part 14 --- Source/Engine/Pickup.swift | 46 +++++++++++ Source/Engine/Player.swift | 77 ++++++++++++------ Source/Engine/Renderer.swift | 9 +- Source/Engine/Sounds.swift | 3 + Source/Engine/Textures.swift | 4 + Source/Engine/Thing.swift | 2 + Source/Engine/Weapon.swift | 75 +++++++++++++++++ Source/Engine/World.swift | 28 +++++++ Source/Rampage.xcodeproj/project.pbxproj | 20 +++++ .../medkit.imageset/Contents.json | 21 +++++ .../medkit.imageset/medkit.png | Bin 0 -> 124 bytes .../shotgun.imageset/Contents.json | 21 +++++ .../shotgun.imageset/shotgun.png | Bin 0 -> 250 bytes .../shotgunFire1.imageset/Contents.json | 21 +++++ .../shotgunFire1.imageset/shotgunFire1.png | Bin 0 -> 321 bytes .../shotgunFire2.imageset/Contents.json | 21 +++++ .../shotgunFire2.imageset/shotgunFire2.png | Bin 0 -> 372 bytes .../shotgunFire3.imageset/Contents.json | 21 +++++ .../shotgunFire3.imageset/shotgunFire3.png | Bin 0 -> 362 bytes .../shotgunFire4.imageset/Contents.json | 21 +++++ .../shotgunFire4.imageset/shotgunFire4.png | Bin 0 -> 305 bytes .../shotgunPickup.imageset/Contents.json | 21 +++++ .../shotgunPickup.imageset/shotgunPickup.png | Bin 0 -> 174 bytes Source/Rampage/Levels.json | 4 +- Source/Rampage/Sounds/medkit.mp3 | Bin 0 -> 11748 bytes Source/Rampage/Sounds/shotgunFire.mp3 | Bin 0 -> 63288 bytes Source/Rampage/Sounds/shotgunPickup.mp3 | Bin 0 -> 17256 bytes 27 files changed, 383 insertions(+), 32 deletions(-) create mode 100644 Source/Engine/Pickup.swift create mode 100644 Source/Engine/Weapon.swift create mode 100644 Source/Rampage/Assets.xcassets/medkit.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/medkit.imageset/medkit.png create mode 100644 Source/Rampage/Assets.xcassets/shotgun.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/shotgun.imageset/shotgun.png create mode 100644 Source/Rampage/Assets.xcassets/shotgunFire1.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/shotgunFire1.imageset/shotgunFire1.png create mode 100644 Source/Rampage/Assets.xcassets/shotgunFire2.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/shotgunFire2.imageset/shotgunFire2.png create mode 100644 Source/Rampage/Assets.xcassets/shotgunFire3.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/shotgunFire3.imageset/shotgunFire3.png create mode 100644 Source/Rampage/Assets.xcassets/shotgunFire4.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/shotgunFire4.imageset/shotgunFire4.png create mode 100644 Source/Rampage/Assets.xcassets/shotgunPickup.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/shotgunPickup.imageset/shotgunPickup.png create mode 100644 Source/Rampage/Sounds/medkit.mp3 create mode 100644 Source/Rampage/Sounds/shotgunFire.mp3 create mode 100644 Source/Rampage/Sounds/shotgunPickup.mp3 diff --git a/Source/Engine/Pickup.swift b/Source/Engine/Pickup.swift new file mode 100644 index 0000000..abcc39f --- /dev/null +++ b/Source/Engine/Pickup.swift @@ -0,0 +1,46 @@ +// +// Pickup.swift +// Engine +// +// Created by Nick Lockwood on 27/01/2020. +// Copyright © 2020 Nick Lockwood. All rights reserved. +// + +public enum PickupType { + case medkit + case shotgun +} + +public struct Pickup: Actor { + public let type: PickupType + public var radius: Double = 0.5 + public var position: Vector + + public init(type: PickupType, position: Vector) { + self.type = type + self.position = position + } +} + +public extension Pickup { + var isDead: Bool { return false } + + var texture: Texture { + switch type { + case .medkit: + return .medkit + case .shotgun: + return .shotgunPickup + } + } + + func billboard(for ray: Ray) -> Billboard { + let plane = ray.direction.orthogonal + return Billboard( + start: position - plane / 2, + direction: plane, + length: 1, + texture: texture + ) + } +} diff --git a/Source/Engine/Player.swift b/Source/Engine/Player.swift index 3f62f43..4a12009 100644 --- a/Source/Engine/Player.swift +++ b/Source/Engine/Player.swift @@ -20,8 +20,9 @@ public struct Player: Actor { public var direction: Vector public var health: Double public var state: PlayerState = .idle - public var animation: Animation = .pistolIdle - public let attackCooldown: Double = 0.25 + public private(set) var weapon: Weapon = .pistol + public private(set) var ammo: Double + public var animation: Animation public let soundChannel: Int public init(position: Vector, soundChannel: Int) { @@ -30,6 +31,8 @@ public struct Player: Actor { self.direction = Vector(x: 1, y: 0) self.health = 100 self.soundChannel = soundChannel + self.animation = weapon.attributes.idleAnimation + self.ammo = weapon.attributes.defaultAmmo } } @@ -43,38 +46,71 @@ public extension Player { } var canFire: Bool { + guard ammo > 0 else { + return false + } switch state { case .idle: return true case .firing: - return animation.time >= attackCooldown + return animation.time >= weapon.attributes.cooldown } } + mutating func setWeapon(_ weapon: Weapon) { + self.weapon = weapon + animation = weapon.attributes.idleAnimation + ammo = weapon.attributes.defaultAmmo + } + + mutating func inherit(from player: Player) { + health = player.health + setWeapon(player.weapon) + ammo = player.ammo + } + mutating func update(with input: Input, in world: inout World) { let wasMoving = isMoving direction = direction.rotated(by: input.rotation) velocity = direction * input.speed * speed if input.isFiring, canFire { state = .firing - animation = .pistolFire - world.playSound(.pistolFire, at: position) - let ray = Ray(origin: position, direction: direction) - if let index = world.pickMonster(ray) { - world.hurtMonster(at: index, damage: 10) - world.playSound(.monsterHit, at: world.monsters[index].position) - } else { - let position = world.hitTest(ray) - world.playSound(.ricochet, at: position) + ammo -= 1 + animation = weapon.attributes.fireAnimation + world.playSound(weapon.attributes.fireSound, at: position) + let projectiles = weapon.attributes.projectiles + var hitPosition, missPosition: Vector? + for _ in 0 ..< projectiles { + let spread = weapon.attributes.spread + let sine = Double.random(in: -spread ... spread) + let cosine = (1 - sine * sine).squareRoot() + let rotation = Rotation(sine: sine, cosine: cosine) + let direction = self.direction.rotated(by: rotation) + let ray = Ray(origin: position, direction: direction) + if let index = world.pickMonster(ray) { + let damage = weapon.attributes.damage / Double(projectiles) + world.hurtMonster(at: index, damage: damage) + hitPosition = world.monsters[index].position + } else { + missPosition = world.hitTest(ray) + } + } + if let hitPosition = hitPosition { + world.playSound(.monsterHit, at: hitPosition) + } + if let missPosition = missPosition { + world.playSound(.ricochet, at: missPosition) } } switch state { case .idle: - break + if ammo == 0 { + setWeapon(.pistol) + } case .firing: if animation.isCompleted { state = .idle - animation = .pistolIdle + animation = weapon.attributes.idleAnimation } } if isMoving, !wasMoving { @@ -84,16 +120,3 @@ public extension Player { } } } - -public extension Animation { - static let pistolIdle = Animation(frames: [ - .pistol - ], duration: 0) - static let pistolFire = Animation(frames: [ - .pistolFire1, - .pistolFire2, - .pistolFire3, - .pistolFire4, - .pistol - ], duration: 0.5) -} diff --git a/Source/Engine/Renderer.swift b/Source/Engine/Renderer.swift index 638f5cd..6363828 100644 --- a/Source/Engine/Renderer.swift +++ b/Source/Engine/Renderer.swift @@ -122,11 +122,14 @@ public extension Renderer { } // Player weapon + let weaponTexture = textures[world.player.animation.texture] + let aspectRatio = Double(weaponTexture.width) / Double(weaponTexture.height) let screenHeight = Double(bitmap.height) + let weaponWidth = screenHeight * aspectRatio bitmap.drawImage( - textures[world.player.animation.texture], - at: Vector(x: Double(bitmap.width) / 2 - screenHeight / 2, y: 0), - size: Vector(x: screenHeight, y: screenHeight) + weaponTexture, + at: Vector(x: Double(bitmap.width) / 2 - weaponWidth / 2, y: 0), + size: Vector(x: weaponWidth, y: screenHeight) ) // Effects diff --git a/Source/Engine/Sounds.swift b/Source/Engine/Sounds.swift index c264091..35ed47f 100644 --- a/Source/Engine/Sounds.swift +++ b/Source/Engine/Sounds.swift @@ -8,6 +8,8 @@ public enum SoundName: String, CaseIterable { case pistolFire + case shotgunFire + case shotgunPickup case ricochet case monsterHit case monsterGroan @@ -20,6 +22,7 @@ public enum SoundName: String, CaseIterable { case playerDeath case playerWalk case squelch + case medkit } public struct Sound { diff --git a/Source/Engine/Textures.swift b/Source/Engine/Textures.swift index ce4fd44..ae171a5 100644 --- a/Source/Engine/Textures.swift +++ b/Source/Engine/Textures.swift @@ -22,8 +22,12 @@ public enum Texture: String, CaseIterable { case monsterHurt, monsterDeath1, monsterDeath2, monsterDead case pistol case pistolFire1, pistolFire2, pistolFire3, pistolFire4 + case shotgun + case shotgunFire1, shotgunFire2, shotgunFire3, shotgunFire4 + case shotgunPickup case switch1, switch2, switch3, switch4 case elevatorFloor, elevatorCeiling, elevatorSideWall, elevatorBackWall + case medkit } public struct Textures { diff --git a/Source/Engine/Thing.swift b/Source/Engine/Thing.swift index 63b197a..fb3908c 100644 --- a/Source/Engine/Thing.swift +++ b/Source/Engine/Thing.swift @@ -13,4 +13,6 @@ public enum Thing: Int, Decodable { case door case pushwall case `switch` + case medkit + case shotgun } diff --git a/Source/Engine/Weapon.swift b/Source/Engine/Weapon.swift new file mode 100644 index 0000000..a778a50 --- /dev/null +++ b/Source/Engine/Weapon.swift @@ -0,0 +1,75 @@ +// +// Weapon.swift +// Engine +// +// Created by Nick Lockwood on 07/02/2020. +// Copyright © 2020 Nick Lockwood. All rights reserved. +// + +public enum Weapon: Int { + case pistol + case shotgun +} + +public extension Weapon { + struct Attributes { + let idleAnimation: Animation + let fireAnimation: Animation + let fireSound: SoundName + let damage: Double + let cooldown: Double + let projectiles: Int + let spread: Double + let defaultAmmo: Double + } + + var attributes: Attributes { + switch self { + case .pistol: + return Attributes( + idleAnimation: .pistolIdle, + fireAnimation: .pistolFire, + fireSound: .pistolFire, + damage: 10, + cooldown: 0.25, + projectiles: 1, + spread: 0, + defaultAmmo: .infinity + ) + case .shotgun: + return Attributes( + idleAnimation: .shotgunIdle, + fireAnimation: .shotgunFire, + fireSound: .shotgunFire, + damage: 50, + cooldown: 0.5, + projectiles: 5, + spread: 0.4, + defaultAmmo: 5 + ) + } + } +} + +public extension Animation { + static let pistolIdle = Animation(frames: [ + .pistol + ], duration: 0) + static let pistolFire = Animation(frames: [ + .pistolFire1, + .pistolFire2, + .pistolFire3, + .pistolFire4, + .pistol + ], duration: 0.5) + static let shotgunIdle = Animation(frames: [ + .shotgun + ], duration: 0) + static let shotgunFire = Animation(frames: [ + .shotgunFire1, + .shotgunFire2, + .shotgunFire3, + .shotgunFire4, + .shotgun + ], duration: 0.5) +} diff --git a/Source/Engine/World.swift b/Source/Engine/World.swift index d69bdb0..ddd6dd4 100644 --- a/Source/Engine/World.swift +++ b/Source/Engine/World.swift @@ -16,6 +16,7 @@ public struct World { public private(set) var doors: [Door] public private(set) var pushwalls: [Pushwall] public private(set) var switches: [Switch] + public private(set) var pickups: [Pickup] public private(set) var monsters: [Monster] public private(set) var player: Player! public private(set) var effects: [Effect] @@ -27,6 +28,7 @@ public struct World { self.doors = [] self.pushwalls = [] self.switches = [] + self.pickups = [] self.monsters = [] self.effects = [] self.isLevelEnded = false @@ -124,6 +126,24 @@ public extension World { } player.avoidWalls(in: self) + // Handle pickups + for i in (0 ..< pickups.count).reversed() { + let pickup = pickups[i] + if player.intersection(with: pickup) != nil { + pickups.remove(at: i) + switch pickup.type { + case .medkit: + player.health += 25 + playSound(.medkit, at: pickup.position) + effects.append(Effect(type: .fadeIn, color: .green, duration: 0.5)) + case .shotgun: + player.setWeapon(.shotgun) + playSound(.shotgunPickup, at: pickup.position) + effects.append(Effect(type: .fadeIn, color: .white, duration: 0.5)) + } + } + } + // Check for stuck actors if player.isStuck(in: self) { hurtPlayer(1) @@ -141,6 +161,7 @@ public extension World { let ray = Ray(origin: player.position, direction: player.direction) return monsters.map { $0.billboard(for: ray) } + doors.map { $0.billboard } + pushwalls.flatMap { $0.billboards(facing: player.position) } + + pickups.map { $0.billboard(for: ray) } } mutating func hurtPlayer(_ damage: Double) { @@ -205,14 +226,17 @@ public extension World { mutating func setLevel(_ map: Tilemap) { let effects = self.effects + let player = self.player! self = World(map: map) self.effects = effects + self.player.inherit(from: player) } mutating func reset() { self.monsters = [] self.doors = [] self.switches = [] + self.pickups = [] self.isLevelEnded = false var pushwallCount = 0 var soundChannel = 0 @@ -259,6 +283,10 @@ public extension World { case .switch: precondition(map[x, y].isWall, "Switch must be placed on a wall tile") switches.append(Switch(position: position)) + case .medkit: + pickups.append(Pickup(type: .medkit, position: position)) + case .shotgun: + pickups.append(Pickup(type: .shotgun, position: position)) } } } diff --git a/Source/Rampage.xcodeproj/project.pbxproj b/Source/Rampage.xcodeproj/project.pbxproj index 1fc0fcb..3f429dd 100644 --- a/Source/Rampage.xcodeproj/project.pbxproj +++ b/Source/Rampage.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 0128F26223EEE7AE00439050 /* shotgunFire.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0128F26123EEE7AE00439050 /* shotgunFire.mp3 */; }; + 0128F26423EEEB0A00439050 /* shotgunPickup.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0128F26323EEEB0A00439050 /* shotgunPickup.mp3 */; }; 012A0C4D22C96E150068E8EF /* Tile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A0C4C22C96E150068E8EF /* Tile.swift */; }; 012A0C4F22C96E1F0068E8EF /* Thing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A0C4E22C96E1F0068E8EF /* Thing.swift */; }; 012A0C6222CC200E0068E8EF /* Billboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A0C6022CC200D0068E8EF /* Billboard.swift */; }; @@ -14,7 +16,10 @@ 012A0C9E22D47C220068E8EF /* Actor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A0C9D22D47C220068E8EF /* Actor.swift */; }; 012A0CA222D7AD0A0068E8EF /* Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A0CA122D7AD0A0068E8EF /* Animation.swift */; }; 012DF10822E251CF00D52706 /* Effect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012DF10722E251CF00D52706 /* Effect.swift */; }; + 013D492523ED607D00763FCA /* medkit.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 013D492423ED607D00763FCA /* medkit.mp3 */; }; + 013D492723EE17C000763FCA /* Weapon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 013D492623EE17C000763FCA /* Weapon.swift */; }; 01467C3E22E6F54600B5607D /* Easing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01467C3D22E6F54600B5607D /* Easing.swift */; }; + 0159A3F523DEF636001EEB81 /* Pickup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0159A3F423DEF636001EEB81 /* Pickup.swift */; }; 015A23C9230586E3004CBB78 /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 015A23C8230586E3004CBB78 /* Switch.swift */; }; 016E41B3228E9A5B00ACF137 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016E41B2228E9A5B00ACF137 /* AppDelegate.swift */; }; 016E41B5228E9A5B00ACF137 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016E41B4228E9A5B00ACF137 /* ViewController.swift */; }; @@ -89,6 +94,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0128F26123EEE7AE00439050 /* shotgunFire.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = shotgunFire.mp3; sourceTree = ""; }; + 0128F26323EEEB0A00439050 /* shotgunPickup.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = shotgunPickup.mp3; sourceTree = ""; }; 012A0C4C22C96E150068E8EF /* Tile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tile.swift; sourceTree = ""; }; 012A0C4E22C96E1F0068E8EF /* Thing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Thing.swift; sourceTree = ""; }; 012A0C6022CC200D0068E8EF /* Billboard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Billboard.swift; sourceTree = ""; }; @@ -96,7 +103,10 @@ 012A0C9D22D47C220068E8EF /* Actor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Actor.swift; sourceTree = ""; }; 012A0CA122D7AD0A0068E8EF /* Animation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Animation.swift; sourceTree = ""; }; 012DF10722E251CF00D52706 /* Effect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Effect.swift; sourceTree = ""; }; + 013D492423ED607D00763FCA /* medkit.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = medkit.mp3; sourceTree = ""; }; + 013D492623EE17C000763FCA /* Weapon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Weapon.swift; sourceTree = ""; }; 01467C3D22E6F54600B5607D /* Easing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Easing.swift; sourceTree = ""; }; + 0159A3F423DEF636001EEB81 /* Pickup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pickup.swift; sourceTree = ""; }; 015A23C8230586E3004CBB78 /* Switch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Switch.swift; sourceTree = ""; }; 016E41AF228E9A5B00ACF137 /* Rampage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Rampage.app; sourceTree = BUILT_PRODUCTS_DIR; }; 016E41B2228E9A5B00ACF137 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -219,6 +229,7 @@ 012DF10722E251CF00D52706 /* Effect.swift */, 01D09B0222A4958E0052745A /* Input.swift */, 012A0C6122CC200D0068E8EF /* Monster.swift */, + 0159A3F423DEF636001EEB81 /* Pickup.swift */, 01D09AFA22A485040052745A /* Player.swift */, 01E396392342758D00D02236 /* Pushwall.swift */, 01D09B0422A5C9DB0052745A /* Ray.swift */, @@ -232,6 +243,7 @@ 01D09AFE22A48E990052745A /* Tilemap.swift */, 012A0C4E22C96E1F0068E8EF /* Thing.swift */, 01D09AF822A484B10052745A /* Vector.swift */, + 013D492623EE17C000763FCA /* Weapon.swift */, 01ADC63F22B9846B00DC8AAD /* World.swift */, 016E41CC228E9A8600ACF137 /* Info.plist */, ); @@ -242,6 +254,8 @@ isa = PBXGroup; children = ( 0199F55623E1A517003E3F08 /* pistolFire.mp3 */, + 0128F26123EEE7AE00439050 /* shotgunFire.mp3 */, + 0128F26323EEEB0A00439050 /* shotgunPickup.mp3 */, 0199F55F23E1A517003E3F08 /* monsterGroan.mp3 */, 0199F55523E1A517003E3F08 /* monsterSwipe.mp3 */, 0199F55A23E1A517003E3F08 /* monsterHit.mp3 */, @@ -254,6 +268,7 @@ 0199F55723E1A517003E3F08 /* wallSlide.mp3 */, 0199F56123E1A517003E3F08 /* wallThud.mp3 */, 0199F56023E1A517003E3F08 /* switchFlip.mp3 */, + 013D492423ED607D00763FCA /* medkit.mp3 */, ); path = Sounds; sourceTree = ""; @@ -383,6 +398,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0128F26223EEE7AE00439050 /* shotgunFire.mp3 in Resources */, 0199F56E23E1A517003E3F08 /* wallThud.mp3 in Resources */, 0199F56623E1A517003E3F08 /* playerWalk.mp3 in Resources */, 0199F56C23E1A517003E3F08 /* monsterGroan.mp3 in Resources */, @@ -391,6 +407,7 @@ 0199F56423E1A517003E3F08 /* wallSlide.mp3 in Resources */, 0199F56323E1A517003E3F08 /* pistolFire.mp3 in Resources */, 016E41BA228E9A5E00ACF137 /* Assets.xcassets in Resources */, + 013D492523ED607D00763FCA /* medkit.mp3 in Resources */, 0199F56223E1A517003E3F08 /* monsterSwipe.mp3 in Resources */, 01D09B0122A493A70052745A /* Levels.json in Resources */, 0199F56D23E1A517003E3F08 /* switchFlip.mp3 in Resources */, @@ -400,6 +417,7 @@ 0199F56823E1A517003E3F08 /* squelch.mp3 in Resources */, 0199F56B23E1A517003E3F08 /* playerDeath.mp3 in Resources */, 0199F56923E1A517003E3F08 /* ricochet.mp3 in Resources */, + 0128F26423EEEB0A00439050 /* shotgunPickup.mp3 in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -438,6 +456,7 @@ 012DF10822E251CF00D52706 /* Effect.swift in Sources */, 012A0C6322CC200E0068E8EF /* Monster.swift in Sources */, 01D09B0B22A7F7570052745A /* Textures.swift in Sources */, + 0159A3F523DEF636001EEB81 /* Pickup.swift in Sources */, 015A23C9230586E3004CBB78 /* Switch.swift in Sources */, 01D09AFF22A48E990052745A /* Tilemap.swift in Sources */, 01D09AFD22A4873B0052745A /* Rect.swift in Sources */, @@ -451,6 +470,7 @@ 01D09B0722A6E09B0052745A /* Rotation.swift in Sources */, 01D09AFB22A485040052745A /* Player.swift in Sources */, 012A0C6222CC200E0068E8EF /* Billboard.swift in Sources */, + 013D492723EE17C000763FCA /* Weapon.swift in Sources */, 01ADC64022B9846B00DC8AAD /* World.swift in Sources */, 012A0C4D22C96E150068E8EF /* Tile.swift in Sources */, 01D0F5F122FF095E00682CA1 /* Door.swift in Sources */, diff --git a/Source/Rampage/Assets.xcassets/medkit.imageset/Contents.json b/Source/Rampage/Assets.xcassets/medkit.imageset/Contents.json new file mode 100644 index 0000000..1e20b83 --- /dev/null +++ b/Source/Rampage/Assets.xcassets/medkit.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "medkit.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/medkit.imageset/medkit.png b/Source/Rampage/Assets.xcassets/medkit.imageset/medkit.png new file mode 100644 index 0000000000000000000000000000000000000000..3639fffcf15cf7694529aef14bcfc593e31ee017 GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|%sgEjLo9le z6C_v{C;Vu-y#4>5<7^vNrYfaGe5-Tb^QnTjAyX}dgU#Wa(=|KhJ#h*d3=0hy7}PvG VC6aF3dI~gw!PC{xWt~$(69749Cfxu4 literal 0 HcmV?d00001 diff --git a/Source/Rampage/Assets.xcassets/shotgun.imageset/Contents.json b/Source/Rampage/Assets.xcassets/shotgun.imageset/Contents.json new file mode 100644 index 0000000..af4aac8 --- /dev/null +++ b/Source/Rampage/Assets.xcassets/shotgun.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "shotgun.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/shotgun.imageset/shotgun.png b/Source/Rampage/Assets.xcassets/shotgun.imageset/shotgun.png new file mode 100644 index 0000000000000000000000000000000000000000..27d749e5cbad5e66468a85bb5d6f126388703586 GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^8bGYT!3HD~)>;8c2FBtbcPEB*=VV?2Ia@qk977^n z-(FG_YI2ZZeXzYxuIYuKN(G}(;}J=YB4+)jM1O}HE;m>j6Q0PaO**+jtyEk>mbtzv z{`dWJ_P^888I>SFXkl;Zt%&d1pI3g(uI>6!JaKuJ=InR5*Yv&_ZSgh8PQDvtc2`)N z-6`dg_Bs*oo}Dnq~t&K2luaCQHxi9y`G~T`64Lv sRQ*xqyb71{p1+d6WevWC%PcB*&bc_j%Ob_XHUZ=tPgg&ebxsLQ0CihnYXATM literal 0 HcmV?d00001 diff --git a/Source/Rampage/Assets.xcassets/shotgunFire1.imageset/Contents.json b/Source/Rampage/Assets.xcassets/shotgunFire1.imageset/Contents.json new file mode 100644 index 0000000..a50d884 --- /dev/null +++ b/Source/Rampage/Assets.xcassets/shotgunFire1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "shotgunFire1.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/shotgunFire1.imageset/shotgunFire1.png b/Source/Rampage/Assets.xcassets/shotgunFire1.imageset/shotgunFire1.png new file mode 100644 index 0000000000000000000000000000000000000000..d56967c5ef4e61af1c01ac7bc88beb2804a50f86 GIT binary patch literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^8bGYT!3HD~)>;8c2FBtbcPEB*=VV?2Ilnz!977^n zlM^IZ7bl4HGzA)PxgFGiaTB^b!93rHg%O_0StRL97#GB&~gC&qMJbd85feACGvTna|;-zhaW( z#Ho!B|1M1CX`3|T7n=@?q=bY-#Qfr9(R!fdLhbtx?3sap;b3BPx$E=fc|R9J=Wk|A%xKo~$@m!W26NoFu;hM2;k5UBlziD3v5MQSn2Oc6D;h$#f3 z15q)_517G_EK|iyP22>zaOG&5X1!wWseWJ6=H=ai#bU8oEEbE!QX<Ml#tXhAqs+^iOfT@bq3E=|(d9aMQ9 z3Px$BuPX;R9J=WlcA2nKomvq5UMsISP~2d%_8^#6avLJAixkLYJJkK^22S3<`ESGYctn2J?>UyUnyG_q6~)5ClOG1VLoTZdetM=8v-*Rz;SQ z?0qF2S*Y^6W$K*fS-C95WXj_rfInGzPSdD0!TrzaE_Is$UHlnVR;&t?$3=LBHIwtS ztG0qH$%9bvAWXDo%2ceaSQSyPO_>R+g10qp7V|{TgHV_<(=(hj2X1G|RgZn)*JITWsKnOX-X_8lmC= zakRpBNk8|o1_8i3d>QjN8euZ13Ba-7)c3V-{y#|om<(#-3dy92-d8^dy8r+H07*qo IM6N<$g4UduB>(^b literal 0 HcmV?d00001 diff --git a/Source/Rampage/Assets.xcassets/shotgunFire4.imageset/Contents.json b/Source/Rampage/Assets.xcassets/shotgunFire4.imageset/Contents.json new file mode 100644 index 0000000..0dd5b89 --- /dev/null +++ b/Source/Rampage/Assets.xcassets/shotgunFire4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "shotgunFire4.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/shotgunFire4.imageset/shotgunFire4.png b/Source/Rampage/Assets.xcassets/shotgunFire4.imageset/shotgunFire4.png new file mode 100644 index 0000000000000000000000000000000000000000..f0d282b67316fe703061f3c5e271a4751ba2ff25 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^8bGYT!3HD~)>;8c2FBtbcPEB*=VV?2Ij=ok977^n z-%eV{*AyVqRzF8&{(%fb?M870K@S^d$1dYfTy_j?zgbv>8d(|>o{09GJMt_|DMpx2 zuiS!J-0b}IbM@tA`~O-qI0~?U&>!pVm#6u^z2K;3V(po5Y*DYvUz48!W}3Yh0=hS6 z2+s)2R!VZ#@w4o{ygpJoSI1H?@KABC@3hY9?u|#KPU*ZnqvN+zNBH{`PNrJV!$nIT zy^UO{@L~6oP0}n4&F|~&%ygE24omaY{~Qw?d@o_PP0|Tvvl+UfT(O4&vbSeEYOMO} z6v}erg+pk}#`yAbwOj#)FTcHJg}XLbP0l+XkKRg86w literal 0 HcmV?d00001 diff --git a/Source/Rampage/Assets.xcassets/shotgunPickup.imageset/Contents.json b/Source/Rampage/Assets.xcassets/shotgunPickup.imageset/Contents.json new file mode 100644 index 0000000..f6b4890 --- /dev/null +++ b/Source/Rampage/Assets.xcassets/shotgunPickup.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "shotgunPickup.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/shotgunPickup.imageset/shotgunPickup.png b/Source/Rampage/Assets.xcassets/shotgunPickup.imageset/shotgunPickup.png new file mode 100644 index 0000000000000000000000000000000000000000..1e2bb542328324bce7760b83483027407b453c80 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|GCW-zLo9le z6C_v{Cx{q;fDsU%iQE0xUa@uM!FfFvyeH0_ax!#yd)Aewb-(KVMITP9#U->zH}GB3 z;eE(vBpqcWVfou=&byUK2|#dR%F`z4Ftd+L%3;g}j57`zIG+M4XJOD6lV+Wr-gg*i OCxfS}pUXO@geCw-Sr0?Y*{-haDD3 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

~{t4g=vv4QV1|gI5LKn?8vl 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

F}Kf@dCXMpYM`9*N;hgHoSzO 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 O%b@@F_5Z&r|Gxn1%1+t< literal 0 HcmV?d00001 diff --git a/Source/Rampage/Sounds/shotgunPickup.mp3 b/Source/Rampage/Sounds/shotgunPickup.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..bff323eeddc475af077bbfc26165cf747111a041 GIT binary patch literal 17256 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 xhoQa%5Vs>WWpBFDZFPDO!YtU&& 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 Date: Thu, 13 Feb 2020 08:41:54 +0000 Subject: [PATCH 05/10] Part 15 --- Source/Engine/Door.swift | 9 +- Source/Engine/Monster.swift | 88 ++++++-- Source/Engine/Pathfinder.swift | 87 ++++++++ Source/Engine/Rect.swift | 2 +- .../Engine/{Textures.swift => Texture.swift} | 22 +- Source/Engine/Vector.swift | 2 +- Source/Engine/World.swift | 64 ++++++ Source/Rampage.xcodeproj/project.pbxproj | 201 ++++++++++++++++-- .../xcshareddata/xcschemes/Rampage.xcscheme | 2 +- Source/Rampage/UIImage+Bitmap.swift | 1 + Source/Rampage/ViewController.swift | 1 + Source/RampageTests/RampageTests.swift | 1 + Source/{Engine => Renderer}/Bitmap.swift | 2 + Source/Renderer/Info.plist | 22 ++ Source/{Engine => Renderer}/Renderer.swift | 2 + Source/Renderer/Textures.swift | 27 +++ 16 files changed, 479 insertions(+), 54 deletions(-) create mode 100644 Source/Engine/Pathfinder.swift rename Source/Engine/{Textures.swift => Texture.swift} (64%) rename Source/{Engine => Renderer}/Bitmap.swift (99%) create mode 100644 Source/Renderer/Info.plist rename Source/{Engine => Renderer}/Renderer.swift (99%) create mode 100644 Source/Renderer/Textures.swift diff --git a/Source/Engine/Door.swift b/Source/Engine/Door.swift index d54a9da..de2848f 100644 --- a/Source/Engine/Door.swift +++ b/Source/Engine/Door.swift @@ -37,7 +37,8 @@ public struct Door { public extension Door { var rect: Rect { let position = self.position + direction * (offset - 0.5) - return Rect(min: position, max: position + direction) + let depth = direction.orthogonal * 0.1 + return Rect(min: position + depth, max: position + direction - depth) } var offset: Double { @@ -70,7 +71,11 @@ public extension Door { mutating func update(in world: inout World) { switch state { case .closed: - if world.player.intersection(with: self) != nil { + if world.player.intersection(with: self) != nil || + world.monsters.contains(where: { monster in + monster.isDead == false && + monster.intersection(with: self) != nil + }) { state = .opening world.playSound(.doorSlide, at: position) time = 0 diff --git a/Source/Engine/Monster.swift b/Source/Engine/Monster.swift index 6201249..ffaf759 100644 --- a/Source/Engine/Monster.swift +++ b/Source/Engine/Monster.swift @@ -9,6 +9,7 @@ public enum MonsterState { case idle case chasing + case blocked case scratching case hurt case dead @@ -24,6 +25,7 @@ public struct Monster: Actor { public var animation: Animation = .monsterIdle public let attackCooldown: Double = 0.4 public private(set) var lastAttackTime: Double = 0 + public private(set) var path: [Vector] = [] public init(position: Vector) { self.position = position @@ -38,27 +40,42 @@ public extension Monster { mutating func update(in world: inout World) { switch state { case .idle: - if canSeePlayer(in: world) { + if canSeePlayer(in: world) || canHearPlayer(in: world) { state = .chasing animation = .monsterWalk world.playSound(.monsterGroan, at: position) } case .chasing: - guard canSeePlayer(in: world) else { - state = .idle - animation = .monsterIdle - velocity = Vector(x: 0, y: 0) + if canSeePlayer(in: world) || canHearPlayer(in: world) { + path = world.findPath(from: position, to: world.player.position) + if canReachPlayer(in: world) { + state = .scratching + animation = .monsterScratch + lastAttackTime = -attackCooldown + velocity = Vector(x: 0, y: 0) + break + } + } + guard let destination = path.first else { break } - if canReachPlayer(in: world) { - state = .scratching - animation = .monsterScratch - lastAttackTime = -attackCooldown - velocity = Vector(x: 0, y: 0) + let direction = destination - position + let distance = direction.length + if distance < 0.1 { + path.removeFirst() break } - let direction = world.player.position - position - velocity = direction * (speed / direction.length) + velocity = direction * (speed / distance) + if world.monsters.contains(where: isBlocked(by:)) { + state = .blocked + animation = .monsterBlocked + velocity = Vector(x: 0, y: 0) + } + case .blocked: + if animation.isCompleted { + state = .chasing + animation = .monsterWalk + } case .scratching: guard canReachPlayer(in: world) else { state = .chasing @@ -82,13 +99,47 @@ public extension Monster { } } + func isBlocked(by other: Monster) -> Bool { + // Ignore dead or inactive monsters + if other.isDead || other.state != .chasing { + return false + } + // Ignore if too far away + let direction = other.position - position + let distance = direction.length + if distance > radius + other.radius + 0.5 { + return false + } + // Is standing in the direction we're moving + return (direction / distance).dot(velocity / velocity.length) > 0.5 + } + func canSeePlayer(in world: World) -> Bool { - let direction = world.player.position - position + var direction = world.player.position - position let playerDistance = direction.length - let ray = Ray(origin: position, direction: direction / playerDistance) - let wallHit = world.hitTest(ray) - let wallDistance = (wallHit - position).length - return wallDistance > playerDistance + direction /= playerDistance + let orthogonal = direction.orthogonal + for offset in [-0.2, 0.2] { + let origin = position + orthogonal * offset + let ray = Ray(origin: origin, direction: direction) + let wallHit = world.hitTest(ray) + let wallDistance = (wallHit - position).length + if wallDistance > playerDistance { + return true + } + } + return false + } + + func canHearPlayer(in world: World) -> Bool { + guard world.player.state == .firing else { + return false + } + return world.findPath( + from: position, + to: world.player.position, + maxDistance: 12 + ).isEmpty == false } func canReachPlayer(in world: World) -> Bool { @@ -122,6 +173,9 @@ public extension Animation { static let monsterIdle = Animation(frames: [ .monster ], duration: 0) + static let monsterBlocked = Animation(frames: [ + .monster + ], duration: 1) static let monsterWalk = Animation(frames: [ .monsterWalk1, .monster, diff --git a/Source/Engine/Pathfinder.swift b/Source/Engine/Pathfinder.swift new file mode 100644 index 0000000..b7a1195 --- /dev/null +++ b/Source/Engine/Pathfinder.swift @@ -0,0 +1,87 @@ +// +// Pathfinder.swift +// Engine +// +// Created by Nick Lockwood on 10/02/2020. +// Copyright © 2020 Nick Lockwood. All rights reserved. +// + +import Foundation + +public protocol Graph { + associatedtype Node: Hashable + + func nodesConnectedTo(_ node: Node) -> [Node] + func estimatedDistance(from a: Node, to b: Node) -> Double + func stepDistance(from a: Node, to b: Node) -> Double +} + +private class Path { + let head: Node + let tail: Path? + let distanceTravelled: Double + let totalDistance: Double + + init(head: Node, tail: Path?, stepDistance: Double, remaining: Double) { + self.head = head + self.tail = tail + self.distanceTravelled = (tail?.distanceTravelled ?? 0) + stepDistance + self.totalDistance = distanceTravelled + remaining + } + + var nodes: [Node] { + var nodes = [head] + var tail = self.tail + while let path = tail { + nodes.insert(path.head, at: 0) + tail = path.tail + } + nodes.removeFirst() + return nodes + } +} + +public extension Graph { + func findPath(from start: Node, to end: Node, maxDistance: Double) -> [Node] { + var visited = Set([start]) + var paths = [Path( + head: start, + tail: nil, + stepDistance: 0, + remaining: estimatedDistance(from: start, to: end) + )] + + while let path = paths.popLast() { + // Finish if goal reached + if path.head == end { + return path.nodes + } + + // Get connected nodes + for node in nodesConnectedTo(path.head) where !visited.contains(node) { + visited.insert(node) + let next = Path( + head: node, + tail: path, + stepDistance: stepDistance(from: path.head, to: node), + remaining: estimatedDistance(from: node, to: end) + ) + // Skip this node if max distance exceeded + if next.totalDistance > maxDistance { + break + } + // Insert shortest path last + if let index = paths.firstIndex(where: { + $0.totalDistance <= next.totalDistance + }) { + paths.insert(next, at: index) + } else { + paths.append(next) + } + } + } + + // Unreachable + return [] + } +} diff --git a/Source/Engine/Rect.swift b/Source/Engine/Rect.swift index 753754c..62494d7 100644 --- a/Source/Engine/Rect.swift +++ b/Source/Engine/Rect.swift @@ -7,7 +7,7 @@ // public struct Rect { - var min, max: Vector + public var min, max: Vector public init(min: Vector, max: Vector) { self.min = min diff --git a/Source/Engine/Textures.swift b/Source/Engine/Texture.swift similarity index 64% rename from Source/Engine/Textures.swift rename to Source/Engine/Texture.swift index ae171a5..ccb1022 100644 --- a/Source/Engine/Textures.swift +++ b/Source/Engine/Texture.swift @@ -1,8 +1,8 @@ // -// Textures.swift +// Texture.swift // Engine // -// Created by Nick Lockwood on 05/06/2019. +// Created by Nick Lockwood on 13/02/2020. // Copyright © 2019 Nick Lockwood. All rights reserved. // @@ -29,21 +29,3 @@ public enum Texture: String, CaseIterable { case elevatorFloor, elevatorCeiling, elevatorSideWall, elevatorBackWall case medkit } - -public struct Textures { - private let textures: [Texture: Bitmap] -} - -public extension Textures { - init(loader: (String) -> Bitmap) { - var textures = [Texture: Bitmap]() - for texture in Texture.allCases { - textures[texture] = loader(texture.rawValue) - } - self.init(textures: textures) - } - - subscript(_ texture: Texture) -> Bitmap { - return textures[texture]! - } -} diff --git a/Source/Engine/Vector.swift b/Source/Engine/Vector.swift index 2574477..f9494b7 100644 --- a/Source/Engine/Vector.swift +++ b/Source/Engine/Vector.swift @@ -6,7 +6,7 @@ // Copyright © 2019 Nick Lockwood. All rights reserved. // -public struct Vector: Equatable { +public struct Vector: Hashable { public var x, y: Double public init(x: Double, y: Double) { diff --git a/Source/Engine/World.swift b/Source/Engine/World.swift index ddd6dd4..cfcc6d6 100644 --- a/Source/Engine/World.swift +++ b/Source/Engine/World.swift @@ -333,6 +333,21 @@ public extension World { return map.things[y * map.width + x] == .door } + func door(at x: Int, _ y: Int) -> Door? { + guard isDoor(at: x, y) else { + return nil + } + return doors.first(where: { + Int($0.position.x) == x && Int($0.position.y) == y + }) + } + + func pushwall(at x: Int, _ y: Int) -> Pushwall? { + return pushwalls.first(where: { + Int($0.position.x) == x && Int($0.position.y) == y + }) + } + func `switch`(at x: Int, _ y: Int) -> Switch? { guard map.things[y * map.width + x] == .switch else { return nil @@ -342,3 +357,52 @@ public extension World { }) } } + +extension World: Graph { + public struct Node: Hashable { + public let x, y: Double + + public init(x: Double, y: Double) { + self.x = x.rounded(.down) + 0.5 + self.y = y.rounded(.down) + 0.5 + } + } + + public func findPath( + from start: Vector, + to end: Vector, + maxDistance: Double = 50 + ) -> [Vector] { + return findPath( + from: Node(x: start.x, y: start.y), + to: Node(x: end.x, y: end.y), + maxDistance: maxDistance + ).map { node in + Vector(x: node.x, y: node.y) + } + } + + public func nodesConnectedTo(_ node: Node) -> [Node] { + return [ + Node(x: node.x - 1, y: node.y), + Node(x: node.x + 1, y: node.y), + Node(x: node.x, y: node.y - 1), + Node(x: node.x, y: node.y + 1), + ].filter { node in + let x = Int(node.x), y = Int(node.y) + return map[x, y].isWall == false && pushwall(at: x, y) == nil + } + } + + public func estimatedDistance(from a: Node, to b: Node) -> Double { + return abs(b.x - a.x) + abs(b.y - a.y) + } + + public func stepDistance(from a: Node, to b: Node) -> Double { + let x = Int(b.x), y = Int(b.y) + if door(at: x, y)?.state == .closed { + return 5 + } + return 1 + } +} diff --git a/Source/Rampage.xcodeproj/project.pbxproj b/Source/Rampage.xcodeproj/project.pbxproj index 3f429dd..1a78709 100644 --- a/Source/Rampage.xcodeproj/project.pbxproj +++ b/Source/Rampage.xcodeproj/project.pbxproj @@ -7,6 +7,13 @@ objects = { /* Begin PBXBuildFile section */ + 0108A65E23F4D84C0075E1AF /* Renderer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0108A65723F4D84C0075E1AF /* Renderer.framework */; }; + 0108A65F23F4D84C0075E1AF /* Renderer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0108A65723F4D84C0075E1AF /* Renderer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 0108A66323F4D8E80075E1AF /* Bitmap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AF222A482030052745A /* Bitmap.swift */; }; + 0108A66523F4D8F00075E1AF /* Renderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01ADC63B22B957FD00DC8AAD /* Renderer.swift */; }; + 0108A66723F4D9370075E1AF /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AF022A481AB0052745A /* Color.swift */; }; + 0108A66923F4D9B70075E1AF /* Textures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0108A66823F4D9B70075E1AF /* Textures.swift */; }; + 0108A66F23F543750075E1AF /* Pathfinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0108A66E23F543740075E1AF /* Pathfinder.swift */; }; 0128F26223EEE7AE00439050 /* shotgunFire.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0128F26123EEE7AE00439050 /* shotgunFire.mp3 */; }; 0128F26423EEEB0A00439050 /* shotgunPickup.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0128F26323EEEB0A00439050 /* shotgunPickup.mp3 */; }; 012A0C4D22C96E150068E8EF /* Tile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A0C4C22C96E150068E8EF /* Tile.swift */; }; @@ -43,10 +50,7 @@ 0199F56E23E1A517003E3F08 /* wallThud.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F56123E1A517003E3F08 /* wallThud.mp3 */; }; 0199F57023E1AFEA003E3F08 /* Sounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0199F56F23E1AFEA003E3F08 /* Sounds.swift */; }; 0199F57423E242D4003E3F08 /* SoundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0199F57323E242D4003E3F08 /* SoundManager.swift */; }; - 01ADC63C22B957FD00DC8AAD /* Renderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01ADC63B22B957FD00DC8AAD /* Renderer.swift */; }; 01ADC64022B9846B00DC8AAD /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01ADC63F22B9846B00DC8AAD /* World.swift */; }; - 01D09AF122A481AB0052745A /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AF022A481AB0052745A /* Color.swift */; }; - 01D09AF322A482030052745A /* Bitmap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AF222A482030052745A /* Bitmap.swift */; }; 01D09AF522A482450052745A /* UIImage+Bitmap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AF422A482450052745A /* UIImage+Bitmap.swift */; }; 01D09AF922A484B10052745A /* Vector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AF822A484B10052745A /* Vector.swift */; }; 01D09AFB22A485040052745A /* Player.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AFA22A485040052745A /* Player.swift */; }; @@ -56,13 +60,27 @@ 01D09B0322A4958E0052745A /* Input.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09B0222A4958E0052745A /* Input.swift */; }; 01D09B0522A5C9DB0052745A /* Ray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09B0422A5C9DB0052745A /* Ray.swift */; }; 01D09B0722A6E09B0052745A /* Rotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09B0622A6E09A0052745A /* Rotation.swift */; }; - 01D09B0B22A7F7570052745A /* Textures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09B0A22A7F7570052745A /* Textures.swift */; }; + 01D09B0B22A7F7570052745A /* Texture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09B0A22A7F7570052745A /* Texture.swift */; }; 01D0F5D922F80E1600682CA1 /* RampageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D0F5D822F80E1600682CA1 /* RampageTests.swift */; }; 01D0F5F122FF095E00682CA1 /* Door.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D0F5F022FF095E00682CA1 /* Door.swift */; }; 01E3963A2342758D00D02236 /* Pushwall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01E396392342758D00D02236 /* Pushwall.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 0108A65C23F4D84C0075E1AF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 016E41A7228E9A5B00ACF137 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0108A65623F4D84C0075E1AF; + remoteInfo = Renderer; + }; + 0108A66C23F4DA5D0075E1AF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 016E41A7228E9A5B00ACF137 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 016E41C8228E9A8600ACF137; + remoteInfo = Engine; + }; 016E41CE228E9A8600ACF137 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 016E41A7228E9A5B00ACF137 /* Project object */; @@ -87,6 +105,7 @@ dstSubfolderSpec = 10; files = ( 016E41D1228E9A8600ACF137 /* Engine.framework in Embed Frameworks */, + 0108A65F23F4D84C0075E1AF /* Renderer.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -94,6 +113,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0108A65723F4D84C0075E1AF /* Renderer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Renderer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0108A65A23F4D84C0075E1AF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0108A66823F4D9B70075E1AF /* Textures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Textures.swift; sourceTree = ""; }; + 0108A66E23F543740075E1AF /* Pathfinder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Pathfinder.swift; sourceTree = ""; }; 0128F26123EEE7AE00439050 /* shotgunFire.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = shotgunFire.mp3; sourceTree = ""; }; 0128F26323EEEB0A00439050 /* shotgunPickup.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = shotgunPickup.mp3; sourceTree = ""; }; 012A0C4C22C96E150068E8EF /* Tile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tile.swift; sourceTree = ""; }; @@ -145,7 +168,7 @@ 01D09B0222A4958E0052745A /* Input.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Input.swift; sourceTree = ""; }; 01D09B0422A5C9DB0052745A /* Ray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ray.swift; sourceTree = ""; }; 01D09B0622A6E09A0052745A /* Rotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Rotation.swift; sourceTree = ""; }; - 01D09B0A22A7F7570052745A /* Textures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Textures.swift; sourceTree = ""; }; + 01D09B0A22A7F7570052745A /* Texture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Texture.swift; sourceTree = ""; }; 01D0F5D622F80E1600682CA1 /* RampageTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RampageTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 01D0F5D822F80E1600682CA1 /* RampageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RampageTests.swift; sourceTree = ""; }; 01D0F5DA22F80E1600682CA1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -154,11 +177,19 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 0108A65423F4D84C0075E1AF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 016E41AC228E9A5B00ACF137 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 016E41D0228E9A8600ACF137 /* Engine.framework in Frameworks */, + 0108A65E23F4D84C0075E1AF /* Renderer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -179,13 +210,33 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0108A65823F4D84C0075E1AF /* Renderer */ = { + isa = PBXGroup; + children = ( + 01D09AF222A482030052745A /* Bitmap.swift */, + 01ADC63B22B957FD00DC8AAD /* Renderer.swift */, + 0108A66823F4D9B70075E1AF /* Textures.swift */, + 0108A65A23F4D84C0075E1AF /* Info.plist */, + ); + path = Renderer; + sourceTree = ""; + }; + 0108A66A23F4DA580075E1AF /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; 016E41A6228E9A5B00ACF137 = { isa = PBXGroup; children = ( 016E41B1228E9A5B00ACF137 /* Rampage */, 016E41CA228E9A8600ACF137 /* Engine */, + 0108A65823F4D84C0075E1AF /* Renderer */, 01D0F5D722F80E1600682CA1 /* RampageTests */, 016E41B0228E9A5B00ACF137 /* Products */, + 0108A66A23F4DA580075E1AF /* Frameworks */, ); sourceTree = ""; }; @@ -195,6 +246,7 @@ 016E41AF228E9A5B00ACF137 /* Rampage.app */, 016E41C9228E9A8600ACF137 /* Engine.framework */, 01D0F5D622F80E1600682CA1 /* RampageTests.xctest */, + 0108A65723F4D84C0075E1AF /* Renderer.framework */, ); name = Products; sourceTree = ""; @@ -222,23 +274,22 @@ 012A0C9D22D47C220068E8EF /* Actor.swift */, 012A0CA122D7AD0A0068E8EF /* Animation.swift */, 012A0C6022CC200D0068E8EF /* Billboard.swift */, - 01D09AF222A482030052745A /* Bitmap.swift */, 01D09AF022A481AB0052745A /* Color.swift */, 01D0F5F022FF095E00682CA1 /* Door.swift */, 01467C3D22E6F54600B5607D /* Easing.swift */, 012DF10722E251CF00D52706 /* Effect.swift */, 01D09B0222A4958E0052745A /* Input.swift */, 012A0C6122CC200D0068E8EF /* Monster.swift */, + 0108A66E23F543740075E1AF /* Pathfinder.swift */, 0159A3F423DEF636001EEB81 /* Pickup.swift */, 01D09AFA22A485040052745A /* Player.swift */, 01E396392342758D00D02236 /* Pushwall.swift */, 01D09B0422A5C9DB0052745A /* Ray.swift */, 01D09AFC22A4873B0052745A /* Rect.swift */, - 01ADC63B22B957FD00DC8AAD /* Renderer.swift */, 01D09B0622A6E09A0052745A /* Rotation.swift */, 015A23C8230586E3004CBB78 /* Switch.swift */, - 01D09B0A22A7F7570052745A /* Textures.swift */, 0199F56F23E1AFEA003E3F08 /* Sounds.swift */, + 01D09B0A22A7F7570052745A /* Texture.swift */, 012A0C4C22C96E150068E8EF /* Tile.swift */, 01D09AFE22A48E990052745A /* Tilemap.swift */, 012A0C4E22C96E1F0068E8EF /* Thing.swift */, @@ -285,6 +336,13 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 0108A65223F4D84C0075E1AF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 016E41C4228E9A8600ACF137 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -295,6 +353,25 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 0108A65623F4D84C0075E1AF /* Renderer */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0108A66223F4D84C0075E1AF /* Build configuration list for PBXNativeTarget "Renderer" */; + buildPhases = ( + 0108A65223F4D84C0075E1AF /* Headers */, + 0108A65323F4D84C0075E1AF /* Sources */, + 0108A65423F4D84C0075E1AF /* Frameworks */, + 0108A65523F4D84C0075E1AF /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 0108A66D23F4DA5D0075E1AF /* PBXTargetDependency */, + ); + name = Renderer; + productName = Renderer; + productReference = 0108A65723F4D84C0075E1AF /* Renderer.framework */; + productType = "com.apple.product-type.framework"; + }; 016E41AE228E9A5B00ACF137 /* Rampage */ = { isa = PBXNativeTarget; buildConfigurationList = 016E41C1228E9A5E00ACF137 /* Build configuration list for PBXNativeTarget "Rampage" */; @@ -308,6 +385,7 @@ ); dependencies = ( 016E41CF228E9A8600ACF137 /* PBXTargetDependency */, + 0108A65D23F4D84C0075E1AF /* PBXTargetDependency */, ); name = Rampage; productName = Rampage; @@ -356,10 +434,14 @@ 016E41A7228E9A5B00ACF137 /* Project object */ = { isa = PBXProject; attributes = { + DefaultBuildSystemTypeForWorkspace = Original; LastSwiftUpdateCheck = 1010; LastUpgradeCheck = 1010; ORGANIZATIONNAME = "Nick Lockwood"; TargetAttributes = { + 0108A65623F4D84C0075E1AF = { + CreatedOnToolsVersion = 11.3.1; + }; 016E41AE228E9A5B00ACF137 = { CreatedOnToolsVersion = 10.1; }; @@ -388,12 +470,20 @@ targets = ( 016E41AE228E9A5B00ACF137 /* Rampage */, 016E41C8228E9A8600ACF137 /* Engine */, + 0108A65623F4D84C0075E1AF /* Renderer */, 01D0F5D522F80E1600682CA1 /* RampageTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 0108A65523F4D84C0075E1AF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 016E41AD228E9A5B00ACF137 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -438,6 +528,16 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 0108A65323F4D84C0075E1AF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0108A66323F4D8E80075E1AF /* Bitmap.swift in Sources */, + 0108A66923F4D9B70075E1AF /* Textures.swift in Sources */, + 0108A66523F4D8F00075E1AF /* Renderer.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 016E41AB228E9A5B00ACF137 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -455,27 +555,26 @@ files = ( 012DF10822E251CF00D52706 /* Effect.swift in Sources */, 012A0C6322CC200E0068E8EF /* Monster.swift in Sources */, - 01D09B0B22A7F7570052745A /* Textures.swift in Sources */, + 01D09B0B22A7F7570052745A /* Texture.swift in Sources */, 0159A3F523DEF636001EEB81 /* Pickup.swift in Sources */, 015A23C9230586E3004CBB78 /* Switch.swift in Sources */, 01D09AFF22A48E990052745A /* Tilemap.swift in Sources */, 01D09AFD22A4873B0052745A /* Rect.swift in Sources */, - 01ADC63C22B957FD00DC8AAD /* Renderer.swift in Sources */, 0199F57023E1AFEA003E3F08 /* Sounds.swift in Sources */, 012A0C9E22D47C220068E8EF /* Actor.swift in Sources */, 012A0C4F22C96E1F0068E8EF /* Thing.swift in Sources */, 01D09AF922A484B10052745A /* Vector.swift in Sources */, - 01D09AF322A482030052745A /* Bitmap.swift in Sources */, 01467C3E22E6F54600B5607D /* Easing.swift in Sources */, 01D09B0722A6E09B0052745A /* Rotation.swift in Sources */, 01D09AFB22A485040052745A /* Player.swift in Sources */, 012A0C6222CC200E0068E8EF /* Billboard.swift in Sources */, 013D492723EE17C000763FCA /* Weapon.swift in Sources */, 01ADC64022B9846B00DC8AAD /* World.swift in Sources */, + 0108A66723F4D9370075E1AF /* Color.swift in Sources */, 012A0C4D22C96E150068E8EF /* Tile.swift in Sources */, 01D0F5F122FF095E00682CA1 /* Door.swift in Sources */, + 0108A66F23F543750075E1AF /* Pathfinder.swift in Sources */, 01D09B0322A4958E0052745A /* Input.swift in Sources */, - 01D09AF122A481AB0052745A /* Color.swift in Sources */, 012A0CA222D7AD0A0068E8EF /* Animation.swift in Sources */, 01D09B0522A5C9DB0052745A /* Ray.swift in Sources */, 01E3963A2342758D00D02236 /* Pushwall.swift in Sources */, @@ -493,6 +592,16 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 0108A65D23F4D84C0075E1AF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0108A65623F4D84C0075E1AF /* Renderer */; + targetProxy = 0108A65C23F4D84C0075E1AF /* PBXContainerItemProxy */; + }; + 0108A66D23F4DA5D0075E1AF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 016E41C8228E9A8600ACF137 /* Engine */; + targetProxy = 0108A66C23F4DA5D0075E1AF /* PBXContainerItemProxy */; + }; 016E41CF228E9A8600ACF137 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 016E41C8228E9A8600ACF137 /* Engine */; @@ -525,6 +634,65 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 0108A66023F4D84C0075E1AF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 8VQKF583ED; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Renderer/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.Renderer; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_DISABLE_SAFETY_CHECKS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 0108A66123F4D84C0075E1AF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 8VQKF583ED; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Renderer/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.Renderer; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_DISABLE_SAFETY_CHECKS = YES; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; 016E41BF228E9A5E00ACF137 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -784,6 +952,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 0108A66223F4D84C0075E1AF /* Build configuration list for PBXNativeTarget "Renderer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0108A66023F4D84C0075E1AF /* Debug */, + 0108A66123F4D84C0075E1AF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 016E41AA228E9A5B00ACF137 /* Build configuration list for PBXProject "Rampage" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Rampage.xcscheme b/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Rampage.xcscheme index edd97b6..ce33339 100644 --- a/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Rampage.xcscheme +++ b/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Rampage.xcscheme @@ -50,7 +50,7 @@ + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/Source/Engine/Renderer.swift b/Source/Renderer/Renderer.swift similarity index 99% rename from Source/Engine/Renderer.swift rename to Source/Renderer/Renderer.swift index 6363828..a1fa8e8 100644 --- a/Source/Engine/Renderer.swift +++ b/Source/Renderer/Renderer.swift @@ -6,6 +6,8 @@ // Copyright © 2019 Nick Lockwood. All rights reserved. // +import Engine + private let fizzle = (0 ..< 10000).shuffled() public struct Renderer { diff --git a/Source/Renderer/Textures.swift b/Source/Renderer/Textures.swift new file mode 100644 index 0000000..bd952b7 --- /dev/null +++ b/Source/Renderer/Textures.swift @@ -0,0 +1,27 @@ +// +// Textures.swift +// Renderer +// +// Created by Nick Lockwood on 05/06/2019. +// Copyright © 2020 Nick Lockwood. All rights reserved. +// + +import Engine + +public struct Textures { + private let textures: [Texture: Bitmap] +} + +public extension Textures { + init(loader: (String) -> Bitmap) { + var textures = [Texture: Bitmap]() + for texture in Texture.allCases { + textures[texture] = loader(texture.rawValue) + } + self.init(textures: textures) + } + + subscript(_ texture: Texture) -> Bitmap { + return textures[texture]! + } +} From 93977d7ebf3697f2f57c20a3c61da73294e05252 Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Sat, 25 Apr 2020 12:36:01 +0100 Subject: [PATCH 06/10] Part 16 --- Source/Engine/Color.swift | 7 +-- Source/Engine/Texture.swift | 4 ++ Source/Engine/Weapon.swift | 7 ++- .../crosshair.imageset/Contents.json | 21 +++++++ .../crosshair.imageset/crosshair.png | Bin 0 -> 1077 bytes .../font.imageset/Contents.json | 21 +++++++ .../Assets.xcassets/font.imageset/font.png | Bin 0 -> 1043 bytes .../healthIcon.imageset/Contents.json | 21 +++++++ .../healthIcon.imageset/healthIcon.png | Bin 0 -> 144 bytes .../pistolIcon.imageset/Contents.json | 21 +++++++ .../pistolIcon.imageset/pistolIcon.png | Bin 0 -> 997 bytes .../shotgunIcon.imageset/Contents.json | 21 +++++++ .../shotgunIcon.imageset/shotgunIcon.png | Bin 0 -> 165 bytes Source/Rampage/Info.plist | 5 +- Source/Rampage/ViewController.swift | 13 ++++ Source/Renderer/Bitmap.swift | 45 +++++++++++--- Source/Renderer/Renderer.swift | 57 ++++++++++++++++++ 17 files changed, 228 insertions(+), 15 deletions(-) create mode 100644 Source/Rampage/Assets.xcassets/crosshair.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/crosshair.imageset/crosshair.png create mode 100644 Source/Rampage/Assets.xcassets/font.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/font.imageset/font.png create mode 100644 Source/Rampage/Assets.xcassets/healthIcon.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/healthIcon.imageset/healthIcon.png create mode 100644 Source/Rampage/Assets.xcassets/pistolIcon.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/pistolIcon.imageset/pistolIcon.png create mode 100644 Source/Rampage/Assets.xcassets/shotgunIcon.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/shotgunIcon.imageset/shotgunIcon.png diff --git a/Source/Engine/Color.swift b/Source/Engine/Color.swift index b0b590f..6081eee 100644 --- a/Source/Engine/Color.swift +++ b/Source/Engine/Color.swift @@ -25,8 +25,7 @@ public extension Color { static let clear = Color(r: 0, g: 0, b: 0, a: 0) static let black = Color(r: 0, g: 0, b: 0) static let white = Color(r: 255, g: 255, b: 255) - static let gray = Color(r: 192, g: 192, b: 192) - static let red = Color(r: 255, g: 0, b: 0) - static let green = Color(r: 0, g: 255, b: 0) - static let blue = Color(r: 0, g: 0, b: 255) + static let red = Color(r: 217, g: 87, b: 99) + static let green = Color(r: 153, g: 229, b: 80) + static let yellow = Color(r: 251, g: 242, b: 54) } diff --git a/Source/Engine/Texture.swift b/Source/Engine/Texture.swift index ccb1022..f94dbb8 100644 --- a/Source/Engine/Texture.swift +++ b/Source/Engine/Texture.swift @@ -28,4 +28,8 @@ public enum Texture: String, CaseIterable { case switch1, switch2, switch3, switch4 case elevatorFloor, elevatorCeiling, elevatorSideWall, elevatorBackWall case medkit + case crosshair + case healthIcon + case pistolIcon, shotgunIcon + case font } diff --git a/Source/Engine/Weapon.swift b/Source/Engine/Weapon.swift index a778a50..878e7fe 100644 --- a/Source/Engine/Weapon.swift +++ b/Source/Engine/Weapon.swift @@ -21,6 +21,7 @@ public extension Weapon { let projectiles: Int let spread: Double let defaultAmmo: Double + public let hudIcon: Texture } var attributes: Attributes { @@ -34,7 +35,8 @@ public extension Weapon { cooldown: 0.25, projectiles: 1, spread: 0, - defaultAmmo: .infinity + defaultAmmo: .infinity, + hudIcon: .pistolIcon ) case .shotgun: return Attributes( @@ -45,7 +47,8 @@ public extension Weapon { cooldown: 0.5, projectiles: 5, spread: 0.4, - defaultAmmo: 5 + defaultAmmo: 10, + hudIcon: .shotgunIcon ) } } diff --git a/Source/Rampage/Assets.xcassets/crosshair.imageset/Contents.json b/Source/Rampage/Assets.xcassets/crosshair.imageset/Contents.json new file mode 100644 index 0000000..66e65dc --- /dev/null +++ b/Source/Rampage/Assets.xcassets/crosshair.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "crosshair.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/crosshair.imageset/crosshair.png b/Source/Rampage/Assets.xcassets/crosshair.imageset/crosshair.png new file mode 100644 index 0000000000000000000000000000000000000000..a3e9ce77c81d8eff4b96621707b79459bbd16b5a GIT binary patch literal 1077 zcmbVLJ8aWH7&a=cXd!fBpaWdpg;)HFmyVq!z=pfd1~0Krm~a~_4EDiW6MyZi6|zW;rFdg^p+Xk>_@ zs90fAE0J}Od_#K%$iLQ)pOfVv&R6g(s^O;LLrS$!6@r3e%)=5itk&WhOjA@}-7Z&f zrFd2`k;52~4ih>aK~q$EBJ>P%0b)>v^R}CzzdT!|fo)~z^T{Gt^m4FnPcHj#c6q97 zE-#p}MNgar=};jA4#WlsorW7IVTNw=Dr6stSsJue@Ir>}I8`Z5gB=w1M_wt;i%L>bgmKV)XkyK`YD!7dySB(FL)S6(6qao^n@lsoAb+0a zWm%3m1R+i|;z7&BMi_U4u^xj41Jk!XY$F#$j7AkL;S5bY?S$ZX#o`vR8*~#zQpSdc z$MOuvI!+WDfX}hH^7E#!k%55*zIByJ7Sfb4-Jg`GD3}B2Ta!yMnN5UAU7+4 zBSpis-AHgWDo`h04f^&aXz4z3Ks&>Vy^RO|j=Y1l{wHfJafXfBvqIkH!_IL3^5K-_V;!D?d9y&vk_uj|%`+dLf&zl|^ zJl@{AzZJu<_SArwMr$|vnp>LD|6z9h2wFN}A`6GjF<6pqfW=ia2k?|G=Rq3C>eR#v zh+$aMAuW@IS?Ls~n0i3=d;+d+AvA`?`dmv^iU8s{kk<^J_%^>t;F`)4BVmb>ECCd> zfwB#T%YzxETvVbe(RU1wxf~+U0hDo9A2%G%<%tR}hxVSCB=Cw0Eb_#bsH`-E3#JY5 zaDeeE6iwqS8=ymBmZf{}AVmjB3cakK4sl_Y3r6tjL!fB3I>x2NWHlB#@k9YaizCTW zsT3$N0n^TtbTk_EID$bx^6)!T29#aD;dIp)MBpg4WWnUjzwkkYLbbgNEl zIMp(tf|0Ilk#vCaQmQ#h(*Ip`z3%P6G}zYLkl4vgS%6Ff$DFhk)VQ%OFOh%$2~DS9TDUOG;@y(0XohDvTtP?@mogkE8wyB?Jb^d@nx=A0vX_bUhT@S( zC`!|bcrQzbgoqfVk_mxf;&crwn#!aO3|Pae+t~gcvEDG~7K$taTe|?%q;2YWC23A; zpd}m+g_9IRBR;0FmMyH>KuZ-H+!0G6F{Ibpe_CBLq51K)^}$7l`sf1#&AW{TyY2hR zIJy*9Qer&guH8;gw_l=KdTuV~cYVBw<*948Mt%Eoo1LWgYU#}N;-)&Yd--IPK9T+v zo8|e}cfbC4diME?mkNKLcr^Ru&&*X}^}+g`8=sYXM}L2@7w6urzW3n{HqkNh?A_^& z14VmbypR34XYJF$a&F$gB&ZuBM$_H}r}gbQUmKQr{9&%cm!rLFno10c_xndL{{^m4 BQ`7(e literal 0 HcmV?d00001 diff --git a/Source/Rampage/Assets.xcassets/healthIcon.imageset/Contents.json b/Source/Rampage/Assets.xcassets/healthIcon.imageset/Contents.json new file mode 100644 index 0000000..7416da1 --- /dev/null +++ b/Source/Rampage/Assets.xcassets/healthIcon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "healthIcon.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/Source/Rampage/Assets.xcassets/healthIcon.imageset/healthIcon.png b/Source/Rampage/Assets.xcassets/healthIcon.imageset/healthIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..6590aada8fba6b2669d152fc05a64ada515dd8cd GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*XJ3i-X*q7}lMWc?slrdAc};aLkPD z*~oi9L4f&vq?+w!mn4Q~NeoNQICX_|B>H?6d~nJx+HKN23Dyh2|Mq^Ja&+NpF>dve q*8DxvA95J}aTjb)yIrKqsJ4_@a?h{8b<=>RGI+ZBxvXlKi{pw___YR z!9I$j`txIIk*vMs>*?(w|K0BG9kLw7*)pC$)3~mCkV>1V3PIl1XJ8TP=HjI-n4+kz z6IQ8=%i4L#KsKX?7$&e?!ltOyXyEF`EX1G+XDmmizpp>1fo00{WJ2RKSAjKaY{`QY zOXDSDY1R-;dh{$v1riakA=W`)&pEyn$aF(jBKy$H(x3ssvogIGR9Pzk1$hu8m{`Q% zcpeA>!^abXz@Gt8j*qe&d4&icmlA>$O@ih_6K|e5Efv*V(-%3(bPZ!yV%d7V&eUTJ z@@80G6va>@8jTP{#9wr<9z+~}sHLDn-|#FKTgU;SqFzPwSf)v&dnwp%Th{TLWg-P* z1KnkLh6___0X6OaP}^>!eO!e5@%~fTFD<%|EkYm7dj@IT^ib%^l@t%^75Wq=IH!LSKoN6#MP0Bky)*S=pRhcFljAfY;FJ{zuj8l^%ioo;PbS9eP zm2{R9MIk+sNyJ-R6&dq3ba0Dn?sKypx#2L_F7d2F&sun z{PM=#L-#(dZLGeC58OPk3GNJj+xod%7~cG0y*-k?oHH-puT-YK94s1H|;y<53(@KJd2^4W3qNoMN$ACB2U761SM literal 0 HcmV?d00001 diff --git a/Source/Rampage/Assets.xcassets/shotgunIcon.imageset/Contents.json b/Source/Rampage/Assets.xcassets/shotgunIcon.imageset/Contents.json new file mode 100644 index 0000000..cd1baff --- /dev/null +++ b/Source/Rampage/Assets.xcassets/shotgunIcon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "shotgunIcon.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/Source/Rampage/Assets.xcassets/shotgunIcon.imageset/shotgunIcon.png b/Source/Rampage/Assets.xcassets/shotgunIcon.imageset/shotgunIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..5e7531ba6a41e75676f8e3574e5f01920d07103a GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngc!3HE{ZXRg@QjEnx?oJHr&dIz4a^gK*9780g zCMPUlFgO>t`>(yC>&k=kdLm5I(^3~^gjE*{I$z8`xnASXrcQAQNeKxF10SEwCN0v( zaxzXPJb81vVAt}lMj&tup2nRQaPtUvPsH42-UB?Xk_?;Y<}fgD%#vn}owgk05C%_I KKbLh*2~7a~&NprV literal 0 HcmV?d00001 diff --git a/Source/Rampage/Info.plist b/Source/Rampage/Info.plist index 16be3b6..ea73a0f 100644 --- a/Source/Rampage/Info.plist +++ b/Source/Rampage/Info.plist @@ -28,9 +28,12 @@ armv7 + UIRequiresFullScreen + + UIStatusBarHidden + UISupportedInterfaceOrientations - UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight diff --git a/Source/Rampage/ViewController.swift b/Source/Rampage/ViewController.swift index dc369b7..28e78cc 100644 --- a/Source/Rampage/ViewController.swift +++ b/Source/Rampage/ViewController.swift @@ -72,6 +72,14 @@ class ViewController: UIViewController { tapGesture.delegate = self } + override var supportedInterfaceOrientations: UIInterfaceOrientationMask { + return .landscape + } + + override var prefersStatusBarHidden: Bool { + return true + } + private var inputVector: Vector { switch panGesture.state { case .began, .changed: @@ -129,6 +137,11 @@ class ViewController: UIViewController { let width = Int(imageView.bounds.width), height = Int(imageView.bounds.height) var renderer = Renderer(width: width, height: height, textures: textures) + let insets = self.view.safeAreaInsets + renderer.safeArea = Rect( + min: Vector(x: Double(insets.left), y: Double(insets.top)), + max: renderer.bitmap.size - Vector(x: Double(insets.left), y: Double(insets.bottom)) + ) renderer.draw(world) imageView.image = UIImage(bitmap: renderer.bitmap) diff --git a/Source/Renderer/Bitmap.swift b/Source/Renderer/Bitmap.swift index 5022192..8286100 100644 --- a/Source/Renderer/Bitmap.swift +++ b/Source/Renderer/Bitmap.swift @@ -22,6 +22,10 @@ public struct Bitmap { } public extension Bitmap { + var size: Vector { + return Vector(x: Double(width), y: Double(height)) + } + subscript(x: Int, y: Int) -> Color { get { return pixels[x * height + y] } set { @@ -69,32 +73,57 @@ public extension Bitmap { } } - mutating func drawColumn(_ sourceX: Int, of source: Bitmap, at point: Vector, height: Double) { + mutating func drawColumn( + _ sourceX: Int, + of source: Bitmap, + at point: Vector, + height: Double, + tint: Color? = nil + ) { let start = Int(point.y), end = Int((point.y + height).rounded(.up)) let stepY = Double(source.height) / height let offset = Int(point.x) * self.height if source.isOpaque { for y in max(0, start) ..< min(self.height, end) { let sourceY = max(0, Double(y) - point.y) * stepY - let sourceColor = source[sourceX, Int(sourceY)] + var sourceColor = source[sourceX, Int(sourceY)] + if let tint = tint { + sourceColor.r = UInt8(UInt16(sourceColor.r) * UInt16(tint.r) / 255) + sourceColor.g = UInt8(UInt16(sourceColor.g) * UInt16(tint.g) / 255) + sourceColor.b = UInt8(UInt16(sourceColor.b) * UInt16(tint.b) / 255) + sourceColor.a = UInt8(UInt16(sourceColor.a) * UInt16(tint.a) / 255) + } pixels[offset + y] = sourceColor } } else { for y in max(0, start) ..< min(self.height, end) { let sourceY = max(0, Double(y) - point.y) * stepY - let sourceColor = source[sourceX, Int(sourceY)] + var sourceColor = source[sourceX, Int(sourceY)] + if let tint = tint { + sourceColor.r = UInt8(UInt16(sourceColor.r) * UInt16(tint.r) / 255) + sourceColor.g = UInt8(UInt16(sourceColor.g) * UInt16(tint.g) / 255) + sourceColor.b = UInt8(UInt16(sourceColor.b) * UInt16(tint.b) / 255) + sourceColor.a = UInt8(UInt16(sourceColor.a) * UInt16(tint.a) / 255) + } blendPixel(at: offset + y, with: sourceColor) } } } - mutating func drawImage(_ source: Bitmap, at point: Vector, size: Vector) { + mutating func drawImage( + _ source: Bitmap, + xRange: Range? = nil, + at point: Vector, + size: Vector, + tint: Color? = nil + ) { + let xRange = xRange ?? 0 ..< source.width let start = Int(point.x), end = Int(point.x + size.x) - let stepX = Double(source.width) / size.x - for x in max(0, start) ..< min(width, end) { - let sourceX = (Double(x) - point.x) * stepX + let stepX = Double(xRange.count) / size.x + for x in max(0, start) ..< max(0, start, min(width, end)) { + let sourceX = Int(max(0, Double(x) - point.x) * stepX) + xRange.lowerBound let outputPosition = Vector(x: Double(x), y: point.y) - drawColumn(Int(sourceX), of: source, at: outputPosition, height: size.y) + drawColumn(sourceX, of: source, at: outputPosition, height: size.y, tint: tint) } } diff --git a/Source/Renderer/Renderer.swift b/Source/Renderer/Renderer.swift index a1fa8e8..12d1fb0 100644 --- a/Source/Renderer/Renderer.swift +++ b/Source/Renderer/Renderer.swift @@ -13,10 +13,12 @@ private let fizzle = (0 ..< 10000).shuffled() public struct Renderer { public private(set) var bitmap: Bitmap private let textures: Textures + public var safeArea: Rect public init(width: Int, height: Int, textures: Textures) { self.bitmap = Bitmap(width: width, height: height, color: .black) self.textures = textures + self.safeArea = Rect(min: Vector(x: 0, y: 0), max: bitmap.size) } } @@ -134,6 +136,61 @@ public extension Renderer { size: Vector(x: weaponWidth, y: screenHeight) ) + // Crosshair + let crosshair = textures[.crosshair] + let hudScale = bitmap.size.y / 64 + let crosshairSize = crosshair.size * hudScale + bitmap.drawImage(crosshair, at: (bitmap.size - crosshairSize) / 2, size: crosshairSize) + + // Health icon + let healthIcon = textures[.healthIcon] + var offset = safeArea.min + Vector(x: 1, y: 1) * hudScale + bitmap.drawImage(healthIcon, at: offset, size: healthIcon.size * hudScale) + offset.x += healthIcon.size.x * hudScale + + // Health + let font = textures[.font] + let charSize = Vector(x: font.size.x / 10, y: font.size.y) + let health = Int(max(0, world.player.health)) + let healthTint: Color + switch health { + case ...10: + healthTint = .red + case 10 ... 30: + healthTint = .yellow + default: + healthTint = .green + } + for char in String(health) { + let index = Int(char.asciiValue!) - 48 + let step = Int(charSize.x) + let xRange = index * step ..< (index + 1) * step + bitmap.drawImage( + font, + xRange: xRange, + at: offset, + size: charSize * hudScale, + tint: healthTint + ) + offset.x += charSize.x * hudScale + } + + // Ammunition + offset.x = safeArea.max.x + let ammo = Int(max(0, min(99, world.player.ammo))) + for char in String(ammo).reversed() { + let index = Int(char.asciiValue!) - 48 + let step = Int(charSize.x) + let xRange = index * step ..< (index + 1) * step + offset.x -= charSize.x * hudScale + bitmap.drawImage(font, xRange: xRange, at: offset, size: charSize * hudScale) + } + + // Weapon icon + let weaponIcon = textures[world.player.weapon.attributes.hudIcon] + offset.x -= weaponIcon.size.x * hudScale + bitmap.drawImage(weaponIcon, at: offset, size: weaponIcon.size * hudScale) + // Effects for effect in world.effects { switch effect.type { From ad697f405586662a834dc70025307ca1ba9c04e4 Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Sun, 3 May 2020 17:31:45 +0100 Subject: [PATCH 07/10] Part 17 --- Source/Engine/Font.swift | 12 ++ Source/Engine/Game.swift | 78 +++++++++++ Source/Engine/HUD.swift | 33 +++++ Source/Engine/Texture.swift | 3 +- Source/Rampage.xcodeproj/project.pbxproj | 45 +++++-- .../xcshareddata/xcschemes/Engine.xcscheme | 6 +- .../xcshareddata/xcschemes/Rampage.xcscheme | 2 +- .../Assets.xcassets/font.imageset/font.png | Bin 1043 -> 1219 bytes .../titleBackground.imageset/Contents.json | 21 +++ .../titleBackground.png | Bin 0 -> 94226 bytes .../titleLogo.imageset/Contents.json | 21 +++ .../titleLogo.imageset/titleLogo.png | Bin 0 -> 2492 bytes Source/Rampage/Font.json | 9 ++ Source/Rampage/ViewController.swift | 75 ++++++----- Source/Renderer/Renderer.swift | 126 ++++++++++++------ 15 files changed, 335 insertions(+), 96 deletions(-) create mode 100644 Source/Engine/Font.swift create mode 100644 Source/Engine/Game.swift create mode 100644 Source/Engine/HUD.swift create mode 100644 Source/Rampage/Assets.xcassets/titleBackground.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/titleBackground.imageset/titleBackground.png create mode 100644 Source/Rampage/Assets.xcassets/titleLogo.imageset/Contents.json create mode 100644 Source/Rampage/Assets.xcassets/titleLogo.imageset/titleLogo.png create mode 100644 Source/Rampage/Font.json diff --git a/Source/Engine/Font.swift b/Source/Engine/Font.swift new file mode 100644 index 0000000..3055737 --- /dev/null +++ b/Source/Engine/Font.swift @@ -0,0 +1,12 @@ +// +// Font.swift +// Engine +// +// Created by Nick Lockwood on 21/04/2020. +// Copyright © 2020 Nick Lockwood. All rights reserved. +// + +public struct Font: Decodable { + public let texture: Texture + public let characters: [String] +} diff --git a/Source/Engine/Game.swift b/Source/Engine/Game.swift new file mode 100644 index 0000000..3a12b7b --- /dev/null +++ b/Source/Engine/Game.swift @@ -0,0 +1,78 @@ +// +// Game.swift +// Engine +// +// Created by Nick Lockwood on 07/10/2019. +// Copyright © 2019 Nick Lockwood. All rights reserved. +// + +public protocol GameDelegate: AnyObject { + func playSound(_ sound: Sound) + func clearSounds() +} + +public enum GameState { + case title + case starting + case playing +} + +public struct Game { + public weak var delegate: GameDelegate? + public let levels: [Tilemap] + public private(set) var world: World + public private(set) var state: GameState + public private(set) var transition: Effect? + public let font: Font + public var titleText = "TAP TO START" + + public init(levels: [Tilemap], font: Font) { + self.state = .title + self.levels = levels + self.world = World(map: levels[0]) + self.font = font + } +} + +public extension Game { + var hud: HUD { + return HUD(player: world.player, font: font) + } + + mutating func update(timeStep: Double, input: Input) { + guard let delegate = delegate else { + return + } + + // Update transition + if var effect = transition { + effect.time += timeStep + transition = effect + } + + // Update state + switch state { + case .title: + if input.isFiring { + transition = Effect(type: .fadeOut, color: .black, duration: 0.5) + state = .starting + } + case .starting: + if transition?.isCompleted == true { + transition = Effect(type: .fadeIn, color: .black, duration: 0.5) + state = .playing + } + case .playing: + if let action = world.update(timeStep: timeStep, input: input) { + switch action { + case .loadLevel(let index): + let index = index % levels.count + world.setLevel(levels[index]) + delegate.clearSounds() + case .playSounds(let sounds): + sounds.forEach(delegate.playSound) + } + } + } + } +} diff --git a/Source/Engine/HUD.swift b/Source/Engine/HUD.swift new file mode 100644 index 0000000..dcb4171 --- /dev/null +++ b/Source/Engine/HUD.swift @@ -0,0 +1,33 @@ +// +// HUD.swift +// Engine +// +// Created by Nick Lockwood on 19/04/2020. +// Copyright © 2020 Nick Lockwood. All rights reserved. +// + +public struct HUD { + public let healthString: String + public let healthTint: Color + public let ammoString: String + public let playerWeapon: Texture + public let weaponIcon: Texture + public let font: Font + + public init(player: Player, font: Font) { + let health = Int(max(0, player.health)) + switch health { + case ...10: + self.healthTint = .red + case 10 ... 30: + self.healthTint = .yellow + default: + self.healthTint = .green + } + self.healthString = String(health) + self.ammoString = String(Int(max(0, min(99, player.ammo)))) + self.playerWeapon = player.animation.texture + self.weaponIcon = player.weapon.attributes.hudIcon + self.font = font + } +} diff --git a/Source/Engine/Texture.swift b/Source/Engine/Texture.swift index f94dbb8..a04114f 100644 --- a/Source/Engine/Texture.swift +++ b/Source/Engine/Texture.swift @@ -6,7 +6,7 @@ // Copyright © 2019 Nick Lockwood. All rights reserved. // -public enum Texture: String, CaseIterable { +public enum Texture: String, CaseIterable, Decodable { case wall, wall2 case crackWall, crackWall2 case slimeWall, slimeWall2 @@ -32,4 +32,5 @@ public enum Texture: String, CaseIterable { case healthIcon case pistolIcon, shotgunIcon case font + case titleBackground, titleLogo } diff --git a/Source/Rampage.xcodeproj/project.pbxproj b/Source/Rampage.xcodeproj/project.pbxproj index 1a78709..d7af904 100644 --- a/Source/Rampage.xcodeproj/project.pbxproj +++ b/Source/Rampage.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 013D492523ED607D00763FCA /* medkit.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 013D492423ED607D00763FCA /* medkit.mp3 */; }; 013D492723EE17C000763FCA /* Weapon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 013D492623EE17C000763FCA /* Weapon.swift */; }; 01467C3E22E6F54600B5607D /* Easing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01467C3D22E6F54600B5607D /* Easing.swift */; }; + 01557AD0245109E600FF8FF0 /* HUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01557ACF245109E600FF8FF0 /* HUD.swift */; }; 0159A3F523DEF636001EEB81 /* Pickup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0159A3F423DEF636001EEB81 /* Pickup.swift */; }; 015A23C9230586E3004CBB78 /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 015A23C8230586E3004CBB78 /* Switch.swift */; }; 016E41B3228E9A5B00ACF137 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016E41B2228E9A5B00ACF137 /* AppDelegate.swift */; }; @@ -63,7 +64,10 @@ 01D09B0B22A7F7570052745A /* Texture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09B0A22A7F7570052745A /* Texture.swift */; }; 01D0F5D922F80E1600682CA1 /* RampageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D0F5D822F80E1600682CA1 /* RampageTests.swift */; }; 01D0F5F122FF095E00682CA1 /* Door.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D0F5F022FF095E00682CA1 /* Door.swift */; }; + 01DD25AA244FA74900D00FE5 /* Font.json in Resources */ = {isa = PBXBuildFile; fileRef = 01DD25A9244FA74900D00FE5 /* Font.json */; }; + 01DD25AC244FA85E00D00FE5 /* Font.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DD25AB244FA85E00D00FE5 /* Font.swift */; }; 01E3963A2342758D00D02236 /* Pushwall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01E396392342758D00D02236 /* Pushwall.swift */; }; + 01EDA5DB2444DC2C00FC1795 /* Game.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EDA5DA2444DC2B00FC1795 /* Game.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -129,6 +133,7 @@ 013D492423ED607D00763FCA /* medkit.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = medkit.mp3; sourceTree = ""; }; 013D492623EE17C000763FCA /* Weapon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Weapon.swift; sourceTree = ""; }; 01467C3D22E6F54600B5607D /* Easing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Easing.swift; sourceTree = ""; }; + 01557ACF245109E600FF8FF0 /* HUD.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HUD.swift; sourceTree = ""; }; 0159A3F423DEF636001EEB81 /* Pickup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pickup.swift; sourceTree = ""; }; 015A23C8230586E3004CBB78 /* Switch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Switch.swift; sourceTree = ""; }; 016E41AF228E9A5B00ACF137 /* Rampage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Rampage.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -173,7 +178,10 @@ 01D0F5D822F80E1600682CA1 /* RampageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RampageTests.swift; sourceTree = ""; }; 01D0F5DA22F80E1600682CA1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 01D0F5F022FF095E00682CA1 /* Door.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Door.swift; sourceTree = ""; }; + 01DD25A9244FA74900D00FE5 /* Font.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Font.json; sourceTree = ""; }; + 01DD25AB244FA85E00D00FE5 /* Font.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Font.swift; sourceTree = ""; }; 01E396392342758D00D02236 /* Pushwall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pushwall.swift; sourceTree = ""; }; + 01EDA5DA2444DC2B00FC1795 /* Game.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Game.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -260,6 +268,7 @@ 0199F57323E242D4003E3F08 /* SoundManager.swift */, 016E41B6228E9A5B00ACF137 /* Main.storyboard */, 01D09B0022A493A70052745A /* Levels.json */, + 01DD25A9244FA74900D00FE5 /* Font.json */, 016E41B9228E9A5E00ACF137 /* Assets.xcassets */, 0199F55423E1A517003E3F08 /* Sounds */, 016E41BB228E9A5E00ACF137 /* LaunchScreen.storyboard */, @@ -278,6 +287,9 @@ 01D0F5F022FF095E00682CA1 /* Door.swift */, 01467C3D22E6F54600B5607D /* Easing.swift */, 012DF10722E251CF00D52706 /* Effect.swift */, + 01DD25AB244FA85E00D00FE5 /* Font.swift */, + 01EDA5DA2444DC2B00FC1795 /* Game.swift */, + 01557ACF245109E600FF8FF0 /* HUD.swift */, 01D09B0222A4958E0052745A /* Input.swift */, 012A0C6122CC200D0068E8EF /* Monster.swift */, 0108A66E23F543740075E1AF /* Pathfinder.swift */, @@ -436,21 +448,24 @@ attributes = { DefaultBuildSystemTypeForWorkspace = Original; LastSwiftUpdateCheck = 1010; - LastUpgradeCheck = 1010; + LastUpgradeCheck = 1130; ORGANIZATIONNAME = "Nick Lockwood"; TargetAttributes = { 0108A65623F4D84C0075E1AF = { CreatedOnToolsVersion = 11.3.1; + LastSwiftMigration = 1130; }; 016E41AE228E9A5B00ACF137 = { CreatedOnToolsVersion = 10.1; + LastSwiftMigration = 1130; }; 016E41C8228E9A8600ACF137 = { CreatedOnToolsVersion = 10.1; - LastSwiftMigration = 1010; + LastSwiftMigration = 1130; }; 01D0F5D522F80E1600682CA1 = { CreatedOnToolsVersion = 10.1; + LastSwiftMigration = 1130; TestTargetID = 016E41AE228E9A5B00ACF137; }; }; @@ -489,6 +504,7 @@ buildActionMask = 2147483647; files = ( 0128F26223EEE7AE00439050 /* shotgunFire.mp3 in Resources */, + 01DD25AA244FA74900D00FE5 /* Font.json in Resources */, 0199F56E23E1A517003E3F08 /* wallThud.mp3 in Resources */, 0199F56623E1A517003E3F08 /* playerWalk.mp3 in Resources */, 0199F56C23E1A517003E3F08 /* monsterGroan.mp3 in Resources */, @@ -556,6 +572,7 @@ 012DF10822E251CF00D52706 /* Effect.swift in Sources */, 012A0C6322CC200E0068E8EF /* Monster.swift in Sources */, 01D09B0B22A7F7570052745A /* Texture.swift in Sources */, + 01EDA5DB2444DC2C00FC1795 /* Game.swift in Sources */, 0159A3F523DEF636001EEB81 /* Pickup.swift in Sources */, 015A23C9230586E3004CBB78 /* Switch.swift in Sources */, 01D09AFF22A48E990052745A /* Tilemap.swift in Sources */, @@ -567,6 +584,7 @@ 01467C3E22E6F54600B5607D /* Easing.swift in Sources */, 01D09B0722A6E09B0052745A /* Rotation.swift in Sources */, 01D09AFB22A485040052745A /* Player.swift in Sources */, + 01557AD0245109E600FF8FF0 /* HUD.swift in Sources */, 012A0C6222CC200E0068E8EF /* Billboard.swift in Sources */, 013D492723EE17C000763FCA /* Weapon.swift in Sources */, 01ADC64022B9846B00DC8AAD /* World.swift in Sources */, @@ -575,6 +593,7 @@ 01D0F5F122FF095E00682CA1 /* Door.swift in Sources */, 0108A66F23F543750075E1AF /* Pathfinder.swift in Sources */, 01D09B0322A4958E0052745A /* Input.swift in Sources */, + 01DD25AC244FA85E00D00FE5 /* Font.swift in Sources */, 012A0CA222D7AD0A0068E8EF /* Animation.swift in Sources */, 01D09B0522A5C9DB0052745A /* Ray.swift in Sources */, 01E3963A2342758D00D02236 /* Pushwall.swift in Sources */, @@ -646,7 +665,6 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Renderer/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -657,7 +675,7 @@ SKIP_INSTALL = YES; SWIFT_DISABLE_SAFETY_CHECKS = YES; SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -676,7 +694,6 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Renderer/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -686,7 +703,7 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SWIFT_DISABLE_SAFETY_CHECKS = YES; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -744,7 +761,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -799,7 +816,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; @@ -823,7 +840,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.Rampage; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -842,7 +859,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.Rampage; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; @@ -871,7 +888,7 @@ SKIP_INSTALL = YES; SWIFT_DISABLE_SAFETY_CHECKS = NO; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -902,7 +919,7 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SWIFT_DISABLE_SAFETY_CHECKS = YES; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -923,7 +940,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.RampageTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Rampage.app/Rampage"; }; @@ -943,7 +960,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.RampageTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Rampage.app/Rampage"; }; diff --git a/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Engine.xcscheme b/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Engine.xcscheme index b8e8ec2..8fdc9d0 100644 --- a/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Engine.xcscheme +++ b/Source/Rampage.xcodeproj/xcshareddata/xcschemes/Engine.xcscheme @@ -1,6 +1,6 @@ - - - - p#P}2bNwrRZD|@ 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 Cnuoyv literal 0 HcmV?d00001 diff --git a/Source/Rampage/Assets.xcassets/titleLogo.imageset/Contents.json b/Source/Rampage/Assets.xcassets/titleLogo.imageset/Contents.json new file mode 100644 index 0000000..7f3981f --- /dev/null +++ b/Source/Rampage/Assets.xcassets/titleLogo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "titleLogo.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/titleLogo.imageset/titleLogo.png b/Source/Rampage/Assets.xcassets/titleLogo.imageset/titleLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..6015126d43d86d8dc5d96417bbb2eea1d83381ba GIT binary patch literal 2492 zcmV;t2}AaYP)Px;c1c7*RCt{2UCnD0SrD&T7mryGuSy7rhZvQ?0fXQkJq;*(S^ojOdy)tq0vkN- zJs$Uxlk6^Y%5fK#EX*<_hJX?n2E7Ks90M|Y$aLp*bydBp?$ z7*9s$g1`y5wFD(x1E4w6vU?H*k;jt}d_V6=006xD>#n)a`;VVs{O&6pY=28Wnu4&g zMP#`6<;UG%V^L$485fNs?gJq5YGoQ_)P^VsTm-joUWeOj0FT!)n;Xr>)`^6KihW4Q zYkgS^GHS(l^PWHmpu@OmE<*~>J`^UeK}PL}S_5Mf+kblnZr{94wte;2-CX-3GRpMf zh*3m_)L+_%{@W`sc=m-ItN-?jS`N1!pNu-uC=EP#_C-sEN;JcGG74@oi;OvV_62_X zbAf!u5!?6tkBxoRXBruGqA3LKfa7ny|M-b)wEXB&2pQ5pu3Z@!);R(Iz~^88Hg=Wa z1jFgPoX?^~QwW>^XTBbM9yrB>D12Z}qY~)A%snvlvC1fn zvNGyeQ;hpo294CfEm|aK8iB>&Z2azPUGr!W37SS=0N{hQCIlS;F!$VROz`@^2Tz|v ze`i?7TqI-;ZRw{UeC_Aa3E{pUV3bkzqwy z8Fj2F#(gV;Rs*+)9-Q_Cs7V7eHz{X0&VTfBAxy!z0oo#&^BzRay;#W07YD%!Y!NQu z&2bm{F!v&&3j=hEmwq;HNZJ=55P?IHmKeA4N;vHyRavSzSnZwua9q9RIoSTjt~vBx zP`pU0$Si#%6ee(0q`hds`zR5tB+{>AX=S`Q&X$h8To_^Ul4O*)(VL8>!^N)34fAPV zfC2<=i5m_=s;DYtNDM%0T}<2rKJs$wNi7Tj3iRJUnYSGlCH89$ojA?STO9;(77a&t_j=H6G{hguL`~#sm zeF{Zu{qQ*JTbsEc3%hfYQgPQo#5*d@YjraU6PTNzyD6HDo~^k>T4b9*TSk*r_rI~PJbb26vy zbFC7fpd#?v(Me7dcqT}~_nb0eMaKd`<4AqEXKt{iuo}6x>symR1XJtJ?Z>qgZ^Bqml0q#P5iCT{`_c`f-; zigYVC?&Rj>m~yXm0fM|Z6`GvsOha<}rPcI7P)RkK&$k0W+7|g10gxZREa?ZVyv_2VJ-Z2z;0cPfTH5*|wmn}K+Qob#5n5>D_YRvVmO?YzeKG_hz z0PcJ^%Ru?l_ze3yLvNtx^NaEL)~n{qig^^*#%f317rbDCXx?IuycArrQrdZjoTj7J zkIBnvS1!VLWjT>Mz+x9(JM(minH!%=wYgT&lRmQ+dw(etaL82GQp&0T^gpp<#{Ej^gD4yFBmYeMz>zw3Z_3j zBy2YEa{#$YPV#NFkbJ?lqmxsz9r101S^{a$$(LPA-Z}rhWE+7sQKt`@+5#jq`H}Q9 z31a309L3nLpFS4@MPN)c(@uI00B71<(AYkWN$#DIyeY7|X6-*Ol+wVGX4Ak*W?xbq z=OLBk)jaPcbM*M-H;KIlq%){$R4zl6gQ726nP{+=KM@w#=t=) z>PBg{3^_GbRK9{07qOE8lb5;xi5cEWy8lOp=T19kUNv70!bnK$%l(4j4+|z8x5exC zJ@>X@G<1|?z+dJ?dSxOpu?b@r*Nt<%@MI8A@1`bljo|S z$A>DuLQ@r*M&1NfW+5_~Z@Acnp+jhmc20^$gmF(z9^|f$%Mh^e;W55%lw=Tm`6%bh z!Tgn?f`#UycJ`22)S9yb^C@aScf_oH&kK10j2c)|U#dh#JG*37v@i0!R>ZD-6Sx;d z%4Qj7H9~ZzO5C#sZk$t5yY&00UXyX(3Sr@q51QwNt&tRshkhQ@LfJ5nleuk zs>!E?8iqa>7=@~;TG(MpqqT=&L%UxsTC`} [Tilemap] { return levels.enumerated().map { Tilemap($0.element, index: $0.offset) } } +public func loadFont() -> Font { + let jsonURL = Bundle.main.url(forResource: "Font", withExtension: "json")! + let jsonData = try! Data(contentsOf: jsonURL) + return try! JSONDecoder().decode(Font.self, from: jsonData) +} + public func loadTextures() -> Textures { return Textures(loader: { name in Bitmap(image: UIImage(named: name)!)! @@ -46,8 +52,7 @@ class ViewController: UIViewController { private let panGesture = UIPanGestureRecognizer() private let tapGesture = UITapGestureRecognizer() private let textures = loadTextures() - private let levels = loadLevels() - private lazy var world = World(map: levels[0]) + private var game = Game(levels: loadLevels(), font: loadFont()) private var lastFrameTime = CACurrentMediaTime() private var lastFiredTime = 0.0 @@ -70,6 +75,8 @@ class ViewController: UIViewController { view.addGestureRecognizer(tapGesture) tapGesture.addTarget(self, action: #selector(fire)) tapGesture.delegate = self + + game.delegate = self } override var supportedInterfaceOrientations: UIInterfaceOrientationMask { @@ -80,6 +87,10 @@ class ViewController: UIViewController { return true } + override var prefersHomeIndicatorAutoHidden: Bool { + return true + } + private var inputVector: Vector { switch panGesture.state { case .began, .changed: @@ -99,41 +110,20 @@ class ViewController: UIViewController { @objc func update(_ displayLink: CADisplayLink) { let timeStep = min(maximumTimeStep, displayLink.timestamp - lastFrameTime) let inputVector = self.inputVector - let rotation = inputVector.x * world.player.turningSpeed * worldTimeStep - let input = Input( + let rotation = inputVector.x * game.world.player.turningSpeed * worldTimeStep + var input = Input( speed: -inputVector.y, rotation: Rotation(sine: sin(rotation), cosine: cos(rotation)), isFiring: lastFiredTime > lastFrameTime ) + lastFrameTime = displayLink.timestamp + lastFiredTime = min(lastFiredTime, lastFrameTime) + let worldSteps = (timeStep / worldTimeStep).rounded(.up) for _ in 0 ..< Int(worldSteps) { - if let action = world.update(timeStep: timeStep / worldSteps, input: input) { - switch action { - case .loadLevel(let index): - SoundManager.shared.clearAll() - let index = index % levels.count - world.setLevel(levels[index]) - case .playSounds(let sounds): - for sound in sounds { - DispatchQueue.main.asyncAfter(deadline: .now() + sound.delay) { - guard let url = sound.name?.url else { - if let channel = sound.channel { - SoundManager.shared.clearChannel(channel) - } - return - } - try? SoundManager.shared.play( - url, - channel: sound.channel, - volume: sound.volume, - pan: sound.pan - ) - } - } - } - } + game.update(timeStep: timeStep / worldSteps, input: input) + input.isFiring = false } - lastFrameTime = displayLink.timestamp let width = Int(imageView.bounds.width), height = Int(imageView.bounds.height) var renderer = Renderer(width: width, height: height, textures: textures) @@ -142,7 +132,7 @@ class ViewController: UIViewController { min: Vector(x: Double(insets.left), y: Double(insets.top)), max: renderer.bitmap.size - Vector(x: Double(insets.left), y: Double(insets.bottom)) ) - renderer.draw(world) + renderer.draw(game) imageView.image = UIImage(bitmap: renderer.bitmap) } @@ -172,3 +162,26 @@ extension ViewController: UIGestureRecognizerDelegate { return true } } + +extension ViewController: GameDelegate { + func playSound(_ sound: Sound) { + DispatchQueue.main.asyncAfter(deadline: .now() + sound.delay) { + guard let url = sound.name?.url else { + if let channel = sound.channel { + SoundManager.shared.clearChannel(channel) + } + return + } + try? SoundManager.shared.play( + url, + channel: sound.channel, + volume: sound.volume, + pan: sound.pan + ) + } + } + + func clearSounds() { + SoundManager.shared.clearAll() + } +} diff --git a/Source/Renderer/Renderer.swift b/Source/Renderer/Renderer.swift index 12d1fb0..bf53069 100644 --- a/Source/Renderer/Renderer.swift +++ b/Source/Renderer/Renderer.swift @@ -23,6 +23,58 @@ public struct Renderer { } public extension Renderer { + mutating func draw(_ game: Game) { + switch game.state { + case .title, .starting: + // Background + let background = textures[.titleBackground] + let backgroundScale = bitmap.size.y / background.size.y + let backgroundSize = background.size * backgroundScale + let backgroundPosition = (bitmap.size - backgroundSize) / 2 + bitmap.drawImage(background, at: backgroundPosition, size: backgroundSize) + + // Logo + let logo = textures[.titleLogo] + let logoScale = bitmap.size.y / logo.size.y / 2 + let logoSize = logo.size * logoScale + let logoPosition = Vector(x: (bitmap.size.x - logoSize.x) / 2, y: bitmap.size.y * 0.15) + bitmap.drawImage(logo, at: logoPosition, size: logoSize) + + // Text + let textScale = bitmap.size.y / 64 + let font = textures[game.font.texture] + let charSize = Vector(x: Double(font.width / game.font.characters.count), y: font.size.y) + let textWidth = charSize.x * Double(game.titleText.count) * textScale + var offset = Vector(x: (bitmap.size.x - textWidth) / 2, y: bitmap.size.y * 0.75) + for char in game.titleText { + let index = game.font.characters.firstIndex(of: String(char)) ?? 0 + let step = Int(charSize.x) + let xRange = index * step ..< (index + 1) * step + bitmap.drawImage( + font, + xRange: xRange, + at: offset, + size: charSize * textScale, + tint: .yellow + ) + offset.x += charSize.x * textScale + } + case .playing: + draw(game.world) + draw(game.hud) + + // Effects + for effect in game.world.effects { + draw(effect) + } + } + + // Transition + if let effect = game.transition { + draw(effect) + } + } + mutating func draw(_ world: World) { let focalLength = 1.0 let viewWidth = Double(bitmap.width) / Double(bitmap.height) @@ -124,17 +176,14 @@ public extension Renderer { columnPosition += step } + } + mutating func draw(_ hud: HUD) { // Player weapon - let weaponTexture = textures[world.player.animation.texture] - let aspectRatio = Double(weaponTexture.width) / Double(weaponTexture.height) - let screenHeight = Double(bitmap.height) - let weaponWidth = screenHeight * aspectRatio - bitmap.drawImage( - weaponTexture, - at: Vector(x: Double(bitmap.width) / 2 - weaponWidth / 2, y: 0), - size: Vector(x: weaponWidth, y: screenHeight) - ) + let weaponTexture = textures[hud.playerWeapon] + let weaponScale = bitmap.size.y / weaponTexture.size.y + let weaponSize = weaponTexture.size * weaponScale + bitmap.drawImage(weaponTexture, at: (bitmap.size - weaponSize) / 2, size: weaponSize) // Crosshair let crosshair = textures[.crosshair] @@ -149,20 +198,11 @@ public extension Renderer { offset.x += healthIcon.size.x * hudScale // Health - let font = textures[.font] - let charSize = Vector(x: font.size.x / 10, y: font.size.y) - let health = Int(max(0, world.player.health)) - let healthTint: Color - switch health { - case ...10: - healthTint = .red - case 10 ... 30: - healthTint = .yellow - default: - healthTint = .green - } - for char in String(health) { - let index = Int(char.asciiValue!) - 48 + let font = textures[hud.font.texture] + let charSize = Vector(x: Double(font.width / hud.font.characters.count), y: font.size.y) + let healthTint = hud.healthTint + for char in hud.healthString { + let index = hud.font.characters.firstIndex(of: String(char)) ?? 0 let step = Int(charSize.x) let xRange = index * step ..< (index + 1) * step bitmap.drawImage( @@ -177,9 +217,8 @@ public extension Renderer { // Ammunition offset.x = safeArea.max.x - let ammo = Int(max(0, min(99, world.player.ammo))) - for char in String(ammo).reversed() { - let index = Int(char.asciiValue!) - 48 + for char in hud.ammoString.reversed() { + let index = hud.font.characters.firstIndex(of: String(char)) ?? 0 let step = Int(charSize.x) let xRange = index * step ..< (index + 1) * step offset.x -= charSize.x * hudScale @@ -187,27 +226,26 @@ public extension Renderer { } // Weapon icon - let weaponIcon = textures[world.player.weapon.attributes.hudIcon] + let weaponIcon = textures[hud.weaponIcon] offset.x -= weaponIcon.size.x * hudScale bitmap.drawImage(weaponIcon, at: offset, size: weaponIcon.size * hudScale) + } - // Effects - for effect in world.effects { - switch effect.type { - case .fadeIn: - bitmap.tint(with: effect.color, opacity: 1 - effect.progress) - case .fadeOut: - bitmap.tint(with: effect.color, opacity: effect.progress) - case .fizzleOut: - let threshold = Int(effect.progress * Double(fizzle.count)) - for x in 0 ..< bitmap.width { - for y in 0 ..< bitmap.height { - let granularity = 4 - let index = y / granularity * bitmap.width + x / granularity - let fizzledIndex = fizzle[index % fizzle.count] - if fizzledIndex <= threshold { - bitmap[x, y] = effect.color - } + mutating func draw(_ effect: Effect) { + switch effect.type { + case .fadeIn: + bitmap.tint(with: effect.color, opacity: 1 - effect.progress) + case .fadeOut: + bitmap.tint(with: effect.color, opacity: effect.progress) + case .fizzleOut: + let threshold = Int(effect.progress * Double(fizzle.count)) + for x in 0 ..< bitmap.width { + for y in 0 ..< bitmap.height { + let granularity = 4 + let index = y / granularity * bitmap.width + x / granularity + let fizzledIndex = fizzle[index % fizzle.count] + if fizzledIndex <= threshold { + bitmap[x, y] = effect.color } } } From 43ec2afa663f5e730a705e5fdd1945c0b31f6d44 Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Mon, 11 May 2020 22:46:34 +0100 Subject: [PATCH 08/10] Part18 --- Source/Engine/MapGenerator.swift | 138 +++++++++++++++++++++++ Source/Engine/RNG.swift | 32 ++++++ Source/Engine/Tilemap.swift | 16 ++- Source/Engine/World.swift | 6 +- Source/Rampage.xcodeproj/project.pbxproj | 8 ++ Source/Rampage/Levels.json | 34 +----- Source/Rampage/ViewController.swift | 4 +- Source/Renderer/Renderer.swift | 11 +- 8 files changed, 210 insertions(+), 39 deletions(-) create mode 100644 Source/Engine/MapGenerator.swift create mode 100644 Source/Engine/RNG.swift diff --git a/Source/Engine/MapGenerator.swift b/Source/Engine/MapGenerator.swift new file mode 100644 index 0000000..2ede64a --- /dev/null +++ b/Source/Engine/MapGenerator.swift @@ -0,0 +1,138 @@ +// +// MapGenerator.swift +// Engine +// +// Created by Nick Lockwood on 09/05/2020. +// Copyright © 2020 Nick Lockwood. All rights reserved. +// + +public struct MapGenerator { + public private(set) var map: Tilemap + private var rng: RNG + private var elevatorPosition: Vector! + private var playerPosition: Vector! + private var emptyTiles: [Vector] = [] + private var wallTiles: [Vector] = [] + + public init(mapData: MapData, index: Int) { + self.map = Tilemap(mapData, index: index) + self.rng = RNG(seed: mapData.seed ?? .random(in: 0 ... .max)) + + // Find empty tiles + for y in 0 ..< map.height { + for x in 0 ..< map.width { + let position = Vector(x: Double(x) + 0.5, y: Double(y) + 0.5) + if map[x, y].isWall { + if map[x, y] == .elevatorBackWall { + map[thing: x, y] = .switch + } + wallTiles.append(position) + } else { + if map[x, y] == .elevatorFloor { + elevatorPosition = position + } + switch map[thing: x, y] { + case .nothing: + emptyTiles.append(position) + case .player: + playerPosition = position + default: + break + } + } + } + } + + // Add doors + for position in emptyTiles { + let x = Int(position.x), y = Int(position.y) + let left = map[x - 1, y], right = map[x + 1, y], + up = map[x, y - 1], down = map[x, y + 1] + if (left.isWall && right.isWall && !up.isWall && !down.isWall) + || (!left.isWall && !right.isWall && up.isWall && down.isWall) { + add(.door, at: position) + } + } + + // Add push-walls + for _ in 0 ..< (mapData.pushwalls ?? 0) { + add(.pushwall, at: wallTiles.filter { position in + let x = Int(position.x), y = Int(position.y) + guard x > 0, x < map.width - 1, y > 0, y < map.height - 1 else { + return false // Outer wall + } + let left = map[x - 1, y], right = map[x + 1, y], + up = map[x, y - 1], down = map[x, y + 1] + if left.isWall, right.isWall, !up.isWall, !down.isWall, + !map[x, y - 2].isWall, !map[x, y + 2].isWall { + return true + } + if !left.isWall, !right.isWall, up.isWall, down.isWall, + !map[x - 2, y].isWall, !map[x + 2, y].isWall { + return true + } + return false + }.randomElement(using: &rng)) + } + + // Add player + if playerPosition == nil { + playerPosition = emptyTiles.filter { + findPath(from: $0, to: elevatorPosition, maxDistance: 1000).isEmpty == false + }.randomElement(using: &rng) + add(.player, at: playerPosition) + } + + // Add monsters + for _ in 0 ..< (mapData.monsters ?? 0) { + add(.monster, at: emptyTiles.filter { + (playerPosition - $0).length > 2.5 + }.randomElement(using: &rng)) + } + + // Add medkits + for _ in 0 ..< (mapData.medkits ?? 0) { + add(.medkit, at: emptyTiles.randomElement(using: &rng)) + } + + // Add shotguns + for _ in 0 ..< (mapData.shotguns ?? 0) { + add(.shotgun, at: emptyTiles.randomElement(using: &rng)) + } + } +} + +private extension MapGenerator { + mutating func add(_ thing: Thing, at position: Vector?) { + if let position = position { + map[thing: Int(position.x), Int(position.y)] = thing + if let index = emptyTiles.lastIndex(of: position) { + emptyTiles.remove(at: index) + } + } + } +} + +extension MapGenerator: Graph { + public typealias Node = Vector + + public func nodesConnectedTo(_ node: Node) -> [Node] { + return [ + Node(x: node.x - 1, y: node.y), + Node(x: node.x + 1, y: node.y), + Node(x: node.x, y: node.y - 1), + Node(x: node.x, y: node.y + 1), + ].filter { node in + let x = Int(node.x), y = Int(node.y) + return map[x, y].isWall == false + } + } + + public func estimatedDistance(from a: Node, to b: Node) -> Double { + return abs(b.x - a.x) + abs(b.y - a.y) + } + + public func stepDistance(from a: Node, to b: Node) -> Double { + return 1 + } +} diff --git a/Source/Engine/RNG.swift b/Source/Engine/RNG.swift new file mode 100644 index 0000000..3103646 --- /dev/null +++ b/Source/Engine/RNG.swift @@ -0,0 +1,32 @@ +// +// RNG.swift +// Engine +// +// Created by Nick Lockwood on 17/05/2020. +// Copyright © 2020 Nick Lockwood. All rights reserved. +// + +let multiplier: UInt64 = 6364136223846793005 +let increment: UInt64 = 1442695040888963407 + +public struct RNG { + private var seed: UInt64 = 0 + + public init(seed: UInt64) { + self.seed = seed + } + + public mutating func next() -> UInt64 { + seed = seed &* multiplier &+ increment + return seed + } +} + +public extension Collection where Index == Int { + func randomElement(using generator: inout RNG) -> Element? { + if isEmpty { + return nil + } + return self[startIndex + Index(generator.next() % UInt64(count))] + } +} diff --git a/Source/Engine/Tilemap.swift b/Source/Engine/Tilemap.swift index c50cf46..bcab8df 100644 --- a/Source/Engine/Tilemap.swift +++ b/Source/Engine/Tilemap.swift @@ -8,19 +8,24 @@ public struct MapData: Decodable { fileprivate let tiles: [Tile] - fileprivate let things: [Thing] + fileprivate let things: [Thing]? fileprivate let width: Int + public let seed: UInt64? + public let monsters: Int? + public let medkits: Int? + public let shotguns: Int? + public let pushwalls: Int? } public struct Tilemap { private(set) var tiles: [Tile] - public let things: [Thing] + private var things: [Thing] public let width: Int public let index: Int public init(_ map: MapData, index: Int) { self.tiles = map.tiles - self.things = map.things + self.things = map.things ?? Array(repeating: .nothing, count: map.tiles.count) self.width = map.width self.index = index } @@ -40,6 +45,11 @@ public extension Tilemap { set { tiles[y * width + x] = newValue } } + subscript(thing x: Int, y: Int) -> Thing { + get { return things[y * width + x] } + set { things[y * width + x] = newValue } + } + func tileCoords(at position: Vector, from direction: Vector) -> (x: Int, y: Int) { var offsetX = 0, offsetY = 0 if position.x.rounded(.down) == position.x { diff --git a/Source/Engine/World.swift b/Source/Engine/World.swift index cfcc6d6..acb9470 100644 --- a/Source/Engine/World.swift +++ b/Source/Engine/World.swift @@ -243,7 +243,7 @@ public extension World { for y in 0 ..< map.height { for x in 0 ..< map.width { let position = Vector(x: Double(x) + 0.5, y: Double(y) + 0.5) - let thing = map.things[y * map.width + x] + let thing = map[thing: x, y] switch thing { case .nothing: break @@ -330,7 +330,7 @@ public extension World { } func isDoor(at x: Int, _ y: Int) -> Bool { - return map.things[y * map.width + x] == .door + return map[thing: x, y] == .door } func door(at x: Int, _ y: Int) -> Door? { @@ -349,7 +349,7 @@ public extension World { } func `switch`(at x: Int, _ y: Int) -> Switch? { - guard map.things[y * map.width + x] == .switch else { + guard map[thing: x, y] == .switch else { return nil } return switches.first(where: { diff --git a/Source/Rampage.xcodeproj/project.pbxproj b/Source/Rampage.xcodeproj/project.pbxproj index d7af904..233461e 100644 --- a/Source/Rampage.xcodeproj/project.pbxproj +++ b/Source/Rampage.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 0108A66723F4D9370075E1AF /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AF022A481AB0052745A /* Color.swift */; }; 0108A66923F4D9B70075E1AF /* Textures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0108A66823F4D9B70075E1AF /* Textures.swift */; }; 0108A66F23F543750075E1AF /* Pathfinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0108A66E23F543740075E1AF /* Pathfinder.swift */; }; + 010978C124694477002CC646 /* MapGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 010978C024694477002CC646 /* MapGenerator.swift */; }; 0128F26223EEE7AE00439050 /* shotgunFire.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0128F26123EEE7AE00439050 /* shotgunFire.mp3 */; }; 0128F26423EEEB0A00439050 /* shotgunPickup.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0128F26323EEEB0A00439050 /* shotgunPickup.mp3 */; }; 012A0C4D22C96E150068E8EF /* Tile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A0C4C22C96E150068E8EF /* Tile.swift */; }; @@ -23,6 +24,7 @@ 012A0C9E22D47C220068E8EF /* Actor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A0C9D22D47C220068E8EF /* Actor.swift */; }; 012A0CA222D7AD0A0068E8EF /* Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A0CA122D7AD0A0068E8EF /* Animation.swift */; }; 012DF10822E251CF00D52706 /* Effect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012DF10722E251CF00D52706 /* Effect.swift */; }; + 013BBC122470B3F200F14BBC /* RNG.swift in Sources */ = {isa = PBXBuildFile; fileRef = 013BBC112470B3F100F14BBC /* RNG.swift */; }; 013D492523ED607D00763FCA /* medkit.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 013D492423ED607D00763FCA /* medkit.mp3 */; }; 013D492723EE17C000763FCA /* Weapon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 013D492623EE17C000763FCA /* Weapon.swift */; }; 01467C3E22E6F54600B5607D /* Easing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01467C3D22E6F54600B5607D /* Easing.swift */; }; @@ -121,6 +123,7 @@ 0108A65A23F4D84C0075E1AF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 0108A66823F4D9B70075E1AF /* Textures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Textures.swift; sourceTree = ""; }; 0108A66E23F543740075E1AF /* Pathfinder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Pathfinder.swift; sourceTree = ""; }; + 010978C024694477002CC646 /* MapGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapGenerator.swift; sourceTree = ""; }; 0128F26123EEE7AE00439050 /* shotgunFire.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = shotgunFire.mp3; sourceTree = ""; }; 0128F26323EEEB0A00439050 /* shotgunPickup.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = shotgunPickup.mp3; sourceTree = ""; }; 012A0C4C22C96E150068E8EF /* Tile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tile.swift; sourceTree = ""; }; @@ -130,6 +133,7 @@ 012A0C9D22D47C220068E8EF /* Actor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Actor.swift; sourceTree = ""; }; 012A0CA122D7AD0A0068E8EF /* Animation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Animation.swift; sourceTree = ""; }; 012DF10722E251CF00D52706 /* Effect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Effect.swift; sourceTree = ""; }; + 013BBC112470B3F100F14BBC /* RNG.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNG.swift; sourceTree = ""; }; 013D492423ED607D00763FCA /* medkit.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = medkit.mp3; sourceTree = ""; }; 013D492623EE17C000763FCA /* Weapon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Weapon.swift; sourceTree = ""; }; 01467C3D22E6F54600B5607D /* Easing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Easing.swift; sourceTree = ""; }; @@ -291,6 +295,7 @@ 01EDA5DA2444DC2B00FC1795 /* Game.swift */, 01557ACF245109E600FF8FF0 /* HUD.swift */, 01D09B0222A4958E0052745A /* Input.swift */, + 010978C024694477002CC646 /* MapGenerator.swift */, 012A0C6122CC200D0068E8EF /* Monster.swift */, 0108A66E23F543740075E1AF /* Pathfinder.swift */, 0159A3F423DEF636001EEB81 /* Pickup.swift */, @@ -299,6 +304,7 @@ 01D09B0422A5C9DB0052745A /* Ray.swift */, 01D09AFC22A4873B0052745A /* Rect.swift */, 01D09B0622A6E09A0052745A /* Rotation.swift */, + 013BBC112470B3F100F14BBC /* RNG.swift */, 015A23C8230586E3004CBB78 /* Switch.swift */, 0199F56F23E1AFEA003E3F08 /* Sounds.swift */, 01D09B0A22A7F7570052745A /* Texture.swift */, @@ -587,6 +593,7 @@ 01557AD0245109E600FF8FF0 /* HUD.swift in Sources */, 012A0C6222CC200E0068E8EF /* Billboard.swift in Sources */, 013D492723EE17C000763FCA /* Weapon.swift in Sources */, + 010978C124694477002CC646 /* MapGenerator.swift in Sources */, 01ADC64022B9846B00DC8AAD /* World.swift in Sources */, 0108A66723F4D9370075E1AF /* Color.swift in Sources */, 012A0C4D22C96E150068E8EF /* Tile.swift in Sources */, @@ -597,6 +604,7 @@ 012A0CA222D7AD0A0068E8EF /* Animation.swift in Sources */, 01D09B0522A5C9DB0052745A /* Ray.swift in Sources */, 01E3963A2342758D00D02236 /* Pushwall.swift in Sources */, + 013BBC122470B3F200F14BBC /* RNG.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/Rampage/Levels.json b/Source/Rampage/Levels.json index 67f37f5..3cd1d27 100644 --- a/Source/Rampage/Levels.json +++ b/Source/Rampage/Levels.json @@ -1,6 +1,11 @@ [ { + "seed": 1, "width": 8, + "monsters": 5, + "medkits": 2, + "shotguns": 1, + "pushwalls": 1, "tiles": [ 1, 3, 1, 1, 3, 1, 1, 1, 1, 0, 0, 2, 0, 0, 0, 1, @@ -10,35 +15,6 @@ 1, 0, 1, 2, 0, 0, 0, 1, 6, 5, 6, 1, 0, 4, 4, 1, 1, 7, 3, 1, 1, 3, 1, 1 - ], - "things": [ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 0, 0, 0, 0, 7, 0, - 0, 0, 0, 0, 2, 0, 0, 0, - 0, 6, 0, 3, 0, 0, 0, 0, - 0, 0, 2, 0, 4, 0, 3, 0, - 0, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 2, 0, - 0, 5, 0, 0, 0, 0, 0, 0 - ] - }, - { - "width": 5, - "tiles": [ - 2, 1, 1, 6, 1, - 1, 0, 4, 5, 7, - 1, 1, 1, 6, 1, - 2, 0, 0, 1, 3, - 1, 0, 3, 1, 3, - 1, 1, 1, 1, 1 - ], - "things": [ - 0, 0, 0, 0, 0, - 0, 1, 3, 0, 5, - 0, 4, 0, 0, 0, - 0, 0, 2, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 ] } ] diff --git a/Source/Rampage/ViewController.swift b/Source/Rampage/ViewController.swift index 86bf586..0dff969 100644 --- a/Source/Rampage/ViewController.swift +++ b/Source/Rampage/ViewController.swift @@ -18,7 +18,9 @@ public func loadLevels() -> [Tilemap] { let jsonURL = Bundle.main.url(forResource: "Levels", withExtension: "json")! let jsonData = try! Data(contentsOf: jsonURL) let levels = try! JSONDecoder().decode([MapData].self, from: jsonData) - return levels.enumerated().map { Tilemap($0.element, index: $0.offset) } + return levels.enumerated().map { index, mapData in + MapGenerator(mapData: mapData, index: index).map + } } public func loadFont() -> Font { diff --git a/Source/Renderer/Renderer.swift b/Source/Renderer/Renderer.swift index bf53069..1b5d533 100644 --- a/Source/Renderer/Renderer.swift +++ b/Source/Renderer/Renderer.swift @@ -107,9 +107,14 @@ public extension Renderer { let tile = world.map[tileX, tileY] if end.x.rounded(.down) == end.x { let neighborX = tileX + (ray.direction.x > 0 ? -1 : 1) - let isDoor = world.isDoor(at: neighborX, tileY) - wallTexture = textures[isDoor ? .doorjamb : tile.textures[0]] - wallX = end.y - end.y.rounded(.down) + if world.map[neighborX, tileY].isWall { + wallTexture = textures[tile.textures[1]] + wallX = end.x - end.x.rounded(.down) + } else { + let isDoor = world.isDoor(at: neighborX, tileY) + wallTexture = textures[isDoor ? .doorjamb : tile.textures[0]] + wallX = end.y - end.y.rounded(.down) + } } else { let neighborY = tileY + (ray.direction.y > 0 ? -1 : 1) let isDoor = world.isDoor(at: tileX, neighborY) From dd2b1420eec338ba2222ed4ce196b541ec5b0747 Mon Sep 17 00:00:00 2001 From: PJ Date: Sun, 22 Mar 2020 14:57:45 +0000 Subject: [PATCH 09/10] Add game controller support --- Source/Rampage.xcodeproj/project.pbxproj | 8 +++++ .../contents.xcworkspacedata | 7 ++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 +++++ .../Rampage/GameControllerManager+Input.swift | 33 +++++++++++++++++++ Source/Rampage/GameControllerManager.swift | 31 +++++++++++++++++ Source/Rampage/ViewController.swift | 6 ++++ 6 files changed, 93 insertions(+) create mode 100644 Source/Rampage.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Source/Rampage.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Source/Rampage/GameControllerManager+Input.swift create mode 100644 Source/Rampage/GameControllerManager.swift diff --git a/Source/Rampage.xcodeproj/project.pbxproj b/Source/Rampage.xcodeproj/project.pbxproj index 233461e..2f8a479 100644 --- a/Source/Rampage.xcodeproj/project.pbxproj +++ b/Source/Rampage.xcodeproj/project.pbxproj @@ -70,6 +70,8 @@ 01DD25AC244FA85E00D00FE5 /* Font.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DD25AB244FA85E00D00FE5 /* Font.swift */; }; 01E3963A2342758D00D02236 /* Pushwall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01E396392342758D00D02236 /* Pushwall.swift */; }; 01EDA5DB2444DC2C00FC1795 /* Game.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EDA5DA2444DC2B00FC1795 /* Game.swift */; }; + D5AA3B932427B3E5004908CD /* GameControllerManager+Input.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AA3B912427B3E5004908CD /* GameControllerManager+Input.swift */; }; + D5AA3B942427B3E5004908CD /* GameControllerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AA3B922427B3E5004908CD /* GameControllerManager.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -186,6 +188,8 @@ 01DD25AB244FA85E00D00FE5 /* Font.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Font.swift; sourceTree = ""; }; 01E396392342758D00D02236 /* Pushwall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pushwall.swift; sourceTree = ""; }; 01EDA5DA2444DC2B00FC1795 /* Game.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Game.swift; sourceTree = ""; }; + D5AA3B912427B3E5004908CD /* GameControllerManager+Input.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GameControllerManager+Input.swift"; sourceTree = ""; }; + D5AA3B922427B3E5004908CD /* GameControllerManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameControllerManager.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -270,6 +274,8 @@ 016E41B4228E9A5B00ACF137 /* ViewController.swift */, 01D09AF422A482450052745A /* UIImage+Bitmap.swift */, 0199F57323E242D4003E3F08 /* SoundManager.swift */, + D5AA3B922427B3E5004908CD /* GameControllerManager.swift */, + D5AA3B912427B3E5004908CD /* GameControllerManager+Input.swift */, 016E41B6228E9A5B00ACF137 /* Main.storyboard */, 01D09B0022A493A70052745A /* Levels.json */, 01DD25A9244FA74900D00FE5 /* Font.json */, @@ -565,6 +571,8 @@ buildActionMask = 2147483647; files = ( 01D09AF522A482450052745A /* UIImage+Bitmap.swift in Sources */, + D5AA3B942427B3E5004908CD /* GameControllerManager.swift in Sources */, + D5AA3B932427B3E5004908CD /* GameControllerManager+Input.swift in Sources */, 0199F57423E242D4003E3F08 /* SoundManager.swift in Sources */, 016E41B5228E9A5B00ACF137 /* ViewController.swift in Sources */, 016E41B3228E9A5B00ACF137 /* AppDelegate.swift in Sources */, diff --git a/Source/Rampage.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Source/Rampage.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Source/Rampage.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Source/Rampage.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Source/Rampage.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Source/Rampage.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Source/Rampage/GameControllerManager+Input.swift b/Source/Rampage/GameControllerManager+Input.swift new file mode 100644 index 0000000..fa402ff --- /dev/null +++ b/Source/Rampage/GameControllerManager+Input.swift @@ -0,0 +1,33 @@ +// +// GameControllerManager+Input.swift +// Rampage +// +// Created by PJ COOK on 23/03/2020. +// Copyright © 2020 Nick Lockwood. All rights reserved. +// + +import Engine +import Foundation + +extension GameControllerManager { + func input(turningSpeed: Double, worldTimeStep: Double) -> Input? { + guard let controller = gameController?.extendedGamepad else { return nil } + + let leftInput = controller.leftThumbstick + let rightInput = controller.rightThumbstick + let rotation = Double(rightInput.xAxis.value) * turningSpeed * worldTimeStep + let isFiring = controller.rightTrigger.isPressed + + /* + If you implement the dual stick touch control PR then use the following for "speed" + Vector(x: Double(leftInput.xAxis.value), y: Double(leftInput.yAxis.value)) + + Implementing the 2 stick approach allows you to strafe, which is awesome! + */ + return Input( + speed: Double(leftInput.yAxis.value), + rotation: Rotation(sine: sin(rotation), cosine: cos(rotation)), + isFiring: isFiring + ) + } +} diff --git a/Source/Rampage/GameControllerManager.swift b/Source/Rampage/GameControllerManager.swift new file mode 100644 index 0000000..f505a13 --- /dev/null +++ b/Source/Rampage/GameControllerManager.swift @@ -0,0 +1,31 @@ +// +// GameControllerManager.swift +// Rampage +// +// Created by PJ COOK on 23/03/2020. +// Copyright © 2020 Nick Lockwood. All rights reserved. +// + +import GameController + +class GameControllerManager { + var gameController: GCController? + + init() { + NotificationCenter.default.addObserver(self, selector: #selector(controllerConnected), name: .GCControllerDidConnect, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(controllerDisconnected), name: .GCControllerDidDisconnect, object: nil) + GCController.startWirelessControllerDiscovery() + } +} + +extension GameControllerManager { + @objc private func controllerConnected(_ note: Notification) { + GCController.stopWirelessControllerDiscovery() + gameController = note.object as? GCController + } + + @objc private func controllerDisconnected(_ note: Notification) { + GCController.startWirelessControllerDiscovery() + gameController = nil + } +} diff --git a/Source/Rampage/ViewController.swift b/Source/Rampage/ViewController.swift index 0dff969..bd7c911 100644 --- a/Source/Rampage/ViewController.swift +++ b/Source/Rampage/ViewController.swift @@ -50,6 +50,7 @@ func setUpAudio() { } class ViewController: UIViewController { + private let gameControllerManager = GameControllerManager() private let imageView = UIImageView() private let panGesture = UIPanGestureRecognizer() private let tapGesture = UITapGestureRecognizer() @@ -121,6 +122,11 @@ class ViewController: UIViewController { lastFrameTime = displayLink.timestamp lastFiredTime = min(lastFiredTime, lastFrameTime) + if let controllerInput = gameControllerManager.input(turningSpeed: + game.world.player.turningSpeed, worldTimeStep: worldTimeStep) { + input = controllerInput + } + let worldSteps = (timeStep / worldTimeStep).rounded(.up) for _ in 0 ..< Int(worldSteps) { game.update(timeStep: timeStep / worldSteps, input: input) From 6bfefd72eb990831e05f57d9b35ea3f9883f3329 Mon Sep 17 00:00:00 2001 From: PJ Date: Mon, 23 Mar 2020 16:09:40 +0000 Subject: [PATCH 10/10] Get Rampage working on tvOS --- Source/Rampage.xcodeproj/project.pbxproj | 369 ++++++++++++++++-- .../xcshareddata/xcschemes/RampageTV.xcscheme | 78 ++++ Source/RampageTV/AppDelegate.swift | 14 + .../Content.imageset/Contents.json | 11 + .../Back.imagestacklayer/Contents.json | 6 + .../Contents.json | 17 + .../Content.imageset/Contents.json | 11 + .../Front.imagestacklayer/Contents.json | 6 + .../Content.imageset/Contents.json | 11 + .../Middle.imagestacklayer/Contents.json | 6 + .../Content.imageset/Contents.json | 16 + .../Back.imagestacklayer/Contents.json | 6 + .../App Icon.imagestack/Contents.json | 17 + .../Content.imageset/Contents.json | 16 + .../Front.imagestacklayer/Contents.json | 6 + .../Content.imageset/Contents.json | 16 + .../Middle.imagestacklayer/Contents.json | 6 + .../Contents.json | 32 ++ .../Contents.json | 24 ++ .../Top Shelf Image.imageset/Contents.json | 24 ++ .../RampageTV/Assets.xcassets/Contents.json | 6 + .../Base.lproj/LaunchScreen.storyboard | 24 ++ Source/RampageTV/Base.lproj/Main.storyboard | 28 ++ Source/RampageTV/Info.plist | 43 ++ Source/{Rampage => Shared}/Font.json | 0 .../GameControllerManager+Input.swift | 0 .../GameControllerManager.swift | 0 Source/{Rampage => Shared}/Levels.json | 0 .../SharedAssets.xcassets/Contents.json | 6 + .../ceiling.imageset/Contents.json | 0 .../ceiling.imageset/ceiling.png | Bin .../crackFloor.imageset/Contents.json | 0 .../crackFloor.imageset/crackFloor.png | Bin .../crackWall.imageset/Contents.json | 0 .../crackWall.imageset/crackWall.png | Bin .../crackWall2.imageset/Contents.json | 0 .../crackWall2.imageset/crackWall2.png | Bin .../crosshair.imageset/Contents.json | 0 .../crosshair.imageset/crosshair.png | Bin .../door.imageset/Contents.json | 0 .../door.imageset/door.png | Bin .../door2.imageset/Contents.json | 0 .../door2.imageset/door2.png | Bin .../doorjamb.imageset/Contents.json | 0 .../doorjamb.imageset/doorjamb.png | Bin .../doorjamb2.imageset/Contents.json | 0 .../doorjamb2.imageset/doorjamb2.png | Bin .../elevatorBackWall.imageset/Contents.json | 0 .../elevatorBackWall.png | Bin .../elevatorCeiling.imageset/Contents.json | 0 .../elevatorCeiling.png | Bin .../elevatorFloor.imageset/Contents.json | 0 .../elevatorFloor.imageset/elevatorFloor.png | Bin .../elevatorSideWall.imageset/Contents.json | 0 .../elevatorSideWall.png | Bin .../floor.imageset/Contents.json | 0 .../floor.imageset/floor.png | Bin .../font.imageset/Contents.json | 0 .../font.imageset/font.png | Bin .../healthIcon.imageset/Contents.json | 2 +- .../healthIcon.imageset/healthIcon.png | Bin .../medkit.imageset/Contents.json | 0 .../medkit.imageset/medkit.png | Bin .../monster.imageset/Contents.json | 0 .../monster.imageset/monster.png | Bin .../monsterDead.imageset/Contents.json | 0 .../monsterDead.imageset/monsterDead.png | Bin .../monsterDeath1.imageset/Contents.json | 0 .../monsterDeath1.imageset/monsterDeath1.png | Bin .../monsterDeath2.imageset/Contents.json | 0 .../monsterDeath2.imageset/monsterDeath2.png | Bin .../monsterHurt.imageset/Contents.json | 0 .../monsterHurt.imageset/monsterHurt.png | Bin .../monsterScratch1.imageset/Contents.json | 0 .../monsterScratch1.png | Bin .../monsterScratch2.imageset/Contents.json | 0 .../monsterScratch2.png | Bin .../monsterScratch3.imageset/Contents.json | 0 .../monsterScratch3.png | Bin .../monsterScratch4.imageset/Contents.json | 0 .../monsterScratch4.png | Bin .../monsterScratch5.imageset/Contents.json | 0 .../monsterScratch5.png | Bin .../monsterScratch6.imageset/Contents.json | 0 .../monsterScratch6.png | Bin .../monsterScratch7.imageset/Contents.json | 0 .../monsterScratch7.png | Bin .../monsterScratch8.imageset/Contents.json | 0 .../monsterScratch8.png | Bin .../monsterWalk1.imageset/Contents.json | 0 .../monsterWalk1.imageset/monsterWalk1.png | Bin .../monsterWalk2.imageset/Contents.json | 0 .../monsterWalk2.imageset/monsterWalk2.png | Bin .../pistol.imageset/Contents.json | 0 .../pistol.imageset/pistol.png | Bin .../pistolFire1.imageset/Contents.json | 0 .../pistolFire1.imageset/pistolFire1.png | Bin .../pistolFire2.imageset/Contents.json | 0 .../pistolFire2.imageset/pistolFire2.png | Bin .../pistolFire3.imageset/Contents.json | 0 .../pistolFire3.imageset/pistolFire3.png | Bin .../pistolFire4.imageset/Contents.json | 0 .../pistolFire4.imageset/pistolFire4.png | Bin .../pistolIcon.imageset/Contents.json | 2 +- .../pistolIcon.imageset/pistolIcon.png | Bin .../shotgun.imageset/Contents.json | 0 .../shotgun.imageset/shotgun.png | Bin .../shotgunFire1.imageset/Contents.json | 0 .../shotgunFire1.imageset/shotgunFire1.png | Bin .../shotgunFire2.imageset/Contents.json | 0 .../shotgunFire2.imageset/shotgunFire2.png | Bin .../shotgunFire3.imageset/Contents.json | 0 .../shotgunFire3.imageset/shotgunFire3.png | Bin .../shotgunFire4.imageset/Contents.json | 0 .../shotgunFire4.imageset/shotgunFire4.png | Bin .../shotgunIcon.imageset/Contents.json | 2 +- .../shotgunIcon.imageset/shotgunIcon.png | Bin .../shotgunPickup.imageset/Contents.json | 0 .../shotgunPickup.imageset/shotgunPickup.png | Bin .../slimeWall.imageset/Contents.json | 0 .../slimeWall.imageset/slimeWall.png | Bin .../slimeWall2.imageset/Contents.json | 0 .../slimeWall2.imageset/slimeWall2.png | Bin .../switch1.imageset/Contents.json | 0 .../switch1.imageset/switch1.png | Bin .../switch2.imageset/Contents.json | 0 .../switch2.imageset/switch2.png | Bin .../switch3.imageset/Contents.json | 0 .../switch3.imageset/switch3.png | Bin .../switch4.imageset/Contents.json | 0 .../switch4.imageset/switch4.png | Bin .../titleBackground.imageset/Contents.json | 0 .../titleBackground.png | Bin .../titleLogo.imageset/Contents.json | 0 .../titleLogo.imageset/titleLogo.png | Bin .../wall.imageset/Contents.json | 0 .../wall.imageset/wall.png | Bin .../wall2.imageset/Contents.json | 0 .../wall2.imageset/wall2.png | Bin Source/{Rampage => Shared}/SoundManager.swift | 0 .../{Rampage => Shared}/Sounds/doorSlide.mp3 | Bin Source/{Rampage => Shared}/Sounds/medkit.mp3 | Bin .../Sounds/monsterDeath.mp3 | Bin .../Sounds/monsterGroan.mp3 | Bin .../{Rampage => Shared}/Sounds/monsterHit.mp3 | Bin .../Sounds/monsterSwipe.mp3 | Bin .../{Rampage => Shared}/Sounds/pistolFire.mp3 | Bin .../Sounds/playerDeath.mp3 | Bin .../{Rampage => Shared}/Sounds/playerWalk.mp3 | Bin .../{Rampage => Shared}/Sounds/ricochet.mp3 | Bin .../Sounds/shotgunFire.mp3 | Bin .../Sounds/shotgunPickup.mp3 | Bin Source/{Rampage => Shared}/Sounds/squelch.mp3 | Bin .../{Rampage => Shared}/Sounds/switchFlip.mp3 | Bin .../{Rampage => Shared}/Sounds/wallSlide.mp3 | Bin .../{Rampage => Shared}/Sounds/wallThud.mp3 | Bin .../{Rampage => Shared}/UIImage+Bitmap.swift | 0 .../{Rampage => Shared}/ViewController.swift | 10 +- TVOS.md | 46 +++ 159 files changed, 830 insertions(+), 31 deletions(-) create mode 100644 Source/Rampage.xcodeproj/xcshareddata/xcschemes/RampageTV.xcscheme create mode 100644 Source/RampageTV/AppDelegate.swift create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json create mode 100644 Source/RampageTV/Assets.xcassets/Contents.json create mode 100644 Source/RampageTV/Base.lproj/LaunchScreen.storyboard create mode 100644 Source/RampageTV/Base.lproj/Main.storyboard create mode 100644 Source/RampageTV/Info.plist rename Source/{Rampage => Shared}/Font.json (100%) rename Source/{Rampage => Shared}/GameControllerManager+Input.swift (100%) rename Source/{Rampage => Shared}/GameControllerManager.swift (100%) rename Source/{Rampage => Shared}/Levels.json (100%) create mode 100644 Source/Shared/SharedAssets.xcassets/Contents.json rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/ceiling.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/ceiling.imageset/ceiling.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/crackFloor.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/crackFloor.imageset/crackFloor.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/crackWall.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/crackWall.imageset/crackWall.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/crackWall2.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/crackWall2.imageset/crackWall2.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/crosshair.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/crosshair.imageset/crosshair.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/door.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/door.imageset/door.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/door2.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/door2.imageset/door2.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/doorjamb.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/doorjamb.imageset/doorjamb.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/doorjamb2.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/doorjamb2.imageset/doorjamb2.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/elevatorBackWall.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/elevatorBackWall.imageset/elevatorBackWall.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/elevatorCeiling.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/elevatorCeiling.imageset/elevatorCeiling.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/elevatorFloor.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/elevatorFloor.imageset/elevatorFloor.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/elevatorSideWall.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/elevatorSideWall.imageset/elevatorSideWall.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/floor.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/floor.imageset/floor.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/font.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/font.imageset/font.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/healthIcon.imageset/Contents.json (99%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/healthIcon.imageset/healthIcon.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/medkit.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/medkit.imageset/medkit.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monster.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monster.imageset/monster.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterDead.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterDead.imageset/monsterDead.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterDeath1.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterDeath1.imageset/monsterDeath1.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterDeath2.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterDeath2.imageset/monsterDeath2.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterHurt.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterHurt.imageset/monsterHurt.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch1.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch1.imageset/monsterScratch1.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch2.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch2.imageset/monsterScratch2.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch3.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch3.imageset/monsterScratch3.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch4.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch4.imageset/monsterScratch4.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch5.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch5.imageset/monsterScratch5.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch6.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch6.imageset/monsterScratch6.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch7.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch7.imageset/monsterScratch7.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch8.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterScratch8.imageset/monsterScratch8.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterWalk1.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterWalk1.imageset/monsterWalk1.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterWalk2.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/monsterWalk2.imageset/monsterWalk2.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistol.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistol.imageset/pistol.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistolFire1.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistolFire1.imageset/pistolFire1.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistolFire2.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistolFire2.imageset/pistolFire2.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistolFire3.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistolFire3.imageset/pistolFire3.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistolFire4.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistolFire4.imageset/pistolFire4.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistolIcon.imageset/Contents.json (99%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/pistolIcon.imageset/pistolIcon.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgun.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgun.imageset/shotgun.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunFire1.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunFire1.imageset/shotgunFire1.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunFire2.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunFire2.imageset/shotgunFire2.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunFire3.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunFire3.imageset/shotgunFire3.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunFire4.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunFire4.imageset/shotgunFire4.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunIcon.imageset/Contents.json (99%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunIcon.imageset/shotgunIcon.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunPickup.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/shotgunPickup.imageset/shotgunPickup.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/slimeWall.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/slimeWall.imageset/slimeWall.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/slimeWall2.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/slimeWall2.imageset/slimeWall2.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/switch1.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/switch1.imageset/switch1.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/switch2.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/switch2.imageset/switch2.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/switch3.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/switch3.imageset/switch3.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/switch4.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/switch4.imageset/switch4.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/titleBackground.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/titleBackground.imageset/titleBackground.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/titleLogo.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/titleLogo.imageset/titleLogo.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/wall.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/wall.imageset/wall.png (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/wall2.imageset/Contents.json (100%) rename Source/{Rampage/Assets.xcassets => Shared/SharedAssets.xcassets}/wall2.imageset/wall2.png (100%) rename Source/{Rampage => Shared}/SoundManager.swift (100%) rename Source/{Rampage => Shared}/Sounds/doorSlide.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/medkit.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/monsterDeath.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/monsterGroan.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/monsterHit.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/monsterSwipe.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/pistolFire.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/playerDeath.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/playerWalk.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/ricochet.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/shotgunFire.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/shotgunPickup.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/squelch.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/switchFlip.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/wallSlide.mp3 (100%) rename Source/{Rampage => Shared}/Sounds/wallThud.mp3 (100%) rename Source/{Rampage => Shared}/UIImage+Bitmap.swift (100%) rename Source/{Rampage => Shared}/ViewController.swift (96%) create mode 100644 TVOS.md diff --git a/Source/Rampage.xcodeproj/project.pbxproj b/Source/Rampage.xcodeproj/project.pbxproj index 2f8a479..12c2dcc 100644 --- a/Source/Rampage.xcodeproj/project.pbxproj +++ b/Source/Rampage.xcodeproj/project.pbxproj @@ -15,6 +15,10 @@ 0108A66923F4D9B70075E1AF /* Textures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0108A66823F4D9B70075E1AF /* Textures.swift */; }; 0108A66F23F543750075E1AF /* Pathfinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0108A66E23F543740075E1AF /* Pathfinder.swift */; }; 010978C124694477002CC646 /* MapGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 010978C024694477002CC646 /* MapGenerator.swift */; }; + 01267214242E47360065863B /* Engine.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 016E41C9228E9A8600ACF137 /* Engine.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 01267218242E47360065863B /* Renderer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0108A65723F4D84C0075E1AF /* Renderer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 0126721B242E48BD0065863B /* Engine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 016E41C9228E9A8600ACF137 /* Engine.framework */; }; + 0126721C242E48BD0065863B /* Renderer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0108A65723F4D84C0075E1AF /* Renderer.framework */; }; 0128F26223EEE7AE00439050 /* shotgunFire.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0128F26123EEE7AE00439050 /* shotgunFire.mp3 */; }; 0128F26423EEEB0A00439050 /* shotgunPickup.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0128F26323EEEB0A00439050 /* shotgunPickup.mp3 */; }; 012A0C4D22C96E150068E8EF /* Tile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A0C4C22C96E150068E8EF /* Tile.swift */; }; @@ -34,7 +38,7 @@ 016E41B3228E9A5B00ACF137 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016E41B2228E9A5B00ACF137 /* AppDelegate.swift */; }; 016E41B5228E9A5B00ACF137 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016E41B4228E9A5B00ACF137 /* ViewController.swift */; }; 016E41B8228E9A5B00ACF137 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 016E41B6228E9A5B00ACF137 /* Main.storyboard */; }; - 016E41BA228E9A5E00ACF137 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 016E41B9228E9A5E00ACF137 /* Assets.xcassets */; }; + 016E41BA228E9A5E00ACF137 /* SharedAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 016E41B9228E9A5E00ACF137 /* SharedAssets.xcassets */; }; 016E41BD228E9A5E00ACF137 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 016E41BB228E9A5E00ACF137 /* LaunchScreen.storyboard */; }; 016E41D0228E9A8600ACF137 /* Engine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 016E41C9228E9A8600ACF137 /* Engine.framework */; }; 016E41D1228E9A8600ACF137 /* Engine.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 016E41C9228E9A8600ACF137 /* Engine.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -53,6 +57,9 @@ 0199F56E23E1A517003E3F08 /* wallThud.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F56123E1A517003E3F08 /* wallThud.mp3 */; }; 0199F57023E1AFEA003E3F08 /* Sounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0199F56F23E1AFEA003E3F08 /* Sounds.swift */; }; 0199F57423E242D4003E3F08 /* SoundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0199F57323E242D4003E3F08 /* SoundManager.swift */; }; + 01A377DF2454C5850040E02B /* Font.json in Resources */ = {isa = PBXBuildFile; fileRef = 01A377DE2454C5840040E02B /* Font.json */; }; + 01A377E02454C5850040E02B /* Font.json in Resources */ = {isa = PBXBuildFile; fileRef = 01A377DE2454C5840040E02B /* Font.json */; }; + 01A84FA8242D5D6B00A7ACD0 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D560412A24290D5000C08E5C /* GameController.framework */; }; 01ADC64022B9846B00DC8AAD /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01ADC63F22B9846B00DC8AAD /* World.swift */; }; 01D09AF522A482450052745A /* UIImage+Bitmap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AF422A482450052745A /* UIImage+Bitmap.swift */; }; 01D09AF922A484B10052745A /* Vector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AF822A484B10052745A /* Vector.swift */; }; @@ -66,10 +73,39 @@ 01D09B0B22A7F7570052745A /* Texture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09B0A22A7F7570052745A /* Texture.swift */; }; 01D0F5D922F80E1600682CA1 /* RampageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D0F5D822F80E1600682CA1 /* RampageTests.swift */; }; 01D0F5F122FF095E00682CA1 /* Door.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D0F5F022FF095E00682CA1 /* Door.swift */; }; - 01DD25AA244FA74900D00FE5 /* Font.json in Resources */ = {isa = PBXBuildFile; fileRef = 01DD25A9244FA74900D00FE5 /* Font.json */; }; 01DD25AC244FA85E00D00FE5 /* Font.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DD25AB244FA85E00D00FE5 /* Font.swift */; }; 01E3963A2342758D00D02236 /* Pushwall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01E396392342758D00D02236 /* Pushwall.swift */; }; 01EDA5DB2444DC2C00FC1795 /* Game.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EDA5DA2444DC2B00FC1795 /* Game.swift */; }; + D56040BB2429021200C08E5C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D56040BA2429021200C08E5C /* AppDelegate.swift */; }; + D56040C02429021300C08E5C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D56040BE2429021200C08E5C /* Main.storyboard */; }; + D56040C22429021500C08E5C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D56040C12429021500C08E5C /* Assets.xcassets */; }; + D56040C52429021500C08E5C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D56040C32429021500C08E5C /* LaunchScreen.storyboard */; }; + D56040CA242903E100C08E5C /* SharedAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 016E41B9228E9A5E00ACF137 /* SharedAssets.xcassets */; }; + D56040CC242903F300C08E5C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D56040CB242903F300C08E5C /* Assets.xcassets */; }; + D56040CD2429050100C08E5C /* pistolFire.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55623E1A517003E3F08 /* pistolFire.mp3 */; }; + D56040CE2429050100C08E5C /* shotgunFire.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0128F26123EEE7AE00439050 /* shotgunFire.mp3 */; }; + D56040CF2429050100C08E5C /* shotgunPickup.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0128F26323EEEB0A00439050 /* shotgunPickup.mp3 */; }; + D56040D02429050100C08E5C /* monsterGroan.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55F23E1A517003E3F08 /* monsterGroan.mp3 */; }; + D56040D12429050100C08E5C /* monsterSwipe.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55523E1A517003E3F08 /* monsterSwipe.mp3 */; }; + D56040D22429050100C08E5C /* monsterHit.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55A23E1A517003E3F08 /* monsterHit.mp3 */; }; + D56040D32429050100C08E5C /* monsterDeath.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55D23E1A517003E3F08 /* monsterDeath.mp3 */; }; + D56040D42429050100C08E5C /* ricochet.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55C23E1A517003E3F08 /* ricochet.mp3 */; }; + D56040D52429050100C08E5C /* playerWalk.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55923E1A517003E3F08 /* playerWalk.mp3 */; }; + D56040D62429050100C08E5C /* playerDeath.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55E23E1A517003E3F08 /* playerDeath.mp3 */; }; + D56040D72429050100C08E5C /* squelch.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55B23E1A517003E3F08 /* squelch.mp3 */; }; + D56040D82429050100C08E5C /* doorSlide.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55823E1A517003E3F08 /* doorSlide.mp3 */; }; + D56040D92429050100C08E5C /* wallSlide.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F55723E1A517003E3F08 /* wallSlide.mp3 */; }; + D56040DA2429050100C08E5C /* wallThud.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F56123E1A517003E3F08 /* wallThud.mp3 */; }; + D56040DB2429050100C08E5C /* switchFlip.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 0199F56023E1A517003E3F08 /* switchFlip.mp3 */; }; + D56040DC2429050100C08E5C /* medkit.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 013D492423ED607D00763FCA /* medkit.mp3 */; }; + D5604121242907A100C08E5C /* GameControllerManager+Input.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AA3B912427B3E5004908CD /* GameControllerManager+Input.swift */; }; + D5604122242907A100C08E5C /* GameControllerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AA3B922427B3E5004908CD /* GameControllerManager.swift */; }; + D5604123242907A100C08E5C /* SoundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0199F57323E242D4003E3F08 /* SoundManager.swift */; }; + D5604124242907A100C08E5C /* UIImage+Bitmap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D09AF422A482450052745A /* UIImage+Bitmap.swift */; }; + D5604125242907B400C08E5C /* Levels.json in Resources */ = {isa = PBXBuildFile; fileRef = 01D09B0022A493A70052745A /* Levels.json */; }; + D5604129242909E700C08E5C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016E41B4228E9A5B00ACF137 /* ViewController.swift */; }; + D56041352429127100C08E5C /* Engine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 016E41C9228E9A8600ACF137 /* Engine.framework */; }; + D56041362429127100C08E5C /* Engine.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 016E41C9228E9A8600ACF137 /* Engine.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; D5AA3B932427B3E5004908CD /* GameControllerManager+Input.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AA3B912427B3E5004908CD /* GameControllerManager+Input.swift */; }; D5AA3B942427B3E5004908CD /* GameControllerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AA3B922427B3E5004908CD /* GameControllerManager.swift */; }; /* End PBXBuildFile section */ @@ -89,6 +125,34 @@ remoteGlobalIDString = 016E41C8228E9A8600ACF137; remoteInfo = Engine; }; + 0126720F242E47290065863B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 016E41A7228E9A5B00ACF137 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 016E41C8228E9A8600ACF137; + remoteInfo = Engine; + }; + 01267211242E47290065863B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 016E41A7228E9A5B00ACF137 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0108A65623F4D84C0075E1AF; + remoteInfo = Renderer; + }; + 01267215242E47360065863B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 016E41A7228E9A5B00ACF137 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 016E41C8228E9A8600ACF137; + remoteInfo = Engine; + }; + 01267219242E47360065863B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 016E41A7228E9A5B00ACF137 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0108A65623F4D84C0075E1AF; + remoteInfo = Renderer; + }; 016E41CE228E9A8600ACF137 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 016E41A7228E9A5B00ACF137 /* Project object */; @@ -103,6 +167,13 @@ remoteGlobalIDString = 016E41AE228E9A5B00ACF137; remoteInfo = Rampage; }; + D56041372429127100C08E5C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 016E41A7228E9A5B00ACF137 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 016E41C8228E9A8600ACF137; + remoteInfo = Engine; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -118,6 +189,29 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; + D56040F3242905AF00C08E5C /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 01267214242E47360065863B /* Engine.framework in Embed Frameworks */, + 01267218242E47360065863B /* Renderer.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + D56041392429127100C08E5C /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + D56041362429127100C08E5C /* Engine.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -146,7 +240,7 @@ 016E41B2228E9A5B00ACF137 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 016E41B4228E9A5B00ACF137 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 016E41B7228E9A5B00ACF137 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 016E41B9228E9A5E00ACF137 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 016E41B9228E9A5E00ACF137 /* SharedAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = SharedAssets.xcassets; sourceTree = ""; }; 016E41BC228E9A5E00ACF137 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 016E41BE228E9A5E00ACF137 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 016E41C9228E9A8600ACF137 /* Engine.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Engine.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -166,6 +260,7 @@ 0199F56123E1A517003E3F08 /* wallThud.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = wallThud.mp3; sourceTree = ""; }; 0199F56F23E1AFEA003E3F08 /* Sounds.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sounds.swift; sourceTree = ""; }; 0199F57323E242D4003E3F08 /* SoundManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoundManager.swift; sourceTree = ""; }; + 01A377DE2454C5840040E02B /* Font.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Font.json; sourceTree = ""; }; 01ADC63B22B957FD00DC8AAD /* Renderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Renderer.swift; sourceTree = ""; }; 01ADC63F22B9846B00DC8AAD /* World.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = ""; }; 01D09AF022A481AB0052745A /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; @@ -184,10 +279,17 @@ 01D0F5D822F80E1600682CA1 /* RampageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RampageTests.swift; sourceTree = ""; }; 01D0F5DA22F80E1600682CA1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 01D0F5F022FF095E00682CA1 /* Door.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Door.swift; sourceTree = ""; }; - 01DD25A9244FA74900D00FE5 /* Font.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Font.json; sourceTree = ""; }; 01DD25AB244FA85E00D00FE5 /* Font.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Font.swift; sourceTree = ""; }; 01E396392342758D00D02236 /* Pushwall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pushwall.swift; sourceTree = ""; }; 01EDA5DA2444DC2B00FC1795 /* Game.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Game.swift; sourceTree = ""; }; + D56040B82429021200C08E5C /* Rampage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Rampage.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D56040BA2429021200C08E5C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + D56040BF2429021200C08E5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + D56040C12429021500C08E5C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + D56040C42429021500C08E5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + D56040C62429021500C08E5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D56040CB242903F300C08E5C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + D560412A24290D5000C08E5C /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS13.2.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; }; D5AA3B912427B3E5004908CD /* GameControllerManager+Input.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GameControllerManager+Input.swift"; sourceTree = ""; }; D5AA3B922427B3E5004908CD /* GameControllerManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameControllerManager.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -197,6 +299,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D56041352429127100C08E5C /* Engine.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -223,6 +326,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D56040B52429021200C08E5C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0126721B242E48BD0065863B /* Engine.framework in Frameworks */, + 0126721C242E48BD0065863B /* Renderer.framework in Frameworks */, + 01A84FA8242D5D6B00A7ACD0 /* GameController.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -240,6 +353,7 @@ 0108A66A23F4DA580075E1AF /* Frameworks */ = { isa = PBXGroup; children = ( + D560412A24290D5000C08E5C /* GameController.framework */, ); name = Frameworks; sourceTree = ""; @@ -247,7 +361,9 @@ 016E41A6228E9A5B00ACF137 = { isa = PBXGroup; children = ( + D56040B32429019D00C08E5C /* Shared */, 016E41B1228E9A5B00ACF137 /* Rampage */, + D56040B92429021200C08E5C /* RampageTV */, 016E41CA228E9A8600ACF137 /* Engine */, 0108A65823F4D84C0075E1AF /* Renderer */, 01D0F5D722F80E1600682CA1 /* RampageTests */, @@ -263,6 +379,7 @@ 016E41C9228E9A8600ACF137 /* Engine.framework */, 01D0F5D622F80E1600682CA1 /* RampageTests.xctest */, 0108A65723F4D84C0075E1AF /* Renderer.framework */, + D56040B82429021200C08E5C /* Rampage.app */, ); name = Products; sourceTree = ""; @@ -271,18 +388,10 @@ isa = PBXGroup; children = ( 016E41B2228E9A5B00ACF137 /* AppDelegate.swift */, - 016E41B4228E9A5B00ACF137 /* ViewController.swift */, - 01D09AF422A482450052745A /* UIImage+Bitmap.swift */, - 0199F57323E242D4003E3F08 /* SoundManager.swift */, - D5AA3B922427B3E5004908CD /* GameControllerManager.swift */, - D5AA3B912427B3E5004908CD /* GameControllerManager+Input.swift */, 016E41B6228E9A5B00ACF137 /* Main.storyboard */, - 01D09B0022A493A70052745A /* Levels.json */, - 01DD25A9244FA74900D00FE5 /* Font.json */, - 016E41B9228E9A5E00ACF137 /* Assets.xcassets */, - 0199F55423E1A517003E3F08 /* Sounds */, 016E41BB228E9A5E00ACF137 /* LaunchScreen.storyboard */, 016E41BE228E9A5E00ACF137 /* Info.plist */, + D56040CB242903F300C08E5C /* Assets.xcassets */, ); path = Rampage; sourceTree = ""; @@ -357,6 +466,34 @@ path = RampageTests; sourceTree = ""; }; + D56040B32429019D00C08E5C /* Shared */ = { + isa = PBXGroup; + children = ( + 01D09AF422A482450052745A /* UIImage+Bitmap.swift */, + 0199F57323E242D4003E3F08 /* SoundManager.swift */, + D5AA3B922427B3E5004908CD /* GameControllerManager.swift */, + D5AA3B912427B3E5004908CD /* GameControllerManager+Input.swift */, + 01D09B0022A493A70052745A /* Levels.json */, + 01A377DE2454C5840040E02B /* Font.json */, + 016E41B4228E9A5B00ACF137 /* ViewController.swift */, + 016E41B9228E9A5E00ACF137 /* SharedAssets.xcassets */, + 0199F55423E1A517003E3F08 /* Sounds */, + ); + path = Shared; + sourceTree = ""; + }; + D56040B92429021200C08E5C /* RampageTV */ = { + isa = PBXGroup; + children = ( + D56040BA2429021200C08E5C /* AppDelegate.swift */, + D56040BE2429021200C08E5C /* Main.storyboard */, + D56040C12429021500C08E5C /* Assets.xcassets */, + D56040C32429021500C08E5C /* LaunchScreen.storyboard */, + D56040C62429021500C08E5C /* Info.plist */, + ); + path = RampageTV; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -385,11 +522,13 @@ 0108A65323F4D84C0075E1AF /* Sources */, 0108A65423F4D84C0075E1AF /* Frameworks */, 0108A65523F4D84C0075E1AF /* Resources */, + D56041392429127100C08E5C /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( 0108A66D23F4DA5D0075E1AF /* PBXTargetDependency */, + D56041382429127100C08E5C /* PBXTargetDependency */, ); name = Renderer; productName = Renderer; @@ -452,6 +591,28 @@ productReference = 01D0F5D622F80E1600682CA1 /* RampageTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + D56040B72429021200C08E5C /* RampageTV */ = { + isa = PBXNativeTarget; + buildConfigurationList = D56040C72429021500C08E5C /* Build configuration list for PBXNativeTarget "RampageTV" */; + buildPhases = ( + D56040B42429021200C08E5C /* Sources */, + D56040B52429021200C08E5C /* Frameworks */, + D56040B62429021200C08E5C /* Resources */, + D56040F3242905AF00C08E5C /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 01267210242E47290065863B /* PBXTargetDependency */, + 01267212242E47290065863B /* PBXTargetDependency */, + 01267216242E47360065863B /* PBXTargetDependency */, + 0126721A242E47360065863B /* PBXTargetDependency */, + ); + name = RampageTV; + productName = RampageTvOS; + productReference = D56040B82429021200C08E5C /* Rampage.app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -459,8 +620,8 @@ isa = PBXProject; attributes = { DefaultBuildSystemTypeForWorkspace = Original; - LastSwiftUpdateCheck = 1010; - LastUpgradeCheck = 1130; + LastSwiftUpdateCheck = 1130; + LastUpgradeCheck = 1010; ORGANIZATIONNAME = "Nick Lockwood"; TargetAttributes = { 0108A65623F4D84C0075E1AF = { @@ -480,6 +641,9 @@ LastSwiftMigration = 1130; TestTargetID = 016E41AE228E9A5B00ACF137; }; + D56040B72429021200C08E5C = { + CreatedOnToolsVersion = 11.3.1; + }; }; }; buildConfigurationList = 016E41AA228E9A5B00ACF137 /* Build configuration list for PBXProject "Rampage" */; @@ -496,6 +660,7 @@ projectRoot = ""; targets = ( 016E41AE228E9A5B00ACF137 /* Rampage */, + D56040B72429021200C08E5C /* RampageTV */, 016E41C8228E9A8600ACF137 /* Engine */, 0108A65623F4D84C0075E1AF /* Renderer */, 01D0F5D522F80E1600682CA1 /* RampageTests */, @@ -516,15 +681,16 @@ buildActionMask = 2147483647; files = ( 0128F26223EEE7AE00439050 /* shotgunFire.mp3 in Resources */, - 01DD25AA244FA74900D00FE5 /* Font.json in Resources */, 0199F56E23E1A517003E3F08 /* wallThud.mp3 in Resources */, 0199F56623E1A517003E3F08 /* playerWalk.mp3 in Resources */, 0199F56C23E1A517003E3F08 /* monsterGroan.mp3 in Resources */, + D56040CC242903F300C08E5C /* Assets.xcassets in Resources */, + 01A377DF2454C5850040E02B /* Font.json in Resources */, 0199F56523E1A517003E3F08 /* doorSlide.mp3 in Resources */, 016E41BD228E9A5E00ACF137 /* LaunchScreen.storyboard in Resources */, 0199F56423E1A517003E3F08 /* wallSlide.mp3 in Resources */, 0199F56323E1A517003E3F08 /* pistolFire.mp3 in Resources */, - 016E41BA228E9A5E00ACF137 /* Assets.xcassets in Resources */, + 016E41BA228E9A5E00ACF137 /* SharedAssets.xcassets in Resources */, 013D492523ED607D00763FCA /* medkit.mp3 in Resources */, 0199F56223E1A517003E3F08 /* monsterSwipe.mp3 in Resources */, 01D09B0122A493A70052745A /* Levels.json in Resources */, @@ -553,6 +719,35 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D56040B62429021200C08E5C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D56040D82429050100C08E5C /* doorSlide.mp3 in Resources */, + D56040D52429050100C08E5C /* playerWalk.mp3 in Resources */, + D56040CD2429050100C08E5C /* pistolFire.mp3 in Resources */, + D56040DA2429050100C08E5C /* wallThud.mp3 in Resources */, + D56040CE2429050100C08E5C /* shotgunFire.mp3 in Resources */, + D56040C52429021500C08E5C /* LaunchScreen.storyboard in Resources */, + D56040DC2429050100C08E5C /* medkit.mp3 in Resources */, + D56040D12429050100C08E5C /* monsterSwipe.mp3 in Resources */, + D56040C22429021500C08E5C /* Assets.xcassets in Resources */, + D56040C02429021300C08E5C /* Main.storyboard in Resources */, + D56040D92429050100C08E5C /* wallSlide.mp3 in Resources */, + D56040D02429050100C08E5C /* monsterGroan.mp3 in Resources */, + D56040DB2429050100C08E5C /* switchFlip.mp3 in Resources */, + D56040CF2429050100C08E5C /* shotgunPickup.mp3 in Resources */, + D56040CA242903E100C08E5C /* SharedAssets.xcassets in Resources */, + D5604125242907B400C08E5C /* Levels.json in Resources */, + D56040D22429050100C08E5C /* monsterHit.mp3 in Resources */, + D56040D32429050100C08E5C /* monsterDeath.mp3 in Resources */, + 01A377E02454C5850040E02B /* Font.json in Resources */, + D56040D62429050100C08E5C /* playerDeath.mp3 in Resources */, + D56040D42429050100C08E5C /* ricochet.mp3 in Resources */, + D56040D72429050100C08E5C /* squelch.mp3 in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -624,6 +819,19 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D56040B42429021200C08E5C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D5604129242909E700C08E5C /* ViewController.swift in Sources */, + D56040BB2429021200C08E5C /* AppDelegate.swift in Sources */, + D5604124242907A100C08E5C /* UIImage+Bitmap.swift in Sources */, + D5604121242907A100C08E5C /* GameControllerManager+Input.swift in Sources */, + D5604122242907A100C08E5C /* GameControllerManager.swift in Sources */, + D5604123242907A100C08E5C /* SoundManager.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -637,6 +845,26 @@ target = 016E41C8228E9A8600ACF137 /* Engine */; targetProxy = 0108A66C23F4DA5D0075E1AF /* PBXContainerItemProxy */; }; + 01267210242E47290065863B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 016E41C8228E9A8600ACF137 /* Engine */; + targetProxy = 0126720F242E47290065863B /* PBXContainerItemProxy */; + }; + 01267212242E47290065863B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0108A65623F4D84C0075E1AF /* Renderer */; + targetProxy = 01267211242E47290065863B /* PBXContainerItemProxy */; + }; + 01267216242E47360065863B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 016E41C8228E9A8600ACF137 /* Engine */; + targetProxy = 01267215242E47360065863B /* PBXContainerItemProxy */; + }; + 0126721A242E47360065863B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0108A65623F4D84C0075E1AF /* Renderer */; + targetProxy = 01267219242E47360065863B /* PBXContainerItemProxy */; + }; 016E41CF228E9A8600ACF137 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 016E41C8228E9A8600ACF137 /* Engine */; @@ -647,6 +875,11 @@ target = 016E41AE228E9A5B00ACF137 /* Rampage */; targetProxy = 01D0F5DB22F80E1600682CA1 /* PBXContainerItemProxy */; }; + D56041382429127100C08E5C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 016E41C8228E9A8600ACF137 /* Engine */; + targetProxy = D56041372429127100C08E5C /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -666,19 +899,36 @@ name = LaunchScreen.storyboard; sourceTree = ""; }; + D56040BE2429021200C08E5C /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + D56040BF2429021200C08E5C /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + D56040C32429021500C08E5C /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + D56040C42429021500C08E5C /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 0108A66023F4D84C0075E1AF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = 8VQKF583ED; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_OPTIMIZATION_LEVEL = s; INFOPLIST_FILE = Renderer/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( @@ -692,7 +942,7 @@ SWIFT_DISABLE_SAFETY_CHECKS = YES; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,3,4"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -701,6 +951,7 @@ 0108A66123F4D84C0075E1AF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; @@ -720,7 +971,7 @@ SKIP_INSTALL = YES; SWIFT_DISABLE_SAFETY_CHECKS = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,3,4"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -781,9 +1032,12 @@ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TVOS_DEPLOYMENT_TARGET = 12.1; + VALID_ARCHS = "arm64 arm64e armv7 armv7s i386 x86_64"; }; name = Debug; }; @@ -835,10 +1089,13 @@ IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; - SDKROOT = iphoneos; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator"; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; + TVOS_DEPLOYMENT_TARGET = 12.1; VALIDATE_PRODUCT = YES; + VALID_ARCHS = "arm64 arm64e armv7 armv7s i386 x86_64"; }; name = Release; }; @@ -856,6 +1113,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.Rampage; PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -875,6 +1134,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.Rampage; PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -888,7 +1149,6 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = 8VQKF583ED; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -905,7 +1165,7 @@ SWIFT_DISABLE_SAFETY_CHECKS = NO; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,3,4"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -936,7 +1196,7 @@ SKIP_INSTALL = YES; SWIFT_DISABLE_SAFETY_CHECKS = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,3,4"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -947,7 +1207,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 8VQKF583ED; + DEVELOPMENT_TEAM = B7H9Y9D4HC; INFOPLIST_FILE = RampageTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -967,7 +1227,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 8VQKF583ED; + DEVELOPMENT_TEAM = B7H9Y9D4HC; INFOPLIST_FILE = RampageTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -982,6 +1242,52 @@ }; name = Release; }; + D56040C82429021500C08E5C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + GCC_OPTIMIZATION_LEVEL = s; + INFOPLIST_FILE = RampageTV/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.Rampage; + PRODUCT_NAME = Rampage; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = appletvos; + SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + D56040C92429021500C08E5C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = RampageTV/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.charcoaldesign.Rampage; + PRODUCT_NAME = Rampage; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = appletvos; + SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -1030,6 +1336,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D56040C72429021500C08E5C /* Build configuration list for PBXNativeTarget "RampageTV" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D56040C82429021500C08E5C /* Debug */, + D56040C92429021500C08E5C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 016E41A7228E9A5B00ACF137 /* Project object */; diff --git a/Source/Rampage.xcodeproj/xcshareddata/xcschemes/RampageTV.xcscheme b/Source/Rampage.xcodeproj/xcshareddata/xcschemes/RampageTV.xcscheme new file mode 100644 index 0000000..00f7f0f --- /dev/null +++ b/Source/Rampage.xcodeproj/xcshareddata/xcschemes/RampageTV.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/RampageTV/AppDelegate.swift b/Source/RampageTV/AppDelegate.swift new file mode 100644 index 0000000..948a167 --- /dev/null +++ b/Source/RampageTV/AppDelegate.swift @@ -0,0 +1,14 @@ +// +// AppDelegate.swift +// RampageTV +// +// Created by PJ COOK on 23/03/2020. +// Copyright © 2020 Nick Lockwood. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? +} diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json new file mode 100644 index 0000000..db288f3 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json @@ -0,0 +1,32 @@ +{ + "assets" : [ + { + "size" : "1280x768", + "idiom" : "tv", + "filename" : "App Icon - App Store.imagestack", + "role" : "primary-app-icon" + }, + { + "size" : "400x240", + "idiom" : "tv", + "filename" : "App Icon.imagestack", + "role" : "primary-app-icon" + }, + { + "size" : "2320x720", + "idiom" : "tv", + "filename" : "Top Shelf Image Wide.imageset", + "role" : "top-shelf-image-wide" + }, + { + "size" : "1920x720", + "idiom" : "tv", + "filename" : "Top Shelf Image.imageset", + "role" : "top-shelf-image" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json new file mode 100644 index 0000000..7dc9502 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + }, + { + "idiom" : "tv-marketing", + "scale" : "1x" + }, + { + "idiom" : "tv-marketing", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json new file mode 100644 index 0000000..7dc9502 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + }, + { + "idiom" : "tv-marketing", + "scale" : "1x" + }, + { + "idiom" : "tv-marketing", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Assets.xcassets/Contents.json b/Source/RampageTV/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Source/RampageTV/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/RampageTV/Base.lproj/LaunchScreen.storyboard b/Source/RampageTV/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..660ba53 --- /dev/null +++ b/Source/RampageTV/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/RampageTV/Base.lproj/Main.storyboard b/Source/RampageTV/Base.lproj/Main.storyboard new file mode 100644 index 0000000..c277013 --- /dev/null +++ b/Source/RampageTV/Base.lproj/Main.storyboard @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/RampageTV/Info.plist b/Source/RampageTV/Info.plist new file mode 100644 index 0000000..34e4ad2 --- /dev/null +++ b/Source/RampageTV/Info.plist @@ -0,0 +1,43 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + GCSupportedGameControllers + + + ProfileName + ExtendedGamepad + + + GCSupportsControllerUserInteraction + + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + arm64 + + UIUserInterfaceStyle + Automatic + + diff --git a/Source/Rampage/Font.json b/Source/Shared/Font.json similarity index 100% rename from Source/Rampage/Font.json rename to Source/Shared/Font.json diff --git a/Source/Rampage/GameControllerManager+Input.swift b/Source/Shared/GameControllerManager+Input.swift similarity index 100% rename from Source/Rampage/GameControllerManager+Input.swift rename to Source/Shared/GameControllerManager+Input.swift diff --git a/Source/Rampage/GameControllerManager.swift b/Source/Shared/GameControllerManager.swift similarity index 100% rename from Source/Rampage/GameControllerManager.swift rename to Source/Shared/GameControllerManager.swift diff --git a/Source/Rampage/Levels.json b/Source/Shared/Levels.json similarity index 100% rename from Source/Rampage/Levels.json rename to Source/Shared/Levels.json diff --git a/Source/Shared/SharedAssets.xcassets/Contents.json b/Source/Shared/SharedAssets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Source/Shared/SharedAssets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/ceiling.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/ceiling.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/ceiling.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/ceiling.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/ceiling.imageset/ceiling.png b/Source/Shared/SharedAssets.xcassets/ceiling.imageset/ceiling.png similarity index 100% rename from Source/Rampage/Assets.xcassets/ceiling.imageset/ceiling.png rename to Source/Shared/SharedAssets.xcassets/ceiling.imageset/ceiling.png diff --git a/Source/Rampage/Assets.xcassets/crackFloor.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/crackFloor.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/crackFloor.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/crackFloor.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/crackFloor.imageset/crackFloor.png b/Source/Shared/SharedAssets.xcassets/crackFloor.imageset/crackFloor.png similarity index 100% rename from Source/Rampage/Assets.xcassets/crackFloor.imageset/crackFloor.png rename to Source/Shared/SharedAssets.xcassets/crackFloor.imageset/crackFloor.png diff --git a/Source/Rampage/Assets.xcassets/crackWall.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/crackWall.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/crackWall.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/crackWall.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/crackWall.imageset/crackWall.png b/Source/Shared/SharedAssets.xcassets/crackWall.imageset/crackWall.png similarity index 100% rename from Source/Rampage/Assets.xcassets/crackWall.imageset/crackWall.png rename to Source/Shared/SharedAssets.xcassets/crackWall.imageset/crackWall.png diff --git a/Source/Rampage/Assets.xcassets/crackWall2.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/crackWall2.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/crackWall2.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/crackWall2.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/crackWall2.imageset/crackWall2.png b/Source/Shared/SharedAssets.xcassets/crackWall2.imageset/crackWall2.png similarity index 100% rename from Source/Rampage/Assets.xcassets/crackWall2.imageset/crackWall2.png rename to Source/Shared/SharedAssets.xcassets/crackWall2.imageset/crackWall2.png diff --git a/Source/Rampage/Assets.xcassets/crosshair.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/crosshair.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/crosshair.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/crosshair.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/crosshair.imageset/crosshair.png b/Source/Shared/SharedAssets.xcassets/crosshair.imageset/crosshair.png similarity index 100% rename from Source/Rampage/Assets.xcassets/crosshair.imageset/crosshair.png rename to Source/Shared/SharedAssets.xcassets/crosshair.imageset/crosshair.png diff --git a/Source/Rampage/Assets.xcassets/door.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/door.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/door.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/door.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/door.imageset/door.png b/Source/Shared/SharedAssets.xcassets/door.imageset/door.png similarity index 100% rename from Source/Rampage/Assets.xcassets/door.imageset/door.png rename to Source/Shared/SharedAssets.xcassets/door.imageset/door.png diff --git a/Source/Rampage/Assets.xcassets/door2.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/door2.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/door2.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/door2.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/door2.imageset/door2.png b/Source/Shared/SharedAssets.xcassets/door2.imageset/door2.png similarity index 100% rename from Source/Rampage/Assets.xcassets/door2.imageset/door2.png rename to Source/Shared/SharedAssets.xcassets/door2.imageset/door2.png diff --git a/Source/Rampage/Assets.xcassets/doorjamb.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/doorjamb.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/doorjamb.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/doorjamb.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/doorjamb.imageset/doorjamb.png b/Source/Shared/SharedAssets.xcassets/doorjamb.imageset/doorjamb.png similarity index 100% rename from Source/Rampage/Assets.xcassets/doorjamb.imageset/doorjamb.png rename to Source/Shared/SharedAssets.xcassets/doorjamb.imageset/doorjamb.png diff --git a/Source/Rampage/Assets.xcassets/doorjamb2.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/doorjamb2.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/doorjamb2.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/doorjamb2.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/doorjamb2.imageset/doorjamb2.png b/Source/Shared/SharedAssets.xcassets/doorjamb2.imageset/doorjamb2.png similarity index 100% rename from Source/Rampage/Assets.xcassets/doorjamb2.imageset/doorjamb2.png rename to Source/Shared/SharedAssets.xcassets/doorjamb2.imageset/doorjamb2.png diff --git a/Source/Rampage/Assets.xcassets/elevatorBackWall.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/elevatorBackWall.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/elevatorBackWall.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/elevatorBackWall.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/elevatorBackWall.imageset/elevatorBackWall.png b/Source/Shared/SharedAssets.xcassets/elevatorBackWall.imageset/elevatorBackWall.png similarity index 100% rename from Source/Rampage/Assets.xcassets/elevatorBackWall.imageset/elevatorBackWall.png rename to Source/Shared/SharedAssets.xcassets/elevatorBackWall.imageset/elevatorBackWall.png diff --git a/Source/Rampage/Assets.xcassets/elevatorCeiling.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/elevatorCeiling.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/elevatorCeiling.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/elevatorCeiling.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/elevatorCeiling.imageset/elevatorCeiling.png b/Source/Shared/SharedAssets.xcassets/elevatorCeiling.imageset/elevatorCeiling.png similarity index 100% rename from Source/Rampage/Assets.xcassets/elevatorCeiling.imageset/elevatorCeiling.png rename to Source/Shared/SharedAssets.xcassets/elevatorCeiling.imageset/elevatorCeiling.png diff --git a/Source/Rampage/Assets.xcassets/elevatorFloor.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/elevatorFloor.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/elevatorFloor.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/elevatorFloor.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/elevatorFloor.imageset/elevatorFloor.png b/Source/Shared/SharedAssets.xcassets/elevatorFloor.imageset/elevatorFloor.png similarity index 100% rename from Source/Rampage/Assets.xcassets/elevatorFloor.imageset/elevatorFloor.png rename to Source/Shared/SharedAssets.xcassets/elevatorFloor.imageset/elevatorFloor.png diff --git a/Source/Rampage/Assets.xcassets/elevatorSideWall.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/elevatorSideWall.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/elevatorSideWall.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/elevatorSideWall.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/elevatorSideWall.imageset/elevatorSideWall.png b/Source/Shared/SharedAssets.xcassets/elevatorSideWall.imageset/elevatorSideWall.png similarity index 100% rename from Source/Rampage/Assets.xcassets/elevatorSideWall.imageset/elevatorSideWall.png rename to Source/Shared/SharedAssets.xcassets/elevatorSideWall.imageset/elevatorSideWall.png diff --git a/Source/Rampage/Assets.xcassets/floor.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/floor.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/floor.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/floor.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/floor.imageset/floor.png b/Source/Shared/SharedAssets.xcassets/floor.imageset/floor.png similarity index 100% rename from Source/Rampage/Assets.xcassets/floor.imageset/floor.png rename to Source/Shared/SharedAssets.xcassets/floor.imageset/floor.png diff --git a/Source/Rampage/Assets.xcassets/font.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/font.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/font.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/font.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/font.imageset/font.png b/Source/Shared/SharedAssets.xcassets/font.imageset/font.png similarity index 100% rename from Source/Rampage/Assets.xcassets/font.imageset/font.png rename to Source/Shared/SharedAssets.xcassets/font.imageset/font.png diff --git a/Source/Rampage/Assets.xcassets/healthIcon.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/healthIcon.imageset/Contents.json similarity index 99% rename from Source/Rampage/Assets.xcassets/healthIcon.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/healthIcon.imageset/Contents.json index 7416da1..2df92c1 100644 --- a/Source/Rampage/Assets.xcassets/healthIcon.imageset/Contents.json +++ b/Source/Shared/SharedAssets.xcassets/healthIcon.imageset/Contents.json @@ -18,4 +18,4 @@ "version" : 1, "author" : "xcode" } -} +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/healthIcon.imageset/healthIcon.png b/Source/Shared/SharedAssets.xcassets/healthIcon.imageset/healthIcon.png similarity index 100% rename from Source/Rampage/Assets.xcassets/healthIcon.imageset/healthIcon.png rename to Source/Shared/SharedAssets.xcassets/healthIcon.imageset/healthIcon.png diff --git a/Source/Rampage/Assets.xcassets/medkit.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/medkit.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/medkit.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/medkit.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/medkit.imageset/medkit.png b/Source/Shared/SharedAssets.xcassets/medkit.imageset/medkit.png similarity index 100% rename from Source/Rampage/Assets.xcassets/medkit.imageset/medkit.png rename to Source/Shared/SharedAssets.xcassets/medkit.imageset/medkit.png diff --git a/Source/Rampage/Assets.xcassets/monster.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monster.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monster.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monster.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monster.imageset/monster.png b/Source/Shared/SharedAssets.xcassets/monster.imageset/monster.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monster.imageset/monster.png rename to Source/Shared/SharedAssets.xcassets/monster.imageset/monster.png diff --git a/Source/Rampage/Assets.xcassets/monsterDead.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterDead.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterDead.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterDead.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterDead.imageset/monsterDead.png b/Source/Shared/SharedAssets.xcassets/monsterDead.imageset/monsterDead.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterDead.imageset/monsterDead.png rename to Source/Shared/SharedAssets.xcassets/monsterDead.imageset/monsterDead.png diff --git a/Source/Rampage/Assets.xcassets/monsterDeath1.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterDeath1.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterDeath1.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterDeath1.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterDeath1.imageset/monsterDeath1.png b/Source/Shared/SharedAssets.xcassets/monsterDeath1.imageset/monsterDeath1.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterDeath1.imageset/monsterDeath1.png rename to Source/Shared/SharedAssets.xcassets/monsterDeath1.imageset/monsterDeath1.png diff --git a/Source/Rampage/Assets.xcassets/monsterDeath2.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterDeath2.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterDeath2.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterDeath2.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterDeath2.imageset/monsterDeath2.png b/Source/Shared/SharedAssets.xcassets/monsterDeath2.imageset/monsterDeath2.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterDeath2.imageset/monsterDeath2.png rename to Source/Shared/SharedAssets.xcassets/monsterDeath2.imageset/monsterDeath2.png diff --git a/Source/Rampage/Assets.xcassets/monsterHurt.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterHurt.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterHurt.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterHurt.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterHurt.imageset/monsterHurt.png b/Source/Shared/SharedAssets.xcassets/monsterHurt.imageset/monsterHurt.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterHurt.imageset/monsterHurt.png rename to Source/Shared/SharedAssets.xcassets/monsterHurt.imageset/monsterHurt.png diff --git a/Source/Rampage/Assets.xcassets/monsterScratch1.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterScratch1.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch1.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterScratch1.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterScratch1.imageset/monsterScratch1.png b/Source/Shared/SharedAssets.xcassets/monsterScratch1.imageset/monsterScratch1.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch1.imageset/monsterScratch1.png rename to Source/Shared/SharedAssets.xcassets/monsterScratch1.imageset/monsterScratch1.png diff --git a/Source/Rampage/Assets.xcassets/monsterScratch2.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterScratch2.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch2.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterScratch2.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterScratch2.imageset/monsterScratch2.png b/Source/Shared/SharedAssets.xcassets/monsterScratch2.imageset/monsterScratch2.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch2.imageset/monsterScratch2.png rename to Source/Shared/SharedAssets.xcassets/monsterScratch2.imageset/monsterScratch2.png diff --git a/Source/Rampage/Assets.xcassets/monsterScratch3.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterScratch3.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch3.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterScratch3.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterScratch3.imageset/monsterScratch3.png b/Source/Shared/SharedAssets.xcassets/monsterScratch3.imageset/monsterScratch3.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch3.imageset/monsterScratch3.png rename to Source/Shared/SharedAssets.xcassets/monsterScratch3.imageset/monsterScratch3.png diff --git a/Source/Rampage/Assets.xcassets/monsterScratch4.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterScratch4.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch4.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterScratch4.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterScratch4.imageset/monsterScratch4.png b/Source/Shared/SharedAssets.xcassets/monsterScratch4.imageset/monsterScratch4.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch4.imageset/monsterScratch4.png rename to Source/Shared/SharedAssets.xcassets/monsterScratch4.imageset/monsterScratch4.png diff --git a/Source/Rampage/Assets.xcassets/monsterScratch5.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterScratch5.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch5.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterScratch5.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterScratch5.imageset/monsterScratch5.png b/Source/Shared/SharedAssets.xcassets/monsterScratch5.imageset/monsterScratch5.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch5.imageset/monsterScratch5.png rename to Source/Shared/SharedAssets.xcassets/monsterScratch5.imageset/monsterScratch5.png diff --git a/Source/Rampage/Assets.xcassets/monsterScratch6.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterScratch6.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch6.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterScratch6.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterScratch6.imageset/monsterScratch6.png b/Source/Shared/SharedAssets.xcassets/monsterScratch6.imageset/monsterScratch6.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch6.imageset/monsterScratch6.png rename to Source/Shared/SharedAssets.xcassets/monsterScratch6.imageset/monsterScratch6.png diff --git a/Source/Rampage/Assets.xcassets/monsterScratch7.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterScratch7.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch7.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterScratch7.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterScratch7.imageset/monsterScratch7.png b/Source/Shared/SharedAssets.xcassets/monsterScratch7.imageset/monsterScratch7.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch7.imageset/monsterScratch7.png rename to Source/Shared/SharedAssets.xcassets/monsterScratch7.imageset/monsterScratch7.png diff --git a/Source/Rampage/Assets.xcassets/monsterScratch8.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterScratch8.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch8.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterScratch8.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterScratch8.imageset/monsterScratch8.png b/Source/Shared/SharedAssets.xcassets/monsterScratch8.imageset/monsterScratch8.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterScratch8.imageset/monsterScratch8.png rename to Source/Shared/SharedAssets.xcassets/monsterScratch8.imageset/monsterScratch8.png diff --git a/Source/Rampage/Assets.xcassets/monsterWalk1.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterWalk1.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterWalk1.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterWalk1.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterWalk1.imageset/monsterWalk1.png b/Source/Shared/SharedAssets.xcassets/monsterWalk1.imageset/monsterWalk1.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterWalk1.imageset/monsterWalk1.png rename to Source/Shared/SharedAssets.xcassets/monsterWalk1.imageset/monsterWalk1.png diff --git a/Source/Rampage/Assets.xcassets/monsterWalk2.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/monsterWalk2.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterWalk2.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/monsterWalk2.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/monsterWalk2.imageset/monsterWalk2.png b/Source/Shared/SharedAssets.xcassets/monsterWalk2.imageset/monsterWalk2.png similarity index 100% rename from Source/Rampage/Assets.xcassets/monsterWalk2.imageset/monsterWalk2.png rename to Source/Shared/SharedAssets.xcassets/monsterWalk2.imageset/monsterWalk2.png diff --git a/Source/Rampage/Assets.xcassets/pistol.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/pistol.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/pistol.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/pistol.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/pistol.imageset/pistol.png b/Source/Shared/SharedAssets.xcassets/pistol.imageset/pistol.png similarity index 100% rename from Source/Rampage/Assets.xcassets/pistol.imageset/pistol.png rename to Source/Shared/SharedAssets.xcassets/pistol.imageset/pistol.png diff --git a/Source/Rampage/Assets.xcassets/pistolFire1.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/pistolFire1.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/pistolFire1.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/pistolFire1.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/pistolFire1.imageset/pistolFire1.png b/Source/Shared/SharedAssets.xcassets/pistolFire1.imageset/pistolFire1.png similarity index 100% rename from Source/Rampage/Assets.xcassets/pistolFire1.imageset/pistolFire1.png rename to Source/Shared/SharedAssets.xcassets/pistolFire1.imageset/pistolFire1.png diff --git a/Source/Rampage/Assets.xcassets/pistolFire2.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/pistolFire2.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/pistolFire2.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/pistolFire2.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/pistolFire2.imageset/pistolFire2.png b/Source/Shared/SharedAssets.xcassets/pistolFire2.imageset/pistolFire2.png similarity index 100% rename from Source/Rampage/Assets.xcassets/pistolFire2.imageset/pistolFire2.png rename to Source/Shared/SharedAssets.xcassets/pistolFire2.imageset/pistolFire2.png diff --git a/Source/Rampage/Assets.xcassets/pistolFire3.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/pistolFire3.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/pistolFire3.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/pistolFire3.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/pistolFire3.imageset/pistolFire3.png b/Source/Shared/SharedAssets.xcassets/pistolFire3.imageset/pistolFire3.png similarity index 100% rename from Source/Rampage/Assets.xcassets/pistolFire3.imageset/pistolFire3.png rename to Source/Shared/SharedAssets.xcassets/pistolFire3.imageset/pistolFire3.png diff --git a/Source/Rampage/Assets.xcassets/pistolFire4.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/pistolFire4.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/pistolFire4.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/pistolFire4.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/pistolFire4.imageset/pistolFire4.png b/Source/Shared/SharedAssets.xcassets/pistolFire4.imageset/pistolFire4.png similarity index 100% rename from Source/Rampage/Assets.xcassets/pistolFire4.imageset/pistolFire4.png rename to Source/Shared/SharedAssets.xcassets/pistolFire4.imageset/pistolFire4.png diff --git a/Source/Rampage/Assets.xcassets/pistolIcon.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/pistolIcon.imageset/Contents.json similarity index 99% rename from Source/Rampage/Assets.xcassets/pistolIcon.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/pistolIcon.imageset/Contents.json index c9844cb..899e7a4 100644 --- a/Source/Rampage/Assets.xcassets/pistolIcon.imageset/Contents.json +++ b/Source/Shared/SharedAssets.xcassets/pistolIcon.imageset/Contents.json @@ -18,4 +18,4 @@ "version" : 1, "author" : "xcode" } -} +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/pistolIcon.imageset/pistolIcon.png b/Source/Shared/SharedAssets.xcassets/pistolIcon.imageset/pistolIcon.png similarity index 100% rename from Source/Rampage/Assets.xcassets/pistolIcon.imageset/pistolIcon.png rename to Source/Shared/SharedAssets.xcassets/pistolIcon.imageset/pistolIcon.png diff --git a/Source/Rampage/Assets.xcassets/shotgun.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/shotgun.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgun.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/shotgun.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/shotgun.imageset/shotgun.png b/Source/Shared/SharedAssets.xcassets/shotgun.imageset/shotgun.png similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgun.imageset/shotgun.png rename to Source/Shared/SharedAssets.xcassets/shotgun.imageset/shotgun.png diff --git a/Source/Rampage/Assets.xcassets/shotgunFire1.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/shotgunFire1.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgunFire1.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/shotgunFire1.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/shotgunFire1.imageset/shotgunFire1.png b/Source/Shared/SharedAssets.xcassets/shotgunFire1.imageset/shotgunFire1.png similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgunFire1.imageset/shotgunFire1.png rename to Source/Shared/SharedAssets.xcassets/shotgunFire1.imageset/shotgunFire1.png diff --git a/Source/Rampage/Assets.xcassets/shotgunFire2.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/shotgunFire2.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgunFire2.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/shotgunFire2.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/shotgunFire2.imageset/shotgunFire2.png b/Source/Shared/SharedAssets.xcassets/shotgunFire2.imageset/shotgunFire2.png similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgunFire2.imageset/shotgunFire2.png rename to Source/Shared/SharedAssets.xcassets/shotgunFire2.imageset/shotgunFire2.png diff --git a/Source/Rampage/Assets.xcassets/shotgunFire3.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/shotgunFire3.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgunFire3.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/shotgunFire3.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/shotgunFire3.imageset/shotgunFire3.png b/Source/Shared/SharedAssets.xcassets/shotgunFire3.imageset/shotgunFire3.png similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgunFire3.imageset/shotgunFire3.png rename to Source/Shared/SharedAssets.xcassets/shotgunFire3.imageset/shotgunFire3.png diff --git a/Source/Rampage/Assets.xcassets/shotgunFire4.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/shotgunFire4.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgunFire4.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/shotgunFire4.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/shotgunFire4.imageset/shotgunFire4.png b/Source/Shared/SharedAssets.xcassets/shotgunFire4.imageset/shotgunFire4.png similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgunFire4.imageset/shotgunFire4.png rename to Source/Shared/SharedAssets.xcassets/shotgunFire4.imageset/shotgunFire4.png diff --git a/Source/Rampage/Assets.xcassets/shotgunIcon.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/shotgunIcon.imageset/Contents.json similarity index 99% rename from Source/Rampage/Assets.xcassets/shotgunIcon.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/shotgunIcon.imageset/Contents.json index cd1baff..defeb72 100644 --- a/Source/Rampage/Assets.xcassets/shotgunIcon.imageset/Contents.json +++ b/Source/Shared/SharedAssets.xcassets/shotgunIcon.imageset/Contents.json @@ -18,4 +18,4 @@ "version" : 1, "author" : "xcode" } -} +} \ No newline at end of file diff --git a/Source/Rampage/Assets.xcassets/shotgunIcon.imageset/shotgunIcon.png b/Source/Shared/SharedAssets.xcassets/shotgunIcon.imageset/shotgunIcon.png similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgunIcon.imageset/shotgunIcon.png rename to Source/Shared/SharedAssets.xcassets/shotgunIcon.imageset/shotgunIcon.png diff --git a/Source/Rampage/Assets.xcassets/shotgunPickup.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/shotgunPickup.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgunPickup.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/shotgunPickup.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/shotgunPickup.imageset/shotgunPickup.png b/Source/Shared/SharedAssets.xcassets/shotgunPickup.imageset/shotgunPickup.png similarity index 100% rename from Source/Rampage/Assets.xcassets/shotgunPickup.imageset/shotgunPickup.png rename to Source/Shared/SharedAssets.xcassets/shotgunPickup.imageset/shotgunPickup.png diff --git a/Source/Rampage/Assets.xcassets/slimeWall.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/slimeWall.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/slimeWall.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/slimeWall.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/slimeWall.imageset/slimeWall.png b/Source/Shared/SharedAssets.xcassets/slimeWall.imageset/slimeWall.png similarity index 100% rename from Source/Rampage/Assets.xcassets/slimeWall.imageset/slimeWall.png rename to Source/Shared/SharedAssets.xcassets/slimeWall.imageset/slimeWall.png diff --git a/Source/Rampage/Assets.xcassets/slimeWall2.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/slimeWall2.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/slimeWall2.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/slimeWall2.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/slimeWall2.imageset/slimeWall2.png b/Source/Shared/SharedAssets.xcassets/slimeWall2.imageset/slimeWall2.png similarity index 100% rename from Source/Rampage/Assets.xcassets/slimeWall2.imageset/slimeWall2.png rename to Source/Shared/SharedAssets.xcassets/slimeWall2.imageset/slimeWall2.png diff --git a/Source/Rampage/Assets.xcassets/switch1.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/switch1.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/switch1.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/switch1.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/switch1.imageset/switch1.png b/Source/Shared/SharedAssets.xcassets/switch1.imageset/switch1.png similarity index 100% rename from Source/Rampage/Assets.xcassets/switch1.imageset/switch1.png rename to Source/Shared/SharedAssets.xcassets/switch1.imageset/switch1.png diff --git a/Source/Rampage/Assets.xcassets/switch2.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/switch2.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/switch2.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/switch2.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/switch2.imageset/switch2.png b/Source/Shared/SharedAssets.xcassets/switch2.imageset/switch2.png similarity index 100% rename from Source/Rampage/Assets.xcassets/switch2.imageset/switch2.png rename to Source/Shared/SharedAssets.xcassets/switch2.imageset/switch2.png diff --git a/Source/Rampage/Assets.xcassets/switch3.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/switch3.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/switch3.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/switch3.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/switch3.imageset/switch3.png b/Source/Shared/SharedAssets.xcassets/switch3.imageset/switch3.png similarity index 100% rename from Source/Rampage/Assets.xcassets/switch3.imageset/switch3.png rename to Source/Shared/SharedAssets.xcassets/switch3.imageset/switch3.png diff --git a/Source/Rampage/Assets.xcassets/switch4.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/switch4.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/switch4.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/switch4.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/switch4.imageset/switch4.png b/Source/Shared/SharedAssets.xcassets/switch4.imageset/switch4.png similarity index 100% rename from Source/Rampage/Assets.xcassets/switch4.imageset/switch4.png rename to Source/Shared/SharedAssets.xcassets/switch4.imageset/switch4.png diff --git a/Source/Rampage/Assets.xcassets/titleBackground.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/titleBackground.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/titleBackground.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/titleBackground.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/titleBackground.imageset/titleBackground.png b/Source/Shared/SharedAssets.xcassets/titleBackground.imageset/titleBackground.png similarity index 100% rename from Source/Rampage/Assets.xcassets/titleBackground.imageset/titleBackground.png rename to Source/Shared/SharedAssets.xcassets/titleBackground.imageset/titleBackground.png diff --git a/Source/Rampage/Assets.xcassets/titleLogo.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/titleLogo.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/titleLogo.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/titleLogo.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/titleLogo.imageset/titleLogo.png b/Source/Shared/SharedAssets.xcassets/titleLogo.imageset/titleLogo.png similarity index 100% rename from Source/Rampage/Assets.xcassets/titleLogo.imageset/titleLogo.png rename to Source/Shared/SharedAssets.xcassets/titleLogo.imageset/titleLogo.png diff --git a/Source/Rampage/Assets.xcassets/wall.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/wall.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/wall.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/wall.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/wall.imageset/wall.png b/Source/Shared/SharedAssets.xcassets/wall.imageset/wall.png similarity index 100% rename from Source/Rampage/Assets.xcassets/wall.imageset/wall.png rename to Source/Shared/SharedAssets.xcassets/wall.imageset/wall.png diff --git a/Source/Rampage/Assets.xcassets/wall2.imageset/Contents.json b/Source/Shared/SharedAssets.xcassets/wall2.imageset/Contents.json similarity index 100% rename from Source/Rampage/Assets.xcassets/wall2.imageset/Contents.json rename to Source/Shared/SharedAssets.xcassets/wall2.imageset/Contents.json diff --git a/Source/Rampage/Assets.xcassets/wall2.imageset/wall2.png b/Source/Shared/SharedAssets.xcassets/wall2.imageset/wall2.png similarity index 100% rename from Source/Rampage/Assets.xcassets/wall2.imageset/wall2.png rename to Source/Shared/SharedAssets.xcassets/wall2.imageset/wall2.png diff --git a/Source/Rampage/SoundManager.swift b/Source/Shared/SoundManager.swift similarity index 100% rename from Source/Rampage/SoundManager.swift rename to Source/Shared/SoundManager.swift diff --git a/Source/Rampage/Sounds/doorSlide.mp3 b/Source/Shared/Sounds/doorSlide.mp3 similarity index 100% rename from Source/Rampage/Sounds/doorSlide.mp3 rename to Source/Shared/Sounds/doorSlide.mp3 diff --git a/Source/Rampage/Sounds/medkit.mp3 b/Source/Shared/Sounds/medkit.mp3 similarity index 100% rename from Source/Rampage/Sounds/medkit.mp3 rename to Source/Shared/Sounds/medkit.mp3 diff --git a/Source/Rampage/Sounds/monsterDeath.mp3 b/Source/Shared/Sounds/monsterDeath.mp3 similarity index 100% rename from Source/Rampage/Sounds/monsterDeath.mp3 rename to Source/Shared/Sounds/monsterDeath.mp3 diff --git a/Source/Rampage/Sounds/monsterGroan.mp3 b/Source/Shared/Sounds/monsterGroan.mp3 similarity index 100% rename from Source/Rampage/Sounds/monsterGroan.mp3 rename to Source/Shared/Sounds/monsterGroan.mp3 diff --git a/Source/Rampage/Sounds/monsterHit.mp3 b/Source/Shared/Sounds/monsterHit.mp3 similarity index 100% rename from Source/Rampage/Sounds/monsterHit.mp3 rename to Source/Shared/Sounds/monsterHit.mp3 diff --git a/Source/Rampage/Sounds/monsterSwipe.mp3 b/Source/Shared/Sounds/monsterSwipe.mp3 similarity index 100% rename from Source/Rampage/Sounds/monsterSwipe.mp3 rename to Source/Shared/Sounds/monsterSwipe.mp3 diff --git a/Source/Rampage/Sounds/pistolFire.mp3 b/Source/Shared/Sounds/pistolFire.mp3 similarity index 100% rename from Source/Rampage/Sounds/pistolFire.mp3 rename to Source/Shared/Sounds/pistolFire.mp3 diff --git a/Source/Rampage/Sounds/playerDeath.mp3 b/Source/Shared/Sounds/playerDeath.mp3 similarity index 100% rename from Source/Rampage/Sounds/playerDeath.mp3 rename to Source/Shared/Sounds/playerDeath.mp3 diff --git a/Source/Rampage/Sounds/playerWalk.mp3 b/Source/Shared/Sounds/playerWalk.mp3 similarity index 100% rename from Source/Rampage/Sounds/playerWalk.mp3 rename to Source/Shared/Sounds/playerWalk.mp3 diff --git a/Source/Rampage/Sounds/ricochet.mp3 b/Source/Shared/Sounds/ricochet.mp3 similarity index 100% rename from Source/Rampage/Sounds/ricochet.mp3 rename to Source/Shared/Sounds/ricochet.mp3 diff --git a/Source/Rampage/Sounds/shotgunFire.mp3 b/Source/Shared/Sounds/shotgunFire.mp3 similarity index 100% rename from Source/Rampage/Sounds/shotgunFire.mp3 rename to Source/Shared/Sounds/shotgunFire.mp3 diff --git a/Source/Rampage/Sounds/shotgunPickup.mp3 b/Source/Shared/Sounds/shotgunPickup.mp3 similarity index 100% rename from Source/Rampage/Sounds/shotgunPickup.mp3 rename to Source/Shared/Sounds/shotgunPickup.mp3 diff --git a/Source/Rampage/Sounds/squelch.mp3 b/Source/Shared/Sounds/squelch.mp3 similarity index 100% rename from Source/Rampage/Sounds/squelch.mp3 rename to Source/Shared/Sounds/squelch.mp3 diff --git a/Source/Rampage/Sounds/switchFlip.mp3 b/Source/Shared/Sounds/switchFlip.mp3 similarity index 100% rename from Source/Rampage/Sounds/switchFlip.mp3 rename to Source/Shared/Sounds/switchFlip.mp3 diff --git a/Source/Rampage/Sounds/wallSlide.mp3 b/Source/Shared/Sounds/wallSlide.mp3 similarity index 100% rename from Source/Rampage/Sounds/wallSlide.mp3 rename to Source/Shared/Sounds/wallSlide.mp3 diff --git a/Source/Rampage/Sounds/wallThud.mp3 b/Source/Shared/Sounds/wallThud.mp3 similarity index 100% rename from Source/Rampage/Sounds/wallThud.mp3 rename to Source/Shared/Sounds/wallThud.mp3 diff --git a/Source/Rampage/UIImage+Bitmap.swift b/Source/Shared/UIImage+Bitmap.swift similarity index 100% rename from Source/Rampage/UIImage+Bitmap.swift rename to Source/Shared/UIImage+Bitmap.swift diff --git a/Source/Rampage/ViewController.swift b/Source/Shared/ViewController.swift similarity index 96% rename from Source/Rampage/ViewController.swift rename to Source/Shared/ViewController.swift index bd7c911..393976e 100644 --- a/Source/Rampage/ViewController.swift +++ b/Source/Shared/ViewController.swift @@ -82,6 +82,8 @@ class ViewController: UIViewController { game.delegate = self } +#if os(iOS) + override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return .landscape } @@ -94,6 +96,8 @@ class ViewController: UIViewController { return true } +#endif + private var inputVector: Vector { switch panGesture.state { case .began, .changed: @@ -133,7 +137,11 @@ class ViewController: UIViewController { input.isFiring = false } - let width = Int(imageView.bounds.width), height = Int(imageView.bounds.height) + let maxHeight = 480 + let height = min(maxHeight, Int(imageView.bounds.height)) + let aspectRatio = imageView.bounds.width / imageView.bounds.height + let width = Int(CGFloat(height) * aspectRatio) + var renderer = Renderer(width: width, height: height, textures: textures) let insets = self.view.safeAreaInsets renderer.safeArea = Rect( diff --git a/TVOS.md b/TVOS.md new file mode 100644 index 0000000..991a610 --- /dev/null +++ b/TVOS.md @@ -0,0 +1,46 @@ +Create a new Target for the tvOS app. + +• File > New > Target +• tvOS > Application > Single View App + +Name it "RampageTV", use Storyboard Interface to be consistent with the existing project. + +The first issue is that all the Assets (images and sounds) are in the original iOS app. So let's create a new Folder in the project so that we can move the "shared resources" into it. + +Select the blue project file in the file explorer, then: File > New > Group and call it "Shared". + +Now you can drag the Assets.xcassets and Sounds folder to the "Shared" folder. +Rename the Assets.xcassets to "SharedAssets.xcassets". + +In the Rampage folder, create a new Assets.xcassets file, alt click it so you get both asset catalogues side by side, then drag the "AppIcon" from the SharedAssets to the Assets catalogue. This is because the AppIcon is only relevant to iOS apps, not tvOS apps. You could have just right clicked inside the Assets catalogue and created a new set of app icons, but your choice. +Select the SharedAssets catalogue again, open the menu on the right hand side of the screen and go to the first tab in order to find the list of Targets that the file is a member of. Put a checkmark next to "Rampage" and "RampageTV" so that the catalogue will be compiled into both projects. + +Expand the Sounds folder, select all the files inside and do the same to add them all to both project targets. + +Compile both projects to make sure they work correctly. + +In the build settings for the "Engine" and "Renderer" targets, select "Other..." for the Support Platforms option, then manually add "appletvos" and "appletvsimulator" lines below "iphoneos" and "iphonesimulator". This will allow the same frameworks to be used for both iOS and tvOS. + +In the RampageTV folder, delete the file ViewController.swift + +Move the following files from "Rampage" into "Shared": +UIImage+Bitmap, SoundManager, GameControllerManager, GameControllerManager+Input, Levels.json, ViewController + +Make sure all those files are in both the "Rampage" and "RampageTV" targets. + +Navigate to the RampageTV target settings. Find the "Signing & Capabilities", add the "Game Controllers" capability and enable support for "Extended controllers". Micro gamepads suck so I won't be implementing that. + +Filling every pixel of a 4K TV is too slow for the software renderer, so you need to cap the bitmap size. In "ViewController.swift" find + +```swift +let width = Int(imageView.bounds.width), height = Int(imageView.bounds.height) +``` + +and replace it with + +```swift +let maxHeight = 480 +let height = min(maxHeight, Int(imageView.bounds.height)) +let aspectRatio = imageView.bounds.width / imageView.bounds.height +let width = Int(CGFloat(height) * aspectRatio) +```