diff --git a/GoldWars/GoldWars/Components/TeamComponent.swift b/GoldWars/GoldWars/Components/TeamComponent.swift index 379a1cc..2369f7b 100644 --- a/GoldWars/GoldWars/Components/TeamComponent.swift +++ b/GoldWars/GoldWars/Components/TeamComponent.swift @@ -8,12 +8,14 @@ import SpriteKit import GameplayKit +import GameKit class TeamComponent: GKComponent { let team: Team let fire: SKEmitterNode + let player: GKPlayer - init(team: Team, position: CGPoint) { + init(team: Team, player: GKPlayer, position: CGPoint) { fire = SKEmitterNode(fileNamed: "Fire")! fire.zPosition = -1 fire.position = position @@ -29,6 +31,7 @@ class TeamComponent: GKComponent { } self.team = team + self.player = player super.init() } diff --git a/GoldWars/GoldWars/Entities/Base.swift b/GoldWars/GoldWars/Entities/Base.swift index 7578e67..02011c4 100644 --- a/GoldWars/GoldWars/Entities/Base.swift +++ b/GoldWars/GoldWars/Entities/Base.swift @@ -8,29 +8,39 @@ import SpriteKit import GameplayKit +import GameKit class Base: GKEntity{ static var BASE_ID_COUNT: Int = 0 var unitCount: Int var adjacencyList: Array - var changeOwnerShip: Bool + var changeOwnership: Bool + var ownershipPlayer: GKPlayer? var baseID: Int - - init(position: CGPoint, team: Team! = nil) { + + init(position: CGPoint, player: GKPlayer! = nil, team: Team! = nil) { self.unitCount = 0 self.adjacencyList = [Base]() - self.changeOwnerShip = false - baseID = Base.BASE_ID_COUNT + self.changeOwnership = false + self.ownershipPlayer = player Base.BASE_ID_COUNT += 1 super.init() addComponent(DefaultBaseComponent(texture: SKTexture(imageNamed: "Base"), position: position)) - if(team != nil){ - addComponent(TeamComponent(team: team!, position: position)) + if(team != nil && player != nil){ + addComponent(TeamComponent(team: team!, player: player!, position: position)) self.unitCount = 500 } } + func attackBase(base: Base, units:Int) -> [GKEntity]{ + base.changeOwnership = true + base.ownershipPlayer = self.ownershipPlayer + self.unitCount -= units + base.unitCount += units + DataService.sharedInstance.addMove(playerMove: PlayerMove(fromBase: self.baseID, toBase: base.baseID, unitCount: units)) + return [self, base] + } func attackBase(base: Base, units: Int) -> [GKEntity]{ base.changeOwnerShip = true self.unitCount -= units @@ -38,7 +48,7 @@ class Base: GKEntity{ DataService.sharedInstance.addMove(playerMove: PlayerMove(fromBase: self.baseID, toBase: base.baseID, unitCount: units)) return [self, base] } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } diff --git a/GoldWars/GoldWars/Entities/EntityManager.swift b/GoldWars/GoldWars/Entities/EntityManager.swift index ac5d529..2f41dcf 100644 --- a/GoldWars/GoldWars/Entities/EntityManager.swift +++ b/GoldWars/GoldWars/Entities/EntityManager.swift @@ -8,62 +8,63 @@ import SpriteKit import GameplayKit +import GameKit class EntityManager { var entities = Set() let scene: SKScene - var isModal: Bool + var isModal: Bool init(scene: SKScene) { self.scene = scene - isModal = false + isModal = false } func add(_ entity: GKEntity) { entities.insert(entity) - if let spriteNode = entity.component(ofType: DefaultBaseComponent.self)?.spriteNode { - scene.addChild(spriteNode) - } - if let fire = entity.component(ofType: TeamComponent.self)?.fire{ - scene.addChild(fire) - } - if let spriteNode = entity.component(ofType: ModalBackgroundComponent.self)?.spriteNode { - scene.addChild(spriteNode) - isModal = true - } - if let modal = entity.component(ofType: ModalContentComponent.self) { - scene.addChild(modal.header) - scene.addChild(modal.body) - scene.addChild(modal.footer) - } - if let skill = entity.component(ofType: AtkBoostSkillComponent.self) { - scene.addChild(skill.shapeNode) - scene.addChild(skill.labelNode) - } - if let skill = entity.component(ofType: DefBoostSkillComponent.self) { - scene.addChild(skill.shapeNode) - scene.addChild(skill.labelNode) - } - if let skill = entity.component(ofType: SpySkillComponent.self) { - scene.addChild(skill.shapeNode) - scene.addChild(skill.labelNode) - } + if let spriteNode = entity.component(ofType: DefaultBaseComponent.self)?.spriteNode { + scene.addChild(spriteNode) + } + if let fire = entity.component(ofType: TeamComponent.self)?.fire{ + scene.addChild(fire) + } + if let spriteNode = entity.component(ofType: ModalBackgroundComponent.self)?.spriteNode { + scene.addChild(spriteNode) + } + if let modal = entity.component(ofType: ModalContentComponent.self) { + scene.addChild(modal.header) + scene.addChild(modal.body) + scene.addChild(modal.footer) + } + if let skill = entity.component(ofType: AtkBoostSkillComponent.self) { + scene.addChild(skill.shapeNode) + scene.addChild(skill.labelNode) + } + if let skill = entity.component(ofType: DefBoostSkillComponent.self) { + scene.addChild(skill.shapeNode) + scene.addChild(skill.labelNode) + } + if let skill = entity.component(ofType: SpySkillComponent.self) { + scene.addChild(skill.shapeNode) + scene.addChild(skill.labelNode) + } if let timer = entity.component(ofType: TimerComponent.self) { scene.addChild(timer.labelNode) } 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 { scene.addChild(node) } } - if let sliderNode = entity.component(ofType: SliderComponent.self)?.sliderNode { - scene.addChild(sliderNode.sliderKnob) - scene.addChild(sliderNode.sliderLine) - } + if let sliderNode = entity.component(ofType: SliderComponent.self)?.sliderNode { + scene.addChild(sliderNode.sliderKnob) + scene.addChild(sliderNode.sliderLine) + } if let labelNode = entity.component(ofType: LabelComponent.self)?.labelNode { scene.addChild(labelNode) } @@ -73,65 +74,88 @@ class EntityManager { if let spriteNode = entity.component(ofType: DefaultBaseComponent.self)?.spriteNode { spriteNode.removeFromParent() } - if let spriteNode = entity.component(ofType: ModalBackgroundComponent.self)?.spriteNode { - spriteNode.removeFromParent() - isModal = false - } - if let modal = entity.component(ofType: ModalContentComponent.self) { - modal.header.removeFromParent() - modal.body.removeFromParent() - modal.footer.removeFromParent() - } - if let sliderNode = entity.component(ofType: SliderComponent.self)?.sliderNode { - sliderNode.sliderKnob.removeFromParent() - sliderNode.sliderLine.removeFromParent() - } + if let spriteNode = entity.component(ofType: ModalBackgroundComponent.self)?.spriteNode { + spriteNode.removeFromParent() + } + if let modal = entity.component(ofType: ModalContentComponent.self) { + modal.header.removeFromParent() + modal.body.removeFromParent() + modal.footer.removeFromParent() + } + if let sliderNode = entity.component(ofType: SliderComponent.self)?.sliderNode { + sliderNode.sliderKnob.removeFromParent() + sliderNode.sliderLine.removeFromParent() + } + if let modalButton = entity.component(ofType: ButtonComponent.self) { + modalButton.buttonNode.removeFromParent() + isModal = false + } entities.remove(entity) } - func update(_ entities: [GKEntity]){ - for entity in entities { - self.entities.update(with: entity) - let base = (entity as! Base) + func update(_ entities: [GKEntity]){ + for entity in entities { + self.entities.update(with: entity) + let base = (entity as! Base) - if base.changeOwnerShip { - base.addComponent(TeamComponent(team: (entities[0] as! Base).component(ofType: TeamComponent.self)!.team, position: (base.component(ofType: DefaultBaseComponent.self)?.spriteNode.position)!)) - base.changeOwnerShip = false - scene.addChild(base.component(ofType: TeamComponent.self)!.fire) - } - } + if base.changeOwnership { + 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)! + ) + ) + base.changeOwnership = false + scene.addChild(base.component(ofType: TeamComponent.self)!.fire) + } + } - } + } - func getBaseByTeam(for team: Team) -> GKEntity? { - for entity in entities { - if let teamComponent = entity.component(ofType: TeamComponent.self), - let _ = entity.component(ofType: DefaultBaseComponent.self) { + func getBaseByPlayer(for player: GKPlayer) -> GKEntity? { + for entity in entities { + if let teamComponent = entity.component(ofType: TeamComponent.self), + let _ = entity.component(ofType: DefaultBaseComponent.self) { + if teamComponent.player == player { + return entity + } + } + } + return nil + } + + func getBaseByTeam(for team: Team) -> GKEntity? { + for entity in entities { + if let teamComponent = entity.component(ofType: TeamComponent.self), + let _ = entity.component(ofType: DefaultBaseComponent.self) { if teamComponent.team == team { return entity - } - } - } - return nil + } + } + } + return nil } func getBasesByTeam(for team: Team) -> Set { return entities.filter{$0 is Base && ($0 as! Base).component(ofType: TeamComponent.self)?.team == team } as! Set } - func getTeamByBase(base: Base) -> Team? { - for entity in entities { - if entity is Base && entity == base{ - for component in entity.components{ - if component is TeamComponent { - return entity.component(ofType: TeamComponent.self)!.team - } - } - } - } - return nil - } + func getBasesByPlayer(for player: GKPlayer) -> Set { + return entities.filter{$0 is Base && ($0 as! Base).component(ofType: TeamComponent.self)?.player == player } as! Set + } + func getTeamByBase(base: Base) -> Team? { + for entity in entities { + if entity is Base && entity == base{ + for component in entity.components{ + if component is TeamComponent { + return entity.component(ofType: TeamComponent.self)!.team + } + } + } + } + return nil + } func getBasebyID(id: Int) -> Base?{ for entity in entities { @@ -141,13 +165,14 @@ class EntityManager { } return nil } + func getBackground() -> GKEntity? { return entities.filter{$0 is Background}[0] } - func getBaseNodeByTeam(for team: Team) -> SKSpriteNode? { - return getBaseByTeam(for: team)?.component(ofType: DefaultBaseComponent.self)?.spriteNode - } + func getBaseNodeByTeam(for team: Team) -> SKSpriteNode? { + return getBaseByTeam(for: team)?.component(ofType: DefaultBaseComponent.self)?.spriteNode + } func getButtonByName(buttonName:String) -> Button { return entities.filter{$0 is Button && ($0 as! Button).name == buttonName }[0] as! Button diff --git a/GoldWars/GoldWars/Entities/Modal.swift b/GoldWars/GoldWars/Entities/Modal.swift index cdafa53..516efb0 100644 --- a/GoldWars/GoldWars/Entities/Modal.swift +++ b/GoldWars/GoldWars/Entities/Modal.swift @@ -9,31 +9,44 @@ import GameplayKit class Modal: GKEntity{ - - var unitCount:Int - init(modaltype: ModalType, base: Base, anchorPoint: CGPoint) { - unitCount = base.unitCount - super.init() - switch modaltype{ - case .BaseDetails: - addComponent(ModalBackgroundComponent(anchorPoint: anchorPoint)) - addComponent(ModalContentComponent(header: "Basis Information", - body: "Diese Basis enthält \(base.unitCount) Einheiten", - footer: "", - anchorPoint: anchorPoint)) - case .BaseAttack: - addComponent(ModalBackgroundComponent(anchorPoint: anchorPoint)) - addComponent(SliderComponent(width: 300, position: CGPoint(x: anchorPoint.x , y: anchorPoint.y - 80))) - addComponent(ModalContentComponent(header: "Angriff", - body: "Schicke \(unitCount / 2) Einheiten", - footer: "", - anchorPoint: anchorPoint)) - } - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + var unitCount:Int + + init(modaltype: ModalType, base: Base, anchorPoint: CGPoint, entityManager: EntityManager, gameScene: SKScene) { + unitCount = base.unitCount + super.init() + switch modaltype{ + case .BaseDetails: + addComponent(ModalBackgroundComponent(anchorPoint: anchorPoint)) + addComponent(ModalContentComponent(header: "Basis Information", body: "Diese Basis enthält \(base.unitCount) Einheiten", footer: "", anchorPoint: anchorPoint)) + addComponent(ButtonComponent(iconName: "", text: "Zurück", position: CGPoint(x: anchorPoint.x , y: anchorPoint.y - 120), isEnabled: true, onButtonPress: { + self.removeModalEntities(entityManager: entityManager, gameScene: gameScene) + })) + case .BaseAttack: + addComponent(ModalBackgroundComponent(anchorPoint: anchorPoint)) + addComponent(SliderComponent(width: 300, position: CGPoint(x: anchorPoint.x , y: anchorPoint.y - 50))) + addComponent(ModalContentComponent(header: "Angriff", body: "Schicke \(unitCount / 2) Einheiten", + footer: "", anchorPoint: anchorPoint)) + addComponent(ButtonComponent(iconName: "", text: "Senden", position: CGPoint(x: anchorPoint.x , y: anchorPoint.y - 120), isEnabled: true, onButtonPress: { + self.removeModalEntities(entityManager: entityManager, gameScene: gameScene) + })) + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func removeModalEntities(entityManager: EntityManager, gameScene: SKScene){ + for entity in entityManager.entities { + if entityManager.isModal && entity.isMember(of: Modal.self) { + entityManager.remove(entity) + } + for child in gameScene.children { + if(child.name != "fire"){ + child.alpha = 1 + } + } + } + } } diff --git a/GoldWars/GoldWars/Map/TwoPlayerDefaultTestMap.swift b/GoldWars/GoldWars/Map/TwoPlayerDefaultTestMap.swift index beff433..fa20823 100644 --- a/GoldWars/GoldWars/Map/TwoPlayerDefaultTestMap.swift +++ b/GoldWars/GoldWars/Map/TwoPlayerDefaultTestMap.swift @@ -8,6 +8,7 @@ import Foundation import SpriteKit +import GameKit class TwoPlayerDefaultTestMap: MapProtocol { @@ -24,6 +25,7 @@ class TwoPlayerDefaultTestMap: MapProtocol { // Create Bases let basePlayerOne = Base( position: CGPoint(x: self.size.width * 0.1, y: self.size.height / 2), + player: (MatchmakingHelper.sharedInstance.isServer) ? GKLocalPlayer.local : MatchmakingHelper.sharedInstance.mpMatch?.players[0], team: .team1 ) @@ -46,6 +48,7 @@ class TwoPlayerDefaultTestMap: MapProtocol { let basePlayerTwo = Base( position: CGPoint(x: self.size.width * 0.9, y: self.size.height / 2), + player: (!MatchmakingHelper.sharedInstance.isServer) ? GKLocalPlayer.local : MatchmakingHelper.sharedInstance.mpMatch?.players[0], team: .team2 ) diff --git a/GoldWars/GoldWars/MatchmakingHelper.swift b/GoldWars/GoldWars/MatchmakingHelper.swift index dc19aae..30b7253 100644 --- a/GoldWars/GoldWars/MatchmakingHelper.swift +++ b/GoldWars/GoldWars/MatchmakingHelper.swift @@ -72,15 +72,15 @@ class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDe /* Der User hat die Verbindung mit "Abbrechen" unterbrochen. GameCenter MatchMaking wird beendet. - */ + */ func matchmakerViewControllerWasCancelled(_ viewController: GKMatchmakerViewController) { viewController.dismiss(animated: true, completion: nil) delegate?.matchEnded() } /* - Wenn GameCenter kein match erstellen kann, wird der viewcontroller dismissed. - */ + Wenn GameCenter kein match erstellen kann, wird der viewcontroller dismissed. + */ func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFailWithError error: Error) { viewController.dismiss(animated: true, completion: nil) print("Error finding match", error.localizedDescription) @@ -91,7 +91,7 @@ class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDe Gamecenter hat erfolgreich ein Match gefunden, das Spiel kann gestartet werden. expectedPlayerCount: Die verbleibende Anzahl von Spielern, die sich noch nicht mit dem Spiel verbunden haben z.B 0 gibt an, dass keine weiteren Spieler benötigt werden um das Match zu starten - */ + */ func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) { viewController.dismiss(animated: true, completion: nil) mpMatch = match @@ -101,22 +101,18 @@ class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDe } } - - /* Vom match erhaltene Spielerdaten - */ - func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) { if mpMatch != match { return } - + let jsonDecoder = JSONDecoder() if let playerMoves = try? jsonDecoder.decode([PlayerMove].self, from: data) { DataService.sharedInstance.addRemotePlayerMoves(playerID: player.displayName, playerMoves: playerMoves) } - + if let message = try? jsonDecoder.decode(Host.self, from: data) { DataService.sharedInstance.gameHost = message } @@ -137,7 +133,6 @@ class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDe /* Wird beim ändern des States/Zustands des Spielers aufgerufen udn gibt dessen Zustand zurück. */ - func match(_ match: GKMatch, player: GKPlayer, didChange state: GKPlayerConnectionState) { if mpMatch != match { return @@ -157,31 +152,29 @@ class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDe } /* - Ein Spieler wird als Host für das Match gewählt. Dieser ist Spieler 1. Im Anschluss wird die GameScene geladen. - */ + Ein Spieler wird als Host für das Match gewählt. Dieser ist Spieler 1. Im Anschluss wird die GameScene geladen. + */ func startMatch() { - + mpMatch!.chooseBestHostingPlayer(completionHandler: { (player) in self.mpMatchStarted = true - + if player == GKLocalPlayer.local { - print("ich bin host") self.isServer = true self.spieler1 = player self.nameSpieler1 = self.spieler1!.displayName - DataService.sharedInstance.setGameHost(host: Host(playerID: player!.displayName)) + } else { self.isServer = false } self.delegate?.matchStarted() self.menusc!.loadScene(scene: GameScene(size: self.menusc!.size)) - MultiplayerNetwork.sharedInstance.sendHostIdentifier() }) } - + /* Trennt die Verbindung vom Match diff --git a/GoldWars/GoldWars/Scenes/GameScene.swift b/GoldWars/GoldWars/Scenes/GameScene.swift index b306854..dae1566 100644 --- a/GoldWars/GoldWars/Scenes/GameScene.swift +++ b/GoldWars/GoldWars/Scenes/GameScene.swift @@ -8,6 +8,7 @@ import SpriteKit import GameplayKit +import GameKit class GameScene: SKScene{ @@ -22,54 +23,47 @@ class GameScene: SKScene{ entityManager.add(Background(size: self.size)) initMap() } - + func initMap() { MapFactory(scene: self, entityManager: self.entityManager).loadMap(playerCount: 2) } - + override func touchesEnded(_ touches: Set, with event: UIEvent?) { guard let touch = touches.first else { return } - + let touchLocation = touch.location(in: self) - - if isMoveTouch{ - isMoveTouch = false + + if isMoveTouch{ + isMoveTouch = false currentDraggedBase!.component(ofType: DefaultBaseComponent.self)?.spriteNode.position = currentDraggedBasePos currentDraggedBase!.component(ofType: TeamComponent.self)?.fire.position = currentDraggedBasePos - - for base in currentDraggedBase!.adjacencyList { - if atPoint(touchLocation) == base.component(ofType: DefaultBaseComponent.self)?.spriteNode { - // TODO: change interaction based on collision instead of touchlocation - - if !(entityManager.getTeamByBase(base: currentDraggedBase!) == entityManager.getTeamByBase(base: base)){ - entityManager.add(Modal(modaltype: .BaseAttack, - base: currentDraggedBase!, - anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2))) - entityManager.update((currentDraggedBase?.attackBase(base: base, units: 100))!) - }else { - entityManager.add(Modal(modaltype: .BaseAttack, - base: currentDraggedBase!, - anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2))) - } - - } - } - } + + for base in currentDraggedBase!.adjacencyList { + if atPoint(touchLocation) == base.component(ofType: DefaultBaseComponent.self)?.spriteNode { + // TODO: change interaction based on collision instead of touchlocation + + if !(entityManager.getTeamByBase(base: currentDraggedBase!) == entityManager.getTeamByBase(base: base)){ + entityManager.add(Modal(modaltype: .BaseAttack, + base: currentDraggedBase!, + anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2), + entityManager: entityManager, gameScene: self)) + entityManager.update((currentDraggedBase?.attackBase(base: base, units: 100))!) + }else { + entityManager.add(Modal(modaltype: .BaseAttack, + base: currentDraggedBase!, + anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2), + entityManager: entityManager, gameScene: self)) + } + + } + } + } else { for entity in entityManager.entities { let spriteNode = entity.component(ofType: DefaultBaseComponent.self)?.spriteNode - - if entityManager.isModal && entity.isMember(of: Modal.self) { - entityManager.remove(entity) - for child in self.children { - if(child.name != "fire"){ - child.alpha = 1 - } - } - } - + if atPoint(touchLocation) == spriteNode && !entityManager.isModal { spriteNode?.touchesBegan(touches, with: event) if !entityManager.isModal { @@ -80,33 +74,34 @@ class GameScene: SKScene{ } entityManager.add(Modal(modaltype: .BaseDetails, base: entity as! Base, - anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2))) + anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2), + entityManager: entityManager, gameScene: self)) } } } } - + } - + override func touchesMoved(_ touches: Set, with event: UIEvent?) { guard let touch = touches.first else { return } let touchLocation = touch.location(in: self) - - for child in children { - if atPoint(touchLocation) == child { - child.touchesMoved(touches, with: event) - } - } - - for e in entityManager.entities{ - if let body = e.component(ofType: ModalContentComponent.self)?.body{ - body.text = "Schicke \( ((e.component(ofType: SliderComponent.self)?.sliderNode.getValue ?? 0) * CGFloat((e as! Modal).unitCount)).rounded(.up)) Einheiten " - } } - - let bases = entityManager.getBasesByTeam(for: .team1) - + + for child in children { + if atPoint(touchLocation) == child { + child.touchesMoved(touches, with: event) + } + } + + for e in entityManager.entities{ + if let body = e.component(ofType: ModalContentComponent.self)?.body{ + body.text = "Schicke \( ((e.component(ofType: SliderComponent.self)?.sliderNode.getValue ?? 0) * CGFloat((e as! Modal).unitCount)).rounded(.up)) Einheiten " + } } + + let bases = entityManager.getBasesByPlayer(for: GKLocalPlayer.local) + for base in bases { if atPoint(touchLocation) == base.component(ofType: DefaultBaseComponent.self)?.spriteNode{ if !isMoveTouch { @@ -114,7 +109,7 @@ class GameScene: SKScene{ currentDraggedBase = base } isMoveTouch = true - + base.component(ofType: DefaultBaseComponent.self)?.spriteNode.position = touchLocation base.component(ofType: TeamComponent.self)?.fire.position = touchLocation for adjacencyBase in base.adjacencyList {