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 point update and health bar #27

Merged
merged 20 commits into from
Mar 23, 2024
8 changes: 8 additions & 0 deletions TowerForge/TowerForge.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
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 */; };
5240D08F2BAE6D0A004F1486 /* Point.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5240D08E2BAE6D0A004F1486 /* Point.swift */; };
5250B42F2BAE0DB000F16CF6 /* LabelComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5250B42E2BAE0DB000F16CF6 /* LabelComponent.swift */; };
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 @@ -135,6 +137,8 @@
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>"; };
5240D08E2BAE6D0A004F1486 /* Point.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Point.swift; sourceTree = "<group>"; };
5250B42E2BAE0DB000F16CF6 /* LabelComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelComponent.swift; 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 @@ -214,6 +218,7 @@
52578B8B2BA627B200B4D76C /* Team.swift */,
529F91872BA6D7A7009551D9 /* SoldierUnit.swift */,
3CE9514A2BAC83FA008B2785 /* SpawnableEntities.swift */,
5240D08E2BAE6D0A004F1486 /* Point.swift */,
);
path = Entities;
sourceTree = "<group>";
Expand Down Expand Up @@ -308,6 +313,7 @@
52DF5FF22BA351E100135367 /* SpriteComponent.swift */,
52DF5FF82BA35D2B00135367 /* MovableComponent.swift */,
52578B812BA61AAF00B4D76C /* PositionComponent.swift */,
5250B42E2BAE0DB000F16CF6 /* LabelComponent.swift */,
);
path = BaseComponents;
sourceTree = "<group>";
Expand Down Expand Up @@ -637,6 +643,7 @@
files = (
3CCF9CAF2BAB1A96004D170E /* SceneUpdateDelegate.swift in Sources */,
3C9955A12BA47DA500D33FA5 /* BaseTower.swift in Sources */,
5250B42F2BAE0DB000F16CF6 /* LabelComponent.swift in Sources */,
3CCF9CB32BAB1F42004D170E /* SystemManager.swift in Sources */,
5295A20F2BAAE7CF005018A8 /* TeamController.swift in Sources */,
3C9955A52BA47DC600D33FA5 /* BaseProjectile.swift in Sources */,
Expand Down Expand Up @@ -682,6 +689,7 @@
52DF5FE12BA3349600135367 /* TFTextures.swift in Sources */,
520062582BA8ED73000DBA30 /* HomeComponent.swift in Sources */,
52DF5FA82BA32B2300135367 /* AppDelegate.swift in Sources */,
5240D08F2BAE6D0A004F1486 /* Point.swift in Sources */,
3C769A742BA591BD00F454F9 /* SpawnSystem.swift in Sources */,
3C9955B12BA4ACA100D33FA5 /* Bullet.swift in Sources */,
3CE9514F2BAC8936008B2785 /* Renderer.swift in Sources */,
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "coin.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "life.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 6 additions & 2 deletions TowerForge/TowerForge/GameWorld.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class GameWorld {
self.setUpSystems()
self.setUpSelectionNode()
self.setupTeam()
self.setupPlayerInfo()
}

func update(deltaTime: TimeInterval) {
Expand All @@ -43,7 +44,6 @@ class GameWorld {
eventManager.executeEvents(in: self)
renderer?.render()
}

func spawnUnit(at location: CGPoint) {
selectionNode.unitNodeDidSpawn(location)
}
Expand All @@ -53,7 +53,11 @@ class GameWorld {
entityManager.add(ownTeam)
entityManager.add(oppositeTeam)
}

func setupPlayerInfo() {
let point = Point(initialPoint: 0)
entityManager.add(point)
renderer?.addNodeToScene(entity: point)
}
// TODO: Move contact handling to a system
func contactDidBegin(between idA: UUID, and idB: UUID) {
guard idA != idB, entityManager.entity(with: idA) != nil, entityManager.entity(with: idB) != nil else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// LabelComponent.swift
// TowerForge
//
// Created by Vanessa Mae on 23/03/24.
//

import Foundation
import SpriteKit

class LabelComponent: TFComponent {
var text: String
init(text: String) {
self.text = text
super.init()
}
override func didAddToEntity(_ entity: TFEntity) {
self.entity = entity
guard let spriteComponent = entity.component(ofType: SpriteComponent.self) else {
return
}
let label = SKLabelNode(text: self.text)
label.fontName = "HelveticaNeue-Bold"
label.fontSize = 60.0
label.fontColor = .white
label.horizontalAlignmentMode = .center
label.verticalAlignmentMode = .center
label.position = CGPoint(x: spriteComponent.node.width, y: 0)
label.name = "point"
spriteComponent.node.addChild(label)
zheng-ze marked this conversation as resolved.
Show resolved Hide resolved
}
func changeText(_ text: String) {
guard let spriteComponent = entity?.component(ofType: SpriteComponent.self),
let labelNode = spriteComponent.node.childNode(withName: "point") as? SKLabelNode else {
return
}
labelNode.text = text
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ import CoreGraphics

class PositionComponent: TFComponent {
var position: CGPoint
var anchorPoint: CGPoint

init(position: CGPoint) {
init(position: CGPoint, anchorPoint: CGPoint) {
self.position = position
self.anchorPoint = anchorPoint
super.init()
}

convenience init(position: CGPoint) {
self.init(position: position, anchorPoint: CGPoint(x: 0, y: 0))
}

func changeTo(to position: CGPoint) {
self.position = position
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ class SpriteComponent: TFComponent {
var height: CGFloat
var width: CGFloat
var animatableKey: String
var node: TFAnimatableNode

init(textureNames: [String], height: CGFloat, width: CGFloat, position: CGPoint, animatableKey: String) {
textures = TFTextures(textureNames: textureNames, textureAtlasName: "Sprites")
self.height = height
self.width = width
self.node = TFAnimatableNode(textures: textures, height: height, width: width, animatableKey: animatableKey)
self.animatableKey = animatableKey
super.init()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import Foundation
import SpriteKit

class HealthComponent: TFComponent {
var currentHealth: CGFloat
Expand All @@ -32,14 +33,35 @@ class HealthComponent: TFComponent {
/// Decreases currentHealth by the specified amount with a floor of 0.
func decreaseHealth(amount: CGFloat) {
self.currentHealth = max(self.currentHealth - amount, 0)
updateHealthMeter()
}

/// Increases currentHealth by the specific amount with a ceiling of maxHealth
func increaseHealth(amount: CGFloat) {
self.currentHealth = min(self.currentHealth + amount, self.maxHealth)
updateHealthMeter()
}

func restoreHealth() {
self.currentHealth = maxHealth
}
override func didAddToEntity(_ entity: TFEntity) {
super.didAddToEntity(entity)
guard let spriteComponent = entity.component(ofType: SpriteComponent.self) else {
return
}
let healthMeterNode = SKSpriteNode(color: .green, size: CGSize(width: 100, height: 10))
healthMeterNode.anchorPoint = CGPoint(x: 0, y: 0)
healthMeterNode.position = CGPoint(x: 0 - spriteComponent.node.width / 2, y: spriteComponent.node.height / 2)
healthMeterNode.name = "healthMeterNode"
spriteComponent.node.addChild(healthMeterNode)
}
func updateHealthMeter() {
guard let spriteComponent = entity?.component(ofType: SpriteComponent.self),
let healthMeterNode = spriteComponent.node.childNode(withName: "healthMeterNode") else {
return
}
let healthPercentage = currentHealth / maxHealth
healthMeterNode.xScale = healthPercentage
}
}
21 changes: 19 additions & 2 deletions TowerForge/TowerForge/LevelManager/Components/HomeComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,25 @@ import Foundation
import SpriteKit

class HomeComponent: TFComponent {
var lifeLeft: Int
var points = 0
var lifeLeft: Int {
didSet {
// Update the life left in the LabelComponent when it changes
guard let labelComponent = entity?.component(ofType: LabelComponent.self) else {
return
}
labelComponent.changeText(String(lifeLeft))
}
}
var points = 0 {
didSet {
// Update the points in the LabelComponent when it changes
guard let labelComponent = entity?.component(ofType: LabelComponent.self) else {
return
}
print(points)
labelComponent.changeText(String(points))
}
}
private var lastPointIncrease = TimeInterval(0)
private var pointInterval: TimeInterval
private var pointsPerInterval: Int = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ class BaseUnit: TFEntity {
player: Player) {
super.init()
createPlayerComponent(player: player)
createHealthComponent(maxHealth: maxHealth)
createSpriteComponent(textureNames: textureNames, size: size, key: key, position: position)
createHealthComponent(maxHealth: maxHealth)
createMovableComponent(position: position, velocity: velocity)
createPositionComponent(position: position)
}
Expand Down
22 changes: 22 additions & 0 deletions TowerForge/TowerForge/LevelManager/Entities/Point.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// Point.swift
// TowerForge
//
// Created by Vanessa Mae on 23/03/24.
//

import Foundation

class Point: TFEntity {
static let position = CGPoint(x: 100, y: 100)
init(initialPoint: Int) {
super.init()
self.addComponent(SpriteComponent(textureNames: ["Coin"],
height: 100,
width: 100,
position: Point.position, animatableKey: "point"))
self.addComponent(HomeComponent(initialLifeCount: Team.lifeCount, pointInterval: Team.pointsInterval))
self.addComponent(LabelComponent(text: String(initialPoint)))
self.addComponent(PositionComponent(position: Point.position))
}
}
2 changes: 2 additions & 0 deletions TowerForge/TowerForge/LevelManager/Entities/Team.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class Team: TFEntity {

if player == .oppositePlayer {
self.addComponent(AiComponent(entityManager: entityManager))
} else {
self.addComponent(LabelComponent(text: String(0)))
}
}
private func createHomeComponent() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ class EventManager {
func executeEvents(in target: EventTarget) {
while !eventQueue.isEmpty {
let currentEvent = eventQueue.removeFirst()
print(currentEvent)
if let output = currentEvent.execute(in: target) {
output.events.forEach { eventQueue.append($0) }
}
Expand Down
1 change: 1 addition & 0 deletions TowerForge/TowerForge/Nodes/UnitSelectionNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class UnitSelectionNode: TFSpriteNode, UnitNodeDelegate {
guard let selectedType = self.selectedNode?.type else {
return
}
self.availablePoints -= selectedType.cost
delegate?.unitSelectionNodeDidSpawn(ofType: selectedType, position: position)
}
}
17 changes: 9 additions & 8 deletions TowerForge/TowerForge/Rendering/Renderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,19 @@ class Renderer {
private unowned var target: Renderable
private unowned var scene: SKScene?

private var renderedNodes: [UUID: TFAnimatableNode] = [:]
private var renderedNodes: [UUID: TFSpriteNode] = [:]

init(target: Renderable, scene: GameScene?) {
self.target = target
self.scene = scene
}

func addNodeToScene(entity: TFEntity) {
guard let spriteComponent = entity.component(ofType: SpriteComponent.self) else {
return
}
renderedNodes[entity.id] = spriteComponent.node
self.scene?.addChild(spriteComponent.node)
}
zheng-ze marked this conversation as resolved.
Show resolved Hide resolved
func render() {
var nodesToBeRemoved = renderedNodes

Expand All @@ -36,7 +42,6 @@ class Renderer {
removeAndUncache(with: entityId)
}
}

private func update(entity: TFEntity) {
guard let positionComponent = entity.component(ofType: PositionComponent.self),
let node = renderedNodes[entity.id] else {
Expand All @@ -45,18 +50,14 @@ class Renderer {

node.position = positionComponent.position
}

private func addAndCache(entity: TFEntity) {
guard let spriteComponent = entity.component(ofType: SpriteComponent.self),
let positionComponent = entity.component(ofType: PositionComponent.self),
let playerComponent = entity.component(ofType: PlayerComponent.self) else {
return
}

let node = TFAnimatableNode(textures: spriteComponent.textures,
height: spriteComponent.height,
width: spriteComponent.width,
animatableKey: spriteComponent.animatableKey)
let node = spriteComponent.node
// Flips the image if it is the opposite team
if playerComponent.player == .oppositePlayer {
node.xScale *= -1
Expand Down