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

Update SpawnEvent and Add ShootingSystem #24

Merged
merged 8 commits into from
Mar 22, 2024
28 changes: 20 additions & 8 deletions TowerForge/TowerForge.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
3C9955A52BA47DC600D33FA5 /* BaseProjectile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9955A42BA47DC600D33FA5 /* BaseProjectile.swift */; };
3C9955AD2BA483B100D33FA5 /* TFSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9955AC2BA483B100D33FA5 /* TFSystem.swift */; };
3C9955AF2BA48FD200D33FA5 /* MeleeUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9955AE2BA48FD200D33FA5 /* MeleeUnit.swift */; };
3C9955B12BA4ACA100D33FA5 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9955B02BA4ACA100D33FA5 /* Arrow.swift */; };
3C9955B12BA4ACA100D33FA5 /* Bullet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9955B02BA4ACA100D33FA5 /* Bullet.swift */; };
3C9955B42BA4B12000D33FA5 /* ArrowTower.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9955B32BA4B12000D33FA5 /* ArrowTower.swift */; };
3C9955BA2BA5637200D33FA5 /* DamageEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9955B92BA5637200D33FA5 /* DamageEvent.swift */; };
3C9955BC2BA563A800D33FA5 /* TFEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9955BB2BA563A800D33FA5 /* TFEvent.swift */; };
Expand All @@ -34,9 +34,12 @@
3CE951512BAC8955008B2785 /* Renderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CE951502BAC8955008B2785 /* Renderable.swift */; };
3CE951562BACA0CF008B2785 /* Collidable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CE951552BACA0CF008B2785 /* Collidable.swift */; };
3CE951582BAD724D008B2785 /* TFContact.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CE951572BAD724D008B2785 /* TFContact.swift */; };
3CE9515F2BADE2C5008B2785 /* ShootingSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CE9515E2BADE2C5008B2785 /* ShootingSystem.swift */; };
3CE951612BADE881008B2785 /* Spawnable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CE951602BADE881008B2785 /* Spawnable.swift */; };
3CE951632BAE037C008B2785 /* AiSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CE951622BAE037C008B2785 /* AiSystem.swift */; };
5200624E2BA8D597000DBA30 /* AiComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5200624D2BA8D597000DBA30 /* AiComponent.swift */; };
520062522BA8DA09000DBA30 /* UnitGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520062512BA8DA09000DBA30 /* UnitGenerator.swift */; };
520062562BA8E026000DBA30 /* Spawnable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520062552BA8E026000DBA30 /* Spawnable.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 */; };
Expand Down Expand Up @@ -104,7 +107,7 @@
3C9955A42BA47DC600D33FA5 /* BaseProjectile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseProjectile.swift; sourceTree = "<group>"; };
3C9955AC2BA483B100D33FA5 /* TFSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TFSystem.swift; sourceTree = "<group>"; };
3C9955AE2BA48FD200D33FA5 /* MeleeUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeleeUnit.swift; sourceTree = "<group>"; };
3C9955B02BA4ACA100D33FA5 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = "<group>"; };
3C9955B02BA4ACA100D33FA5 /* Bullet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bullet.swift; sourceTree = "<group>"; };
3C9955B32BA4B12000D33FA5 /* ArrowTower.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowTower.swift; sourceTree = "<group>"; };
3C9955B92BA5637200D33FA5 /* DamageEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamageEvent.swift; sourceTree = "<group>"; };
3C9955BB2BA563A800D33FA5 /* TFEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TFEvent.swift; sourceTree = "<group>"; };
Expand All @@ -124,9 +127,12 @@
3CE951502BAC8955008B2785 /* Renderable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Renderable.swift; sourceTree = "<group>"; };
3CE951552BACA0CF008B2785 /* Collidable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Collidable.swift; sourceTree = "<group>"; };
3CE951572BAD724D008B2785 /* TFContact.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TFContact.swift; sourceTree = "<group>"; };
3CE9515E2BADE2C5008B2785 /* ShootingSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShootingSystem.swift; sourceTree = "<group>"; };
3CE951602BADE881008B2785 /* Spawnable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Spawnable.swift; sourceTree = "<group>"; };
3CE951622BAE037C008B2785 /* AiSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AiSystem.swift; sourceTree = "<group>"; };
5200624D2BA8D597000DBA30 /* AiComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AiComponent.swift; sourceTree = "<group>"; };
520062512BA8DA09000DBA30 /* UnitGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitGenerator.swift; sourceTree = "<group>"; };
520062552BA8E026000DBA30 /* Spawnable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Spawnable.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>"; };
Expand Down Expand Up @@ -203,7 +209,7 @@
children = (
3CE9514C2BAC8668008B2785 /* Base Entities */,
3C9955AE2BA48FD200D33FA5 /* MeleeUnit.swift */,
3C9955B02BA4ACA100D33FA5 /* Arrow.swift */,
3C9955B02BA4ACA100D33FA5 /* Bullet.swift */,
3C9955B32BA4B12000D33FA5 /* ArrowTower.swift */,
52578B8B2BA627B200B4D76C /* Team.swift */,
529F91872BA6D7A7009551D9 /* SoldierUnit.swift */,
Expand Down Expand Up @@ -232,6 +238,8 @@
3C769A712BA58DE700F454F9 /* MovementSystem.swift */,
3C769A732BA591BD00F454F9 /* SpawnSystem.swift */,
BA443D3C2BAD9557009F0FFB /* RemoveSystem.swift */,
3CE9515E2BADE2C5008B2785 /* ShootingSystem.swift */,
3CE951622BAE037C008B2785 /* AiSystem.swift */,
);
path = Systems;
sourceTree = "<group>";
Expand Down Expand Up @@ -435,7 +443,8 @@
isa = PBXGroup;
children = (
52DF5FE82BA33F9700135367 /* Animatable.swift */,
520062552BA8E026000DBA30 /* Spawnable.swift */,
520062552BA8E026000DBA30 /* PlayerSpawnable.swift */,
3CE951602BADE881008B2785 /* Spawnable.swift */,
);
path = Protocols;
sourceTree = "<group>";
Expand Down Expand Up @@ -642,6 +651,8 @@
52578B822BA61AAF00B4D76C /* PositionComponent.swift in Sources */,
3C9955A32BA47DBB00D33FA5 /* BaseUnit.swift in Sources */,
3C9955BA2BA5637200D33FA5 /* DamageEvent.swift in Sources */,
3CE951632BAE037C008B2785 /* AiSystem.swift in Sources */,
3CE9515F2BADE2C5008B2785 /* ShootingSystem.swift in Sources */,
3C9955CA2BA5888F00D33FA5 /* SpawnEvent.swift in Sources */,
3CE951582BAD724D008B2785 /* TFContact.swift in Sources */,
5295A2132BAAEA16005018A8 /* UnitNode.swift in Sources */,
Expand All @@ -664,14 +675,15 @@
3CE951562BACA0CF008B2785 /* Collidable.swift in Sources */,
52DF5FE62BA33AF300135367 /* TFSpriteNode.swift in Sources */,
3C9955B42BA4B12000D33FA5 /* ArrowTower.swift in Sources */,
3CE951612BADE881008B2785 /* Spawnable.swift in Sources */,
52DF5FE92BA33F9700135367 /* Animatable.swift in Sources */,
3C9955AF2BA48FD200D33FA5 /* MeleeUnit.swift in Sources */,
5295A2022BA9FBD9005018A8 /* SceneManagerDelegate.swift in Sources */,
52DF5FE12BA3349600135367 /* TFTextures.swift in Sources */,
520062582BA8ED73000DBA30 /* HomeComponent.swift in Sources */,
52DF5FA82BA32B2300135367 /* AppDelegate.swift in Sources */,
3C769A742BA591BD00F454F9 /* SpawnSystem.swift in Sources */,
3C9955B12BA4ACA100D33FA5 /* Arrow.swift in Sources */,
3C9955B12BA4ACA100D33FA5 /* Bullet.swift in Sources */,
3CE9514F2BAC8936008B2785 /* Renderer.swift in Sources */,
3C769A722BA58DE700F454F9 /* MovementSystem.swift in Sources */,
52DF5FEB2BA3400C00135367 /* TFAnimatableNode.swift in Sources */,
Expand All @@ -680,7 +692,7 @@
52DF5FED2BA34D0300135367 /* TFComponent.swift in Sources */,
527E3A242BA613F000FE1628 /* PlayerComponent.swift in Sources */,
3C9955C52BA585DD00D33FA5 /* HealthSystem.swift in Sources */,
520062562BA8E026000DBA30 /* Spawnable.swift in Sources */,
520062562BA8E026000DBA30 /* PlayerSpawnable.swift in Sources */,
52DF5FFB2BA3601400135367 /* HealthComponent.swift in Sources */,
3C9955BC2BA563A800D33FA5 /* TFEvent.swift in Sources */,
BA443D3F2BAD9774009F0FFB /* RemoveEvent.swift in Sources */,
Expand Down
11 changes: 10 additions & 1 deletion TowerForge/TowerForge/GameWorld.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class GameWorld {
}
renderer = Renderer(target: self, scene: scene)

self.setUpSystems()
self.setUpSelectionNode()
self.setupTeam()
}
Expand All @@ -40,7 +41,6 @@ class GameWorld {

systemManager.update(deltaTime)
eventManager.executeEvents(in: self)
entityManager.update(deltaTime)
renderer?.render()
}

Expand Down Expand Up @@ -91,6 +91,15 @@ class GameWorld {
// TODO: Handle any separation logic here.
}

private func setUpSystems() {
systemManager.add(system: HealthSystem(entityManager: entityManager, eventManager: eventManager))
systemManager.add(system: MovementSystem(entityManager: entityManager, eventManager: eventManager))
systemManager.add(system: RemoveSystem(entityManager: entityManager, eventManager: eventManager))
systemManager.add(system: SpawnSystem(entityManager: entityManager, eventManager: eventManager))
systemManager.add(system: ShootingSystem(entityManager: entityManager, eventManager: eventManager))
systemManager.add(system: AiSystem(entityManager: entityManager, eventManager: eventManager))
}

private func setUpSelectionNode() {
selectionNode.delegate = grid
scene?.addChild(selectionNode)
Expand Down
14 changes: 6 additions & 8 deletions TowerForge/TowerForge/Grid.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ class Grid: UnitSelectionNodeDelegate {
self.height = screenSize.height
}

func unitSelectionNodeDidSpawn<T: TFEntity & PlayerSpawnable>(ofType type: T.Type, position: CGPoint) {
let snapPosition = CGPoint(x: position.x, y: snapYPosition(yPosition: position.y))
let unit = UnitGenerator.spawn(ofType: type, at: snapPosition, player: Player.ownPlayer)
entityManager.add(unit)
}

func generateTileMap(scene: SKScene) {
let screenWidth = self.width
let screenHeight = self.height
Expand All @@ -41,14 +47,6 @@ class Grid: UnitSelectionNodeDelegate {
}
}
}
func unitSelectionNodeDidSpawn<T: BaseUnit & Spawnable>(ofType type: T.Type, position: CGPoint) {
let snapPosition = CGPoint(x: position.x, y: snapYPosition(yPosition: position.y))
let unit = UnitGenerator.spawn(ofType: type,
at: snapPosition,
player: Player.ownPlayer,
entityManager: entityManager)
entityManager.add(unit)
}

private func snapYPosition(yPosition: Double) -> Double {
let normalizedYPosition = normalizeYPosition(yPosition: yPosition)
Expand Down
11 changes: 4 additions & 7 deletions TowerForge/TowerForge/LevelManager/Components/AiComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import UIKit

class AiComponent: TFComponent {
private var entityManager: EntityManager
private var chosenUnit: (BaseUnit & Spawnable).Type?
private var chosenUnit: (TFEntity & PlayerSpawnable).Type?
init(entityManager: EntityManager) {
self.entityManager = entityManager
self.chosenUnit = SpawnableEntities.possibleUnits.randomElement()
self.chosenUnit = SpawnableEntities.playerSpawnableEntities.randomElement()
super.init()
}

Expand All @@ -22,20 +22,17 @@ class AiComponent: TFComponent {
let chosenUnit = chosenUnit else {
return
}

// Generate random coordinates within the defined range
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,
entityManager: entityManager)
player: .oppositePlayer)
homeComponent.decreasePoints(chosenUnit.cost)

// Re-randomize the unit
self.chosenUnit = SpawnableEntities.possibleUnits.randomElement()
self.chosenUnit = SpawnableEntities.playerSpawnableEntities.randomElement()
entityManager.add(unit)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@
//

import Foundation
import CoreGraphics
import SpriteKit

class DamageComponent: TFComponent {
private let attackRate: TimeInterval
private var lastAttackTime = TimeInterval(0)
private let entityManager: EntityManager
private let temporary: Bool
let attackPower: CGFloat

init(attackRate: TimeInterval, attackPower: CGFloat, temporary: Bool, entityManager: EntityManager) {
init(attackRate: TimeInterval, attackPower: CGFloat, temporary: Bool) {
self.attackRate = attackRate
self.attackPower = attackPower
self.entityManager = entityManager
self.temporary = temporary
super.init()
}
Expand All @@ -28,8 +25,8 @@ class DamageComponent: TFComponent {
CACurrentMediaTime() - lastAttackTime >= attackRate
}

func damage(_ healthComponent: HealthComponent) -> DamageEvent? {
guard canDamage, let entityId = healthComponent.entity?.id else {
func damage(_ healthComponent: HealthComponent) -> TFEvent? {
guard canDamage, let enemyId = healthComponent.entity?.id, let id = entity?.id else {
return nil
}

Expand All @@ -40,6 +37,11 @@ class DamageComponent: TFComponent {
}

lastAttackTime = CACurrentMediaTime()
return DamageEvent(on: entityId, at: lastAttackTime, with: attackPower)
let event = DamageEvent(on: enemyId, at: lastAttackTime, with: attackPower)

if temporary {
return event.concurrentlyWith(RemoveEvent(on: id, at: lastAttackTime))
}
return event
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,16 @@ import Foundation
class HealthComponent: TFComponent {
var currentHealth: CGFloat
var maxHealth: CGFloat
private let entityManager: EntityManager
var isZero: Bool {
currentHealth.isZero
}

init(maxHealth: CGFloat, entityManager: EntityManager) {
init(maxHealth: CGFloat) {
self.currentHealth = maxHealth
self.maxHealth = maxHealth
self.entityManager = entityManager
super.init()
}

override func update(deltaTime: TimeInterval) {
if self.currentHealth <= 0 {
guard let entity = entity,
let spriteComponent = entity.component(ofType: SpriteComponent.self) else {
return
}
// Need to remove the entity entirely if the health goes to zero or less
self.entityManager.removeEntity(with: entity.id)
}
}

/// Adjusts health by the specified amount.
func adjustHealth(amount: CGFloat) {
if amount < 0 {
Expand Down
Loading