diff --git a/GoldWars/GoldWars/Components/AtkBoostSkillComponent.swift b/GoldWars/GoldWars/Components/AtkBoostSkillComponent.swift index 3f2e1c3..8829c19 100644 --- a/GoldWars/GoldWars/Components/AtkBoostSkillComponent.swift +++ b/GoldWars/GoldWars/Components/AtkBoostSkillComponent.swift @@ -25,8 +25,7 @@ class AtkBoostSkillComponent: GKComponent{ }else { base.unitType = .Attack } - } - }) + }}) super.init() } diff --git a/GoldWars/GoldWars/Components/TeamComponent.swift b/GoldWars/GoldWars/Components/TeamComponent.swift index db67deb..7fee0ae 100644 --- a/GoldWars/GoldWars/Components/TeamComponent.swift +++ b/GoldWars/GoldWars/Components/TeamComponent.swift @@ -14,7 +14,7 @@ class TeamComponent: GKComponent { var team: Team var player: GKPlayer let fire: SKEmitterNode - + init(team: Team, player: GKPlayer, position: CGPoint) { fire = SKEmitterNode(fileNamed: "Fire")! fire.zPosition = -1 @@ -22,21 +22,30 @@ class TeamComponent: GKComponent { fire.name = "fire" fire.particleColorSequence = nil fire.particleColorBlendFactor = 1.0 - - switch team { - case .team1: fire.particleColor = SKColor.red - case .team2: fire.particleColor = SKColor.purple - case .team3: fire.particleColor = SKColor.green - case .team4: fire.particleColor = SKColor.gray - } - + self.team = team self.player = player super.init() + fire.particleColor = getColor(by: team) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + func getColor(by team: Team) -> SKColor { + switch team { + case .team1: return SKColor.red + case .team2: return SKColor.purple + case .team3: return SKColor.green + case .team4: return SKColor.gray + } + } + + func change(to team: Team, to player: GKPlayer) -> Void { + self.team = team + self.player = player + self.fire.particleColor = getColor(by: team) + } } diff --git a/GoldWars/GoldWars/Components/TimerComponent.swift b/GoldWars/GoldWars/Components/TimerComponent.swift index 52c51b6..3d2579c 100644 --- a/GoldWars/GoldWars/Components/TimerComponent.swift +++ b/GoldWars/GoldWars/Components/TimerComponent.swift @@ -13,6 +13,7 @@ class TimerComponent: GKComponent { let labelNode :SKLabelNode var endTime :Date! var duration :Double + var isRunning = false init(text: String, anchorPoint: CGPoint, duration: TimeInterval) { self.labelNode = SKLabelNode(text: text) @@ -25,16 +26,24 @@ class TimerComponent: GKComponent { } func startWithDuration(duration: TimeInterval){ + isRunning = true endTime = Date().addingTimeInterval(duration) RoundCalculatorService.sharedInstance.isCalculating = false } func timeLeft() -> Int { - let remainingSeconds = Int(endTime.timeIntervalSince(Date())) - if(remainingSeconds < 0 ){ - startWithDuration(duration: duration) + if isRunning { + let remainingSeconds = Int(endTime.timeIntervalSince(Date())) + if(remainingSeconds == 0) { + isRunning = false + } + return remainingSeconds } - return remainingSeconds + + // if(remainingSeconds < 0){ + // startWithDuration(duration: duration) + // } + return 0 } func isFinished() -> Bool { diff --git a/GoldWars/GoldWars/Entities/Base.swift b/GoldWars/GoldWars/Entities/Base.swift index 4f695c9..0749085 100644 --- a/GoldWars/GoldWars/Entities/Base.swift +++ b/GoldWars/GoldWars/Entities/Base.swift @@ -31,9 +31,10 @@ class Base: GKEntity{ self.position = position super.init() - addComponent(DefaultBaseComponent(texture: SKTexture(imageNamed: "Base"), position: position)) + let spritePos = position + addComponent(DefaultBaseComponent(texture: SKTexture(imageNamed: "Base"), position: spritePos)) if(team != nil && player != nil){ - addComponent(TeamComponent(team: team!, player: player!, position: position)) + addComponent(TeamComponent(team: team!, player: player!, position: spritePos)) self.unitCount = 500 } } diff --git a/GoldWars/GoldWars/Entities/EntityManager.swift b/GoldWars/GoldWars/Entities/EntityManager.swift index cbeb114..3cfafa7 100644 --- a/GoldWars/GoldWars/Entities/EntityManager.swift +++ b/GoldWars/GoldWars/Entities/EntityManager.swift @@ -43,10 +43,10 @@ class EntityManager { scene.addChild(modal.header) scene.addChild(modal.body) scene.addChild(modal.footer) + isModal = true } if let skillButtonNode = entity.component(ofType: AtkBoostSkillComponent.self)?.skillButtonNode { scene.addChild(skillButtonNode) - isModal = true } if let skillButtonNode = entity.component(ofType: DefBoostSkillComponent.self)?.skillButtonNode { scene.addChild(skillButtonNode) @@ -60,7 +60,6 @@ class EntityManager { } if let buttonNode = entity.component(ofType: ButtonComponent.self)?.buttonNode { scene.addChild(buttonNode) - isModal = true } if let nodes = entity.component(ofType: BackgroundComponent.self)?.nodes { for node in nodes { @@ -76,7 +75,6 @@ class EntityManager { } if let cancelBtnNode = entity.component(ofType: CancelBtnComponent.self)?.cancelBtnNode { scene.addChild(cancelBtnNode) - isModal = true } if let node = entity.component(ofType: SpinningLogoComponent.self)?.node { scene.addChild(node) @@ -97,6 +95,7 @@ class EntityManager { modal.header.removeFromParent() modal.body.removeFromParent() modal.footer.removeFromParent() + isModal = false } if let sliderNode = entity.component(ofType: SliderComponent.self)?.sliderNode { sliderNode.sliderKnob.removeFromParent() @@ -104,11 +103,9 @@ class EntityManager { } if let modalButton = entity.component(ofType: ButtonComponent.self) { modalButton.buttonNode.removeFromParent() - isModal = false } if let cancelBtnNode = entity.component(ofType: CancelBtnComponent.self)?.cancelBtnNode { cancelBtnNode.removeFromParent() - isModal = false } entities.remove(entity) } @@ -119,17 +116,18 @@ class EntityManager { let base = (entity as! Base) if base.changeOwnership { - //FIX-ME: Find a way to update the Component without deleting it upfront - //TODO: outsource component handling to a generic function - //base.removeComponent(ofType: TeamComponent.self) - base.addComponent(TeamComponent( - team: (entities[0] as! Base).component(ofType: TeamComponent.self)!.team, - player: (entities[0] as! Base).component(ofType: TeamComponent.self)!.player, - position: (base.component(ofType: DefaultBaseComponent.self)?.spriteNode.position)! + if (entity.component(ofType: TeamComponent.self) != nil) { + entity.component(ofType: TeamComponent.self)!.change(to: (entities[0] as! Base).component(ofType: TeamComponent.self)!.team, to: (entities[0] as! Base).component(ofType: TeamComponent.self)!.player) + } else { + base.addComponent(TeamComponent( + team: (entities[0] as! Base).component(ofType: TeamComponent.self)!.team, + player: (entities[0] as! Base).component(ofType: TeamComponent.self)!.player, + position: (base.component(ofType: DefaultBaseComponent.self)?.spriteNode.position)! + ) ) - ) - if let fire = entity.component(ofType: TeamComponent.self)?.fire{ - scene.addChild(fire) + if let fire = entity.component(ofType: TeamComponent.self)?.fire{ + scene.addChild(fire) + } } base.changeOwnership = false } @@ -146,21 +144,24 @@ class EntityManager { if snapBase.ownership != nil { getOwnerBySnapBase = MatchmakingHelper.sharedInstance.getGKPlayerByUsername(displayName: snapBase.ownership!) + } else { + entity.removeComponent(ofType: TeamComponent.self) } if getOwnerBySnapBase != nil { base.changeOwnership = true base.ownershipPlayer = getOwnerBySnapBase - //FIX-ME: Find a way to update the Component without deleting it upfront - //TODO: outsource component handling to a generic function - //entity.removeComponent(ofType: TeamComponent.self) - entity.addComponent(TeamComponent( - team: getTeamByPlayer(playerName: snapBase.ownership!), - player: getOwnerBySnapBase!, - position: (entity.component(ofType: DefaultBaseComponent.self)?.spriteNode.position)! + if (entity.component(ofType: TeamComponent.self) != nil) { + entity.component(ofType: TeamComponent.self)!.change(to: getTeamByPlayer(playerName: snapBase.ownership!), to: getOwnerBySnapBase!) + } else { + entity.addComponent(TeamComponent( + team: getTeamByPlayer(playerName: snapBase.ownership!), + player: getOwnerBySnapBase!, + position: (entity.component(ofType: DefaultBaseComponent.self)?.spriteNode.position)! + ) ) - ) - if let fire = entity.component(ofType: TeamComponent.self)?.fire{ - scene.addChild(fire) + if let fire = entity.component(ofType: TeamComponent.self)?.fire{ + scene.addChild(fire) + } } } } @@ -257,4 +258,8 @@ class EntityManager { return SnapshotModel(baseEntites: snapBase) } + + func getTimer() -> TimerComponent { + return entities.filter{$0 is HUD}[0].component(ofType: TimerComponent.self)! + } } diff --git a/GoldWars/GoldWars/Entities/Modal.swift b/GoldWars/GoldWars/Entities/Modal.swift index c01999e..489aed4 100644 --- a/GoldWars/GoldWars/Entities/Modal.swift +++ b/GoldWars/GoldWars/Entities/Modal.swift @@ -58,6 +58,7 @@ class Modal: GKEntity{ for base in currentDraggedBase!.adjacencyList { if base == collisionBase { EntityManager.sharedInstance.update((currentDraggedBase?.doPlayerMoveTypeToBase(base: base, playerMoveType: PlayerMoveType.AtkMove, units: Int(GameScene.sendUnits)))!) + GameScene.sendUnits = 0 } } } diff --git a/GoldWars/GoldWars/MatchmakingHelper.swift b/GoldWars/GoldWars/MatchmakingHelper.swift index 5e09ed6..60dc5d2 100644 --- a/GoldWars/GoldWars/MatchmakingHelper.swift +++ b/GoldWars/GoldWars/MatchmakingHelper.swift @@ -120,6 +120,7 @@ class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDe if let snapshotModel = try? jsonDecoder.decode(SnapshotModel.self, from: data) { DataService.sharedInstance.snapshotModel = snapshotModel EntityManager.sharedInstance.updateSnapshotModel(snapshotModel: snapshotModel) + EntityManager.sharedInstance.getTimer().startWithDuration(duration: 31) } if let mapModel = try? jsonDecoder.decode(MapGenerationModel.self, from: data) { diff --git a/GoldWars/GoldWars/MultiplayerNetwork.swift b/GoldWars/GoldWars/MultiplayerNetwork.swift index 34cbccd..5cf2937 100644 --- a/GoldWars/GoldWars/MultiplayerNetwork.swift +++ b/GoldWars/GoldWars/MultiplayerNetwork.swift @@ -45,8 +45,8 @@ class MultiplayerNetwork{ let encoder = JSONEncoder() let encoded = (try? encoder.encode(playerMoves))! sendDataToHost(data: encoded) + DataService.sharedInstance.localPlayerMoves.removeAll() } - DataService.sharedInstance.localPlayerMoves.removeAll() } func sendHostIdentifier() { diff --git a/GoldWars/GoldWars/Partikels/Fire.sks b/GoldWars/GoldWars/Partikels/Fire.sks index f25e78f..1f31d2e 100644 Binary files a/GoldWars/GoldWars/Partikels/Fire.sks and b/GoldWars/GoldWars/Partikels/Fire.sks differ diff --git a/GoldWars/GoldWars/RoundCalculatorService.swift b/GoldWars/GoldWars/RoundCalculatorService.swift index 3704ec8..b9186c6 100644 --- a/GoldWars/GoldWars/RoundCalculatorService.swift +++ b/GoldWars/GoldWars/RoundCalculatorService.swift @@ -54,7 +54,7 @@ class RoundCalculatorService { } playerMovesByBase.removeValue(forKey: playerName) } - + for (_, playerMoves) in playerMovesByBase { for playerMove in playerMoves { for base in currentSnapshotModel!.baseEntites { @@ -84,11 +84,22 @@ class RoundCalculatorService { for base in currentSnapshotModel!.baseEntites { if base.baseId == playerMoveWithMaxUnits.value.toBase { - base.unitCount += playerMoveWithMaxUnits.value.unitCount - if playerMoveWithMaxUnits.value.unitCount == 0 { - base.ownership = nil + if base.ownership == nil { + base.unitCount += playerMoveWithMaxUnits.value.unitCount + if playerMoveWithMaxUnits.value.unitCount == 0 { + base.ownership = nil + } else { + base.ownership = playerMoveWithMaxUnits.key + } } else { - base.ownership = playerMoveWithMaxUnits.key + if base.unitCount < playerMoveWithMaxUnits.value.unitCount { + base.unitCount = playerMoveWithMaxUnits.value.unitCount - base.unitCount + base.ownership = playerMoveWithMaxUnits.key + } else if (base.unitCount == playerMoveWithMaxUnits.value.unitCount) { + base.ownership = nil + } else { + base.unitCount -= playerMoveWithMaxUnits.value.unitCount + } } } } @@ -96,8 +107,12 @@ class RoundCalculatorService { baseSpecificMoves.removeValue(forKey: baseId) } allPlayerMoves.removeAll() + DataService.sharedInstance.localPlayerMoves.removeAll() MultiplayerNetwork.sharedInstance.sendSnapshotModelToPlayers() + DataService.sharedInstance.snapshotModel = currentSnapshotModel EntityManager.sharedInstance.updateSnapshotModel(snapshotModel: currentSnapshotModel!) + sleep(1) + EntityManager.sharedInstance.getTimer().startWithDuration(duration: 31) os_log("Finished calculating Round", log: RoundCalculatorService.LOG, type: .info) } diff --git a/GoldWars/GoldWars/Scenes/GameScene.swift b/GoldWars/GoldWars/Scenes/GameScene.swift index 58a3d9d..8a967a0 100644 --- a/GoldWars/GoldWars/Scenes/GameScene.swift +++ b/GoldWars/GoldWars/Scenes/GameScene.swift @@ -13,7 +13,6 @@ import GameKit class GameScene: SKScene{ var isMoveTouch = false - var currentDraggedBasePos = CGPoint() var currentDraggedBase : Base? static var sendUnits: CGFloat = 0 var collisionBase: Base? @@ -26,13 +25,14 @@ class GameScene: SKScene{ } func initMap() { - if (DataService.sharedInstance.gameHost?.playerName == GKLocalPlayer.local.displayName) { let mapModel = MapFactory(scene: self, entityManager: EntityManager.sharedInstance).loadMap() MultiplayerNetwork.sharedInstance.sendMapModelToPlayers(mapModel: mapModel) + DataService.sharedInstance.setSnapshotModel(snapshotModel: EntityManager.sharedInstance.getSnapshotModel()) + } + if CommandLine.arguments.contains("--no-matchmaking") { + MapFactory(scene: self, entityManager: EntityManager.sharedInstance).loadMap() } - - DataService.sharedInstance.setSnapshotModel(snapshotModel: EntityManager.sharedInstance.getSnapshotModel()) } override func touchesEnded(_ touches: Set, with event: UIEvent?) { @@ -44,8 +44,8 @@ class GameScene: SKScene{ if isMoveTouch{ isMoveTouch = false - currentDraggedBase!.component(ofType: DefaultBaseComponent.self)?.spriteNode.position = currentDraggedBasePos - currentDraggedBase!.component(ofType: TeamComponent.self)?.fire.position = currentDraggedBasePos + currentDraggedBase!.component(ofType: DefaultBaseComponent.self)?.spriteNode.position = currentDraggedBase!.position + currentDraggedBase!.component(ofType: TeamComponent.self)?.fire.position = currentDraggedBase!.position addAttackDetails(touchLocation: touchLocation) } @@ -53,6 +53,7 @@ class GameScene: SKScene{ for entity in EntityManager.sharedInstance.entities { let spriteNode = entity.component(ofType: DefaultBaseComponent.self)?.spriteNode + //FIXME: this is confusing addBaseDetails(touchLocation: touchLocation, spriteNode: spriteNode, touches: touches, event: event, entity: entity) } } @@ -85,16 +86,20 @@ class GameScene: SKScene{ func addBaseDetails(touchLocation: CGPoint, spriteNode: SKNode?, touches: Set, event: UIEvent?, entity: GKEntity){ if atPoint(touchLocation) == spriteNode && !EntityManager.sharedInstance.isModal { spriteNode?.touchesBegan(touches, with: event) - if !EntityManager.sharedInstance.isModal { - for child in self.children { - if(child.name != "fire"){ - child.alpha = 0.3 + if let baseEntity = entity as? Base { + if baseEntity.ownershipPlayer == GKLocalPlayer.local { + for child in self.children { + if(child.name != "fire"){ + child.alpha = 0.3 + } } + EntityManager.sharedInstance.add(Modal(modaltype: .BaseDetails, + base: entity as! Base, + anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2), + gameScene: self, + currentDraggedBase: currentDraggedBase, touchLocation: touchLocation, collisionBase: collisionBase)) + } - EntityManager.sharedInstance.add(Modal(modaltype: .BaseDetails, - base: entity as! Base, - anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2), - gameScene: self, currentDraggedBase: currentDraggedBase, touchLocation: touchLocation, collisionBase: collisionBase)) } } } @@ -104,10 +109,13 @@ class GameScene: SKScene{ if atPoint(touchLocation) == base.component(ofType: DefaultBaseComponent.self)?.spriteNode { collisionBase = base // TODO: change interaction based on collision instead of touchlocation - EntityManager.sharedInstance.add(Modal(modaltype: .BaseAttack, - base: currentDraggedBase!, - anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2), - gameScene: self, currentDraggedBase: currentDraggedBase, touchLocation: touchLocation, collisionBase: collisionBase)) + if currentDraggedBase!.unitCount > 1 { + EntityManager.sharedInstance.add(Modal(modaltype: .BaseAttack, + base: currentDraggedBase!, + anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2), + gameScene: self, currentDraggedBase: currentDraggedBase, touchLocation: touchLocation, collisionBase: collisionBase)) + GameScene.sendUnits = CGFloat(currentDraggedBase!.unitCount / 2) + } } } } @@ -116,6 +124,13 @@ class GameScene: SKScene{ for e in EntityManager.sharedInstance.entities{ if let body = e.component(ofType: ModalContentComponent.self)?.body{ GameScene.sendUnits = ((e.component(ofType: SliderComponent.self)?.sliderNode.getValue ?? 0) * CGFloat((e as! Modal).unitCount)).rounded(.up) + + //TODO: refactor this quick and dirty fix + if GameScene.sendUnits == 0 { + GameScene.sendUnits = 1 + } else if Int(GameScene.sendUnits) == currentDraggedBase?.unitCount { + GameScene.sendUnits -= 1 + } body.text = "Schicke \(GameScene.sendUnits) Einheiten " } } @@ -123,9 +138,9 @@ class GameScene: SKScene{ func checkBases(bases: Set, touchLocation: CGPoint){ for base in bases { - if atPoint(touchLocation) == base.component(ofType: DefaultBaseComponent.self)?.spriteNode{ if !isMoveTouch { - currentDraggedBasePos = base.component(ofType: DefaultBaseComponent.self)!.spriteNode.position - currentDraggedBase = base + if atPoint(touchLocation) == base.component(ofType: DefaultBaseComponent.self)?.spriteNode{ + if !isMoveTouch { + currentDraggedBase = base } isMoveTouch = true moveFireAndBase(base: base, touchLocation: touchLocation)