├── Little Orion
├── README.md
├── Little Orion
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── icons
│ │ │ ├── Contents.json
│ │ │ ├── energy-icon.imageset
│ │ │ │ ├── energy-icon.png
│ │ │ │ ├── energy-icon@2x.png
│ │ │ │ └── Contents.json
│ │ │ ├── mineral-icon.imageset
│ │ │ │ ├── mineral-icon.png
│ │ │ │ ├── mineral-icon@2x.png
│ │ │ │ └── Contents.json
│ │ │ └── science-icon.imageset
│ │ │ │ ├── science-icon.png
│ │ │ │ ├── science-icon@2x.png
│ │ │ │ └── Contents.json
│ │ ├── stars
│ │ │ ├── Contents.json
│ │ │ └── StarParticle.imageset
│ │ │ │ ├── Star.png
│ │ │ │ └── Contents.json
│ │ ├── planets
│ │ │ ├── 3D
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Empty.imageset
│ │ │ │ │ ├── Empty.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── MoonTexture.imageset
│ │ │ │ │ ├── MoonTexture.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── ToxicTexture.imageset
│ │ │ │ │ ├── ToxicTexture.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── DesertTexture.imageset
│ │ │ │ │ ├── DesertTexture.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── FrozenTexture.imageset
│ │ │ │ │ ├── FrozenTexture.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── OceanicTexture.imageset
│ │ │ │ │ ├── OceanicTexture.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── VolcanicTexture.imageset
│ │ │ │ │ ├── VolcanicTexture.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ └── ContinentalTexture.imageset
│ │ │ │ │ ├── ContinentalTexture.jpg
│ │ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── Star.imageset
│ │ │ │ ├── SunRed.png
│ │ │ │ └── Contents.json
│ │ │ ├── Desert.imageset
│ │ │ │ ├── planet5.png
│ │ │ │ └── Contents.json
│ │ │ ├── Frozen.imageset
│ │ │ │ ├── planet4.png
│ │ │ │ └── Contents.json
│ │ │ ├── Toxic.imageset
│ │ │ │ ├── planet20.png
│ │ │ │ └── Contents.json
│ │ │ ├── blue.imageset
│ │ │ │ ├── SunBlue.png
│ │ │ │ └── Contents.json
│ │ │ ├── Oceanic.imageset
│ │ │ │ ├── planet2.png
│ │ │ │ └── Contents.json
│ │ │ ├── planet1.imageset
│ │ │ │ ├── planet1.png
│ │ │ │ └── Contents.json
│ │ │ ├── planet6.imageset
│ │ │ │ ├── planet6.png
│ │ │ │ └── Contents.json
│ │ │ ├── planet7.imageset
│ │ │ │ ├── planet7.png
│ │ │ │ └── Contents.json
│ │ │ ├── Continental.imageset
│ │ │ │ ├── planet3.png
│ │ │ │ └── Contents.json
│ │ │ ├── Volcanic.imageset
│ │ │ │ ├── planet14.png
│ │ │ │ └── Contents.json
│ │ │ ├── planet10.imageset
│ │ │ │ ├── planet10.png
│ │ │ │ └── Contents.json
│ │ │ ├── planet11.imageset
│ │ │ │ ├── planet11.png
│ │ │ │ └── Contents.json
│ │ │ ├── planet13.imageset
│ │ │ │ ├── planet13.png
│ │ │ │ └── Contents.json
│ │ │ ├── planet15.imageset
│ │ │ │ ├── planet15.png
│ │ │ │ └── Contents.json
│ │ │ ├── planet16.imageset
│ │ │ │ ├── planet16.png
│ │ │ │ └── Contents.json
│ │ │ ├── planet19.imageset
│ │ │ │ ├── planet19.png
│ │ │ │ └── Contents.json
│ │ │ └── planet18_0.imageset
│ │ │ │ ├── planet18_0.png
│ │ │ │ └── Contents.json
│ │ ├── skybox
│ │ │ ├── Contents.json
│ │ │ ├── Skybox_NegativeX.imageset
│ │ │ │ ├── Skybox_NegativeX.jpg
│ │ │ │ └── Contents.json
│ │ │ ├── Skybox_NegativeY.imageset
│ │ │ │ ├── Skybox_NegativeY.jpg
│ │ │ │ └── Contents.json
│ │ │ ├── Skybox_NegativeZ.imageset
│ │ │ │ ├── Skybox_NegativeZ.jpg
│ │ │ │ └── Contents.json
│ │ │ ├── Skybox_PositiveX.imageset
│ │ │ │ ├── Skybox_PositiveX.jpg
│ │ │ │ └── Contents.json
│ │ │ ├── Skybox_PositiveY.imageset
│ │ │ │ ├── Skybox_PositiveY.jpg
│ │ │ │ └── Contents.json
│ │ │ └── Skybox_PositiveZ.imageset
│ │ │ │ ├── Skybox_PositiveZ.jpg
│ │ │ │ └── Contents.json
│ │ ├── Spaceship.imageset
│ │ │ ├── Spaceship.png
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── scenes
│ │ ├── UniverseScene.sks
│ │ └── UniverseScene.swift
│ ├── flux
│ │ ├── middleware
│ │ │ ├── FilterMiddleware.swift
│ │ │ └── LogMiddleware.swift
│ │ ├── state
│ │ │ ├── UniverseState.swift
│ │ │ ├── AppState.swift
│ │ │ ├── UIState.swift
│ │ │ └── PlayerState.swift
│ │ ├── actions
│ │ │ ├── UniverseActions.swift
│ │ │ ├── UIActions.swift
│ │ │ └── PlayerActions.swift
│ │ └── reducers
│ │ │ ├── AppReducer.swift
│ │ │ ├── UniverseReducer.swift
│ │ │ ├── UIReducer.swift
│ │ │ └── PlayerReducer.swift
│ ├── models
│ │ ├── player
│ │ │ ├── AIPlayer.swift
│ │ │ ├── components
│ │ │ │ ├── PlayerSpriteComponent.swift
│ │ │ │ └── PlayerMovementComponent.swift
│ │ │ ├── PlayerResources.swift
│ │ │ └── Player.swift
│ │ ├── space
│ │ │ ├── protocols
│ │ │ │ ├── Discoverable.swift
│ │ │ │ └── Traversable.swift
│ │ │ ├── universe
│ │ │ │ ├── EmptyEntity.swift
│ │ │ │ ├── SystemEntity.swift
│ │ │ │ ├── components
│ │ │ │ │ └── UniverseSpriteComponent.swift
│ │ │ │ └── UniverseEntity.swift
│ │ │ ├── bodies
│ │ │ │ ├── SystemBody.swift
│ │ │ │ ├── StarEntity.swift
│ │ │ │ └── PlanetEntity.swift
│ │ │ └── Dimension.swift
│ │ └── pop
│ │ │ ├── Pop.swift
│ │ │ ├── Nation.swift
│ │ │ └── Race.swift
│ ├── AI
│ │ └── AIController.swift
│ ├── resources
│ │ ├── text
│ │ │ ├── starsText.plist
│ │ │ ├── testsText.plist
│ │ │ ├── planetsText.plist
│ │ │ └── raceText.plist
│ │ ├── modifiers
│ │ │ ├── raceForceModifier.plist
│ │ │ └── planetResourcesModifier.plist
│ │ ├── rules
│ │ │ └── universeRules.plist
│ │ └── dimensions
│ │ │ └── universeDimensions.plist
│ ├── helpers
│ │ ├── Date.swift
│ │ └── ResourcesLoader.swift
│ ├── AppDelegate.swift
│ ├── ui
│ │ ├── BaseUI.swift
│ │ ├── selection menu
│ │ │ ├── cells
│ │ │ │ ├── SelectionMenuTableViewCell.swift
│ │ │ │ └── SelectionMenuTableViewCell.xib
│ │ │ ├── SelectionMenu.swift
│ │ │ └── SelectionMenu.xib
│ │ ├── outliner
│ │ │ ├── cells
│ │ │ │ ├── OutlinerSystemTableViewCell.swift
│ │ │ │ └── OutlinerSystemTableViewCell.xib
│ │ │ ├── Outliner.swift
│ │ │ └── Outliner.xib
│ │ ├── BottomBar.swift
│ │ ├── Modal.swift
│ │ ├── TopBar.swift
│ │ ├── SystemUI.swift
│ │ ├── StarCell.xib
│ │ ├── BottomBar.xib
│ │ ├── SystemUI.xib
│ │ └── TopBar.xib
│ ├── Info.plist
│ ├── viewControllers
│ │ ├── GameViewController.swift
│ │ └── PlanetViewController.swift
│ └── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
├── Little Orion.xcodeproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
├── Podfile
├── Little Orion.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
├── Podfile.lock
├── UI
│ ├── UI.h
│ ├── UIButton
│ │ └── BarButton.swift
│ └── Info.plist
└── OrionTests
│ ├── Info.plist
│ ├── ResourcesTest.swift
│ └── RacesTests.swift
├── README.md
└── .gitignore
/Little Orion/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/icons/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/stars/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/scenes/UniverseScene.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/scenes/UniverseScene.sks
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/Spaceship.imageset/Spaceship.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/Spaceship.imageset/Spaceship.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Star.imageset/SunRed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/Star.imageset/SunRed.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/Empty.imageset/Empty.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/3D/Empty.imageset/Empty.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Desert.imageset/planet5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/Desert.imageset/planet5.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Frozen.imageset/planet4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/Frozen.imageset/planet4.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Toxic.imageset/planet20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/Toxic.imageset/planet20.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/blue.imageset/SunBlue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/blue.imageset/SunBlue.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Oceanic.imageset/planet2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/Oceanic.imageset/planet2.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet1.imageset/planet1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/planet1.imageset/planet1.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet6.imageset/planet6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/planet6.imageset/planet6.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet7.imageset/planet7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/planet7.imageset/planet7.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/stars/StarParticle.imageset/Star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/stars/StarParticle.imageset/Star.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Continental.imageset/planet3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/Continental.imageset/planet3.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Volcanic.imageset/planet14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/Volcanic.imageset/planet14.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet10.imageset/planet10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/planet10.imageset/planet10.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet11.imageset/planet11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/planet11.imageset/planet11.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet13.imageset/planet13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/planet13.imageset/planet13.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet15.imageset/planet15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/planet15.imageset/planet15.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet16.imageset/planet16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/planet16.imageset/planet16.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet19.imageset/planet19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/planet19.imageset/planet19.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/icons/energy-icon.imageset/energy-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/icons/energy-icon.imageset/energy-icon.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet18_0.imageset/planet18_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/planet18_0.imageset/planet18_0.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/icons/energy-icon.imageset/energy-icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/icons/energy-icon.imageset/energy-icon@2x.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/icons/mineral-icon.imageset/mineral-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/icons/mineral-icon.imageset/mineral-icon.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/icons/science-icon.imageset/science-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/icons/science-icon.imageset/science-icon.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/icons/mineral-icon.imageset/mineral-icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/icons/mineral-icon.imageset/mineral-icon@2x.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/icons/science-icon.imageset/science-icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/icons/science-icon.imageset/science-icon@2x.png
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/MoonTexture.imageset/MoonTexture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/3D/MoonTexture.imageset/MoonTexture.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/ToxicTexture.imageset/ToxicTexture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/3D/ToxicTexture.imageset/ToxicTexture.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/DesertTexture.imageset/DesertTexture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/3D/DesertTexture.imageset/DesertTexture.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/FrozenTexture.imageset/FrozenTexture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/3D/FrozenTexture.imageset/FrozenTexture.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/OceanicTexture.imageset/OceanicTexture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/3D/OceanicTexture.imageset/OceanicTexture.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/VolcanicTexture.imageset/VolcanicTexture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/3D/VolcanicTexture.imageset/VolcanicTexture.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_NegativeX.imageset/Skybox_NegativeX.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_NegativeX.imageset/Skybox_NegativeX.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_NegativeY.imageset/Skybox_NegativeY.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_NegativeY.imageset/Skybox_NegativeY.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_NegativeZ.imageset/Skybox_NegativeZ.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_NegativeZ.imageset/Skybox_NegativeZ.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_PositiveX.imageset/Skybox_PositiveX.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_PositiveX.imageset/Skybox_PositiveX.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_PositiveY.imageset/Skybox_PositiveY.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_PositiveY.imageset/Skybox_PositiveY.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_PositiveZ.imageset/Skybox_PositiveZ.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_PositiveZ.imageset/Skybox_PositiveZ.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/ContinentalTexture.imageset/ContinentalTexture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dimillian/LittleOrion/master/Little Orion/Little Orion/Assets.xcassets/planets/3D/ContinentalTexture.imageset/ContinentalTexture.jpg
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/middleware/FilterMiddleware.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FilterMiddleware.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 22/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/player/AIPlayer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AIPlayer.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 22/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class AIPlayer: Player {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/AI/AIController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AIController.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 19/04/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
12 | class AIController {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/Little Orion/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 | platform :ios, '12.0'
3 | use_frameworks!
4 | inhibit_all_warnings!
5 |
6 | def shared_pods
7 | pod 'ReSwift'
8 | end
9 |
10 | target 'LittleOrion' do
11 | shared_pods
12 | end
13 |
14 | target 'OrionTests' do
15 | shared_pods
16 | end
17 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Latest
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/resources/text/starsText.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Nova
6 | Supernova
7 | Dwarf
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Little Orion/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - ReSwift (4.1.1)
3 |
4 | DEPENDENCIES:
5 | - ReSwift
6 |
7 | SPEC REPOS:
8 | https://github.com/cocoapods/specs.git:
9 | - ReSwift
10 |
11 | SPEC CHECKSUMS:
12 | ReSwift: d925be0033558f55bd73d92869961230dfe19d52
13 |
14 | PODFILE CHECKSUM: 1b1f0c46086663ef1eb499cc7a6d5441844fc44c
15 |
16 | COCOAPODS: 1.6.1
17 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/resources/text/testsText.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | test1
6 | test 1 result
7 | test2
8 | test 2 result
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/state/UniverseState.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UniverseState.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
12 | struct UniverseState: Equatable {
13 | var universe: Universe?
14 | }
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/resources/modifiers/raceForceModifier.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | weak
6 | 0.8
7 | average
8 | 1
9 | strong
10 | 1.2
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/actions/UniverseActions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UniverseActions.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
12 | class UniverseActions {
13 | struct CreateUnivserse: Action {
14 | let size: Universe.UniverseSize
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/state/AppState.swift:
--------------------------------------------------------------------------------
1 | //
2 | // State.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
12 | struct AppState: StateType, Equatable {
13 |
14 | var universeState: UniverseState
15 | var playerState: PlayerState
16 | var uiState: UIState
17 | }
18 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/resources/text/planetsText.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Desert
6 | Oceanic
7 | Toxic
8 | Continental
9 | Frozen
10 | Volcanic
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/resources/text/raceText.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | human
6 | Human are standard
7 | lizard
8 | Lizard are cool
9 | plantoid
10 | Plantoid are not worth it
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/Spaceship.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "Spaceship.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Star.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "SunRed.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "SunBlue.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/Empty.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Empty.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Desert.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet5.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Frozen.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet4.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Oceanic.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet2.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Toxic.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet20.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Volcanic.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet14.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet1.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet10.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet10.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet11.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet11.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet13.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet13.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet15.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet15.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet16.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet16.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet19.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet19.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet6.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet6.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet7.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet7.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/stars/StarParticle.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Star.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/Continental.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet3.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/planet18_0.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "planet18_0.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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/MoonTexture.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "MoonTexture.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/ToxicTexture.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "ToxicTexture.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/DesertTexture.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "DesertTexture.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/FrozenTexture.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "FrozenTexture.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/OceanicTexture.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "OceanicTexture.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_NegativeX.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Skybox_NegativeX.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_NegativeY.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Skybox_NegativeY.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_NegativeZ.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Skybox_NegativeZ.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_PositiveX.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Skybox_PositiveX.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_PositiveY.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Skybox_PositiveY.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/skybox/Skybox_PositiveZ.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Skybox_PositiveZ.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/VolcanicTexture.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "VolcanicTexture.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/planets/3D/ContinentalTexture.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "ContinentalTexture.jpg",
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 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/space/protocols/Discoverable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Discoverable.swift
3 | // LittleOrion
4 | //
5 | // Created by Thomas Ricouard on 24/03/2018.
6 | // Copyright © 2018 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | // Entities which are discoverable by the player need to implement that protocol.
12 | protocol Discoverable: class {
13 |
14 | var discovered: Bool { get }
15 | var dayToDiscover: Int { get }
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/icons/energy-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "energy-icon.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "energy-icon@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/icons/mineral-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "mineral-icon.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "mineral-icon@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Assets.xcassets/icons/science-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "science-icon.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "science-icon@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/middleware/LogMiddleware.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LogMiddleware.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
12 | let logMiddleware: Middleware = { dispatch, getState in
13 | return { next in
14 | return { action in
15 | print(type(of: action))
16 | return next(action)
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/space/protocols/Traversable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Traversable.swift
3 | // LittleOrion
4 | //
5 | // Created by Thomas Ricouard on 09/10/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | // Entities which are travelable by the player need to implement that protocol.
12 | protocol Travelable: class {
13 |
14 | // The numver of day that it takes to travel trough the entity which implement that function.
15 | var travelTimeDay: Int { get }
16 | }
17 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/space/universe/EmptyEntity.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Empty.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 25/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import GameplayKit
10 |
11 | class EmptyEntity: UniverseEntity {
12 |
13 | override var travelTimeDay: Int {
14 | return 5
15 | }
16 |
17 | override var description: String {
18 | get {
19 | return "Empty part of the universe"
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Little Orion/UI/UI.h:
--------------------------------------------------------------------------------
1 | //
2 | // UI.h
3 | // UI
4 | //
5 | // Created by Thomas Ricouard on 08/10/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for UI.
12 | FOUNDATION_EXPORT double UIVersionNumber;
13 |
14 | //! Project version string for UI.
15 | FOUNDATION_EXPORT const unsigned char UIVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/pop/Pop.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Pop.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 24/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import GameplayKit
10 |
11 | class Pop: GKEntity {
12 |
13 | let race: Race
14 |
15 | public init(race: Race) {
16 | self.race = race
17 | super.init()
18 |
19 | }
20 |
21 | required init?(coder aDecoder: NSCoder) {
22 | fatalError("init(coder:) has not been implemented")
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/resources/rules/universeRules.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | systemSpwawnProbability
6 | 10
7 | superPlanetSpwawnProbability
8 | 10
9 | superPlanetScale
10 | 1.3
11 | basePlanetsRadius
12 | 9500
13 | planetMaxSpace
14 | 50
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/space/bodies/SystemBody.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SystemBody.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 25/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import GameplayKit
10 |
11 | class SystemBody: GKEntity {
12 |
13 | let name: String
14 |
15 | public init(name: String) {
16 | self.name = name
17 | super.init()
18 | }
19 |
20 | required init?(coder aDecoder: NSCoder) {
21 | fatalError("init(coder:) has not been implemented")
22 | }
23 |
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Little Orion
2 |
3 | Little Orion is a 4X space strategy game tailored for iOS.
4 | It's vastly insprired from Stellaris and Master of Orion.
5 |
6 | My goal while writing this game is mainly to learn SpriteKit, GameplayKit and SceneKit frameworks from Apple.
7 |
8 | It's wrote in Swift 4, use all of the latest iOS technologies. It's also using the Redux pattern as a backend. So most of the state machine from GameplayKit is not used here. It havr its own state machine and events bus instead.
9 |
10 | So for the time being, Little Orion will be iOS only. Once it'll be good enough, I might port it to Unity.
11 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/reducers/AppReducer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppReducer.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
12 | func AppReducer(action: Action, state: AppState?) -> AppState {
13 | return AppState(
14 | universeState: universeReducer(state: state?.universeState, action: action),
15 | playerState: playerReducer(state: state?.playerState, action: action),
16 | uiState: uiReducer(state: state?.uiState, action: action)
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/reducers/UniverseReducer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UniverseReducer.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
12 | func universeReducer(state: UniverseState?, action: Action) -> UniverseState {
13 | var state = state ?? UniverseState()
14 | switch action {
15 | case let action as UniverseActions.CreateUnivserse:
16 | state.universe = Universe(size: action.size)
17 | default:
18 | break
19 | }
20 | return state
21 | }
22 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/helpers/Date.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Date.swift
3 | // LittleOrion
4 | //
5 | // Created by Thomas Ricouard on 09/10/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Date {
12 |
13 | func numberOfDaysSince(date: Date) -> Int {
14 | let calendar = Calendar.current
15 |
16 | let fromDate = calendar.startOfDay(for: date)
17 | let toDate = calendar.startOfDay(for: self)
18 |
19 | let components = calendar.dateComponents([.day], from: fromDate, to: toDate)
20 | return components.day ?? 0
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Little Orion/UI/UIButton/BarButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BarButton.swift
3 | // UI
4 | //
5 | // Created by Thomas Ricouard on 08/10/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @IBDesignable
12 | open class BarButton: UIButton {
13 |
14 | override open func awakeFromNib() {
15 | setup()
16 | }
17 |
18 | override open func prepareForInterfaceBuilder() {
19 | setup()
20 | }
21 |
22 | func setup() {
23 | layer.borderColor = UIColor.white.cgColor
24 | layer.borderWidth = 0.5
25 | layer.cornerRadius = 4
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/state/UIState.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIState.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 | import GameplayKit
12 |
13 | struct UIState: Equatable {
14 |
15 | var selectedEntity: UniverseEntity?
16 | var selectedSystem: SystemEntity?
17 | var selectedPlanet: PlanetEntity?
18 | var currentModal: Modal
19 | var currentScene: Scene
20 |
21 | var selectedNode: SKNode?
22 | }
23 |
24 | enum Modal {
25 | case none
26 | case entity
27 | case system
28 |
29 | }
30 |
31 | enum Scene {
32 | case universe
33 | case planet
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import ReSwift
11 |
12 | let store = Store(reducer: AppReducer,
13 | state: nil,
14 | middleware: [logMiddleware])
15 |
16 | @UIApplicationMain
17 | class AppDelegate: UIResponder, UIApplicationDelegate {
18 |
19 | var window: UIWindow?
20 |
21 |
22 | internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
23 | return true
24 | }
25 |
26 |
27 |
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/Little Orion/OrionTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/BaseUI.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseUI.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 25/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIView {
12 | public static func loadFromNib() -> T {
13 | let nib = UINib(nibName: String(describing: self), bundle: Bundle.main)
14 | return nib.instantiate(withOwner: self, options: nil)[0] as! T
15 | }
16 | }
17 |
18 | class BaseUI: UIView {
19 |
20 | override func didMoveToSuperview() {
21 | super.didMoveToSuperview()
22 |
23 | layer.borderWidth = 0.5
24 | layer.borderColor = UIColor.white.cgColor
25 | layer.cornerRadius = 5
26 | clipsToBounds = true
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/selection menu/cells/SelectionMenuTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SelectionMenuTableViewCell.swift
3 | // LittleOrion
4 | //
5 | // Created by Thomas Ricouard on 01/04/2018.
6 | // Copyright © 2018 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SelectionMenuTableViewCell: UITableViewCell {
12 |
13 | static let id = "SelectionMenuTableViewCell"
14 |
15 | @IBOutlet var menuLabel: UILabel!
16 |
17 | override func awakeFromNib() {
18 | super.awakeFromNib()
19 | // Initialization code
20 | }
21 |
22 | override func setSelected(_ selected: Bool, animated: Bool) {
23 | super.setSelected(selected, animated: animated)
24 |
25 | // Configure the view for the selected state
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/outliner/cells/OutlinerSystemTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OutlinerSystemTableViewCell.swift
3 | // LittleOrion
4 | //
5 | // Created by Thomas Ricouard on 26/03/2018.
6 | // Copyright © 2018 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class OutlinerSystemTableViewCell: UITableViewCell {
12 |
13 | static let id = "OutlinerSystemTableViewCell"
14 |
15 | @IBOutlet var systemName: UILabel!
16 | @IBOutlet var systemDiscoveryProgress: UIProgressView!
17 |
18 | override func awakeFromNib() {
19 | super.awakeFromNib()
20 | }
21 |
22 | override func setSelected(_ selected: Bool, animated: Bool) {
23 | super.setSelected(selected, animated: animated)
24 |
25 | // Configure the view for the selected state
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/actions/UIActions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIActions.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 | import SpriteKit
12 |
13 | class UIActions {
14 | struct ShowSelectedSystemModal: Action {
15 | let system: SystemEntity
16 | }
17 |
18 | struct ShowSelectionModal: Action {
19 | let entity: UniverseEntity
20 | }
21 |
22 | struct ShowPlanetDetail: Action {
23 | let planet: PlanetEntity
24 | }
25 |
26 | struct ShowUniverseScene: Action {
27 |
28 | }
29 |
30 | struct DismissModal: Action {
31 |
32 | }
33 |
34 | struct SetSelectedNode: Action {
35 | let node: SKNode
36 | }
37 |
38 | struct RemoveSelectedNode: Action { }
39 | }
40 |
--------------------------------------------------------------------------------
/Little Orion/UI/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 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/pop/Nation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Nation.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 24/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import GameplayKit
10 |
11 | class Nation: GKEntity {
12 |
13 | private var pops: [Pop]
14 |
15 | //A nation must be created with at least one pop in it.
16 | init(pops: [Pop]) {
17 | self.pops = pops
18 |
19 | super.init()
20 | }
21 |
22 | required init?(coder aDecoder: NSCoder) {
23 | fatalError("init(coder:) has not been implemented")
24 | }
25 |
26 | public func addPop(pop: Pop) {
27 | pops.append(pop)
28 | }
29 |
30 | public func removePop(pop: Pop) {
31 | if let index = pops.index(of: pop) {
32 | pops.remove(at: index)
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/space/Dimension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Dimension.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 25/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Size: Equatable {
12 | var width: Int32 = 0
13 | var height: Int32 = 0;
14 |
15 | public init(width: Int32, height: Int32) {
16 | self.width = width
17 | self.height = height
18 | }
19 | }
20 |
21 | func ==(lhs: T, rhs: T) -> Bool {
22 | return lhs.width == rhs.width &&
23 | rhs.height == lhs.height
24 | }
25 |
26 | class Location: Equatable {
27 | var x: Int32 = 0
28 | var y: Int32 = 0
29 |
30 | public init(x: Int32, y: Int32) {
31 | self.x = x
32 | self.y = y
33 | }
34 | }
35 |
36 | func ==(lhs: T, rhs: T) -> Bool {
37 | return lhs.x == rhs.x &&
38 | rhs.y == lhs.y
39 | }
40 |
--------------------------------------------------------------------------------
/Little Orion/OrionTests/ResourcesTest.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ResourcesTest.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 24/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import LittleOrion
11 |
12 |
13 | class ResourcesTest: XCTestCase {
14 |
15 | let test1result = "test 1 result"
16 | let test2result = "test 2 result"
17 |
18 | override func setUp() {
19 | super.setUp()
20 | }
21 |
22 | override func tearDown() {
23 | super.tearDown()
24 | }
25 |
26 | func testResourceLoader() {
27 | let plist = ResourcesLoader.loadTextResource(name: "testsText")
28 | if let plist = plist {
29 | XCTAssertEqual(plist["test1"], test1result)
30 | XCTAssertEqual(plist["test2"], test2result)
31 | } else {
32 | XCTFail("plist is nil")
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/player/components/PlayerSpriteComponent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PlayerSpriteComponent.swift
3 | // LittleOrion
4 | //
5 | // Created by Thomas Ricouard on 08/10/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import GameplayKit
11 | import SpriteKit
12 |
13 | class PlayerSpriteComponent: GKSKNodeComponent {
14 |
15 | override init() {
16 | let texture = SKTexture(image: #imageLiteral(resourceName: "Spaceship"))
17 | let node = SKShapeNode(rect: CGRect(x: 0, y: 0, width: UniverseSpriteComponent.nodeSize.width,
18 | height: UniverseSpriteComponent.nodeSize.height))
19 | node.name = "Player node"
20 | node.fillTexture = texture
21 | node.fillColor = .white
22 | node.zPosition = 5
23 | super.init(node: node)
24 | }
25 |
26 | required init?(coder aDecoder: NSCoder) {
27 | fatalError("init(coder:) has not been implemented")
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/resources/dimensions/universeDimensions.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | node
6 |
7 | width
8 | 70
9 | height
10 | 70
11 |
12 | standard
13 |
14 | width
15 | 50
16 | height
17 | 50
18 |
19 | tiny
20 |
21 | width
22 | 10
23 | height
24 | 10
25 |
26 | small
27 |
28 | width
29 | 20
30 | height
31 | 20
32 |
33 | big
34 |
35 | width
36 | 100
37 | height
38 | 100
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/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" : "ios-marketing",
45 | "size" : "1024x1024",
46 | "scale" : "1x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/pop/Race.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Race.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import GameplayKit
10 |
11 | class Race: GKEntity {
12 |
13 | enum Kind: String {
14 | case human, lizard, plantoid
15 |
16 | func description() -> String {
17 | return ResourcesLoader.loadTextResource(name: "raceText")![rawValue]!
18 | }
19 | }
20 |
21 | enum Force: String {
22 | case weak, average, strong
23 |
24 | func modifier() -> Float {
25 | return ResourcesLoader.loadModifierResource(name: "raceForceModifier")![rawValue]!
26 | }
27 | }
28 |
29 | let name: String
30 | let kind: Kind
31 | let force: Force
32 |
33 | init(name: String, kind: Kind, force: Force) {
34 | self.kind = kind
35 | self.force = force
36 | self.name = name
37 | super.init()
38 | }
39 |
40 | required init?(coder aDecoder: NSCoder) {
41 | fatalError("init(coder:) has not been implemented")
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 0.1
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UIStatusBarHidden
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/state/PlayerState.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PlayerState.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
12 | enum PlayerSpeed: TimeInterval {
13 | case slow = 1.5
14 | case normal = 1.0
15 | case fast = 0.5
16 | case faster = 0.2
17 |
18 | func nextValue() -> PlayerSpeed {
19 | switch self {
20 | case .slow:
21 | return .normal
22 | case .normal:
23 | return .fast
24 | case .fast:
25 | return .faster
26 | case .faster:
27 | return .slow
28 | }
29 | }
30 |
31 | func displayValue() -> String {
32 | switch self {
33 | case .slow:
34 | return "0.5"
35 | case .normal:
36 | return "1.0"
37 | case .fast:
38 | return "1.5"
39 | case .faster:
40 | return "2.0"
41 | }
42 | }
43 | }
44 |
45 | struct PlayerState: Equatable {
46 | var player = Player(name: "Player 1")
47 | var currentDate = Date()
48 | var dateTimer: Timer?
49 | var currentSpeed = PlayerSpeed.normal
50 | var isPlaying = false
51 | }
52 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/BottomBar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BottomBar.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 22/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import ReSwift
12 | import UI
13 |
14 | protocol BottomBarDelegate: class {
15 | func onCenterPlayerButton()
16 | func onMovePlayerButton()
17 | }
18 |
19 | class BottomBar: BaseUI, StoreSubscriber {
20 |
21 | @IBOutlet var planetNumber: UILabel!
22 | @IBOutlet var moveButton: BarButton!
23 |
24 | weak var delegate: BottomBarDelegate?
25 |
26 | override func didMoveToSuperview() {
27 | super.didMoveToSuperview()
28 |
29 | layer.cornerRadius = 0
30 |
31 | store.subscribe(self) {
32 | $0.select{ $0.playerState }.skipRepeats()
33 | }
34 | }
35 |
36 | func newState(state: PlayerState) {
37 | planetNumber.text = "Planets: \(state.player.discoveredPlanets.count)"
38 | moveButton.setTitle(state.player.isInMovement ? "Stop" : "Move", for: .normal)
39 | }
40 |
41 | @IBAction func onMeButton(_ sender: Any) {
42 | delegate?.onCenterPlayerButton()
43 | }
44 |
45 | @IBAction func onMoveButton(_ sender: Any) {
46 | delegate?.onMovePlayerButton()
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Little Orion/OrionTests/RacesTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RacesTests.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 24/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import LittleOrion
11 |
12 | class RacesTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testsDescription() {
25 | let race = Race(name: "race1", kind: .human, force: .weak)
26 | let race2 = Race(name: "race2", kind: .plantoid, force: .weak)
27 | let race3 = Race(name: "race3", kind: .lizard, force: .weak)
28 |
29 | XCTAssertNotNil(race.kind.description())
30 | XCTAssertNotNil(race2.kind.description())
31 | XCTAssertNotNil(race3.kind.description())
32 |
33 | XCTAssertNotNil(race.force.modifier())
34 | XCTAssertNotNil(race2.force.modifier())
35 | XCTAssertNotNil(race3.force.modifier())
36 |
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/player/PlayerResources.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PlayerResource.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
12 | enum PlayerResourceType: String {
13 | case energy, minerals, science
14 | }
15 |
16 | class PlayerResource: Equatable {
17 |
18 | let type: PlayerResourceType
19 | var value = 0
20 | var income: Int {
21 | get {
22 | //TODO: Random for now, will be calculated from player inhabited planets
23 | return Int(arc4random_uniform(10))
24 | }
25 | }
26 |
27 | init(type: PlayerResourceType) {
28 | self.type = type
29 | }
30 |
31 |
32 | func update() {
33 | value += income
34 | }
35 | }
36 |
37 | func ==(lhs: PlayerResource, rhs: PlayerResource) -> Bool {
38 | return lhs.value == rhs.value &&
39 | rhs.income == lhs.income
40 | }
41 |
42 | class PlayerResources: Equatable {
43 | var energy = PlayerResource(type: .energy)
44 | var minerals = PlayerResource(type: .minerals)
45 | var science = PlayerResource(type: .science)
46 |
47 | func update() {
48 | self.energy.update()
49 | self.minerals.update()
50 | self.science.update()
51 | }
52 | }
53 |
54 | func ==(lhs: PlayerResources, rhs: PlayerResources) -> Bool {
55 | return lhs.energy == rhs.energy &&
56 | lhs.minerals == rhs.minerals &&
57 | lhs.science == rhs.science
58 | }
59 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/player/Player.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Player.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 22/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import GameplayKit
11 | import ReSwift
12 |
13 | class Player: GKEntity, GKGameModelPlayer, StateType {
14 | let name: String
15 |
16 | public var playerId: Int {
17 | get {
18 | return name.hashValue
19 | }
20 | }
21 |
22 | var resources = PlayerResources()
23 |
24 | var discoveringEntities: [UniverseId: Int] = [:]
25 | var discoveredEntities: Set = []
26 | var discoveringPlanets: [PlanetId: Int] = [:]
27 | var discoveredPlanets: Set = []
28 |
29 | var spriteNode: SKNode {
30 | get {
31 | return component(ofType: PlayerSpriteComponent.self)!.node
32 | }
33 | }
34 |
35 | var position = CGPoint.zero {
36 | didSet {
37 | let movement = SKAction.move(to: position, duration: 1.0)
38 | spriteNode.run(movement)
39 | spriteNode.position = position
40 | }
41 | }
42 |
43 | var isInMovement: Bool {
44 | return component(ofType: PlayerMovementComponent.self) != nil
45 | }
46 |
47 | init(name: String) {
48 | self.name = name
49 | super.init()
50 |
51 | addComponent(PlayerSpriteComponent())
52 | }
53 |
54 | required init?(coder aDecoder: NSCoder) {
55 | fatalError("init(coder:) has not been implemented")
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/viewControllers/GameViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameViewController.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SpriteKit
11 | import GameplayKit
12 |
13 | class MainViewController: UIViewController {
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 |
18 | if let scene = GKScene(fileNamed: "UniverseScene") {
19 | if let sceneNode = scene.rootNode as! UniverseScene? {
20 | sceneNode.scaleMode = .aspectFill
21 | if let view = view as! SKView? {
22 | view.presentScene(sceneNode)
23 |
24 | view.ignoresSiblingOrder = true
25 |
26 | view.showsFPS = true
27 | view.showsNodeCount = true
28 | }
29 | }
30 | }
31 | }
32 |
33 | override var shouldAutorotate: Bool {
34 | return true
35 | }
36 |
37 | override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
38 | if UIDevice.current.userInterfaceIdiom == .phone {
39 | return .allButUpsideDown
40 | } else {
41 | return .all
42 | }
43 | }
44 |
45 | override func didReceiveMemoryWarning() {
46 | super.didReceiveMemoryWarning()
47 | // Release any cached data, images, etc that aren't in use.
48 | }
49 |
50 | override var prefersStatusBarHidden: Bool {
51 | return true
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xcuserstate
23 |
24 | ## Obj-C/Swift specific
25 | *.hmap
26 | *.ipa
27 | *.dSYM.zip
28 | *.dSYM
29 |
30 | ## Playgrounds
31 | timeline.xctimeline
32 | playground.xcworkspace
33 |
34 | # Swift Package Manager
35 | #
36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37 | # Packages/
38 | .build/
39 |
40 | # CocoaPods
41 | #
42 | # We recommend against adding the Pods directory to your .gitignore. However
43 | # you should judge for yourself, the pros and cons are mentioned at:
44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45 | #
46 | Pods/
47 |
48 | # Carthage
49 | #
50 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
51 | # Carthage/Checkouts
52 |
53 | Carthage/Build
54 |
55 | # fastlane
56 | #
57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
58 | # screenshots whenever they are needed.
59 | # For more information about the recommended setup visit:
60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
61 |
62 | fastlane/report.xml
63 | fastlane/Preview.html
64 | fastlane/screenshots
65 | fastlane/test_output
66 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/resources/modifiers/planetResourcesModifier.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Desert
6 |
7 | Food
8 | 1
9 | Mineral
10 | 3
11 | Energy
12 | 1
13 | Research
14 | 1
15 |
16 | Toxic
17 |
18 | Food
19 | 0
20 | Mineral
21 | 3
22 | Energy
23 | 1
24 | Research
25 | 0
26 |
27 | Frozen
28 |
29 | Food
30 | 1
31 | Mineral
32 | 1
33 | Energy
34 | 1
35 | Research
36 | 1
37 |
38 | Volcanic
39 |
40 | Food
41 | 0
42 | Mineral
43 | 3
44 | Energy
45 | 2
46 | Research
47 | 1
48 |
49 | Oceanic
50 |
51 | Food
52 | 3
53 | Mineral
54 | 1
55 | Energy
56 | 1
57 | Research
58 | 2
59 |
60 | Continental
61 |
62 | Food
63 | 2
64 | Mineral
65 | 2
66 | Energy
67 | 2
68 | Research
69 | 3
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/space/universe/SystemEntity.swift:
--------------------------------------------------------------------------------
1 | //
2 | // System.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import GameplayKit
10 |
11 | class SystemEntity: UniverseEntity {
12 |
13 | private var _planets = [PlanetEntity]()
14 |
15 | var planets: [PlanetEntity] {
16 | get {
17 | return _planets
18 | }
19 | }
20 |
21 | override var travelTimeDay: Int {
22 | return 5
23 | }
24 |
25 | var star = StarEntity(name: "Star")
26 |
27 | override var description: String {
28 | get {
29 | return "System: \(id.name), Planets: \(planetsCount())"
30 | }
31 | }
32 |
33 | override var extraInfo: String? {
34 | get {
35 | var text = ""
36 | for planet in planets {
37 | text += "\(planet.name): \(planet.kind.name()), "
38 | }
39 | return text
40 | }
41 | }
42 |
43 | public override init(location: Location) {
44 | super.init(location: location)
45 |
46 | makePlanets()
47 | }
48 |
49 | required init?(coder aDecoder: NSCoder) {
50 | fatalError("init(coder:) has not been implemented")
51 | }
52 |
53 | private func makePlanets() {
54 | let planetsCount = Int(arc4random_uniform(6))
55 | for index in 0...planetsCount {
56 | let star = PlanetEntity(in: self, order: index)
57 | _planets.append(star)
58 | }
59 | }
60 |
61 | func planet(at: Int) -> PlanetEntity {
62 | return _planets[at]
63 | }
64 |
65 | func planetsCount() -> Int {
66 | return _planets.count
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/Modal.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Modal.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import SpriteKit
12 |
13 | class ModalUI {
14 |
15 | fileprivate static var systemUIShown = false
16 | fileprivate static var selectionUIShown = false
17 | fileprivate static var _systemUI: SystemUI?
18 | fileprivate static var _selectionUI: SelectionMenu?
19 |
20 | static var systemUI: SystemUI! {
21 | if _systemUI == nil {
22 | _systemUI = SystemUI.loadFromNib()
23 | _systemUI!.isHidden = true
24 | }
25 | return _systemUI!
26 | }
27 |
28 | static var selectionUI: SelectionMenu! {
29 | if _selectionUI == nil {
30 | _selectionUI = SelectionMenu.loadFromNib()
31 | _selectionUI!.isHidden = true
32 | }
33 | return _selectionUI!
34 | }
35 |
36 | static func presentSystemUI(from: SKScene, delegate: SystemUiDelegate) {
37 | if (!systemUIShown) {
38 | systemUIShown = true
39 | from.view?.addSubview(systemUI)
40 | systemUI.delegate = delegate
41 | systemUI.show()
42 | }
43 | }
44 |
45 | static func dismissSystemUI() {
46 | systemUI.hide()
47 | systemUIShown = false
48 | }
49 |
50 | static func presentSelectionUI(from: SKScene) {
51 | if(!selectionUIShown) {
52 | selectionUIShown = true
53 | from.view?.addSubview(selectionUI)
54 | selectionUI.isHidden = false
55 | }
56 | }
57 |
58 | static func dismissSelectionUI() {
59 | selectionUI.isHidden = true
60 | selectionUIShown = false
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/reducers/UIReducer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIState.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
12 | func uiReducer(state: UIState?, action: Action) -> UIState {
13 | var state = state ?? UIState(selectedEntity: nil,
14 | selectedSystem: nil,
15 | selectedPlanet: nil,
16 | currentModal: .none,
17 | currentScene: .universe,
18 | selectedNode: nil)
19 | switch action {
20 | case let action as UIActions.ShowSelectedSystemModal:
21 | state.selectedSystem = action.system
22 | state.currentModal = .system
23 |
24 | case let action as UIActions.ShowSelectionModal:
25 | state.selectedEntity = action.entity
26 | state.currentModal = .entity
27 |
28 | case let action as UIActions.ShowPlanetDetail:
29 | state.selectedPlanet = action.planet
30 | state.currentScene = .planet
31 | state.currentModal = .none
32 |
33 | case _ as UIActions.ShowUniverseScene:
34 | state.selectedPlanet = nil
35 | state.selectedSystem = nil
36 | state.currentScene = .universe
37 | state.currentModal = .none
38 |
39 | case _ as UIActions.DismissModal:
40 | state.currentModal = .none
41 | state.selectedSystem = nil
42 | state.selectedEntity = nil
43 |
44 | case let action as UIActions.SetSelectedNode:
45 | state.selectedNode = action.node
46 |
47 | case _ as UIActions.RemoveSelectedNode:
48 | state.selectedNode = nil
49 |
50 | default:
51 | break
52 | }
53 | return state
54 | }
55 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/space/bodies/StarEntity.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Star.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import GameplayKit
10 |
11 | class StarEntity: SystemBody {
12 |
13 | enum Kind: UInt32 {
14 | case nova, supernova, dwarf
15 |
16 | private static let _count: Kind.RawValue = {
17 | var maxValue: UInt32 = 0
18 | while let _ = Kind(rawValue: maxValue) {
19 | maxValue += 1
20 | }
21 | return maxValue
22 | }()
23 |
24 | static func randomKind() -> Kind {
25 | let rand = arc4random_uniform(_count)
26 | return Kind(rawValue: rand)!
27 | }
28 |
29 | func name() -> String {
30 | return ResourcesLoader.loadArrayTextResource(name: "starsText")![Int(rawValue)]
31 | }
32 |
33 | func imageName() -> String {
34 | return "Star"
35 | }
36 | func image() -> UIImage {
37 | return #imageLiteral(resourceName: "Star")
38 | }
39 |
40 | func textureFillColor() -> UIColor {
41 | switch self {
42 | case .nova:
43 | return UIColor(red: 5/255, green: 22/255, blue: 177/255, alpha: 1.0)
44 | case .dwarf:
45 | return UIColor(red: 248/255, green: 187/255, blue: 66/255, alpha: 1.0)
46 | case .supernova:
47 | return UIColor(red: 199/255, green: 20/255, blue: 21/255, alpha: 1.0)
48 | }
49 | }
50 | }
51 |
52 | let kind: Kind
53 |
54 | public override init(name: String) {
55 | kind = Kind.randomKind()
56 | super.init(name: name)
57 | }
58 |
59 | required init?(coder aDecoder: NSCoder) {
60 | fatalError("init(coder:) has not been implemented")
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/TopBar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TopBar.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import ReSwift
11 |
12 | class TopBar: BaseUI {
13 |
14 | @IBOutlet var dateLabel: UILabel!
15 | @IBOutlet var playButton: UIButton!
16 | @IBOutlet var speedButton: UIButton!
17 |
18 | @IBOutlet var energyIcon: UIImageView!
19 | @IBOutlet var energyLabel: UILabel!
20 |
21 | @IBOutlet var mineralIcon: UIImageView!
22 | @IBOutlet var mineralLabel: UILabel!
23 |
24 | @IBOutlet var scienceIcon: UIImageView!
25 | @IBOutlet var scienceLabel: UILabel!
26 |
27 | override func didMoveToSuperview() {
28 | super.didMoveToSuperview()
29 |
30 | layer.cornerRadius = 0
31 |
32 | store.subscribe(self) {
33 | $0.select{ $0.playerState }.skipRepeats()
34 | }
35 | }
36 |
37 | @IBAction func onPlayButton(_ sender: Any) {
38 | if store.state.playerState.isPlaying {
39 | store.dispatch(PlayerActions.PauseTimer())
40 | }
41 | else {
42 | store.dispatch(PlayerActions.StartTimer())
43 | }
44 | }
45 |
46 | @IBAction func onSpeedButton(_ sender: Any) {
47 | store.dispatch(PlayerActions.UpdateSpeed(speed: store.state.playerState.currentSpeed.nextValue()))
48 | }
49 | }
50 |
51 | extension TopBar: StoreSubscriber {
52 | func newState(state: PlayerState) {
53 | let dateFormatter = DateFormatter()
54 | dateFormatter.dateFormat = "dd/MM/yyyy"
55 | dateLabel.text = dateFormatter.string(from: state.currentDate)
56 | playButton.setTitle(state.isPlaying ? "||" : ">", for: .normal)
57 | speedButton.setTitle("x\(state.currentSpeed.displayValue())", for: .normal)
58 | energyLabel.text = "\(state.player.resources.energy.value)"
59 | mineralLabel.text = "\(state.player.resources.minerals.value)"
60 | scienceLabel.text = "\(state.player.resources.science.value)"
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/selection menu/SelectionMenu.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SelectionMenu.swift
3 | // LittleOrion
4 | //
5 | // Created by Thomas Ricouard on 01/04/2018.
6 | // Copyright © 2018 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import UI
11 |
12 | class SelectionMenu: BaseUI {
13 | enum MenuType: Int {
14 | case unknown
15 |
16 | func datasource() -> [String] {
17 | switch self {
18 | case .unknown:
19 | return ["Survey", "Cancel"]
20 | }
21 | }
22 | }
23 |
24 | @IBOutlet var tableView: UITableView!
25 |
26 | var menuType = MenuType.unknown
27 |
28 | override func awakeFromNib() {
29 | super.awakeFromNib()
30 |
31 | let nib = UINib(nibName: SelectionMenuTableViewCell.id, bundle: Bundle.main)
32 | tableView.register(nib, forCellReuseIdentifier: SelectionMenuTableViewCell.id)
33 | }
34 |
35 | override func didMoveToSuperview() {
36 | super.didMoveToSuperview()
37 |
38 | frame = CGRect(x: 0, y: 0, width: 300, height: 200)
39 | center = superview!.center
40 | }
41 | }
42 |
43 | extension SelectionMenu: UITableViewDelegate, UITableViewDataSource {
44 | func numberOfSections(in tableView: UITableView) -> Int {
45 | return 1
46 | }
47 |
48 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
49 | return menuType.datasource().count
50 | }
51 |
52 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
53 | let cell = tableView.dequeueReusableCell(withIdentifier: SelectionMenuTableViewCell.id,
54 | for: indexPath) as! SelectionMenuTableViewCell
55 | cell.menuLabel.text = menuType.datasource()[indexPath.row]
56 | return cell
57 | }
58 |
59 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
60 | tableView.deselectRow(at: indexPath, animated: true)
61 | if indexPath.row == 0, let entity = store.state.uiState.selectedEntity {
62 | store.dispatch(PlayerActions.startDiscoveryUniverseEntity(entity: entity.id))
63 | }
64 | store.dispatch(UIActions.DismissModal())
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/helpers/ResourcesLoader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ResourcesLoader.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 24/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | class ResourcesLoader {
13 |
14 | static func loadDicResource(name: String) -> [String: AnyObject]? {
15 | if let path = Bundle.main.path(forResource: name, ofType: "plist"),
16 | let dic = NSDictionary(contentsOfFile: path) as? [String : AnyObject] {
17 | return dic
18 | }
19 | return nil
20 | }
21 |
22 | static func loadTextResource(name: String) -> [String : String]? {
23 | if let path = Bundle.main.path(forResource: name, ofType: "plist"),
24 | let dic = NSDictionary(contentsOfFile: path) as? [String : String] {
25 | return dic
26 | }
27 | return nil
28 | }
29 |
30 | static func loadArrayTextResource(name: String) -> [String]? {
31 | if let path = Bundle.main.path(forResource: name, ofType: "plist"),
32 | let dic = NSArray(contentsOfFile: path) as? [String] {
33 | return dic
34 | }
35 | return nil
36 | }
37 |
38 | static func loadModifierResource(name: String) -> [String : Float]? {
39 | if let path = Bundle.main.path(forResource: name, ofType: "plist"),
40 | let dic = NSDictionary(contentsOfFile: path) as? [String : Float] {
41 | return dic
42 | }
43 | return nil
44 | }
45 |
46 | static func loadDimensionResource(name: String, dimensionName: String) -> Size? {
47 | if let path = Bundle.main.path(forResource: name, ofType: "plist"),
48 | let dic = NSDictionary(contentsOfFile: path) {
49 | if let sizeDic = dic[dimensionName] as? [String: Int],
50 | let width = sizeDic["width"],
51 | let height = sizeDic["height"] {
52 | return Size(width: Int32(width), height: Int32(height))
53 | }
54 | }
55 | return nil
56 | }
57 |
58 | static func loadPlanetResource(name: String) -> [String: [String: Int]]? {
59 | if let path = Bundle.main.path(forResource: name, ofType: "plist"),
60 | let dic = NSDictionary(contentsOfFile: path) as? [String: [String: Int]] {
61 | return dic
62 | }
63 | return nil
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/player/components/PlayerMovementComponent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PlayerMovementComponent.swift
3 | // LittleOrion
4 | //
5 | // Created by Thomas Ricouard on 09/10/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import GameplayKit
11 | import ReSwift
12 |
13 | class PlayerMovementComponent: GKComponent {
14 |
15 | let startDate: Date
16 | let startLocation: Location
17 | let endLocation: Location
18 |
19 | var travelPath: [GKGraphNode] = []
20 | var previousDate: Date
21 |
22 | init(startDate: Date, from: Location, to: Location) {
23 | self.startDate = startDate
24 | self.startLocation = from
25 | self.endLocation = to
26 | self.previousDate = startDate
27 | super.init()
28 | }
29 |
30 | required init?(coder aDecoder: NSCoder) {
31 | fatalError("init(coder:) has not been implemented")
32 | }
33 |
34 | override func didAddToEntity() {
35 | super.didAddToEntity()
36 |
37 | if let universe = store.state.universeState.universe {
38 | if let startNode = universe.nodeAt(location: startLocation),
39 | let endNode = universe.nodeAt(location: endLocation) {
40 | for node in startNode.findPath(to: endNode) {
41 | if let node = node as? UniverseNode {
42 | for _ in 0.. PlayerState {
13 | var state = state ?? PlayerState()
14 |
15 | switch action {
16 | case _ as PlayerActions.Initialize:
17 | let gridNodes = store.state.universeState.universe!.grid.nodes!
18 | let randomNodeIndex = arc4random_uniform(UInt32(gridNodes.count))
19 | if let node = gridNodes[Int(randomNodeIndex)] as? UniverseNode {
20 | state.player.discoveredEntities.insert(node.entity.id)
21 | state.player.position = Universe.grideNodePositionToMapPosition(gridNode: node)
22 | }
23 | case let action as PlayerActions.StartTimer:
24 | state.dateTimer = action.timer
25 | state.isPlaying = true
26 | case let action as PlayerActions.UpdateSpeed:
27 | state.currentSpeed = action.speed
28 | case let action as PlayerActions.UpdateTimer:
29 | state.dateTimer = action.timer
30 | state.currentDate = Calendar.current.date(byAdding: .day, value: 1, to: state.currentDate)!
31 | state.isPlaying = true
32 |
33 | //Player operation
34 | if let universe = store.state.universeState.universe {
35 | let mapcCopy = state.player.discoveringEntities
36 | mapcCopy.forEach { (params) in
37 | let (id, progress) = params
38 | let entity = universe.entityAt(location: id.location)
39 | if progress == entity.dayToDiscover {
40 | state.player.discoveringEntities.removeValue(forKey: id)
41 | state.player.discoveredEntities.insert(id)
42 | } else {
43 | state.player.discoveringEntities[id] = progress + 1
44 | }
45 | }
46 | }
47 |
48 | case _ as PlayerActions.UpdateTimerMonth:
49 | state.player.resources.update()
50 | case _ as PlayerActions.PauseTimer:
51 | state.dateTimer?.invalidate()
52 | state.dateTimer = nil
53 | state.isPlaying = false
54 | case let action as PlayerActions.MoveToPosition:
55 | state.player.addComponent(action.movement)
56 | case _ as PlayerActions.StopMovement:
57 | state.player.removeComponent(ofType: PlayerMovementComponent.self)
58 | case let action as PlayerActions.UpdatePosition:
59 | state.player.position = action.position
60 | case let action as PlayerActions.startDiscoveryUniverseEntity:
61 | state.player.discoveringEntities[action.entity] = 0
62 | default:
63 | break
64 | }
65 | return state
66 | }
67 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/space/universe/components/UniverseSpriteComponent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UniverseSpriteComponent.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 25/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import GameplayKit
10 |
11 | class UniverseSpriteComponent: GKSKNodeComponent {
12 |
13 | static let size = ResourcesLoader.loadDimensionResource(name: "universeDimensions", dimensionName: "node")!
14 | static let nodeSize = CGSize(width: Int(UniverseSpriteComponent.size.width), height: Int(UniverseSpriteComponent.size.height))
15 |
16 | static public func component(with entity: UniverseEntity) -> UniverseSpriteComponent {
17 | var component: UniverseSpriteComponent
18 | let node = SKShapeNode(rect: CGRect(x: 0, y: 0, width: nodeSize.width, height: nodeSize.height))
19 | node.lineWidth = 0.50
20 | node.strokeColor = UIColor.init(white: 1.0, alpha: 0.5)
21 | node.fillColor = node.undiscovedColor
22 | if let _ = entity as? SystemEntity {
23 | node.name = "System node"
24 | } else {
25 | node.name = "Empty node"
26 | }
27 | component = UniverseSpriteComponent(node: node)
28 | return component
29 |
30 | }
31 |
32 | override func update(deltaTime seconds: TimeInterval) {
33 | if let universeEntity = entity as? UniverseEntity, let node = node as? SKShapeNode {
34 | let discovered = universeEntity.discovered
35 | if let systemEntity = universeEntity as? SystemEntity, discovered {
36 | if node.fillTexture == nil {
37 | let texture = SKTexture(imageNamed: systemEntity.star.kind.imageName())
38 | node.fillTexture = texture
39 | }
40 | node.fillColor = systemEntity.star.kind.textureFillColor()
41 | node.strokeColor = .red
42 | node.glowWidth = 3
43 | } else {
44 | node.fillColor = discovered ? .clear : node.undiscovedColor
45 | node.glowWidth = discovered ? 2 : 0
46 | node.strokeColor = UIColor.init(white: 1.0, alpha: 0.5)
47 | }
48 |
49 | if let dayProgress = store.state.playerState.player.discoveringEntities[universeEntity.id] {
50 | let progress = Float(dayProgress) / Float(universeEntity.dayToDiscover)
51 | node.strokeColor = UIColor.green.withAlphaComponent(CGFloat(progress))
52 | }
53 |
54 | if node == store.state.uiState.selectedNode {
55 | node.glowWidth = 5
56 | }
57 |
58 | if let movement = store.state.playerState.player.component(ofType: PlayerMovementComponent.self) {
59 | // TODO: Highlight node for player movement
60 | }
61 | }
62 | }
63 |
64 | }
65 |
66 | extension SKShapeNode {
67 |
68 | var undiscovedColor: UIColor {
69 | return UIColor.gray.withAlphaComponent(0.3)
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/flux/actions/PlayerActions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PlayerActions.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/01/2017.
6 | // Copyright © 2017 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ReSwift
11 |
12 | class PlayerActions {
13 | struct Initialize: Action {}
14 |
15 | struct StartTimer: Action {
16 | var timer: Timer!
17 | var currentDate: Date!
18 |
19 | init() {
20 | self.currentDate = store.state.playerState.currentDate
21 | let speed = store.state.playerState.currentSpeed
22 | var copy = self
23 | self.timer = Timer.scheduledTimer(withTimeInterval: speed.rawValue, repeats: true, block: { (timer) in
24 | if store.state.playerState.isPlaying {
25 | store.dispatch(UpdateTimer(timer: timer))
26 | copy.currentDate = store.state.playerState.currentDate
27 | if Calendar.current.isDate(copy.currentDate, equalTo: copy.endOfMonth(), toGranularity: .day) {
28 | store.dispatch(UpdateTimerMonth(timer: timer))
29 | }
30 | }
31 | })
32 | }
33 |
34 | func startOfMonth() -> Date {
35 | return Calendar.current.date(from: Calendar.current.dateComponents([.year, .month],
36 | from: Calendar.current.startOfDay(for:
37 | currentDate)))!
38 | }
39 |
40 | func endOfMonth() -> Date {
41 | return Calendar.current.date(byAdding: DateComponents(month: 1, day: -1), to: self.startOfMonth())!
42 | }
43 | }
44 |
45 | struct UpdateSpeed: Action {
46 | let speed: PlayerSpeed
47 |
48 | init(speed: PlayerSpeed) {
49 | self.speed = speed
50 |
51 | // Hacky workaround to wait for the init to be done so the state is up to date when restarting the timer.
52 | // Will do better later.
53 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
54 | store.dispatch(PauseTimer())
55 | store.dispatch(StartTimer())
56 | }
57 | }
58 | }
59 |
60 | struct UpdateTimer: Action {
61 | let timer: Timer
62 |
63 | init(timer: Timer) {
64 | self.timer = timer
65 | }
66 | }
67 |
68 | struct UpdateTimerMonth: Action {
69 | let timer: Timer
70 |
71 | init(timer: Timer) {
72 | self.timer = timer
73 | }
74 | }
75 |
76 | struct MoveToPosition: Action {
77 | let movement: PlayerMovementComponent
78 | }
79 |
80 | struct UpdatePosition: Action {
81 | let position: CGPoint
82 | }
83 |
84 | struct startDiscoveryUniverseEntity: Action {
85 | let entity: UniverseId
86 | }
87 |
88 | struct StopMovement: Action {}
89 |
90 | struct PauseTimer: Action {
91 |
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/viewControllers/PlanetViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PlanetViewController.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 29/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SceneKit
11 | import ReSwift
12 |
13 | class PlanetViewController: UIViewController {
14 |
15 | let planet: PlanetEntity
16 |
17 | var mainScene: SCNScene! = nil
18 | var mainSceneView: SCNView! = nil
19 |
20 | init(){
21 | planet = store.state.uiState.selectedPlanet!
22 | super.init(nibName: nil, bundle: nil)
23 |
24 | }
25 |
26 | required init?(coder aDecoder: NSCoder) {
27 | fatalError("init(coder:) has not been implemented")
28 | }
29 |
30 | override func viewDidLoad() {
31 | super.viewDidLoad()
32 |
33 | store.subscribe(self) {
34 | $0.select{ $0.uiState }.skipRepeats()
35 | }
36 |
37 | setupScene()
38 | setupCloseButton()
39 | }
40 | }
41 |
42 | // MARK: - State
43 | extension PlanetViewController: StoreSubscriber {
44 | func newState(state: UIState) {
45 | if state.currentScene != .planet {
46 | self.dismiss(animated: true, completion: nil)
47 | }
48 | }
49 | }
50 |
51 | // MARK: - Action
52 | extension PlanetViewController {
53 |
54 | @objc func onClose() {
55 | store.dispatch(UIActions.ShowUniverseScene())
56 | }
57 | }
58 |
59 | // MARK: - Setup
60 | extension PlanetViewController {
61 |
62 | func setupCloseButton() {
63 | let button = UIButton(type: .custom)
64 | button.setTitle("Close", for: .normal)
65 | button.setTitleColor(UIColor.white, for: .normal)
66 | button.frame = CGRect(x: view.frame.size.width - 70, y: 15.0, width: 60, height: 30)
67 | button.addTarget(self, action: #selector(onClose), for: .touchUpInside)
68 | view.addSubview(button)
69 | }
70 |
71 | func setupScene() {
72 |
73 | mainSceneView = SCNView(frame: view.bounds)
74 | view.addSubview(mainSceneView)
75 |
76 | mainScene = SCNScene()
77 | mainScene.background.contents = planet.planet3D.skybox
78 |
79 | setupLight()
80 | setupCamera()
81 |
82 | mainSceneView.scene = mainScene
83 |
84 | mainScene.rootNode.addChildNode(SCNNode(geometry: planet.planet3D.sphere))
85 | }
86 |
87 | func setupLight() {
88 | let lightNode = SCNNode()
89 | lightNode.light = SCNLight()
90 | lightNode.light?.type = .ambient
91 | lightNode.light?.color = UIColor(white: 0.37, alpha: 1.0)
92 | lightNode.position = SCNVector3Make(0, 50, 50)
93 |
94 | mainScene.rootNode.addChildNode(lightNode)
95 |
96 |
97 | mainScene.rootNode.addChildNode(planet.planet3D.light)
98 | }
99 |
100 | func setupCamera() {
101 | mainSceneView.allowsCameraControl = true
102 |
103 | let cameraNode = SCNNode()
104 | cameraNode.camera = SCNCamera()
105 | cameraNode.position = SCNVector3Make(0, 0, 20)
106 |
107 | mainScene.rootNode.addChildNode(cameraNode)
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/selection menu/cells/SelectionMenuTableViewCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/SystemUI.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SystemUI.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 25/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import ReSwift
11 |
12 | class StarCell: UITableViewCell {
13 | static let id = "starCell"
14 |
15 | @IBOutlet var starImageView: UIImageView!
16 | @IBOutlet var starTitleLabel: UILabel!
17 | @IBOutlet var kindTitleLabel: UILabel!
18 |
19 | public var planet: PlanetEntity? {
20 | didSet {
21 | starTitleLabel.text = "\(planet!.name) (\(planet!.kind.name()))"
22 | let radius = String(format: "%.0f", planet!.radius)
23 | kindTitleLabel.text = "Score: \(planet!.resourceScore) | Radius: \(radius) Km"
24 | starImageView.image = planet!.kind.image()
25 | starImageView.transform = CGAffineTransform(scaleX: planet!.scale, y: planet!.scale)
26 | }
27 | }
28 | }
29 |
30 | protocol SystemUiDelegate {
31 | func systemUISelectedPlanet(planet: PlanetEntity)
32 | }
33 |
34 | class SystemUI: BaseUI, UITableViewDelegate, UITableViewDataSource, StoreSubscriber {
35 |
36 | @IBOutlet var titleLabel: UILabel!
37 | @IBOutlet var starName: UILabel!
38 | @IBOutlet var starImageView: UIImageView!
39 | @IBOutlet var tableView: UITableView!
40 |
41 | var delegate: SystemUiDelegate?
42 |
43 | public var system: SystemEntity? {
44 | didSet {
45 | if let system = system {
46 | titleLabel.text = system.description
47 | starName.text = "Star: \(system.star.kind.name())"
48 | starImageView.image = system.star.kind.image()
49 | tableView.reloadData()
50 | }
51 | }
52 | }
53 |
54 | public func show() {
55 | system = store.state.uiState.selectedSystem
56 | store.subscribe(self) {
57 | $0.select{ $0.uiState }.skipRepeats()
58 | }
59 | isHidden = false
60 | alpha = 0
61 | layer.transform = CATransform3DMakeScale(0.2, 0.2, 0.2)
62 | UIView.animate(withDuration: 0.50,
63 | delay: 0,
64 | usingSpringWithDamping: 0.8,
65 | initialSpringVelocity: 15,
66 | options: .curveEaseInOut, animations: {
67 | self.alpha = 1
68 | self.layer.transform = CATransform3DMakeScale(1.0, 1.0, 1.0)
69 | }, completion: nil)
70 | }
71 |
72 | public func hide() {
73 | store.unsubscribe(self)
74 | UIView.animate(withDuration: 0.30, animations: {
75 | self.alpha = 0
76 | self.layer.transform = CATransform3DMakeScale(0.2, 0.2, 0.2)
77 | }, completion: {(success) in
78 | self.isHidden = true
79 | })
80 | }
81 |
82 | override func didMoveToSuperview() {
83 | super.didMoveToSuperview()
84 |
85 | frame = CGRect(x: 0, y: 0, width: 300, height: 400)
86 | center = superview!.center
87 |
88 | tableView.register(UINib(nibName: "StarCell", bundle: Bundle.main),
89 | forCellReuseIdentifier: StarCell.id)
90 | tableView.rowHeight = 60
91 | }
92 |
93 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
94 | if let system = system {
95 | return system.planetsCount()
96 | }
97 | return 0
98 | }
99 |
100 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
101 | let cell = tableView.dequeueReusableCell(withIdentifier: StarCell.id, for: indexPath) as! StarCell
102 | cell.planet = system!.planet(at: indexPath.row)
103 | return cell
104 | }
105 |
106 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
107 | tableView.deselectRow(at: indexPath, animated: true)
108 | if let delegate = delegate {
109 | delegate.systemUISelectedPlanet(planet: system!.planet(at: indexPath.row))
110 | }
111 | }
112 |
113 | func newState(state: UIState) {
114 | if system != state.selectedSystem {
115 | system = state.selectedSystem
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/outliner/Outliner.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Outliner.swift
3 | // LittleOrion
4 | //
5 | // Created by Thomas Ricouard on 26/03/2018.
6 | // Copyright © 2018 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import ReSwift
11 |
12 | protocol OutlinerDelegate: class {
13 | func outlinerDidChangeExpanded(outliner: Outliner, expanded: Bool)
14 | func outlinerDidSelectSystem(outliner: Outliner, system: UniverseId)
15 | }
16 |
17 | class Outliner: BaseUI {
18 |
19 | @IBOutlet var expandButton: UIButton!
20 | @IBOutlet var tableView: UITableView!
21 |
22 | var researchingSystems: [[UniverseId: Int]] = [] {
23 | didSet {
24 | if researchingSystems != oldValue {
25 | tableView.reloadData()
26 | }
27 | }
28 | }
29 | var discoveredSystems: [UniverseId] = [] {
30 | didSet {
31 | if discoveredSystems != oldValue {
32 | tableView.reloadData()
33 | }
34 | }
35 | }
36 |
37 | weak var delegate: OutlinerDelegate?
38 |
39 | let sections = ["Researching", "Systems", "Planets"]
40 |
41 | var expanded = false {
42 | didSet {
43 | delegate?.outlinerDidChangeExpanded(outliner: self, expanded: expanded)
44 | }
45 | }
46 |
47 | override func didMoveToSuperview() {
48 | super.didMoveToSuperview()
49 |
50 | tableView.register(UINib(nibName: OutlinerSystemTableViewCell.id, bundle: Bundle.main),
51 | forCellReuseIdentifier: OutlinerSystemTableViewCell.id)
52 | tableView.backgroundColor = .clear
53 |
54 | store.subscribe(self) {
55 | $0.select{ $0.playerState }.skipRepeats()
56 | }
57 | }
58 |
59 | @IBAction func onExpandButton(_ sender: Any) {
60 | expanded = !expanded
61 | }
62 | }
63 |
64 | extension Outliner: StoreSubscriber {
65 | func newState(state: PlayerState) {
66 | researchingSystems = state.player.discoveringEntities.compactMap({ [$0: $1] })
67 | discoveredSystems = state.player.discoveredEntities.filter({ store.state.universeState.universe!.entityAt(location: $0.location) is SystemEntity })
68 | }
69 | }
70 |
71 | extension Outliner: UITableViewDelegate, UITableViewDataSource {
72 | func numberOfSections(in tableView: UITableView) -> Int {
73 | return sections.count
74 | }
75 |
76 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
77 | if section == 0 {
78 | return researchingSystems.count
79 | }
80 | else if section == 1 {
81 | return discoveredSystems.count
82 | }
83 | return 0
84 | }
85 |
86 | func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
87 | return sections[section]
88 | }
89 |
90 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
91 | return 44
92 | }
93 |
94 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
95 | if let cell = tableView.dequeueReusableCell(withIdentifier: OutlinerSystemTableViewCell.id) as? OutlinerSystemTableViewCell {
96 | if indexPath.section == 0 {
97 | let system = researchingSystems[indexPath.row]
98 | cell.systemName.text = system.first!.key.name
99 | cell.systemDiscoveryProgress.isHidden = false
100 | let progress = system.first!.value
101 | cell.systemDiscoveryProgress.progress = Float(progress) / Float(UniverseEntity.dayToDisover)
102 | } else if indexPath.section == 1 {
103 | cell.systemName.text = discoveredSystems[indexPath.row].name
104 | cell.systemDiscoveryProgress.isHidden = true
105 | }
106 | return cell
107 | }
108 | return UITableViewCell(frame: CGRect.zero)
109 | }
110 |
111 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
112 | if indexPath.section == 0 {
113 | let system = researchingSystems[indexPath.row]
114 | delegate?.outlinerDidSelectSystem(outliner: self, system: system.first!.key)
115 | } else if indexPath.section == 1 {
116 | let system = discoveredSystems[indexPath.row]
117 | delegate?.outlinerDidSelectSystem(outliner: self, system: system)
118 | }
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/outliner/cells/OutlinerSystemTableViewCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/selection menu/SelectionMenu.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/StarCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/space/universe/UniverseEntity.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Universe.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import GameplayKit
10 |
11 | class UniverseRules {
12 |
13 | private static let dic = ResourcesLoader.loadDicResource(name: "universeRules")!
14 |
15 | static let systemSpawnProbability: UInt32 = dic["systemSpwawnProbability"] as! UInt32
16 | static let basePlanetsRadius: CGFloat = dic["basePlanetsRadius"] as! CGFloat
17 | static let superPlanetSpwawnProbability: UInt32 = dic["superPlanetSpwawnProbability"] as! UInt32
18 | static let superPlanetScale: CGFloat = dic["superPlanetScale"] as! CGFloat
19 | static let planetMaxSpace: Int = dic["planetMaxSpace"] as! Int
20 |
21 | }
22 |
23 | class UniverseNode: GKGridGraphNode {
24 | var entity: UniverseEntity!
25 | }
26 |
27 | struct UniverseId: Equatable, Hashable {
28 | let location: Location
29 | var name: String {
30 | get {
31 | return "Node x:\(location.x) y:\(location.y)"
32 | }
33 | }
34 | var hashValue: Int {
35 | get {
36 | return name.hashValue
37 | }
38 | }
39 |
40 | init(location: Location) {
41 | self.location = location
42 | }
43 | }
44 |
45 | class UniverseEntity: GKEntity, Travelable, Discoverable {
46 |
47 | var id: UniverseId
48 | static let dayToDisover = 10
49 |
50 | var spriteNode: SKNode {
51 | get {
52 | return (component(ofType: UniverseSpriteComponent.self)?.node)!
53 | }
54 | }
55 |
56 | var travelTimeDay: Int {
57 | return 0
58 | }
59 |
60 | var discovered: Bool {
61 | return store.state.playerState.player.discoveredEntities.contains(id)
62 | }
63 |
64 | var dayToDiscover: Int {
65 | return UniverseEntity.dayToDisover
66 | }
67 |
68 | override var description: String {
69 | get {
70 | return "Default Universe Entity"
71 | }
72 | }
73 |
74 | var extraInfo: String? {
75 | get {
76 | return nil
77 | }
78 | }
79 |
80 | public init(location: Location) {
81 | self.id = UniverseId(location: location)
82 | super.init()
83 | addComponent(UniverseSpriteComponent.component(with: self))
84 | }
85 |
86 | required init?(coder aDecoder: NSCoder) {
87 | fatalError("init(coder:) has not been implemented")
88 | }
89 |
90 | }
91 |
92 | class Universe: GKEntity {
93 |
94 | let size: Size
95 | let grid: GKGridGraph
96 |
97 | enum UniverseSize: String {
98 | case tiny, small, standard, big
99 |
100 | func size() -> Size {
101 | return ResourcesLoader.loadDimensionResource(name: "universeDimensions", dimensionName: rawValue)!
102 | }
103 | }
104 |
105 | public init(size: UniverseSize) {
106 | self.size = size.size()
107 | self.grid = GKGridGraph(fromGridStartingAt: int2(0, 0),
108 | width: self.size.width,
109 | height: self.size.height,
110 | diagonalsAllowed: true, nodeClass: UniverseNode.self)
111 | super.init()
112 |
113 | generate()
114 | }
115 |
116 | required init?(coder aDecoder: NSCoder) {
117 | fatalError("init(coder:) has not been implemented")
118 | }
119 |
120 | private func generate() {
121 | for node in grid.nodes! {
122 | if let node = node as? UniverseNode {
123 | let location = Location(x: node.gridPosition.x, y: node.gridPosition.y)
124 | if arc4random_uniform(UniverseRules.systemSpawnProbability) == 1 {
125 | node.entity = SystemEntity(location: location)
126 | } else {
127 | node.entity = EmptyEntity(location: location)
128 | }
129 | }
130 | }
131 |
132 | for node in grid.nodes! {
133 | if let node = node as? UniverseNode {
134 | let neighboors = node.connectedNodes
135 | for neighboor in neighboors {
136 | if let neighboor = neighboor as? UniverseNode {
137 | if let _ = neighboor.entity as? SystemEntity, let _ = node.entity as? SystemEntity {
138 | let location = Location(x: node.gridPosition.x, y: node.gridPosition.y)
139 | neighboor.entity = EmptyEntity(location: location)
140 | }
141 | }
142 | }
143 | }
144 | }
145 | }
146 |
147 | public func entityAt(location: Location) -> UniverseEntity {
148 | return grid.node(atGridPosition: int2(location.x, location.y))!.entity!
149 | }
150 |
151 | public func nodeAt(location: Location) -> UniverseNode? {
152 | return grid.node(atGridPosition: int2(location.x, location.y))
153 | }
154 |
155 | public static func grideNodePositionToMapPosition(gridNode: UniverseNode) -> CGPoint {
156 | let size = UniverseSpriteComponent.nodeSize
157 | let position = CGPoint(x: CGFloat(CGFloat(gridNode.gridPosition.x) * size.width),
158 | y: CGFloat(CGFloat(gridNode.gridPosition.y) * size.height))
159 | return position
160 | }
161 |
162 | public static func mapNodePositionToGridPosition(mapNode: SKNode) -> Location {
163 | let size = UniverseSpriteComponent.nodeSize
164 | let gridPosition = Location(x: Int32(Int32(mapNode.position.x) / Int32(size.width)),
165 | y: Int32(Int32(mapNode.position.y) / Int32(size.height)))
166 | return gridPosition
167 | }
168 |
169 | override func update(deltaTime seconds: TimeInterval) {
170 | super.update(deltaTime: seconds)
171 |
172 | for case let node as UniverseNode in grid.nodes! {
173 | node.entity.components.forEach({ $0.update(deltaTime: seconds) })
174 | }
175 | }
176 |
177 | }
178 |
179 | func ==(lhs: Universe, rhs: Universe) -> Bool {
180 | return lhs.size == rhs.size &&
181 | lhs.grid == rhs.grid
182 | }
183 |
184 |
185 | func ==(lhs: Universe?, rhs: Universe?) -> Bool {
186 | return false
187 | }
188 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/outliner/Outliner.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/BottomBar.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
32 |
41 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/SystemUI.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/models/space/bodies/PlanetEntity.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Planet.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 25/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import GameplayKit
10 | import SceneKit
11 |
12 | struct PlanetId: Equatable, Hashable {
13 | let systemId: UniverseId
14 | let index: Int
15 |
16 | var hashValue: Int {
17 | get {
18 | return systemId.hashValue * index.hashValue
19 | }
20 | }
21 |
22 | init(systemId: UniverseId, index: Int) {
23 | self.systemId = systemId
24 | self.index = index
25 | }
26 | }
27 |
28 | //MARK: - Planet
29 | class PlanetEntity: SystemBody, Discoverable {
30 |
31 | static let planetRessourceModifier = ResourcesLoader.loadPlanetResource(name: "planetResourcesModifier")!
32 | static let planetNames = ResourcesLoader.loadArrayTextResource(name: "planetsText")!
33 |
34 | enum Kind: UInt32 {
35 | case desert, oceanic, toxic, continental, frozen, volcanic
36 |
37 | private static let _count: Kind.RawValue = {
38 | var maxValue: UInt32 = 0
39 | while let _ = Kind(rawValue: maxValue) {
40 | maxValue += 1
41 | }
42 | return maxValue
43 | }()
44 |
45 | static func randomKind() -> Kind {
46 | let rand = arc4random_uniform(_count)
47 | return Kind(rawValue: rand)!
48 | }
49 |
50 | func name() -> String {
51 | return planetNames[Int(rawValue)]
52 | }
53 |
54 | func image() -> UIImage {
55 | return UIImage(named: ResourcesLoader.loadArrayTextResource(name: "planetsText")![Int(rawValue)])!
56 | }
57 |
58 | func ressources() -> [String: Int] {
59 | return planetRessourceModifier[name()]!
60 | }
61 |
62 | }
63 |
64 | var discovered: Bool {
65 | return store.state.playerState.player.discoveredPlanets.contains(id)
66 | }
67 |
68 | var dayToDiscover: Int {
69 | return 200
70 | }
71 |
72 | let id: PlanetId
73 | let kind: Kind
74 | let scale: CGFloat
75 | var planet3D: Planet3D! = nil
76 |
77 | //resource
78 | let food: Food
79 | let energy: Energy
80 | let mineral: Mineral
81 | let reseach: Research
82 |
83 | var resourceScore: Int {
84 | get {
85 | return food.abundance.rawValue +
86 | energy.abundance.rawValue +
87 | mineral.abundance.rawValue +
88 | reseach.abundance.rawValue
89 | }
90 | }
91 |
92 | //The radius, in KM of the planet.
93 | var radius: CGFloat {
94 | get {
95 | return UniverseRules.basePlanetsRadius * scale
96 | }
97 | }
98 |
99 | //How many space are buildable on this planet.
100 | var space: Int {
101 | get {
102 | let divider = (UniverseRules.basePlanetsRadius * UniverseRules.superPlanetScale) / CGFloat(UniverseRules.planetMaxSpace)
103 | return Int(radius / divider)
104 | }
105 | }
106 |
107 |
108 | //A planet may or may not have inhabitants.
109 | private var inhabitants: [Pop]?
110 |
111 | //The parent system of the planet.
112 | let system: SystemEntity
113 |
114 | public init(in system: SystemEntity, order: Int) {
115 | id = PlanetId(systemId: system.id, index: order)
116 | self.system = system
117 | kind = Kind.randomKind()
118 | var tmpScale = CGFloat((arc4random_uniform(600) + 400)) / 1000
119 | if tmpScale > 0.9 && arc4random_uniform(UniverseRules.superPlanetSpwawnProbability) == 1 {
120 | //1 out of X chance to generate a super planet if scale is already big.
121 | tmpScale = UniverseRules.superPlanetScale
122 | }
123 | scale = tmpScale
124 | food = Food(abundance: PlanetResource.Abundance(rawValue: kind.ressources()["Food"]!)!)
125 | mineral = Mineral(abundance: PlanetResource.Abundance(rawValue: kind.ressources()["Mineral"]!)!)
126 | energy = Energy(abundance: PlanetResource.Abundance(rawValue: kind.ressources()["Energy"]!)!)
127 | reseach = Research(abundance: PlanetResource.Abundance(rawValue: kind.ressources()["Research"]!)!)
128 |
129 | super.init(name: "Planet \(order)")
130 |
131 | planet3D = Planet3D(planet: self)
132 | }
133 |
134 | required init?(coder aDecoder: NSCoder) {
135 | fatalError("init(coder:) has not been implemented")
136 | }
137 |
138 | func inhabitantsCount() -> Int {
139 | if let inhabitants = inhabitants {
140 | return inhabitants.count
141 | }
142 | return 0
143 | }
144 |
145 | func addInhabitants(pop: Pop) {
146 | if inhabitants == nil {
147 | inhabitants = [Pop]()
148 | }
149 | inhabitants?.append(pop)
150 | }
151 | }
152 |
153 | //MARK: - 3D
154 | class Planet3D {
155 |
156 | var skybox: [UIImage] {
157 | get {
158 | return [#imageLiteral(resourceName: "Skybox_PositiveX"),
159 | #imageLiteral(resourceName: "Skybox_NegativeX"),
160 | #imageLiteral(resourceName: "Skybox_PositiveY"),
161 | #imageLiteral(resourceName: "Skybox_NegativeY"),
162 | #imageLiteral(resourceName: "Skybox_PositiveZ"),
163 | #imageLiteral(resourceName: "Skybox_NegativeZ")]
164 | }
165 | }
166 |
167 | var sphere: SCNSphere {
168 | get {
169 | let sphere = SCNSphere(radius: 5.0)
170 | let textureName = planet.kind.name() + "Texture"
171 | let material = SCNMaterial()
172 | material.diffuse.contents = UIImage(named: textureName)
173 | material.specular.contents = planet.system.star.kind.textureFillColor()
174 | material.shininess = 0.8
175 | sphere.materials = [material]
176 | return sphere
177 | }
178 | }
179 |
180 | var light: SCNNode {
181 | get {
182 | let omniLightNode = SCNNode()
183 | omniLightNode.light = SCNLight()
184 | omniLightNode.light?.color = planet.system.star.kind.textureFillColor()
185 | omniLightNode.light?.type = .omni
186 | omniLightNode.position = SCNVector3Make(0, 40, 40)
187 | return omniLightNode
188 | }
189 | }
190 |
191 | var planet: PlanetEntity! = nil
192 |
193 | init(planet: PlanetEntity) {
194 | self.planet = planet
195 | }
196 | }
197 |
198 | //MARK: - Resources
199 | class PlanetResource {
200 |
201 | var name: String {
202 | get {
203 | return ""
204 | }
205 | }
206 |
207 | var description: String {
208 | get {
209 | return ""
210 | }
211 | }
212 |
213 | let abundance: Abundance
214 |
215 | enum Abundance: Int {
216 | case none, low, average, plenty, enormous
217 |
218 | func abundancyDescription() -> String {
219 | return "Coming soon"
220 | }
221 | }
222 |
223 | init(abundance: Abundance) {
224 | let randomness = arc4random_uniform(3)
225 | if randomness == 1 && abundance.rawValue > 0 {
226 | self.abundance = Abundance(rawValue: abundance.rawValue - 1)!
227 | }
228 | else if randomness == 2 && abundance.rawValue < 4 {
229 | self.abundance = Abundance(rawValue: abundance.rawValue + 1)!
230 | }
231 | else {
232 | self.abundance = abundance
233 | }
234 | }
235 | }
236 |
237 | class Food: PlanetResource {
238 |
239 | override var name: String {
240 | get {
241 | return "Food"
242 | }
243 | }
244 |
245 | override var description: String {
246 | get {
247 | return "The foods available on the planet"
248 | }
249 | }
250 | }
251 |
252 |
253 | class Mineral: PlanetResource {
254 |
255 | override var name: String {
256 | get {
257 | return "Mineral"
258 | }
259 | }
260 |
261 | override var description: String {
262 | get {
263 | return "The minerals available on the planet"
264 | }
265 | }
266 | }
267 |
268 | class Energy: PlanetResource {
269 |
270 | override var name: String {
271 | get {
272 | return "Energy"
273 | }
274 | }
275 |
276 | override var description: String {
277 | get {
278 | return "The energy available on the planet"
279 | }
280 | }
281 | }
282 |
283 | class Research: PlanetResource {
284 |
285 | override var name: String {
286 | get {
287 | return "Science"
288 | }
289 | }
290 |
291 | override var description: String {
292 | get {
293 | return "The research (for science) available on the planet"
294 | }
295 | }
296 | }
297 |
298 |
299 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/scenes/UniverseScene.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameScene.swift
3 | // Little Orion
4 | //
5 | // Created by Thomas Ricouard on 21/11/2016.
6 | // Copyright © 2016 Thomas Ricouard. All rights reserved.
7 | //
8 |
9 | import SpriteKit
10 | import GameplayKit
11 | import ReSwift
12 |
13 | class UniverseScene: SKScene {
14 |
15 | var lastUpdateTime : TimeInterval = 0
16 | var universe: Universe? {
17 | didSet {
18 | if let universe = universe {
19 | setupUniverse(universe: universe)
20 | }
21 | }
22 | }
23 |
24 | let topBar: TopBar = TopBar.loadFromNib()
25 | let bottomBar: BottomBar = BottomBar.loadFromNib()
26 | let outliner: Outliner = Outliner.loadFromNib()
27 |
28 | var universeSubscriber: UniverseSubscriber?
29 | var uiSubscriber: UISubscriber?
30 | var playerSubscriber: PlayerSubcriber?
31 |
32 | var loaded = false
33 | var universeLoaded = false
34 | var dismissiveInteraction = false
35 |
36 | var startX: CGFloat = 0.0
37 | var startY: CGFloat = 0.0
38 |
39 | var mapNode = SKNode()
40 | var mapMoved = false
41 | var mapNewPosition: CGPoint?
42 | var mapNewScale: CGFloat?
43 | var inZoomGesture = false
44 |
45 | override func sceneDidLoad() {
46 |
47 | view?.isMultipleTouchEnabled = true
48 | backgroundColor = UIColor.black
49 |
50 | if (!loaded) {
51 |
52 | universeSubscriber = UniverseSubscriber(scene: self)
53 | uiSubscriber = UISubscriber(scene: self)
54 | playerSubscriber = PlayerSubcriber(scene: self)
55 |
56 | store.subscribe(universeSubscriber!) {
57 | $0.select{ $0.universeState }.skipRepeats()
58 | }
59 |
60 | store.subscribe(uiSubscriber!) {
61 | $0.select{ $0.uiState }.skipRepeats()
62 | }
63 |
64 | store.subscribe(playerSubscriber!) {
65 | $0.select{ $0.playerState }.skipRepeats()
66 | }
67 |
68 | lastUpdateTime = 0
69 |
70 | store.dispatch(UniverseActions.CreateUnivserse(size: .standard))
71 | store.dispatch(PlayerActions.Initialize())
72 | store.dispatch(PlayerActions.StartTimer())
73 |
74 | onCenterPlayerButton()
75 |
76 | bottomBar.delegate = self
77 | outliner.delegate = self
78 | }
79 |
80 | loaded = true
81 | }
82 |
83 | func setupUniverse(universe: Universe) {
84 | if !universeLoaded {
85 | universeLoaded = true
86 | for node in universe.grid.nodes! {
87 | if let node = node as? UniverseNode {
88 | let spriteNode = node.entity.spriteNode
89 | spriteNode.position = Universe.grideNodePositionToMapPosition(gridNode: node)
90 | if spriteNode.parent == nil {
91 | mapNode.addChild(spriteNode)
92 | }
93 | }
94 | }
95 | addChild(mapNode)
96 |
97 | generateStarField()
98 | }
99 | }
100 |
101 | override func didMove(to view: SKView) {
102 | let pinch = UIPinchGestureRecognizer(target: self, action: #selector(self.onPinchGesture(pinch:)))
103 | self.view?.addGestureRecognizer(pinch)
104 |
105 | self.view?.addSubview(topBar)
106 | topBar.frame = CGRect(x: -2, y: -1, width: self.view!.frame.size.width + 4, height: 80)
107 |
108 | self.view?.addSubview(bottomBar)
109 | bottomBar.frame = CGRect(x: -2, y: self.view!.frame.size.height - 49,
110 | width: self.view!.frame.size.width + 4, height: 50)
111 |
112 | self.view?.addSubview(outliner)
113 | outliner.frame = CGRect(x: -130, y: 90, width: 150, height: self.view!.frame.size.height - 180)
114 | }
115 |
116 |
117 | func generateStarField() {
118 | var emitterNode = starfieldEmitter(color: SKColor.lightGray, starSpeedY: 50, starsPerSecond: 1, starScaleFactor: 0.2)
119 | emitterNode.zPosition = -10
120 | addChild(emitterNode)
121 |
122 | emitterNode = starfieldEmitter(color: SKColor.gray, starSpeedY: 30, starsPerSecond: 2, starScaleFactor: 0.1)
123 | emitterNode.zPosition = -11
124 | addChild(emitterNode)
125 |
126 | emitterNode = starfieldEmitter(color: SKColor.darkGray, starSpeedY: 15, starsPerSecond: 4, starScaleFactor: 0.05)
127 | emitterNode.zPosition = -12
128 | addChild(emitterNode)
129 | }
130 |
131 | func starfieldEmitter(color: SKColor, starSpeedY: CGFloat, starsPerSecond: CGFloat, starScaleFactor: CGFloat) -> SKEmitterNode {
132 |
133 | let lifetime = frame.size.height * UIScreen.main.scale / starSpeedY
134 |
135 | let emitterNode = SKEmitterNode()
136 | emitterNode.particleTexture = SKTexture(imageNamed: "StarParticle")
137 | emitterNode.particleBirthRate = starsPerSecond
138 | emitterNode.particleColor = color
139 | emitterNode.particleSpeed = starSpeedY * -1
140 | emitterNode.particleScale = starScaleFactor
141 | emitterNode.particleColorBlendFactor = 1
142 | emitterNode.particleLifetime = lifetime
143 |
144 | emitterNode.position = CGPoint(x: 0, y: frame.size.height)
145 | emitterNode.particlePositionRange = CGVector(dx: frame.size.width, dy: 0)
146 |
147 | emitterNode.advanceSimulationTime(TimeInterval(lifetime))
148 |
149 | return emitterNode
150 | }
151 |
152 | override func update(_ currentTime: TimeInterval) {
153 |
154 | if mapNewPosition != nil {
155 | mapNode.position = mapNewPosition!
156 | }
157 | if mapNewScale != nil {
158 | mapNode.setScale(mapNewScale!)
159 | }
160 |
161 | mapNewPosition = nil
162 | mapNewScale = nil
163 |
164 | universe?.update(deltaTime: currentTime)
165 | }
166 |
167 | }
168 |
169 | //MARK: - State
170 | class UniverseSubscriber: StoreSubscriber {
171 | weak var scene: UniverseScene?
172 |
173 | init(scene: UniverseScene) {
174 | self.scene = scene
175 | }
176 |
177 | func newState(state: UniverseState) {
178 | scene?.updateUniverse(state: state)
179 | }
180 | }
181 |
182 | class UISubscriber: StoreSubscriber {
183 |
184 | weak var scene: UniverseScene?
185 |
186 | init(scene: UniverseScene) {
187 | self.scene = scene
188 | }
189 |
190 |
191 | func newState(state: UIState) {
192 | scene?.updateModal(state: state)
193 | scene?.updateScene(state: state)
194 | }
195 | }
196 |
197 | class PlayerSubcriber: StoreSubscriber {
198 | weak var scene: UniverseScene?
199 |
200 | init(scene: UniverseScene) {
201 | self.scene = scene
202 | }
203 |
204 | func newState(state: PlayerState) {
205 | scene?.updatePlayer(state: state)
206 | }
207 | }
208 |
209 | extension UniverseScene {
210 | func updateUniverse(state: UniverseState) {
211 | if let universe = state.universe {
212 | self.universe = universe
213 | }
214 | }
215 |
216 | func updateScene(state: UIState) {
217 | switch state.currentScene {
218 | case .universe:
219 | break
220 | case .planet:
221 | let planetController = PlanetViewController()
222 | view?.window?.rootViewController?.present(planetController, animated: true, completion: nil)
223 | break
224 | }
225 | }
226 |
227 | func updateModal(state: UIState) {
228 | switch state.currentModal {
229 | case .none:
230 | ModalUI.dismissSystemUI()
231 | ModalUI.dismissSelectionUI()
232 | case .system:
233 | ModalUI.presentSystemUI(from: self, delegate: self)
234 | case .entity:
235 | ModalUI.presentSelectionUI(from: self)
236 | }
237 | }
238 |
239 | func updatePlayer(state: PlayerState) {
240 | if state.player.spriteNode.parent == nil {
241 | mapNode.addChild(state.player.spriteNode)
242 | }
243 | }
244 | }
245 |
246 | //MARK: - Nodes
247 | extension UniverseScene {
248 | func systemAt(_ touches: Set, with event: UIEvent?) -> SystemEntity? {
249 | let node = nodeAt(touches, with: event)
250 | if let entity = node?.entity as? SystemEntity {
251 | return entity
252 | }
253 | return nil
254 | }
255 |
256 | func nodeAt(_ touches: Set, with event: UIEvent?) -> SKNode? {
257 | return nodes(at: (touches.first?.location(in: self))!).first
258 | }
259 |
260 | func gridNodeAt(_ touches: Set, with event: UIEvent?) -> UniverseNode? {
261 | if let node = nodeAt(touches, with: event) {
262 | return gridNodeRelativeTo(node: node)
263 | }
264 | return nil
265 | }
266 |
267 | func gridNodeRelativeTo(node: SKNode) -> UniverseNode? {
268 | let entity = universe?.nodeAt(location: Universe.mapNodePositionToGridPosition(mapNode: node))
269 | return entity
270 | }
271 | }
272 |
273 | //MARK: - UI
274 | extension UniverseScene: SystemUiDelegate {
275 | func systemUISelectedPlanet(planet: PlanetEntity) {
276 | store.dispatch(UIActions.ShowPlanetDetail(planet: planet))
277 | }
278 | }
279 |
280 | //MARK: - BottomBar delegate
281 | extension UniverseScene: BottomBarDelegate {
282 | func onCenterPlayerButton() {
283 | let playerPosition = store.state.playerState.player.spriteNode.position
284 | mapNewPosition = CGPoint(x: -playerPosition.x, y: -playerPosition.y)
285 | }
286 |
287 | func onMovePlayerButton() {
288 | if store.state.playerState.player.isInMovement {
289 | store.dispatch(PlayerActions.StopMovement())
290 | } else if let node = store.state.uiState.selectedNode {
291 | if let originalGridNode = gridNodeRelativeTo(node: store.state.playerState.player.spriteNode),
292 | let newGridPosition = gridNodeRelativeTo(node: node) {
293 | let paths = originalGridNode.findPath(to: newGridPosition)
294 | for universeNode in paths {
295 | if let universeNode = universeNode as? UniverseNode,
296 | let shapeNode = universeNode.entity.spriteNode as? SKShapeNode {
297 | //TODO: Hightlight travel path
298 | }
299 | }
300 |
301 | let fromLocation = Universe.mapNodePositionToGridPosition(mapNode: store.state.playerState.player.spriteNode)
302 | let toLocation = Universe.mapNodePositionToGridPosition(mapNode: node)
303 | let movement = PlayerMovementComponent(startDate: store.state.playerState.currentDate,
304 | from: fromLocation,
305 | to: toLocation)
306 | store.dispatch(PlayerActions.MoveToPosition(movement: movement))
307 | }
308 | }
309 | }
310 | }
311 |
312 | //MARK: - OutlinerDelegate
313 | extension UniverseScene: OutlinerDelegate {
314 | func outlinerDidChangeExpanded(outliner: Outliner, expanded: Bool) {
315 | var frame = outliner.frame
316 | frame.origin.x = expanded ? 0 : -outliner.bounds.size.width + 20
317 | UIView.animate(withDuration: 0.20) {
318 | self.outliner.frame = frame
319 | }
320 | }
321 |
322 | func outlinerDidSelectSystem(outliner: Outliner, system: UniverseId) {
323 | if let system = universe!.entityAt(location: system.location) as? SystemEntity {
324 | store.dispatch(UIActions.ShowSelectedSystemModal(system: system))
325 | }
326 | }
327 | }
328 |
329 | //MARK: - Touch
330 | extension UniverseScene {
331 |
332 | override func touchesBegan(_ touches: Set, with event: UIEvent?) {
333 | store.dispatch(UIActions.RemoveSelectedNode())
334 |
335 | if (touches.count == 1) {
336 | let position = touches.first!.location(in: self)
337 |
338 | startX = position.x
339 | startY = position.y
340 | }
341 |
342 | if store.state.uiState.currentModal != .none {
343 | store.dispatch(UIActions.DismissModal())
344 | dismissiveInteraction = true
345 | }
346 | }
347 |
348 | override func touchesMoved(_ touches: Set, with event: UIEvent?) {
349 | if (touches.count == 1 && !inZoomGesture) {
350 | let position = touches.first!.location(in: self)
351 | let currentMapPosition = mapNode.position
352 |
353 | let delX = position.x - startX
354 | let delY = position.y - startY
355 |
356 | //Will be updated in the update method
357 | mapNewPosition = CGPoint(x: currentMapPosition.x + delX , y: currentMapPosition.y + delY)
358 |
359 | startX = position.x
360 | startY = position.y
361 |
362 | if (abs(delX) >= 5 || abs(delY) >= 5) {
363 | mapMoved = true
364 | store.dispatch(UIActions.RemoveSelectedNode())
365 | }
366 | }
367 | }
368 |
369 | override func touchesEnded(_ touches: Set, with event: UIEvent?) {
370 | if !mapMoved && !dismissiveInteraction {
371 | if let node = nodeAt(touches, with: event) as? SKShapeNode {
372 | store.dispatch(UIActions.SetSelectedNode(node: node))
373 | }
374 |
375 | if let system = systemAt(touches, with: event), system.discovered {
376 | store.dispatch(UIActions.ShowSelectedSystemModal(system: system))
377 | }
378 |
379 | if let universeNode = gridNodeAt(touches, with: event), !universeNode.entity.discovered {
380 | store.dispatch(UIActions.ShowSelectionModal(entity: universeNode.entity))
381 | }
382 |
383 | }
384 |
385 | dismissiveInteraction = false
386 | mapMoved = false
387 | }
388 |
389 | @objc func onPinchGesture(pinch: UIPinchGestureRecognizer) {
390 |
391 | if pinch.state == .began {
392 | inZoomGesture = true
393 | } else if pinch.state == .ended {
394 | inZoomGesture = false
395 | }
396 |
397 | var anchorPoint = pinch.location(in: pinch.view)
398 | anchorPoint = self.convertPoint(fromView: anchorPoint)
399 | let mapAnchorPoint = mapNode.convert(anchorPoint, from: self)
400 |
401 | let newScale = mapNode.xScale * pinch.scale
402 |
403 | if (newScale >= 0.7 && newScale <= 3) {
404 | mapNewScale = newScale
405 |
406 | let mapSceneAnchorPoint = self.convert(mapAnchorPoint, from: mapNode)
407 | let translationOfAnchorInScene = (x: anchorPoint.x - mapSceneAnchorPoint.x, y: anchorPoint.y - mapSceneAnchorPoint.y)
408 |
409 | mapNewPosition = CGPoint(x: mapNode.position.x + translationOfAnchorInScene.x, y: mapNode.position.y + translationOfAnchorInScene.y)
410 | }
411 |
412 | pinch.scale = 1.0
413 | }
414 | }
415 |
416 |
--------------------------------------------------------------------------------
/Little Orion/Little Orion/ui/TopBar.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
33 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
--------------------------------------------------------------------------------