diff --git a/GoldWars/.idea/.gitignore b/GoldWars/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/GoldWars/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/GoldWars/.idea/GoldWars.iml b/GoldWars/.idea/GoldWars.iml new file mode 100644 index 0000000..74121dc --- /dev/null +++ b/GoldWars/.idea/GoldWars.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/GoldWars/.idea/misc.xml b/GoldWars/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/GoldWars/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/GoldWars/.idea/modules.xml b/GoldWars/.idea/modules.xml new file mode 100644 index 0000000..3bd1ffb --- /dev/null +++ b/GoldWars/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/GoldWars/.idea/runConfigurations/GoldWars.xml b/GoldWars/.idea/runConfigurations/GoldWars.xml new file mode 100644 index 0000000..447b8da --- /dev/null +++ b/GoldWars/.idea/runConfigurations/GoldWars.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/GoldWars/.idea/vcs.xml b/GoldWars/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/GoldWars/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/GoldWars/.idea/xcode.xml b/GoldWars/.idea/xcode.xml new file mode 100644 index 0000000..62ab3fc --- /dev/null +++ b/GoldWars/.idea/xcode.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/GoldWars/GoldWars.xcodeproj/project.pbxproj b/GoldWars/GoldWars.xcodeproj/project.pbxproj index 2255b11..1017e12 100644 --- a/GoldWars/GoldWars.xcodeproj/project.pbxproj +++ b/GoldWars/GoldWars.xcodeproj/project.pbxproj @@ -21,6 +21,8 @@ 3EBD242C245D8044003CECE7 /* GameCenterHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */; }; 3EBD242E245D9332003CECE7 /* Team.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EBD242D245D9332003CECE7 /* Team.swift */; }; 8BB6FF402472B8F000162BBD /* SkillButtonNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB6FF3F2472B8F000162BBD /* SkillButtonNode.swift */; }; + 3F745DF0246F48FC00CE7375 /* PlayerMoveType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F745DEF246F48FC00CE7375 /* PlayerMoveType.swift */; }; + 3FE19DB5246C7A22004827AB /* RoundCalculatorService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FE19DB4246C7A22004827AB /* RoundCalculatorService.swift */; }; 9E04AFAF245E2B73002D5CFC /* AttackActionComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E04AFAE245E2B73002D5CFC /* AttackActionComponent.swift */; }; 9E11FF79245CD81100EED3BE /* Fire.sks in Resources */ = {isa = PBXBuildFile; fileRef = 9E11FF77245CD81100EED3BE /* Fire.sks */; }; 9E174C82245DD81D00209FF0 /* ButtonNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E174C81245DD81D00209FF0 /* ButtonNode.swift */; }; @@ -39,6 +41,7 @@ 9EA3ABED245C8143006BC61D /* ModalBackgroundComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EA3ABEC245C8143006BC61D /* ModalBackgroundComponent.swift */; }; 9EA3ABEF245C834B006BC61D /* ModalContentComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EA3ABEE245C834B006BC61D /* ModalContentComponent.swift */; }; 9EBFD7552462CF5A00E1E219 /* SliderComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EBFD7542462CF5A00E1E219 /* SliderComponent.swift */; }; + 9EC239E1246878A900952F74 /* MultiplayerNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC239E0246878A900952F74 /* MultiplayerNetwork.swift */; }; 9EC7E48B2461FBF700396BCD /* SliderNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC7E48A2461FBF700396BCD /* SliderNode.swift */; }; 9EC86B9F245C88A300796EF3 /* Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC86B9E245C88A300796EF3 /* Modal.swift */; }; 9EC86BA6245C8AD000796EF3 /* ModalType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC86BA5245C8AD000796EF3 /* ModalType.swift */; }; @@ -49,12 +52,15 @@ 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 */; }; C064E9A8246C0EA50022B228 /* LabelNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = C064E9A7246C0EA50022B228 /* LabelNode.swift */; }; C064E9AA246C114C0022B228 /* LabelComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C064E9A9246C114C0022B228 /* LabelComponent.swift */; }; C064E9AC246C151F0022B228 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = C064E9AB246C151F0022B228 /* Label.swift */; }; + C099579C246C5E5C0016AA22 /* DataService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C099579B246C5E5C0016AA22 /* DataService.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -86,6 +92,8 @@ 3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCenterHelper.swift; sourceTree = ""; }; 3EBD242D245D9332003CECE7 /* Team.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Team.swift; sourceTree = ""; }; 8BB6FF3F2472B8F000162BBD /* SkillButtonNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkillButtonNode.swift; sourceTree = ""; }; + 3F745DEF246F48FC00CE7375 /* PlayerMoveType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerMoveType.swift; sourceTree = ""; }; + 3FE19DB4246C7A22004827AB /* RoundCalculatorService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundCalculatorService.swift; sourceTree = ""; }; 9E04AFAE245E2B73002D5CFC /* AttackActionComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttackActionComponent.swift; sourceTree = ""; }; 9E11FF77245CD81100EED3BE /* Fire.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Fire.sks; sourceTree = ""; }; 9E174C81245DD81D00209FF0 /* ButtonNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ButtonNode.swift; sourceTree = ""; }; @@ -99,11 +107,12 @@ 9E78ACBD245CC9C000526FF7 /* AtkBoostSkillComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtkBoostSkillComponent.swift; sourceTree = ""; }; 9E78ACC1245CC9EE00526FF7 /* DefBoostSkillComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefBoostSkillComponent.swift; sourceTree = ""; }; 9E78ACC3245CCA3600526FF7 /* SpySkillComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpySkillComponent.swift; sourceTree = ""; }; - 9EA3ABE8245C6DAA006BC61D /* DefaultBaseComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultBaseComponent.swift; sourceTree = ""; }; + 9EA3ABE8245C6DAA006BC61D /* DefaultBaseComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultBaseComponent.swift; sourceTree = ""; wrapsLines = 1; }; 9EA3ABEA245C6DFA006BC61D /* BaseNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseNode.swift; sourceTree = ""; }; 9EA3ABEC245C8143006BC61D /* ModalBackgroundComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalBackgroundComponent.swift; sourceTree = ""; }; 9EA3ABEE245C834B006BC61D /* ModalContentComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalContentComponent.swift; sourceTree = ""; }; 9EBFD7542462CF5A00E1E219 /* SliderComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SliderComponent.swift; sourceTree = ""; }; + 9EC239E0246878A900952F74 /* MultiplayerNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiplayerNetwork.swift; sourceTree = ""; }; 9EC7E48A2461FBF700396BCD /* SliderNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderNode.swift; sourceTree = ""; }; 9EC86B9E245C88A300796EF3 /* Modal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modal.swift; sourceTree = ""; }; 9EC86BA5245C8AD000796EF3 /* ModalType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalType.swift; sourceTree = ""; }; @@ -115,12 +124,15 @@ 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 = ""; }; C064E9A7246C0EA50022B228 /* LabelNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelNode.swift; sourceTree = ""; }; C064E9A9246C114C0022B228 /* LabelComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelComponent.swift; sourceTree = ""; }; C064E9AB246C151F0022B228 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; + C099579B246C5E5C0016AA22 /* DataService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataService.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -177,9 +189,14 @@ C05FAED52468559D0006AF2E /* SoundManager.swift */, 110360DA244B101A008610AF /* GameViewController.swift */, 110360DF244B101B008610AF /* Assets.xcassets */, + 9EC239E0246878A900952F74 /* MultiplayerNetwork.swift */, + C099579B246C5E5C0016AA22 /* DataService.swift */, 110360E4244B101B008610AF /* Info.plist */, AE151588245F18EF001D363E /* MatchmakingHelper.swift */, + 3FE19DB4246C7A22004827AB /* RoundCalculatorService.swift */, 3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */, + AEBF3B00246EB187004F7CD5 /* CancelBtnComponent.swift */, + AEBF3AFE246EB146004F7CD5 /* CancelBtnNode.swift */, C04783EF24685995004961FB /* SettingsScene.swift */, C064E9A7246C0EA50022B228 /* LabelNode.swift */, C064E9A9246C114C0022B228 /* LabelComponent.swift */, @@ -257,6 +274,7 @@ 11738A3A24508F68004426F1 /* UnitType.swift */, 9EC86BA5245C8AD000796EF3 /* ModalType.swift */, 3EBD242D245D9332003CECE7 /* Team.swift */, + 3F745DEF246F48FC00CE7375 /* PlayerMoveType.swift */, ); path = Enums; sourceTree = ""; @@ -394,7 +412,9 @@ files = ( 9E78ACB8245CB75B00526FF7 /* TeamComponent.swift in Sources */, 9EA3ABEF245C834B006BC61D /* ModalContentComponent.swift in Sources */, + 3FE19DB5246C7A22004827AB /* RoundCalculatorService.swift in Sources */, 9EC86BA6245C8AD000796EF3 /* ModalType.swift in Sources */, + 9EC239E1246878A900952F74 /* MultiplayerNetwork.swift in Sources */, 9E78ACBE245CC9C000526FF7 /* AtkBoostSkillComponent.swift in Sources */, 9E78ACC4245CCA3600526FF7 /* SpySkillComponent.swift in Sources */, 9EA3ABEB245C6DFA006BC61D /* BaseNode.swift in Sources */, @@ -411,13 +431,16 @@ 9E174C86245DD91500209FF0 /* ButtonComponent.swift in Sources */, AE151589245F18EF001D363E /* MatchmakingHelper.swift in Sources */, 11036113244B3E30008610AF /* MenuScene.swift in Sources */, + C099579C246C5E5C0016AA22 /* DataService.swift in Sources */, 9EA3ABE9245C6DAA006BC61D /* DefaultBaseComponent.swift in Sources */, 9E174C8A245E1A0A00209FF0 /* Background.swift in Sources */, 8BB6FF402472B8F000162BBD /* SkillButtonNode.swift in Sources */, 9EA3ABED245C8143006BC61D /* ModalBackgroundComponent.swift in Sources */, C064E9A8246C0EA50022B228 /* LabelNode.swift in Sources */, 3EBD242C245D8044003CECE7 /* GameCenterHelper.swift in Sources */, + 3F745DF0246F48FC00CE7375 /* PlayerMoveType.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 */, @@ -427,6 +450,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 */, @@ -593,8 +617,8 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = GoldWars/GoldWars.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = DDKFQG46BQ; INFOPLIST_FILE = GoldWars/Info.plist; @@ -605,7 +629,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = de.hft.stuttgart.ip2.goldwars; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "Developer Profile"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 2; }; @@ -616,8 +640,8 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = GoldWars/GoldWars.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = DDKFQG46BQ; INFOPLIST_FILE = GoldWars/Info.plist; 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/Components/TeamComponent.swift b/GoldWars/GoldWars/Components/TeamComponent.swift index 2369f7b..db67deb 100644 --- a/GoldWars/GoldWars/Components/TeamComponent.swift +++ b/GoldWars/GoldWars/Components/TeamComponent.swift @@ -11,9 +11,9 @@ import GameplayKit import GameKit class TeamComponent: GKComponent { - let team: Team + var team: Team + var player: GKPlayer let fire: SKEmitterNode - let player: GKPlayer init(team: Team, player: GKPlayer, position: CGPoint) { fire = SKEmitterNode(fileNamed: "Fire")! diff --git a/GoldWars/GoldWars/Components/TimerComponent.swift b/GoldWars/GoldWars/Components/TimerComponent.swift index 816ca04..52c51b6 100644 --- a/GoldWars/GoldWars/Components/TimerComponent.swift +++ b/GoldWars/GoldWars/Components/TimerComponent.swift @@ -9,12 +9,12 @@ import GameplayKit class TimerComponent: GKComponent { - + let labelNode :SKLabelNode var endTime :Date! var duration :Double - - init(text: String, anchorPoint: CGPoint, duration: TimeInterval) { + + init(text: String, anchorPoint: CGPoint, duration: TimeInterval) { self.labelNode = SKLabelNode(text: text) self.labelNode.fontColor = UIColor.black self.labelNode.fontSize = CGFloat(45) @@ -26,6 +26,7 @@ class TimerComponent: GKComponent { func startWithDuration(duration: TimeInterval){ endTime = Date().addingTimeInterval(duration) + RoundCalculatorService.sharedInstance.isCalculating = false } func timeLeft() -> Int { @@ -45,12 +46,20 @@ class TimerComponent: GKComponent { if(isFinished()){ self.labelNode.text = "Synching" + if !MultiplayerNetwork.sharedInstance.isSending { + MultiplayerNetwork.sharedInstance.sendPlayerMoves(playerMoves: DataService.sharedInstance.localPlayerMoves) + } + if !RoundCalculatorService.sharedInstance.isCalculating + && DataService.sharedInstance.didReceiveAllData() + && MatchmakingHelper.sharedInstance.isServer { + RoundCalculatorService.sharedInstance.calculateRound() + } } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + } diff --git a/GoldWars/GoldWars/DataService.swift b/GoldWars/GoldWars/DataService.swift new file mode 100644 index 0000000..e06dff6 --- /dev/null +++ b/GoldWars/GoldWars/DataService.swift @@ -0,0 +1,72 @@ +// +// PlayerMovesService.swift +// GoldWars +// +// Created by Tim Herbst on 13.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +struct PlayerMove: Codable{ + let fromBase: Int + let toBase: Int + var unitCount: Int +} + +struct Host: Codable { + let playerName: String +} + +class SnapshotModel: Codable { + var baseEntites: [BaseEntityModel] + + init(baseEntites: [BaseEntityModel]) { + self.baseEntites = baseEntites + } +} + +class BaseEntityModel: Codable { + let baseId: Int + var unitCount: Int + var ownership: String? + + init(baseId: Int, unitCount: Int, ownership: String?) { + self.baseId = baseId + self.unitCount = unitCount + self.ownership = ownership + } +} + +class DataService { + static let sharedInstance = DataService() + var localPlayerMoves: [PlayerMove] = [] + var remotePlayerMoves: [String: [PlayerMove]] = [:] + var snapshotModel: SnapshotModel? + var gameHost: Host? + + func addMove(playerMove: PlayerMove) { + var equalMove = localPlayerMoves.filter { (ele) -> Bool in + ele.fromBase == playerMove.fromBase && ele.toBase == playerMove.toBase + } + if equalMove.count == 1 { + equalMove[0].unitCount = Int(equalMove[0].unitCount) + Int(playerMove.unitCount) + } else { + self.localPlayerMoves.append(playerMove) + } + } + + func addRemotePlayerMoves(playerName: String, playerMoves: [PlayerMove]) { + self.remotePlayerMoves[playerName] = playerMoves + } + + func didReceiveAllData() -> Bool { + return remotePlayerMoves.count == MatchmakingHelper.sharedInstance.mpMatch?.players.count + } + + func setGameHost(host: Host) { + self.gameHost = host + } + + func setSnapshotModel(snapshotModel: SnapshotModel) { + self.snapshotModel = snapshotModel + } +} diff --git a/GoldWars/GoldWars/Entities/Base.swift b/GoldWars/GoldWars/Entities/Base.swift index d9b865a..322d328 100644 --- a/GoldWars/GoldWars/Entities/Base.swift +++ b/GoldWars/GoldWars/Entities/Base.swift @@ -10,13 +10,14 @@ import SpriteKit import GameplayKit import GameKit -class Base: GKEntity { - +class Base: GKEntity{ + static var BASE_ID_COUNT: Int = 0 var unitCount: Int var unitType: UnitType var adjacencyList: Array var changeOwnership: Bool var ownershipPlayer: GKPlayer? + var baseID: Int init(position: CGPoint, player: GKPlayer! = nil, team: Team! = nil) { self.unitCount = 0 @@ -24,6 +25,8 @@ class Base: GKEntity { self.adjacencyList = [Base]() self.changeOwnership = false self.ownershipPlayer = player + self.baseID = Base.BASE_ID_COUNT + Base.BASE_ID_COUNT += 1 super.init() addComponent(DefaultBaseComponent(texture: SKTexture(imageNamed: "Base"), position: position)) @@ -33,11 +36,14 @@ class Base: GKEntity { } } - func attackBase(base: Base, units:Int) -> [GKEntity]{ + func doPlayerMoveTypeToBase(base: Base, playerMoveType: PlayerMoveType, 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 * playerMoveType.rawValue)) return [self, base] } diff --git a/GoldWars/GoldWars/Entities/EntityManager.swift b/GoldWars/GoldWars/Entities/EntityManager.swift index 66e9964..7260b2d 100644 --- a/GoldWars/GoldWars/Entities/EntityManager.swift +++ b/GoldWars/GoldWars/Entities/EntityManager.swift @@ -74,6 +74,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) } @@ -99,6 +103,10 @@ class EntityManager { modalButton.buttonNode.removeFromParent() isModal = false } + if let cancelBtnNode = entity.component(ofType: CancelBtnComponent.self)?.cancelBtnNode { + cancelBtnNode.removeFromParent() + isModal = false + } entities.remove(entity) } @@ -108,17 +116,55 @@ 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 let fire = entity.component(ofType: TeamComponent.self)?.fire{ + scene.addChild(fire) + } base.changeOwnership = false - scene.addChild(base.component(ofType: TeamComponent.self)!.fire) } } - + } + + func updateSnapshotModel(snapshotModel: SnapshotModel) { + let bases = entities.filter{$0 is Base} + for entity in bases{ + let base = entity as! Base + let snapBase = self.getSnapshotBaseById(baseId: base.baseID, snapshotModel: snapshotModel) + var getOwnerBySnapBase: GKPlayer? = nil + base.unitCount = snapBase.unitCount + + if snapBase.ownership != nil { + getOwnerBySnapBase = MatchmakingHelper.sharedInstance.getGKPlayerByUsername(displayName: snapBase.ownership!) + } + 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 let fire = entity.component(ofType: TeamComponent.self)?.fire{ + scene.addChild(fire) + } + } + } + } + + func getSnapshotBaseById(baseId: Int, snapshotModel: SnapshotModel) -> BaseEntityModel{ + return snapshotModel.baseEntites.filter { $0.baseId == baseId }[0] } func getBaseByPlayer(for player: GKPlayer) -> GKEntity? { @@ -166,6 +212,19 @@ class EntityManager { return nil } + func getTeamByPlayer(playerName: String) -> Team { + return entities.filter { $0 is Base && ($0 as! Base).component(ofType: TeamComponent.self)?.player.displayName == playerName }[0].component(ofType: TeamComponent.self)!.team + } + + func getBasebyID(id: Int) -> Base?{ + for entity in entities { + if entity is Base && (entity as! Base).baseID == id { + return (entity as! Base) + } + } + return nil + } + func getBackground() -> GKEntity? { return entities.filter{$0 is Background}[0] } @@ -181,4 +240,18 @@ class EntityManager { func getHUD() -> GKEntity? { return entities.filter{$0 is HUD}[0] } + + + + func getSnapshotModel() -> SnapshotModel { + let bases = entities.filter{$0 is Base} + var snapBase: [BaseEntityModel] = [] + + for entity in bases { + let base = entity as! Base + snapBase.append(BaseEntityModel(baseId: base.baseID, unitCount: base.unitCount, ownership: base.ownershipPlayer?.displayName)) + } + + return SnapshotModel(baseEntites: snapBase) + } } diff --git a/GoldWars/GoldWars/Entities/Modal.swift b/GoldWars/GoldWars/Entities/Modal.swift index 516efb0..c01999e 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?.doPlayerMoveTypeToBase(base: base, playerMoveType: PlayerMoveType.AtkMove, units: Int(GameScene.sendUnits)))!) + } + } + } } diff --git a/GoldWars/GoldWars/Enums/PlayerMoveType.swift b/GoldWars/GoldWars/Enums/PlayerMoveType.swift new file mode 100644 index 0000000..2f1bdd6 --- /dev/null +++ b/GoldWars/GoldWars/Enums/PlayerMoveType.swift @@ -0,0 +1,13 @@ +// +// PlayerMoveType.swift +// GoldWars +// +// Created by Aldin Duraki on 16.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +enum PlayerMoveType: Int, Codable{ + case AtkMove = 1 + case TxnMove = -1 +} + diff --git a/GoldWars/GoldWars/MatchmakingHelper.swift b/GoldWars/GoldWars/MatchmakingHelper.swift index a99bb31..a695d39 100644 --- a/GoldWars/GoldWars/MatchmakingHelper.swift +++ b/GoldWars/GoldWars/MatchmakingHelper.swift @@ -33,6 +33,8 @@ class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDe var viewController: UIViewController? var mpMatchStarted: Bool var isServer: Bool + var spieler1: GKPlayer? + var nameSpieler1 = "" var menusc: MenuScene? let localPlayer: GKLocalPlayer = GKLocalPlayer.local @@ -100,12 +102,27 @@ class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDe } /* - Vom match erhaltene Spielerdaten - */ - private func match(match: GKMatch!, didReceiveData data: NSData!,fromPlayer playerID: String!) { + Vom match erhaltene Spielerdaten + */ + func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) { if mpMatch != match { return } - delegate?.matchReceivedData(match: match, data: data, fromPlayer: playerID) + + let jsonDecoder = JSONDecoder() + if let playerMoves = try? jsonDecoder.decode([PlayerMove].self, from: data) { + DataService.sharedInstance.addRemotePlayerMoves(playerName: player.displayName, playerMoves: playerMoves) + } + + if let message = try? jsonDecoder.decode(Host.self, from: data) { + DataService.sharedInstance.gameHost = message + } + + if let snapshotModel = try? jsonDecoder.decode(SnapshotModel.self, from: data) { + DataService.sharedInstance.snapshotModel = snapshotModel + EntityManager.sharedInstance.updateSnapshotModel(snapshotModel: snapshotModel) + } + + MultiplayerNetwork.sharedInstance.isSending = false } /* @@ -152,15 +169,33 @@ class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDe if player == GKLocalPlayer.local { self.isServer = true + self.spieler1 = player + self.nameSpieler1 = self.spieler1!.displayName + DataService.sharedInstance.setGameHost(host: Host(playerName: player!.displayName)) } else { self.isServer = false } self.delegate?.matchStarted() self.menusc!.loadScene(scene: GameScene(size: self.menusc!.size)) + MultiplayerNetwork.sharedInstance.sendHostIdentifier() }) } + func getGKPlayerByUsername(displayName: String) -> GKPlayer? { + let nilGK : GKPlayer? = nil + + if GKLocalPlayer.local.displayName == displayName { + return GKLocalPlayer.local + } + + for player in mpMatch!.players { + if player.displayName == displayName { + return player + } + } + return nilGK + } /* Trennt die Verbindung vom Match diff --git a/GoldWars/GoldWars/MultiplayerNetwork.swift b/GoldWars/GoldWars/MultiplayerNetwork.swift new file mode 100644 index 0000000..7ffbc37 --- /dev/null +++ b/GoldWars/GoldWars/MultiplayerNetwork.swift @@ -0,0 +1,64 @@ +// +// MultiplayerNetwork.swift +// GoldWars +// +// Created by Niko Jochim on 10.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import GameplayKit +import Foundation +import GameKit + +class MultiplayerNetwork{ + static let sharedInstance = MultiplayerNetwork() + + var isSending = false + + func sendData(data: Data) { + let mmHelper = MatchmakingHelper.sharedInstance + if let multiplayerMatch = mmHelper.mpMatch { + do { + try multiplayerMatch.sendData(toAllPlayers: data, with: .reliable) + } catch { + //TODO: Add logging + } + } + } + + func sendDataToHost(data: Data) { + let mmHelper = MatchmakingHelper.sharedInstance + let hostGKPlayer = MatchmakingHelper.sharedInstance.mpMatch?.players.filter{ $0.displayName == DataService.sharedInstance.gameHost!.playerName}[0] + + if let multiplayerMatch = mmHelper.mpMatch{ + do { + try multiplayerMatch.send(data, to: [hostGKPlayer!], dataMode: .reliable) + } catch { + //TODO: Add logging + } + } + } + + func sendPlayerMoves(playerMoves: [PlayerMove]) { + if MatchmakingHelper.sharedInstance.isServer == false { + self.isSending = true + let encoder = JSONEncoder() + let encoded = (try? encoder.encode(playerMoves))! + sendDataToHost(data: encoded) + } + DataService.sharedInstance.localPlayerMoves.removeAll() + } + + func sendHostIdentifier() { + let encoder = JSONEncoder() + let encoded = (try? encoder.encode(DataService.sharedInstance.gameHost))! + sendData(data: encoded) + } + + func sendSnapshotModelToPlayers() { + let encoder = JSONEncoder() + let encoded = (try? encoder.encode(DataService.sharedInstance.snapshotModel))! + sendData(data: encoded) + } + +} diff --git a/GoldWars/GoldWars/PlayerMovesService.swift b/GoldWars/GoldWars/PlayerMovesService.swift new file mode 100644 index 0000000..3c0f41d --- /dev/null +++ b/GoldWars/GoldWars/PlayerMovesService.swift @@ -0,0 +1,32 @@ +// +// PlayerMovesService.swift +// GoldWars +// +// Created by Tim Herbst on 13.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +struct PlayerMove : Codable{ + let fromBase: Int + let toBase: Int + let unitCount: Int +} + +struct Host: Codable { + let playerName: String +} + +class DataService { + static let sharedInstance = DataService() + var playerMoves: [PlayerMove] = [] + var gameHost: Host? + + + func addMove(playerMove: PlayerMove) { + self.playerMoves.append(playerMove) + } + + func setGameHost(host: Host) { + self.gameHost = host + } +} diff --git a/GoldWars/GoldWars/RoundCalculatorService.swift b/GoldWars/GoldWars/RoundCalculatorService.swift new file mode 100644 index 0000000..3704ec8 --- /dev/null +++ b/GoldWars/GoldWars/RoundCalculatorService.swift @@ -0,0 +1,124 @@ +// +// RoundCalculatorService.swift +// GoldWars +// +// Created by Aldin Duraki on 13.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import GameKit +import os + +class RoundCalculatorService { + static let sharedInstance = RoundCalculatorService() + static let LOG = OSLog.init(subsystem: "Round Calculator", category: "RoundCalculatorService") + + var allPlayerMoves: [String: [PlayerMove]] = [:] + var baseSpecificMoves: [Int: [String: [PlayerMove]]] = [:] + + var isCalculating = false + + func calculateRound() { + os_log("Started calculating Round", log: RoundCalculatorService.LOG, type: .info) + isCalculating = true + let currentSnapshotModel = DataService.sharedInstance.snapshotModel + + for playerMove in DataService.sharedInstance.remotePlayerMoves { + addPlayerMove(playerName: playerMove.key, playerMoves: playerMove.value) + } + addPlayerMove(playerName: GKLocalPlayer.local.displayName, playerMoves: DataService.sharedInstance.localPlayerMoves) + + for playerMove in allPlayerMoves { + for move in playerMove.value { + mapPlayerMoveToAttackedBase(playerName: playerMove.key, playerMove: move) + } + } + + // TODO: Refactor to a less complex way + for (key, value) in baseSpecificMoves { + let baseId = key + var playerMovesByBase = value + let targetBase = currentSnapshotModel?.baseEntites.filter { $0.baseId == baseId }[0] + let possiblyOwnershipMoves = playerMovesByBase.filter { $0.key == targetBase?.ownership} + + for (playerName, playerMoves) in possiblyOwnershipMoves { + for playerMove in playerMoves { + for base in currentSnapshotModel!.baseEntites { + if base.baseId == playerMove.fromBase { + base.unitCount -= playerMove.unitCount + } + if base.baseId == playerMove.toBase { + base.unitCount += playerMove.unitCount + } + } + } + playerMovesByBase.removeValue(forKey: playerName) + } + + for (_, playerMoves) in playerMovesByBase { + for playerMove in playerMoves { + for base in currentSnapshotModel!.baseEntites { + if base.baseId == playerMove.fromBase { + base.unitCount -= playerMove.unitCount + } + } + } + } + + var combinePotentionalForces: [String: PlayerMove] = [:] + + for playerMoves in playerMovesByBase { + combinePotentionalForces[playerMoves.key] = PlayerMove(fromBase: playerMoves.value[0].fromBase, toBase: playerMoves.value[0].toBase, unitCount: 0) + for move in playerMoves.value { + combinePotentionalForces[playerMoves.key]!.unitCount += move.unitCount + } + } + if(combinePotentionalForces.count > 0) { + let sortedPotentionalCombinedForces = combinePotentionalForces.sorted { $0.1.unitCount > $1.1.unitCount } + + var playerMoveWithMaxUnits = sortedPotentionalCombinedForces[0] + if playerMovesByBase.count >= 2 { + let playerMoveWithSecMaxUnits = sortedPotentionalCombinedForces[1] + playerMoveWithMaxUnits.value.unitCount -= playerMoveWithSecMaxUnits.value.unitCount + } + + for base in currentSnapshotModel!.baseEntites { + if base.baseId == playerMoveWithMaxUnits.value.toBase { + base.unitCount += playerMoveWithMaxUnits.value.unitCount + if playerMoveWithMaxUnits.value.unitCount == 0 { + base.ownership = nil + } else { + base.ownership = playerMoveWithMaxUnits.key + } + } + } + } + baseSpecificMoves.removeValue(forKey: baseId) + } + allPlayerMoves.removeAll() + MultiplayerNetwork.sharedInstance.sendSnapshotModelToPlayers() + EntityManager.sharedInstance.updateSnapshotModel(snapshotModel: currentSnapshotModel!) + os_log("Finished calculating Round", log: RoundCalculatorService.LOG, type: .info) + } + + func addPlayerMove(playerName: String, playerMoves: [PlayerMove]) { + self.allPlayerMoves[playerName] = playerMoves + } + + func mapPlayerMoveToAttackedBase(playerName: String, playerMove: PlayerMove) { + if self.baseSpecificMoves.keys.contains(playerMove.toBase) { + if (self.baseSpecificMoves[playerMove.toBase]?.keys.contains(playerName))!{ + self.baseSpecificMoves[playerMove.toBase]?[playerName]?.append(playerMove) + } else { + self.baseSpecificMoves[playerMove.toBase]?.merge([playerName: [playerMove]]){(current, _) in current} + } + } else { + self.baseSpecificMoves[playerMove.toBase] = [playerName: [playerMove]] + } + } + + func resolvePlayerMove(playerMove: PlayerMove, unitCount: Int, ownership: String?, resolveType: String) { + //TODO: outsource playermoves + } + +} diff --git a/GoldWars/GoldWars/Scenes/GameScene.swift b/GoldWars/GoldWars/Scenes/GameScene.swift index 85d512e..7b91850 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) @@ -25,6 +27,7 @@ class GameScene: SKScene{ func initMap() { MapFactory(scene: self, entityManager: EntityManager.sharedInstance).loadMap(playerCount: 2) + DataService.sharedInstance.setSnapshotModel(snapshotModel: EntityManager.sharedInstance.getSnapshotModel()) } override func touchesEnded(_ touches: Set, with event: UIEvent?) { @@ -39,44 +42,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 +65,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) + ])) + } + } } diff --git a/GoldWars/GoldWars/SoundManager.swift b/GoldWars/GoldWars/SoundManager.swift index 4f8f34d..b6cb5d4 100644 --- a/GoldWars/GoldWars/SoundManager.swift +++ b/GoldWars/GoldWars/SoundManager.swift @@ -23,7 +23,7 @@ class SoundManager { do { audioPlayer = try AVAudioPlayer(contentsOf: backgroundMainMenuAudio!) } catch { - print("Datei nicht gefunden!") + //TODO: Add logging } audioPlayer.numberOfLoops = -1 audioPlayer.prepareToPlay() diff --git a/GoldWars/GoldWars/Storyboards/RoundSimulatorService.swift b/GoldWars/GoldWars/Storyboards/RoundSimulatorService.swift new file mode 100644 index 0000000..4847831 --- /dev/null +++ b/GoldWars/GoldWars/Storyboards/RoundSimulatorService.swift @@ -0,0 +1,13 @@ +// +// RoundSimulatorService.swift +// GoldWars +// +// Created by student on 13.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import Foundation + +class RoundSimulatorService { + +}