Skip to content

Commit

Permalink
Merge commit '5206c06000d6a6666a8b63f173b7440720495c34' into working-…
Browse files Browse the repository at this point in the history
…branch

# Conflicts:
#	TowerForge/TowerForge/Grid.swift
#	TowerForge/TowerForge/LevelManager/Components/AiComponent.swift
#	TowerForge/TowerForge/LevelManager/Entities/Base Entities/BaseUnit.swift
#	TowerForge/TowerForge/LevelManager/Entities/MeleeUnit.swift
#	TowerForge/TowerForge/LevelManager/Entities/SoldierUnit.swift
#	TowerForge/TowerForge/LevelManager/Generators/UnitGenerator.swift
#	TowerForge/TowerForge/Protocols/Spawnable.swift
  • Loading branch information
zheng-ze committed Mar 22, 2024
2 parents fd0251f + 5206c06 commit 14108b3
Show file tree
Hide file tree
Showing 24 changed files with 160 additions and 41 deletions.
48 changes: 48 additions & 0 deletions TowerForge/Launch Screen.storyboard
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13142" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12042"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd">
<rect key="frame" x="0.0" y="626.5" width="375" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="TowerForge" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
<rect key="frame" x="0.0" y="202" width="375" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="obG-Y5-kRd" secondAttribute="centerX" id="5cz-MP-9tL"/>
<constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/>
<constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="20" symbolic="YES" id="SfN-ll-jLj"/>
<constraint firstAttribute="bottom" secondItem="obG-Y5-kRd" secondAttribute="bottom" constant="20" id="Y44-ml-fuU"/>
<constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/>
<constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="20" symbolic="YES" id="x7j-FC-K8j"/>
</constraints>
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
8 changes: 6 additions & 2 deletions TowerForge/TowerForge.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
520062522BA8DA09000DBA30 /* UnitGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520062512BA8DA09000DBA30 /* UnitGenerator.swift */; };
520062562BA8E026000DBA30 /* PlayerSpawnable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520062552BA8E026000DBA30 /* PlayerSpawnable.swift */; };
520062582BA8ED73000DBA30 /* HomeComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520062572BA8ED73000DBA30 /* HomeComponent.swift */; };
523923E72BADC8530044BA61 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 523923E62BADC8530044BA61 /* Launch Screen.storyboard */; };
52578B822BA61AAF00B4D76C /* PositionComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52578B812BA61AAF00B4D76C /* PositionComponent.swift */; };
52578B872BA6209700B4D76C /* DamageComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52578B862BA6209700B4D76C /* DamageComponent.swift */; };
52578B8C2BA627B200B4D76C /* Team.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52578B8B2BA627B200B4D76C /* Team.swift */; };
Expand Down Expand Up @@ -131,6 +132,7 @@
520062512BA8DA09000DBA30 /* UnitGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitGenerator.swift; sourceTree = "<group>"; };
520062552BA8E026000DBA30 /* PlayerSpawnable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerSpawnable.swift; sourceTree = "<group>"; };
520062572BA8ED73000DBA30 /* HomeComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeComponent.swift; sourceTree = "<group>"; };
523923E62BADC8530044BA61 /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
52578B812BA61AAF00B4D76C /* PositionComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionComponent.swift; sourceTree = "<group>"; };
52578B862BA6209700B4D76C /* DamageComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamageComponent.swift; sourceTree = "<group>"; };
52578B8B2BA627B200B4D76C /* Team.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Team.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -340,6 +342,7 @@
52DF5F9B2BA32B2200135367 = {
isa = PBXGroup;
children = (
523923E62BADC8530044BA61 /* Launch Screen.storyboard */,
BABB7C052BA9A41000D54DAE /* TowerForceTestPlan.xctestplan */,
52DF5FA62BA32B2300135367 /* TowerForge */,
52DF5FC02BA32B2600135367 /* TowerForgeTests */,
Expand Down Expand Up @@ -583,6 +586,7 @@
52DF5FB52BA32B2600135367 /* Assets.xcassets in Resources */,
52DF5FB82BA32B2600135367 /* LaunchScreen.storyboard in Resources */,
52DF5FAC2BA32B2300135367 /* Actions.sks in Resources */,
523923E72BADC8530044BA61 /* Launch Screen.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -876,7 +880,7 @@
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UIRequiresFullScreen = YES;
INFOPLIST_KEY_UIStatusBarHidden = YES;
Expand Down Expand Up @@ -911,7 +915,7 @@
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UIRequiresFullScreen = YES;
INFOPLIST_KEY_UIStatusBarHidden = YES;
Expand Down
Binary file not shown.
4 changes: 2 additions & 2 deletions TowerForge/TowerForge/GameViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class GameViewController: UIViewController {
}

private func setUpGameWorld(scene: GameScene) {
self.gameWorld = GameWorld(scene: scene)
self.gameWorld = GameWorld(scene: scene, screenSize: self.view.frame)
}
}

Expand Down Expand Up @@ -85,7 +85,7 @@ extension GameViewController: SceneManagerDelegate {
}
func showScene(scene: SKScene) {
if let view = self.view as? SKView {
scene.scaleMode = .aspectFill
scene.scaleMode = .resizeFill
view.presentScene(scene)
view.ignoresSiblingOrder = true // to render nodes more efficiently
view.showsFPS = true
Expand Down
14 changes: 12 additions & 2 deletions TowerForge/TowerForge/GameWorld.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,21 @@ class GameWorld {
private var renderer: Renderer?
private var entitiesInContact: Set<TFContact> = []

init(scene: GameScene?) {
init(scene: GameScene?, screenSize: CGRect) {
self.scene = scene
entityManager = EntityManager()
systemManager = SystemManager()
eventManager = EventManager()
selectionNode = UnitSelectionNode()
grid = Grid(entityManager: entityManager)
grid = Grid(entityManager: entityManager, screenSize: screenSize)
if let scene = self.scene {
grid.generateTileMap(scene: scene)
}
renderer = Renderer(target: self, scene: scene)

self.setUpSystems()
self.setUpSelectionNode()
self.setupTeam()
}

func update(deltaTime: TimeInterval) {
Expand All @@ -43,6 +47,12 @@ class GameWorld {
func spawnUnit(at location: CGPoint) {
selectionNode.unitNodeDidSpawn(location)
}
func setupTeam() {
let ownTeam = Team(player: .ownPlayer, entityManager: entityManager)
let oppositeTeam = Team(player: .oppositePlayer, entityManager: entityManager)
entityManager.add(ownTeam)
entityManager.add(oppositeTeam)
}

// TODO: Move contact handling to a system
func contactDidBegin(between idA: UUID, and idB: UUID) {
Expand Down
30 changes: 27 additions & 3 deletions TowerForge/TowerForge/Grid.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ class Grid: UnitSelectionNodeDelegate {

private var entityManager: EntityManager
private var noOfRows: Int
private var width: CGFloat
private var height: CGFloat

init(entityManager: EntityManager) {
init(entityManager: EntityManager, screenSize: CGRect) {
self.entityManager = entityManager
self.noOfRows = DEFAULT_NO_OF_ROWS
self.width = screenSize.width
self.height = screenSize.height
}

func unitSelectionNodeDidSpawn<T: TFEntity & PlayerSpawnable>(ofType type: T.Type, position: CGPoint) {
Expand All @@ -24,6 +28,26 @@ class Grid: UnitSelectionNodeDelegate {
entityManager.add(unit)
}

func generateTileMap(scene: SKScene) {
let screenWidth = self.width
let screenHeight = self.height
let tileSize = CGSize(width: screenHeight / CGFloat(noOfRows), height: screenHeight / CGFloat(noOfRows))

// Calculate the number of columns needed to cover the screen width
let numberOfColumns = Int(ceil(screenWidth / tileSize.width))

for row in 0..<noOfRows {
for col in 0..<numberOfColumns {
let node = TFSpriteNode(imageName: "road-tile", height: tileSize.height, width: tileSize.width)
node.anchorPoint = CGPoint(x: 0, y: 0)
node.position = CGPoint(x: CGFloat(CGFloat(col) * tileSize.width),
y: CGFloat(CGFloat(row) * tileSize.height))
node.zPosition = -100
scene.addChild(node)
}
}
}

private func snapYPosition(yPosition: Double) -> Double {
let normalizedYPosition = normalizeYPosition(yPosition: yPosition)
let screenHeight = Double(UIScreen.main.bounds.height)
Expand All @@ -34,10 +58,10 @@ class Grid: UnitSelectionNodeDelegate {
}

private func normalizeYPosition(yPosition: Double) -> Double {
yPosition + UIScreen.main.bounds.height / 2
yPosition
}

private func denormalizeYPosition(yPosition: Double) -> Double {
yPosition - UIScreen.main.bounds.height / 2
yPosition
}
}
19 changes: 16 additions & 3 deletions TowerForge/TowerForge/LevelManager/Components/AiComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import Foundation
import UIKit

class AiComponent: TFComponent {
private var entityManager: EntityManager
Expand All @@ -17,10 +18,22 @@ class AiComponent: TFComponent {
}

override func update(deltaTime: TimeInterval) {
guard let homeComponent = entity?.component(ofType: HomeComponent.self), let chosenUnit = chosenUnit else {
guard let homeComponent = entity?.component(ofType: HomeComponent.self),
let chosenUnit = chosenUnit else {
return
}
let unit = UnitGenerator.spawn(ofType: chosenUnit, at: CGPoint(x: 0, y: 10), player: .oppositePlayer)
entityManager.add(unit)
let randomY = CGFloat.random(in: 0...UIScreen.main.bounds.height)

if homeComponent.points >= chosenUnit.cost {
let unit = UnitGenerator.spawn(ofType: chosenUnit,
at: CGPoint(x: UIScreen.main.bounds.width,
y: randomY),
player: .oppositePlayer)
homeComponent.decreasePoints(chosenUnit.cost)

// Re-randomize the unit
self.chosenUnit = SpawnableEntities.playerSpawnableEntities.randomElement()
entityManager.add(unit)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ class ShootingComponent: TFComponent {
}

lastShotTime = CACurrentMediaTime()
return SpawnEvent(ofType: Arrow.self, timestamp: lastShotTime, position: positionA, team: Team(player: playerA))
return SpawnEvent(ofType: Arrow.self, timestamp: lastShotTime, position: positionA, player: playerA)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class HomeComponent: TFComponent {
var points = 0
private var lastPointIncrease = TimeInterval(0)
private var pointInterval: TimeInterval
private var pointsPerInterval: Int = 10
private var pointsPerInterval: Int = 1
init(initialLifeCount: Int, pointInterval: TimeInterval) {
self.lifeLeft = initialLifeCount
self.pointInterval = pointInterval
Expand All @@ -27,6 +27,12 @@ class HomeComponent: TFComponent {
self.lifeLeft += 1
return self.lifeLeft
}
func decreasePoints(_ amount: Int) {
self.points -= amount
}
func increasePoints(_ amount: Int) {
self.points += amount
}
override func update(deltaTime: TimeInterval) {
super.update(deltaTime: deltaTime)
// Points update
Expand Down
4 changes: 2 additions & 2 deletions TowerForge/TowerForge/LevelManager/Entities/Arrow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ class Arrow: BaseProjectile, Spawnable {
static let attackRate = 1.0
static let velocity = CGVector(dx: 100, dy: 0)

required init(position: CGPoint, team: Team) {
required init(position: CGPoint, player: Player) {
super.init(textureNames: Arrow.textureNames,
size: Arrow.size,
key: Arrow.key,
position: position,
team: team,
player: player,
velocity: Arrow.velocity)
self.addComponent(DamageComponent(attackRate: Arrow.attackRate,
attackPower: Arrow.damage,
Expand Down
4 changes: 2 additions & 2 deletions TowerForge/TowerForge/LevelManager/Entities/ArrowTower.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ class ArrowTower: BaseTower, PlayerSpawnable {
static var cost = 10
static let fireRate = 1.0

required init(position: CGPoint, team: Team) {
required init(position: CGPoint, player: Player) {
super.init(textureNames: ArrowTower.textureNames,
size: ArrowTower.size,
key: ArrowTower.key,
position: position,
maxHealth: ArrowTower.maxHealth,
team: team)
player: player)
self.addComponent(ShootingComponent(fireRate: ArrowTower.fireRate,
range: 1.0,
attackPower: ArrowTower.damage))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
import Foundation

class BaseProjectile: TFEntity {
init(textureNames: [String], size: CGSize, key: String, position: CGPoint, team: Team, velocity: CGVector = .zero) {
init(textureNames: [String], size: CGSize, key: String, position: CGPoint, player: Player, velocity: CGVector = .zero) {
super.init()

createSpriteComponent(textureNames: textureNames, size: size, key: key, position: position)
createMovableComponent(position: position, velocity: velocity)
createPositionComponent(position: position)
createPlayerComponent(team: team)
createPlayerComponent(player: player)
}

private func createSpriteComponent(textureNames: [String], size: CGSize, key: String, position: CGPoint) {
Expand All @@ -36,8 +36,8 @@ class BaseProjectile: TFEntity {
self.addComponent(movableComponent)
}

private func createPlayerComponent(team: Team) {
let playerComponent = PlayerComponent(player: team.player)
private func createPlayerComponent(player: Player) {
let playerComponent = PlayerComponent(player: player)
self.addComponent(playerComponent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ class BaseTower: TFEntity {
key: String,
position: CGPoint,
maxHealth: CGFloat,
team: Team) {
player: Player) {
super.init()

createHealthComponent(maxHealth: maxHealth)
createSpriteComponent(textureNames: textureNames, size: size, key: key, position: position)
createPositionComponent(position: position)
createPlayerComponent(team: team)
createPlayerComponent(player: player)
}

override func collide(with other: any Collidable) -> TFEvent? {
Expand Down Expand Up @@ -60,8 +60,8 @@ class BaseTower: TFEntity {
self.addComponent(spriteComponent)
}

private func createPlayerComponent(team: Team) {
let playerComponent = PlayerComponent(player: team.player)
private func createPlayerComponent(player: Player) {
let playerComponent = PlayerComponent(player: player)
self.addComponent(playerComponent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ class BaseUnit: TFEntity {
position: CGPoint,
maxHealth: CGFloat,
velocity: CGVector,
team: Team) {
player: Player) {
super.init()
createPlayerComponent(player: player)
createHealthComponent(maxHealth: maxHealth)
createSpriteComponent(textureNames: textureNames, size: size, key: key, position: position)
createMovableComponent(position: position, velocity: velocity)
createPositionComponent(position: position)
createPlayerComponent(team: team)
}

override func collide(with other: any Collidable) -> TFEvent? {
Expand Down Expand Up @@ -67,8 +67,8 @@ class BaseUnit: TFEntity {
self.addComponent(movableComponent)
}

private func createPlayerComponent(team: Team) {
let playerComponent = PlayerComponent(player: team.player)
private func createPlayerComponent(player: Player) {
let playerComponent = PlayerComponent(player: player)
self.addComponent(playerComponent)
}
}
Loading

0 comments on commit 14108b3

Please sign in to comment.