├── tinyRPG
├── World
│ ├── Terrain.sks
│ ├── StateMachine.swift
│ └── MapGen.swift
├── Support
│ ├── GameScene.sks
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── beach.imageset
│ │ │ ├── beach.png
│ │ │ └── Contents.json
│ │ ├── grass.imageset
│ │ │ ├── grass.png
│ │ │ └── Contents.json
│ │ ├── icon.imageset
│ │ │ ├── icon.png
│ │ │ └── Contents.json
│ │ ├── ocean.imageset
│ │ │ ├── ocean.png
│ │ │ └── Contents.json
│ │ ├── snow.imageset
│ │ │ ├── snow.png
│ │ │ └── Contents.json
│ │ ├── taiga.imageset
│ │ │ ├── taiga.png
│ │ │ └── Contents.json
│ │ ├── water.imageset
│ │ │ ├── water.png
│ │ │ └── Contents.json
│ │ ├── desert.imageset
│ │ │ ├── desert.png
│ │ │ └── Contents.json
│ │ ├── forest.imageset
│ │ │ ├── forest.png
│ │ │ └── Contents.json
│ │ ├── blank.imageset
│ │ │ ├── highlight.png
│ │ │ └── Contents.json
│ │ ├── mountain.imageset
│ │ │ ├── mountain.png
│ │ │ └── Contents.json
│ │ ├── hero.imageset
│ │ │ ├── hero-idle-front.png
│ │ │ └── Contents.json
│ │ ├── rainForest.imageset
│ │ │ ├── rainForest.png
│ │ │ └── Contents.json
│ │ ├── mountainSnow.imageset
│ │ │ ├── mountainSnow.png
│ │ │ └── Contents.json
│ │ ├── mountainForest.imageset
│ │ │ ├── mountainForest.png
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Extensions.swift
│ ├── Info.plist
│ ├── GameData.plist
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ └── AppDelegate.swift
├── MyPlayground.playground
│ ├── contents.xcplayground
│ ├── Contents.swift
│ └── timeline.xctimeline
├── Interface
│ ├── TileActions.swift
│ ├── ActionMenu.swift
│ └── StatMenu.swift
├── Items
│ ├── AttackMove.swift
│ ├── Armor.swift
│ └── Weapon.swift
├── Character
│ ├── CharacterComponents
│ │ ├── HealthComponent.swift
│ │ ├── MagicComponent.swift
│ │ ├── SpriteComponent.swift
│ │ ├── ExperienceComponent.swift
│ │ ├── InventoryComponent.swift
│ │ └── MovementComponent.swift
│ └── Character.swift
├── GameViewController.swift
└── GameScene.swift
├── tinyRPG.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcuserdata
│ └── loganroberts.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
└── project.pbxproj
├── README.md
└── azure-pipelines.yml
/tinyRPG/World/Terrain.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/World/Terrain.sks
--------------------------------------------------------------------------------
/tinyRPG/Support/GameScene.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/GameScene.sks
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/beach.imageset/beach.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/beach.imageset/beach.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/grass.imageset/grass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/grass.imageset/grass.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/icon.imageset/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/icon.imageset/icon.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/ocean.imageset/ocean.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/ocean.imageset/ocean.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/snow.imageset/snow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/snow.imageset/snow.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/taiga.imageset/taiga.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/taiga.imageset/taiga.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/water.imageset/water.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/water.imageset/water.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/desert.imageset/desert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/desert.imageset/desert.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/forest.imageset/forest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/forest.imageset/forest.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/blank.imageset/highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/blank.imageset/highlight.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/mountain.imageset/mountain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/mountain.imageset/mountain.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/hero.imageset/hero-idle-front.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/hero.imageset/hero-idle-front.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/rainForest.imageset/rainForest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/rainForest.imageset/rainForest.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/mountainSnow.imageset/mountainSnow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/mountainSnow.imageset/mountainSnow.png
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/mountainForest.imageset/mountainForest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loganroberts/tinyRPG/HEAD/tinyRPG/Support/Assets.xcassets/mountainForest.imageset/mountainForest.png
--------------------------------------------------------------------------------
/tinyRPG.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/tinyRPG/MyPlayground.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # tinyRPG
2 | Swift 5 based turn based RPG game using GameplayKit and SpriteKit. WIP
3 |
4 | Self-lead learning project. Procedural terrain generation based on
5 | perlin noise for height and a separate source for moisture resulting
6 | in a diverse biome set on an infinetly large map.
7 |
8 |
--------------------------------------------------------------------------------
/tinyRPG/Interface/TileActions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TileActions.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/18/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SpriteKit
11 | import GameplayKit
12 |
13 | class TileActions: SKNode {
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/tinyRPG.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/beach.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "beach.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/grass.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "grass.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/ocean.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "ocean.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/snow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "snow.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/taiga.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "taiga.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/water.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "water.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/blank.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "highlight.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/desert.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "desert.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/forest.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "forest.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/hero.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "hero-idle-front.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/mountain.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "mountain.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/rainForest.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "rainForest.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/mountainSnow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "mountainSnow.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/mountainForest.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "mountainForest.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/tinyRPG.xcodeproj/xcuserdata/loganroberts.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | tinyRPG.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | # Xcode
2 | # Build, test, and archive an Xcode workspace on macOS.
3 | # Add steps that install certificates, test, sign, and distribute an app, save build artifacts, and more:
4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/xcode
5 |
6 | trigger:
7 | - master
8 |
9 | pool:
10 | vmImage: 'macOS-10.13'
11 |
12 | steps:
13 | - task: Xcode@5
14 | inputs:
15 | actions: 'build'
16 | scheme: ''
17 | sdk: 'iphoneos'
18 | configuration: 'Release'
19 | xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace'
20 | xcodeVersion: 'default' # Options: 8, 9, 10, default, specifyPath
21 |
--------------------------------------------------------------------------------
/tinyRPG/Items/AttackMove.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AttackMove.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/12/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SpriteKit
11 |
12 | class AttackMove {
13 | var name: String
14 | var damage: Int
15 | var criticalChance: Int
16 | var points: Int
17 |
18 | init(data: Dictionary) {
19 | self.name = data["Name"] as! String
20 | self.damage = data["Damage"] as! Int
21 | self.criticalChance = data["CriticalChance"] as! Int
22 | self.points = data["Points"] as! Int
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tinyRPG/Character/CharacterComponents/HealthComponent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HealthComponent.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/12/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import GameplayKit
11 |
12 | class HealthComponent: GKComponent {
13 | var owner: Character
14 |
15 | var max = 10
16 | var current = 10
17 | var min = 0
18 |
19 | init(owner: Character) {
20 | self.owner = owner
21 | super.init()
22 | }
23 |
24 | required init?(coder aDecoder: NSCoder) {
25 | fatalError("init(coder:) has not been implemented")
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/tinyRPG/Character/CharacterComponents/MagicComponent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MagicComponent.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/14/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import GameplayKit
11 | import SpriteKit
12 |
13 | class MagicComponent: GKComponent {
14 | var owner: Character
15 |
16 | var max = 10
17 | var current = 10
18 | var min = 0
19 |
20 | init(owner: Character) {
21 | self.owner = owner
22 | super.init()
23 | }
24 |
25 | required init?(coder aDecoder: NSCoder) {
26 | fatalError("init(coder:) has not been implemented")
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/tinyRPG/MyPlayground.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import GameplayKit
3 | import SpriteKit
4 |
5 |
6 | let biomeNoise = GKNoise(GKVoronoiNoiseSource(frequency: 3, displacement: 1, distanceEnabled: false, seed: 2222))
7 | let biomeMap = GKNoiseMap(biomeNoise, size: vector2(1.0, 1.0), origin: vector2(0, 0), sampleCount: vector2(1000, 1000), seamless: false)
8 | let bTexture = SKTexture(noiseMap: biomeMap)
9 |
10 |
11 |
12 | let riverNoise = GKNoise(GKRidgedNoiseSource(frequency: 6.0, octaveCount: 2, lacunarity: 5, seed: 1234))
13 | let riverMap = GKNoiseMap(riverNoise, size: vector2(1.0, 1.0), origin: vector2(0, 0), sampleCount: vector2(1000, 1000), seamless: false)
14 | let rTexture = SKTexture(noiseMap: riverMap)
15 |
--------------------------------------------------------------------------------
/tinyRPG/Support/Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Extensions.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/8/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | extension UIGestureRecognizer {
13 | func cancel() {
14 | isEnabled = false
15 | isEnabled = true
16 | }
17 | }
18 |
19 |
20 | func getDefaults(name: String) -> Dictionary {
21 | var dictionary: [String: Any] = [:]
22 | if let url = Bundle.main.url(forResource: name, withExtension: "plist") {
23 | do {
24 | let data = try Data(contentsOf: url)
25 | dictionary = try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as! [String : Any]
26 | } catch {
27 | print("No Plist Found")
28 | }
29 | }
30 | return dictionary
31 | }
32 |
--------------------------------------------------------------------------------
/tinyRPG/Character/CharacterComponents/SpriteComponent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SpriteComponent.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/8/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SpriteKit
11 | import GameplayKit
12 |
13 | class SpriteComponent: GKComponent {
14 | let node: SKSpriteNode
15 |
16 | init(texture: SKTexture) {
17 | node = SKSpriteNode(texture: texture, color: .white, size: texture.size())
18 | super.init()
19 |
20 | node.position = CGPoint(x: 0, y: 0)
21 | node.scale(to: CGSize(width: 100, height: 100))
22 | node.zPosition = 1
23 | node.name = "PlayerSprite"
24 | }
25 |
26 | required init?(coder aDecoder: NSCoder) {
27 | fatalError("init(coder:) has not been implemented")
28 | }
29 |
30 | override func update(deltaTime seconds: TimeInterval) {
31 | //update func goes here
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/tinyRPG/World/StateMachine.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StateMachine.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/12/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import GameplayKit
11 |
12 | class PlayerTurn: GKState {
13 | //gets the scene the state is attached to
14 | let game: GameScene
15 | let player: Character
16 |
17 | init(game: GameScene, player: Character) {
18 | self.game = game
19 | self.player = player
20 | }
21 |
22 | override func didEnter(from previousState: GKState?) {
23 | //reset player movepoints after ending a turn
24 | player.movement.movementPoints = player.movement.maxMovementPoints
25 | let moves = player.movement.getRange(from: player.movement.currentLocation)
26 | player.movement.highlightMoves(moves: moves)
27 | game.addChild(player.movement.movesMap)
28 | }
29 | }
30 |
31 | class GameTurn: GKState {
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/tinyRPG/Items/Armor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Armor.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/12/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SpriteKit
11 |
12 | class Armor {
13 | enum ArmorSlot: String {
14 | case head = "Head"
15 | case body = "Body"
16 | case hands = "Hands"
17 | case feet = "Feet"
18 | }
19 |
20 | var name: String
21 | var slot: ArmorSlot
22 | var defense: Int
23 | var speed: Int
24 | var weight: Int
25 | var value: Int
26 | var sellable: Bool
27 |
28 | init(data: Dictionary) {
29 | self.name = data["Name"] as! String
30 | self.slot = ArmorSlot.init(rawValue: data["ArmorSlot"] as! String)!
31 | self.defense = data["Defense"] as! Int
32 | self.speed = data["Speed"] as! Int
33 | self.weight = data["Weight"] as! Int
34 | self.value = data["Value"] as! Int
35 | self.sellable = data["Sellable"] as! Bool
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tinyRPG/Items/Weapon.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Weapon.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/12/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SpriteKit
11 |
12 | class Weapon {
13 | enum WeaponType: String {
14 | case melee = "Melee"
15 | case ranged = "Ranged"
16 | case magic = "Magic"
17 | }
18 |
19 | var name: String
20 | var weaponType: WeaponType
21 | var accuracy: Int
22 | var damage: Int
23 | var weight: Int
24 | var value: Int
25 | var sellable: Bool
26 |
27 | init(data: Dictionary) {
28 | self.name = data["Name"] as! String
29 | self.accuracy = data["Accuracy"] as! Int
30 | self.damage = data["Damage"] as! Int
31 | self.weight = data["Weight"] as! Int
32 | self.value = data["Value"] as! Int
33 | self.sellable = data["Sellable"] as! Bool
34 | self.weaponType = WeaponType.init(rawValue: data["WeaponType"] as! String)!
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/tinyRPG/Character/Character.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Character.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/7/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import GameplayKit
11 | import SpriteKit
12 |
13 |
14 | class Character: GKEntity {
15 |
16 | //add conveienceProperty for world
17 | var worldMap: MapGen
18 | //Visual image of the player. very basic
19 | let sprite: SpriteComponent
20 | //movement functions and data for the player
21 | let movement: MovementComponent
22 | //experience system for leveling
23 | lazy var experience = ExperienceSystem(owner: self)
24 | // health system for damage
25 | lazy var health = HealthComponent(owner: self)
26 | //magic system for spells
27 | lazy var magic = MagicComponent(owner: self)
28 | //inventory for items and weapons
29 | lazy var inventory = InventoryComponent(owner: self)
30 |
31 | init(texture: SKTexture, map: MapGen) {
32 | self.worldMap = map
33 | self.sprite = SpriteComponent(texture: texture)
34 | self.movement = MovementComponent(map: worldMap)
35 | super.init()
36 |
37 | addComponent(magic)
38 | addComponent(health)
39 | addComponent(experience)
40 | addComponent(movement)
41 | addComponent(sprite)
42 | addComponent(inventory)
43 | }
44 |
45 | required init?(coder aDecoder: NSCoder) {
46 | fatalError("init(coder:) has not been implemented")
47 | }
48 |
49 | override func update(deltaTime seconds: TimeInterval) {
50 | //update func goes here
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tinyRPG/Support/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UIStatusBarHidden
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/tinyRPG/Support/GameData.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Armor
6 |
7 | Clothes
8 |
9 | Name
10 | Clothes
11 | ArmorSlot
12 | Body
13 | Defense
14 | 1
15 | Speed
16 | 2
17 | Weight
18 | 0
19 | Value
20 | 0
21 | Sellable
22 |
23 |
24 |
25 | Weapons
26 |
27 | Hands
28 |
29 | Name
30 | Hands
31 | WeaponType
32 | Melee
33 | Accuracy
34 | 100
35 | Move
36 | Punch
37 | Damage
38 | 1
39 | Weight
40 | 0
41 | Value
42 | 0
43 | Sellable
44 |
45 |
46 | Stick
47 |
48 | Name
49 | Stick
50 | WeaponType
51 | Melee
52 | Accuracy
53 | 100
54 | Move
55 | Punch
56 | Damage
57 | 1
58 | Weight
59 | 0
60 | Value
61 | 0
62 | Sellable
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/tinyRPG/Support/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/tinyRPG/Support/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/tinyRPG/Interface/ActionMenu.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ActionMenu.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/14/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SpriteKit
11 | import GameplayKit
12 |
13 | class ActionMenu: SKNode {
14 |
15 | let background = SKSpriteNode(color: .black, size: CGSize(width: 420, height: 420))
16 |
17 | let moveButton = SKSpriteNode(color: .darkGray, size: CGSize(width: 160, height: 160))
18 | let endTurnButton = SKSpriteNode(color: .darkGray, size: CGSize(width: 160, height: 160))
19 | let tileActionButton = SKSpriteNode(color: .darkGray, size: CGSize(width: 160, height: 160))
20 | let inventoryButton = SKSpriteNode(color: .darkGray, size: CGSize(width: 160, height: 160))
21 |
22 | init(name: String) {
23 | super.init()
24 | self.name = name
25 |
26 | moveButton.name = "MoveButton"
27 | moveButton.position = CGPoint(x: -100, y: 100)
28 |
29 | endTurnButton.name = "EndTurn"
30 | endTurnButton.position = CGPoint(x: -100, y: -100)
31 |
32 | tileActionButton.name = "TileActoin"
33 | tileActionButton.position = CGPoint(x: 100, y: 100)
34 |
35 | inventoryButton.name = "Inventory"
36 | inventoryButton.position = CGPoint(x: 100, y: -100)
37 |
38 | background.alpha = 0.75
39 |
40 | addChild(background)
41 | addChild(endTurnButton)
42 | addChild(tileActionButton)
43 | addChild(moveButton)
44 | addChild(inventoryButton)
45 | }
46 |
47 | required init?(coder aDecoder: NSCoder) {
48 | fatalError("init(coder:) has not been implemented")
49 | }
50 |
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/tinyRPG/Character/CharacterComponents/ExperienceComponent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExperienceComponent.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/12/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import GameplayKit
11 |
12 | class ExperienceSystem: GKComponent {
13 | var owner: Character
14 | var killCount = 0
15 |
16 | var level = 1
17 | var baseXP = 10
18 | var total = 0.0
19 |
20 | var netXP: Double {
21 | let _a = xpNeeded - total
22 | let _b = (_a*100).rounded()/100
23 | return _b
24 | }
25 |
26 | var dropXP: Double {
27 | let _xp = Double(baseXP * level) / 7
28 | return _xp
29 | }
30 |
31 | var xpNeeded: Double {
32 | let _a: Double = Double(nextLevel)
33 | let _b: Double = pow(_a, 3.0)
34 | let _c: Double = _b * 4.0
35 | return _c / 7
36 | }
37 |
38 | var nextLevel: Int {
39 | return level + 1
40 | }
41 |
42 | init(owner: Character) {
43 | self.owner = owner
44 | super.init()
45 | }
46 |
47 | required init?(coder aDecoder: NSCoder) {
48 | fatalError("init(coder:) has not been implemented")
49 | }
50 |
51 | func combatComplete(xpDrop: Double) {
52 | total += xpDrop
53 | killCount += 1
54 | levelUpCheck()
55 | }
56 |
57 | func levelUpCheck() {
58 | guard total >= xpNeeded else {
59 | print("You need \(netXP) XP to get to level \(nextLevel)")
60 | return
61 | }
62 | level += 1
63 | print("You leveled up! You are now level \(level)!!")
64 | print("You need \(xpNeeded) XP to get to level \(nextLevel)")
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/tinyRPG/GameViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameViewController.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/7/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SpriteKit
11 | import GameplayKit
12 |
13 | class GameViewController: UIViewController {
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 |
18 | // Load 'GameScene.sks' as a GKScene. This provides gameplay related content
19 | // including entities and graphs.
20 | if let scene = GKScene(fileNamed: "GameScene") {
21 |
22 | // Get the SKScene from the loaded GKScene
23 | if let sceneNode = scene.rootNode as! GameScene? {
24 |
25 | // Copy gameplay related content over to the scene
26 | sceneNode.entities = scene.entities
27 | sceneNode.graphs = scene.graphs
28 |
29 | // Set the scale mode to scale to fit the window
30 | sceneNode.scaleMode = .aspectFill
31 |
32 | // Present the scene
33 | if let view = self.view as! SKView? {
34 | view.presentScene(sceneNode)
35 |
36 | view.ignoresSiblingOrder = true
37 |
38 | view.showsFPS = true
39 | view.showsNodeCount = true
40 | }
41 | }
42 | }
43 | }
44 |
45 | override var shouldAutorotate: Bool {
46 | return true
47 | }
48 |
49 | override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
50 | if UIDevice.current.userInterfaceIdiom == .phone {
51 | return .allButUpsideDown
52 | } else {
53 | return .all
54 | }
55 | }
56 |
57 | override var prefersStatusBarHidden: Bool {
58 | return true
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/tinyRPG/Support/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/tinyRPG/Support/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/7/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/tinyRPG/Character/CharacterComponents/InventoryComponent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InventoryComponent.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/12/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import GameplayKit
11 | import SpriteKit
12 |
13 | class InventoryComponent: GKComponent {
14 | var owner: Character
15 |
16 | var weaponBag: [String: Weapon] = [:]
17 | var armorBag: [String: Armor] = [:]
18 |
19 | var weaponSlot: Weapon? = nil
20 |
21 | var headSlot: Armor? = nil
22 | var bodySlot: Armor? = nil
23 | var feetSlot: Armor? = nil
24 | var handsSlot: Armor? = nil
25 |
26 | var gold = 0
27 | var wood = 0
28 | var stone = 0
29 | var food = 0
30 |
31 | init(owner: Character) {
32 | self.owner = owner
33 | super.init()
34 | }
35 |
36 | required init?(coder aDecoder: NSCoder) {
37 | fatalError("init(coder:) has not been implemented")
38 | }
39 |
40 | func addWeapon(weapon: Weapon) {
41 | guard weaponBag[weapon.name] == nil else {
42 | print("You have one of those already!")
43 | return
44 | }
45 | weaponBag[weapon.name] = weapon
46 | }
47 |
48 | func removeWeapon(weapon: Weapon) {
49 | guard weapon.sellable == true else {
50 | print("You can't get rid of that!")
51 | return
52 | }
53 | weaponBag[weapon.name] = nil
54 | }
55 |
56 | func addArmor(armor: Armor) {
57 | guard armorBag[armor.name] == nil else {
58 | print("You have one of those already!")
59 | return
60 | }
61 | armorBag[armor.name] = armor
62 | }
63 |
64 | func removeArmor(armor: Armor) {
65 | guard armor.sellable == true else {
66 | print("You can't get rid of that!")
67 | return
68 | }
69 | armorBag[armor.name] = nil
70 | }
71 |
72 | func canAffordArmor(armor: Armor) -> Bool {
73 | guard gold >= armor.value else {
74 | return false
75 | }
76 | return true
77 | }
78 |
79 | func canAffordWeapon(weapon: Weapon) -> Bool {
80 | guard gold >= weapon.value else {
81 | return false
82 | }
83 | return true
84 | }
85 |
86 | func equipWeapon(weapon: Weapon) {
87 | weaponSlot = weaponBag[weapon.name]
88 | }
89 |
90 | func deEquipWeapon(weapon: Weapon) {
91 | weaponSlot = nil
92 | }
93 |
94 | func equipArmor(armor: Armor) {
95 | switch armor.slot {
96 | case .body:
97 | bodySlot = armorBag[armor.name]
98 | case .head:
99 | headSlot = armorBag[armor.name]
100 | case .feet:
101 | feetSlot = armorBag[armor.name]
102 | case .hands:
103 | handsSlot = armorBag[armor.name]
104 | }
105 | }
106 |
107 | func deEquipArmor(armor: Armor) {
108 | switch armor.slot {
109 | case .body:
110 | bodySlot = nil
111 | case .head:
112 | headSlot = nil
113 | case .feet:
114 | feetSlot = nil
115 | case .hands:
116 | handsSlot = nil
117 | }
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/tinyRPG/MyPlayground.playground/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
39 |
40 |
44 |
45 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/tinyRPG/Interface/StatMenu.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StatMenu.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/14/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SpriteKit
11 | import GameplayKit
12 |
13 | class StatMenu: SKNode {
14 |
15 | //setup stat menu things
16 | let background = SKSpriteNode(color: .black, size: CGSize(width: 620, height: 150))
17 |
18 | var food = 0
19 | var foodDisplay: SKLabelNode
20 |
21 | var wood = 0
22 | var woodDisplay: SKLabelNode
23 |
24 | var stone = 0
25 | var stoneDisplay: SKLabelNode
26 |
27 | var gold = 0
28 | var goldDisplay: SKLabelNode
29 |
30 | var currentHealth = 100
31 | var maxHealth = 100
32 | var healthBar: SKSpriteNode
33 | var healthBackground: SKSpriteNode
34 |
35 | var currentMagic = 100
36 | var maxMagic = 100
37 | var magicBar: SKSpriteNode
38 | var magicBackground: SKSpriteNode
39 |
40 | init(name: String) {
41 | self.foodDisplay = SKLabelNode(text: "Food: \(food)")
42 | self.woodDisplay = SKLabelNode(text: "Wood: \(wood)")
43 | self.stoneDisplay = SKLabelNode(text: "Stone: \(stone)")
44 | self.goldDisplay = SKLabelNode(text: "Gold: \(gold)")
45 |
46 | //set bars and backgrounds to feed from current/max stats
47 | self.healthBar = SKSpriteNode(color: .red, size: CGSize(width: currentHealth, height: 20))
48 | self.healthBackground = SKSpriteNode(color: .darkGray, size: CGSize(width: maxHealth, height: 16))
49 | self.magicBar = SKSpriteNode(color: .blue, size: CGSize(width: currentMagic, height: 20))
50 | self.magicBackground = SKSpriteNode(color: .darkGray, size: CGSize(width: maxMagic, height: 16))
51 |
52 | super.init()
53 | self.name = name
54 |
55 | //positioning
56 | foodDisplay.position = CGPoint(x: -230, y: -50)
57 | woodDisplay.position = CGPoint(x: -80, y: -50)
58 | stoneDisplay.position = CGPoint(x: 80, y: -50)
59 | goldDisplay.position = CGPoint(x: 220, y: -50)
60 |
61 | //anchorpoint changes to allow for filling, depleting
62 | healthBar.position = CGPoint(x: -280, y: 10)
63 | healthBar.anchorPoint = CGPoint(x: 0.0, y: 0.5)
64 | healthBackground.anchorPoint = CGPoint(x: 0.0, y: 0.5)
65 | healthBackground.position = CGPoint(x: -280, y: 10)
66 | healthBackground.alpha = 0.45
67 |
68 | magicBar.position = CGPoint(x: 275, y: 10)
69 | magicBar.anchorPoint = CGPoint(x: 1.0, y: 0.5)
70 | magicBackground.anchorPoint = CGPoint(x: 1.0, y: 0.5)
71 | magicBackground.position = CGPoint(x: 275, y: 10)
72 | magicBackground.alpha = 0.45
73 |
74 | addChild(background)
75 |
76 | addChild(healthBackground)
77 | addChild(healthBar)
78 | addChild(magicBackground)
79 | addChild(magicBar)
80 |
81 |
82 | addChild(foodDisplay)
83 | addChild(woodDisplay)
84 | addChild(stoneDisplay)
85 | addChild(goldDisplay)
86 | }
87 |
88 | required init?(coder aDecoder: NSCoder) {
89 | fatalError("init(coder:) has not been implemented")
90 | }
91 |
92 | //Called during update loop and changes values based on new info
93 | func update(character: Character) {
94 | gold = character.inventory.gold
95 | food = character.inventory.food
96 | wood = character.inventory.wood
97 | stone = character.inventory.stone
98 |
99 | foodDisplay.text = "Food: \(food)"
100 | goldDisplay.text = "Gold: \(gold)"
101 | woodDisplay.text = "Wood: \(wood)"
102 | stoneDisplay.text = "Stone: \(stone)"
103 |
104 | maxHealth = character.health.max
105 | currentHealth = character.health.current
106 | currentMagic = character.magic.current
107 |
108 | maxMagic = character.magic.max
109 | healthBackground.size = CGSize(width: maxHealth, height: 16)
110 | healthBar.size = CGSize(width: currentHealth, height: 20)
111 | magicBackground.size = CGSize(width: maxMagic, height: 16)
112 | magicBar.size = CGSize(width: currentMagic, height: 20)
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/tinyRPG/GameScene.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameScene.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/7/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import SpriteKit
10 | import GameplayKit
11 |
12 | class GameScene: SKScene {
13 |
14 | //Basic Scene setup
15 | var entities = [GKEntity]()
16 | var graphs = [String : GKGraph]()
17 | var cam: SKCameraNode?
18 |
19 | // min size = C:64 R: 64
20 | let map = MapGen(columns: 64, rows: 64)
21 |
22 | var previousCameraPoint = CGPoint.zero
23 |
24 | let panGesture = UIPanGestureRecognizer()
25 |
26 | var gameState: GKStateMachine!
27 |
28 | let gameData = getDefaults(name: "GameData")
29 | //Helper character for testing. DO NOT REFERENCE
30 | lazy var character = Character(texture: SKTexture(imageNamed: "hero"), map: map)
31 |
32 | let statMenu = StatMenu(name: "Stats")
33 | let actionMenu = ActionMenu(name: "Actions")
34 |
35 | override func sceneDidLoad() {
36 | //setup game state
37 | gameState = GKStateMachine(states: [PlayerTurn(game: self, player: character), GameTurn()])
38 | gameState.enter(PlayerTurn.self)
39 |
40 | entities.append(character)
41 |
42 | addChild(map.tileMap)
43 | character.sprite.node.zPosition = 999
44 | addChild(character.sprite.node)
45 |
46 | }
47 |
48 | //Sets up gestures and camera in scene
49 | override func didMove(to view: SKView) {
50 | //pan around the map
51 | panGesture.addTarget(self, action: #selector(panGestureAction(_:)))
52 | view.addGestureRecognizer(panGesture)
53 |
54 |
55 | //setup camera
56 | cam = SKCameraNode()
57 | self.camera = cam
58 | self.addChild(cam!)
59 |
60 | //menus
61 | statMenu.position = CGPoint(x: 0, y: 620)
62 | cam?.addChild(statMenu)
63 |
64 | actionMenu.zPosition = 1000
65 | actionMenu.isHidden = true
66 |
67 | cam?.addChild(actionMenu)
68 |
69 | //set player to middle of current tile on map
70 | let playerPosition = character.movement.getOffsetLocation(point: character.sprite.node.position)
71 | character.sprite.node.position = map.tileMap.centerOfTile(atColumn: playerPosition.0, row: playerPosition.1)
72 | character.movement.currentLocation = playerPosition
73 |
74 | //sets camera to focus on player
75 | cam!.position = character.sprite.node.position
76 |
77 | }
78 |
79 | func showMovesMap(point: CGPoint) {
80 | //setups up the initial moves map - will move once a menu button is set for "move" action
81 | let playerPosition = character.movement.getOffsetLocation(point: point)
82 | let moves = character.movement.getRange(from: playerPosition)
83 | character.movement.highlightMoves(moves: moves)
84 | addChild(character.movement.movesMap)
85 | }
86 |
87 | //Allows for panning around the map
88 | @objc func panGestureAction(_ sender: UIPanGestureRecognizer) {
89 | guard let camera = self.camera else {
90 | return
91 | }
92 | // If the movement just began, save the first camera position
93 | if sender.state == .began {
94 | previousCameraPoint = self.camera!.position
95 | }
96 | // Perform the translation
97 | let translation = sender.translation(in: self.view)
98 | let newPosition = CGPoint(
99 | x: previousCameraPoint.x + translation.x * -1,
100 | y: previousCameraPoint.y + translation.y
101 | )
102 | camera.position = newPosition
103 | }
104 |
105 |
106 | func touchDown(atPoint pos : CGPoint) {
107 |
108 | }
109 |
110 | func touchMoved(toPoint pos : CGPoint) {
111 |
112 | }
113 |
114 | func touchUp(atPoint pos : CGPoint) {
115 | let destination = character.movement.moveTo(point: pos)
116 | let moveToTile = SKAction.move(to: destination, duration: 0.25)
117 | if character.movement.moved == true {
118 | cam?.run(moveToTile)
119 | character.sprite.node.run(moveToTile)
120 | showMovesMap(point: destination)
121 | character.movement.moved = false
122 | }
123 | }
124 |
125 | override func touchesBegan(_ touches: Set, with event: UIEvent?) {
126 |
127 |
128 | for t in touches {
129 | self.touchDown(atPoint: t.location(in: self))
130 | }
131 | }
132 |
133 | override func touchesMoved(_ touches: Set, with event: UIEvent?) {
134 | for t in touches {
135 | //detect force touch
136 | let maxForce = t.maximumPossibleForce
137 | let force = t.force
138 | let normalizedForce = force / maxForce
139 |
140 | let location = t.location(in: self)
141 | let node = self.atPoint(location)
142 |
143 | if normalizedForce >= 0.75 && node.name == "PlayerSprite" {
144 | actionMenu.isHidden = false
145 | }
146 |
147 | self.touchMoved(toPoint: t.location(in: self))
148 |
149 | }
150 | }
151 |
152 | override func touchesEnded(_ touches: Set, with event: UIEvent?) {
153 |
154 | let location = touches.first!.location(in: self)
155 | let node = self.atPoint(location)
156 |
157 | if node.parent is ActionMenu {
158 | switch node.name {
159 | case "MoveButton":
160 | showMovesMap(point: character.sprite.node.position)
161 | actionMenu.isHidden = true
162 | case "EndTurn":
163 | gameState.enter(GameTurn.self)
164 | actionMenu.isHidden = true
165 | case "TileAction":
166 | print("Tile Action Button Pushed")
167 | actionMenu.isHidden = true
168 | case "Inventory":
169 | print("Inventory Button Pushed")
170 | actionMenu.isHidden = true
171 | default:
172 | print(node.name ?? "NO Name")
173 | }
174 | } else {
175 | if actionMenu.isHidden {
176 | self.touchUp(atPoint: location)
177 | }
178 | actionMenu.isHidden = true
179 | }
180 |
181 | }
182 |
183 | override func touchesCancelled(_ touches: Set, with event: UIEvent?) {
184 | for t in touches { self.touchUp(atPoint: t.location(in: self)) }
185 | }
186 |
187 |
188 | override func update(_ currentTime: TimeInterval) {
189 | if gameState.currentState is GameTurn {
190 | gameState.enter(PlayerTurn.self)
191 | }
192 |
193 | //If moving happened, add the new tileMap to the scene and set the camera position and end the pan gesture
194 | if map.updateMap(point: camera?.position ?? CGPoint(x: 0.0, y: 0.0), zoom: 1.0) == true {
195 | self.addChild(map.tileMap)
196 | camera?.position = map.getTileCenter(point: CGPoint(x: 0.0, y: 0.0), inMap: map.tileMap)
197 | panGesture.cancel()
198 | }
199 |
200 | statMenu.update(character: character)
201 |
202 | }
203 |
204 | }
205 |
--------------------------------------------------------------------------------
/tinyRPG/Character/CharacterComponents/MovementComponent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MovementComponent.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 2/28/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SpriteKit
11 | import GameplayKit
12 |
13 | class MovementComponent: GKComponent {
14 |
15 | var movesMap = SKNode()
16 | var moved = false
17 | var range = 2
18 | var maxMovementPoints = 2
19 | var movementPoints = 2
20 |
21 | var directions = [(1, -1, 0), (1, 0, -1), (0, 1, -1),
22 | (-1, 1, 0), (-1, 0, 1), (0, -1, 1)]
23 |
24 | var diagonals = [(2, -1, -1), (1, 1, -2), (-1, 2, -1),
25 | (-2, 1, 1), (-1, -1, 2), (1, -2, 1)]
26 |
27 | var map: MapGen
28 | var validTiles = [(Int, Int)]()
29 |
30 | var currentLocation = (0, 0)
31 |
32 | lazy var currentTile = map.tileMap.tileDefinition(atColumn: currentLocation.0, row: currentLocation.1)
33 |
34 | init(map: MapGen) {
35 | self.map = map
36 | super.init()
37 | }
38 |
39 | required init?(coder aDecoder: NSCoder) {
40 | fatalError("init(coder:) has not been implemented")
41 | }
42 |
43 |
44 | func moveTo(point: CGPoint) -> CGPoint {
45 |
46 | let column = map.tileMap.tileColumnIndex(fromPosition: point)
47 | let row = map.tileMap.tileRowIndex(fromPosition: point)
48 | let tile = (column, row)
49 |
50 | //sets up a path from origin to the new location
51 | let currentCube = offsetToCube(column: currentLocation.0, row: currentLocation.1)
52 | let futureCube = offsetToCube(column: tile.0, row: tile.1)
53 | let path = getPath(from: currentCube, to: futureCube)
54 |
55 | //checks the cost for each step between origin and new location
56 | var totalCost = 0
57 | for each in path {
58 | if each != currentCube {
59 | //incriments the totalCost for all new tiles
60 | let loc = cubeToOffset(cube: each)
61 | let tileDef = map.tileMap.tileDefinition(atColumn: loc.0, row: loc.1)
62 | let cost = tileDef?.userData?.value(forKey: "cost") as! Int
63 | totalCost += cost
64 | }
65 | }
66 |
67 | var destination = map.tileMap.centerOfTile(atColumn: currentLocation.0, row: currentLocation.1)
68 |
69 | if validTiles.contains(where: { $0 == tile }) && totalCost <= movementPoints {
70 | destination = map.tileMap.centerOfTile(atColumn: column, row: row)
71 | moved = true
72 | currentLocation = (column, row)
73 | }
74 | movementPoints -= totalCost
75 | return destination
76 | }
77 |
78 |
79 | ///////Supporting Functions
80 |
81 | func getOffsetLocation(point: CGPoint) -> (Int, Int) {
82 | let column = map.tileMap.tileColumnIndex(fromPosition: point)
83 | let row = map.tileMap.tileRowIndex(fromPosition: point)
84 |
85 | return (column, row)
86 | }
87 |
88 | func offsetToCube(column: Int, row: Int) -> (Int, Int, Int){
89 | let x = (column - (row - (row&1)) / 2)
90 | let z = row
91 | let y = (-x - z)
92 |
93 | return(x, y, z)
94 | }
95 |
96 | func cubeToOffset(cube: (Int, Int, Int)) -> (Int, Int) {
97 | let column = cube.0 + (cube.2 - (cube.2&1)) / 2
98 | let row = cube.2
99 | return (column, row)
100 | }
101 |
102 | func cubeAdd(cubeA: (Int, Int, Int), cubeB: (Int, Int, Int)) -> (Int, Int, Int) {
103 | let result = ((cubeA.0 + cubeB.0), (cubeA.1 + cubeB.1), (cubeA.2 + cubeB.2))
104 | return result
105 | }
106 |
107 | func cubeSubtract(cubeA: (Int, Int, Int), cubeB: (Int, Int, Int)) -> (Int, Int, Int) {
108 | let result = ((cubeA.0 - cubeB.0), (cubeA.1 - cubeB.1), (cubeA.2 - cubeB.2))
109 | return result
110 | }
111 |
112 | func cubeRound(cube: (Double, Double, Double)) -> (Int, Int, Int) {
113 | var xi = round(cube.0)
114 | var yi = round(cube.1)
115 | var zi = round(cube.2)
116 |
117 | let xDiff = abs(xi - cube.0)
118 | let yDiff = abs(yi - cube.1)
119 | let zDiff = abs(zi - cube.2)
120 |
121 | if xDiff > yDiff && xDiff > zDiff {
122 | xi = (-yi - zi)
123 | } else if yDiff > zDiff {
124 | yi = (-xi - zi)
125 | } else {
126 | zi = (-xi - yi)
127 | }
128 |
129 | return (Int(xi), Int(yi), Int(zi))
130 | }
131 |
132 | func cubeNudge(cube: (Int, Int, Int)) -> (Double, Double, Double) {
133 | let result = (Double(cube.0) + 0.000001, Double(cube.1) + 0.000001, Double(cube.2) - 0.000002)
134 | return result
135 | }
136 |
137 | func getNeighbors(location: (Int, Int)) -> [(Int, Int, Int)] {
138 | let cubeLocation = offsetToCube(column: location.0, row: location.1)
139 | var neighbors = [(Int, Int, Int)]()
140 |
141 | for direction in directions {
142 | let result = cubeAdd(cubeA: cubeLocation, cubeB: direction)
143 | neighbors.append(result)
144 | }
145 |
146 | return neighbors
147 | }
148 |
149 | func getDistance(cubeA: (Int, Int, Int), cubeB: (Int, Int, Int)) -> Int {
150 |
151 | let x = abs(cubeA.0 - cubeB.0)
152 | let y = abs(cubeA.1 - cubeB.1)
153 | let z = abs(cubeA.2 - cubeB.2)
154 |
155 | let distance = max(x, y, z)
156 |
157 | return distance
158 |
159 | }
160 |
161 | //Linear Interpolation
162 | func lerp(a: (Double, Double, Double), b: (Double, Double, Double), t: Double) -> (Double, Double, Double) {
163 | let x = a.0 * (1.0 - t) + (b.0 * t)
164 | let y = a.1 * (1.0 - t) + (b.1 * t)
165 | let z = a.2 * (1.0 - t) + (b.2 * t)
166 |
167 | return (x, y, z)
168 | }
169 |
170 | func getPath(from: (Int, Int, Int), to: (Int, Int, Int)) -> [(Int, Int, Int)] {
171 | let d = getDistance(cubeA: from, cubeB: to)
172 |
173 | let aNudge = cubeNudge(cube: from)
174 | let bNudge = cubeNudge(cube: to)
175 | let step = 1.0 / max(Double(d), 1.0)
176 |
177 | var results = [(Int, Int, Int)]()
178 |
179 | let path1 = 000
180 |
181 | for i in 0...d {
182 | let t = step * Double(i)
183 | let lerpedCube = lerp(a: aNudge, b: bNudge, t: t)
184 | let result = cubeRound(cube: lerpedCube)
185 | results.append(result)
186 | }
187 |
188 | return results
189 | }
190 |
191 | func getRange(from: (Int, Int)) -> [(Int, Int)] {
192 | let origin = offsetToCube(column: from.0, row: from.1)
193 | var visited = [origin]
194 | var fringes = [[(origin)]]
195 |
196 | var validTiles = [(Int, Int)]()
197 |
198 | for k in 1...range {
199 | let emptyA = [(Int, Int, Int)]()
200 | fringes.append(emptyA)
201 | for tile in fringes[k - 1] {
202 | let neighbors = getNeighbors(location: cubeToOffset(cube: tile))
203 | for neighbor in neighbors {
204 | if visited.contains(where: { $0 == neighbor }) {
205 | } else {
206 | visited.append(neighbor)
207 | fringes[k].append(neighbor)
208 | }
209 | }
210 | }
211 |
212 | for (index, member) in visited.enumerated() {
213 | if member == origin {
214 | visited.remove(at: index)
215 | } else {
216 | validTiles.append(cubeToOffset(cube: member))
217 | }
218 | }
219 | }
220 |
221 | let results = filterMovementCost(origin: offsetToCube(column: from.0, row: from.1), range: validTiles)
222 |
223 |
224 | return results
225 | }
226 |
227 | func filterMovementCost(origin: (Int, Int, Int), range: [(Int, Int)]) -> [(Int, Int)] {
228 | var validMoves = [(Int, Int, Int)]()
229 | var validCoordinates = [(Int, Int)]()
230 |
231 | for each in range {
232 | let path = getPath(from: origin, to: offsetToCube(column: each.0, row: each.1))
233 | var pathCost = 0
234 | for step in path {
235 | if step != origin {
236 | let tile = map.tileMap.tileDefinition(atColumn: cubeToOffset(cube: step).0, row: cubeToOffset(cube: step).1)
237 | let cost = tile?.userData?.value(forKey: "cost") as? Int ?? 5
238 | pathCost += cost
239 | if pathCost <= movementPoints {
240 | if !validMoves.contains(where: { $0 == step }) {
241 | validMoves.append(step)
242 | }
243 | }
244 | }
245 | }
246 | }
247 | for each in validMoves {
248 | validCoordinates.append(cubeToOffset(cube: each))
249 | }
250 | validTiles = validCoordinates
251 | return validCoordinates
252 | }
253 |
254 | func highlightMoves(moves: [(Int, Int)]) {
255 | clearMoveMap()
256 | let movesMapNode = SKTileMapNode(tileSet: map.tileSet!, columns: map.columns, rows: map.rows, tileSize: CGSize(width: 125, height: 144))
257 | movesMapNode.zPosition = 2
258 | movesMapNode.name = "movesMapNode"
259 | for move in moves {
260 | movesMapNode.setTileGroup(map.tileSet!.tileGroups.first( where: { $0.name == "blank"}), forColumn: move.0, row: move.1)
261 | }
262 | movesMap.addChild(movesMapNode)
263 | }
264 |
265 | func clearMoveMap() {
266 | movesMap.childNode(withName: "movesMapNode")?.removeFromParent()
267 | movesMap.removeFromParent()
268 | }
269 | }
270 |
--------------------------------------------------------------------------------
/tinyRPG/World/MapGen.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MapGen.swift
3 | // tinyRPG
4 | //
5 | // Created by Logan Roberts on 3/7/19.
6 | // Copyright © 2019 Logan Roberts. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import GameplayKit
11 | import SpriteKit
12 |
13 | class MapGen {
14 | //List of valid biomes for tile Data
15 | enum Biome {
16 | case Ocean
17 | case Beach
18 | case Grassland
19 | case Forest
20 | case Rainforest
21 | case Desert
22 | case Mountain
23 | case Taiga
24 | case MountainSnow
25 | case MountainForest
26 | case Snow
27 | case Blank
28 | case River
29 | }
30 |
31 |
32 | //Noise Setup. One for height(and temperature) and one for moisture
33 | let moistureNoise = GKNoise(GKPerlinNoiseSource(
34 | frequency: 2,
35 | octaveCount: 8,
36 | persistence: 0.8,
37 | lacunarity: 1.5,
38 | seed: Int32(arc4random_uniform(5000 - 1))))
39 |
40 | let heightNoise = GKNoise(GKPerlinNoiseSource(
41 | frequency: 2,
42 | octaveCount: 8,
43 | persistence: 0.8,
44 | lacunarity: 1.5,
45 | seed: Int32(arc4random_uniform(5000 - 1))))
46 |
47 | var tileSet = SKTileSet(named: "Terrain")
48 |
49 | // tileMap setup
50 | var tileMap: SKTileMapNode
51 | var columns: Int
52 | var rows: Int
53 |
54 | var currentTileIndex = (0, 0)
55 |
56 | init(columns: Int, rows: Int) {
57 |
58 | self.columns = columns
59 | self.rows = rows
60 |
61 | self.tileMap = SKTileMapNode(tileSet: tileSet!, columns: columns, rows: rows, tileSize: CGSize(width: 125, height: 144))
62 |
63 | heightNoise.clamp(lowerBound: -0.1, upperBound: 1.0)
64 | heightNoise.raiseToPower(4)
65 |
66 | self.tileMap = createMap(columns: columns, rows: rows)
67 |
68 | }
69 |
70 | /*
71 | Creates an updated map aftermovement by using the utility function to adjust noisemaps.
72 | If no movement, does nothing. Returns bool back to the GameScene for use in the Update()
73 | function.
74 | */
75 |
76 | func isRiver() -> Bool {
77 | let num = arc4random_uniform(5000-1)
78 | guard num > 4900 else {
79 | return false
80 | }
81 | return true
82 | }
83 |
84 | func updateMap(point: CGPoint, zoom: CGFloat) -> Bool {
85 | var modified = false
86 |
87 | currentTileIndex = getOffsetLocation(point: point, inMap: tileMap)
88 |
89 | let mapOffsetCenter = (tileMap.numberOfColumns / 2, tileMap.numberOfRows / 2 - 1)
90 | let movedTiles = (currentTileIndex.0 - mapOffsetCenter.0, currentTileIndex.1 - mapOffsetCenter.1)
91 |
92 | //set zoom level for tile offsets
93 | let xBorder = Int(round(zoom) * 4)
94 | let yBorder = Int(round(zoom) * 7)
95 |
96 | //check if camera.position.x is in bounds
97 | switch currentTileIndex.0 {
98 | case .. (Int, Int) {
139 | let column = inMap.tileColumnIndex(fromPosition: point)
140 | let row = inMap.tileRowIndex(fromPosition: point)
141 | return (column, row)
142 | }
143 |
144 | //Gets the center tile on screen in point (for passing back to the camera.position)
145 | func getTileCenter(point: CGPoint, inMap: SKTileMapNode) -> CGPoint {
146 | let offset = getOffsetLocation(point: point, inMap: inMap)
147 | let centerPoint = tileMap.centerOfTile(atColumn: offset.0, row: offset.1)
148 | return centerPoint
149 | }
150 |
151 | /*
152 | Map generation function. Sets the noiseMaps from the preset noiseSources.
153 | Creates a TileMap and then iterates to create biome data by comparing the HeightMap to the Moisture Map
154 | Calls the setBiome helper function to get the results
155 | */
156 | func createMap(columns: Int, rows: Int) -> SKTileMapNode {
157 | let elevationMap = GKNoiseMap(heightNoise)
158 | let moistureMap = GKNoiseMap(moistureNoise)
159 |
160 | let map = SKTileMapNode(tileSet: tileSet!, columns: columns, rows: rows, tileSize: CGSize(width: 125, height: 144))
161 |
162 | for column in 0 ..< columns {
163 | for row in 0 ..< rows {
164 | let location = vector2(Int32(row), Int32(column))
165 | let tileBiome = setBiome(location: location, e: elevationMap, m: moistureMap)
166 |
167 | switch tileBiome {
168 | case .Ocean:
169 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "ocean"}), forColumn: column, row: row)
170 | case .Beach:
171 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "beach"}), forColumn: column, row: row)
172 | case .Grassland:
173 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "grass"}), forColumn: column, row: row)
174 | case .Forest:
175 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "forest"}), forColumn: column, row: row)
176 | case .Rainforest:
177 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "rainForest"}), forColumn: column, row: row)
178 | case .Desert:
179 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "desert"}), forColumn: column, row: row)
180 | case .Mountain:
181 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "mountain"}), forColumn: column, row: row)
182 | case .MountainSnow:
183 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "mountainSnow"}), forColumn: column, row: row)
184 | case .MountainForest:
185 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "mountainForest"}), forColumn: column, row: row)
186 | case .River:
187 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "water"}), forColumn: column, row: row)
188 | case .Snow:
189 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "snow"}), forColumn: column, row: row)
190 | case .Taiga:
191 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "taiga"}), forColumn: column, row: row)
192 | case .Blank:
193 | map.setTileGroup(map.tileSet.tileGroups.first( where: { $0.name == "blank"}), forColumn: column, row: row)
194 | }
195 |
196 | }
197 | }
198 | let newMap = generateRiverSource(dryMap: map)
199 | return newMap
200 | }
201 |
202 | // Get the elevation and compare against a moisture map for biome generation and return the Biome for tilemap creation
203 | func setBiome(location: simd_int2, e: GKNoiseMap, m: GKNoiseMap) -> Biome {
204 | let eV = e.value(at: location)
205 | let mV = m.value(at: location)
206 | var biome: Biome = .Blank
207 |
208 | //Check for Ocean/Beach
209 | guard eV > -0.5 else {
210 | if eV > -0.51 {
211 | biome = .Beach
212 | } else {
213 | biome = .Ocean
214 | }
215 | return biome
216 | }
217 |
218 | if eV > -0.5 && eV < -0.25 {
219 | switch mV {
220 | case -1.0 ... -0.75:
221 | biome = .Desert
222 | case -0.75 ... -0.5:
223 | biome = .Grassland
224 | case -0.5 ... 0.25:
225 | biome = .Forest
226 | case 0.25 ... 1.0:
227 | if isRiver() {
228 | biome = .River
229 | } else {
230 | biome = .Rainforest
231 | }
232 | default:
233 | print("Tropical Biome outside range")
234 | biome = .Blank
235 | }
236 | return biome
237 | }
238 |
239 | if eV > -0.25 && eV < 0.25 {
240 | switch mV {
241 | case -1.0 ... -0.5:
242 | biome = .Desert
243 | case -0.5 ... 0.0:
244 | biome = .Grassland
245 | case 0.0 ... 1.0:
246 | if isRiver() {
247 | biome = .River
248 | } else {
249 | biome = .Forest
250 | }
251 | default:
252 | print("Temperate Biome outside range")
253 | biome = .Blank
254 | }
255 | return biome
256 | }
257 |
258 | if eV > 0.25 && eV < 0.5 {
259 | switch mV {
260 | case -1.0 ... -0.25:
261 | biome = .Desert
262 | case -0.25 ... 0.25:
263 | biome = .Taiga
264 | case 0.25 ... 1.0:
265 | biome = .Snow
266 | default:
267 | print("Arctic Biome outside range")
268 | biome = .Blank
269 | }
270 | return biome
271 | }
272 |
273 | if eV > 0.5 && eV <= 1.0 {
274 | switch mV {
275 | case -1.0 ... -0.25:
276 | biome = .Mountain
277 | case -0.25 ... 0.25:
278 | if isRiver() {
279 | biome = .River
280 | } else {
281 | biome = .MountainForest
282 | }
283 | case 0.25 ... 1.0:
284 | biome = .MountainSnow
285 | default:
286 | print("Mountain Biome outside range")
287 | biome = .Blank
288 | }
289 | return biome
290 | }
291 |
292 | return biome
293 | }
294 |
295 | func generateRiverSource(dryMap: SKTileMapNode) -> SKTileMapNode {
296 | let map = dryMap
297 | var rivers = [(Int, Int)]()
298 |
299 |
300 | //creates the sources and then adds to the array of points
301 | for column in 0...map.numberOfColumns {
302 | for row in 0...map.numberOfRows {
303 | let tile = map.tileDefinition(atColumn: column, row: row)
304 | if ((tile?.userData?.value(forKey: "river")) != nil) {
305 | rivers.append((column, row))
306 | }
307 |
308 | }
309 | }
310 |
311 | var index = 0
312 |
313 | for (i, each) in rivers.enumerated() {
314 |
315 |
316 | }
317 |
318 |
319 | return map
320 | }
321 |
322 | }
323 |
--------------------------------------------------------------------------------
/tinyRPG.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | C8147477223300EB00FCE476 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8147476223300EB00FCE476 /* Extensions.swift */; };
11 | C814747B223314E200FCE476 /* MovementComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C814747A223314E200FCE476 /* MovementComponent.swift */; };
12 | C83167B22231582100584C0B /* Character.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83167B12231582100584C0B /* Character.swift */; };
13 | C83167B52231583B00584C0B /* MapGen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83167B42231583B00584C0B /* MapGen.swift */; };
14 | C83167BA2232CEEB00584C0B /* SpriteComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83167B92232CEEB00584C0B /* SpriteComponent.swift */; };
15 | C874AA7B2238277200FA152F /* StateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = C874AA7A2238277200FA152F /* StateMachine.swift */; };
16 | C874AA7E2238439A00FA152F /* Weapon.swift in Sources */ = {isa = PBXBuildFile; fileRef = C874AA7D2238439A00FA152F /* Weapon.swift */; };
17 | C874AA80223843BD00FA152F /* Armor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C874AA7F223843BD00FA152F /* Armor.swift */; };
18 | C874AA82223843CB00FA152F /* AttackMove.swift in Sources */ = {isa = PBXBuildFile; fileRef = C874AA81223843CB00FA152F /* AttackMove.swift */; };
19 | C874AA842238441000FA152F /* ExperienceComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C874AA832238441000FA152F /* ExperienceComponent.swift */; };
20 | C874AA862238445A00FA152F /* HealthComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C874AA852238445A00FA152F /* HealthComponent.swift */; };
21 | C874AA88223848B600FA152F /* InventoryComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C874AA87223848B600FA152F /* InventoryComponent.swift */; };
22 | C87F7DB8223157420055E617 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C87F7DB7223157420055E617 /* AppDelegate.swift */; };
23 | C87F7DBA223157420055E617 /* GameScene.sks in Resources */ = {isa = PBXBuildFile; fileRef = C87F7DB9223157420055E617 /* GameScene.sks */; };
24 | C87F7DBE223157420055E617 /* GameScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = C87F7DBD223157420055E617 /* GameScene.swift */; };
25 | C87F7DC0223157420055E617 /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C87F7DBF223157420055E617 /* GameViewController.swift */; };
26 | C87F7DC3223157420055E617 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C87F7DC1223157420055E617 /* Main.storyboard */; };
27 | C87F7DC5223157440055E617 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C87F7DC4223157440055E617 /* Assets.xcassets */; };
28 | C87F7DC8223157440055E617 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C87F7DC6223157440055E617 /* LaunchScreen.storyboard */; };
29 | C8857791223935DD0092CAF5 /* Terrain.sks in Resources */ = {isa = PBXBuildFile; fileRef = C885778F223935DD0092CAF5 /* Terrain.sks */; };
30 | C885779622393FCC0092CAF5 /* GameData.plist in Resources */ = {isa = PBXBuildFile; fileRef = C885779522393FCC0092CAF5 /* GameData.plist */; };
31 | C8CD774B224014EA00227751 /* TileActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8CD774A224014EA00227751 /* TileActions.swift */; };
32 | C8F9F7A9223A9D610059FB1C /* StatMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8F9F7A8223A9D610059FB1C /* StatMenu.swift */; };
33 | C8FA71C5223AB378003E063F /* MagicComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8FA71C4223AB378003E063F /* MagicComponent.swift */; };
34 | C8FA71C7223AB6C0003E063F /* ActionMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8FA71C6223AB6C0003E063F /* ActionMenu.swift */; };
35 | /* End PBXBuildFile section */
36 |
37 | /* Begin PBXFileReference section */
38 | C8147476223300EB00FCE476 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; };
39 | C814747A223314E200FCE476 /* MovementComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovementComponent.swift; sourceTree = ""; };
40 | C83167B12231582100584C0B /* Character.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Character.swift; sourceTree = ""; };
41 | C83167B42231583B00584C0B /* MapGen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapGen.swift; sourceTree = ""; };
42 | C83167B7223159A500584C0B /* MyPlayground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = MyPlayground.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
43 | C83167B92232CEEB00584C0B /* SpriteComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpriteComponent.swift; sourceTree = ""; };
44 | C874AA7A2238277200FA152F /* StateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateMachine.swift; sourceTree = ""; };
45 | C874AA7D2238439A00FA152F /* Weapon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Weapon.swift; sourceTree = ""; };
46 | C874AA7F223843BD00FA152F /* Armor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Armor.swift; sourceTree = ""; };
47 | C874AA81223843CB00FA152F /* AttackMove.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttackMove.swift; sourceTree = ""; };
48 | C874AA832238441000FA152F /* ExperienceComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExperienceComponent.swift; sourceTree = ""; };
49 | C874AA852238445A00FA152F /* HealthComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthComponent.swift; sourceTree = ""; };
50 | C874AA87223848B600FA152F /* InventoryComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InventoryComponent.swift; sourceTree = ""; };
51 | C87F7DB4223157420055E617 /* tinyRPG.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tinyRPG.app; sourceTree = BUILT_PRODUCTS_DIR; };
52 | C87F7DB7223157420055E617 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
53 | C87F7DB9223157420055E617 /* GameScene.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = GameScene.sks; sourceTree = ""; };
54 | C87F7DBD223157420055E617 /* GameScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameScene.swift; sourceTree = ""; };
55 | C87F7DBF223157420055E617 /* GameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = ""; };
56 | C87F7DC2223157420055E617 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
57 | C87F7DC4223157440055E617 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
58 | C87F7DC7223157440055E617 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
59 | C87F7DC9223157440055E617 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
60 | C885778F223935DD0092CAF5 /* Terrain.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Terrain.sks; sourceTree = ""; };
61 | C885779522393FCC0092CAF5 /* GameData.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = GameData.plist; sourceTree = ""; };
62 | C8CD774A224014EA00227751 /* TileActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileActions.swift; sourceTree = ""; };
63 | C8F9F7A8223A9D610059FB1C /* StatMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatMenu.swift; sourceTree = ""; };
64 | C8FA71C4223AB378003E063F /* MagicComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MagicComponent.swift; sourceTree = ""; };
65 | C8FA71C6223AB6C0003E063F /* ActionMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionMenu.swift; sourceTree = ""; };
66 | /* End PBXFileReference section */
67 |
68 | /* Begin PBXFrameworksBuildPhase section */
69 | C87F7DB1223157420055E617 /* Frameworks */ = {
70 | isa = PBXFrameworksBuildPhase;
71 | buildActionMask = 2147483647;
72 | files = (
73 | );
74 | runOnlyForDeploymentPostprocessing = 0;
75 | };
76 | /* End PBXFrameworksBuildPhase section */
77 |
78 | /* Begin PBXGroup section */
79 | C83167B32231582600584C0B /* Character */ = {
80 | isa = PBXGroup;
81 | children = (
82 | C83167B12231582100584C0B /* Character.swift */,
83 | C83167B82232CEDE00584C0B /* CharacterComponents */,
84 | );
85 | path = Character;
86 | sourceTree = "";
87 | };
88 | C83167B62231583E00584C0B /* World */ = {
89 | isa = PBXGroup;
90 | children = (
91 | C874AA7A2238277200FA152F /* StateMachine.swift */,
92 | C83167B42231583B00584C0B /* MapGen.swift */,
93 | C885778F223935DD0092CAF5 /* Terrain.sks */,
94 | );
95 | path = World;
96 | sourceTree = "";
97 | };
98 | C83167B82232CEDE00584C0B /* CharacterComponents */ = {
99 | isa = PBXGroup;
100 | children = (
101 | C83167B92232CEEB00584C0B /* SpriteComponent.swift */,
102 | C814747A223314E200FCE476 /* MovementComponent.swift */,
103 | C874AA832238441000FA152F /* ExperienceComponent.swift */,
104 | C874AA852238445A00FA152F /* HealthComponent.swift */,
105 | C8FA71C4223AB378003E063F /* MagicComponent.swift */,
106 | C874AA87223848B600FA152F /* InventoryComponent.swift */,
107 | );
108 | path = CharacterComponents;
109 | sourceTree = "";
110 | };
111 | C874AA792238275A00FA152F /* Interface */ = {
112 | isa = PBXGroup;
113 | children = (
114 | C8F9F7A8223A9D610059FB1C /* StatMenu.swift */,
115 | C8FA71C6223AB6C0003E063F /* ActionMenu.swift */,
116 | C8CD774A224014EA00227751 /* TileActions.swift */,
117 | );
118 | path = Interface;
119 | sourceTree = "";
120 | };
121 | C874AA7C2238435200FA152F /* Items */ = {
122 | isa = PBXGroup;
123 | children = (
124 | C874AA7D2238439A00FA152F /* Weapon.swift */,
125 | C874AA7F223843BD00FA152F /* Armor.swift */,
126 | C874AA81223843CB00FA152F /* AttackMove.swift */,
127 | );
128 | path = Items;
129 | sourceTree = "";
130 | };
131 | C87F7DAB223157420055E617 = {
132 | isa = PBXGroup;
133 | children = (
134 | C87F7DB6223157420055E617 /* tinyRPG */,
135 | C87F7DB5223157420055E617 /* Products */,
136 | );
137 | sourceTree = "";
138 | };
139 | C87F7DB5223157420055E617 /* Products */ = {
140 | isa = PBXGroup;
141 | children = (
142 | C87F7DB4223157420055E617 /* tinyRPG.app */,
143 | );
144 | name = Products;
145 | sourceTree = "";
146 | };
147 | C87F7DB6223157420055E617 /* tinyRPG */ = {
148 | isa = PBXGroup;
149 | children = (
150 | C83167B7223159A500584C0B /* MyPlayground.playground */,
151 | C87F7DBF223157420055E617 /* GameViewController.swift */,
152 | C87F7DBD223157420055E617 /* GameScene.swift */,
153 | C874AA792238275A00FA152F /* Interface */,
154 | C83167B32231582600584C0B /* Character */,
155 | C874AA7C2238435200FA152F /* Items */,
156 | C83167B62231583E00584C0B /* World */,
157 | C87F7DD12231578C0055E617 /* Support */,
158 | );
159 | path = tinyRPG;
160 | sourceTree = "";
161 | };
162 | C87F7DD12231578C0055E617 /* Support */ = {
163 | isa = PBXGroup;
164 | children = (
165 | C87F7DB9223157420055E617 /* GameScene.sks */,
166 | C8147476223300EB00FCE476 /* Extensions.swift */,
167 | C87F7DB7223157420055E617 /* AppDelegate.swift */,
168 | C87F7DC4223157440055E617 /* Assets.xcassets */,
169 | C87F7DC1223157420055E617 /* Main.storyboard */,
170 | C87F7DC6223157440055E617 /* LaunchScreen.storyboard */,
171 | C87F7DC9223157440055E617 /* Info.plist */,
172 | C885779522393FCC0092CAF5 /* GameData.plist */,
173 | );
174 | path = Support;
175 | sourceTree = "";
176 | };
177 | /* End PBXGroup section */
178 |
179 | /* Begin PBXNativeTarget section */
180 | C87F7DB3223157420055E617 /* tinyRPG */ = {
181 | isa = PBXNativeTarget;
182 | buildConfigurationList = C87F7DCC223157440055E617 /* Build configuration list for PBXNativeTarget "tinyRPG" */;
183 | buildPhases = (
184 | C87F7DB0223157420055E617 /* Sources */,
185 | C87F7DB1223157420055E617 /* Frameworks */,
186 | C87F7DB2223157420055E617 /* Resources */,
187 | );
188 | buildRules = (
189 | );
190 | dependencies = (
191 | );
192 | name = tinyRPG;
193 | productName = tinyRPG;
194 | productReference = C87F7DB4223157420055E617 /* tinyRPG.app */;
195 | productType = "com.apple.product-type.application";
196 | };
197 | /* End PBXNativeTarget section */
198 |
199 | /* Begin PBXProject section */
200 | C87F7DAC223157420055E617 /* Project object */ = {
201 | isa = PBXProject;
202 | attributes = {
203 | LastSwiftUpdateCheck = 1020;
204 | LastUpgradeCheck = 1020;
205 | ORGANIZATIONNAME = "Logan Roberts";
206 | TargetAttributes = {
207 | C87F7DB3223157420055E617 = {
208 | CreatedOnToolsVersion = 10.2;
209 | };
210 | };
211 | };
212 | buildConfigurationList = C87F7DAF223157420055E617 /* Build configuration list for PBXProject "tinyRPG" */;
213 | compatibilityVersion = "Xcode 9.3";
214 | developmentRegion = en;
215 | hasScannedForEncodings = 0;
216 | knownRegions = (
217 | en,
218 | Base,
219 | );
220 | mainGroup = C87F7DAB223157420055E617;
221 | productRefGroup = C87F7DB5223157420055E617 /* Products */;
222 | projectDirPath = "";
223 | projectRoot = "";
224 | targets = (
225 | C87F7DB3223157420055E617 /* tinyRPG */,
226 | );
227 | };
228 | /* End PBXProject section */
229 |
230 | /* Begin PBXResourcesBuildPhase section */
231 | C87F7DB2223157420055E617 /* Resources */ = {
232 | isa = PBXResourcesBuildPhase;
233 | buildActionMask = 2147483647;
234 | files = (
235 | C885779622393FCC0092CAF5 /* GameData.plist in Resources */,
236 | C87F7DC3223157420055E617 /* Main.storyboard in Resources */,
237 | C87F7DBA223157420055E617 /* GameScene.sks in Resources */,
238 | C87F7DC5223157440055E617 /* Assets.xcassets in Resources */,
239 | C87F7DC8223157440055E617 /* LaunchScreen.storyboard in Resources */,
240 | C8857791223935DD0092CAF5 /* Terrain.sks in Resources */,
241 | );
242 | runOnlyForDeploymentPostprocessing = 0;
243 | };
244 | /* End PBXResourcesBuildPhase section */
245 |
246 | /* Begin PBXSourcesBuildPhase section */
247 | C87F7DB0223157420055E617 /* Sources */ = {
248 | isa = PBXSourcesBuildPhase;
249 | buildActionMask = 2147483647;
250 | files = (
251 | C8FA71C7223AB6C0003E063F /* ActionMenu.swift in Sources */,
252 | C874AA88223848B600FA152F /* InventoryComponent.swift in Sources */,
253 | C814747B223314E200FCE476 /* MovementComponent.swift in Sources */,
254 | C87F7DBE223157420055E617 /* GameScene.swift in Sources */,
255 | C83167B52231583B00584C0B /* MapGen.swift in Sources */,
256 | C8CD774B224014EA00227751 /* TileActions.swift in Sources */,
257 | C87F7DC0223157420055E617 /* GameViewController.swift in Sources */,
258 | C874AA7E2238439A00FA152F /* Weapon.swift in Sources */,
259 | C87F7DB8223157420055E617 /* AppDelegate.swift in Sources */,
260 | C874AA842238441000FA152F /* ExperienceComponent.swift in Sources */,
261 | C874AA7B2238277200FA152F /* StateMachine.swift in Sources */,
262 | C874AA862238445A00FA152F /* HealthComponent.swift in Sources */,
263 | C83167BA2232CEEB00584C0B /* SpriteComponent.swift in Sources */,
264 | C874AA82223843CB00FA152F /* AttackMove.swift in Sources */,
265 | C8F9F7A9223A9D610059FB1C /* StatMenu.swift in Sources */,
266 | C83167B22231582100584C0B /* Character.swift in Sources */,
267 | C874AA80223843BD00FA152F /* Armor.swift in Sources */,
268 | C8147477223300EB00FCE476 /* Extensions.swift in Sources */,
269 | C8FA71C5223AB378003E063F /* MagicComponent.swift in Sources */,
270 | );
271 | runOnlyForDeploymentPostprocessing = 0;
272 | };
273 | /* End PBXSourcesBuildPhase section */
274 |
275 | /* Begin PBXVariantGroup section */
276 | C87F7DC1223157420055E617 /* Main.storyboard */ = {
277 | isa = PBXVariantGroup;
278 | children = (
279 | C87F7DC2223157420055E617 /* Base */,
280 | );
281 | name = Main.storyboard;
282 | sourceTree = "";
283 | };
284 | C87F7DC6223157440055E617 /* LaunchScreen.storyboard */ = {
285 | isa = PBXVariantGroup;
286 | children = (
287 | C87F7DC7223157440055E617 /* Base */,
288 | );
289 | name = LaunchScreen.storyboard;
290 | sourceTree = "";
291 | };
292 | /* End PBXVariantGroup section */
293 |
294 | /* Begin XCBuildConfiguration section */
295 | C87F7DCA223157440055E617 /* Debug */ = {
296 | isa = XCBuildConfiguration;
297 | buildSettings = {
298 | ALWAYS_SEARCH_USER_PATHS = NO;
299 | CLANG_ANALYZER_NONNULL = YES;
300 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
301 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
302 | CLANG_CXX_LIBRARY = "libc++";
303 | CLANG_ENABLE_MODULES = YES;
304 | CLANG_ENABLE_OBJC_ARC = YES;
305 | CLANG_ENABLE_OBJC_WEAK = YES;
306 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
307 | CLANG_WARN_BOOL_CONVERSION = YES;
308 | CLANG_WARN_COMMA = YES;
309 | CLANG_WARN_CONSTANT_CONVERSION = YES;
310 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
311 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
312 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
313 | CLANG_WARN_EMPTY_BODY = YES;
314 | CLANG_WARN_ENUM_CONVERSION = YES;
315 | CLANG_WARN_INFINITE_RECURSION = YES;
316 | CLANG_WARN_INT_CONVERSION = YES;
317 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
318 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
319 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
320 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
321 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
322 | CLANG_WARN_STRICT_PROTOTYPES = YES;
323 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
324 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
325 | CLANG_WARN_UNREACHABLE_CODE = YES;
326 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
327 | CODE_SIGN_IDENTITY = "iPhone Developer";
328 | COPY_PHASE_STRIP = NO;
329 | DEBUG_INFORMATION_FORMAT = dwarf;
330 | ENABLE_STRICT_OBJC_MSGSEND = YES;
331 | ENABLE_TESTABILITY = YES;
332 | GCC_C_LANGUAGE_STANDARD = gnu11;
333 | GCC_DYNAMIC_NO_PIC = NO;
334 | GCC_NO_COMMON_BLOCKS = YES;
335 | GCC_OPTIMIZATION_LEVEL = 0;
336 | GCC_PREPROCESSOR_DEFINITIONS = (
337 | "DEBUG=1",
338 | "$(inherited)",
339 | );
340 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
341 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
342 | GCC_WARN_UNDECLARED_SELECTOR = YES;
343 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
344 | GCC_WARN_UNUSED_FUNCTION = YES;
345 | GCC_WARN_UNUSED_VARIABLE = YES;
346 | IPHONEOS_DEPLOYMENT_TARGET = 12.2;
347 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
348 | MTL_FAST_MATH = YES;
349 | ONLY_ACTIVE_ARCH = YES;
350 | SDKROOT = iphoneos;
351 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
352 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
353 | };
354 | name = Debug;
355 | };
356 | C87F7DCB223157440055E617 /* Release */ = {
357 | isa = XCBuildConfiguration;
358 | buildSettings = {
359 | ALWAYS_SEARCH_USER_PATHS = NO;
360 | CLANG_ANALYZER_NONNULL = YES;
361 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
362 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
363 | CLANG_CXX_LIBRARY = "libc++";
364 | CLANG_ENABLE_MODULES = YES;
365 | CLANG_ENABLE_OBJC_ARC = YES;
366 | CLANG_ENABLE_OBJC_WEAK = YES;
367 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
368 | CLANG_WARN_BOOL_CONVERSION = YES;
369 | CLANG_WARN_COMMA = YES;
370 | CLANG_WARN_CONSTANT_CONVERSION = YES;
371 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
372 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
373 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
374 | CLANG_WARN_EMPTY_BODY = YES;
375 | CLANG_WARN_ENUM_CONVERSION = YES;
376 | CLANG_WARN_INFINITE_RECURSION = YES;
377 | CLANG_WARN_INT_CONVERSION = YES;
378 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
379 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
380 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
381 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
382 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
383 | CLANG_WARN_STRICT_PROTOTYPES = YES;
384 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
385 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
386 | CLANG_WARN_UNREACHABLE_CODE = YES;
387 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
388 | CODE_SIGN_IDENTITY = "iPhone Developer";
389 | COPY_PHASE_STRIP = NO;
390 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
391 | ENABLE_NS_ASSERTIONS = NO;
392 | ENABLE_STRICT_OBJC_MSGSEND = YES;
393 | GCC_C_LANGUAGE_STANDARD = gnu11;
394 | GCC_NO_COMMON_BLOCKS = YES;
395 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
396 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
397 | GCC_WARN_UNDECLARED_SELECTOR = YES;
398 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
399 | GCC_WARN_UNUSED_FUNCTION = YES;
400 | GCC_WARN_UNUSED_VARIABLE = YES;
401 | IPHONEOS_DEPLOYMENT_TARGET = 12.2;
402 | MTL_ENABLE_DEBUG_INFO = NO;
403 | MTL_FAST_MATH = YES;
404 | SDKROOT = iphoneos;
405 | SWIFT_COMPILATION_MODE = wholemodule;
406 | SWIFT_OPTIMIZATION_LEVEL = "-O";
407 | VALIDATE_PRODUCT = YES;
408 | };
409 | name = Release;
410 | };
411 | C87F7DCD223157440055E617 /* Debug */ = {
412 | isa = XCBuildConfiguration;
413 | buildSettings = {
414 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
415 | CODE_SIGN_STYLE = Automatic;
416 | DEVELOPMENT_TEAM = 4CJPA6ZPGD;
417 | INFOPLIST_FILE = tinyRPG/Support/Info.plist;
418 | LD_RUNPATH_SEARCH_PATHS = (
419 | "$(inherited)",
420 | "@executable_path/Frameworks",
421 | );
422 | PRODUCT_BUNDLE_IDENTIFIER = loganroberts.tinyRPG;
423 | PRODUCT_NAME = "$(TARGET_NAME)";
424 | SWIFT_VERSION = 5.0;
425 | TARGETED_DEVICE_FAMILY = "1,2";
426 | };
427 | name = Debug;
428 | };
429 | C87F7DCE223157440055E617 /* Release */ = {
430 | isa = XCBuildConfiguration;
431 | buildSettings = {
432 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
433 | CODE_SIGN_STYLE = Automatic;
434 | DEVELOPMENT_TEAM = 4CJPA6ZPGD;
435 | INFOPLIST_FILE = tinyRPG/Support/Info.plist;
436 | LD_RUNPATH_SEARCH_PATHS = (
437 | "$(inherited)",
438 | "@executable_path/Frameworks",
439 | );
440 | PRODUCT_BUNDLE_IDENTIFIER = loganroberts.tinyRPG;
441 | PRODUCT_NAME = "$(TARGET_NAME)";
442 | SWIFT_VERSION = 5.0;
443 | TARGETED_DEVICE_FAMILY = "1,2";
444 | };
445 | name = Release;
446 | };
447 | /* End XCBuildConfiguration section */
448 |
449 | /* Begin XCConfigurationList section */
450 | C87F7DAF223157420055E617 /* Build configuration list for PBXProject "tinyRPG" */ = {
451 | isa = XCConfigurationList;
452 | buildConfigurations = (
453 | C87F7DCA223157440055E617 /* Debug */,
454 | C87F7DCB223157440055E617 /* Release */,
455 | );
456 | defaultConfigurationIsVisible = 0;
457 | defaultConfigurationName = Release;
458 | };
459 | C87F7DCC223157440055E617 /* Build configuration list for PBXNativeTarget "tinyRPG" */ = {
460 | isa = XCConfigurationList;
461 | buildConfigurations = (
462 | C87F7DCD223157440055E617 /* Debug */,
463 | C87F7DCE223157440055E617 /* Release */,
464 | );
465 | defaultConfigurationIsVisible = 0;
466 | defaultConfigurationName = Release;
467 | };
468 | /* End XCConfigurationList section */
469 | };
470 | rootObject = C87F7DAC223157420055E617 /* Project object */;
471 | }
472 |
--------------------------------------------------------------------------------