Merge branch 'sprint_3_delivery' into 'master'

Sprint 3 delivery

See merge request marcel.schwarz/software-projekt-2!79
This commit is contained in:
Aldin Duraki 2020-05-21 17:44:26 +00:00
commit d7108aa167
64 changed files with 3736 additions and 405 deletions

8
GoldWars/.idea/.gitignore generated vendored Normal file
View File

@ -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/

2
GoldWars/.idea/GoldWars.iml generated Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="AppCode" type="CIDR_MODULE" version="4" />

6
GoldWars/.idea/misc.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

8
GoldWars/.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/GoldWars.iml" filepath="$PROJECT_DIR$/.idea/GoldWars.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,11 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="GoldWars" type="AppleRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="GoldWars" TARGET_NAME="GoldWars" CONFIG_NAME="Debug" SCHEME_NAME="GoldWars" IS_LOCATION_SIMULATION_ALLOWED="true" APPLICATION_LANGUAGE="IDELaunchSchemeLanguageUseSystemLanguage" APPLICATION_REGION="" RUN_TARGET_PROJECT_NAME="GoldWars" RUN_TARGET_NAME="GoldWars" MAKE_ACTIVE="TRUE" SHOULD_DEBUG_EXTENSIONS="false">
<EXTENSION ID="org.jetbrains.appcode.reveal.RevealRunConfigurationExtension">
<REVEAL_SETTINGS autoInject="false" autoInstall="true" askToEnableAutoInstall="true" />
</EXTENSION>
<embedded_app_extension_list />
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

6
GoldWars/.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

4
GoldWars/.idea/xcode.xml generated Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="XcodeMetaData" PROJECT_FILE="$PROJECT_DIR$/GoldWars.xcodeproj" />
</project>

View File

@ -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 = "<group>"; };
11036112244B3E30008610AF /* MenuScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuScene.swift; sourceTree = "<group>"; };
116060F6245C57D2004E5A36 /* EntityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntityManager.swift; sourceTree = "<group>"; };
11738A3A24508F68004426F1 /* Unit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Unit.swift; sourceTree = "<group>"; };
11738A3A24508F68004426F1 /* UnitType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnitType.swift; sourceTree = "<group>"; };
2086465B2461B66200817C23 /* TimerComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerComponent.swift; sourceTree = "<group>"; };
3E67853F24728368007B9DE4 /* CElements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CElements.swift; sourceTree = "<group>"; };
3E6785412472CBEC007B9DE4 /* Way.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Way.swift; sourceTree = "<group>"; };
3E6785432472CC27007B9DE4 /* DefaultWayComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultWayComponent.swift; sourceTree = "<group>"; };
3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCenterHelper.swift; sourceTree = "<group>"; };
3EBD242D245D9332003CECE7 /* Team.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Team.swift; sourceTree = "<group>"; };
3F745DEF246F48FC00CE7375 /* PlayerMoveType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerMoveType.swift; sourceTree = "<group>"; };
3FE19DB4246C7A22004827AB /* RoundCalculatorService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundCalculatorService.swift; sourceTree = "<group>"; };
8BB6FF3F2472B8F000162BBD /* SkillButtonNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkillButtonNode.swift; sourceTree = "<group>"; };
9E04AFAE245E2B73002D5CFC /* AttackActionComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttackActionComponent.swift; sourceTree = "<group>"; };
9E11FF77245CD81100EED3BE /* Fire.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Fire.sks; sourceTree = "<group>"; };
9E174C81245DD81D00209FF0 /* ButtonNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ButtonNode.swift; sourceTree = "<group>"; };
@ -89,20 +114,33 @@
9E78ACBD245CC9C000526FF7 /* AtkBoostSkillComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtkBoostSkillComponent.swift; sourceTree = "<group>"; };
9E78ACC1245CC9EE00526FF7 /* DefBoostSkillComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefBoostSkillComponent.swift; sourceTree = "<group>"; };
9E78ACC3245CCA3600526FF7 /* SpySkillComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpySkillComponent.swift; sourceTree = "<group>"; };
9EA3ABE8245C6DAA006BC61D /* DefaultBaseComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultBaseComponent.swift; sourceTree = "<group>"; };
9EA3ABE8245C6DAA006BC61D /* DefaultBaseComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultBaseComponent.swift; sourceTree = "<group>"; wrapsLines = 1; };
9EA3ABEA245C6DFA006BC61D /* BaseNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseNode.swift; sourceTree = "<group>"; };
9EA3ABEC245C8143006BC61D /* ModalBackgroundComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalBackgroundComponent.swift; sourceTree = "<group>"; };
9EA3ABEE245C834B006BC61D /* ModalContentComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalContentComponent.swift; sourceTree = "<group>"; };
9EBFD7542462CF5A00E1E219 /* SliderComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SliderComponent.swift; sourceTree = "<group>"; };
9EC239E0246878A900952F74 /* MultiplayerNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiplayerNetwork.swift; sourceTree = "<group>"; };
9EC2FBA62476B1EC00ABF11F /* PlayerInfoComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerInfoComponent.swift; sourceTree = "<group>"; };
9EC7E48A2461FBF700396BCD /* SliderNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderNode.swift; sourceTree = "<group>"; };
9EC86B9E245C88A300796EF3 /* Modal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modal.swift; sourceTree = "<group>"; };
9EC86BA5245C8AD000796EF3 /* ModalType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalType.swift; sourceTree = "<group>"; };
9ECD3699245C91F7008DEEBD /* GoldWars.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = GoldWars.entitlements; sourceTree = "<group>"; };
AB1D759A245DD18100671525 /* MapProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapProtocol.swift; sourceTree = "<group>"; };
9EEDE02C246FCD770096C735 /* SpinningLogoEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpinningLogoEntity.swift; sourceTree = "<group>"; };
9EEDE02E246FCD800096C735 /* SpinningLogoComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpinningLogoComponent.swift; sourceTree = "<group>"; };
AB1D759B245DD18100671525 /* TwoPlayerDefaultTestMap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwoPlayerDefaultTestMap.swift; sourceTree = "<group>"; };
AB1D759F245DEC0500671525 /* MapFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapFactory.swift; sourceTree = "<group>"; };
AB21D7D4246C748A00B09CBA /* TwoPlayerMapGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoPlayerMapGenerator.swift; sourceTree = "<group>"; };
ABA03D9F244BD54F00A66916 /* Base.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Base.swift; sourceTree = "<group>"; };
AE151588245F18EF001D363E /* MatchmakingHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchmakingHelper.swift; sourceTree = "<group>"; };
AEBF3AFE246EB146004F7CD5 /* CancelBtnNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CancelBtnNode.swift; sourceTree = "<group>"; };
AEBF3B00246EB187004F7CD5 /* CancelBtnComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CancelBtnComponent.swift; sourceTree = "<group>"; };
C04783ED2468583F004961FB /* intro-music.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = "intro-music.mp3"; sourceTree = "<group>"; };
C04783EF24685995004961FB /* SettingsScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScene.swift; sourceTree = "<group>"; };
C05FAED52468559D0006AF2E /* SoundManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoundManager.swift; sourceTree = "<group>"; };
C064E9A7246C0EA50022B228 /* LabelNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelNode.swift; sourceTree = "<group>"; };
C064E9A9246C114C0022B228 /* LabelComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelComponent.swift; sourceTree = "<group>"; };
C064E9AB246C151F0022B228 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
C099579B246C5E5C0016AA22 /* DataService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataService.swift; sourceTree = "<group>"; };
/* 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 = "<group>";
@ -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 = "<group>";
@ -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 = "<group>";
@ -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 = "<group>";
@ -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 = "<group>";
@ -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;
};

View File

@ -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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -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")
}
}

View File

@ -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<UITouch>, 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")
}
}

View File

@ -10,22 +10,27 @@ import GameplayKit
class AtkBoostSkillComponent: GKComponent{
let shapeNode: SKShapeNode
let labelNode: SKLabelNode
var skillButtonNode: SkillButtonNode
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
init(iconName: String, text: String, position: CGPoint, isEnabled:Bool) {
skillButtonNode = SkillButtonNode(iconName: iconName,
text: text,
isEnabled: isEnabled,
position: position,
onButtonPress: {
var bases: Set<Base> = EntityManager.sharedInstance.getBasesByTeam(for: .team2)
bases.forEach{ base in
if(base.unitType == .Defence){
base.unitType = .AttackDefence
}else {
shapeNode.fillColor = SKColor.gray
base.unitType = .Attack
}
}})
super.init()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

View File

@ -12,6 +12,7 @@ class BackgroundComponent: GKComponent{
var nodes = [SKSpriteNode]()
let size: CGSize
static var isMovingBackgroundEnabled = true
init(size: CGSize) {
self.size = size
@ -27,6 +28,7 @@ class BackgroundComponent: GKComponent{
}
func update(){
if BackgroundComponent.isMovingBackgroundEnabled {
for node in nodes{
node.position.x -= 2
if node.position.x < -(size.width) {
@ -34,6 +36,7 @@ class BackgroundComponent: GKComponent{
}
}
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")

View File

@ -18,6 +18,7 @@ class ButtonComponent: GKComponent {
isEnabled: isEnabled,
position: position,
onButtonPress: onButtonPress)
buttonNode.zPosition = 4
super.init()
}

View File

@ -10,19 +10,23 @@ import GameplayKit
class DefBoostSkillComponent: GKComponent{
let shapeNode: SKShapeNode
let labelNode: SKLabelNode
var skillButtonNode: SkillButtonNode
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
init(iconName: String, text: String, position: CGPoint, isEnabled:Bool) {
skillButtonNode = SkillButtonNode(iconName: iconName,
text: text,
isEnabled: isEnabled,
position: position,
onButtonPress: {
var bases: Set<Base> = EntityManager.sharedInstance.getBasesByTeam(for: .team2)
bases.forEach{ base in
if(base.unitType == .Attack){
base.unitType = .AttackDefence
}else {
shapeNode.fillColor = SKColor.gray
base.unitType = .Defence
}
}
})
super.init()
}

View File

@ -8,14 +8,25 @@
import GameplayKit
import SpriteKit
import GameKit
class DefaultBaseComponent: GKComponent {
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) {

View File

@ -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")
}
}

View File

@ -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()
}

View File

@ -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()
}

View File

@ -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")
}
}

View File

@ -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<UITouch>, 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")
}
}

View File

@ -14,6 +14,7 @@ class SliderComponent: GKComponent {
init(width: CGFloat, position: CGPoint) {
sliderNode = SliderNode(width: width, position: position)
sliderNode.zPosition = 4
super.init()
}

View File

@ -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

View File

@ -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")
}
}

View File

@ -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)
}
}

View File

@ -13,6 +13,7 @@ class TimerComponent: GKComponent {
let labelNode :SKLabelNode
var endTime :Date!
var duration :Double
var isRunning = false
init(text: String, anchorPoint: CGPoint, duration: TimeInterval) {
self.labelNode = SKLabelNode(text: text)
@ -25,17 +26,26 @@ class TimerComponent: GKComponent {
}
func startWithDuration(duration: TimeInterval){
isRunning = true
endTime = Date().addingTimeInterval(duration)
RoundCalculatorService.sharedInstance.isCalculating = false
}
func timeLeft() -> Int {
if isRunning {
let remainingSeconds = Int(endTime.timeIntervalSince(Date()))
if(remainingSeconds < 0 ){
startWithDuration(duration: duration)
if(remainingSeconds == 0) {
isRunning = false
}
return remainingSeconds
}
// if(remainingSeconds < 0){
// startWithDuration(duration: duration)
// }
return 0
}
func isFinished() -> Bool {
return timeLeft() == 0
}
@ -45,6 +55,14 @@ 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()
}
}
}

View File

@ -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<UITouch>, with event: UIEvent?) {
print("touched Way")
// TODO: PopUp Einheiten + Close PopUp
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// TODO: zeige Angirff Effect
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
// TODO: Open Slider PopUp
}
}

View File

@ -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!)
}
}

View File

@ -8,30 +8,52 @@
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<Base>
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
}
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]
}

View File

@ -8,42 +8,51 @@
import SpriteKit
import GameplayKit
import GameKit
class EntityManager {
static let sharedInstance = EntityManager()
var entities = Set<GKEntity>()
let scene: SKScene
var scene: SKScene
var isModal: Bool
init(scene: SKScene) {
self.scene = scene
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 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)
isModal = true
}
if let modal = entity.component(ofType: ModalContentComponent.self) {
scene.addChild(modal.header)
scene.addChild(modal.body)
scene.addChild(modal.footer)
isModal = true
}
if let skill = entity.component(ofType: AtkBoostSkillComponent.self) {
scene.addChild(skill.shapeNode)
scene.addChild(skill.labelNode)
if let skillButtonNode = entity.component(ofType: AtkBoostSkillComponent.self)?.skillButtonNode {
scene.addChild(skillButtonNode)
}
if let skill = entity.component(ofType: DefBoostSkillComponent.self) {
scene.addChild(skill.shapeNode)
scene.addChild(skill.labelNode)
if let skillButtonNode = entity.component(ofType: DefBoostSkillComponent.self)?.skillButtonNode {
scene.addChild(skillButtonNode)
}
if let skill = entity.component(ofType: SpySkillComponent.self) {
scene.addChild(skill.shapeNode)
@ -64,6 +73,24 @@ class EntityManager {
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) {
@ -72,17 +99,23 @@ class EntityManager {
}
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()
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)
}
@ -91,14 +124,82 @@ class EntityManager {
self.entities.update(with: entity)
let base = (entity as! Base)
if base.changeOwnerShip {
base.addComponent(TeamComponent(team: (entities[0] as! Base).component(ofType: TeamComponent.self)!.team, position: (base.component(ofType: DefaultBaseComponent.self)?.spriteNode.position)!))
base.changeOwnerShip = false
scene.addChild(base.component(ofType: TeamComponent.self)!.fire)
if base.changeOwnership {
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),
@ -115,6 +216,10 @@ class EntityManager {
return entities.filter{$0 is Base && ($0 as! Base).component(ofType: TeamComponent.self)?.team == team } as! Set<Base>
}
func getBasesByPlayer(for player: GKPlayer) -> Set<Base> {
return entities.filter{$0 is Base && ($0 as! Base).component(ofType: TeamComponent.self)?.player == player } as! Set<Base>
}
func getTeamByBase(base: Base) -> Team? {
for entity in entities {
if entity is Base && entity == base{
@ -128,6 +233,19 @@ class EntityManager {
return nil
}
func getTeamByPlayer(playerName: String) -> Team {
return entities.filter { $0 is Base && ($0 as! Base).component(ofType: TeamComponent.self)?.player.displayName == playerName }[0].component(ofType: TeamComponent.self)!.team
}
func getBasebyID(id: Int) -> Base?{
for entity in entities {
if entity is Base && (entity as! Base).baseID == id {
return (entity as! Base)
}
}
return nil
}
func getBackground() -> GKEntity? {
return entities.filter{$0 is Background}[0]
}
@ -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
}
}

View File

@ -17,17 +17,16 @@ class HUD: GKEntity {
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(AtkBoostSkillComponent(iconName: "", text: "Atk", position: CGPoint(x: size.width * 0.85, y: size.height * 0.1), isEnabled: true))
addComponent(DefBoostSkillComponent(text: "Def",
texture: nil,
anchorPoint: CGPoint(x: size.width * 0.95, y: size.height * 0.1)))
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))
addComponent(PlayerInfoComponent(size: size))
}
required init?(coder: NSCoder) {

View File

@ -12,23 +12,28 @@ class Modal: GKEntity{
var unitCount:Int
init(modaltype: ModalType, base: Base, anchorPoint: CGPoint) {
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(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 - 80)))
addComponent(ModalContentComponent(header: "Angriff",
body: "Schicke \(unitCount / 2) Einheiten",
footer: "",
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)
}))
}
}
@ -36,4 +41,25 @@ class Modal: GKEntity{
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
}
}
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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
}

View File

@ -6,8 +6,9 @@
// Copyright © 2020 SP2. All rights reserved.
//
enum Unit{
enum UnitType{
case General
case Defence
case Attack
case AttackDefence
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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..<strongSelf.labels.count {
let zoomIn = SKAction.scale(to: 2.0, duration: delay)
let zoomOut = SKAction.scale(to: 1.0, duration: delay)
let currentDuration = delay * TimeInterval(i)
let wait = SKAction.wait(forDuration: currentDuration)
let seq = SKAction.sequence([wait,zoomIn,zoomOut])
let currentLab = strongSelf.labels[i]
currentLab.run(seq, withKey: "seq\(i)")
}
}
let waitAfter = SKAction.wait(forDuration: delay * TimeInterval(self.labels.count+1))
let seq = SKAction.sequence([main,waitAfter])
let finalAction = infinite ? SKAction.repeatForever(seq) : main
self.run(finalAction, withKey: "sequentiallyBouncingZoom")
}
}
}
extension SKAction {
class func afterDelay(_ delay: TimeInterval, performAction action: SKAction) -> 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))
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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)
}
}

View File

@ -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()
}

View File

@ -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
}
}

View File

@ -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
)

View File

@ -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)
}
}

View File

@ -104,10 +104,30 @@ class MatchmakingHelper: NSObject, GKMatchmakerViewControllerDelegate, GKMatchDe
/*
Vom match erhaltene Spielerdaten
*/
private func match(match: GKMatch!, didReceiveData data: NSData!,fromPlayer playerID: String!) {
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

View File

@ -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)
}
}

Binary file not shown.

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -8,23 +8,31 @@
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<UITouch>, with event: UIEvent?) {
@ -36,53 +44,17 @@ class GameScene: SKScene{
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)))
}
}
}
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)
}
}
@ -99,24 +71,91 @@ class GameScene: SKScene{
child.touchesMoved(touches, with: event)
}
}
checkSlider()
for e in entityManager.entities{
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<UITouch>, 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))
}
}
}
}
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{
body.text = "Schicke \( ((e.component(ofType: SliderComponent.self)?.sliderNode.getValue ?? 0) * CGFloat((e as! Modal).unitCount)).rounded(.up)) Einheiten "
} }
GameScene.sendUnits = ((e.component(ofType: SliderComponent.self)?.sliderNode.getValue ?? 0) * CGFloat((e as! Modal).unitCount)).rounded(.up)
let bases = entityManager.getBasesByTeam(for: .team1)
//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<Base>, touchLocation: CGPoint){
for base in bases {
if atPoint(touchLocation) == base.component(ofType: DefaultBaseComponent.self)?.spriteNode{
if !isMoveTouch {
currentDraggedBasePos = base.component(ofType: DefaultBaseComponent.self)!.spriteNode.position
currentDraggedBase = base
}
isMoveTouch = true
moveFireAndBase(base: base, touchLocation: touchLocation)
showNearestBases(base: base)
}
}
}
func moveFireAndBase(base: Base, touchLocation: CGPoint){
base.component(ofType: DefaultBaseComponent.self)?.spriteNode.position = touchLocation
base.component(ofType: TeamComponent.self)?.fire.position = touchLocation
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([
@ -125,11 +164,4 @@ class GameScene: SKScene{
]))
}
}
}
}
override func update(_ currentTime: TimeInterval) {
entityManager.getBackground()?.update(deltaTime: currentTime)
entityManager.getHUD()?.component(ofType: TimerComponent.self)?.update()
}
}

View File

@ -7,34 +7,38 @@
//
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)
}
}))
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
self.loadScene(scene: SettingsScene(size: self.size))
}))
entityManager.add(Background(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) {
@ -43,7 +47,7 @@ class MenuScene: SKScene {
}
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
}
}

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -0,0 +1,13 @@
//
// RoundSimulatorService.swift
// GoldWars
//
// Created by student on 13.05.20.
// Copyright © 2020 SP2. All rights reserved.
//
import Foundation
class RoundSimulatorService {
}

Binary file not shown.