diff --git a/GoldWars/GoldWars.xcodeproj/project.pbxproj b/GoldWars/GoldWars.xcodeproj/project.pbxproj index 8b35a21..9f1328a 100644 --- a/GoldWars/GoldWars.xcodeproj/project.pbxproj +++ b/GoldWars/GoldWars.xcodeproj/project.pbxproj @@ -48,6 +48,8 @@ AB1D75A0245DEC0500671525 /* MapFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB1D759F245DEC0500671525 /* MapFactory.swift */; }; ABA03DA0244BD54F00A66916 /* Base.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA03D9F244BD54F00A66916 /* Base.swift */; }; AE151589245F18EF001D363E /* MatchmakingHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE151588245F18EF001D363E /* MatchmakingHelper.swift */; }; + AEBF3AFF246EB146004F7CD5 /* CancelBtnNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEBF3AFE246EB146004F7CD5 /* CancelBtnNode.swift */; }; + AEBF3B01246EB187004F7CD5 /* CancelBtnComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEBF3B00246EB187004F7CD5 /* CancelBtnComponent.swift */; }; C04783EE2468583F004961FB /* intro-music.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C04783ED2468583F004961FB /* intro-music.mp3 */; }; C04783F024685995004961FB /* SettingsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04783EF24685995004961FB /* SettingsScene.swift */; }; C05FAED62468559D0006AF2E /* SoundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05FAED52468559D0006AF2E /* SoundManager.swift */; }; @@ -113,6 +115,8 @@ AB1D759F245DEC0500671525 /* MapFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapFactory.swift; sourceTree = ""; }; ABA03D9F244BD54F00A66916 /* Base.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Base.swift; sourceTree = ""; }; AE151588245F18EF001D363E /* MatchmakingHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchmakingHelper.swift; sourceTree = ""; }; + AEBF3AFE246EB146004F7CD5 /* CancelBtnNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CancelBtnNode.swift; sourceTree = ""; }; + AEBF3B00246EB187004F7CD5 /* CancelBtnComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CancelBtnComponent.swift; sourceTree = ""; }; C04783ED2468583F004961FB /* intro-music.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = "intro-music.mp3"; sourceTree = ""; }; C04783EF24685995004961FB /* SettingsScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScene.swift; sourceTree = ""; }; C05FAED52468559D0006AF2E /* SoundManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoundManager.swift; sourceTree = ""; }; @@ -178,6 +182,8 @@ 110360E4244B101B008610AF /* Info.plist */, AE151588245F18EF001D363E /* MatchmakingHelper.swift */, 3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */, + AEBF3B00246EB187004F7CD5 /* CancelBtnComponent.swift */, + AEBF3AFE246EB146004F7CD5 /* CancelBtnNode.swift */, C04783EF24685995004961FB /* SettingsScene.swift */, C064E9A7246C0EA50022B228 /* LabelNode.swift */, C064E9A9246C114C0022B228 /* LabelComponent.swift */, @@ -414,6 +420,7 @@ C064E9A8246C0EA50022B228 /* LabelNode.swift in Sources */, 3EBD242C245D8044003CECE7 /* GameCenterHelper.swift in Sources */, AB1D759C245DD18100671525 /* MapProtocol.swift in Sources */, + AEBF3B01246EB187004F7CD5 /* CancelBtnComponent.swift in Sources */, AB1D75A0245DEC0500671525 /* MapFactory.swift in Sources */, AB1D759D245DD18100671525 /* TwoPlayerDefaultTestMap.swift in Sources */, 9EBFD7552462CF5A00E1E219 /* SliderComponent.swift in Sources */, @@ -423,6 +430,7 @@ 9EC7E48B2461FBF700396BCD /* SliderNode.swift in Sources */, 9EEDE02F246FCD800096C735 /* SpinningLogoComponent.swift in Sources */, 9E174C84245DD8CE00209FF0 /* Button.swift in Sources */, + AEBF3AFF246EB146004F7CD5 /* CancelBtnNode.swift in Sources */, 110360DB244B101A008610AF /* GameViewController.swift in Sources */, 2086465C2461B66200817C23 /* TimerComponent.swift in Sources */, 110360D3244B101A008610AF /* AppDelegate.swift in Sources */, diff --git a/GoldWars/GoldWars/CancelBtnComponent.swift b/GoldWars/GoldWars/CancelBtnComponent.swift new file mode 100644 index 0000000..7d15f68 --- /dev/null +++ b/GoldWars/GoldWars/CancelBtnComponent.swift @@ -0,0 +1,27 @@ +// +// CancelBtnComponent.swift +// GoldWars +// +// Created by Chauntalle Schüle on 15.05.20. +// Copyright © 2020 SP2. All rights reserved. +// +import GameplayKit +import SpriteKit + +class CancelBtnComponent: GKComponent { + + var cancelBtnNode: CancelBtnNode + + init(iconName: String, text: String, position: CGPoint, isEnabled:Bool, onButtonPress: @escaping () -> ()) { + cancelBtnNode = CancelBtnNode(iconName: iconName, + text: text, + isEnabled: isEnabled, + position: position, + onButtonPress: onButtonPress) + super.init() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/GoldWars/GoldWars/CancelBtnNode.swift b/GoldWars/GoldWars/CancelBtnNode.swift new file mode 100644 index 0000000..770baa5 --- /dev/null +++ b/GoldWars/GoldWars/CancelBtnNode.swift @@ -0,0 +1,57 @@ +// +// CancelBtnNode.swift +// GoldWars +// +// Created by Chauntalle Schüle on 15.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import SpriteKit + +class CancelBtnNode: SKSpriteNode { + + var isEnabled: Bool{ + didSet{ + if isEnabled { + self.alpha = 1 + self.childNode(withName: "label")?.alpha = 1 + } else { + self.alpha = 0.3 + self.childNode(withName: "label")?.alpha = 0.3 + } + } + } + + let onButtonPress: () -> () + + init(iconName: String, text: String, isEnabled: Bool, position: CGPoint, onButtonPress: @escaping () -> ()) { + self.onButtonPress = onButtonPress + self.isEnabled = isEnabled + let texture = SKTexture(imageNamed: "yellow_cross") + super.init(texture: texture, color: SKColor.white, size: texture.size()) + self.size = CGSize(width: 30, height: 30) + self.position = position + isUserInteractionEnabled = true + } + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + if isEnabled { + let action = SKAction.sequence( + [ + SKAction.scale(by: (3/4), duration: 0.3), + SKAction.scale(by: (4/3), duration: 0.3), + ] + ) + + self.childNode(withName: "label")?.run(action) + self.run(action) + onButtonPress() + } + } + + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} diff --git a/GoldWars/GoldWars/Entities/EntityManager.swift b/GoldWars/GoldWars/Entities/EntityManager.swift index fd2ce27..b7d5de6 100644 --- a/GoldWars/GoldWars/Entities/EntityManager.swift +++ b/GoldWars/GoldWars/Entities/EntityManager.swift @@ -75,6 +75,10 @@ class EntityManager { if let labelNode = entity.component(ofType: LabelComponent.self)?.labelNode { scene.addChild(labelNode) } + 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) } @@ -100,6 +104,10 @@ class EntityManager { modalButton.buttonNode.removeFromParent() isModal = false } + if let cancelBtnNode = entity.component(ofType: CancelBtnComponent.self)?.cancelBtnNode { + cancelBtnNode.removeFromParent() + isModal = false + } entities.remove(entity) } diff --git a/GoldWars/GoldWars/Entities/Modal.swift b/GoldWars/GoldWars/Entities/Modal.swift index 516efb0..aadd374 100644 --- a/GoldWars/GoldWars/Entities/Modal.swift +++ b/GoldWars/GoldWars/Entities/Modal.swift @@ -12,7 +12,7 @@ class Modal: GKEntity{ var unitCount:Int - init(modaltype: ModalType, base: Base, anchorPoint: CGPoint, entityManager: EntityManager, gameScene: SKScene) { + init(modaltype: ModalType, base: Base, anchorPoint: CGPoint, gameScene: GameScene, currentDraggedBase: Base?, touchLocation: CGPoint, collisionBase: Base?) { unitCount = base.unitCount super.init() switch modaltype{ @@ -20,7 +20,7 @@ class Modal: GKEntity{ 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) + self.removeModalEntities(gameScene: gameScene) })) case .BaseAttack: addComponent(ModalBackgroundComponent(anchorPoint: anchorPoint)) @@ -28,7 +28,11 @@ class Modal: GKEntity{ 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) + self.sendUnits(currentDraggedBase: currentDraggedBase, touchLocation: touchLocation, gameScene: gameScene, collisionBase: collisionBase) + self.removeModalEntities(gameScene: gameScene) + })) + addComponent(CancelBtnComponent(iconName: "", text: "", position: CGPoint(x: anchorPoint.x + 160, y: anchorPoint.y + 140), isEnabled: true, onButtonPress: { + self.removeModalEntities(gameScene: gameScene) })) } } @@ -37,10 +41,10 @@ class Modal: GKEntity{ 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) + func removeModalEntities(gameScene: SKScene){ + for entity in EntityManager.sharedInstance.entities { + if EntityManager.sharedInstance.isModal && entity.isMember(of: Modal.self) { + EntityManager.sharedInstance.remove(entity) } for child in gameScene.children { if(child.name != "fire"){ @@ -49,4 +53,12 @@ class Modal: GKEntity{ } } } + + func sendUnits(currentDraggedBase: Base?, touchLocation: CGPoint, gameScene: GameScene, collisionBase: Base?){ + for base in currentDraggedBase!.adjacencyList { + if base == collisionBase { + EntityManager.sharedInstance.update((currentDraggedBase?.attackBase(base: base, units: Int(GameScene.sendUnits)))!) + } + } + } } diff --git a/GoldWars/GoldWars/Scenes/GameScene.swift b/GoldWars/GoldWars/Scenes/GameScene.swift index 85d512e..fb229f8 100644 --- a/GoldWars/GoldWars/Scenes/GameScene.swift +++ b/GoldWars/GoldWars/Scenes/GameScene.swift @@ -15,6 +15,8 @@ class GameScene: SKScene{ var isMoveTouch = false var currentDraggedBasePos = CGPoint() var currentDraggedBase : Base? + static var sendUnits: CGFloat = 0 + var collisionBase: Base? override func sceneDidLoad() { EntityManager.sharedInstance.setScene(scene: self) @@ -39,44 +41,13 @@ class GameScene: SKScene{ 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.sharedInstance.getTeamByBase(base: currentDraggedBase!) == EntityManager.sharedInstance.getTeamByBase(base: base)){ - EntityManager.sharedInstance.add(Modal(modaltype: .BaseAttack, - base: currentDraggedBase!, - anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2), - entityManager: EntityManager.sharedInstance, gameScene: self)) - EntityManager.sharedInstance.update((currentDraggedBase?.attackBase(base: base, units: 100))!) - }else { - EntityManager.sharedInstance.add(Modal(modaltype: .BaseAttack, - base: currentDraggedBase!, - anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2), - entityManager: EntityManager.sharedInstance, gameScene: self)) - } - - } - } + addAttackDetails(touchLocation: touchLocation) } else { for entity in EntityManager.sharedInstance.entities { let spriteNode = entity.component(ofType: DefaultBaseComponent.self)?.spriteNode - 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 - } - } - EntityManager.sharedInstance.add(Modal(modaltype: .BaseDetails, - base: entity as! Base, - anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2), - entityManager: EntityManager.sharedInstance, gameScene: self)) - } - } + addBaseDetails(touchLocation: touchLocation, spriteNode: spriteNode, touches: touches, event: event, entity: entity) } } @@ -93,37 +64,82 @@ class GameScene: SKScene{ child.touchesMoved(touches, with: event) } } - - for e in EntityManager.sharedInstance.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 " - } } + checkSlider() let bases = EntityManager.sharedInstance.getBasesByPlayer(for: GKLocalPlayer.local) - 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 - } - isMoveTouch = true - - base.component(ofType: DefaultBaseComponent.self)?.spriteNode.position = touchLocation - base.component(ofType: TeamComponent.self)?.fire.position = touchLocation - for adjacencyBase in base.adjacencyList { - let node = adjacencyBase.component(ofType: DefaultBaseComponent.self)?.spriteNode - node?.run(SKAction.sequence([ - SKAction.resize(byWidth: 2, height: 2, duration: 0.5), - SKAction.resize(byWidth: -2, height: -2, duration: 0.5) - ])) - } - } - } + checkBases(bases: bases, touchLocation: touchLocation) } override func update(_ currentTime: TimeInterval) { EntityManager.sharedInstance.getBackground()?.update(deltaTime: currentTime) EntityManager.sharedInstance.getHUD()?.component(ofType: TimerComponent.self)?.update() } + + 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 + } + } + 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)) + } + } + } + + func addAttackDetails(touchLocation: CGPoint){ + for base in currentDraggedBase!.adjacencyList { + 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)) + } + } + } + + func checkSlider(){ + 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) + body.text = "Schicke \(GameScene.sendUnits) Einheiten " + } + } + } + + 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 + } + isMoveTouch = true + moveFireAndBase(base: base, touchLocation: touchLocation) + showNearestBases(base: base) + } + } + } + + func moveFireAndBase(base: Base, touchLocation: CGPoint){ + base.component(ofType: DefaultBaseComponent.self)?.spriteNode.position = touchLocation + base.component(ofType: TeamComponent.self)?.fire.position = touchLocation + } + + func showNearestBases(base: Base){ + for adjacencyBase in base.adjacencyList { + let node = adjacencyBase.component(ofType: DefaultBaseComponent.self)?.spriteNode + node?.run(SKAction.sequence([ + SKAction.resize(byWidth: 2, height: 2, duration: 0.5), + SKAction.resize(byWidth: -2, height: -2, duration: 0.5) + ])) + } + } }