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 ebaec53..c92245c 100644 --- a/GoldWars/GoldWars.xcodeproj/project.pbxproj +++ b/GoldWars/GoldWars.xcodeproj/project.pbxproj @@ -16,10 +16,16 @@ 110360EE244B101B008610AF /* GoldWarsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 110360ED244B101B008610AF /* GoldWarsTests.swift */; }; 11036113244B3E30008610AF /* MenuScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11036112244B3E30008610AF /* MenuScene.swift */; }; 116060F7245C57D2004E5A36 /* EntityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 116060F6245C57D2004E5A36 /* EntityManager.swift */; }; - 11738A3B24508F68004426F1 /* Unit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11738A3A24508F68004426F1 /* Unit.swift */; }; + 11738A3B24508F68004426F1 /* UnitType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11738A3A24508F68004426F1 /* UnitType.swift */; }; 2086465C2461B66200817C23 /* TimerComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2086465B2461B66200817C23 /* TimerComponent.swift */; }; + 3E67854024728368007B9DE4 /* CElements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E67853F24728368007B9DE4 /* CElements.swift */; }; + 3E6785422472CBEC007B9DE4 /* Way.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E6785412472CBEC007B9DE4 /* Way.swift */; }; + 3E6785442472CC27007B9DE4 /* DefaultWayComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E6785432472CC27007B9DE4 /* DefaultWayComponent.swift */; }; 3EBD242C245D8044003CECE7 /* GameCenterHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */; }; 3EBD242E245D9332003CECE7 /* Team.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EBD242D245D9332003CECE7 /* Team.swift */; }; + 3F745DF0246F48FC00CE7375 /* PlayerMoveType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F745DEF246F48FC00CE7375 /* PlayerMoveType.swift */; }; + 3FE19DB5246C7A22004827AB /* RoundCalculatorService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FE19DB4246C7A22004827AB /* RoundCalculatorService.swift */; }; + 8BB6FF402472B8F000162BBD /* SkillButtonNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB6FF3F2472B8F000162BBD /* SkillButtonNode.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 */; }; @@ -38,14 +44,27 @@ 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 */; }; + 9EC2FBA72476B1EC00ABF11F /* PlayerInfoComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC2FBA62476B1EC00ABF11F /* PlayerInfoComponent.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 */; }; - AB1D759C245DD18100671525 /* MapProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB1D759A245DD18100671525 /* MapProtocol.swift */; }; + 9EEDE02D246FCD770096C735 /* SpinningLogoEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EEDE02C246FCD770096C735 /* SpinningLogoEntity.swift */; }; + 9EEDE02F246FCD800096C735 /* SpinningLogoComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EEDE02E246FCD800096C735 /* SpinningLogoComponent.swift */; }; AB1D759D245DD18100671525 /* TwoPlayerDefaultTestMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB1D759B245DD18100671525 /* TwoPlayerDefaultTestMap.swift */; }; AB1D75A0245DEC0500671525 /* MapFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB1D759F245DEC0500671525 /* MapFactory.swift */; }; + AB21D7D5246C748A00B09CBA /* TwoPlayerMapGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB21D7D4246C748A00B09CBA /* TwoPlayerMapGenerator.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 */ @@ -72,10 +91,16 @@ 110360EF244B101B008610AF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 11036112244B3E30008610AF /* MenuScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuScene.swift; sourceTree = ""; }; 116060F6245C57D2004E5A36 /* EntityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntityManager.swift; sourceTree = ""; }; - 11738A3A24508F68004426F1 /* Unit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Unit.swift; sourceTree = ""; }; + 11738A3A24508F68004426F1 /* UnitType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnitType.swift; sourceTree = ""; }; 2086465B2461B66200817C23 /* TimerComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerComponent.swift; sourceTree = ""; }; + 3E67853F24728368007B9DE4 /* CElements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CElements.swift; sourceTree = ""; }; + 3E6785412472CBEC007B9DE4 /* Way.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Way.swift; sourceTree = ""; }; + 3E6785432472CC27007B9DE4 /* DefaultWayComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultWayComponent.swift; sourceTree = ""; }; 3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCenterHelper.swift; sourceTree = ""; }; 3EBD242D245D9332003CECE7 /* Team.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Team.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 = ""; }; + 8BB6FF3F2472B8F000162BBD /* SkillButtonNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkillButtonNode.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 = ""; }; @@ -89,20 +114,33 @@ 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 = ""; }; + 9EC2FBA62476B1EC00ABF11F /* PlayerInfoComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerInfoComponent.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 = ""; }; 9ECD3699245C91F7008DEEBD /* GoldWars.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = GoldWars.entitlements; sourceTree = ""; }; - AB1D759A245DD18100671525 /* MapProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapProtocol.swift; sourceTree = ""; }; + 9EEDE02C246FCD770096C735 /* SpinningLogoEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpinningLogoEntity.swift; sourceTree = ""; }; + 9EEDE02E246FCD800096C735 /* SpinningLogoComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpinningLogoComponent.swift; sourceTree = ""; }; AB1D759B245DD18100671525 /* TwoPlayerDefaultTestMap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwoPlayerDefaultTestMap.swift; sourceTree = ""; }; AB1D759F245DEC0500671525 /* MapFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapFactory.swift; sourceTree = ""; }; + AB21D7D4246C748A00B09CBA /* TwoPlayerMapGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoPlayerMapGenerator.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 */ @@ -146,6 +184,7 @@ 110360D1244B101A008610AF /* GoldWars */ = { isa = PBXGroup; children = ( + C04783ED2468583F004961FB /* intro-music.mp3 */, 9ECD3699245C91F7008DEEBD /* GoldWars.entitlements */, 9E11FF74245CD79100EED3BE /* Partikels */, 116060F5245C5709004E5A36 /* Entities */, @@ -155,11 +194,21 @@ 9EC86BA4245C8A1E00796EF3 /* Scenes */, 9EC86BA3245C89F400796EF3 /* Storyboards */, 110360D2244B101A008610AF /* AppDelegate.swift */, + 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 */, + C064E9AB246C151F0022B228 /* Label.swift */, ); path = GoldWars; sourceTree = ""; @@ -176,6 +225,7 @@ 116060F4245C56EA004E5A36 /* Components */ = { isa = PBXGroup; children = ( + 9EEDE02E246FCD800096C735 /* SpinningLogoComponent.swift */, 9E174C81245DD81D00209FF0 /* ButtonNode.swift */, 9EA3ABE8245C6DAA006BC61D /* DefaultBaseComponent.swift */, 9EA3ABEC245C8143006BC61D /* ModalBackgroundComponent.swift */, @@ -191,6 +241,9 @@ 2086465B2461B66200817C23 /* TimerComponent.swift */, 9EBFD7542462CF5A00E1E219 /* SliderComponent.swift */, 9EC7E48A2461FBF700396BCD /* SliderNode.swift */, + 3E6785432472CC27007B9DE4 /* DefaultWayComponent.swift */, + 8BB6FF3F2472B8F000162BBD /* SkillButtonNode.swift */, + 9EC2FBA62476B1EC00ABF11F /* PlayerInfoComponent.swift */, ); path = Components; sourceTree = ""; @@ -198,12 +251,14 @@ 116060F5245C5709004E5A36 /* Entities */ = { isa = PBXGroup; children = ( + 9E174C89245E1A0A00209FF0 /* Background.swift */, ABA03D9F244BD54F00A66916 /* Base.swift */, - 9EC86B9E245C88A300796EF3 /* Modal.swift */, + 9E174C83245DD8CE00209FF0 /* Button.swift */, 116060F6245C57D2004E5A36 /* EntityManager.swift */, 9E78ACB9245CBDAF00526FF7 /* HUD.swift */, - 9E174C83245DD8CE00209FF0 /* Button.swift */, - 9E174C89245E1A0A00209FF0 /* Background.swift */, + 9EC86B9E245C88A300796EF3 /* Modal.swift */, + 9EEDE02C246FCD770096C735 /* SpinningLogoEntity.swift */, + 3E6785412472CBEC007B9DE4 /* Way.swift */, ); path = Entities; sourceTree = ""; @@ -227,9 +282,10 @@ 9EC86BA2245C89B200796EF3 /* Enums */ = { isa = PBXGroup; children = ( - 11738A3A24508F68004426F1 /* Unit.swift */, + 11738A3A24508F68004426F1 /* UnitType.swift */, 9EC86BA5245C8AD000796EF3 /* ModalType.swift */, 3EBD242D245D9332003CECE7 /* Team.swift */, + 3F745DEF246F48FC00CE7375 /* PlayerMoveType.swift */, ); path = Enums; sourceTree = ""; @@ -255,9 +311,10 @@ AB1D759E245DD2EA00671525 /* Map */ = { isa = PBXGroup; children = ( - AB1D759A245DD18100671525 /* MapProtocol.swift */, + 3E67853F24728368007B9DE4 /* CElements.swift */, AB1D759F245DEC0500671525 /* MapFactory.swift */, AB1D759B245DD18100671525 /* TwoPlayerDefaultTestMap.swift */, + AB21D7D4246C748A00B09CBA /* TwoPlayerMapGenerator.swift */, ); path = Map; sourceTree = ""; @@ -347,6 +404,7 @@ 9E11FF79245CD81100EED3BE /* Fire.sks in Resources */, 110360E0244B101B008610AF /* Assets.xcassets in Resources */, 110360E3244B101B008610AF /* LaunchScreen.storyboard in Resources */, + C04783EE2468583F004961FB /* intro-music.mp3 in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -366,37 +424,55 @@ 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 */, 9E04AFAF245E2B73002D5CFC /* AttackActionComponent.swift in Sources */, + 3E6785422472CBEC007B9DE4 /* Way.swift in Sources */, 110360D9244B101A008610AF /* GameScene.swift in Sources */, + C04783F024685995004961FB /* SettingsScene.swift in Sources */, 116060F7245C57D2004E5A36 /* EntityManager.swift in Sources */, + C064E9AA246C114C0022B228 /* LabelComponent.swift in Sources */, 3EBD242E245D9332003CECE7 /* Team.swift in Sources */, 9E174C88245DF1FF00209FF0 /* BackgroundComponent.swift in Sources */, 9E78ACBA245CBDAF00526FF7 /* HUD.swift in Sources */, - 11738A3B24508F68004426F1 /* Unit.swift in Sources */, + 9EC2FBA72476B1EC00ABF11F /* PlayerInfoComponent.swift in Sources */, + 9EEDE02D246FCD770096C735 /* SpinningLogoEntity.swift in Sources */, + 11738A3B24508F68004426F1 /* UnitType.swift in Sources */, 9E174C86245DD91500209FF0 /* ButtonComponent.swift in Sources */, AE151589245F18EF001D363E /* MatchmakingHelper.swift in Sources */, 11036113244B3E30008610AF /* MenuScene.swift in Sources */, + C099579C246C5E5C0016AA22 /* DataService.swift in Sources */, + AB21D7D5246C748A00B09CBA /* TwoPlayerMapGenerator.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 */, - AB1D759C245DD18100671525 /* MapProtocol.swift in Sources */, + 3F745DF0246F48FC00CE7375 /* PlayerMoveType.swift in Sources */, + AEBF3B01246EB187004F7CD5 /* CancelBtnComponent.swift in Sources */, AB1D75A0245DEC0500671525 /* MapFactory.swift in Sources */, AB1D759D245DD18100671525 /* TwoPlayerDefaultTestMap.swift in Sources */, 9EBFD7552462CF5A00E1E219 /* SliderComponent.swift in Sources */, + 3E67854024728368007B9DE4 /* CElements.swift in Sources */, ABA03DA0244BD54F00A66916 /* Base.swift in Sources */, + C064E9AC246C151F0022B228 /* Label.swift in Sources */, 9E174C82245DD81D00209FF0 /* ButtonNode.swift in Sources */, 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 */, + 3E6785442472CC27007B9DE4 /* DefaultWayComponent.swift in Sources */, 2086465C2461B66200817C23 /* TimerComponent.swift in Sources */, 110360D3244B101A008610AF /* AppDelegate.swift in Sources */, 9EC86B9F245C88A300796EF3 /* Modal.swift in Sources */, 9E78ACC2245CC9EE00526FF7 /* DefBoostSkillComponent.swift in Sources */, + C05FAED62468559D0006AF2E /* SoundManager.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -557,9 +633,9 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = GoldWars/GoldWars.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = DDKFQG46BQ; INFOPLIST_FILE = GoldWars/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -569,7 +645,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; }; @@ -580,9 +656,9 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = GoldWars/GoldWars.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = DDKFQG46BQ; INFOPLIST_FILE = GoldWars/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -592,7 +668,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; }; diff --git a/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/Contents.json b/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/Contents.json new file mode 100644 index 0000000..72ffd48 --- /dev/null +++ b/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "logo_kante.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "logo_kante-1.jpg", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "logo_kante-2.jpg", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/logo_kante-1.jpg b/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/logo_kante-1.jpg new file mode 100644 index 0000000..1ef166f Binary files /dev/null and b/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/logo_kante-1.jpg differ diff --git a/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/logo_kante-2.jpg b/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/logo_kante-2.jpg new file mode 100644 index 0000000..1ef166f Binary files /dev/null and b/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/logo_kante-2.jpg differ diff --git a/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/logo_kante.jpg b/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/logo_kante.jpg new file mode 100644 index 0000000..1ef166f Binary files /dev/null and b/GoldWars/GoldWars/Assets.xcassets/logo_kante.imageset/logo_kante.jpg differ diff --git a/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/Contents.json b/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/Contents.json new file mode 100644 index 0000000..8401033 --- /dev/null +++ b/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "logo_no_background.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "logo_no_background-1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "logo_no_background-2.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/logo_no_background-1.png b/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/logo_no_background-1.png new file mode 100644 index 0000000..07b8c65 Binary files /dev/null and b/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/logo_no_background-1.png differ diff --git a/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/logo_no_background-2.png b/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/logo_no_background-2.png new file mode 100644 index 0000000..07b8c65 Binary files /dev/null and b/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/logo_no_background-2.png differ diff --git a/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/logo_no_background.png b/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/logo_no_background.png new file mode 100644 index 0000000..07b8c65 Binary files /dev/null and b/GoldWars/GoldWars/Assets.xcassets/logo_no_background.imageset/logo_no_background.png differ diff --git a/GoldWars/GoldWars/CancelBtnComponent.swift b/GoldWars/GoldWars/CancelBtnComponent.swift new file mode 100644 index 0000000..ae7d6a2 --- /dev/null +++ b/GoldWars/GoldWars/CancelBtnComponent.swift @@ -0,0 +1,28 @@ +// +// 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) + cancelBtnNode.zPosition = 4 + 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/AtkBoostSkillComponent.swift b/GoldWars/GoldWars/Components/AtkBoostSkillComponent.swift index a2d36b3..8829c19 100644 --- a/GoldWars/GoldWars/Components/AtkBoostSkillComponent.swift +++ b/GoldWars/GoldWars/Components/AtkBoostSkillComponent.swift @@ -9,25 +9,30 @@ import GameplayKit class AtkBoostSkillComponent: GKComponent{ - - let shapeNode: SKShapeNode - let labelNode: SKLabelNode - - init(text: String, texture: SKTexture?, anchorPoint: CGPoint) { - self.labelNode = SKLabelNode(text: text) - self.shapeNode = SKShapeNode(circleOfRadius: 30) - self.shapeNode.position = anchorPoint - self.labelNode.position = CGPoint(x: anchorPoint.x, y: anchorPoint.y - 15) - if texture != nil { - shapeNode.fillTexture = texture - }else { - shapeNode.fillColor = SKColor.gray - } - super.init() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + + var skillButtonNode: SkillButtonNode + + init(iconName: String, text: String, position: CGPoint, isEnabled:Bool) { + skillButtonNode = SkillButtonNode(iconName: iconName, + text: text, + isEnabled: isEnabled, + position: position, + onButtonPress: { + var bases: Set = EntityManager.sharedInstance.getBasesByTeam(for: .team2) + bases.forEach{ base in + if(base.unitType == .Defence){ + base.unitType = .AttackDefence + }else { + base.unitType = .Attack + } + }}) + super.init() + } + + + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } diff --git a/GoldWars/GoldWars/Components/BackgroundComponent.swift b/GoldWars/GoldWars/Components/BackgroundComponent.swift index 7239741..f74d5dd 100644 --- a/GoldWars/GoldWars/Components/BackgroundComponent.swift +++ b/GoldWars/GoldWars/Components/BackgroundComponent.swift @@ -12,6 +12,7 @@ class BackgroundComponent: GKComponent{ var nodes = [SKSpriteNode]() let size: CGSize + static var isMovingBackgroundEnabled = true init(size: CGSize) { self.size = size @@ -27,10 +28,12 @@ class BackgroundComponent: GKComponent{ } func update(){ - for node in nodes{ - node.position.x -= 2 - if node.position.x < -(size.width) { - node.position.x += (size.width) * 3 + if BackgroundComponent.isMovingBackgroundEnabled { + for node in nodes{ + node.position.x -= 2 + if node.position.x < -(size.width) { + node.position.x += (size.width) * 3 + } } } } diff --git a/GoldWars/GoldWars/Components/ButtonComponent.swift b/GoldWars/GoldWars/Components/ButtonComponent.swift index 0fe059f..2c2d82a 100644 --- a/GoldWars/GoldWars/Components/ButtonComponent.swift +++ b/GoldWars/GoldWars/Components/ButtonComponent.swift @@ -18,6 +18,7 @@ class ButtonComponent: GKComponent { isEnabled: isEnabled, position: position, onButtonPress: onButtonPress) + buttonNode.zPosition = 4 super.init() } diff --git a/GoldWars/GoldWars/Components/DefBoostSkillComponent.swift b/GoldWars/GoldWars/Components/DefBoostSkillComponent.swift index 01c0aef..66ddba8 100644 --- a/GoldWars/GoldWars/Components/DefBoostSkillComponent.swift +++ b/GoldWars/GoldWars/Components/DefBoostSkillComponent.swift @@ -9,25 +9,29 @@ import GameplayKit class DefBoostSkillComponent: GKComponent{ - - let shapeNode: SKShapeNode - let labelNode: SKLabelNode - - init(text: String, texture: SKTexture?, anchorPoint: CGPoint) { - self.labelNode = SKLabelNode(text: text) - self.shapeNode = SKShapeNode(circleOfRadius: 30) - self.shapeNode.position = anchorPoint - self.labelNode.position = CGPoint(x: anchorPoint.x, y: anchorPoint.y - 15) - if texture != nil { - shapeNode.fillTexture = texture - }else { - shapeNode.fillColor = SKColor.gray - } - super.init() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + + var skillButtonNode: SkillButtonNode + + init(iconName: String, text: String, position: CGPoint, isEnabled:Bool) { + skillButtonNode = SkillButtonNode(iconName: iconName, + text: text, + isEnabled: isEnabled, + position: position, + onButtonPress: { + var bases: Set = EntityManager.sharedInstance.getBasesByTeam(for: .team2) + bases.forEach{ base in + if(base.unitType == .Attack){ + base.unitType = .AttackDefence + }else { + base.unitType = .Defence + } + } + }) + super.init() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } diff --git a/GoldWars/GoldWars/Components/DefaultBaseComponent.swift b/GoldWars/GoldWars/Components/DefaultBaseComponent.swift index 715840b..2510ad8 100644 --- a/GoldWars/GoldWars/Components/DefaultBaseComponent.swift +++ b/GoldWars/GoldWars/Components/DefaultBaseComponent.swift @@ -8,17 +8,28 @@ import GameplayKit import SpriteKit +import GameKit class DefaultBaseComponent: GKComponent { - var spriteNode: BaseNode - - init(texture: SKTexture, position: CGPoint) { - spriteNode = BaseNode(texture: texture, size: CGSize(width: 80, height: 80)) - spriteNode.position = position - super.init() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + var spriteNode: BaseNode + var labelNode : SKLabelNode? + + init(texture: SKTexture, position: CGPoint) { + spriteNode = BaseNode(texture: texture, size: CGSize(width: 80, height: 80)) + spriteNode.position = position + spriteNode.zPosition = 2 + super.init() + labelNode = SKLabelNode(text: "") + labelNode?.fontColor = SKColor.black + labelNode?.horizontalAlignmentMode = .left + labelNode?.verticalAlignmentMode = .center + labelNode?.fontName = "AvenirNext-Bold" + labelNode?.fontSize = 15 + labelNode?.position = CGPoint(x: position.x + 30 , y: position.y - 50 ) + labelNode?.zPosition = spriteNode.zPosition - 1 + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/GoldWars/GoldWars/Components/DefaultWayComponent.swift b/GoldWars/GoldWars/Components/DefaultWayComponent.swift new file mode 100644 index 0000000..045ac04 --- /dev/null +++ b/GoldWars/GoldWars/Components/DefaultWayComponent.swift @@ -0,0 +1,28 @@ +// +// DefaultWayComponent.swift +// GoldWars +// +// Created by Jakob Haag on 18.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import Foundation +import GameplayKit +import SpriteKit + +class DefaultWayComponent: GKComponent { + var shapeNode: SKShapeNode + + init(pathToDraw: CGMutablePath) { + self.shapeNode = SKShapeNode() + shapeNode.path = pathToDraw + shapeNode.strokeColor = UIColor(red: 0.852, green: 0.649, blue: 0.123, alpha: 1) + shapeNode.lineWidth = 10 + shapeNode.zPosition = 0 + super.init() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/GoldWars/GoldWars/Components/ModalBackgroundComponent.swift b/GoldWars/GoldWars/Components/ModalBackgroundComponent.swift index e81fcf9..c7edfae 100644 --- a/GoldWars/GoldWars/Components/ModalBackgroundComponent.swift +++ b/GoldWars/GoldWars/Components/ModalBackgroundComponent.swift @@ -17,6 +17,7 @@ class ModalBackgroundComponent: GKComponent { spriteNode = SKSpriteNode(texture: texture, size: texture.size()) spriteNode.setScale(2) spriteNode.position = anchorPoint + spriteNode.zPosition = 3 super.init() } diff --git a/GoldWars/GoldWars/Components/ModalContentComponent.swift b/GoldWars/GoldWars/Components/ModalContentComponent.swift index df004a3..23c301e 100644 --- a/GoldWars/GoldWars/Components/ModalContentComponent.swift +++ b/GoldWars/GoldWars/Components/ModalContentComponent.swift @@ -20,6 +20,7 @@ class ModalContentComponent: GKComponent{ self.header.position = CGPoint(x: anchorPoint.x, y: anchorPoint.y + 125) self.header.fontName = "HelveticaNeue-Bold" self.header.fontSize = 40 + self.header.zPosition = 4 self.body = SKLabelNode(text: body) self.body.position = CGPoint(x: anchorPoint.x, y: anchorPoint.y - 20) @@ -28,11 +29,13 @@ class ModalContentComponent: GKComponent{ self.body.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.center self.body.fontName = "HelveticaNeue-Bold" self.body.fontSize = 40 + self.body.zPosition = 4 self.footer = SKLabelNode(text: footer) self.footer.position = CGPoint(x: anchorPoint.x, y: anchorPoint.y - 40) self.footer.fontName = "HelveticaNeue-Bold" self.footer.fontSize = 40 + self.footer.zPosition = 4 super.init() } diff --git a/GoldWars/GoldWars/Components/PlayerInfoComponent.swift b/GoldWars/GoldWars/Components/PlayerInfoComponent.swift new file mode 100644 index 0000000..d48b6e9 --- /dev/null +++ b/GoldWars/GoldWars/Components/PlayerInfoComponent.swift @@ -0,0 +1,61 @@ +// +// PlayerInfoComponent.swift +// GoldWars +// +// Created by Niko Jochim on 21.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import Foundation +import GameplayKit +import GameKit + + +class PlayerInfoComponent: GKComponent { + + var hostLabel:SKLabelNode + var hostUnitsLabel:SKLabelNode + + var peerLabel:SKLabelNode + var peerUnitsLabel:SKLabelNode + var host: GKPlayer? + var peer: GKPlayer? + + init(size: CGSize) { + if MatchmakingHelper.sharedInstance.isServer { + host = GKLocalPlayer.local + peer = MatchmakingHelper.sharedInstance.mpMatch?.players[0] + } else { + host = MatchmakingHelper.sharedInstance.mpMatch?.players[0] + peer = GKLocalPlayer.local + } + hostLabel = SKLabelNode(text: host?.displayName) + hostUnitsLabel = SKLabelNode(text: "500" ) + peerLabel = SKLabelNode(text: peer?.displayName) + peerUnitsLabel = SKLabelNode(text: "500") + super.init() + hostLabel.position = CGPoint(x: size.width * 0.02, y: size.height * 0.95) + hostLabel.horizontalAlignmentMode = .left + peerLabel.position = CGPoint(x: size.width * 0.98, y: size.height * 0.95) + peerLabel.horizontalAlignmentMode = .right + hostUnitsLabel.position = CGPoint(x: size.width * 0.05, y: size.height * 0.9) + peerUnitsLabel.position = CGPoint(x: size.width * 0.95, y: size.height * 0.9) + setColor(labelNodes: [hostLabel,hostUnitsLabel,peerLabel,peerUnitsLabel]) + } + + func update(){ + hostUnitsLabel.text = "\(EntityManager.sharedInstance.getUnitSum(by: host!))" + peerUnitsLabel.text = "\(EntityManager.sharedInstance.getUnitSum(by: peer!))" + } + + func setColor(labelNodes: [SKLabelNode]) -> Void { + for label in labelNodes { + label.fontColor = SKColor.black + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} diff --git a/GoldWars/GoldWars/Components/SkillButtonNode.swift b/GoldWars/GoldWars/Components/SkillButtonNode.swift new file mode 100644 index 0000000..1decb06 --- /dev/null +++ b/GoldWars/GoldWars/Components/SkillButtonNode.swift @@ -0,0 +1,76 @@ +// +// SkillButtonNode.swift +// GoldWars +// +// Created by Simon Kellner on 18.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import SpriteKit + +class SkillButtonNode: 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_circle") + super.init(texture: texture, color: SKColor.white, size: texture.size()) + self.position = position + + let label = SKLabelNode(fontNamed: "Courier-Bold") + label.fontSize = 30 + label.fontColor = SKColor.black + label.zPosition = 1 + label.verticalAlignmentMode = .center + label.text = text + label.name = "label" + + if iconName.isEmpty { + label.position = CGPoint(x: 0, y: 0) + } else { + label.position = CGPoint(x: size.width * 0.5, y: 0) + let icon = SKSpriteNode(imageNamed: iconName) + icon.position = CGPoint(x: -size.width * 0.5, y: 0) + icon.zPosition = 1 + self.addChild(icon) + } + self.addChild(label) + 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) + self.isEnabled = false + onButtonPress() + } + } + + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} diff --git a/GoldWars/GoldWars/Components/SliderComponent.swift b/GoldWars/GoldWars/Components/SliderComponent.swift index dc46145..9682f10 100644 --- a/GoldWars/GoldWars/Components/SliderComponent.swift +++ b/GoldWars/GoldWars/Components/SliderComponent.swift @@ -14,6 +14,7 @@ class SliderComponent: GKComponent { init(width: CGFloat, position: CGPoint) { sliderNode = SliderNode(width: width, position: position) + sliderNode.zPosition = 4 super.init() } diff --git a/GoldWars/GoldWars/Components/SliderNode.swift b/GoldWars/GoldWars/Components/SliderNode.swift index 93f42d2..2ae988e 100644 --- a/GoldWars/GoldWars/Components/SliderNode.swift +++ b/GoldWars/GoldWars/Components/SliderNode.swift @@ -26,6 +26,7 @@ class SliderNode :SKNode { sliderLine = SKShapeNode(rectOf: CGSize(width: width, height: 8)) sliderLine.position = position sliderLine.fillColor = SKColor.white + sliderLine.zPosition = 4 sliderKnob = SliderKnob(circleOfRadius: 20) sliderKnob.min = position.x - width / 2 sliderKnob.max = position.x + width / 2 diff --git a/GoldWars/GoldWars/Components/SpinningLogoComponent.swift b/GoldWars/GoldWars/Components/SpinningLogoComponent.swift new file mode 100644 index 0000000..ab01672 --- /dev/null +++ b/GoldWars/GoldWars/Components/SpinningLogoComponent.swift @@ -0,0 +1,45 @@ +// +// SpinningLogoComponent.swift +// GoldWars +// +// Created by Niko Jochim on 15.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import Foundation +import GameKit + +class SpinningLogoComponent: GKComponent{ + + var node : SK3DNode + + init(position: CGPoint) { + + let scnScene: SCNScene = { + let scnScene = SCNScene() + let cylinder = SCNCylinder(radius: 250, height: 50) + let logoMaterial = SCNMaterial() + let colorMaterial = SCNMaterial() + logoMaterial.diffuse.contents = UIImage(named: "logo_no_background") + colorMaterial.diffuse.contents = UIColor(red: 0.852, green: 0.649, blue: 0.123, alpha: 1) + cylinder.materials = [colorMaterial,logoMaterial,logoMaterial] + let cylinderNode = SCNNode(geometry: cylinder) + cylinderNode.eulerAngles = SCNVector3(x: Float(CGFloat.pi / 2), y: 0, z: Float(CGFloat.pi / 2)) + let action = SCNAction.rotateBy(x: CGFloat(GLKMathDegreesToRadians(360)), y:0 , z: 0, duration: 8) + let forever = SCNAction.repeatForever(action) + cylinderNode.runAction(forever) + scnScene.rootNode.addChildNode(cylinderNode) + return scnScene + }() + + self.node = SK3DNode(viewportSize: CGSize(width: 250, height: 250)) + node.scnScene = scnScene + node.position = position + super.init() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} diff --git a/GoldWars/GoldWars/Components/TeamComponent.swift b/GoldWars/GoldWars/Components/TeamComponent.swift index 379a1cc..87562af 100644 --- a/GoldWars/GoldWars/Components/TeamComponent.swift +++ b/GoldWars/GoldWars/Components/TeamComponent.swift @@ -8,32 +8,44 @@ import SpriteKit import GameplayKit +import GameKit class TeamComponent: GKComponent { - let team: Team + var team: Team + var player: GKPlayer let fire: SKEmitterNode - - init(team: Team, position: CGPoint) { + + init(team: Team, player: GKPlayer, position: CGPoint) { fire = SKEmitterNode(fileNamed: "Fire")! - fire.zPosition = -1 + fire.zPosition = 1 fire.position = position 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 816ca04..3d2579c 100644 --- a/GoldWars/GoldWars/Components/TimerComponent.swift +++ b/GoldWars/GoldWars/Components/TimerComponent.swift @@ -9,12 +9,13 @@ import GameplayKit class TimerComponent: GKComponent { - + let labelNode :SKLabelNode var endTime :Date! var duration :Double - - init(text: String, anchorPoint: CGPoint, duration: TimeInterval) { + var isRunning = false + + init(text: String, anchorPoint: CGPoint, duration: TimeInterval) { self.labelNode = SKLabelNode(text: text) self.labelNode.fontColor = UIColor.black self.labelNode.fontSize = CGFloat(45) @@ -25,15 +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 { @@ -45,12 +55,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/Components/WayNode.swift b/GoldWars/GoldWars/Components/WayNode.swift new file mode 100644 index 0000000..41559a6 --- /dev/null +++ b/GoldWars/GoldWars/Components/WayNode.swift @@ -0,0 +1,25 @@ +// +// WayNode.swift +// GoldWars +// +// Created by Jakob Haag on 18.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import SpriteKit + +class WayNode: SKSpriteNode{ + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + print("touched Way") + // TODO: PopUp Einheiten + Close PopUp + } + + override func touchesMoved(_ touches: Set, with event: UIEvent?) { + // TODO: zeige Angirff Effect + } + + override func touchesEnded(_ touches: Set, with event: UIEvent?) { + // TODO: Open Slider PopUp + } +} diff --git a/GoldWars/GoldWars/DataService.swift b/GoldWars/GoldWars/DataService.swift new file mode 100644 index 0000000..d94a992 --- /dev/null +++ b/GoldWars/GoldWars/DataService.swift @@ -0,0 +1,78 @@ +// +// 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? + var mapModel: MapGenerationModel? + + 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 + } + + func setMapModel(model: MapGenerationModel) { + self.mapModel = model + MapFactory(scene: EntityManager.sharedInstance.scene, entityManager: EntityManager.sharedInstance).loadMap(fromModel: DataService.sharedInstance.mapModel!) + } +} diff --git a/GoldWars/GoldWars/Entities/Base.swift b/GoldWars/GoldWars/Entities/Base.swift index 70fe75d..41078fa 100644 --- a/GoldWars/GoldWars/Entities/Base.swift +++ b/GoldWars/GoldWars/Entities/Base.swift @@ -8,32 +8,54 @@ 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 changeOwnership: Bool + var ownershipPlayer: GKPlayer? + var baseID: Int + var position: CGPoint - init(position: CGPoint, team: Team! = nil) { + init(position: CGPoint, player: GKPlayer! = nil, team: Team! = nil) { self.unitCount = 0 + self.unitType = .General self.adjacencyList = [Base]() - self.changeOwnerShip = false + self.changeOwnership = false + self.ownershipPlayer = player + self.baseID = Base.BASE_ID_COUNT + Base.BASE_ID_COUNT += 1 + self.position = position super.init() - addComponent(DefaultBaseComponent(texture: SKTexture(imageNamed: "Base"), position: position)) - if(team != nil){ - addComponent(TeamComponent(team: team!, 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: spritePos)) self.unitCount = 500 } + if ownershipPlayer == GKLocalPlayer.local { + self.component(ofType: DefaultBaseComponent.self)?.labelNode?.text = "\(unitCount)" + } + + } - func attackBase(base: Base, units:Int) -> [GKEntity]{ - base.changeOwnerShip = true - self.unitCount -= units - base.unitCount += units - return [self, base] - } + func doPlayerMoveTypeToBase(base: Base, playerMoveType: PlayerMoveType, units: Int) -> [GKEntity]{ + base.changeOwnership = true + base.ownershipPlayer = self.ownershipPlayer + self.unitCount -= units + base.unitCount += units + self.component(ofType: DefaultBaseComponent.self)?.labelNode?.text = "\(self.unitCount)" + base.component(ofType: DefaultBaseComponent.self)?.labelNode?.text = "\(base.unitCount)" + DataService.sharedInstance.addMove(playerMove: PlayerMove(fromBase: self.baseID, + toBase: base.baseID, + unitCount: units * playerMoveType.rawValue)) + 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 0f7166c..a1c69d3 100644 --- a/GoldWars/GoldWars/Entities/EntityManager.swift +++ b/GoldWars/GoldWars/Entities/EntityManager.swift @@ -8,47 +8,56 @@ import SpriteKit import GameplayKit +import GameKit class EntityManager { - var entities = Set() - let scene: SKScene - var isModal: Bool + static let sharedInstance = EntityManager() - init(scene: SKScene) { - self.scene = scene - isModal = false + var entities = Set() + var scene: SKScene + var isModal: Bool + + private init() { + isModal = false + scene = SKScene.init() } + func setScene(scene: SKScene){ + self.scene = scene + } + + 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 label = entity.component(ofType: DefaultBaseComponent.self)?.labelNode { + scene.addChild(label) + } + 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) + isModal = true + } + if let skillButtonNode = entity.component(ofType: AtkBoostSkillComponent.self)?.skillButtonNode { + scene.addChild(skillButtonNode) + } + if let skillButtonNode = entity.component(ofType: DefBoostSkillComponent.self)?.skillButtonNode { + scene.addChild(skillButtonNode) + } + 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) } @@ -60,82 +69,191 @@ class EntityManager { 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) + } + if let cancelBtnNode = entity.component(ofType: CancelBtnComponent.self)?.cancelBtnNode { + scene.addChild(cancelBtnNode) + } + if let node = entity.component(ofType: SpinningLogoComponent.self)?.node { + scene.addChild(node) + } + if let wayNode = entity.component(ofType: DefaultWayComponent.self)?.shapeNode { + scene.addChild(wayNode) + } + if let playerInfos = entity.component(ofType: PlayerInfoComponent.self) { + scene.addChild(playerInfos.hostLabel) + scene.addChild(playerInfos.hostUnitsLabel) + scene.addChild(playerInfos.peerLabel) + scene.addChild(playerInfos.peerUnitsLabel) + } } func remove(_ entity: GKEntity) { 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() + isModal = false + } + 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() + } + if let cancelBtnNode = entity.component(ofType: CancelBtnComponent.self)?.cancelBtnNode { + cancelBtnNode.removeFromParent() + } entities.remove(entity) } - - 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) - } - } - - } - 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 update(_ entities: [GKEntity]){ + for entity in entities { + self.entities.update(with: entity) + let base = (entity as! Base) + + if base.changeOwnership { + 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) + } + } + base.changeOwnership = false + } + } + } + + 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!) + } else { + entity.removeComponent(ofType: TeamComponent.self) + } + if getOwnerBySnapBase != nil { + if getOwnerBySnapBase == GKLocalPlayer.local { + base.component(ofType: DefaultBaseComponent.self)?.labelNode?.text = "\(base.unitCount)" + }else { + base.component(ofType: DefaultBaseComponent.self)?.labelNode?.text = "" + } + base.changeOwnership = true + base.ownershipPlayer = getOwnerBySnapBase + 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) + } + } + } + } + + getHUD()?.component(ofType: PlayerInfoComponent.self)?.update() + + } + + func getSnapshotBaseById(baseId: Int, snapshotModel: SnapshotModel) -> BaseEntityModel{ + return snapshotModel.baseEntites.filter { $0.baseId == baseId }[0] + } + + 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 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] } - - 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 } @@ -143,4 +261,29 @@ 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) + } + + func getTimer() -> TimerComponent { + return entities.filter{$0 is HUD}[0].component(ofType: TimerComponent.self)! + } + func getUnitSum(by player: GKPlayer) -> Int{ + let bases = getBasesByPlayer(for: player) + + var sum = 0 + for base in bases { + sum += base.unitCount + } + return sum + } } diff --git a/GoldWars/GoldWars/Entities/HUD.swift b/GoldWars/GoldWars/Entities/HUD.swift index a161285..e2da8bf 100644 --- a/GoldWars/GoldWars/Entities/HUD.swift +++ b/GoldWars/GoldWars/Entities/HUD.swift @@ -9,29 +9,28 @@ import GameplayKit class HUD: GKEntity { - - init(size: CGSize) { - super.init() - addComponent(SpySkillComponent(text: "Spy", - texture: nil, - anchorPoint: CGPoint(x: size.width * 0.75, y: size.height * 0.1))) - - - addComponent(AtkBoostSkillComponent(text: "Atk", - texture: nil, - anchorPoint: CGPoint(x: size.width * 0.85, y: size.height * 0.1))) - - - addComponent(DefBoostSkillComponent(text: "Def", - texture: nil, - anchorPoint: CGPoint(x: size.width * 0.95, y: size.height * 0.1))) + + init(size: CGSize) { + super.init() + addComponent(SpySkillComponent(text: "Spy", + texture: nil, + anchorPoint: CGPoint(x: size.width * 0.75, y: size.height * 0.1))) + + + addComponent(AtkBoostSkillComponent(iconName: "", text: "Atk", position: CGPoint(x: size.width * 0.85, y: size.height * 0.1), isEnabled: true)) + + + addComponent(DefBoostSkillComponent(iconName: "", text: "Def", position: CGPoint(x: size.width * 0.95, y: size.height * 0.1), isEnabled: true)) addComponent(TimerComponent(text: "", - anchorPoint: CGPoint(x: size.width * 0.5, y: size.height * 0.9), duration: 30)) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + anchorPoint: CGPoint(x: size.width * 0.5, y: size.height * 0.9), duration: 30)) + + addComponent(PlayerInfoComponent(size: size)) + + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } diff --git a/GoldWars/GoldWars/Entities/Modal.swift b/GoldWars/GoldWars/Entities/Modal.swift index cdafa53..489aed4 100644 --- a/GoldWars/GoldWars/Entities/Modal.swift +++ b/GoldWars/GoldWars/Entities/Modal.swift @@ -9,31 +9,57 @@ 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, gameScene: GameScene, currentDraggedBase: Base?, touchLocation: CGPoint, collisionBase: Base?) { + 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(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.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) + })) + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + 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"){ + child.alpha = 1 + } + } + } + } + + 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)))!) + GameScene.sendUnits = 0 + } + } + } } diff --git a/GoldWars/GoldWars/Entities/SpinningLogoEntity.swift b/GoldWars/GoldWars/Entities/SpinningLogoEntity.swift new file mode 100644 index 0000000..0e84923 --- /dev/null +++ b/GoldWars/GoldWars/Entities/SpinningLogoEntity.swift @@ -0,0 +1,22 @@ +// +// SpinningLogoEntity.swift +// GoldWars +// +// Created by Niko Jochim on 15.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import Foundation +import GameplayKit + +class SpinningLogoEntity: GKEntity { + + init(position: CGPoint) { + super.init() + self.addComponent(SpinningLogoComponent(position: position)) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/GoldWars/GoldWars/Entities/Way.swift b/GoldWars/GoldWars/Entities/Way.swift new file mode 100644 index 0000000..6a64eb6 --- /dev/null +++ b/GoldWars/GoldWars/Entities/Way.swift @@ -0,0 +1,30 @@ +// +// Way.swift +// GoldWars +// +// Created by Jakob Haag on 18.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import Foundation +import SpriteKit +import GameplayKit + +class Way: GKEntity { + + required init(fromBase: Base, toBase: Base) { + super.init() + + let pathToDraw = CGMutablePath() + pathToDraw.move(to: fromBase.position) + pathToDraw.addLine(to: toBase.position) + + + addComponent(DefaultWayComponent(pathToDraw: pathToDraw)) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + 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/Enums/Unit.swift b/GoldWars/GoldWars/Enums/UnitType.swift similarity index 83% rename from GoldWars/GoldWars/Enums/Unit.swift rename to GoldWars/GoldWars/Enums/UnitType.swift index a4fa851..aec5ccd 100644 --- a/GoldWars/GoldWars/Enums/Unit.swift +++ b/GoldWars/GoldWars/Enums/UnitType.swift @@ -6,8 +6,9 @@ // Copyright © 2020 SP2. All rights reserved. // -enum Unit{ +enum UnitType{ case General case Defence case Attack + case AttackDefence } diff --git a/GoldWars/GoldWars/GameViewController.swift b/GoldWars/GoldWars/GameViewController.swift index e4a2f43..05b2706 100644 --- a/GoldWars/GoldWars/GameViewController.swift +++ b/GoldWars/GoldWars/GameViewController.swift @@ -11,7 +11,7 @@ import SpriteKit import GameplayKit class GameViewController: UIViewController { - + override func viewDidLoad() { super.viewDidLoad() diff --git a/GoldWars/GoldWars/Label.swift b/GoldWars/GoldWars/Label.swift new file mode 100644 index 0000000..2cac987 --- /dev/null +++ b/GoldWars/GoldWars/Label.swift @@ -0,0 +1,21 @@ +// +// Label.swift +// GoldWars +// +// Created by Tim Herbst on 13.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import GameplayKit + +class Label: GKEntity { + + init(fontnamed: String, name: String, text: String, fontSize: CGFloat, fontColor: UIColor, position: CGPoint, horizontalAlignmentMode: SKLabelHorizontalAlignmentMode, vertikalAligmentMode: SKLabelVerticalAlignmentMode, isAnimationEnabled: Bool, isAnimationInfinite: Bool) { + super.init() + self.addComponent(LabelComponent(fontnamed: fontnamed, name: name, text: text, fontSize: fontSize, fontColor: fontColor, position: position, horizontalAlignmentMode: horizontalAlignmentMode, vertikalAligmentMode: vertikalAligmentMode, isAnimationEnabled: isAnimationEnabled, isAnimationInfinite: isAnimationInfinite)) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/GoldWars/GoldWars/LabelComponent.swift b/GoldWars/GoldWars/LabelComponent.swift new file mode 100644 index 0000000..aa57816 --- /dev/null +++ b/GoldWars/GoldWars/LabelComponent.swift @@ -0,0 +1,32 @@ +// +// LabelComponent.swift +// GoldWars +// +// Created by Tim Herbst on 13.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import GameplayKit + +class LabelComponent: GKComponent { + var labelNode: LabelNode + + init(fontnamed: String?, name: String, text: String, fontSize: CGFloat, fontColor: UIColor, position: CGPoint, horizontalAlignmentMode: SKLabelHorizontalAlignmentMode, vertikalAligmentMode: SKLabelVerticalAlignmentMode, isAnimationEnabled: Bool, isAnimationInfinite: Bool) { + labelNode = LabelNode(fontNamed: fontnamed) + labelNode.name = name + labelNode.text = text + labelNode.fontSize = fontSize + labelNode.fontColor = fontColor + labelNode.horizontalAlignmentMode = horizontalAlignmentMode + labelNode.verticalAlignmentMode = vertikalAligmentMode + labelNode.position = position + if isAnimationEnabled { + labelNode.sequentiallyBouncingZoom(delay: 0.3, infinite: isAnimationInfinite) + } + super.init() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/GoldWars/GoldWars/LabelNode.swift b/GoldWars/GoldWars/LabelNode.swift new file mode 100644 index 0000000..669a0b5 --- /dev/null +++ b/GoldWars/GoldWars/LabelNode.swift @@ -0,0 +1,152 @@ +// +// LabelNode.swift +// GoldWars +// +// Created by Tim Herbst on 13.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import SpriteKit + +class LabelNode: SKNode { + let colt = SKLabelNode() + var labels = [SKLabelNode]() + var text = "" { + didSet { + refreshLabels() + } + } + var fontName = "HelveticaNeue-UltraLight" { + didSet { + _ = labels.compactMap({ $0.fontName = fontName }) + refreshLabels() + } + } + var fontSize = CGFloat(30.0) { + didSet { + _ = labels.compactMap({ $0.fontSize = fontSize }) + refreshLabels() + } + } + var fontColor = UIColor.init(white: 1.0, alpha: 1.0) { + didSet { + _ = labels.compactMap({ $0.fontColor = fontColor }) + refreshLabels() + } + } + var horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.init(rawValue: 0) { // left + didSet { + _ = labels.compactMap({ $0.horizontalAlignmentMode = horizontalAlignmentMode! }) + refreshLabels() + } + } + var verticalAlignmentMode = SKLabelVerticalAlignmentMode.init(rawValue: 0) { // center + didSet { + _ = labels.compactMap({ $0.verticalAlignmentMode = verticalAlignmentMode! }) + refreshLabels() + } + } + var lineSpacingFactor: CGFloat = -1.3 { + didSet { + refreshLabels() + } + } + override init() { + super.init() + } + convenience init(text: String) { + self.init() + self.text = text + } + convenience init(fontNamed fontName: String?) { + self.init(text: "") + if let f = fontName { + self.fontName = f + } + } + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func refreshLabels() { + _ = labels.compactMap({ $0.removeFromParent() }) + labels.removeAll() + if text.count > 0 { + var newX: CGFloat = 0.0 + var gapX: CGFloat = 0.0 + let ghostSpace = SKLabelNode(text: ".") + ghostSpace.fontName = fontName + ghostSpace.fontSize = fontSize + let ghostSpaceWidth = ghostSpace.frame.size.width + var fullNodeWidth:CGFloat = 0.0 + for char in text { + if String(char) != " " { + let charLabelNode = SKLabelNode(text: String(char)) + charLabelNode.fontName = fontName + charLabelNode.fontSize = fontSize + fullNodeWidth += charLabelNode.frame.size.width + lineSpacingFactor + } else { + fullNodeWidth += ghostSpaceWidth + lineSpacingFactor + } + } + switch horizontalAlignmentMode { + case .left? : gapX = 0.0 + case .center? : gapX = fullNodeWidth/2 + case .right? : gapX = fullNodeWidth + default: break + } + var index: Int = 0 + for char in text { + if String(char) != " " { + let charLabelNode = SKLabelNode(text: String(char)) + charLabelNode.fontName = fontName + charLabelNode.fontSize = fontSize + charLabelNode.fontColor = fontColor + charLabelNode.horizontalAlignmentMode = .left + charLabelNode.verticalAlignmentMode = verticalAlignmentMode! + charLabelNode.position.x = newX - gapX + charLabelNode.alpha = 1 + self.addChild(charLabelNode) + labels.append(charLabelNode) + newX += charLabelNode.frame.size.width + lineSpacingFactor + } else { + ghostSpace.horizontalAlignmentMode = .left + ghostSpace.verticalAlignmentMode = verticalAlignmentMode! + ghostSpace.position.x = newX - gapX + labels.append(ghostSpace) + newX += ghostSpaceWidth + lineSpacingFactor + } + index += 1 + } + } + } + + func sequentiallyBouncingZoom(delay:TimeInterval, infinite:Bool = false) { + if labels.count > 0 && self.action(forKey: "sequentiallyBouncingZoom") == nil { + let main = SKAction.run { [weak self] in + guard let strongSelf = self else { return } + for i in 0.. SKAction { + return SKAction.sequence([SKAction.wait(forDuration: delay), action]) + } + class func afterDelay(_ delay: TimeInterval, runBlock block: @escaping () -> Void) -> SKAction { + return SKAction.afterDelay(delay, performAction: SKAction.run(block)) + } +} diff --git a/GoldWars/GoldWars/Map/CElements.swift b/GoldWars/GoldWars/Map/CElements.swift new file mode 100644 index 0000000..22fc4dc --- /dev/null +++ b/GoldWars/GoldWars/Map/CElements.swift @@ -0,0 +1,1349 @@ +// +// CElemente.swift +// GoldWars +// +// Created by Jakob Haag on 18.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import SpriteKit + +class CElement0: CenterElementProtocol { + + var bases: [Base] = [] + var centerBase: Base + var ways: [Way] = [] + var id: Int = 0 + + required init(frame: CGRect) { + self.centerBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.midY + ) + ) + self.bases.append(centerBase) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.centerBase + } + + func getRightConnection() -> Base? { + return self.centerBase + } + + func getBottomConnection() -> Base? { + return self.centerBase + } + + func getLeftConnection() -> Base? { + return self.centerBase + } +} + +class CElement1: CenterElementProtocol { + var bases: [Base] = [] + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 1 + + required init(frame: CGRect) { + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.midY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.midY + ) + ) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.rightBase.adjacencyList.append(self.leftBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.leftBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.rightBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement2: CenterElementProtocol { + var bases: [Base] = [] + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 2 + + required init(frame: CGRect) { + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.midY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.midY + ) + ) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.rightBase.adjacencyList.append(self.leftBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.rightBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.leftBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement3: CenterElementProtocol { + var bases: [Base] = [] + var centerBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 3 + + required init(frame: CGRect) { + self.centerBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.maxY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.minY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.minY + ) + ) + self.bases.append(centerBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.centerBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.centerBase) + self.centerBase.adjacencyList.append(self.leftBase) + self.centerBase.adjacencyList.append(self.rightBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.leftBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.leftBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.centerBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement4: CenterElementProtocol { + var bases: [Base] = [] + var centerBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 4 + + required init(frame: CGRect) { + self.centerBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.maxY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.minY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.minY + ) + ) + self.bases.append(centerBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.centerBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.centerBase) + self.centerBase.adjacencyList.append(self.leftBase) + self.centerBase.adjacencyList.append(self.rightBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.leftBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.rightBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.centerBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement5: CenterElementProtocol { + var bases: [Base] = [] + var centerBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 5 + + required init(frame: CGRect) { + self.centerBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.minY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.maxY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.maxY + ) + ) + self.bases.append(centerBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.centerBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.centerBase) + self.centerBase.adjacencyList.append(self.leftBase) + self.centerBase.adjacencyList.append(self.rightBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.leftBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.centerBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.leftBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement6: CenterElementProtocol { + var bases: [Base] = [] + var centerBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 6 + + required init(frame: CGRect) { + self.centerBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.minY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.maxY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.maxY + ) + ) + self.bases.append(centerBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.centerBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.centerBase) + self.centerBase.adjacencyList.append(self.leftBase) + self.centerBase.adjacencyList.append(self.rightBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.leftBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.centerBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.rightBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement7: CenterElementProtocol { + var bases: [Base] = [] + var topBase: Base + var bottomBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 7 + + required init(frame: CGRect) { + self.topBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.minY + ) + ) + + self.bottomBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.maxY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.midY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.midY + ) + ) + self.bases.append(topBase) + self.bases.append(bottomBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.topBase) + self.leftBase.adjacencyList.append(self.bottomBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.topBase) + self.rightBase.adjacencyList.append(self.bottomBase) + self.topBase.adjacencyList.append(self.leftBase) + self.topBase.adjacencyList.append(self.rightBase) + self.topBase.adjacencyList.append(self.bottomBase) + self.bottomBase.adjacencyList.append(self.topBase) + self.bottomBase.adjacencyList.append(self.rightBase) + self.bottomBase.adjacencyList.append(self.leftBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.topBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.topBase, toBase: self.leftBase)) + ways.append(Way(fromBase: self.bottomBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.bottomBase, toBase: self.leftBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.topBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.bottomBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement8: CenterElementProtocol { + var bases: [Base] = [] + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 8 + + required init(frame: CGRect) { + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.midY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.midY + ) + ) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.rightBase.adjacencyList.append(self.leftBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.leftBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return nil + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement9: CenterElementProtocol { + var bases: [Base] = [] + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 9 + + required init(frame: CGRect) { + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.midY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.midY + ) + ) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.rightBase.adjacencyList.append(self.leftBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return nil + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.rightBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement10: CenterElementProtocol { + var bases: [Base] = [] + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 10 + + required init(frame: CGRect) { + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.midY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.midY + ) + ) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.rightBase.adjacencyList.append(self.leftBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.rightBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return nil + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement11: CenterElementProtocol { + var bases: [Base] = [] + var centerBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 11 + + required init(frame: CGRect) { + self.centerBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.maxY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.minY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.minY + ) + ) + self.bases.append(centerBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.centerBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.centerBase) + self.centerBase.adjacencyList.append(self.leftBase) + self.centerBase.adjacencyList.append(self.rightBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.leftBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.rightBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return nil + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.centerBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement12: CenterElementProtocol { + var bases: [Base] = [] + var centerBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 12 + + required init(frame: CGRect) { + self.centerBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.maxY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.minY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.minY + ) + ) + self.bases.append(centerBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.centerBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.centerBase) + self.centerBase.adjacencyList.append(self.leftBase) + self.centerBase.adjacencyList.append(self.rightBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.leftBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.rightBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.rightBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return nil + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement13: CenterElementProtocol { + var bases: [Base] = [] + var centerBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 13 + + required init(frame: CGRect) { + self.centerBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.minY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.maxY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.maxY + ) + ) + self.bases.append(centerBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.centerBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.centerBase) + self.centerBase.adjacencyList.append(self.leftBase) + self.centerBase.adjacencyList.append(self.rightBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.leftBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.rightBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return nil + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.leftBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement14: CenterElementProtocol { + var bases: [Base] = [] + var centerBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 14 + + required init(frame: CGRect) { + self.centerBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.minY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.maxY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.maxY + ) + ) + self.bases.append(centerBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.centerBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.centerBase) + self.centerBase.adjacencyList.append(self.leftBase) + self.centerBase.adjacencyList.append(self.rightBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.leftBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.centerBase, toBase: self.leftBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.centerBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return nil + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement15: CenterElementProtocol { + var bases: [Base] = [] + var topBase: Base + var bottomBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 15 + + required init(frame: CGRect) { + self.topBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.minY + ) + ) + + self.bottomBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.maxY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.midY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.midY + ) + ) + self.bases.append(topBase) + self.bases.append(bottomBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.topBase) + self.leftBase.adjacencyList.append(self.bottomBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.topBase) + self.rightBase.adjacencyList.append(self.bottomBase) + self.topBase.adjacencyList.append(self.leftBase) + self.topBase.adjacencyList.append(self.rightBase) + self.topBase.adjacencyList.append(self.bottomBase) + self.bottomBase.adjacencyList.append(self.topBase) + self.bottomBase.adjacencyList.append(self.rightBase) + self.bottomBase.adjacencyList.append(self.leftBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.topBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.topBase, toBase: self.leftBase)) + ways.append(Way(fromBase: self.bottomBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.bottomBase, toBase: self.leftBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return self.topBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return nil + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement16: CenterElementProtocol { + var bases: [Base] = [] + var topBase: Base + var bottomBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 16 + + required init(frame: CGRect) { + self.topBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.minY + ) + ) + + self.bottomBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.maxY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.midY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.midY + ) + ) + self.bases.append(topBase) + self.bases.append(bottomBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.topBase) + self.leftBase.adjacencyList.append(self.bottomBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.topBase) + self.rightBase.adjacencyList.append(self.bottomBase) + self.topBase.adjacencyList.append(self.leftBase) + self.topBase.adjacencyList.append(self.rightBase) + self.topBase.adjacencyList.append(self.bottomBase) + self.bottomBase.adjacencyList.append(self.topBase) + self.bottomBase.adjacencyList.append(self.rightBase) + self.bottomBase.adjacencyList.append(self.leftBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.topBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.topBase, toBase: self.leftBase)) + ways.append(Way(fromBase: self.bottomBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.bottomBase, toBase: self.leftBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return nil + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.bottomBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + +class CElement17: CenterElementProtocol { + var bases: [Base] = [] + var topBase: Base + var bottomBase: Base + var leftBase: Base + var rightBase: Base + var ways: [Way] = [] + var id: Int = 17 + + required init(frame: CGRect) { + self.topBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.minY + ) + ) + + self.bottomBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.maxY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.midY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.midY + ) + ) + self.bases.append(topBase) + self.bases.append(bottomBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + + self.connectInnerBases() + self.createInternalWays() + } + + func connectInnerBases() { + self.leftBase.adjacencyList.append(self.rightBase) + self.leftBase.adjacencyList.append(self.topBase) + self.leftBase.adjacencyList.append(self.bottomBase) + self.rightBase.adjacencyList.append(self.leftBase) + self.rightBase.adjacencyList.append(self.topBase) + self.rightBase.adjacencyList.append(self.bottomBase) + self.topBase.adjacencyList.append(self.leftBase) + self.topBase.adjacencyList.append(self.rightBase) + self.topBase.adjacencyList.append(self.bottomBase) + self.bottomBase.adjacencyList.append(self.topBase) + self.bottomBase.adjacencyList.append(self.rightBase) + self.bottomBase.adjacencyList.append(self.leftBase) + } + + func createInternalWays() { + ways.append(Way(fromBase: self.topBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.topBase, toBase: self.leftBase)) + ways.append(Way(fromBase: self.bottomBase, toBase: self.rightBase)) + ways.append(Way(fromBase: self.bottomBase, toBase: self.leftBase)) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getInternalWays() -> [Way] { + return self.ways + } + + func getTopConnection() -> Base? { + return nil + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return nil + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} diff --git a/GoldWars/GoldWars/Map/MapFactory.swift b/GoldWars/GoldWars/Map/MapFactory.swift index ab4321a..fd7dc3c 100644 --- a/GoldWars/GoldWars/Map/MapFactory.swift +++ b/GoldWars/GoldWars/Map/MapFactory.swift @@ -8,29 +8,81 @@ import Foundation import SpriteKit +import os + +protocol MapProtocol { + var size: CGSize! {get set} + var entityManager: EntityManager! {get set} + + init(scene: SKScene, entityManager: EntityManager) + + func load(withModel mapModel: MapGenerationModel) +} + +protocol CenterElementProtocol { + + var bases: [Base] {get set} + var ways: [Way] {get set} + var id: Int { get } + + init(frame: CGRect) + + func getAllBases() -> [Base] + func getInternalWays() -> [Way] + func getTopConnection() -> Base? + func getRightConnection() -> Base? + func getBottomConnection() -> Base? + func getLeftConnection() -> Base? +} class MapFactory { + let LOG = OSLog.init(subsystem: "MapGenerator", category: "MapFactory") - var twoPlayerMaps: [MapProtocol]! - var threePlayerMaps: [MapProtocol]! - var fourPlayerMaps: [MapProtocol]! + var twoPlayerMapGenerator: TwoPlayerMapGenerator init(scene: SKScene, entityManager: EntityManager) { - self.twoPlayerMaps = [ - TwoPlayerDefaultTestMap(scene: scene, entityManager: entityManager) - ] - - self.threePlayerMaps = [MapProtocol]() - self.fourPlayerMaps = [MapProtocol]() + self.twoPlayerMapGenerator = TwoPlayerMapGenerator(scene: scene, entityManager: entityManager) } - func loadMap(playerCount: Int) { - if playerCount == 2 { - twoPlayerMaps.randomElement()?.load() - } else if playerCount == 3 { - threePlayerMaps.randomElement()?.load() - } else { - fourPlayerMaps.randomElement()?.load() - } + func loadMap() -> MapGenerationModel{ + let mapModel = TwoPlayerMapGenerator.getNewMapModel() + loadMap(fromModel: mapModel) + return mapModel + } + + func loadMap(fromModel model: MapGenerationModel) { + os_log("Loading two player map", log: LOG, type: .info) + twoPlayerMapGenerator.load(withModel: model) + } +} + +class CenterElementProvider { + static let LOG = OSLog.init(subsystem: "MapGenerator", category: "CenterElementProvider") + + static let centerElements: [CenterElementProtocol.Type] = [ + CElement0.self, + CElement1.self, + CElement2.self, + CElement3.self, + CElement4.self, + CElement5.self, + CElement6.self, + CElement7.self, + CElement8.self, + CElement9.self, + CElement10.self, + CElement11.self, + CElement12.self, + CElement13.self, + CElement14.self, + CElement15.self, + CElement16.self, + CElement17.self + ] + + static func get(inFrame frame: CGRect, withId id: Int) -> CenterElementProtocol { + os_log("Getting new predifined center element from provider", log: LOG, type: .info) + + return centerElements[id].init(frame: frame) } } diff --git a/GoldWars/GoldWars/Map/MapProtocol.swift b/GoldWars/GoldWars/Map/MapProtocol.swift deleted file mode 100644 index 2560d39..0000000 --- a/GoldWars/GoldWars/Map/MapProtocol.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// MapProtocoll.swift -// GoldWars -// -// Created by Marcel Schwarz on 02.05.20. -// Copyright © 2020 SP2. All rights reserved. -// - -import Foundation -import SpriteKit - -protocol MapProtocol { - - var size: CGSize! {get set} - var entityManager: EntityManager! {get set} - - init(scene: SKScene, entityManager: EntityManager) - - func load() -} diff --git a/GoldWars/GoldWars/Map/SampleCElement.swift b/GoldWars/GoldWars/Map/SampleCElement.swift new file mode 100644 index 0000000..e71d78c --- /dev/null +++ b/GoldWars/GoldWars/Map/SampleCElement.swift @@ -0,0 +1,123 @@ +// +// CElemente.swift +// GoldWars +// +// Created by Jakob Haag on 14.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import Foundation +import SpriteKit + +class SampleCElement : CenterElementProtocol { + var frame: CGRect + var bases: [Base] = [] + var centerBase: Base + + required init(frame: CGRect) { + self.frame = frame + self.centerBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.midY + ) + ) + self.bases.append(centerBase) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getTopConnection() -> Base? { + return self.centerBase + } + + func getRightConnection() -> Base? { + return self.centerBase + } + + func getBottomConnection() -> Base? { + return self.centerBase + } + + func getLeftConnection() -> Base? { + return self.centerBase + } +} + +// +// CElement7.swift +// GoldWars +// +// Created by Jakob Haag on 14.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import Foundation +import SpriteKit + +class CElement1700 : CenterElementProtocol { + var frame: CGRect + var bases: [Base] = [] + var topBase: Base + var bottomBase: Base + var leftBase: Base + var rightBase: Base + + required init(frame: CGRect) { + self.frame = frame + self.topBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.minY + ) + ) + + self.bottomBase = Base( + position: CGPoint( + x: frame.midX, + y: frame.maxY + ) + ) + + self.leftBase = Base( + position: CGPoint( + x: frame.minX, + y: frame.midY + ) + ) + + self.rightBase = Base( + position: CGPoint( + x: frame.maxX, + y: frame.midY + ) + ) + self.bases.append(topBase) + self.bases.append(bottomBase) + self.bases.append(leftBase) + self.bases.append(rightBase) + } + + func getAllBases() -> [Base] { + return self.bases + } + + func getTopConnection() -> Base? { + return self.topBase + } + + func getRightConnection() -> Base? { + return self.rightBase + } + + func getBottomConnection() -> Base? { + return self.bottomBase + } + + func getLeftConnection() -> Base? { + return self.leftBase + } +} + diff --git a/GoldWars/GoldWars/Map/TwoPlayerDefaultTestMap.swift b/GoldWars/GoldWars/Map/TwoPlayerDefaultTestMap.swift index beff433..5f67cd7 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 { @@ -19,11 +20,12 @@ class TwoPlayerDefaultTestMap: MapProtocol { self.size = scene.size } - func load() { + func load(withModel mapModel: MapGenerationModel) { // 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/Map/TwoPlayerMapGenerator.swift b/GoldWars/GoldWars/Map/TwoPlayerMapGenerator.swift new file mode 100644 index 0000000..918bdf2 --- /dev/null +++ b/GoldWars/GoldWars/Map/TwoPlayerMapGenerator.swift @@ -0,0 +1,273 @@ +// +// TwoPlayerMapGenerator.swift +// GoldWars +// +// Created by Marcel Schwarz on 13.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import Foundation +import SpriteKit +import GameKit +import os + +struct MapGenerationModel: Codable { + + let numBasesP1: Int + let numBasesP2: Int + let topLeftId: Int + let topRightId: Int + let bottomLeftId: Int + let bottomRightId: Int + +} + +class TwoPlayerMapGenerator: MapProtocol { + + let LOG = OSLog.init(subsystem: "MapGenerator", category: "TwoPlayerMapGenerator") + + var size: CGSize! + var entityManager: EntityManager! + + static func getNewMapModel() -> MapGenerationModel { + + let noOfCElements = CenterElementProvider.centerElements.count - 1 + + return MapGenerationModel( + numBasesP1: Int.random(in: 1...3), + numBasesP2: Int.random(in: 1...3), + topLeftId: Int.random(in: 0...noOfCElements), + topRightId: Int.random(in: 0...noOfCElements), + bottomLeftId: Int.random(in: 0...noOfCElements), + bottomRightId: Int.random(in: 0...noOfCElements) + ) + + } + + required init(scene: SKScene, entityManager: EntityManager) { + self.size = scene.size + self.entityManager = entityManager + } + + func load(withModel mapModel: MapGenerationModel) { + os_log("Loading from TwoPlayerMapFactory", log: LOG, type: .info) + + // Generate bases structure + os_log("Get player one base", log: LOG, type: .info) + let basePlayerOne = Base( + position: CGPoint(x: self.size.width * 0.07, y: self.size.height / 2), + player: (MatchmakingHelper.sharedInstance.isServer) ? GKLocalPlayer.local : MatchmakingHelper.sharedInstance.mpMatch?.players[0], + team: .team1 + ) + + os_log("Get player one's startbases", log: LOG, type: .info) + var p1StartBases = [String: Base]() + var ways = [Way]() + + if (mapModel.numBasesP1 == 1) { + p1StartBases["mid"] = Base(position: CGPoint(x: self.size.width * 0.2, y: self.size.height * 0.5)) + ways.append(Way(fromBase: basePlayerOne, toBase: p1StartBases["mid"]!)) + } else if (mapModel.numBasesP1 == 2) { + p1StartBases["top"] = Base(position: CGPoint(x: self.size.width * 0.2, y: self.size.height * 0.333)) + p1StartBases["bot"] = Base(position: CGPoint(x: self.size.width * 0.2, y: self.size.height * 0.666)) + ways.append(Way(fromBase: basePlayerOne, toBase: p1StartBases["top"]!)) + ways.append(Way(fromBase: basePlayerOne, toBase: p1StartBases["bot"]!)) + } else { + p1StartBases["top"] = Base(position: CGPoint(x: self.size.width * 0.2, y: self.size.height * 0.25)) + p1StartBases["mid"] = Base(position: CGPoint(x: self.size.width * 0.2, y: self.size.height * 0.5)) + p1StartBases["bot"] = Base(position: CGPoint(x: self.size.width * 0.2, y: self.size.height * 0.75)) + ways.append(Way(fromBase: basePlayerOne, toBase: p1StartBases["top"]!)) + ways.append(Way(fromBase: basePlayerOne, toBase: p1StartBases["mid"]!)) + ways.append(Way(fromBase: basePlayerOne, toBase: p1StartBases["bot"]!)) + } + + os_log("Generate Map center", log: LOG, type: .info) + let gridCellWidth = self.size.width * 0.2 + let gridCellHeight = self.size.height * 0.4 + let cellInsetX = CGFloat(self.size.width * 0.05) + let cellInsetY = CGFloat(self.size.height * 0.07) + + let gridTopLeft = CGRect( + x: self.size.width * 0.3, + y: self.size.height * 0.1, + width: gridCellWidth, + height: gridCellHeight + ).insetBy(dx: cellInsetX, dy: cellInsetY) + + let gridTopRight = CGRect( + x: self.size.width * 0.5, + y: self.size.height * 0.1, + width: gridCellWidth, + height: gridCellHeight + ).insetBy(dx: cellInsetX, dy: cellInsetY) + + let gridBottomLeft = CGRect( + x: self.size.width * 0.3, + y: self.size.height * 0.5, + width: gridCellWidth, + height: gridCellHeight + ).insetBy(dx: cellInsetX, dy: cellInsetY) + + let gridBottomRight = CGRect( + x: self.size.width * 0.5, + y: self.size.height * 0.5, + width: gridCellWidth, + height: gridCellHeight + ).insetBy(dx: cellInsetX, dy: cellInsetY) + + let topLeft = CenterElementProvider.get(inFrame: gridTopLeft, withId: mapModel.topLeftId) + let topRight = CenterElementProvider.get(inFrame: gridTopRight, withId: mapModel.topRightId) + let bottomLeft = CenterElementProvider.get(inFrame: gridBottomLeft, withId: mapModel.bottomLeftId) + let bottomRight = CenterElementProvider.get(inFrame: gridBottomRight, withId: mapModel.bottomRightId) + + ways.append(contentsOf: topLeft.getInternalWays()) + ways.append(contentsOf: topRight.getInternalWays()) + ways.append(contentsOf: bottomLeft.getInternalWays()) + ways.append(contentsOf: bottomRight.getInternalWays()) + + os_log("Get player two base", log: LOG, type: .info) + let basePlayerTwo = Base( + position: CGPoint(x: self.size.width * 0.93, y: self.size.height / 2), + player: (!MatchmakingHelper.sharedInstance.isServer) ? GKLocalPlayer.local : MatchmakingHelper.sharedInstance.mpMatch?.players[0], + team: .team2 + ) + + os_log("Get player two's startbases", log: LOG, type: .info) + var p2StartBases = [String: Base]() + + if (mapModel.numBasesP2 == 1) { + p2StartBases["mid"] = Base(position: CGPoint(x: self.size.width * 0.8, y: self.size.height * 0.5)) + ways.append(Way(fromBase: basePlayerTwo, toBase: p2StartBases["mid"]!)) + } else if (mapModel.numBasesP2 == 2) { + p2StartBases["top"] = Base(position: CGPoint(x: self.size.width * 0.8, y: self.size.height * 0.333)) + p2StartBases["bot"] = Base(position: CGPoint(x: self.size.width * 0.8, y: self.size.height * 0.666)) + ways.append(Way(fromBase: basePlayerTwo, toBase: p2StartBases["top"]!)) + ways.append(Way(fromBase: basePlayerTwo, toBase: p2StartBases["bot"]!)) + } else { + p2StartBases["top"] = Base(position: CGPoint(x: self.size.width * 0.8, y: self.size.height * 0.25)) + p2StartBases["mid"] = Base(position: CGPoint(x: self.size.width * 0.8, y: self.size.height * 0.5)) + p2StartBases["bot"] = Base(position: CGPoint(x: self.size.width * 0.8, y: self.size.height * 0.75)) + ways.append(Way(fromBase: basePlayerTwo, toBase: p2StartBases["top"]!)) + ways.append(Way(fromBase: basePlayerTwo, toBase: p2StartBases["mid"]!)) + ways.append(Way(fromBase: basePlayerTwo, toBase: p2StartBases["bot"]!)) + } + + // Create adjacency mapping + os_log("Connecting base p1 and start bases", log: LOG, type: .info) + basePlayerOne.adjacencyList.append(contentsOf: p1StartBases.values) + p1StartBases.values.forEach({base in base.adjacencyList.append(basePlayerOne)}) + + if (p1StartBases["top"] != nil && topLeft.getLeftConnection() != nil) { + os_log("Connecting p1 startbase top with topLeft segment", log: LOG, type: .info) + p1StartBases["top"]!.adjacencyList.append(topLeft.getLeftConnection()!) + topLeft.getLeftConnection()!.adjacencyList.append(p1StartBases["top"]!) + ways.append(Way(fromBase: p1StartBases["top"]!, toBase: topLeft.getLeftConnection()!)) + } + + if (p1StartBases["mid"] != nil) { + if (topLeft.getLeftConnection() != nil) { + os_log("Connecting p1 startbase mid with topLeft segment", log: LOG, type: .info) + p1StartBases["mid"]!.adjacencyList.append(topLeft.getLeftConnection()!) + topLeft.getLeftConnection()!.adjacencyList.append(p1StartBases["mid"]!) + ways.append(Way(fromBase: p1StartBases["mid"]!, toBase: topLeft.getLeftConnection()!)) + } + + if (bottomLeft.getLeftConnection() != nil) { + os_log("Connecting p1 startbase mid with bottomLeft segment", log: LOG, type: .info) + p1StartBases["mid"]!.adjacencyList.append(bottomLeft.getLeftConnection()!) + bottomLeft.getLeftConnection()!.adjacencyList.append(p1StartBases["mid"]!) + ways.append(Way(fromBase: p1StartBases["mid"]!, toBase: bottomLeft.getLeftConnection()!)) + } + } + + if (p1StartBases["bot"] != nil && bottomLeft.getLeftConnection() != nil) { + os_log("Connecting p1 startbase bot with bottomLeft segment", log: LOG, type: .info) + p1StartBases["bot"]!.adjacencyList.append(bottomLeft.getLeftConnection()!) + bottomLeft.getLeftConnection()!.adjacencyList.append(p1StartBases["bot"]!) + ways.append(Way(fromBase: p1StartBases["bot"]!, toBase: bottomLeft.getLeftConnection()!)) + } + + if (topLeft.getRightConnection() != nil && topRight.getLeftConnection() != nil) { + os_log("Connecting topLeft with topRight segment horizontally", log: LOG, type: .info) + topLeft.getRightConnection()!.adjacencyList.append(topRight.getLeftConnection()!) + topRight.getLeftConnection()!.adjacencyList.append(topLeft.getRightConnection()!) + ways.append(Way(fromBase: topLeft.getRightConnection()!, toBase: topRight.getLeftConnection()!)) + } + + if (bottomLeft.getRightConnection() != nil && bottomRight.getLeftConnection() != nil) { + os_log("Connecting bottomLeft with bottomRight segment horizontally", log: LOG, type: .info) + bottomLeft.getRightConnection()!.adjacencyList.append(bottomRight.getLeftConnection()!) + bottomRight.getLeftConnection()!.adjacencyList.append(bottomLeft.getRightConnection()!) + ways.append(Way(fromBase: bottomLeft.getRightConnection()!, toBase: bottomRight.getLeftConnection()!)) + } + + if (topLeft.getBottomConnection() != nil && bottomLeft.getTopConnection() != nil) { + os_log("Connecting topLeft with bottomLeft segment vertically", log: LOG, type: .info) + topLeft.getBottomConnection()!.adjacencyList.append(bottomLeft.getTopConnection()!) + bottomLeft.getTopConnection()!.adjacencyList.append(topLeft.getBottomConnection()!) + ways.append(Way(fromBase: topLeft.getBottomConnection()!, toBase: bottomLeft.getTopConnection()!)) + } + + if (topRight.getBottomConnection() != nil && bottomRight.getTopConnection() != nil) { + os_log("Connecting topRight with bottomRight segment vertically", log: LOG, type: .info) + topRight.getBottomConnection()!.adjacencyList.append(bottomRight.getTopConnection()!) + bottomRight.getTopConnection()!.adjacencyList.append(topRight.getBottomConnection()!) + ways.append(Way(fromBase: topRight.getBottomConnection()!, toBase: bottomRight.getTopConnection()!)) + } + + os_log("Connecting base p2 and start bases", log: LOG, type: .info) + basePlayerTwo.adjacencyList.append(contentsOf: p2StartBases.values) + p2StartBases.values.forEach({base in base.adjacencyList.append(basePlayerTwo)}) + + if (p2StartBases["top"] != nil && topRight.getRightConnection() != nil) { + os_log("Connecting p2 startbase top with topRight segment", log: LOG, type: .info) + p2StartBases["top"]!.adjacencyList.append(topRight.getRightConnection()!) + topRight.getRightConnection()!.adjacencyList.append(p2StartBases["top"]!) + ways.append(Way(fromBase: p2StartBases["top"]!, toBase: topRight.getRightConnection()!)) + } + + if (p2StartBases["mid"] != nil) { + if (topRight.getRightConnection() != nil) { + os_log("Connecting p2 startbase mid with topRight segment", log: LOG, type: .info) + p2StartBases["mid"]!.adjacencyList.append(topRight.getRightConnection()!) + topRight.getRightConnection()!.adjacencyList.append(p2StartBases["mid"]!) + ways.append(Way(fromBase: topRight.getRightConnection()!, toBase: p2StartBases["mid"]!)) + } + + if (bottomRight.getRightConnection() != nil) { + os_log("Connecting p2 startbase mid with bottomRight segment", log: LOG, type: .info) + p2StartBases["mid"]!.adjacencyList.append(bottomRight.getRightConnection()!) + bottomRight.getRightConnection()!.adjacencyList.append(p2StartBases["mid"]!) + ways.append(Way(fromBase: p2StartBases["mid"]!, toBase: bottomRight.getRightConnection()!)) + } + } + + if (p2StartBases["bot"] != nil && bottomRight.getRightConnection() != nil) { + os_log("Connecting p2 startbase bot with bottomRight segment", log: LOG, type: .info) + p2StartBases["bot"]!.adjacencyList.append(bottomRight.getRightConnection()!) + bottomRight.getRightConnection()!.adjacencyList.append(p2StartBases["bot"]!) + ways.append(Way(fromBase: p2StartBases["bot"]!, toBase: bottomRight.getRightConnection()!)) + } + + + // Add all bases to the scene + entityManager.add(basePlayerOne) + p1StartBases.forEach({(key, base) in entityManager.add(base)}) + + topLeft.getAllBases().forEach({base in entityManager.add(base)}) + topRight.getAllBases().forEach({base in entityManager.add(base)}) + bottomLeft.getAllBases().forEach({base in entityManager.add(base)}) + bottomRight.getAllBases().forEach({base in entityManager.add(base)}) + + entityManager.add(basePlayerTwo) + p2StartBases.forEach({(key, base) in entityManager.add(base)}) + + ways.forEach({way in entityManager.add(way)}) + } + + + func createPathFromBaseToBase(fromBase: Base, toBase: Base) { + let path = Way(fromBase: fromBase, toBase: toBase) + entityManager.add(path) + } +} diff --git a/GoldWars/GoldWars/MatchmakingHelper.swift b/GoldWars/GoldWars/MatchmakingHelper.swift index 48628ce..60dc5d2 100644 --- a/GoldWars/GoldWars/MatchmakingHelper.swift +++ b/GoldWars/GoldWars/MatchmakingHelper.swift @@ -102,12 +102,32 @@ 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) + EntityManager.sharedInstance.getTimer().startWithDuration(duration: 31) + } + + if let mapModel = try? jsonDecoder.decode(MapGenerationModel.self, from: data) { + DataService.sharedInstance.setMapModel(model: mapModel) + } + + MultiplayerNetwork.sharedInstance.isSending = false } /* @@ -156,16 +176,31 @@ class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDe 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..5cf2937 --- /dev/null +++ b/GoldWars/GoldWars/MultiplayerNetwork.swift @@ -0,0 +1,70 @@ +// +// 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) + } + + func sendMapModelToPlayers(mapModel: MapGenerationModel) { + let encoder = JSONEncoder() + let encoded = (try? encoder.encode(mapModel))! + sendData(data: encoded) + } + +} 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/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..b9186c6 --- /dev/null +++ b/GoldWars/GoldWars/RoundCalculatorService.swift @@ -0,0 +1,139 @@ +// +// 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 { + if base.ownership == nil { + base.unitCount += playerMoveWithMaxUnits.value.unitCount + if playerMoveWithMaxUnits.value.unitCount == 0 { + base.ownership = nil + } else { + base.ownership = playerMoveWithMaxUnits.key + } + } else { + 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 + } + } + } + } + } + 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) + } + + 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 b306854..7618d1a 100644 --- a/GoldWars/GoldWars/Scenes/GameScene.swift +++ b/GoldWars/GoldWars/Scenes/GameScene.swift @@ -8,128 +8,160 @@ import SpriteKit import GameplayKit +import GameKit class GameScene: SKScene{ - var entityManager: EntityManager! var isMoveTouch = false - var currentDraggedBasePos = CGPoint() var currentDraggedBase : Base? + static var sendUnits: CGFloat = 0 + var collisionBase: Base? override func sceneDidLoad() { - entityManager = EntityManager(scene: self) - entityManager.add(HUD(size: self.size)) - entityManager.add(Background(size: self.size)) + EntityManager.sharedInstance.setScene(scene: self) + EntityManager.sharedInstance.add(HUD(size: self.size)) + EntityManager.sharedInstance.add(Background(size: self.size)) initMap() } - + func initMap() { - MapFactory(scene: self, entityManager: self.entityManager).loadMap(playerCount: 2) + 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() + } } - + 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 - 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))) - } - - } - } - } + + if isMoveTouch{ + isMoveTouch = false + currentDraggedBase!.component(ofType: DefaultBaseComponent.self)?.spriteNode.position = currentDraggedBase!.position + currentDraggedBase!.component(ofType: TeamComponent.self)?.fire.position = currentDraggedBase!.position + currentDraggedBase!.component(ofType: DefaultBaseComponent.self)?.labelNode?.position = CGPoint(x: currentDraggedBase!.position.x + 30, y: currentDraggedBase!.position.y - 50) + addAttackDetails(touchLocation: touchLocation) + } else { - for entity in entityManager.entities { + for entity in EntityManager.sharedInstance.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 { - for child in self.children { - if(child.name != "fire"){ - child.alpha = 0.3 - } - } - entityManager.add(Modal(modaltype: .BaseDetails, - base: entity as! Base, - anchorPoint: CGPoint(x: self.size.width / 2 , y: self.size.height / 2))) - } - } + + //FIXME: this is confusing + addBaseDetails(touchLocation: touchLocation, spriteNode: spriteNode, touches: touches, event: event, entity: entity) } } - + } - + 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 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) - ])) + + for child in children { + if atPoint(touchLocation) == child { + child.touchesMoved(touches, with: event) + } + } + checkSlider() + + let bases = EntityManager.sharedInstance.getBasesByPlayer(for: GKLocalPlayer.local) + + 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 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)) + } } } } - override func update(_ currentTime: TimeInterval) { - entityManager.getBackground()?.update(deltaTime: currentTime) - entityManager.getHUD()?.component(ofType: TimerComponent.self)?.update() + 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 + 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) + } + } + } + } + + 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) + + //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 " + } + } + } + + func checkBases(bases: Set, touchLocation: CGPoint){ + for base in bases { + if atPoint(touchLocation) == base.component(ofType: DefaultBaseComponent.self)?.spriteNode{ + if !isMoveTouch { + 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 + base.component(ofType: DefaultBaseComponent.self)?.labelNode?.position = CGPoint(x:touchLocation.x + 30, y: touchLocation.y - 50) + } + + 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/Scenes/MenuScene.swift b/GoldWars/GoldWars/Scenes/MenuScene.swift index edf6bb9..764a1da 100644 --- a/GoldWars/GoldWars/Scenes/MenuScene.swift +++ b/GoldWars/GoldWars/Scenes/MenuScene.swift @@ -7,43 +7,47 @@ // import SpriteKit - +import SceneKit class MenuScene: SKScene { - - var entityManager: EntityManager! - + override func sceneDidLoad() { - entityManager = EntityManager(scene: self) + EntityManager.sharedInstance.setScene(scene: self) let midX = self.size.width / 2 let midY = self.size.height / 2 - entityManager.add(Button(name: "startGameButton", + EntityManager.sharedInstance.add(Button(name: "startGameButton", iconName: "", text: "Start Game", position: CGPoint(x: midX, y: midY), onButtonPress: { if CommandLine.arguments.contains("--no-matchmaking") { self.loadScene(scene: GameScene(size: self.size)) + SoundManager.sharedInstance.stopMenuMusic() } else { - MatchmakingHelper.sharedInstance.presentMatchmaker(scene: self) + MatchmakingHelper.sharedInstance.presentMatchmaker(scene: self) } - })) - entityManager.add(Button(name: "settingsButton", + })) + EntityManager.sharedInstance.add(Button(name: "settingsButton", iconName: "", text: "Settings", position: CGPoint(x: midX, y: midY - 80 ), onButtonPress: { - //TODO: create Settings Scene - })) - entityManager.add(Background(size: self.size)) + self.loadScene(scene: SettingsScene(size: self.size)) + })) + EntityManager.sharedInstance.add(Background(size: self.size)) + EntityManager.sharedInstance.add(SpinningLogoEntity(position: CGPoint(x: midX, y: midY + 200))) + + if SoundManager.sharedInstance.isMusicPlaying == false && SoundManager.sharedInstance.isMusicEnabled == true { + SoundManager.sharedInstance.startMenuMusic() + } } - + func loadScene(scene: SKScene) { let transition = SKTransition.flipVertical(withDuration: 0.5) self.view?.presentScene(scene, transition: transition) } - + override func update(_ currentTime: TimeInterval) { - entityManager.getBackground()!.update(deltaTime: currentTime) - entityManager.getButtonByName(buttonName: "startGameButton").component(ofType: ButtonComponent.self)?.buttonNode.isEnabled = GameCenterHelper.isAuthenticated + EntityManager.sharedInstance.getBackground()!.update(deltaTime: currentTime) + EntityManager.sharedInstance.getButtonByName(buttonName: "startGameButton").component(ofType: ButtonComponent.self)?.buttonNode.isEnabled = GameCenterHelper.isAuthenticated } } diff --git a/GoldWars/GoldWars/SettingsScene.swift b/GoldWars/GoldWars/SettingsScene.swift new file mode 100644 index 0000000..a9cd9e0 --- /dev/null +++ b/GoldWars/GoldWars/SettingsScene.swift @@ -0,0 +1,93 @@ +// +// SettingsScene.swift +// GoldWars +// +// Created by Tim Herbst on 10.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import SpriteKit + +class SettingsScene: SKScene { + + override func sceneDidLoad() { + EntityManager.sharedInstance.setScene(scene: self) + let positionX = self.size.width * 0.1 + let positionY = self.size.height * 0.05 + + EntityManager.sharedInstance.add(Button(name: "backToMenuScene", + iconName: "", + text: "Back", + position: CGPoint(x: positionX, y: positionY), + onButtonPress: { + self.loadScene(scene: MenuScene(size: self.size)) + })) + EntityManager.sharedInstance.add(Button(name: "StopMenuMusic", + iconName: "", + text: "ON/OFF", + position: CGPoint(x: self.size.width * 0.6, y: self.size.height / 2), + onButtonPress: { + if SoundManager.sharedInstance.isMusicPlaying { + SoundManager.sharedInstance.stopMenuMusic() + SoundManager.sharedInstance.isMusicEnabled = false + } else { + SoundManager.sharedInstance.isMusicEnabled = true + SoundManager.sharedInstance.startMenuMusic() + } + })) + EntityManager.sharedInstance.add(Button(name: "StopMovingBackground", + iconName: "", + text: "MOVE/STOP", + position: CGPoint(x: self.size.width * 0.6, y: self.size.height / 2 - 100), + onButtonPress: { + if BackgroundComponent.isMovingBackgroundEnabled { + BackgroundComponent.isMovingBackgroundEnabled = false + } else { + BackgroundComponent.isMovingBackgroundEnabled = true + } + })) + EntityManager.sharedInstance.add(Label(fontnamed: "Courier-Bold", + name: "SettingsLabel", + text: "Settings", + fontSize: 200.0, + fontColor: .black, + position: CGPoint(x: self.size.width * 0.5, y: self.size.height * 0.7), + horizontalAlignmentMode: .center, + vertikalAligmentMode: .baseline, + isAnimationEnabled: true, + isAnimationInfinite: true) + ) + EntityManager.sharedInstance.add(Label(fontnamed: "Courier-Bold", + name: "LabelMusic", + text: "Music", fontSize: 50.0, + fontColor: .black, + position: CGPoint(x: self.size.width * 0.5, y: self.size.height / 2 - 15), + horizontalAlignmentMode: .right, + vertikalAligmentMode: .baseline, + isAnimationEnabled: true, + isAnimationInfinite: false) + ) + EntityManager.sharedInstance.add(Label(fontnamed: "Courier-Bold", + name: "LabelBackground", + text: "Background", + fontSize: 50.0, + fontColor: .black, + position: CGPoint(x: self.size.width * 0.5, y: self.size.height / 2 - 115), + horizontalAlignmentMode: .right, + vertikalAligmentMode: .baseline, + isAnimationEnabled: true, + isAnimationInfinite: false) + ) + EntityManager.sharedInstance.add(Background(size: self.size)) + } + + func loadScene(scene: SKScene) { + let transition = SKTransition.flipVertical(withDuration: 0.5) + self.view?.presentScene(scene, transition: transition) + } + + override func update(_ currentTime: TimeInterval) { + EntityManager.sharedInstance.getBackground()!.update(deltaTime: currentTime) + } + +} diff --git a/GoldWars/GoldWars/SoundManager.swift b/GoldWars/GoldWars/SoundManager.swift new file mode 100644 index 0000000..b6cb5d4 --- /dev/null +++ b/GoldWars/GoldWars/SoundManager.swift @@ -0,0 +1,47 @@ +// +// SoundManager.swift +// GoldWars +// +// Created by Tim Herbst on 10.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import SpriteKit +import AVFoundation + +class SoundManager { + public static var sharedInstance = SoundManager() + + var audioPlayer = AVAudioPlayer() + var backgroundMainMenuAudio: URL? + var isMusicPlaying = false + var isMusicEnabled = true + + func startMenuMusic() { + self.isMusicPlaying = true + backgroundMainMenuAudio = Bundle.main.url(forResource: "intro-music", withExtension: "mp3") + do { + audioPlayer = try AVAudioPlayer(contentsOf: backgroundMainMenuAudio!) + } catch { + //TODO: Add logging + } + audioPlayer.numberOfLoops = -1 + audioPlayer.prepareToPlay() + if self.isMusicEnabled == true { + audioPlayer.play() + } + } + + func stopMenuMusic() { + audioPlayer.pause() + self.isMusicPlaying = false + } + + func setVolume(_ volume: Float) { + audioPlayer.volume = volume + } + + func getVolume() -> Float { + return audioPlayer.volume + } +} 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 { + +} diff --git a/GoldWars/GoldWars/intro-music.mp3 b/GoldWars/GoldWars/intro-music.mp3 new file mode 100644 index 0000000..6aaa001 Binary files /dev/null and b/GoldWars/GoldWars/intro-music.mp3 differ