Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Systems Component [with merge conflicts resolved] #22

Merged
merged 5 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions TowerForge/TowerForge.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
52DF5FFB2BA3601400135367 /* HealthComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52DF5FFA2BA3601400135367 /* HealthComponent.swift */; };
52DF5FFF2BA3656500135367 /* ShootingComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52DF5FFE2BA3656500135367 /* ShootingComponent.swift */; };
9B8696552BAD759F0002377C /* Grid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B8696542BAD759F0002377C /* Grid.swift */; };
BA443D3D2BAD9557009F0FFB /* RemoveSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA443D3C2BAD9557009F0FFB /* RemoveSystem.swift */; };
BA443D3F2BAD9774009F0FFB /* RemoveEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA443D3E2BAD9774009F0FFB /* RemoveEvent.swift */; };
BA443D422BAD9885009F0FFB /* DamageEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA443D412BAD9885009F0FFB /* DamageEventTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -162,6 +165,9 @@
52DF5FFA2BA3601400135367 /* HealthComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthComponent.swift; sourceTree = "<group>"; };
52DF5FFE2BA3656500135367 /* ShootingComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShootingComponent.swift; sourceTree = "<group>"; };
9B8696542BAD759F0002377C /* Grid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Grid.swift; sourceTree = "<group>"; };
BA443D3C2BAD9557009F0FFB /* RemoveSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveSystem.swift; sourceTree = "<group>"; };
BA443D3E2BAD9774009F0FFB /* RemoveEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveEvent.swift; sourceTree = "<group>"; };
BA443D412BAD9885009F0FFB /* DamageEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamageEventTests.swift; sourceTree = "<group>"; };
BABB7C052BA9A41000D54DAE /* TowerForceTestPlan.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = TowerForceTestPlan.xctestplan; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -219,9 +225,11 @@
3C9955C32BA585CD00D33FA5 /* Systems */ = {
isa = PBXGroup;
children = (
3C9955AC2BA483B100D33FA5 /* TFSystem.swift */,
3C9955C42BA585DD00D33FA5 /* HealthSystem.swift */,
3C769A712BA58DE700F454F9 /* MovementSystem.swift */,
3C769A732BA591BD00F454F9 /* SpawnSystem.swift */,
BA443D3C2BAD9557009F0FFB /* RemoveSystem.swift */,
);
path = Systems;
sourceTree = "<group>";
Expand All @@ -233,6 +241,7 @@
3C9955C92BA5888F00D33FA5 /* SpawnEvent.swift */,
3C9955CB2BA5889800D33FA5 /* MoveEvent.swift */,
3C9955C72BA5865C00D33FA5 /* ConcurrentEvent.swift */,
BA443D3E2BAD9774009F0FFB /* RemoveEvent.swift */,
);
path = "Implemented Events";
sourceTree = "<group>";
Expand Down Expand Up @@ -296,6 +305,7 @@
5295A2002BA9FB97005018A8 /* Scenes */ = {
isa = PBXGroup;
children = (
52DF5FAB2BA32B2300135367 /* Actions.sks */,
52DF5FA92BA32B2300135367 /* GameScene.sks */,
52DF5FAD2BA32B2300135367 /* GameScene.swift */,
5295A2032BA9FED4005018A8 /* MenuScene.swift */,
Expand Down Expand Up @@ -346,6 +356,8 @@
52DF5FA62BA32B2300135367 /* TowerForge */ = {
isa = PBXGroup;
children = (
52DF5FB42BA32B2600135367 /* Assets.xcassets */,
BA443D432BAD98CD009F0FFB /* AppMain */,
3CE9514D2BAC8925008B2785 /* Rendering */,
5295A2082BAAE14B005018A8 /* Controllers */,
5295A2052BAA0208005018A8 /* Nodes */,
Expand All @@ -355,12 +367,7 @@
3CCF9CAE2BAB1A96004D170E /* SceneUpdateDelegate.swift */,
5295A2012BA9FBD9005018A8 /* SceneManagerDelegate.swift */,
52DF5FDB2BA32CEF00135367 /* LevelManager */,
52DF5FA72BA32B2300135367 /* AppDelegate.swift */,
52DF5FAB2BA32B2300135367 /* Actions.sks */,
3CCF9CB02BAB1BCE004D170E /* GameWorld.swift */,
52DF5FB12BA32B2300135367 /* Main.storyboard */,
52DF5FB42BA32B2600135367 /* Assets.xcassets */,
52DF5FB62BA32B2600135367 /* LaunchScreen.storyboard */,
9B8696542BAD759F0002377C /* Grid.swift */,
);
path = TowerForge;
Expand All @@ -369,6 +376,7 @@
52DF5FC02BA32B2600135367 /* TowerForgeTests */ = {
isa = PBXGroup;
children = (
BA443D402BAD9872009F0FFB /* EventTests */,
52DF5FE22BA3386400135367 /* TFCoreTests */,
52DF5FC12BA32B2600135367 /* TowerForgeTests.swift */,
);
Expand Down Expand Up @@ -396,7 +404,6 @@
52DF5FDD2BA32D7E00135367 /* EntityManager.swift */,
3CCF9CB22BAB1F42004D170E /* SystemManager.swift */,
52DF5FEC2BA34D0300135367 /* TFComponent.swift */,
3C9955AC2BA483B100D33FA5 /* TFSystem.swift */,
52DF5FEE2BA34EA000135367 /* TFEntity.swift */,
);
path = LevelManager;
Expand Down Expand Up @@ -442,6 +449,24 @@
path = Components;
sourceTree = "<group>";
};
BA443D402BAD9872009F0FFB /* EventTests */ = {
isa = PBXGroup;
children = (
BA443D412BAD9885009F0FFB /* DamageEventTests.swift */,
);
path = EventTests;
sourceTree = "<group>";
};
BA443D432BAD98CD009F0FFB /* AppMain */ = {
isa = PBXGroup;
children = (
52DF5FB12BA32B2300135367 /* Main.storyboard */,
52DF5FB62BA32B2600135367 /* LaunchScreen.storyboard */,
52DF5FA72BA32B2300135367 /* AppDelegate.swift */,
);
path = AppMain;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -605,6 +630,7 @@
52578B8C2BA627B200B4D76C /* Team.swift in Sources */,
3CCF9CB72BAB2877004D170E /* MainMenuViewController.swift in Sources */,
52DF5FFF2BA3656500135367 /* ShootingComponent.swift in Sources */,
BA443D3D2BAD9557009F0FFB /* RemoveSystem.swift in Sources */,
3C9955CC2BA5889800D33FA5 /* MoveEvent.swift in Sources */,
5200624E2BA8D597000DBA30 /* AiComponent.swift in Sources */,
3C9955C22BA5838900D33FA5 /* EventOutput.swift in Sources */,
Expand Down Expand Up @@ -653,6 +679,7 @@
520062562BA8E026000DBA30 /* Spawnable.swift in Sources */,
52DF5FFB2BA3601400135367 /* HealthComponent.swift in Sources */,
3C9955BC2BA563A800D33FA5 /* TFEvent.swift in Sources */,
BA443D3F2BAD9774009F0FFB /* RemoveEvent.swift in Sources */,
5295A2072BAA02FD005018A8 /* TFButton.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -663,6 +690,7 @@
files = (
52DF5FC22BA32B2600135367 /* TowerForgeTests.swift in Sources */,
52DF5FE42BA3391200135367 /* TFTexturesTests.swift in Sources */,
BA443D422BAD9885009F0FFB /* DamageEventTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ class MovableComponent: TFComponent {
super.init()
}

func updatePosition(to position: CGPoint) {
self.position = position
}

func updatePosition(with vector: CGVector) {
self.position.x += vector.dx
self.position.y += vector.dy
}

override func update(deltaTime: TimeInterval) {
guard let entity = entity,
let positionComponent = entity.component(ofType: PositionComponent.self),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class HealthComponent: TFComponent {
var currentHealth: CGFloat
var maxHealth: CGFloat
private let entityManager: EntityManager
var isZero: Bool {
currentHealth.isZero
}

init(maxHealth: CGFloat, entityManager: EntityManager) {
self.currentHealth = maxHealth
Expand All @@ -30,10 +33,21 @@ class HealthComponent: TFComponent {
}
}

/// Adjusts health by the specified amount.
func adjustHealth(amount: CGFloat) {
if amount < 0 {
decreaseHealth(amount: abs(amount))
} else {
increaseHealth(amount: amount)
}
}

/// Decreases currentHealth by the specified amount with a floor of 0.
func decreaseHealth(amount: CGFloat) {
self.currentHealth -= amount
self.currentHealth = max(self.currentHealth - amount, 0)
}

/// Increases currentHealth by the specific amount with a ceiling of maxHealth
func increaseHealth(amount: CGFloat) {
self.currentHealth = min(self.currentHealth + amount, self.maxHealth)
}
Expand Down
5 changes: 3 additions & 2 deletions TowerForge/TowerForge/LevelManager/Events/EventManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ class EventManager {
while !eventQueue.isEmpty {
let currentEvent = eventQueue.removeFirst()

let output = currentEvent.execute(in: target)
output.events.forEach { eventQueue.append($0) }
if let output = currentEvent.execute(in: target) {
output.events.forEach { eventQueue.append($0) }
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@ struct ConcurrentEvent: TFEvent {
self.event2 = event2
}

func execute(in target: any EventTarget) -> EventOutput {
var eventOutput = event1.execute(in: target)
let eventOutput2 = event2.execute(in: target)
eventOutput.combine(with: eventOutput2)
func execute(in target: any EventTarget) -> EventOutput? {
guard var eventOutput = event1.execute(in: target) else {
return nil
}

guard let eventOutput2 = event2.execute(in: target) else {
return eventOutput
}

eventOutput.combine(with: eventOutput2)
return eventOutput
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,17 @@ struct DamageEvent: TFEvent {
self.damage = damage
}

func execute(in target: any EventTarget) -> EventOutput {
target.system(ofType: HealthSystem.self) // TODO: Handle Damge Event
func execute(in target: any EventTarget) -> EventOutput? {
guard let healthSystem = target.system(ofType: HealthSystem.self) else {
return nil
}
let healthIsZero = healthSystem.modifyHealth(for: entityId, with: damage)
if healthIsZero {
var newEventOutput = EventOutput()
newEventOutput.add(RemoveEvent(on: entityId, at: timestamp))
return newEventOutput
}

return EventOutput()
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
//
// MoveEvent.swift
// TowerForge
//
// Created by Zheng Ze on 16/3/24.
//

import Foundation

struct MoveEvent: TFEvent {
Expand All @@ -18,8 +11,11 @@ struct MoveEvent: TFEvent {
self.displacement = displacement
}

func execute(in target: any EventTarget) -> EventOutput {
target.system(ofType: MovementSystem.self) // TODO: Handle Move Event
func execute(in target: any EventTarget) -> EventOutput? {
guard let movementSystem = target.system(ofType: MovementSystem.self) else {
return nil
}
movementSystem.handleMovement(for: entityId, with: displacement)
return EventOutput()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Foundation

struct RemoveEvent: TFEvent {
let timestamp: TimeInterval
let entityId: UUID

init(on entityId: UUID, at timestamp: TimeInterval) {
self.timestamp = timestamp
self.entityId = entityId
}

func execute(in target: any EventTarget) -> EventOutput? {
guard let removeSystem = target.system(ofType: RemoveSystem.self) else {
return nil
}

removeSystem.handleRemove(for: entityId)
return EventOutput()
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
//
// SpawnEvent.swift
// TowerForge
//
// Created by Zheng Ze on 16/3/24.
//

import Foundation

struct SpawnEvent<T: TFEntity>: TFEvent {
struct SpawnEvent: TFEvent {
let timestamp: TimeInterval
let entityId: UUID

Expand All @@ -21,8 +14,13 @@ struct SpawnEvent<T: TFEntity>: TFEvent {
self.velocity = velocity
}

func execute(in target: any EventTarget) -> EventOutput {
target.system(ofType: SpawnSystem.self) // TODO: Handle Spawn Event
func execute(in target: any EventTarget) -> EventOutput? {
guard let spawnSystem = target.system(ofType: SpawnSystem.self) else {
return nil
}
var entity = TFEntity()
entity.addComponent(MovableComponent(position: position, velocity: velocity))
spawnSystem.handleSpawn(with: entity)
return EventOutput()
}
}
4 changes: 3 additions & 1 deletion TowerForge/TowerForge/LevelManager/Events/TFEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ protocol TFEvent {
var timestamp: TimeInterval { get }
var entityId: UUID { get }

func execute(in target: EventTarget) -> EventOutput
/// Execute method returns an optional EventOutput as not all event executions
/// will return an EventOutput
func execute(in target: EventTarget) -> EventOutput?
}

extension TFEvent {
Expand Down
32 changes: 25 additions & 7 deletions TowerForge/TowerForge/LevelManager/Systems/HealthSystem.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
//
// HealthSystem.swift
// TowerForge
//
// Created by Zheng Ze on 16/3/24.
//

import Foundation

class HealthSystem: TFSystem {
var isActive = false
weak var entityManager: EntityManager?
weak var eventManager: EventManager?

init(entityManager: EntityManager, eventManager: EventManager) {
self.entityManager = entityManager
self.eventManager = eventManager
}

/// Modifies the health of the entity associated with the specified UUID according
/// to the provided healthpoints amount.
/// - Parameters:
/// - entityId: UUID of the entity whose health component is to be modified
/// - hp: Value of the required adjustment of health. Can be positive or negative.
func modifyHealth(for entityId: UUID, with hp: CGFloat) -> Bool {
/*guard isActive else { TODO: Implement boolean check
return
}*/
guard let currentEntity = entityManager?.entity(with: entityId),
let healthComponent = currentEntity.component(ofType: HealthComponent.self) else {
return false
}

healthComponent.adjustHealth(amount: hp)
return healthComponent.isZero
}
}
Loading