From d74bcf9bf390418df35d94b54d59df0170033f65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= Date: Tue, 30 Jun 2015 06:21:50 +0200 Subject: TankOnTank -> CreepingArmor --- android/AndroidManifest.xml | 4 +- android/build.gradle | 2 +- android/res/values/strings.xml | 2 +- .../asynk/tankontank/android/AndroidLauncher.java | 6 +- build.gradle | 2 +- core/src/TankOnTank.gwt.xml | 2 +- core/src/ch/asynk/creepingarmor/CreepingArmor.java | 222 +++++++ core/src/ch/asynk/creepingarmor/engine/Attack.java | 28 + core/src/ch/asynk/creepingarmor/engine/Board.java | 554 +++++++++++++++++ .../src/ch/asynk/creepingarmor/engine/Faction.java | 6 + .../ch/asynk/creepingarmor/engine/HeadedPawn.java | 88 +++ .../ch/asynk/creepingarmor/engine/Meteorology.java | 24 + core/src/ch/asynk/creepingarmor/engine/Move.java | 158 +++++ .../ch/asynk/creepingarmor/engine/Objective.java | 49 ++ .../asynk/creepingarmor/engine/ObjectiveSet.java | 78 +++ core/src/ch/asynk/creepingarmor/engine/Order.java | 16 + .../ch/asynk/creepingarmor/engine/OrderList.java | 64 ++ .../ch/asynk/creepingarmor/engine/Orientation.java | 134 +++++ core/src/ch/asynk/creepingarmor/engine/Path.java | 62 ++ .../ch/asynk/creepingarmor/engine/PathBuilder.java | 266 +++++++++ .../asynk/creepingarmor/engine/PathIterator.java | 73 +++ core/src/ch/asynk/creepingarmor/engine/Pawn.java | 365 ++++++++++++ .../ch/asynk/creepingarmor/engine/SearchBoard.java | 545 +++++++++++++++++ .../asynk/creepingarmor/engine/SelectedTile.java | 80 +++ core/src/ch/asynk/creepingarmor/engine/Tile.java | 175 ++++++ .../asynk/creepingarmor/engine/gfx/Animation.java | 8 + .../asynk/creepingarmor/engine/gfx/Drawable.java | 10 + .../asynk/creepingarmor/engine/gfx/Moveable.java | 16 + .../creepingarmor/engine/gfx/StackedImages.java | 99 ++++ .../engine/gfx/animations/AnimationSequence.java | 76 +++ .../engine/gfx/animations/DestroyAnimation.java | 62 ++ .../engine/gfx/animations/DiceAnimation.java | 141 +++++ .../engine/gfx/animations/FireAnimation.java | 87 +++ .../gfx/animations/InfantryFireAnimation.java | 222 +++++++ .../engine/gfx/animations/MoveToAnimation.java | 126 ++++ .../engine/gfx/animations/PromoteAnimation.java | 98 +++ .../engine/gfx/animations/RunnableAnimation.java | 67 +++ .../engine/gfx/animations/SoundAnimation.java | 83 +++ .../engine/gfx/animations/SpriteAnimation.java | 76 +++ .../engine/gfx/animations/Sprites.java | 38 ++ .../engine/gfx/animations/TankFireAnimation.java | 196 ++++++ .../engine/gfx/animations/TimedAnimation.java | 48 ++ core/src/ch/asynk/creepingarmor/game/Army.java | 30 + core/src/ch/asynk/creepingarmor/game/Battle.java | 40 ++ core/src/ch/asynk/creepingarmor/game/Command.java | 225 +++++++ core/src/ch/asynk/creepingarmor/game/Config.java | 76 +++ core/src/ch/asynk/creepingarmor/game/Ctrl.java | 336 +++++++++++ .../ch/asynk/creepingarmor/game/Engagement.java | 114 ++++ core/src/ch/asynk/creepingarmor/game/Hex.java | 138 +++++ core/src/ch/asynk/creepingarmor/game/HexSet.java | 29 + core/src/ch/asynk/creepingarmor/game/Hud.java | 307 ++++++++++ core/src/ch/asynk/creepingarmor/game/Map.java | 659 +++++++++++++++++++++ core/src/ch/asynk/creepingarmor/game/Player.java | 213 +++++++ core/src/ch/asynk/creepingarmor/game/State.java | 35 ++ core/src/ch/asynk/creepingarmor/game/Unit.java | 361 +++++++++++ core/src/ch/asynk/creepingarmor/game/UnitList.java | 20 + core/src/ch/asynk/creepingarmor/game/Zone.java | 14 + .../creepingarmor/game/battles/BattleCommon.java | 151 +++++ .../game/battles/BattleCounterAttack.java | 150 +++++ .../game/battles/BattleFrontalAssault.java | 124 ++++ .../game/battles/BattleHeadToHead.java | 118 ++++ .../game/battles/BattleLastStand.java | 136 +++++ .../game/battles/BattleNightAction.java | 153 +++++ .../game/battles/BattleStabToTheFlank.java | 143 +++++ .../creepingarmor/game/battles/BattleTest.java | 128 ++++ .../asynk/creepingarmor/game/battles/Factory.java | 192 ++++++ .../ch/asynk/creepingarmor/game/battles/MapA.java | 77 +++ .../ch/asynk/creepingarmor/game/battles/MapB.java | 75 +++ .../creepingarmor/game/hud/ActionButtons.java | 185 ++++++ .../creepingarmor/game/hud/EngagementPanel.java | 255 ++++++++ .../asynk/creepingarmor/game/hud/PlayerInfo.java | 202 +++++++ .../creepingarmor/game/hud/StatisticsPanel.java | 120 ++++ .../ch/asynk/creepingarmor/game/hud/UnitDock.java | 226 +++++++ .../creepingarmor/game/states/StateAnimation.java | 37 ++ .../creepingarmor/game/states/StateBreak.java | 90 +++ .../creepingarmor/game/states/StateCommon.java | 68 +++ .../creepingarmor/game/states/StateDeployment.java | 138 +++++ .../creepingarmor/game/states/StateEngage.java | 105 ++++ .../asynk/creepingarmor/game/states/StateMove.java | 193 ++++++ .../creepingarmor/game/states/StatePromote.java | 42 ++ .../game/states/StateReinforcement.java | 87 +++ .../creepingarmor/game/states/StateRotate.java | 111 ++++ .../creepingarmor/game/states/StateSelect.java | 132 +++++ .../creepingarmor/game/states/StateWithdraw.java | 71 +++ .../ch/asynk/creepingarmor/loading/LoadingBar.java | 32 + core/src/ch/asynk/creepingarmor/menu/MainMenu.java | 67 +++ .../ch/asynk/creepingarmor/menu/OptionsMenu.java | 257 ++++++++ .../ch/asynk/creepingarmor/menu/ScenariosMenu.java | 141 +++++ .../ch/asynk/creepingarmor/menu/TutorialsMenu.java | 94 +++ .../ch/asynk/creepingarmor/screens/GameCamera.java | 188 ++++++ .../ch/asynk/creepingarmor/screens/GameScreen.java | 217 +++++++ .../ch/asynk/creepingarmor/screens/MenuCamera.java | 113 ++++ .../ch/asynk/creepingarmor/screens/MenuScreen.java | 264 +++++++++ core/src/ch/asynk/creepingarmor/ui/Bg.java | 28 + core/src/ch/asynk/creepingarmor/ui/Label.java | 72 +++ core/src/ch/asynk/creepingarmor/ui/LabelImage.java | 72 +++ core/src/ch/asynk/creepingarmor/ui/LabelStack.java | 72 +++ core/src/ch/asynk/creepingarmor/ui/Menu.java | 93 +++ core/src/ch/asynk/creepingarmor/ui/Msg.java | 79 +++ core/src/ch/asynk/creepingarmor/ui/OkCancel.java | 115 ++++ core/src/ch/asynk/creepingarmor/ui/Patch.java | 28 + core/src/ch/asynk/creepingarmor/ui/Position.java | 239 ++++++++ core/src/ch/asynk/creepingarmor/ui/Widget.java | 93 +++ core/src/ch/asynk/tankontank/TankOnTank.java | 222 ------- core/src/ch/asynk/tankontank/engine/Attack.java | 28 - core/src/ch/asynk/tankontank/engine/Board.java | 554 ----------------- core/src/ch/asynk/tankontank/engine/Faction.java | 6 - .../src/ch/asynk/tankontank/engine/HeadedPawn.java | 88 --- .../ch/asynk/tankontank/engine/Meteorology.java | 24 - core/src/ch/asynk/tankontank/engine/Move.java | 158 ----- core/src/ch/asynk/tankontank/engine/Objective.java | 49 -- .../ch/asynk/tankontank/engine/ObjectiveSet.java | 78 --- core/src/ch/asynk/tankontank/engine/Order.java | 16 - core/src/ch/asynk/tankontank/engine/OrderList.java | 64 -- .../ch/asynk/tankontank/engine/Orientation.java | 134 ----- core/src/ch/asynk/tankontank/engine/Path.java | 62 -- .../ch/asynk/tankontank/engine/PathBuilder.java | 266 --------- .../ch/asynk/tankontank/engine/PathIterator.java | 73 --- core/src/ch/asynk/tankontank/engine/Pawn.java | 365 ------------ .../ch/asynk/tankontank/engine/SearchBoard.java | 545 ----------------- .../ch/asynk/tankontank/engine/SelectedTile.java | 80 --- core/src/ch/asynk/tankontank/engine/Tile.java | 175 ------ .../ch/asynk/tankontank/engine/gfx/Animation.java | 8 - .../ch/asynk/tankontank/engine/gfx/Drawable.java | 10 - .../ch/asynk/tankontank/engine/gfx/Moveable.java | 16 - .../asynk/tankontank/engine/gfx/StackedImages.java | 99 ---- .../engine/gfx/animations/AnimationSequence.java | 76 --- .../engine/gfx/animations/DestroyAnimation.java | 62 -- .../engine/gfx/animations/DiceAnimation.java | 141 ----- .../engine/gfx/animations/FireAnimation.java | 87 --- .../gfx/animations/InfantryFireAnimation.java | 222 ------- .../engine/gfx/animations/MoveToAnimation.java | 126 ---- .../engine/gfx/animations/PromoteAnimation.java | 98 --- .../engine/gfx/animations/RunnableAnimation.java | 67 --- .../engine/gfx/animations/SoundAnimation.java | 83 --- .../engine/gfx/animations/SpriteAnimation.java | 76 --- .../tankontank/engine/gfx/animations/Sprites.java | 38 -- .../engine/gfx/animations/TankFireAnimation.java | 196 ------ .../engine/gfx/animations/TimedAnimation.java | 48 -- core/src/ch/asynk/tankontank/game/Army.java | 30 - core/src/ch/asynk/tankontank/game/Battle.java | 40 -- core/src/ch/asynk/tankontank/game/Command.java | 225 ------- core/src/ch/asynk/tankontank/game/Config.java | 76 --- core/src/ch/asynk/tankontank/game/Ctrl.java | 336 ----------- core/src/ch/asynk/tankontank/game/Engagement.java | 114 ---- core/src/ch/asynk/tankontank/game/Hex.java | 138 ----- core/src/ch/asynk/tankontank/game/HexSet.java | 29 - core/src/ch/asynk/tankontank/game/Hud.java | 307 ---------- core/src/ch/asynk/tankontank/game/Map.java | 659 --------------------- core/src/ch/asynk/tankontank/game/Player.java | 213 ------- core/src/ch/asynk/tankontank/game/State.java | 35 -- core/src/ch/asynk/tankontank/game/Unit.java | 361 ----------- core/src/ch/asynk/tankontank/game/UnitList.java | 20 - core/src/ch/asynk/tankontank/game/Zone.java | 14 - .../tankontank/game/battles/BattleCommon.java | 151 ----- .../game/battles/BattleCounterAttack.java | 150 ----- .../game/battles/BattleFrontalAssault.java | 124 ---- .../tankontank/game/battles/BattleHeadToHead.java | 118 ---- .../tankontank/game/battles/BattleLastStand.java | 136 ----- .../tankontank/game/battles/BattleNightAction.java | 153 ----- .../game/battles/BattleStabToTheFlank.java | 143 ----- .../asynk/tankontank/game/battles/BattleTest.java | 128 ---- .../ch/asynk/tankontank/game/battles/Factory.java | 192 ------ .../src/ch/asynk/tankontank/game/battles/MapA.java | 77 --- .../src/ch/asynk/tankontank/game/battles/MapB.java | 75 --- .../asynk/tankontank/game/hud/ActionButtons.java | 185 ------ .../asynk/tankontank/game/hud/EngagementPanel.java | 255 -------- .../ch/asynk/tankontank/game/hud/PlayerInfo.java | 202 ------- .../asynk/tankontank/game/hud/StatisticsPanel.java | 120 ---- .../src/ch/asynk/tankontank/game/hud/UnitDock.java | 226 ------- .../tankontank/game/states/StateAnimation.java | 37 -- .../asynk/tankontank/game/states/StateBreak.java | 90 --- .../asynk/tankontank/game/states/StateCommon.java | 68 --- .../tankontank/game/states/StateDeployment.java | 138 ----- .../asynk/tankontank/game/states/StateEngage.java | 105 ---- .../ch/asynk/tankontank/game/states/StateMove.java | 193 ------ .../asynk/tankontank/game/states/StatePromote.java | 42 -- .../tankontank/game/states/StateReinforcement.java | 87 --- .../asynk/tankontank/game/states/StateRotate.java | 111 ---- .../asynk/tankontank/game/states/StateSelect.java | 132 ----- .../tankontank/game/states/StateWithdraw.java | 71 --- .../ch/asynk/tankontank/loading/LoadingBar.java | 32 - core/src/ch/asynk/tankontank/menu/MainMenu.java | 67 --- core/src/ch/asynk/tankontank/menu/OptionsMenu.java | 257 -------- .../ch/asynk/tankontank/menu/ScenariosMenu.java | 141 ----- .../ch/asynk/tankontank/menu/TutorialsMenu.java | 94 --- .../ch/asynk/tankontank/screens/GameCamera.java | 188 ------ .../ch/asynk/tankontank/screens/GameScreen.java | 217 ------- .../ch/asynk/tankontank/screens/MenuCamera.java | 113 ---- .../ch/asynk/tankontank/screens/MenuScreen.java | 264 --------- core/src/ch/asynk/tankontank/ui/Bg.java | 28 - core/src/ch/asynk/tankontank/ui/Label.java | 72 --- core/src/ch/asynk/tankontank/ui/LabelImage.java | 72 --- core/src/ch/asynk/tankontank/ui/LabelStack.java | 72 --- core/src/ch/asynk/tankontank/ui/Menu.java | 93 --- core/src/ch/asynk/tankontank/ui/Msg.java | 79 --- core/src/ch/asynk/tankontank/ui/OkCancel.java | 115 ---- core/src/ch/asynk/tankontank/ui/Patch.java | 28 - core/src/ch/asynk/tankontank/ui/Position.java | 239 -------- core/src/ch/asynk/tankontank/ui/Widget.java | 93 --- core/test/ch/asynk/tankontank/BoardUtils.java | 6 +- core/test/ch/asynk/tankontank/Helpers.java | 14 +- core/test/ch/asynk/tankontank/LineOfSightTest.java | 6 +- desktop/build.gradle | 2 +- .../asynk/tankontank/desktop/DesktopLauncher.java | 8 +- html/build.gradle | 4 +- html/src/ch/asynk/tankontank/GdxDefinition.gwt.xml | 4 +- .../asynk/tankontank/GdxDefinitionSuperdev.gwt.xml | 4 +- .../ch/asynk/tankontank/client/HtmlLauncher.java | 6 +- html/webapp/index.html | 2 +- ios/build.gradle | 2 +- ios/robovm.properties | 6 +- ios/src/ch/asynk/tankontank/IOSLauncher.java | 6 +- run | 2 +- tools/debug_pools.patch | 18 +- 215 files changed, 12864 insertions(+), 12864 deletions(-) create mode 100644 core/src/ch/asynk/creepingarmor/CreepingArmor.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/Attack.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/Board.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/Faction.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/HeadedPawn.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/Meteorology.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/Move.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/Objective.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/ObjectiveSet.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/Order.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/OrderList.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/Orientation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/Path.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/PathBuilder.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/PathIterator.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/Pawn.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/SearchBoard.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/SelectedTile.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/Tile.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/Animation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/Drawable.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/Moveable.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/StackedImages.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/AnimationSequence.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/DestroyAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/DiceAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/FireAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/InfantryFireAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/MoveToAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/PromoteAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/RunnableAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/SoundAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/SpriteAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/Sprites.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/TankFireAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/engine/gfx/animations/TimedAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Army.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Battle.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Command.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Config.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Ctrl.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Engagement.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Hex.java create mode 100644 core/src/ch/asynk/creepingarmor/game/HexSet.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Hud.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Map.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Player.java create mode 100644 core/src/ch/asynk/creepingarmor/game/State.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Unit.java create mode 100644 core/src/ch/asynk/creepingarmor/game/UnitList.java create mode 100644 core/src/ch/asynk/creepingarmor/game/Zone.java create mode 100644 core/src/ch/asynk/creepingarmor/game/battles/BattleCommon.java create mode 100644 core/src/ch/asynk/creepingarmor/game/battles/BattleCounterAttack.java create mode 100644 core/src/ch/asynk/creepingarmor/game/battles/BattleFrontalAssault.java create mode 100644 core/src/ch/asynk/creepingarmor/game/battles/BattleHeadToHead.java create mode 100644 core/src/ch/asynk/creepingarmor/game/battles/BattleLastStand.java create mode 100644 core/src/ch/asynk/creepingarmor/game/battles/BattleNightAction.java create mode 100644 core/src/ch/asynk/creepingarmor/game/battles/BattleStabToTheFlank.java create mode 100644 core/src/ch/asynk/creepingarmor/game/battles/BattleTest.java create mode 100644 core/src/ch/asynk/creepingarmor/game/battles/Factory.java create mode 100644 core/src/ch/asynk/creepingarmor/game/battles/MapA.java create mode 100644 core/src/ch/asynk/creepingarmor/game/battles/MapB.java create mode 100644 core/src/ch/asynk/creepingarmor/game/hud/ActionButtons.java create mode 100644 core/src/ch/asynk/creepingarmor/game/hud/EngagementPanel.java create mode 100644 core/src/ch/asynk/creepingarmor/game/hud/PlayerInfo.java create mode 100644 core/src/ch/asynk/creepingarmor/game/hud/StatisticsPanel.java create mode 100644 core/src/ch/asynk/creepingarmor/game/hud/UnitDock.java create mode 100644 core/src/ch/asynk/creepingarmor/game/states/StateAnimation.java create mode 100644 core/src/ch/asynk/creepingarmor/game/states/StateBreak.java create mode 100644 core/src/ch/asynk/creepingarmor/game/states/StateCommon.java create mode 100644 core/src/ch/asynk/creepingarmor/game/states/StateDeployment.java create mode 100644 core/src/ch/asynk/creepingarmor/game/states/StateEngage.java create mode 100644 core/src/ch/asynk/creepingarmor/game/states/StateMove.java create mode 100644 core/src/ch/asynk/creepingarmor/game/states/StatePromote.java create mode 100644 core/src/ch/asynk/creepingarmor/game/states/StateReinforcement.java create mode 100644 core/src/ch/asynk/creepingarmor/game/states/StateRotate.java create mode 100644 core/src/ch/asynk/creepingarmor/game/states/StateSelect.java create mode 100644 core/src/ch/asynk/creepingarmor/game/states/StateWithdraw.java create mode 100644 core/src/ch/asynk/creepingarmor/loading/LoadingBar.java create mode 100644 core/src/ch/asynk/creepingarmor/menu/MainMenu.java create mode 100644 core/src/ch/asynk/creepingarmor/menu/OptionsMenu.java create mode 100644 core/src/ch/asynk/creepingarmor/menu/ScenariosMenu.java create mode 100644 core/src/ch/asynk/creepingarmor/menu/TutorialsMenu.java create mode 100644 core/src/ch/asynk/creepingarmor/screens/GameCamera.java create mode 100644 core/src/ch/asynk/creepingarmor/screens/GameScreen.java create mode 100644 core/src/ch/asynk/creepingarmor/screens/MenuCamera.java create mode 100644 core/src/ch/asynk/creepingarmor/screens/MenuScreen.java create mode 100644 core/src/ch/asynk/creepingarmor/ui/Bg.java create mode 100644 core/src/ch/asynk/creepingarmor/ui/Label.java create mode 100644 core/src/ch/asynk/creepingarmor/ui/LabelImage.java create mode 100644 core/src/ch/asynk/creepingarmor/ui/LabelStack.java create mode 100644 core/src/ch/asynk/creepingarmor/ui/Menu.java create mode 100644 core/src/ch/asynk/creepingarmor/ui/Msg.java create mode 100644 core/src/ch/asynk/creepingarmor/ui/OkCancel.java create mode 100644 core/src/ch/asynk/creepingarmor/ui/Patch.java create mode 100644 core/src/ch/asynk/creepingarmor/ui/Position.java create mode 100644 core/src/ch/asynk/creepingarmor/ui/Widget.java delete mode 100644 core/src/ch/asynk/tankontank/TankOnTank.java delete mode 100644 core/src/ch/asynk/tankontank/engine/Attack.java delete mode 100644 core/src/ch/asynk/tankontank/engine/Board.java delete mode 100644 core/src/ch/asynk/tankontank/engine/Faction.java delete mode 100644 core/src/ch/asynk/tankontank/engine/HeadedPawn.java delete mode 100644 core/src/ch/asynk/tankontank/engine/Meteorology.java delete mode 100644 core/src/ch/asynk/tankontank/engine/Move.java delete mode 100644 core/src/ch/asynk/tankontank/engine/Objective.java delete mode 100644 core/src/ch/asynk/tankontank/engine/ObjectiveSet.java delete mode 100644 core/src/ch/asynk/tankontank/engine/Order.java delete mode 100644 core/src/ch/asynk/tankontank/engine/OrderList.java delete mode 100644 core/src/ch/asynk/tankontank/engine/Orientation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/Path.java delete mode 100644 core/src/ch/asynk/tankontank/engine/PathBuilder.java delete mode 100644 core/src/ch/asynk/tankontank/engine/PathIterator.java delete mode 100644 core/src/ch/asynk/tankontank/engine/Pawn.java delete mode 100644 core/src/ch/asynk/tankontank/engine/SearchBoard.java delete mode 100644 core/src/ch/asynk/tankontank/engine/SelectedTile.java delete mode 100644 core/src/ch/asynk/tankontank/engine/Tile.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/Animation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/Drawable.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/Moveable.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/StackedImages.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/AnimationSequence.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/DestroyAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/DiceAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/FireAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/InfantryFireAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/MoveToAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/PromoteAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/RunnableAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/SoundAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/SpriteAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/Sprites.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/TankFireAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/engine/gfx/animations/TimedAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/game/Army.java delete mode 100644 core/src/ch/asynk/tankontank/game/Battle.java delete mode 100644 core/src/ch/asynk/tankontank/game/Command.java delete mode 100644 core/src/ch/asynk/tankontank/game/Config.java delete mode 100644 core/src/ch/asynk/tankontank/game/Ctrl.java delete mode 100644 core/src/ch/asynk/tankontank/game/Engagement.java delete mode 100644 core/src/ch/asynk/tankontank/game/Hex.java delete mode 100644 core/src/ch/asynk/tankontank/game/HexSet.java delete mode 100644 core/src/ch/asynk/tankontank/game/Hud.java delete mode 100644 core/src/ch/asynk/tankontank/game/Map.java delete mode 100644 core/src/ch/asynk/tankontank/game/Player.java delete mode 100644 core/src/ch/asynk/tankontank/game/State.java delete mode 100644 core/src/ch/asynk/tankontank/game/Unit.java delete mode 100644 core/src/ch/asynk/tankontank/game/UnitList.java delete mode 100644 core/src/ch/asynk/tankontank/game/Zone.java delete mode 100644 core/src/ch/asynk/tankontank/game/battles/BattleCommon.java delete mode 100644 core/src/ch/asynk/tankontank/game/battles/BattleCounterAttack.java delete mode 100644 core/src/ch/asynk/tankontank/game/battles/BattleFrontalAssault.java delete mode 100644 core/src/ch/asynk/tankontank/game/battles/BattleHeadToHead.java delete mode 100644 core/src/ch/asynk/tankontank/game/battles/BattleLastStand.java delete mode 100644 core/src/ch/asynk/tankontank/game/battles/BattleNightAction.java delete mode 100644 core/src/ch/asynk/tankontank/game/battles/BattleStabToTheFlank.java delete mode 100644 core/src/ch/asynk/tankontank/game/battles/BattleTest.java delete mode 100644 core/src/ch/asynk/tankontank/game/battles/Factory.java delete mode 100644 core/src/ch/asynk/tankontank/game/battles/MapA.java delete mode 100644 core/src/ch/asynk/tankontank/game/battles/MapB.java delete mode 100644 core/src/ch/asynk/tankontank/game/hud/ActionButtons.java delete mode 100644 core/src/ch/asynk/tankontank/game/hud/EngagementPanel.java delete mode 100644 core/src/ch/asynk/tankontank/game/hud/PlayerInfo.java delete mode 100644 core/src/ch/asynk/tankontank/game/hud/StatisticsPanel.java delete mode 100644 core/src/ch/asynk/tankontank/game/hud/UnitDock.java delete mode 100644 core/src/ch/asynk/tankontank/game/states/StateAnimation.java delete mode 100644 core/src/ch/asynk/tankontank/game/states/StateBreak.java delete mode 100644 core/src/ch/asynk/tankontank/game/states/StateCommon.java delete mode 100644 core/src/ch/asynk/tankontank/game/states/StateDeployment.java delete mode 100644 core/src/ch/asynk/tankontank/game/states/StateEngage.java delete mode 100644 core/src/ch/asynk/tankontank/game/states/StateMove.java delete mode 100644 core/src/ch/asynk/tankontank/game/states/StatePromote.java delete mode 100644 core/src/ch/asynk/tankontank/game/states/StateReinforcement.java delete mode 100644 core/src/ch/asynk/tankontank/game/states/StateRotate.java delete mode 100644 core/src/ch/asynk/tankontank/game/states/StateSelect.java delete mode 100644 core/src/ch/asynk/tankontank/game/states/StateWithdraw.java delete mode 100644 core/src/ch/asynk/tankontank/loading/LoadingBar.java delete mode 100644 core/src/ch/asynk/tankontank/menu/MainMenu.java delete mode 100644 core/src/ch/asynk/tankontank/menu/OptionsMenu.java delete mode 100644 core/src/ch/asynk/tankontank/menu/ScenariosMenu.java delete mode 100644 core/src/ch/asynk/tankontank/menu/TutorialsMenu.java delete mode 100644 core/src/ch/asynk/tankontank/screens/GameCamera.java delete mode 100644 core/src/ch/asynk/tankontank/screens/GameScreen.java delete mode 100644 core/src/ch/asynk/tankontank/screens/MenuCamera.java delete mode 100644 core/src/ch/asynk/tankontank/screens/MenuScreen.java delete mode 100644 core/src/ch/asynk/tankontank/ui/Bg.java delete mode 100644 core/src/ch/asynk/tankontank/ui/Label.java delete mode 100644 core/src/ch/asynk/tankontank/ui/LabelImage.java delete mode 100644 core/src/ch/asynk/tankontank/ui/LabelStack.java delete mode 100644 core/src/ch/asynk/tankontank/ui/Menu.java delete mode 100644 core/src/ch/asynk/tankontank/ui/Msg.java delete mode 100644 core/src/ch/asynk/tankontank/ui/OkCancel.java delete mode 100644 core/src/ch/asynk/tankontank/ui/Patch.java delete mode 100644 core/src/ch/asynk/tankontank/ui/Position.java delete mode 100644 core/src/ch/asynk/tankontank/ui/Widget.java diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index b1bc868..1ae8ee6 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,6 +1,6 @@ @@ -12,7 +12,7 @@ android:label="@string/app_name" android:theme="@style/GdxTheme" > diff --git a/android/build.gradle b/android/build.gradle index 750b776..c8fba62 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -63,7 +63,7 @@ task run(type: Exec) { } def adb = path + "/platform-tools/adb" - commandLine "$adb", 'shell', 'am', 'start', '-n', 'ch.asynk.tankontank.android/ch.asynk.tankontank.android.AndroidLauncher' + commandLine "$adb", 'shell', 'am', 'start', '-n', 'ch.asynk.creepingarmor.android/ch.asynk.creepingarmor.android.AndroidLauncher' } // sets up the Android Eclipse project, using the old Ant based build. diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index 7566cd6..98b0131 100644 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -1,6 +1,6 @@ - TankOnTank + CreepingArmor diff --git a/android/src/ch/asynk/tankontank/android/AndroidLauncher.java b/android/src/ch/asynk/tankontank/android/AndroidLauncher.java index eded114..1390870 100644 --- a/android/src/ch/asynk/tankontank/android/AndroidLauncher.java +++ b/android/src/ch/asynk/tankontank/android/AndroidLauncher.java @@ -1,16 +1,16 @@ -package ch.asynk.tankontank.android; +package ch.asynk.creepingarmor.android; import android.os.Bundle; import com.badlogic.gdx.backends.android.AndroidApplication; import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; -import ch.asynk.tankontank.TankOnTank; +import ch.asynk.creepingarmor.CreepingArmor; public class AndroidLauncher extends AndroidApplication { @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); - initialize(new TankOnTank(), config); + initialize(new CreepingArmor(), config); } } diff --git a/build.gradle b/build.gradle index 603aee2..f13a4d1 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ allprojects { version = '1.0' ext { - appName = 'TankOnTank' + appName = 'CreepingArmor' gdxVersion = '1.6.1' roboVMVersion = '0.0.14' } diff --git a/core/src/TankOnTank.gwt.xml b/core/src/TankOnTank.gwt.xml index d27ee0e..622ea41 100644 --- a/core/src/TankOnTank.gwt.xml +++ b/core/src/TankOnTank.gwt.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/core/src/ch/asynk/creepingarmor/CreepingArmor.java b/core/src/ch/asynk/creepingarmor/CreepingArmor.java new file mode 100644 index 0000000..7e7e4db --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/CreepingArmor.java @@ -0,0 +1,222 @@ +package ch.asynk.creepingarmor; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Game; +import com.badlogic.gdx.assets.AssetManager; +import com.badlogic.gdx.audio.Sound; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; + +import ch.asynk.creepingarmor.screens.MenuScreen; +import ch.asynk.creepingarmor.screens.GameScreen; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.Config; +import ch.asynk.creepingarmor.game.battles.Factory; + +public class CreepingArmor extends Game +{ + public AssetManager manager; + public Factory factory; + public Ctrl ctrl; + public Config config; + public int hudCorrection; + + public TextureAtlas uiAtlas; + public TextureAtlas menuAtlas; + public BitmapFont fontB; + public BitmapFont fontW; + + public enum State + { + MENU, + GAME, + NONE + } + private State state; + + public static void debug(String msg) + { + debug("", msg); + } + + public static void debug(String dom, String msg) + { + Gdx.app.debug(dom, msg); + } + + @Override + public void create () + { + Gdx.app.setLogLevel(Gdx.app.LOG_DEBUG); + this.hudCorrection = ((int) (125 * Gdx.graphics.getDensity()) - 75); + debug("CreepingArmor", "create() [" + Gdx.graphics.getWidth() + ";" + Gdx.graphics.getHeight() + "] " + Gdx.graphics.getDensity() + " -> " + hudCorrection); + + manager = new AssetManager(); + factory = new Factory(this); + config = new Config(); + + state = State.NONE; + loadUiAssets(); + switchToMenu(); + } + + public void switchToMenu() + { + if (state == State.GAME) { + unloadGameAssets(); + factory.dispose(); + ctrl.dispose(); + getScreen().dispose(); + } + loadMenuAssets(); + state = State.MENU; + setScreen(new MenuScreen(this)); + } + + public void switchToGame() + { + unloadMenuAssets(); + getScreen().dispose(); + factory.assetsLoaded(); + state = State.GAME; + setScreen(new GameScreen(this)); + } + + public void loadGameAssets() + { + if (config.battle.getMapType() == Factory.MapType.MAP_A) + manager.load("data/map_a.png", Texture.class); + if (config.battle.getMapType() == Factory.MapType.MAP_B) + manager.load("data/map_b.png", Texture.class); + int i = config.graphics.i; + manager.load(String.format("data/units%d.atlas",i), TextureAtlas.class); + manager.load(String.format("data/unit-overlays%d.atlas", i), TextureAtlas.class); + manager.load("data/hex.png", Texture.class); + manager.load("data/hud.atlas", TextureAtlas.class); + manager.load("data/hex-overlays.atlas", TextureAtlas.class); + manager.load("data/dice.png", Texture.class); + manager.load("data/infantry_fire.png", Texture.class); + manager.load("data/tank_fire.png", Texture.class); + manager.load("data/explosions.png", Texture.class); + manager.load("sounds/dice.mp3", Sound.class); + manager.load("sounds/tank_move.mp3", Sound.class); + manager.load("sounds/infantry_move.mp3", Sound.class); + manager.load("sounds/infantry_fire.mp3", Sound.class); + manager.load("sounds/tank_fire.mp3", Sound.class); + manager.load("sounds/tank_fire_short.mp3", Sound.class); + manager.load("sounds/explosion.mp3", Sound.class); + manager.load("sounds/explosion_short.mp3", Sound.class); + manager.load("sounds/promote_us.mp3", Sound.class); + manager.load("sounds/promote_ge.mp3", Sound.class); + debug("CreepingArmor", " assets loaded : " + (Gdx.app.getJavaHeap()/1024.0f) + "KB"); + } + + private void unloadGameAssets() + { + if (config.battle.getMapType() == Factory.MapType.MAP_A) + manager.unload("data/map_a.png"); + if (config.battle.getMapType() == Factory.MapType.MAP_B) + manager.unload("data/map_b.png"); + int i = config.graphics.i; + manager.unload(String.format("data/units%d.atlas",i)); + manager.unload(String.format("data/unit-overlays%d.atlas", i)); + manager.unload("data/hex.png"); + manager.unload("data/hud.atlas"); + manager.unload("data/hex-overlays.atlas"); + manager.unload("data/dice.png"); + manager.unload("data/infantry_fire.png"); + manager.unload("data/tank_fire.png"); + manager.unload("data/explosions.png"); + manager.unload("sounds/dice.mp3"); + manager.unload("sounds/tank_move.mp3"); + manager.unload("sounds/infantry_move.mp3"); + manager.unload("sounds/infantry_fire.mp3"); + manager.unload("sounds/tank_fire.mp3"); + manager.unload("sounds/tank_fire_short.mp3"); + manager.unload("sounds/explosion.mp3"); + manager.unload("sounds/explosion_short.mp3"); + manager.unload("sounds/promote_us.mp3"); + manager.unload("sounds/promote_ge.mp3"); + debug("CreepingArmor", " assets unloaded : " + (Gdx.app.getJavaHeap()/1024.0f) + "KB"); + } + + private void loadUiAssets() + { + manager.load("data/ui.atlas", TextureAtlas.class); + manager.finishLoading(); + uiAtlas = manager.get("data/ui.atlas", TextureAtlas.class); + fontB = new BitmapFont(Gdx.files.internal("skin/veteran.fnt"), uiAtlas.findRegion("veteran-black")); + fontW = new BitmapFont(Gdx.files.internal("skin/veteran.fnt"), uiAtlas.findRegion("veteran-white")); + } + + private void unloadUiAssets() + { + fontB.dispose(); + fontW.dispose(); + manager.unload("data/ui.atlas"); + } + + private void loadMenuAssets() + { + manager.load("data/map_a.png", Texture.class); + manager.load("data/menu.atlas", TextureAtlas.class); + manager.finishLoading(); + menuAtlas = manager.get("data/menu.atlas", TextureAtlas.class); + } + + private void unloadMenuAssets() + { + manager.unload("data/map_a.png"); + manager.unload("data/menu.atlas"); + } + + // @Override + // public void render () + // { + // Gdx.gl.glClearColor(0, 0, 0, 1); + // Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + // super.render(); + // } + + // @Override + // public void resize(int width, int height) + // { + // debug("CreepingArmor", "resize(" + width + ", " + height + ")"); + // super.resize(width, height); + // } + + @Override + public void dispose() + { + debug("CreepingArmor", "dispose()"); + debug("CreepingArmor", "diagnostics:\n" + manager.getDiagnostics() ); + getScreen().dispose(); + unloadUiAssets(); + switch(state) { + case MENU: + unloadMenuAssets(); + break; + case GAME: + unloadGameAssets(); + factory.dispose(); + ctrl.dispose(); + break; + } + debug("CreepingArmor", "diagnostics:\n" + manager.getDiagnostics() ); + manager.clear(); + manager.dispose(); + } + + // @Override + // public void pause() + // { + // debug("CreepingArmor", "pause()"); + // } + + // @Override + // public void resume() + // { + // debug("CreepingArmor", "resume()"); + // } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/Attack.java b/core/src/ch/asynk/creepingarmor/engine/Attack.java new file mode 100644 index 0000000..e4fa678 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/Attack.java @@ -0,0 +1,28 @@ +package ch.asynk.creepingarmor.engine; + +public class Attack +{ + public Pawn attacker; + public Pawn target; + public int distance; + public boolean isClear; + public boolean isFlank; + + public Attack(Pawn attacker) + { + this.attacker = attacker; + } + + public String toString() + { + return String.format("attack : %s -> %s dist:%d clear:%b flank:%b", attacker, target, distance, isClear, isFlank); + } + + public void reset() + { + target = null; + distance = 0;; + isClear = false; + isFlank = false; + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/Board.java b/core/src/ch/asynk/creepingarmor/engine/Board.java new file mode 100644 index 0000000..4c42003 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/Board.java @@ -0,0 +1,554 @@ +package ch.asynk.creepingarmor.engine; + +import java.util.Iterator; +import java.util.Collection; +import java.util.ArrayList; +import java.util.LinkedHashSet; + +import com.badlogic.gdx.Gdx; + +import com.badlogic.gdx.utils.Disposable; + +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import com.badlogic.gdx.math.Matrix4; + +import ch.asynk.creepingarmor.engine.gfx.Animation; +import ch.asynk.creepingarmor.engine.gfx.animations.AnimationSequence; +import ch.asynk.creepingarmor.engine.gfx.animations.RunnableAnimation; +import ch.asynk.creepingarmor.engine.gfx.animations.MoveToAnimation.MoveToAnimationCb; + +public abstract class Board implements Disposable, Animation +{ + private int cols; + private int rows; + private final Tile neighbours[] = new Tile[6]; + + public interface TileBuilder + { + public Tile getNewTile(float x, float y, int col, int row, boolean offmap); + } + + public static class Config + { + public int cols; + public int rows; + public int x0; // bottom left x offset + public int y0; // bottom left y offset + public int w; // hex width + public int dw; // half hex : w/2 + public int s; // hex side + public float dh; // hex top : s/2 + public float h; // square height : s + dh + public float slope; // north-west side slope : (dh / (float) dw) + } + + private Config cfg; + private Tile[] tiles; + private SearchBoard searchBoard; + private Sprite board; + private Orientation sides[]; + + private boolean transform; + private Matrix4 prevTransform; + private Matrix4 nextTransform; + + private int tileCount = 0; + private int pawnCount = 0; + private int animationCount = 0; + private final ArrayList animations = new ArrayList(2); + private final ArrayList nextAnimations = new ArrayList(2); + private final LinkedHashSet tilesToDraw = new LinkedHashSet(); + + protected SelectedTile selectedTile; + + protected Board(int cols, int rows) + { + // add a frame of OFFMAP Tiles + this.cols = (cols + 2); + this.rows = (rows + 2); + searchBoard = new SearchBoard(this, cols, rows); + initSides(); + } + + public Board(TileBuilder tileBuilder, Config cfg, Texture boardTexture, SelectedTile selectedTile) + { + board = new Sprite(boardTexture); + this.cfg = cfg; + // add a frame of OFFMAP Tiles + this.cols = (cfg.cols + 2); + this.rows = (cfg.rows + 2); + this.tiles = new Tile[this.cols * this.rows]; + searchBoard = new SearchBoard(this, cfg.cols, cfg.rows); + + int idx = 0; + boolean evenRow = false; + float y = cfg.y0 - cfg.dh + cfg.s - cfg.h; + for (int i = -1; i < (cfg.rows + 1); i++) { + float x = cfg.x0 + cfg.dw - cfg.w; + if (!evenRow) x += cfg.dw; + for ( int j = -1; j < (cfg.cols + 1); j ++) { + boolean offmap = ((j < 0) || (i < 0) || (j >= cfg.cols) || (i >= cfg.rows)); + this.tiles[idx] = tileBuilder.getNewTile(x, y, (j + ((i + 1) / 2)), i, offmap); + idx += 1; + x += cfg.w; + } + y += cfg.h; + evenRow = !evenRow; + } + + initSides(); + + this.selectedTile = selectedTile; + } + + private void initSides() + { + this.sides = new Orientation[6]; + sides[0] = Orientation.NORTH; + sides[1] = Orientation.NORTH_EAST; + sides[2] = Orientation.SOUTH_EAST; + sides[3] = Orientation.SOUTH; + sides[4] = Orientation.SOUTH_WEST; + sides[5] = Orientation.NORTH_WEST; + } + + @Override + public void dispose() + { + for (int i = 0; i < (this.cols * this.rows); i++) + tiles[i].dispose(); + tilesToDraw.clear(); + for (int i = 0, n = nextAnimations.size(); i < n; i++) + nextAnimations.get(i).dispose(); + animations.clear(); + for (int i = 0, n = animations.size(); i < n; i++) + animations.get(i).dispose(); + animations.clear(); + if (selectedTile != null) + selectedTile.dispose(); + Move.clearPool(); + Path.clearPool(); + } + + public float getWidth() + { + return board.getWidth(); + } + + public float getHeight() + { + return board.getHeight(); + } + + public void setPosition(float x, float y) + { + board.setPosition(x, y); + if ((x != 0.0f) || (y != 0.0f)) { + transform = true; + prevTransform = new Matrix4(); + nextTransform = new Matrix4(); + nextTransform.translate(x, y, 0); + } else + transform = false; + } + + public Orientation getSide(int i) + { + return sides[i]; + } + + protected int getTileOffset(int col, int row) + { + col = (col + 1 - ((row + 1) / 2)); + row = (row + 1); + if ((col < 0) || (row < 0) || (row >= this.rows) || (col >= this.cols)) + return -1; + + return (col + (row * this.cols)); + } + + protected Tile getTile(int col, int row) + { + int offset = getTileOffset(col, row); + if (offset < 0) + return null; + return tiles[offset]; + } + + public void setAdjacentTiles(Tile tile, Tile tiles[]) + { + tiles[0] = getAdjTileAt(tile, sides[0].opposite()); + tiles[1] = getAdjTileAt(tile, sides[1].opposite()); + tiles[2] = getAdjTileAt(tile, sides[2].opposite()); + tiles[3] = getAdjTileAt(tile, sides[3].opposite()); + tiles[4] = getAdjTileAt(tile, sides[4].opposite()); + tiles[5] = getAdjTileAt(tile, sides[5].opposite()); + } + + public Tile getAdjTileAt(Tile tile, Orientation o) + { + Tile t = null; + switch(o) { + case NORTH: + t = getTile((tile.col + 1), tile.row); + break; + case NORTH_EAST: + t = getTile(tile.col, (tile.row - 1)); + break; + case SOUTH_EAST: + t = getTile((tile.col - 1), (tile.row - 1)); + break; + case SOUTH: + t = getTile((tile.col - 1), tile.row); + break; + case SOUTH_WEST: + t = getTile(tile.col, (tile.row + 1)); + break; + case NORTH_WEST: + t = getTile((tile.col + 1), (tile.row + 1)); + break; + } + return t; + } + + protected abstract void animationsOver(); + + protected void addAnimation(Animation a) + { + nextAnimations.add(a); + } + + public int animationCount() + { + return animations.size(); + } + + private void stats() + { + boolean print = false; + + if (tileCount != tilesToDraw.size()) { + tileCount = tilesToDraw.size(); + print = true; + } + + if (animationCount != animations.size()) { + animationCount = animations.size(); + print = true; + } + + if (print) + Gdx.app.debug("Board", " tiles:" + tileCount + " pawns:" + pawnCount + " animations:" + animationCount); + } + + public boolean animate(float delta) + { + boolean over = (animations.size() > 0); + Iterator iter = animations.iterator(); + while (iter.hasNext()) { + Animation a = iter.next(); + if (a.animate(delta)) + iter.remove(); + } + if (over && (animations.size() == 0)) + animationsOver(); + + for (int i = 0, n = nextAnimations.size(); i < n; i++) + animations.add(nextAnimations.get(i)); + nextAnimations.clear(); + + selectedTile.animate(delta); + + return true; + } + + public void draw(Batch batch) + { + board.draw(batch); + + if (transform) { + prevTransform.set(batch.getTransformMatrix()); + batch.setTransformMatrix(nextTransform); + } + + Iterator tileIter = tilesToDraw.iterator(); + while (tileIter.hasNext()) + tileIter.next().draw(batch); + + Iterator animationIter = animations.iterator(); + while (animationIter.hasNext()) + animationIter.next().draw(batch); + + selectedTile.draw(batch); + + if (transform) + batch.setTransformMatrix(prevTransform); + } + + public void drawDebug(ShapeRenderer debugShapes) + { + stats(); + if (transform) { + prevTransform.set(debugShapes.getTransformMatrix()); + debugShapes.setTransformMatrix(nextTransform); + } + + Iterator iter = tilesToDraw.iterator(); + while (iter.hasNext()) + iter.next().drawDebug(debugShapes); + + Iterator animationIter = animations.iterator(); + while (animationIter.hasNext()) + animationIter.next().drawDebug(debugShapes); + + if (transform) + debugShapes.setTransformMatrix(prevTransform); + } + + protected int collectPossibleMoves(Pawn pawn, Collection moves) + { + return searchBoard.possibleMovesFrom(pawn, moves); + } + + protected int collectPossibleTargets(Pawn pawn, Collection targets) + { + return searchBoard.possibleTargetsFrom(pawn, targets); + } + + protected int collectPossibleTargets(Pawn pawn, Collection units, Collection targets) + { + targets.clear(); + for (Pawn target : units) { + if (pawn.canEngage(target) && searchBoard.canAttack(pawn, target, true)) + targets.add(target); + } + + return targets.size(); + } + + protected int collectMoveAssists(Pawn pawn, Collection assists) + { + assists.clear(); + setAdjacentTiles(pawn.getTile(), neighbours); + for (int i = 0; i < 6; i++) { + Tile tile = neighbours[i]; + if (tile != null) { + Iterator pawns = tile.iterator(); + while(pawns.hasNext()) { + Pawn p = pawns.next(); + if (!pawn.isEnemy(p) && p.canMove()) + assists.add(p); + } + } + } + return assists.size(); + } + + protected int collectAttackAssists(Pawn pawn, Pawn target, Collection units, Collection assists) + { + assists.clear(); + for (Pawn p : units) { + if ((p != pawn) && p.canEngage(target) && searchBoard.canAttack(p, target, !p.canAssistEngagementWithoutLos())) + assists.add(p); + } + + return assists.size(); + } + + public Orientation findBestEntry(Pawn pawn, Tile to, int allowedMoves) + { + Orientation entry = Orientation.KEEP; + int cost = Integer.MAX_VALUE; + boolean road = false; + + setAdjacentTiles(to, neighbours); + for (int i = 0; i < 6; i++) { + Tile t = neighbours[i]; + if (t.isOffMap()) { + Orientation o = Orientation.fromAdj(t.col, t.row, to.col, to.row); + if (o.isInSides(allowedMoves)) { + o = o.opposite(); + boolean r = to.road(o); + int c = to.costFrom(pawn, o); + if ((c < cost) || (r && (c == cost))) { + entry = o; + cost = c; + road = r; + } + } + } + } + + return entry.opposite(); + } + + public void enableOverlayOn(Tile tile, int i, boolean enable) + { + if(tile.enableOverlay(i, enable)) + tilesToDraw.add(tile); + else + tilesToDraw.remove(tile); + } + + public void enableOverlayOn(Tile tile, int i, Orientation o, boolean enable) + { + if(tile.enableOverlay(i, enable, o.r())) + tilesToDraw.add(tile); + else + tilesToDraw.remove(tile); + } + + private int pushPawnOnto(Pawn pawn, Tile tile) + { + if (!tile.isOffMap()) + tilesToDraw.add(tile); + return tile.push(pawn); + } + + public int removePawn(Pawn pawn) + { + Tile tile = pawn.getTile(); + if (tile == null) + return 0; + int n = tile.remove(pawn); + if (!tile.mustBeDrawn()) + tilesToDraw.remove(tile); + return n; + } + + public Pawn setPawnOnto(Pawn pawn, Move move) + { + pawn.move(move); + return setPawnOnto(pawn, move.to, move.orientation); + } + + public Pawn setPawnOnto(Pawn pawn, Tile tile, Orientation o) + { + pawn.setOnTile(tile, o.r()); + pushPawnOnto(pawn, tile); + return pawn; + } + + private RunnableAnimation getSetPawnOntoAnimation(final Pawn pawn) + { + return RunnableAnimation.get(pawn, new Runnable() { + @Override + public void run() { + Tile to = pawn.move.to; + if (!to.isOffMap()) + setPawnOnto(pawn, to, pawn.move.orientation); + } + }); + } + + protected void movePawn(final Pawn pawn, Move move, MoveToAnimationCb cb) + { + pawn.move(move); + removePawn(pawn); + + AnimationSequence seq = pawn.getMoveAnimation(move.iterator(), (move.steps() + 1), cb); + seq.addAnimation(getSetPawnOntoAnimation(pawn)); + addAnimation(seq); + } + + protected void enterPawn(final Pawn pawn, Move move) + { + pawn.move(move); + setPawnOnto(pawn, move.to, move.orientation); + } + + protected void revertLastPawnMove(final Pawn pawn) + { + removePawn(pawn); + + addAnimation(RunnableAnimation.get(pawn, new Runnable() { + @Override + public void run() { + pushPawnOnto(pawn, pawn.getTile()); + } + })); + + pawn.revertLastMove(); + } + + public void attack(final Pawn pawn, final Pawn target, boolean clearVisibility) + { + if (!pawn.canEngage(target) || !searchBoard.canAttack(pawn, target, clearVisibility)) + throw new RuntimeException(String.format("%s cannot attack %s", pawn, target)); + } + + public Tile getTileAt(float mx, float my) + { + // compute row + float y = (my - cfg.y0); + int row = (int) (y / cfg.h); + boolean oddRow = ((row % 2) == 1); + if (y < 0.f) { + row = -1; + oddRow = true; + } + + // compute col + float x = (mx - cfg.x0); + if (oddRow) x -= cfg.dw; + int col = (int) (x / cfg.w); + if (x < 0.f) + col = -1; + + int colOffset = ((row + 1) / 2); + + // check upper boundaries + float dy = (y - (row * cfg.h)); + if (dy > cfg.s) { + dy -= cfg.s; + float dx = (x - (col * cfg.w)); + col += colOffset; + if (dx < cfg.dw) { + if ((dx * cfg.slope) < dy) { + // upper left corner + row += 1; + colOffset = ((row +1) / 2); + } + } else { + if (((cfg.w - dx) * cfg.slope) < dy) { + // upper right corner + row += 1; + col += 1; + colOffset = ((row +1) / 2); + } + } + } else + col += colOffset; + + return getTile(col, row); + } + + public int distance(Tile from, Tile to) + { + return distance(from.col, from.row, to.col, to.row); + } + + public int distance(int col0, int row0, int col1, int row1) + { + int dx = Math.abs(col1 - col0); + int dy = Math.abs(row1 - row0); + int dz = Math.abs((col0 - row0) - (col1 - row1)); + + if (dx > dy) { + if (dx > dz) + return dx; + else + return dz; + } else { + if (dy > dz) + return dy; + else + return dz; + } + } +} + diff --git a/core/src/ch/asynk/creepingarmor/engine/Faction.java b/core/src/ch/asynk/creepingarmor/engine/Faction.java new file mode 100644 index 0000000..b45f351 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/Faction.java @@ -0,0 +1,6 @@ +package ch.asynk.creepingarmor.engine; + +public interface Faction +{ + public boolean isEnemy(Faction other); +} diff --git a/core/src/ch/asynk/creepingarmor/engine/HeadedPawn.java b/core/src/ch/asynk/creepingarmor/engine/HeadedPawn.java new file mode 100644 index 0000000..3b78cd5 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/HeadedPawn.java @@ -0,0 +1,88 @@ +package ch.asynk.creepingarmor.engine; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import com.badlogic.gdx.math.Vector3; + +public abstract class HeadedPawn extends Pawn +{ + private Sprite head; + protected Orientation orientation; + + public HeadedPawn(Faction faction, String pawn, String head, TextureAtlas pawns, TextureAtlas overlays) + { + super(faction, pawn, pawns, overlays); + this.head = new Sprite(pawns.findRegion(head)); + this.orientation = Orientation.KEEP; + this.descr += " " + orientation; + } + + @Override + public void dispose() + { + super.dispose(); + } + + @Override + public void setAlpha(float alpha) + { + super.setAlpha(alpha); + head.setAlpha(alpha); + } + + @Override + public float getRotation() + { + return orientation.r(); + } + + @Override + public Orientation getOrientation() + { + return orientation; + } + + @Override + public void setPosition(float x, float y) + { + super.setPosition(x, y); + float cx = x + (getWidth() / 2f); + float cy = y + (getHeight() / 2f); + head.setPosition((cx - (head.getWidth() / 2f)), (cy - (head.getHeight() / 2f))); + } + + @Override + public void setRotation(float z) + { + getPosition().z = z; + head.setRotation(z); + this.orientation = Orientation.fromRotation(z); + } + + @Override + public void setPosition(float x, float y, float z) + { + setPosition(x, y); + setRotation(z); + } + + @Override + public void draw(Batch batch) + { + head.draw(batch); + super.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + float w = head.getWidth(); + float h = head.getHeight(); + debugShapes.rect(head.getX(), head.getY(), (w / 2f), (h / 2f), w, h, head.getScaleX(), head.getScaleY(), head.getRotation()); + super.drawDebug(debugShapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/Meteorology.java b/core/src/ch/asynk/creepingarmor/engine/Meteorology.java new file mode 100644 index 0000000..6d5319e --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/Meteorology.java @@ -0,0 +1,24 @@ +package ch.asynk.creepingarmor.engine; + +public class Meteorology +{ + public enum Day { DAY, NIGHT }; + public enum Season { SUMMER, SPRING, WINTER, FALL }; + public enum Weather { CLEAR, RAIN, SNOW, WIND }; + + public Day day; + public Season season; + public Weather weather; + + public Meteorology() + { + clear(); + } + + public void clear() + { + day = Day.DAY; + season = Season.SUMMER; + weather = Weather.CLEAR; + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/Move.java b/core/src/ch/asynk/creepingarmor/engine/Move.java new file mode 100644 index 0000000..2f33982 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/Move.java @@ -0,0 +1,158 @@ +package ch.asynk.creepingarmor.engine; + +import java.util.Iterator; + +import com.badlogic.gdx.utils.Pool; +import com.badlogic.gdx.math.Vector3; + +public class Move extends Path implements Iterable +{ + public enum MoveType + { + REGULAR, + SET, + ENTER, + EXIT; + } + + private static final Pool movePool = new Pool() + { + @Override + protected Move newObject() { + return new Move(); + } + }; + + public static Move get(Pawn pawn, Tile from, Tile to, Orientation orientation, Path path) + { + Move m = movePool.obtain(); + m.pawn = pawn; + m.from = from; + m.to = to; + m.orientation = orientation; + if (path != null) { + m.init(path.tiles.size()); + m.cost = path.cost; + m.roadMarch = path.roadMarch; + for (Tile tile : path.tiles) + m.tiles.add(tile); + } else { + m.init(0); + } + + return m; + } + + public static void clearPool() + { + movePool.clear(); + } + + public static Move getEnter(Pawn pawn, Tile to, Orientation orientation) + { + Move m = get(pawn, null, to, orientation, null); + m.type = MoveType.ENTER; + m.cost = to.costFrom(pawn, orientation); + return m; + } + + public static Move getSet(Pawn pawn, Tile to, Orientation orientation) + { + Move m = get(pawn, null, to, orientation, null); + m.type = MoveType.SET; + m.cost = 0; + return m; + } + + public Pawn pawn; + public Tile from; + public Tile to; + public Orientation orientation; + public MoveType type; + + public Move() + { + super(); + this.pawn = null; + this.from = null; + this.to = null; + this.orientation = Orientation.KEEP; + this.type = MoveType.REGULAR; + } + + @Override + public void reset() + { + pawn = null; + from = null; + to = null; + orientation = Orientation.KEEP; + type = MoveType.REGULAR; + super.reset(); + } + + @Override + public void dispose() + { + tiles.clear(); + movePool.free(this); + } + + public boolean isSet() + { + return (type == MoveType.SET); + } + + public boolean isEnter() + { + return (type == MoveType.ENTER); + } + + public boolean isRegular() + { + return (type == MoveType.REGULAR); + } + + public boolean isFinal() + { + return (type != MoveType.ENTER); + } + + public int steps() + { + int steps = 0; + + Tile tile = from; + Orientation o = pawn.getOrientation(); + for (Tile next : tiles) { + Orientation nextO = Orientation.fromMove(tile.col, tile.row, next.col, next.row); + if (nextO != o) { + steps += 2; + o = nextO; + } else + steps += 1; + tile = next; + } + if (orientation != Orientation.fromMove(tile.col, tile.row, to.col, to.row)) + steps += 2; + else + steps +=1; + + return steps; + } + + @Override + public String toString() + { + if (from == null) + return String.format("%s %s c:%d", to.toShort(), orientation, cost); + else + return String.format("%s->%s %s c:%d", from.toShort(), to.toShort(), orientation, cost); + } + + @Override + public Iterator iterator() + { + return new PathIterator(pawn, from, to, orientation, tiles); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/Objective.java b/core/src/ch/asynk/creepingarmor/engine/Objective.java new file mode 100644 index 0000000..c923cdd --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/Objective.java @@ -0,0 +1,49 @@ +package ch.asynk.creepingarmor.engine; + +public class Objective +{ + protected Faction curFaction; + protected Faction prevFaction; + private boolean persistent; + + public Objective(Faction faction, boolean persistent) + { + this.curFaction = faction; + this.prevFaction = faction; + this.persistent = persistent; + } + + public boolean is(Faction faction) + { + return (curFaction == faction); + } + + public Faction faction() + { + return curFaction; + } + + public boolean set(Faction faction) + { + if (faction == curFaction) + return false; + + prevFaction = curFaction; + curFaction = faction; + return true; + } + + public boolean unset() + { + if (persistent) + return false; + revert(); + return true; + } + + public Faction revert() + { + curFaction = prevFaction; + return curFaction; + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/ObjectiveSet.java b/core/src/ch/asynk/creepingarmor/engine/ObjectiveSet.java new file mode 100644 index 0000000..be1b0bb --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/ObjectiveSet.java @@ -0,0 +1,78 @@ +package ch.asynk.creepingarmor.engine; + +import java.util.Collection; +import java.util.HashMap; + +public class ObjectiveSet extends HashMap +{ + public interface ObjectiveCb + { + public void showObjective(Tile tile, Faction faction); + } + + private final Board board; + private final HashMap modified; + + public ObjectiveSet(Board board, int n) + { + super(n); + this.board = board; + this.modified = new HashMap(10); + } + + public void add(Tile tile, Faction faction, boolean persistent) + { + put(tile, new Objective(faction, persistent)); + } + + public int count(Faction faction) + { + int n = 0; + for (Objective objective : values()) { + if (objective.is(faction)) + n += 1; + } + return n; + } + + public Faction claim(Tile tile, Faction faction) + { + Objective objective = get(tile); + if (objective == null) + return null; + + if (objective.set(faction)) + modified.put(objective, tile); + return objective.faction(); + } + + public Faction unclaim(Tile tile) + { + Objective objective = get(tile); + if (objective == null) + return null; + + if (objective.unset()) + modified.remove(objective); + return objective.faction(); + } + + public void forget() + { + modified.clear(); + } + + public int modifiedCount() + { + return modified.size(); + } + + public void revert(ObjectiveCb cb) + { + for (Objective objective : modified.keySet()) { + objective.revert(); + cb.showObjective(modified.get(objective), objective.faction()); + } + modified.clear(); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/Order.java b/core/src/ch/asynk/creepingarmor/engine/Order.java new file mode 100644 index 0000000..51fa8b0 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/Order.java @@ -0,0 +1,16 @@ +package ch.asynk.creepingarmor.engine; + +import java.lang.Comparable; + +import com.badlogic.gdx.utils.Disposable; +import com.badlogic.gdx.utils.Pool; +import com.badlogic.gdx.utils.Json; + +public abstract class Order implements Disposable, Pool.Poolable, Json.Serializable, Comparable +{ + public interface OrderType + { + } + + public abstract boolean isA(OrderType type); +} diff --git a/core/src/ch/asynk/creepingarmor/engine/OrderList.java b/core/src/ch/asynk/creepingarmor/engine/OrderList.java new file mode 100644 index 0000000..c5d7037 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/OrderList.java @@ -0,0 +1,64 @@ +package ch.asynk.creepingarmor.engine; + +import java.util.LinkedList; +import java.util.Iterator; + +import com.badlogic.gdx.utils.Json; +import com.badlogic.gdx.utils.JsonValue; +import com.badlogic.gdx.utils.JsonWriter.OutputType; + +public class OrderList extends LinkedList implements Json.Serializable +{ + public void dispose(Pawn pawn) + { + Iterator it = iterator(); + while(it.hasNext()) { + Order order = it.next(); + if (order.compareTo(pawn) == 0) { + it.remove(); + order.dispose(); + } + } + } + + public void dispose(Pawn pawn, Order.OrderType type) + { + Iterator it = iterator(); + while(it.hasNext()) { + Order order = it.next(); + if ((order.compareTo(pawn) == 0) && (order.isA(type))) { + it.remove(); + order.dispose(); + } + } + } + + public void dispose() + { + for (Order o : this) + o.dispose(); + clear(); + } + + public String toJson() + { + Json json = new Json(); + json.setOutputType(OutputType.json); + return json.toJson(this); + } + + @Override + public void write(Json json) + { + json.writeArrayStart("commands"); + for (Order o : this) + json.writeValue(o); + json.writeArrayEnd(); + } + + @Override + public void read(Json json, JsonValue jsonMap) + { + // TODO read(Json json, JsonValue jsonMap) + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/Orientation.java b/core/src/ch/asynk/creepingarmor/engine/Orientation.java new file mode 100644 index 0000000..a061d05 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/Orientation.java @@ -0,0 +1,134 @@ +package ch.asynk.creepingarmor.engine; + +public enum Orientation +{ + ALL(0, 63), + KEEP(0, 0), + NORTH(270, 1), + NORTH_EAST(210, 2), + SOUTH_EAST(150, 4), + SOUTH(90, 8), + SOUTH_WEST (30, 16), + NORTH_WEST(330, 32); + + public static int offset = 0; + public static float delta = 5f; + private final int r; + public final int s; + + Orientation(int r, int s) { this.r = r; this.s = s; } + + public float r() { return offset + r; } + + public boolean isInSides(int sides) + { + return ((sides & s) == s); + } + + public Orientation left() + { + if (this == NORTH) return NORTH_WEST; + else return fromSide(s >> 1); + } + + public Orientation right() + { + if (this == NORTH_WEST) return NORTH; + else return fromSide(s << 1); + } + + public Orientation opposite() + { + return left().left().left(); + } + + public int allBut() + { + return ALL.s & (s ^ 0xFFFF); + } + + public int getFrontSides() + { + return s | left().s | right().s; + } + + public int getBackSides() + { + return opposite().getFrontSides(); + } + + public static Orientation fromSide(int s) + { + if (s == NORTH.s) return NORTH; + else if (s == NORTH_EAST.s) return NORTH_EAST; + else if (s == SOUTH_EAST.s) return SOUTH_EAST; + else if (s == SOUTH.s) return SOUTH; + else if (s == SOUTH_WEST.s) return SOUTH_WEST; + else if (s == NORTH_WEST.s) return NORTH_WEST; + else return KEEP; + } + + public static Orientation fromRotation(float r) + { + if (r < 0) r += 360f; + if ((r > (NORTH.r - 5f)) && (r < (NORTH.r + 5f))) return NORTH; + else if ((r > (NORTH_EAST.r - delta)) && (r < (NORTH_EAST.r + delta))) return NORTH_EAST; + else if ((r > (SOUTH_EAST.r - delta)) && (r < (SOUTH_EAST.r + delta))) return SOUTH_EAST; + else if ((r > (SOUTH.r - delta)) && (r < (SOUTH.r + delta))) return SOUTH; + else if ((r > (SOUTH_WEST.r - delta)) && (r < (SOUTH_WEST.r + delta))) return SOUTH_WEST; + else if ((r > (NORTH_WEST.r - delta)) && (r < (NORTH_WEST.r + delta))) return NORTH_WEST; + else return KEEP; + } + + public static Orientation fromMove(int col0, int row0, int col1, int row1) + { + int dx = col1 - col0; + int dy = row1 - row0; + + if (dy == 0) { + if (dx == 0) return KEEP; + if (dx > 0) return NORTH; + return SOUTH; + } + if (dy > 0) { + if (dx > 0) return NORTH_WEST; + return SOUTH_WEST; + } else { + if (dx < 0) return SOUTH_EAST; + return NORTH_EAST; + } + } + + public static Orientation fromAdj(Tile from, Tile to) + { + return fromAdj(from.col, from.row, to.col, to.row); + } + + public static Orientation fromAdj(int col0, int row0, int col1, int row1) + { + Orientation o = KEEP; + + if (row1 == row0) { + if (col1 == (col0 - 1)) { + o = SOUTH; + } else if (col1 == (col0 + 1)) { + o = NORTH; + } + } else if (row1 == (row0 - 1)) { + if (col1 == (col0 - 1)) { + o = SOUTH_EAST; + } else if (col1 == col0) { + o = NORTH_EAST; + } + + } else if (row1 == (row0 + 1)) { + if (col1 == col0) { + o = SOUTH_WEST; + } else if (col1 == (col0 + 1)) { + o = NORTH_WEST; + } + } + + return o; + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/Path.java b/core/src/ch/asynk/creepingarmor/engine/Path.java new file mode 100644 index 0000000..20da213 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/Path.java @@ -0,0 +1,62 @@ +package ch.asynk.creepingarmor.engine; + +import java.util.ArrayList; + +import com.badlogic.gdx.utils.Pool; +import com.badlogic.gdx.utils.Disposable; + +public class Path implements Disposable, Pool.Poolable +{ + private static final Pool pathPool = new Pool() { + @Override + protected Path newObject() { + return new Path(); + } + }; + + public static Path get(int size) + { + Path p = pathPool.obtain(); + p.init(size); + return p; + } + + public static void clearPool() + { + pathPool.clear(); + } + + public int cost; + public boolean roadMarch; + public ArrayList tiles; + + public Path() + { + this.cost = -1; + this.roadMarch = true; + this.tiles = null; + } + + protected void init(int size) + { + if (tiles == null) + tiles = new ArrayList(size); + else + tiles. ensureCapacity(size); + } + + @Override + public void reset() + { + cost = -1; + roadMarch = true; + tiles.clear(); + } + + @Override + public void dispose() + { + tiles.clear(); + pathPool.free(this); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/PathBuilder.java b/core/src/ch/asynk/creepingarmor/engine/PathBuilder.java new file mode 100644 index 0000000..bad14e8 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/PathBuilder.java @@ -0,0 +1,266 @@ +package ch.asynk.creepingarmor.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.LinkedList; +import java.util.HashSet; +import java.util.LinkedHashSet; + +import com.badlogic.gdx.utils.Disposable; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; + +public class PathBuilder implements Disposable +{ + private final Board board; + + public Pawn pawn; + public Tile from; + public Tile to; + public int distance; + public Orientation orientation; + private List stack; + private List ctrlTiles; + private List paths; + private List filteredPaths; + private HashSet tiles; + + public PathBuilder(Board board, int tSize, int stSize, int ftSize, int vectSize) + { + this.board = board; + this.tiles = new LinkedHashSet(tSize); + this.stack = new ArrayList(stSize); + this.ctrlTiles = new ArrayList(ftSize); + this.paths = new LinkedList(); + this.filteredPaths = new LinkedList(); + this.to = null; + this.pawn = null; + this.orientation = Orientation.KEEP; + } + + public void init(Pawn pawn, Tile from) + { + this.pawn = pawn; + this.from = from; + } + + public void init(Pawn pawn) + { + init(pawn, pawn.getTile()); + } + + public void initRotation(Pawn pawn, Orientation o) + { + init(pawn, pawn.getTile()); + build(pawn.getTile()); + orientation = o; + } + + public boolean isSet() + { + return (to != null); + } + + @Override + public void dispose() + { + clear(); + } + + public void clear() + { + this.to = null; + this.distance = -1; + this.orientation = Orientation.KEEP; + for (Path path : this.paths) path.dispose(); + this.tiles.clear(); + this.stack.clear(); + this.ctrlTiles.clear(); + this.paths.clear(); + this.filteredPaths.clear(); + } + + public int size() + { + if (ctrlTiles.size() == 0) + return paths.size(); + return filteredPaths.size(); + } + + public boolean contains(Tile tile) + { + return tiles.contains(tile); + } + + public void enable(int i, boolean enable) + { + for (Tile tile : tiles) + board.enableOverlayOn(tile, i, enable); + } + + public int build(Tile to) + { + clear(); + this.to = to; + // from and to are not part of the path + this.distance = board.distance(from, to); + if (distance < 2) { + Orientation o = Orientation.fromMove(to.col, to.row, from.col, from.row); + Path path = Path.get(0); + path.roadMarch = to.road(o); + path.cost = to.costFrom(pawn, o); + paths.add(path); + } else { + findAllPaths(from, pawn.getMovementPoints(), true); + } + + // printToErr("paths", paths); + stack.clear(); + return paths.size(); + } + + private void findAllPaths(Tile from, int mvtLeft, boolean roadMarch) + { + Tile moves[] = new Tile[6]; + board.setAdjacentTiles(from, moves); + + for(int i = 0; i < 6; i++) { + Tile next = moves[i]; + if ((next == null) || next.isOffMap()) continue; + + Orientation o = board.getSide(i); + int m = (mvtLeft - next.costFrom(pawn, o)); + boolean r = roadMarch & next.road(o); + + int l = (m + (r ? pawn.getRoadMarchBonus() : 0)); + + if ((board.distance(next, to) <= l)) { + if (next == to) { + Path path = Path.get(stack.size() + 1); + for (Tile t: stack) { + path.tiles.add(t); + tiles.add(t); + } + path.roadMarch = r; + path.cost = (pawn.getMovementPoints() - m); + paths.add(path); + } else { + stack.add(next); + findAllPaths(next, m, r); + stack.remove(stack.size() - 1); + } + } + } + } + + public int toggleCtrlTile(Tile tile) + { + if (ctrlTiles.contains(tile)) + ctrlTiles.remove(tile); + else + ctrlTiles.add(tile); + return filterPaths(); + } + + private int filterPaths() + { + int s = ctrlTiles.size(); + + tiles.clear(); + filteredPaths.clear(); + for (Path path : paths) { + int ok = 0; + for (Tile filter : ctrlTiles) { + if (path.tiles.contains(filter)) + ok += 1; + } + if (ok == s) { + if (path.tiles.size() == (s + 0)) { // from and to are not part of the path + filteredPaths.clear(); + filteredPaths.add(path); + tiles.clear(); + for (Tile tile : path.tiles) tiles.add(tile); + break; + } else { + filteredPaths.add(path); + for (Tile tile : path.tiles) tiles.add(tile); + } + } + } + + // printToErr("filteredPaths", filteredPaths); + return filteredPaths.size(); + } + + public int pathCost(int i) + { + return paths.get(i).cost; + } + + public Move getMove() + { + if (size() != 1) { + System.err.println("ask for only move but they are many"); + return null; + } + + return Move.get(pawn, from, to, orientation, getPath(0)); + } + + public Move getExitMove() + { + Move move = getMove(); + move.type = Move.MoveType.EXIT; + return move; + } + + public boolean canExit(Orientation o) + { + List ps; + if (ctrlTiles.size() == 0) + ps = paths; + else + ps = filteredPaths; + + int mvt = pawn.getMovementPoints(); + int rBonus = pawn.getRoadMarchBonus(); + boolean road = to.road(o); + int cost = to.exitCost(); + + for (Path p : ps) { + int c = (p.cost + cost); + if ((c <= mvt) || (p.roadMarch && road && (c <= (mvt + rBonus)))) + return true; + } + return false; + } + + public Path getPath(int i) + { + if (ctrlTiles.size() == 0) + return paths.get(i); + return filteredPaths.get(i); + } + + public void setExit(Orientation o) + { + orientation = o; + Path path = getPath(0); + if (from != to) { + path.cost += 1; + path.tiles.add(to); + } + to = board.getAdjTileAt(to, o); + } + + private void printToErr(String what, List paths) + { + System.err.println(what + pawn + " ("+paths.size()+") " + from + " -> " + to); + for (Path path : paths) { + System.err.println(String.format(" - path (l:%d c:%d r:%b)", path.tiles.size(), path.cost, path.roadMarch)); + for(Tile tile : path.tiles) + System.err.println(" " + tile.toString()); + } + System.err.println(); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/PathIterator.java b/core/src/ch/asynk/creepingarmor/engine/PathIterator.java new file mode 100644 index 0000000..ca74ed4 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/PathIterator.java @@ -0,0 +1,73 @@ +package ch.asynk.creepingarmor.engine; + +import java.util.List; +import java.util.Iterator; + +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; + +public class PathIterator implements Iterator +{ + private Pawn pawn; + private Tile to; + private Orientation o; + private Orientation orientation; + private Tile tile; + private Vector2 pos = new Vector2(); + private Vector3 v = new Vector3(); + private int i; + private List path; + + public PathIterator(Pawn pawn, Tile from, Tile to, Orientation orientation, List path) + { + this.pawn = pawn; + this.to = to; + this.tile = from; + this.orientation = orientation; + this.path = path; + this.o = pawn.getOrientation(); + this.v.set(pawn.getPosition().x, pawn.getPosition().y, o.r()); + this.i = 0; + } + + @Override + public boolean hasNext() + { + if ((tile == to) && (o == orientation)) + return false; + return true; + } + + @Override + public Vector3 next() + { + if (tile == to) { + v.z = orientation.r(); + o = orientation; + return v; + } + Tile nextTile; + if (i < path.size()) + nextTile = path.get(i); + else + nextTile = to; + Orientation nextO = Orientation.fromMove(tile.col, tile.row, nextTile.col, nextTile.row); + if (nextO != o) { + v.z = nextO.r(); + o = nextO; + return v; + } + pawn.getPosAt(nextTile, pos); + v.x = pos.x; + v.y = pos.y; + tile = nextTile; + i += 1; + return v; + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/Pawn.java b/core/src/ch/asynk/creepingarmor/engine/Pawn.java new file mode 100644 index 0000000..7f82f1c --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/Pawn.java @@ -0,0 +1,365 @@ +package ch.asynk.creepingarmor.engine; + +import java.util.Iterator; + +import com.badlogic.gdx.utils.Disposable; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; + +import ch.asynk.creepingarmor.engine.gfx.Moveable; +import ch.asynk.creepingarmor.engine.gfx.StackedImages; +import ch.asynk.creepingarmor.engine.gfx.animations.MoveToAnimation; +import ch.asynk.creepingarmor.engine.gfx.animations.RunnableAnimation; +import ch.asynk.creepingarmor.engine.gfx.animations.AnimationSequence; + +public abstract class Pawn implements Moveable, Disposable +{ + public interface PawnType + { + } + + public interface PawnId + { + } + + private static final float MOVE_TIME = 0.4f; + + private Vector3 position; + private Vector3 prevPosition; + private Tile tile; + private Tile prevTile; + protected Faction faction; + protected String descr; + private Sprite sprite; + private StackedImages overlays; + protected Attack attack; + protected Move move; + + public abstract int getMovementPoints(); + public abstract int getRoadMarchBonus(); + public abstract int getAngleOfAttack(); + public abstract int getFlankSides(); + public abstract int getEngagementRangeFrom(Tile tile); + public abstract int getDefense(Tile tile); + + public abstract boolean isUnit(); + public abstract boolean isA(PawnId id); + public abstract boolean isA(PawnType type); + public abstract boolean isHq(); + public abstract boolean isHqOf(Pawn other); + public abstract boolean isHardTarget(); + + public abstract boolean canMove(); + public abstract boolean canRotate(); + public abstract boolean canEngage(); + public abstract boolean canEngage(Pawn other); + public abstract boolean canAssistEngagementWithoutLos(); + + public abstract void move(); + public abstract void engage(); + + public abstract void revertLastMove(); + + protected Pawn() + { + this.tile = null; + this.prevTile = null; + this.position = new Vector3(0f, 0f, 0f); + this.prevPosition = new Vector3(0f, 0f, 0f); + this.attack = new Attack(this); + } + + public Pawn(Faction faction, String name, TextureAtlas pawns, TextureAtlas overlays) + { + this(); + this.faction = faction; + this.descr = descr; + this.sprite = new Sprite(pawns.findRegion(name)); + this.overlays = new StackedImages(overlays); + } + + @Override + public String toString() + { + return descr; + } + + @Override + public void dispose() + { + } + + @Override + public Faction getFaction() + { + return faction; + } + + public void reset() + { + move = null; + attack.reset(); + } + + public void move(Move move) + { + switch(move.type) + { + case REGULAR: + if ((this.move != null) && (!this.move.isEnter())) + throw new RuntimeException("try to override an existing move instance"); + break; + case ENTER: + if (this.move != null) + throw new RuntimeException("try to override an existing move instance"); + break; + case SET: + break; + default: + throw new RuntimeException("unsupported MoveType"); + } + + this.move = move; + move(); + } + + public void setAttack(Pawn target, int distance) + { + attack.reset(); + attack.target = target; + attack.distance = distance; + } + + public boolean justEntered() + { + return ((move != null) && move.isEnter()); + } + + public boolean is(Faction faction) + { + return (this.faction == faction); + } + + public boolean isEnemy(Faction other) + { + return faction.isEnemy(other); + } + + public boolean isEnemy(Pawn other) + { + return faction.isEnemy(other.faction); + } + + public boolean isFlankAttack() + { + return (attack.isClear && attack.isFlank); + } + + public int attackDistance() + { + return attack.distance; + } + + public Tile getTile() + { + return tile; + } + + public Tile getPreviousTile() + { + return prevTile; + } + + public Vector3 getPosition() + { + return position; + } + + public Vector3 getPreviousPosition() + { + return prevPosition; + } + + private void revertPosition() + { + this.tile = this.prevTile; + this.prevTile = null; + position.set(prevPosition); + prevPosition.set(0f, 0f, 0f); + setPosition(position.x, position.y, position.z); + } + + public float getCenterX() + { + return (getX() + (getWidth() / 2f)); + } + + public float getCenterY() + { + return (getY() + (getHeight() / 2f)); + } + + public Vector2 getPosAt(Tile tile, Vector2 pos) + { + float x = (tile.getX() - (getWidth() / 2f)); + float y = (tile.getY() - (getHeight() / 2f)); + if (pos == null) + return new Vector2(x, y); + else + pos.set(x, y); + return pos; + } + + public void setOnTile(Tile tile, float z) + { + this.prevTile = this.tile; + this.tile = tile; + float x = (tile.getX() - (getWidth() / 2f)); + float y = (tile.getY() - (getHeight() / 2f)); + setPosition(x, y, z); + } + + @Override + public void setAlpha(float alpha) + { + sprite.setAlpha(alpha); + overlays.setAlpha(alpha); + } + + @Override + public float getX() + { + return sprite.getX(); + } + + @Override + public float getY() + { + return sprite.getY(); + } + + @Override + public float getWidth() + { + return sprite.getWidth(); + } + + @Override + public float getHeight() + { + return sprite.getHeight(); + } + + @Override + public float getRotation() + { + return sprite.getRotation(); + } + + public Orientation getOrientation() + { + return Orientation.fromRotation(getRotation()); + } + + public void translate(float dx, float dy) + { + setPosition((getX() + dx), (getY() + dy)); + } + + public void centerOn(float x, float y) + { + setPosition((x - (getWidth() / 2f)), (y - (getHeight() / 2f))); + } + + @Override + public void setPosition(float x, float y) + { + position.set(x, y, 0f); + sprite.setPosition(x, y); + float cx = x + (getWidth() / 2f); + float cy = y + (getHeight() / 2f); + overlays.centerOn(cx, cy); + } + + public void setRotation(float z) + { + position.z = z; + sprite.setRotation(z); + overlays.setRotation(z); + } + + @Override + public void setPosition(float x, float y, float z) + { + setPosition(x, y); + setRotation(z); + } + + public boolean hasOverlayEnabled() + { + return overlays.isEnabled(); + } + + public boolean enableOverlay(int i, boolean enable) + { + overlays.enable(i, enable); + if (enable) return true; + return hasOverlayEnabled(); + } + + public AnimationSequence getRotateAnimation(float z, int size) + { + prevPosition.set(position); + AnimationSequence seq = AnimationSequence.get(1 + size); + seq.addAnimation(MoveToAnimation.get(this, position.x, position.y, z, MOVE_TIME)); + + return seq; + } + + public AnimationSequence getMoveAnimation(Iterator vectors, int size, MoveToAnimation.MoveToAnimationCb cb) + { + prevPosition.set(position); + AnimationSequence seq = AnimationSequence.get(size); + while (vectors.hasNext()) + seq.addAnimation(MoveToAnimation.get(this, vectors.next(), MOVE_TIME, cb)); + + return seq; + } + + public AnimationSequence getRevertLastMoveAnimation(int size) + { + AnimationSequence seq = AnimationSequence.get(2 + size); + seq.addAnimation(MoveToAnimation.get(this, prevPosition, MOVE_TIME)); + seq.addAnimation(RunnableAnimation.get(this, new Runnable() { + @Override + public void run() { + revertPosition(); + } + })); + + return seq; + } + + @Override + public void draw(Batch batch) + { + sprite.draw(batch); + overlays.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + float w = sprite.getWidth(); + float h = sprite.getHeight(); + debugShapes.rect(sprite.getX(), sprite.getY(), (w / 2f), (h / 2f), w, h, sprite.getScaleX(), sprite.getScaleY(), sprite.getRotation()); + overlays.drawDebug(debugShapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/SearchBoard.java b/core/src/ch/asynk/creepingarmor/engine/SearchBoard.java new file mode 100644 index 0000000..2a7db3e --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/SearchBoard.java @@ -0,0 +1,545 @@ +package ch.asynk.creepingarmor.engine; + +import java.util.List; +import java.util.ArrayList; +import java.util.Set; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.ArrayDeque; +import java.util.Iterator; +import java.util.Collection; + +public class SearchBoard +{ + public class Node + { + public int col; + public int row; + public int search; + public int remaining; + public Node parent; + public boolean roadMarch; + + public Node(int col, int row) + { + this.col = col; + this.row = row; + } + + @Override + public String toString() + { + return col + ";" + row; + } + } + + private int cols; + private int rows; + private Board board; + private int searchCount; + private Node nodes[]; + + private ArrayDeque stack; + private LinkedList queue; + private ArrayDeque roadMarch; + private List los; + + public SearchBoard(Board board, int cols, int rows) + { + this.cols = cols; + this.rows = rows; + this.board = board; + this.searchCount = 0; + + this.nodes = new Node[cols * rows]; + for (int j = 0; j < rows; j++) { + int dx = ((j + 1) / 2); + for (int i = 0; i < cols; i++) + nodes[i + (j * cols)] = new Node((i + dx), j); + } + + this.queue = new LinkedList(); + this.stack = new ArrayDeque(20); + this.roadMarch = new ArrayDeque(5); + this.los = new ArrayList(10); + } + + private boolean inMap(int col, int row) + { + if ((row < 0) || (row >= rows)) + return false; + + int colOffset = ((row + 1) / 2); + if ((col < colOffset) || ((col - colOffset) >= cols)) + return false; + + return true; + } + + private Tile getTile(Node node) + { + return board.getTile(node.col, node.row); + } + + private Node getNode(Tile tile) + { + return getNode(tile.col, tile.row); + } + + protected Node getNode(int col, int row) + { + int colOffset = ((row + 1) / 2); + if ((col < colOffset) || (row < 0) || (row >= rows) || ((col - colOffset) >= cols)) + return null; + + return nodes[((col - colOffset)) + (row * cols)]; + } + + public int distance(Node from, Node to) + { + return board.distance(from.col, from.row, to.col, to.row); + } + + public void adjacentMoves(Node src, Node a[]) + { + // move to enter dst by sides[i] + a[0] = getNode((src.col - 1), src.row); + a[1] = getNode(src.col, (src.row + 1)); + a[2] = getNode((src.col + 1), (src.row + 1)); + a[3] = getNode((src.col + 1), src.row); + a[4] = getNode(src.col, (src.row - 1)); + a[5] = getNode((src.col - 1), (src.row - 1)); + } + + public int possibleMovesFrom(Pawn pawn, Collection moves) + { + moves.clear(); + searchCount += 1; + + Node adjacents[] = new Node[6]; + + Node from = getNode(pawn.getTile()); + from.parent = null; + from.search = searchCount; + from.remaining = pawn.getMovementPoints(); + from.roadMarch = true; + + if (from.remaining <= 0) + return moves.size(); + + int roadMarchBonus = pawn.getRoadMarchBonus(); + boolean first = true; + + stack.push(from); + + while (stack.size() != 0) { + Node src = stack.pop(); + + if (src.remaining < 0) + continue; + if (src.remaining == 0) { + if (src.roadMarch) + roadMarch.push(src); + continue; + } + + adjacentMoves(src, adjacents); + + for(int i = 0; i < 6; i++) { + Node dst = adjacents[i]; + if (dst != null) { + + Tile t = getTile(dst); + int cost = t.costFrom(pawn, board.getSide(i)); + boolean mayMoveOne = first && t.atLeastOneMove(pawn); + int r = src.remaining - cost; + boolean roadMarch = (src.roadMarch && t.road(board.getSide(i))); + + if (dst.search == searchCount) { + if ((r >= 0) && ((r > dst.remaining) || (roadMarch && ((r + roadMarchBonus) >= dst.remaining)))) { + dst.remaining = r; + dst.parent = src; + dst.roadMarch = roadMarch; + stack.push(dst); + moves.add(getTile(dst)); + } + } else { + dst.search = searchCount; + if ((r >= 0) || mayMoveOne) { + dst.parent = src; + dst.remaining = r; + dst.roadMarch = roadMarch; + stack.push(dst); + moves.add(getTile(dst)); + } else { + dst.parent = null; + dst.remaining = -1; + } + } + } + } + first = false; + } + + for (Node n : roadMarch) n.remaining = roadMarchBonus; + while(roadMarch.size() != 0) { + Node src = roadMarch.pop(); + + adjacentMoves(src, adjacents); + + for(int i = 0; i < 6; i++) { + Node dst = adjacents[i]; + if (dst != null) { + + Tile t = getTile(dst); + if (!t.road(board.getSide(i))) + continue; + int cost = t.costFrom(pawn, board.getSide(i)); + int r = src.remaining - cost; + + if (dst.search == searchCount) { + if ((r >= 0) && (r > dst.remaining)) { + dst.remaining = r; + dst.parent = src; + dst.roadMarch = true; + roadMarch.push(dst); + moves.add(getTile(dst)); + } + } else { + dst.search = searchCount; + if (r >= 0) { + dst.parent = src; + dst.remaining = r; + dst.roadMarch = true; + roadMarch.push(dst); + moves.add(getTile(dst)); + } else { + dst.parent = null; + dst.remaining = -1; + } + } + } + } + } + + return moves.size(); + } + + private void adjacentTargets(Node src, int angle, Node a[]) + { + // move in allowed directions + if (Orientation.NORTH.isInSides(angle)) + a[0] = getNode((src.col + 1), src.row); + else + a[0] = null; + + if (Orientation.NORTH_EAST.isInSides(angle)) + a[1] = getNode(src.col, (src.row - 1)); + else + a[1] = null; + + if (Orientation.SOUTH_EAST.isInSides(angle)) + a[2] = getNode((src.col - 1), (src.row - 1)); + else + a[2] = null; + + if (Orientation.SOUTH.isInSides(angle)) + a[3] = getNode((src.col - 1), src.row); + else + a[3] = null; + + if (Orientation.SOUTH_WEST.isInSides(angle)) + a[4] = getNode(src.col, (src.row + 1)); + else + a[4] = null; + + if (Orientation.NORTH_WEST.isInSides(angle)) + a[5] = getNode((src.col + 1), (src.row + 1)); + else + a[5] = null; + } + + public int possibleTargetsFrom(Pawn pawn, Collection targets) + { + targets.clear(); + searchCount += 1; + + Node adjacents[] = new Node[6]; + + int range = pawn.getEngagementRangeFrom(pawn.getTile()); + int angle = pawn.getAngleOfAttack(); + int extendedAngle = pawn.getOrientation().opposite().allBut(); + + Node from = getNode(pawn.getTile()); + from.search = searchCount; + from.remaining = range; + + if (range <= 0) + return targets.size(); + + queue.add(from); + + boolean first = true; + while (queue.size() != 0) { + Node src = queue.remove(); + + if (src.remaining <= 0) + continue; + + if (!first && (((range - src.remaining) % 2) == 0)) + adjacentTargets(src, extendedAngle, adjacents); + else + adjacentTargets(src, angle, adjacents); + + first = false; + int rangeLeft = src.remaining - 1; + + for(int i = 0; i < 6; i++) { + Node dst = adjacents[i]; + if (dst != null) { + if (dst.search == searchCount) { + if ((rangeLeft > dst.remaining)) + dst.remaining = rangeLeft; + } else { + dst.search = searchCount; + dst.remaining = rangeLeft; + queue.add(dst); + Tile t = getTile(dst); + if (hasClearLineOfSight(from, dst, angle)) { + Iterator it = t.iterator(); + while (it.hasNext()) { + Pawn target = it.next(); + if (pawn.canEngage(target)) + targets.add(target); + } + } + } + } + } + } + + return targets.size(); + } + + public boolean canAttack(Pawn pawn, Pawn target, boolean clearVisibility) + { + Node from = getNode(pawn.getTile()); + Node to = getNode(target.getTile()); + + pawn.setAttack(target, distance(from, to)); + + if (pawn.attack.distance > pawn.getEngagementRangeFrom(pawn.getTile())) + return false; + + List los = lineOfSight(from.col, from.row, to.col, to.row, clearVisibility); + Node last = los.get(los.size() -1); + if (last != to) + return false; + + if (!validatePathAngle(pawn.getAngleOfAttack(), los)) + return false; + + pawn.attack.isClear = isClearAttack(getTile(from), los); + pawn.attack.isFlank = isFlankAttack(target.getFlankSides(), los); + + return true; + } + + private boolean hasClearLineOfSight(Node from, Node to, int angleOfAttack) + { + List los = lineOfSight(from.col, from.row, to.col, to.row, true); + Node last = los.get(los.size() -1); + if ((last.col != to.col) || (last.row != to.row)) + return false; + return validatePathAngle(angleOfAttack, los); + } + + private boolean isFlankAttack(int angle, List los) + { + Node from = los.get(los.size() - 2); + Node to = los.get(los.size() - 1); + Orientation o = Orientation.fromMove(to.col, to.row, from.col, from.row); + return o.isInSides(angle); + } + + private boolean isClearAttack(Tile from, List los) + { + int n = los.size() - 1; + for (int i = 1; i < n; i++) { + if (getTile(los.get(i)).blockLineOfSightFrom(from)) + return false; + } + return true; + } + + private boolean validatePathAngle(int angle, List los) + { + int forth = 0; + Node prev = null; + for (Node next : los) { + if (prev != null) { + Orientation o = Orientation.fromMove(prev.col, prev.row, next.col, next.row); + if (!o.isInSides(angle)) { + forth -= 1; + if (forth < 0) + return false; + } + forth += 1; + } + prev = next; + } + + return true; + } + + public List lineOfSight(int x0, int y0, int x1, int y1, boolean clearVisibility) + { + los.clear(); + Tile from = board.getTile(x0, y0); + + // orthogonal axis + int ox0 = x0 - ((y0 +1) / 2); + int ox1 = x1 - ((y1 +1) / 2); + + int dy = y1 - y0; + int dx = ox1 - ox0; + + int xs = 1; + int ys = 1; + if (dx < 0) xs = -1; + if (dy < 0) ys = -1; + boolean sig = !(((dx < 0) && (dy >= 0)) || ((dx >= 0) && (dy < 0))); + + dy = Math.abs(dy); + dx = Math.abs(2 * dx); + if ((dy % 2) == 1) { + if ((y0 % 2) == 0) dx += xs; + else { + dx -= xs; + Math.abs(dx); + } + } + + if (dx == 0) + return verticalLineOfSight(x0, y0, x1, y1, clearVisibility); + if (dx == (3 * dy)) + return diagonalLineOfSight(x0, y0, x1, y1, clearVisibility); + + int dx3 = 3 * dx; + int dy3 = 3 * dy; + + int x = x0; + int y = y0; + int e = -2 * dx; + + boolean flat = (dx > (3 * dy)); + boolean diag = (dx == (3 * dy)); + + los.add(getNode(x, y)); + while((x != x1) || (y != y1)) { + if (e > 0) { + e -= (dy3 + dx3); + y += ys; + if (!sig) + x -= xs; + } else { + e += dy3; + if ((e > -dx) || (!flat && (e == -dx))) { + e -= dx3; + y += ys; + if (sig) + x += xs; + } else if ((e < -dx3) || (diag && (e == -dx3))) { + e += dx3; + y -= ys; + if (!sig) + x += xs; + } else { + e += dy3; + x += xs; + } + } + los.add(getNode(x, y)); + if(clearVisibility && board.getTile(x, y).blockLineOfSightFrom(from)) return los; + } + + return los; + } + + private List verticalLineOfSight(int x0, int y0, int x1, int y1, boolean clearVisibility) + { + Tile from = board.getTile(x0, y0); + + int d = ( (y1 > y0) ? 1 : -1); + int x = x0; + int y = y0; + + Tile t = null; + los.add(getNode(x, y)); + while((x != x1) || (y != y1)) { + boolean ok = false; + + y += d; + t = board.getTile(x, y); + if (!t.isOffMap()) los.add(getNode(x, y)); + if (!clearVisibility || !t.blockLineOfSightFrom(from)) + ok = true; + + x += d; + t = board.getTile(x, y); + if (!t.isOffMap()) los.add(getNode(x, y)); + if (!clearVisibility || !t.blockLineOfSightFrom(from)) + ok = true; + + if (!ok) + return los; + + y += d; + t = board.getTile(x, y); + if (!t.isOffMap()) los.add(getNode(x, y)); + } + + return los; + } + + private List diagonalLineOfSight(int x0, int y0, int x1, int y1, boolean clearVisibility) + { + Tile from = board.getTile(x0, y0); + + int dy = ( (y1 > y0) ? 1 : -1); + int dx = ( (x1 > x0) ? 1 : -1); + boolean sig = !(((dx < 0) && (dy >= 0)) || ((dx >= 0) && (dy < 0))); + + int x = x0; + int y = y0; + + Tile t = null; + los.add(getNode(x, y)); + while((x != x1) || (y != y1)) { + boolean ok = false; + + x += dx; + t = board.getTile(x, y); + if (!t.isOffMap()) los.add(getNode(x, y)); + if (!clearVisibility || !t.blockLineOfSightFrom(from)) + ok = true; + + y += dy; + if (!sig) + x -= dx; + t = board.getTile(x, y); + if (!t.isOffMap()) los.add(getNode(x, y)); + if (!clearVisibility || !t.blockLineOfSightFrom(from)) + ok = true; + + if (!ok) + return los; + + x += dx; + t = board.getTile(x, y); + if (!t.isOffMap()) los.add(getNode(x, y)); + } + + return los; + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/SelectedTile.java b/core/src/ch/asynk/creepingarmor/engine/SelectedTile.java new file mode 100644 index 0000000..4157f4c --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/SelectedTile.java @@ -0,0 +1,80 @@ +package ch.asynk.creepingarmor.engine; + +import com.badlogic.gdx.utils.Disposable; + +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Drawable; +import ch.asynk.creepingarmor.engine.gfx.Animation; +import ch.asynk.creepingarmor.engine.gfx.animations.Sprites; + +public class SelectedTile implements Disposable, Drawable, Animation +{ + private Sprites sprites; + public Tile tile; + public boolean visible; + public float x; + public float y; + private float elapsed; + private int frame; + private float[] seq; + + public SelectedTile(Texture texture, float[] seq) + { + this.sprites = new Sprites(texture, seq.length, 1); + this.visible = false; + this.tile = null; + this.elapsed = 0f; + this.seq = seq; + } + + public void hide() + { + tile = null; + visible = false; + } + + public void set(Tile tile) + { + this.visible = true; + this.tile = tile; + this.frame = 0; + this.elapsed = 0f; + this.x = (tile.getX() - (sprites.width / 2f)); + this.y = (tile.getY() - (sprites.height / 2f)); + } + + public void dispose() + { + sprites.dispose(); + } + + @Override + public boolean animate(float delta) + { + if (visible) { + elapsed += delta; + if (elapsed > seq[frame]) { + frame = ((frame + 1) % sprites.frames.length); + elapsed = 0f; + } + } + return false; + } + + @Override + public void draw(Batch batch) + { + if (visible) + batch.draw(sprites.frames[frame], x, y); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + if (visible) + debugShapes.rect(x, y, sprites.width, sprites.height); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/Tile.java b/core/src/ch/asynk/creepingarmor/engine/Tile.java new file mode 100644 index 0000000..bd4138a --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/Tile.java @@ -0,0 +1,175 @@ +package ch.asynk.creepingarmor.engine; + +import java.util.List; +import java.util.Iterator; +import java.util.ArrayDeque; + +import com.badlogic.gdx.utils.Disposable; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.math.Vector2; + +import ch.asynk.creepingarmor.engine.Board; +import ch.asynk.creepingarmor.engine.gfx.Drawable; +import ch.asynk.creepingarmor.engine.gfx.StackedImages; + +public abstract class Tile implements Drawable, Disposable, Iterable +{ + public interface TileTerrain + { + } + + protected int col; + protected int row; + protected float x; + protected float y; + private StackedImages overlays; + protected ArrayDeque stack; + + public abstract int defense(); + public abstract int exitCost(); + public abstract int costFrom(Pawn pawn, Orientation side); + + public abstract boolean isOffMap(); + public abstract boolean isA(TileTerrain terrain); + public abstract boolean road(Orientation side); + public abstract boolean atLeastOneMove(Pawn pawn); + public abstract boolean blockLineOfSightFrom(Tile tile); + + protected Tile(int col, int row) + { + this.col = col; + this.row = row; + } + + public Tile(float x, float y, int col, int row, TextureAtlas atlas) + { + this.stack = new ArrayDeque(); + this.x = x; + this.y = y; + this.col = col; + this.row = row; + this.overlays = new StackedImages(atlas); + this.overlays.centerOn(x, y); + } + + public float getX() { return x; } + public float getY() { return y; } + public int getCol() { return col; } + public int getRow() { return row; } + + @Override + public String toString() + { + return String.format("(%d;%d) %s", col, row, (isOffMap() ? "x" : "")); + } + + public String toShort() + { + return String.format("(%d;%d)", col, row); + } + + @Override + public void dispose() + { + stack.clear(); + overlays.dispose(); + } + + public boolean isEmpty() + { + return stack.isEmpty(); + } + + public Iterator iterator() + { + return stack.iterator(); + } + + public int push(Pawn pawn) + { + if (!stack.contains(pawn)) + stack.push(pawn); + return stack.size(); + } + + public int remove(Pawn pawn) + { + stack.remove(pawn); + return stack.size(); + } + + private Pawn getTopPawn() + { + if (isEmpty()) return null; + return stack.getFirst(); + } + + public boolean hasUnits() + { + if (isEmpty()) return false; + Iterator itr = iterator(); + while(itr.hasNext()) { + if (itr.next().isUnit()) + return true; + } + return false; + } + + public boolean mustBeDrawn() + { + if (!isEmpty()) return true; + return hasOverlayEnabled(); + } + + public boolean disableOverlays() + { + overlays.disableAll(); + return !isEmpty(); + } + + public boolean hasOverlayEnabled() + { + return overlays.isEnabled(); + } + + public boolean isOverlayEnabled(int i) + { + return overlays.isEnabled(i); + } + + public boolean enableOverlay(int i, boolean enable) + { + overlays.enable(i, enable); + if (enable) return true; + return mustBeDrawn(); + } + + public boolean enableOverlay(int i, boolean enable, float r) + { + overlays.enable(i, enable); + overlays.rotate(i, r); + if (enable) return true; + return mustBeDrawn(); + } + + @Override + public void draw(Batch batch) + { + overlays.draw(batch); + Pawn pawn = getTopPawn(); + if (pawn != null) + pawn.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + overlays.drawDebug(debugShapes); + Pawn pawn = getTopPawn(); + if (pawn != null) + pawn.drawDebug(debugShapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/Animation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/Animation.java new file mode 100644 index 0000000..ab82ea5 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/Animation.java @@ -0,0 +1,8 @@ +package ch.asynk.creepingarmor.engine.gfx; + +import com.badlogic.gdx.utils.Disposable; + +public interface Animation extends Disposable, Drawable +{ + public boolean animate(float delta); +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/Drawable.java b/core/src/ch/asynk/creepingarmor/engine/gfx/Drawable.java new file mode 100644 index 0000000..5f5117a --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/Drawable.java @@ -0,0 +1,10 @@ +package ch.asynk.creepingarmor.engine.gfx; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +public interface Drawable +{ + public void draw(Batch batch); + public void drawDebug(ShapeRenderer debugShapes); +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/Moveable.java b/core/src/ch/asynk/creepingarmor/engine/gfx/Moveable.java new file mode 100644 index 0000000..a20810d --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/Moveable.java @@ -0,0 +1,16 @@ +package ch.asynk.creepingarmor.engine.gfx; + +import ch.asynk.creepingarmor.engine.Faction; + +public interface Moveable extends Drawable +{ + public void setAlpha(float alpha); + public float getX(); + public float getY(); + public float getWidth(); + public float getHeight(); + public float getRotation(); + public void setPosition(float x, float y); + public void setPosition(float x, float y, float r); + public Faction getFaction(); +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/StackedImages.java b/core/src/ch/asynk/creepingarmor/engine/gfx/StackedImages.java new file mode 100644 index 0000000..60d4a42 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/StackedImages.java @@ -0,0 +1,99 @@ +package ch.asynk.creepingarmor.engine.gfx; + +import com.badlogic.gdx.utils.Disposable; + +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.utils.Array; + +public class StackedImages implements Drawable, Disposable +{ + private boolean enabled[]; + private Array sprites; + + public StackedImages(TextureAtlas atlas) + { + this.sprites = atlas.createSprites(); + this.enabled = new boolean[sprites.size]; + } + + @Override + public void dispose() + { + } + + public void disableAll() + { + for (int i = 0; i < sprites.size; i++) + enabled[i] = false; + } + + public void enable(int i, boolean enable) + { + enabled[i] = enable; + } + + public boolean isEnabled(int i) + { + return enabled[i]; + } + + public boolean isEnabled() + { + for (int i = 0; i < sprites.size; i++) + if (enabled[i]) return true; + return false; + } + + public void setAlpha(float alpha) + { + for (int i = 0, n = sprites.size; i < n; i++) + sprites.get(i).setAlpha(alpha); + } + + public void rotate(int i, float r) + { + sprites.get(i).setRotation(r); + } + + public void setRotation(float r) + { + for (int i = 0, n = sprites.size; i < n; i++) + sprites.get(i).setRotation(r); + } + + public void translate(float dx, float dy) + { + for (int i = 0, n = sprites.size; i < n; i++) + sprites.get(i).translate(dx, dy); + } + + public void centerOn(float cx, float cy) + { + for (int i = 0, n = sprites.size; i < n; i++) { + float x = (cx - (sprites.get(i).getWidth() / 2f)); + float y = (cy - (sprites.get(i).getHeight() / 2f)); + sprites.get(i).setPosition(x, y); + } + } + + @Override + public void draw(Batch batch) + { + for (int i = 0, n = sprites.size; i < n; i++) { + if (enabled[i]) + sprites.get(i).draw(batch); + } + } + + @Override + public void drawDebug(ShapeRenderer shapes) + { + Sprite sprite = sprites.get(0); + float w = sprite.getWidth(); + float h = sprite.getHeight(); + shapes.rect(sprite.getX(), sprite.getY(), (w / 2f), (h / 2f), w, h, sprite.getScaleX(), sprite.getScaleY(), sprite.getRotation()); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/AnimationSequence.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/AnimationSequence.java new file mode 100644 index 0000000..7ac9eb1 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/AnimationSequence.java @@ -0,0 +1,76 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import java.util.ArrayList; + +import com.badlogic.gdx.utils.Pool; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Animation; + +public class AnimationSequence implements Animation, Pool.Poolable +{ + private ArrayList animations; + + private static final Pool animationSequencePool = new Pool() { + @Override + protected AnimationSequence newObject() { + return new AnimationSequence(); + } + }; + + public static AnimationSequence get(int capacity) + { + AnimationSequence seq = animationSequencePool.obtain(); + if (seq.animations == null) + seq.animations = new ArrayList(capacity); + else + seq.animations.ensureCapacity(capacity); + + return seq; + } + + @Override + public void reset() + { + for (int i = 0, n = animations.size(); i < n; i++) + animations.get(i).dispose(); + animations.clear(); + } + + @Override + public void dispose() + { + animationSequencePool.free(this); + } + + public void addAnimation(Animation animation) + { + animations.add(animation); + } + + @Override + public boolean animate(float delta) + { + if(animations.isEmpty()) return true; + + Animation animation = animations.get(0); + if (animation.animate(delta)) { + animations.remove(0); + } + + return (animations.isEmpty()); + } + + @Override + public void draw(Batch batch) + { + animations.get(0).draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + animations.get(0).drawDebug(debugShapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/DestroyAnimation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/DestroyAnimation.java new file mode 100644 index 0000000..16d84b0 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/DestroyAnimation.java @@ -0,0 +1,62 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import com.badlogic.gdx.utils.Disposable; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Moveable; +import ch.asynk.creepingarmor.engine.gfx.Animation; + +public class DestroyAnimation implements Disposable, Animation +{ + private static final float DELAY = 1.5f; + private static final float DURATION = 1.5f; + + private Moveable moveable; + private float x; + private float y; + private int alphaP; + private float elapsed; + + @Override + public void dispose() + { + } + + public void set(float duration, Moveable moveable) + { + this.moveable = moveable; + this.alphaP = 0; + this.elapsed = 0f; + this.x = (moveable.getX() + (moveable.getWidth() / 2f)); + this.y = (moveable.getY() + (moveable.getHeight() / 2f)); + } + + @Override + public boolean animate(float delta) + { + elapsed += delta; + if (elapsed < DELAY) + return false; + + int a = (int) (((elapsed - DELAY) / DURATION) * 10); + if (a != alphaP) { + alphaP = a; + moveable.setAlpha(1f - (alphaP / 10f)); + } + + return (elapsed >= (DELAY + DURATION)); + } + + @Override + public void draw(Batch batch) + { + moveable.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + moveable.drawDebug(debugShapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/DiceAnimation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/DiceAnimation.java new file mode 100644 index 0000000..4d2ca67 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/DiceAnimation.java @@ -0,0 +1,141 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import java.util.Random; + +import com.badlogic.gdx.audio.Sound; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Drawable; +import ch.asynk.creepingarmor.engine.gfx.Animation; + +public class DiceAnimation implements Animation, Drawable +{ + private static final float DURATION = 0.7f; + private static final float DURATION_SCATTERING = 0.5f; + private static final int DICE_DIMENSION = 24; + + private static Random random = new Random(); + private static Sprites dice; + private static Sound sound; + private static double sndId; + private static float volume; + private static int[][] rolls = new int[][]{ + { 25, 40, 55, 70, 85, 100, 115, 99, 83, 67, 51, 36, 37, 52, 67, 66, 65, 64 }, + { 58, 74, 59, 60, 45, 62, 78, 94, 109, 108, 123, 106, 89, 71, 70, 69, 68 }, + { 106, 121, 120, 103, 86, 70, 54, 37, 20, 19, 18, 34, 50, 51, 52, 69, 86, 103, 119, 128 }, + { 95, 79, 93, 92, 91, 90, 104, 103, 102, 85, 84, 67, 66, 65, 49, 32, 16, 0 }, + { 22, 39, 56, 73, 90, 107, 124, 128, 113, 98, 83, 68, 53, 38, 23, 0, 25, 42, 59, 76 }, + { 79, 78, 61, 76, 91, 106, 121, 120, 119, 102, 101, 84, 68, 52, 37, 38, 39, 40, 41, 58, 75, 74, 73, 72 }, + }; + + private float x; + private float y; + private int frame; + private int[] roll; + private float elapsed; + private float duration; + // public boolean stop; + + public static void init(Texture texture, int cols, int rows, Sound s) + { + dice = new Sprites(texture, cols, rows); + sound = s; + sndId = -1; + } + + public static void initSound(float v) + { + sndId = -1; + volume = v; + } + + public static void free() + { + sound.dispose(); + dice.dispose(); + } + + public void translate(float dx, float dy) + { + x += dx; + y += dy; + } + + public float getX() + { + return x; + } + + public float getY() + { + return y; + } + + public int getWidth() + { + return DICE_DIMENSION; + } + + public int getHeight() + { + return DICE_DIMENSION; + } + + public void setPosition(float x, float y) + { + this.x = x; + this.y = y; + } + + public void set(int result) + { + this.frame = 0; + this.elapsed = 0f; + this.roll = rolls[result - 1]; + this.duration = DURATION + (DURATION_SCATTERING * random.nextFloat()); + // this.stop = false; + } + + public boolean isDone() + { + return (elapsed >= duration); + } + + @Override + public void dispose() + { + } + + @Override + public boolean animate(float delta) + { + // if (stop) + // return true; + elapsed += delta; + if (elapsed < duration) { + int idx = (int) (roll.length * elapsed / duration); + if (idx >= roll.length) + idx = (roll.length -1); + frame = roll[idx]; + } + if (sndId == -1) + sndId = sound.play(volume); + + return false; + } + + @Override + public void draw(Batch batch) + { + batch.draw(dice.frames[frame], x, y, DICE_DIMENSION, DICE_DIMENSION); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + debugShapes.rect(x, y, dice.frames[frame].getRegionWidth(), dice.frames[frame].getRegionHeight()); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/FireAnimation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/FireAnimation.java new file mode 100644 index 0000000..c221460 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/FireAnimation.java @@ -0,0 +1,87 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import java.util.Random; + +import com.badlogic.gdx.audio.Sound; +import com.badlogic.gdx.graphics.Texture; + +public class FireAnimation +{ + public static Random random = new Random(); + + public static Sprites infantryFire; + public static Sprites tankFire; + public static Sprites explosion; + + public static Sound infantryFireSnd; + public static Sound tankFireSnd; + public static Sound tankFireSndLong; + public static Sound explosionSnd; + public static Sound explosionSndLong; + + public static double infantryFireSndLongId; + public static double tankFireSndLongId; + public static double explosionSndLongId; + + public static void init( + Texture infantryFireT, int iCols, int iRows, + Texture tankFireT, int sCols, int sRows, + Texture explosionT, int eCols, int eRows, + Sound infantryFireS, + Sound tankFireS, + Sound tankFireLongS, + Sound explosionS, + Sound explosionLongS) + { + infantryFire = new Sprites(infantryFireT, iCols, iRows); + tankFire = new Sprites(tankFireT, sCols, sRows); + explosion = new Sprites(explosionT, eCols, eRows); + infantryFireSnd = infantryFireS; + tankFireSnd = tankFireS; + tankFireSndLong = tankFireLongS; + explosionSnd = explosionS; + explosionSndLong = explosionLongS; + + reset(); + } + + public static void reset() + { + infantryFireSndLongId = -1; + tankFireSndLongId = -1; + explosionSndLongId = -1; + } + + public static void free() + { + tankFire.dispose(); + explosion.dispose(); + + tankFireSnd.dispose(); + tankFireSndLong.dispose(); + explosionSnd.dispose(); + explosionSndLong.dispose(); + } + + public static void infantryFireSndPlay(float volume) + { + if (infantryFireSndLongId == -1) + infantryFireSndLongId = infantryFireSnd.play(volume); + } + + public static void tankFireSndPlay(float volume) + { + if (tankFireSndLongId == -1) + tankFireSndLongId = tankFireSndLong.play(volume); + else + tankFireSnd.play(volume); + } + + public static void explosionSndPlay(float volume) + { + if (explosionSndLongId == -1) + explosionSndLongId = explosionSndLong.play(volume); + else + explosionSnd.play(volume); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/InfantryFireAnimation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/InfantryFireAnimation.java new file mode 100644 index 0000000..b478a2b --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/InfantryFireAnimation.java @@ -0,0 +1,222 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import java.util.Random; + +import com.badlogic.gdx.utils.Disposable; +import com.badlogic.gdx.utils.Pool; + +import com.badlogic.gdx.audio.Sound; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Drawable; +import ch.asynk.creepingarmor.engine.gfx.Animation; + +public class InfantryFireAnimation implements Disposable, Animation, Pool.Poolable +{ + class Shot + { + public TextureRegion fireRegion; + public float fire_a; + public float fire_x; + public float fire_y; + public float fire_w; + public float fire_dx; + public float fire_dy; + public float fire_dw; + + public boolean fired; + public boolean hit; + public boolean completed; + + public float fire_time; + public float hit_time; + public float end_time; + + public int hit_frame; + + public Shot(TextureRegion region) + { + this.fireRegion = region; + } + + public void set(float delay, float x0, float y0, float x1, float y1, float w, float a) + { + float dx = (x1 - x0); + float dy = (y1 - y0); + + // timing + float fire_duration = ((FireAnimation.random.nextFloat() * TIME_SCATTERING) + (w / SHOT_SPEED)); + float hit_duration = (FireAnimation.infantryFire.rows * HIT_FRAME_DURATION); + + this.fired = false; + this.fire_time = delay; + this.hit_time = (this.fire_time + fire_duration); + this.end_time = (this.hit_time + hit_duration); + + // fire vars + this.fire_a = a; + this.fire_x = x0; + this.fire_y = y0; + this.fire_w = 0; + this.fire_dx = (dx / fire_duration); + this.fire_dy = (dy / fire_duration); + this.fire_dw = (w / fire_duration); + this.hit_frame = 0; + } + + public boolean animate(float delta) + { + if (!fired && (elapsed < fire_time)) + return false; + + if (!fired) { + fired = true; + FireAnimation.infantryFireSndPlay(volume); + } + + if (!hit && (elapsed < hit_time)) { + fire_w += (fire_dw * delta); + fire_x += (fire_dx * delta); + fire_y += (fire_dy * delta); + fireRegion.setRegionWidth((int) fire_w); + return false; + } + + if (!hit) + hit = true; + + if (elapsed < end_time) { + int frame = (int) ((elapsed - hit_time) / HIT_FRAME_DURATION); + if (frame != hit_frame) { + hit_frame = frame; + fireRegion.setRegion(FireAnimation.infantryFire.frames[hit_frame]); + fireRegion.setRegionWidth((int) fire_w); + } + return false; + } + + completed = true; + return true; + } + + public void draw(Batch batch) + { + if (fired && !completed) + batch.draw(fireRegion, fire_x, fire_y, 0, 0, fireRegion.getRegionWidth(), fireRegion.getRegionHeight(), 1f, 1f, fire_a); + } + } + + private static final int SHOT_COUNT = 19; + private static final float SHOT_DELAY = (1.6f / SHOT_COUNT); + private static final float SHOT_SCATTERING = 40f; + private static final float TIME_SCATTERING = 0.6f; + private static final float START_DELAY = 0.8f; + private static final float SHOT_SPEED = 1000f; + private static final float HIT_FRAME_DURATION = 0.05f; + + private Shot[] shots; + + private float elapsed; + + private float volume; + + private static final Pool fireAnimationPool = new Pool() { + @Override + protected InfantryFireAnimation newObject() { + return new InfantryFireAnimation(); + } + }; + + public static InfantryFireAnimation get(float volume, float x0, float y0, float x1, float y1, float halfWidth) + { + InfantryFireAnimation a = fireAnimationPool.obtain(); + a.set(volume, x0, y0, x1, y1, halfWidth); + return a; + } + + public InfantryFireAnimation() + { + this.shots = new Shot[SHOT_COUNT]; + for (int i = 0; i < shots.length; i++) + shots[i] = new Shot(new TextureRegion(FireAnimation.infantryFire.frames[0])); + } + + private void set(float volume, float x0, float y0, float x1, float y1, float halfWidth) + { + this.volume = volume; + this.elapsed = 0f; + + float delay = START_DELAY + (FireAnimation.random.nextFloat() * TIME_SCATTERING); + + y0 -= (FireAnimation.infantryFire.height / 2.0f); + double r = Math.atan2((y0 - y1), (x0 - x1)); + x0 -= ((float) (Math.cos(r) * halfWidth)); + y0 -= ((float) (Math.sin(r) * halfWidth)); + + float dx = (x1 - x0); + float dy = (y1 - y0); + float w = (float) Math.sqrt((dx * dx) + (dy * dy)); + double dr = (Math.atan2(halfWidth, w) / 2f); + + double a = (r + (dr / 2f)); + double da = (dr / (float) SHOT_COUNT); + + for (Shot shot : shots) { + float x = (float) (x0 - (Math.cos(a) * w)); + float y = (float) (y0 - (Math.sin(a) * w)); + + shot.set(delay, x0, y0, x, y, w, (float) Math.toDegrees(a)); + + delay += SHOT_DELAY; + a -= 2 * (da * FireAnimation.random.nextFloat()); + } + } + + @Override + public void reset() + { + } + + @Override + public void dispose() + { + fireAnimationPool.free(this); + } + + @Override + public boolean animate(float delta) + { + elapsed += delta; + + boolean completed = true; + for (Shot shot : shots) + completed &= shot.animate(delta); + + return completed; + } + + @Override + public void draw(Batch batch) + { + for (Shot shot : shots) + shot.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + // debugShapes.end(); + // debugShapes.begin(ShapeRenderer.ShapeType.Line); + // debugShapes.identity(); + // debugShapes.translate(fire_x, fire_y, 0); + // debugShapes.rotate(0, 0, 1, fire_a); + // debugShapes.translate(-fire_x, -fire_y, 0); + // debugShapes.rect(fire_x, fire_y, fire_w, FireAnimation.infantryFire.height); + // debugShapes.end(); + // debugShapes.begin(ShapeRenderer.ShapeType.Line); + // debugShapes.identity(); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/MoveToAnimation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/MoveToAnimation.java new file mode 100644 index 0000000..a1d548c --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/MoveToAnimation.java @@ -0,0 +1,126 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.utils.Pool; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Moveable; + +public class MoveToAnimation extends TimedAnimation +{ + public interface MoveToAnimationCb { + void moveToAnimationLeave(Moveable moveable, float x, float y, float r); + void moveToAnimationEnter(Moveable moveable, float x, float y, float r); + void moveToAnimationDone(Moveable moveable, float x, float y, float r); + } + + private Moveable moveable; + private float fromX; + private float fromY; + private float fromR; + private float toX; + private float toY; + private float toR; + private float rDelta; + private boolean notified; + private MoveToAnimationCb cb; + + private static final Pool moveToAnimationPool = new Pool() { + @Override + protected MoveToAnimation newObject() { + return new MoveToAnimation(); + } + }; + + public static MoveToAnimation get(Moveable moveable, Vector3 v, float duration) + { + return get(moveable, v.x, v.y, v.z, duration); + } + + public static MoveToAnimation get(Moveable moveable, Vector3 v, float duration, MoveToAnimationCb cb) + { + return get(moveable, v.x, v.y, v.z, duration, cb); + } + + public static MoveToAnimation get(Moveable moveable, float x, float y, float r, float duration) + { + return get(moveable, x, y, r, duration, null); + } + + public static MoveToAnimation get(Moveable moveable, float x, float y, float r, float duration, MoveToAnimationCb cb) + { + MoveToAnimation a = moveToAnimationPool.obtain(); + + a.moveable = moveable; + a.toX = x; + a.toY = y; + a.toR = r; + a.duration = duration; + a.cb = cb; + a.rDelta = 0; + a.notified = false; + + return a; + } + + @Override + public void dispose() + { + moveToAnimationPool.free(this); + } + + @Override + protected void begin() + { + fromX = moveable.getX(); + fromY = moveable.getY(); + fromR = moveable.getRotation(); + notified = ((fromX == toX) && (fromY == toY)); + + if (Math.abs(toR - fromR) <= 180.f) + rDelta = (toR - fromR); + else { + if (toR > fromR) + rDelta = (toR - 360 - fromR); + else + rDelta = (toR + 360 - fromR); + } + } + + @Override + protected void end() + { + if (cb != null) + cb.moveToAnimationDone(moveable, (toX + (moveable.getWidth() / 2)), (toY + (moveable.getHeight() / 2)), toR); + dispose(); + } + + @Override + protected void update(float percent) + { + if ((cb != null) && !notified && (percent >= 0.5)) { + float dw = (moveable.getWidth() / 2); + float dh = (moveable.getHeight() / 2); + cb.moveToAnimationLeave(moveable, (fromX + dw), (fromY + dh), fromR); + cb.moveToAnimationEnter(moveable, (toX + dw), (toY + dh), toR); + notified = true; + } + if (percent == 1f) + moveable.setPosition(toX, toY, (int) toR); + else + moveable.setPosition(fromX + ((toX - fromX) * percent), fromY + ((toY - fromY) * percent), (fromR + (rDelta * percent))); + } + + @Override + public void draw(Batch batch) + { + moveable.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + moveable.drawDebug(debugShapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/PromoteAnimation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/PromoteAnimation.java new file mode 100644 index 0000000..1d8d98e --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/PromoteAnimation.java @@ -0,0 +1,98 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import java.lang.Math; + +import com.badlogic.gdx.audio.Sound; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Drawable; +import ch.asynk.creepingarmor.engine.gfx.Animation; + +public class PromoteAnimation implements Animation, Drawable +{ + private static PromoteAnimation instance = new PromoteAnimation(); + + private static final float DURATION = 0.3f; + private static final float MAX_SCALE = 2f; + + private static Sound usSound; + private static Sound geSound; + private static Sound snd; + private static TextureRegion region; + + private float x0; + private float y0; + private float x; + private float y; + private float scale; + private float step; + private float volume; + private float elapsed; + + public static void init(TextureAtlas atlas, Sound usSnd, Sound geSnd) + { + region = atlas.findRegion("stars"); + usSound = usSnd; + geSound = geSnd; + } + + public static void free() + { + } + + protected void PromoteAnimation() + { + } + + public static PromoteAnimation get(boolean us, float x, float y, float v) + { + x = (x - (region.getRegionWidth() / 2.0f)); + y = (y - (region.getRegionHeight() / 2.0f)); + + instance.volume = v; + instance.x0 = x; + instance.y0 = y; + instance.scale = 0f; + instance.elapsed = 0f; + snd = (us ? usSound : geSound); + + return instance; + } + + @Override + public void dispose() + { + } + + @Override + public boolean animate(float delta) + { + elapsed += delta; + if (elapsed >= DURATION) { + snd.play(volume); + return true; + } + + float s = MAX_SCALE * (float) Math.sin(Math.PI / DURATION * elapsed); + scale = 1f + s; + x = x0 - ((region.getRegionWidth() * scale) / 4f); + y = y0 - ((region.getRegionHeight() * scale) / 4f); + + return false; + } + + @Override + public void draw(Batch batch) + { + batch.draw(region, x, y, 0, 0, region.getRegionWidth(), region.getRegionHeight(), scale, scale, 0f); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + debugShapes.rect(x, y, region.getRegionWidth(), region.getRegionHeight()); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/RunnableAnimation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/RunnableAnimation.java new file mode 100644 index 0000000..6c09904 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/RunnableAnimation.java @@ -0,0 +1,67 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import com.badlogic.gdx.utils.Pool; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Moveable; +import ch.asynk.creepingarmor.engine.gfx.Animation; + +public class RunnableAnimation implements Animation, Pool.Poolable +{ + private Runnable runnable; + private Moveable moveable; + private boolean ran; + + private static final Pool runnableAnimationPool = new Pool() { + @Override + protected RunnableAnimation newObject() { + return new RunnableAnimation(); + } + }; + + public static RunnableAnimation get(Moveable moveable, Runnable runnable) + { + RunnableAnimation a = runnableAnimationPool.obtain(); + a.runnable = runnable; + a.moveable = moveable; + return a; + } + + @Override + public void reset() + { + ran = false; + } + + @Override + public void dispose() + { + runnableAnimationPool.free(this); + } + + @Override + public boolean animate(float delta) + { + if (ran) return true; + + runnable.run(); + runnable = null; + ran = true; + dispose(); + + return true; + } + + @Override + public void draw(Batch batch) + { + moveable.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + moveable.drawDebug(debugShapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/SoundAnimation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/SoundAnimation.java new file mode 100644 index 0000000..9c6a289 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/SoundAnimation.java @@ -0,0 +1,83 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import com.badlogic.gdx.utils.Pool; +import com.badlogic.gdx.audio.Sound; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +public class SoundAnimation extends TimedAnimation +{ + public enum Action + { + FADE_IN, + FADE_OUT + }; + + private Sound sound; + private long soundId; + private Action action; + private float volume; + + private static final Pool soundAnimationPool = new Pool() { + @Override + protected SoundAnimation newObject() { + return new SoundAnimation(); + } + }; + + public static SoundAnimation get(Action action, Sound sound, long soundId, float volume, float duration) + { + SoundAnimation a = soundAnimationPool.obtain(); + + a.action = action; + a.sound = sound; + a.soundId = soundId; + a.volume = volume; + a.duration = duration; + + return a; + } + + @Override + public void dispose() + { + soundAnimationPool.free(this); + } + + @Override + protected void begin() + { + } + + @Override + protected void end() + { + dispose(); + } + + @Override + protected void update(float percent) + { + float v; + switch(action) { + case FADE_IN: + v = ( volume * percent); + sound.setVolume(soundId, v); + break; + case FADE_OUT: + v = (volume - ( volume * percent)); + sound.setVolume(soundId, v); + break; + } + } + + @Override + public void draw(Batch batch) + { + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/SpriteAnimation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/SpriteAnimation.java new file mode 100644 index 0000000..377cf6b --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/SpriteAnimation.java @@ -0,0 +1,76 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import java.util.Random; + +import com.badlogic.gdx.utils.Disposable; + +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Drawable; +import ch.asynk.creepingarmor.engine.gfx.Animation; + +public class SpriteAnimation implements Disposable, Animation +{ + private static Random random = new Random(); + private Sprites sprites; + private float duration; + private float frameDuration; + private float elapsed; + private float x0; + private float y0; + private float x1; + private float y1; + private int randFreq; + + public SpriteAnimation(Texture texture, int cols, int rows, int randFreq) + { + this.sprites = new Sprites(texture, cols, rows); + this.randFreq = randFreq; + } + + @Override + public void dispose() + { + sprites.dispose(); + } + + public void init(float duration, float x, float y) + { + this.duration = duration; + this.frameDuration = (duration / (float) sprites.frames.length); + this.x0 = x - (sprites.width / 2f); + this.y0 = y - (sprites.height / 2f); + this.elapsed = 0f; + randPos(); + } + + private void randPos() + { + this.x1 = this.x0 + (random.nextInt(sprites.width) - (sprites.width / 2)); + this.y1 = this.y0 + (random.nextInt(sprites.height) - (sprites.height / 2)); + } + + @Override + public boolean animate(float delta) + { + elapsed += delta; + return (elapsed >= duration); + } + + @Override + public void draw(Batch batch) + { + int n = (((int)(elapsed / frameDuration)) % sprites.frames.length); + if ((n > 0) && (n % randFreq) == 0) + randPos(); + batch.draw(sprites.frames[n], x1, y1); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/Sprites.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/Sprites.java new file mode 100644 index 0000000..407b8a5 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/Sprites.java @@ -0,0 +1,38 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import com.badlogic.gdx.utils.Disposable; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.TextureRegion; + +public class Sprites implements Disposable +{ + public Texture texture; + public TextureRegion[] frames; + public final int width; + public final int height; + public final int cols; + public final int rows; + + public Sprites(Texture texture, int cols, int rows) + { + this.cols = cols; + this.rows = rows; + this.width = (texture.getWidth() / cols); + this.height = (texture.getHeight() / rows); + this.texture = texture; + TextureRegion[][] tmp = TextureRegion.split(texture, width, height); + frames = new TextureRegion[cols * rows]; + int idx = 0; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + frames[idx++] = tmp[i][j]; + } + } + } + + @Override + public void dispose() + { + texture.dispose(); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/TankFireAnimation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/TankFireAnimation.java new file mode 100644 index 0000000..55ee435 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/TankFireAnimation.java @@ -0,0 +1,196 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import java.util.Random; + +import com.badlogic.gdx.utils.Disposable; +import com.badlogic.gdx.utils.Pool; + +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Drawable; +import ch.asynk.creepingarmor.engine.gfx.Animation; + +public class TankFireAnimation implements Disposable, Animation, Pool.Poolable +{ + private static final float SHOT_SCATTERING = 60f; + private static final float TIME_SCATTERING = 0.6f; + private static final float START_DELAY = 0.8f; + private static final float SHOT_SPEED = 900f; + private static final float EXPLOSION_FRAME_DURATION = 0.07f; + + private TextureRegion fireRegion; + private float fire_a; + private float fire_x; + private float fire_y; + private float fire_w; + private float fire_dx; + private float fire_dy; + private float fire_dw; + + private float smoke_df; + private int smoke_frame; + + private float explosion_x; + private float explosion_y; + private float explosion_df; + private int explosion_frame; + + private boolean fired; + private boolean hit; + private float elapsed; + private float fire_time; + private float hit_time; + private float end_time; + + private float volume; + + private static final Pool fireAnimationPool = new Pool() { + @Override + protected TankFireAnimation newObject() { + return new TankFireAnimation(); + } + }; + + public static TankFireAnimation get(float volume, float x0, float y0, float x1, float y1, float halfWidth) + { + TankFireAnimation a = fireAnimationPool.obtain(); + a.set(volume, x0, y0, x1, y1, halfWidth); + return a; + } + + public TankFireAnimation() + { + this.fireRegion = new TextureRegion(FireAnimation.tankFire.frames[0]); + } + + private void set(float volume, float x0, float y0, float x1, float y1, float halfWidth) + { + this.fired = false; + this.hit = false; + this.volume = volume; + + // fire geometry + y0 -= (FireAnimation.tankFire.height / 2.0f); + x1 += ((SHOT_SCATTERING * FireAnimation.random.nextFloat()) - (SHOT_SCATTERING / 2f)); + y1 += ((SHOT_SCATTERING * FireAnimation.random.nextFloat()) - (SHOT_SCATTERING / 2f)); + + double r = Math.atan2((y0 - y1), (x0 - x1)); + float xadj = (float) (Math.cos(r) * halfWidth); + float yadj = (float) (Math.sin(r) * halfWidth); + x0 -= xadj; + y0 -= yadj; + + float a = (float) Math.toDegrees(r); + float dx = (x1 - x0); + float dy = (y1 - y0); + float w = (float) Math.sqrt((dx * dx) + (dy * dy)); + + // timing + float delay = START_DELAY + (FireAnimation.random.nextFloat() * TIME_SCATTERING); + float fire_duration = ((FireAnimation.random.nextFloat() * TIME_SCATTERING) + (w / SHOT_SPEED)); + float explosion_duration = (FireAnimation.explosion.cols * EXPLOSION_FRAME_DURATION); + + this.elapsed = 0f; + this.fire_time = delay; + this.hit_time = (fire_time + fire_duration); + this.end_time = (hit_time + explosion_duration); + + // fire vars + this.fire_a = a; + this.fire_x = x0; + this.fire_y = y0; + this.fire_w = 0; + this.fire_dx = (dx / fire_duration); + this.fire_dy = (dy / fire_duration); + this.fire_dw = (w / fire_duration); + + // smoke var + this.smoke_df = (FireAnimation.tankFire.rows / explosion_duration); + this.smoke_frame = 0; + + // explosion vars + this.explosion_x = (x1 - (FireAnimation.explosion.width / 2.0f)); + this.explosion_y = (y1 - (FireAnimation.explosion.height / 2.0f)); + this.explosion_df = (FireAnimation.explosion.cols / explosion_duration); + this.explosion_frame = (FireAnimation.random.nextInt(FireAnimation.explosion.rows) * FireAnimation.explosion.cols); + } + + @Override + public void reset() + { + } + + @Override + public void dispose() + { + fireAnimationPool.free(this); + } + + @Override + public boolean animate(float delta) + { + elapsed += delta; + + if (!fired && (elapsed < fire_time)) + return false; + + if (!fired) { + fired = true; + FireAnimation.tankFireSndPlay(volume); + } + + if (!hit && (elapsed < hit_time)) { + fire_w += (fire_dw * delta); + fire_x += (fire_dx * delta); + fire_y += (fire_dy * delta); + fireRegion.setRegionWidth((int) fire_w); + return false; + } + + if (!hit) { + hit = true; + FireAnimation.explosionSndPlay(volume); + } + + if (elapsed < end_time) { + int frame = (int) ((elapsed - hit_time) * smoke_df); + if (frame != smoke_frame) { + smoke_frame = frame; + fireRegion.setRegion(FireAnimation.tankFire.frames[smoke_frame]); + fireRegion.setRegionWidth((int) fire_w); + } + return false; + } + + return true; + } + + @Override + public void draw(Batch batch) + { + if (fired) + batch.draw(fireRegion, fire_x, fire_y, 0, 0, fireRegion.getRegionWidth(), fireRegion.getRegionHeight(), 1f, 1f, fire_a); + + if (hit) { + int frame = (explosion_frame + (int) ((elapsed - hit_time) * explosion_df)); + batch.draw(FireAnimation.explosion.frames[frame], explosion_x, explosion_y); + } + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + debugShapes.end(); + debugShapes.begin(ShapeRenderer.ShapeType.Line); + debugShapes.identity(); + debugShapes.translate(fire_x, fire_y, 0); + debugShapes.rotate(0, 0, 1, fire_a); + debugShapes.translate(-fire_x, -fire_y, 0); + debugShapes.rect(fire_x, fire_y, fire_w, FireAnimation.tankFire.height); + debugShapes.end(); + debugShapes.begin(ShapeRenderer.ShapeType.Line); + debugShapes.identity(); + } +} diff --git a/core/src/ch/asynk/creepingarmor/engine/gfx/animations/TimedAnimation.java b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/TimedAnimation.java new file mode 100644 index 0000000..376b03e --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/engine/gfx/animations/TimedAnimation.java @@ -0,0 +1,48 @@ +package ch.asynk.creepingarmor.engine.gfx.animations; + +import com.badlogic.gdx.utils.Pool; + +import ch.asynk.creepingarmor.engine.gfx.Animation; + +public abstract class TimedAnimation implements Animation, Pool.Poolable +{ + private float time; + private boolean began; + private boolean completed; + protected float duration; + + abstract protected void begin(); + abstract protected void end(); + abstract protected void update(float percent); + + @Override + public void reset() + { + time = 0f; + began = false; + completed = false; + } + + @Override + public boolean animate(float delta) + { + if (completed) return true; + + if (!began) { + begin(); + began = true; + } + + time += delta; + completed = (time >= duration); + + if (!completed) { + update(time / duration); + return false; + } + + update(1); + end(); + return true; + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/Army.java b/core/src/ch/asynk/creepingarmor/game/Army.java new file mode 100644 index 0000000..dbf5656 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Army.java @@ -0,0 +1,30 @@ +package ch.asynk.creepingarmor.game; + +import ch.asynk.creepingarmor.engine.Faction; + +public enum Army implements Faction +{ + NONE("None"), + GE("German"), + US("US"), + USSR("Soviet"), + EN("English"); + + private String s; + + Army(String s) { + this.s = s; + } + + @Override + public String toString() + { + return s; + } + + @Override + public boolean isEnemy(Faction other) + { + return (this != other); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/Battle.java b/core/src/ch/asynk/creepingarmor/game/Battle.java new file mode 100644 index 0000000..9a4a0c3 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Battle.java @@ -0,0 +1,40 @@ +package ch.asynk.creepingarmor.game; + +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.game.battles.Factory.MapType; +import ch.asynk.creepingarmor.ui.Position; + +public interface Battle +{ + public void init(); + + public String getName(); + + public String getDescription(); + + public Player getPlayer(); + + public Player opponent(Player player); + + public MapType getMapType(); + + public Map getMap(); + + public Player checkVictory(Ctrl ctrl); + + public boolean getReinforcement(Ctrl ctrl, Map map); + + public Zone getEntryZone(Unit unit); + + public Zone getExitZone(Unit unit); + + public Position getHudPosition(Player player); + + public State.StateType getState(Player player); + + public boolean deploymentDone(Player player); + + public void setup(Ctrl ctrl, Map map); +} diff --git a/core/src/ch/asynk/creepingarmor/game/Command.java b/core/src/ch/asynk/creepingarmor/game/Command.java new file mode 100644 index 0000000..34af71b --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Command.java @@ -0,0 +1,225 @@ +package ch.asynk.creepingarmor.game; + +import java.util.List; + +import com.badlogic.gdx.utils.Pool; +import com.badlogic.gdx.utils.Json; +import com.badlogic.gdx.utils.JsonValue; + +import ch.asynk.creepingarmor.engine.Order; +import ch.asynk.creepingarmor.engine.Move; +import ch.asynk.creepingarmor.engine.Pawn; +import ch.asynk.creepingarmor.engine.Tile; + +public class Command extends Order +{ + public enum CommandType implements Order.OrderType + { + NONE, + MOVE, + ENGAGE, + PROMOTE, + END_OF_TURN; + } + + private static final Pool commandPool = new Pool() + { + @Override + protected Command newObject() { + return new Command(); + } + }; + + public static void clearPool() + { + commandPool.clear(); + } + + public static Command get(Player player) + { + Command c = commandPool.obtain(); + c.player = player; + c.ap = player.getAp(); + c.turn = player.getCurrentTurn(); + return c; + } + + public CommandType type; + public Player player; + public int ap; + public int turn; + public Unit unit; + public Unit.UnitId unitId; + public Unit.UnitType unitType; + public Tile unitTile; + public Move move; + public Engagement engagement; + + private Command() + { + reset(); + } + + @Override + public void dispose() + { + commandPool.free(this); + } + + @Override + public void reset() + { + this.type = CommandType.NONE; + this.player = null; + this.unit = null; + if (this.move != null) { + this.move.dispose(); + this.move = null; + } + if (this.engagement != null) { + this.engagement.dispose(); + this.engagement = null; + } + } + + @Override + public int compareTo(Pawn pawn) + { + if (pawn == unit) + return 0; + return 1; + } + + @Override + public boolean isA(OrderType type) + { + return (type == this.type); + } + + @Override + public String toString() + { + return String.format("%s : %s", type, unit.id); + } + + public void setMove(Unit unit, Move move) + { + this.type = CommandType.MOVE; + this.move = move; + setUnit(unit); + } + + public void setPromote(Unit unit) + { + this.type = CommandType.PROMOTE; + setUnit(unit); + } + + public void setEngage(Unit unit, Unit target) + { + this.type = CommandType.ENGAGE; + this.engagement = Engagement.get(unit, target); + setUnit(unit); + } + + private void setUnit(Unit unit) + { + this.unit = unit; + this.unitId = unit.id; + this.unitType = unit.type; + this.unitTile = unit.getTile(); + } + + @Override + public void write(Json json) + { + json.writeValue("type", type); + json.writeObjectStart("player"); + json.writeValue("army", player.getName()); + json.writeValue("turn", turn); + json.writeValue("aps", ap); + json.writeObjectEnd(); + json.writeObjectStart("unit"); + json.writeValue("id", unitId); + json.writeValue("type", unitType); + json.writeValue("ace", unit.ace); + writeTile(json, "tile", unitTile); + json.writeObjectEnd(); + if (move != null) writeMove(json, "move", move); + if (engagement != null) writeEngagement(json, "engagement", engagement); + } + + private void writeMove(Json json, String key, Move m) + { + json.writeObjectStart(key); + json.writeValue("type", move.type); + writeTile(json, "from", move.from); + writeTile(json, "to", move.to); + json.writeValue("orientation", move.orientation.r()); + writeTiles(json, "path", move.tiles); + json.writeObjectEnd(); + } + + private void writeEngagement(Json json, String key, Engagement e) + { + json.writeObjectStart(key); + writeUnit(json, "attacker", e.attacker); + writeUnit(json, "defender", e.defender); + writeUnits(json, "assists", e.assists); + json.writeObjectStart("dice"); + json.writeValue("d1", e.d1); + json.writeValue("d2", e.d2); + json.writeValue("d3", e.d3); + json.writeValue("d4", e.d4); + json.writeObjectEnd(); + json.writeObjectStart("results"); + json.writeValue("success", e.success); + json.writeValue("attackSum", e.attackSum); + json.writeValue("defenseSum", e.defenseSum); + json.writeObjectEnd(); + json.writeObjectEnd(); + } + + private void writeUnit(Json json, String key, Unit u) + { + if (key != null) json.writeObjectStart(key); + else json.writeObjectStart(); + json.writeValue("id", u.id); + json.writeValue("ace", u.ace); + json.writeValue("army", u.getArmy()); + writeTile(json, "tile", u.getTile()); + json.writeObjectEnd(); + } + + private void writeUnits(Json json, String key, List units) + { + json.writeArrayStart(key); + for (Unit u : units) + writeUnit(json, null, u); + json.writeArrayEnd(); + } + + private void writeTile(Json json, String key, Tile t) + { + if (t == null) return; + if (key != null) json.writeObjectStart(key); + else json.writeObjectStart(); + json.writeValue("col", t.getCol()); + json.writeValue("row", t.getRow()); + json.writeObjectEnd(); + } + + private void writeTiles(Json json, String key, List tiles) + { + json.writeArrayStart(key); + for (Tile t : tiles) + writeTile(json, null, t); + json.writeArrayEnd(); + } + + @Override + public void read(Json json, JsonValue jsonMap) + { + // FIXME Command.read(Json, JsonValue); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/Config.java b/core/src/ch/asynk/creepingarmor/game/Config.java new file mode 100644 index 0000000..88a7fe2 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Config.java @@ -0,0 +1,76 @@ +package ch.asynk.creepingarmor.game; + +public class Config +{ + public enum Graphics { + MINE("mine", 0), + ORIGINAL("original", 1); + public String s; + public int i; + Graphics(String s, int i) + { + this.s = s; + this.i = i; + } + public Graphics next() + { + if (this == ORIGINAL) + return MINE; + return ORIGINAL; + } + }; + + public enum GameMode + { + SOLO("Solo", 0), + PVE("Player vs AI", 1), + PVP("Player vs Player", 2); + public String s; + public int i; + GameMode(String s, int i) + { + this.s = s; + this.i = i; + } + public GameMode next() + { + if (this == SOLO) + return PVE; + if(this == PVE) + return PVP; + return SOLO; + } + }; + + public GameMode gameMode; + public boolean showMoves; + public boolean showTargets; + public boolean showMoveAssists; + public boolean canCancel; + public boolean mustValidate; + public boolean showEnemyPossibilities; + public boolean debug; + public Battle battle; + public float fxVolume; + public Graphics graphics; + + public Config() + { + this.gameMode = GameMode.SOLO; + this.debug = false; + this.showMoves = true; + this.showTargets = true; + this.showMoveAssists = true; + this.canCancel = false; + this.mustValidate = false; + this.showEnemyPossibilities = false; + this.graphics = Graphics.MINE; + this.battle = null; + this.fxVolume = 1f; + } + + public boolean gameModeImplemented() + { + return (gameMode == GameMode.SOLO); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/Ctrl.java b/core/src/ch/asynk/creepingarmor/game/Ctrl.java new file mode 100644 index 0000000..f4696f1 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Ctrl.java @@ -0,0 +1,336 @@ +package ch.asynk.creepingarmor.game; + +import com.badlogic.gdx.utils.Disposable; + +import com.badlogic.gdx.math.Vector3; + +import ch.asynk.creepingarmor.CreepingArmor; +import ch.asynk.creepingarmor.ui.Position; +import ch.asynk.creepingarmor.game.State.StateType; +import ch.asynk.creepingarmor.game.states.StateSelect; +import ch.asynk.creepingarmor.game.states.StateMove; +import ch.asynk.creepingarmor.game.states.StateRotate; +import ch.asynk.creepingarmor.game.states.StatePromote; +import ch.asynk.creepingarmor.game.states.StateEngage; +import ch.asynk.creepingarmor.game.states.StateBreak; +import ch.asynk.creepingarmor.game.states.StateAnimation; +import ch.asynk.creepingarmor.game.states.StateReinforcement; +import ch.asynk.creepingarmor.game.states.StateDeployment; +import ch.asynk.creepingarmor.game.states.StateWithdraw; + +public class Ctrl implements Disposable +{ + private final CreepingArmor game; + public final Battle battle; + + public Map map; + public Hud hud; + public Config cfg; + public Player player; + public Player opponent; + public boolean blockMap; + public boolean blockHud; + + public Vector3 mapTouch = new Vector3(); + public Vector3 hudTouch = new Vector3(); + + private State selectState; + private State pathState; + private State rotateState; + private State promoteState; + private State engageState; + private State breakState; + private State animationState; + private State reinforcementState; + private State deploymentState; + private State withdrawState; + + private int animationCount = 0; + + private State state; + private StateType stateType; + private StateType stateAfterAnimation; + + public Ctrl(final CreepingArmor game, final Battle battle) + { + this.game = game; + this.battle = battle; + this.cfg = game.config; + game.ctrl = this; + + battle.init(); + + this.map = battle.getMap(); + battle.setup(this, map); + this.map.init(); + this.player = battle.getPlayer(); + this.opponent = battle.opponent(player); + + this.selectState = new StateSelect(this, map); + this.pathState = new StateMove(); + this.rotateState = new StateRotate(); + this.promoteState = new StatePromote(); + this.engageState = new StateEngage(); + this.breakState = new StateBreak(); + this.animationState = new StateAnimation(); + this.reinforcementState = new StateReinforcement(); + this.deploymentState = new StateDeployment(); + this.withdrawState = new StateWithdraw(); + + this.state = selectState; + this.stateType = StateType.DONE; + + this.hud = new Hud(this, game); + this.blockMap = false; + this.blockHud = false; + + hud.notify(battle.toString(), 2, Position.MIDDLE_CENTER, false); + startPlayerTurn(); + } + + @Override + public void dispose() + { + hud.dispose(); + map.dispose(); + } + + public Player getPlayer(Army army) + { + return (player.is(army) ? player : opponent); + } + + public boolean isInAction() + { + return (state != selectState); + } + + public void animationsOver() + { + if (hud.dialogActive()) + return; + if (stateType == StateType.ANIMATION) + leaveAnimationState(); + } + + private void leaveAnimationState() + { + + StateType tmp = stateAfterAnimation; + stateAfterAnimation = StateType.DONE; + setState(tmp); + } + + private void startPlayerTurn() + { + player.turnStart(); + // hud.notify(player.getName() + "'s turn", 2, Position.MIDDLE_CENTER, true); + if (battle.getReinforcement(this, map)) + hud.notify("You have reinforcement", 2, Position.MIDDLE_CENTER, true); + hud.update(); + setState(battle.getState(player)); + } + + private void endPlayerTurn() + { + player.turnEnd(); + Player winner = battle.checkVictory(this); + if (winner != null) + hud.victory(winner, ((winner == player) ? opponent : player)); + } + + private StateType actionAborted() + { + hud.notify("Action canceled"); + StateType nextState = this.state.abort(); + + if (nextState == StateType.ABORT) + nextState = battle.getState(player); + + return nextState; + } + + private void turnDone() + { + map.turnDone(); + endPlayerTurn(); + player = battle.getPlayer(); + opponent = battle.opponent(player); + startPlayerTurn(); + } + + private StateType actionDone() + { + StateType nextState = this.state.execute(); + + if (nextState == StateType.DONE) { + map.actionDone(); + if (map.activatedUnits.size() > 0) { + CreepingArmor.debug("Ctrl", "burn down 1AP"); + hud.notify("1 Action Point burnt", 0.6f, Position.BOTTOM_CENTER, false); + player.burnDownOneAp(); + hud.update(); + } + if (player.apExhausted()) + hud.notifyNoMoreAP(); + } + + if (nextState == StateType.DONE) + nextState = battle.getState(player); + + return nextState; + } + + private StateType deploymentDone() + { + map.actionDone(); + return this.state.execute(); + } + + public void setState(StateType nextState) + { + if (nextState == StateType.ABORT) + nextState = actionAborted(); + else if (nextState == StateType.DONE) { + if (stateType == StateType.DEPLOYMENT) + nextState = deploymentDone(); + else + nextState = actionDone(); + } + + if (stateType == StateType.ANIMATION) { + this.blockMap = hud.dialogActive(); + } + hud.playerInfo.blockEndOfTurn(nextState != StateType.SELECT); + + this.state.leave(nextState); + + CreepingArmor.debug("Ctrl", String.format(" %s -> %s : %s", stateType, nextState, player)); + + switch(nextState) { + case SELECT: + this.state = selectState; + break; + case MOVE: + this.state = pathState; + break; + case ROTATE: + this.state = rotateState; + break; + case PROMOTE: + this.state = promoteState; + break; + case ENGAGE: + this.state = engageState; + break; + case BREAK: + this.state = breakState; + break; + case WITHDRAW: + this.state = withdrawState; + break; + case ANIMATION: + this.blockMap = true; + this.state = animationState; + break; + case REINFORCEMENT: + this.state = reinforcementState; + break; + case DEPLOYMENT: + this.state = deploymentState; + break; + default: + break; + } + + StateType tmp = stateType; + stateType = nextState; + + this.state.enter(tmp); + + } + + public void touchDown() + { + if (!blockHud && hud.touchDown(hudTouch.x, hudTouch.y)) + return; + + if (!blockMap && state.downInMap(mapTouch.x, mapTouch.y)) + state.touchDown(); + } + + public void touchUp() + { + if (!blockHud && hud.touchUp(hudTouch.x, hudTouch.y)) + return; + + if (!blockMap && state.upInMap(mapTouch.x, mapTouch.y)) + state.touchUp(); + } + + public void stateTouchUp() + { + state.downInMap(-1, -1); + state.upInMap(-1, -1); + state.touchUp(); + } + + public boolean isInAnimation() + { + return (this.stateType == StateType.ANIMATION); + } + + public void setAfterAnimationState(StateType after) + { + stateAfterAnimation = after; + } + + public boolean checkDeploymentDone() + { + boolean done = battle.deploymentDone(player); + if (done) + hud.askEndDeployment(); + return done; + } + + public void reinforcementHit() + { + if (this.stateType == StateType.SELECT) + setState(StateType.REINFORCEMENT); + else if (this.stateType == StateType.REINFORCEMENT) + setState(StateType.SELECT); + } + + // Hud callbacks + public void engagementPanelClosed() + { + if (animationCount == 0) + leaveAnimationState(); + } + + public void endDeployment() + { + setState(StateType.DONE); + turnDone(); + } + + public void endGame() + { + game.switchToMenu(); + } + + public void endPlayerTurn(boolean abort) + { + if (abort) + state.abort(); + turnDone(); + } + + public void exitBoard(boolean doit) + { + if (doit) + setState(StateType.DONE); + else + setState(StateType.ABORT); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/Engagement.java b/core/src/ch/asynk/creepingarmor/game/Engagement.java new file mode 100644 index 0000000..1468181 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Engagement.java @@ -0,0 +1,114 @@ +package ch.asynk.creepingarmor.game; + +import java.util.List; +import java.util.LinkedList; +import java.util.Random; + +import com.badlogic.gdx.utils.Pool; +import com.badlogic.gdx.utils.Disposable; + +public class Engagement implements Disposable, Pool.Poolable +{ + private static Random rand = new Random(); + + private static final Pool engagementPool = new Pool() { + @Override + protected Engagement newObject() { + return new Engagement(); + } + }; + + public static Engagement get(Unit attacker, Unit defender) + { + Engagement e = engagementPool.obtain(); + e.attacker = attacker; + e.defender = defender; + e.diceRoll(); + + return e; + } + + public static void clearPool() + { + engagementPool.clear(); + } + + public Unit attacker; + public Unit defender; + public List assists; + public boolean success; + public int d1; + public int d2; + public int d3; + public int d4; + public int unitCount; + public int flankBonus; + public int unitDefense; + public int terrainDefense; + public int weatherDefense; + public int attackSum; + public int defenseSum; + + public Engagement() + { + assists = new LinkedList(); + reset(); + } + + @Override + public void reset() + { + attacker = null; + defender = null; + assists.clear(); + } + + @Override + public void dispose() + { + assists.clear(); + engagementPool.free(this); + } + + public void addAssist(Unit unit) + { + assists.add(unit); + } + + private void diceRoll() + { + d1 = rand.nextInt(6) + 1; + d2 = rand.nextInt(6) + 1; + d3 = rand.nextInt(6) + 1; + d4 = rand.nextInt(6) + 1; + } + + public void set(int cnt, int flk, int def, int tdf, int wdf) + { + this.unitCount = cnt; + this.flankBonus = flk; + this.unitDefense = def; + this.terrainDefense = tdf; + this.weatherDefense = wdf; + if (d3 == 0) + this.attackSum = (d1 + d2 + unitCount + flankBonus); + else + this.attackSum = (d3 + d4 + unitCount + flankBonus); + this.defenseSum = (unitDefense + terrainDefense + weatherDefense); + } + + + @Override + public String toString() + { + int a, b; + if (d3 == 0) { + a = d1; + b = d2; + } else { + a = d3; + b = d4; + } + return String.format("Engagement : (%d + %d + %d + %d) vs (%d + %d + %d) -> %b", a, b, unitCount, flankBonus, unitDefense, terrainDefense, weatherDefense, success); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/Hex.java b/core/src/ch/asynk/creepingarmor/game/Hex.java new file mode 100644 index 0000000..cca4fad --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Hex.java @@ -0,0 +1,138 @@ +package ch.asynk.creepingarmor.game; + +import java.util.List; +import java.util.Iterator; + +import com.badlogic.gdx.graphics.g2d.TextureAtlas; + +import ch.asynk.creepingarmor.engine.Board; +import ch.asynk.creepingarmor.engine.Pawn; +import ch.asynk.creepingarmor.engine.Tile; +import ch.asynk.creepingarmor.engine.Orientation; +import ch.asynk.creepingarmor.game.Unit.UnitType; + +public class Hex extends Tile +{ + public enum Terrain implements TileTerrain + { + OFFMAP, + BLOCKED, + CLEAR, + HILLS, + WOODS, + TOWN + } + + public static final int FOG = 0; + public static final int SELECT = 1; + public static final int AREA = 2; + public static final int MOVE = 3; + public static final int DIRECTIONS = 4; + public static final int ORIENTATION = 5; + public static final int OBJECTIVE = 6; + public static final int OBJECTIVE_HOLD = 7; + public static final int OBJECTIVE_GE = 8; + public static final int OBJECTIVE_US = 9; + public static final int EXIT = 10; + + public Terrain terrain; + public int roads; + + public String toString() + { + return String.format("(%d;%d) [%f;%f] t:%s r:%d", col, row, x, y, terrain, roads); + } + + public String toShort() + { + return String.format("(%d;%d)", col, row); + } + + public Hex(float x, float y, int col, int row, TextureAtlas atlas) + { + super(x, y, col, row, atlas); + this.terrain = Terrain.CLEAR; + this.roads = 0; + } + + public Unit getUnit() + { + return (Unit) stack.peekFirst(); + } + + @Override + public boolean isA(TileTerrain terrain) + { + return (this.terrain == terrain); + } + + @Override + public boolean isOffMap() + { + return isA(Terrain.OFFMAP); + } + + @Override + public boolean blockLineOfSightFrom(Tile tile) + { + if (isA(Terrain.CLEAR) && !hasUnits()) + return false; + + if (tile.isA(Terrain.HILLS) && isA(Terrain.CLEAR)) + return false; + + return true; + } + + @Override + public boolean atLeastOneMove(Pawn pawn) + { + if (hasUnits() || isA(Terrain.BLOCKED) || isA(Terrain.OFFMAP)) + return false; + return true; + } + + @Override + public boolean road(Orientation side) + { + return (side.s == (roads & side.s)); + } + + @Override + public int exitCost() + { + return 1; + } + + @Override + public int costFrom(Pawn pawn, Orientation side) + { + if (side == Orientation.KEEP) return 0; + if (hasUnits()) return (Integer.MAX_VALUE / 2); + if (road(side)) return 1; + + int c = 0; + switch(terrain) { + case CLEAR: + case HILLS: + c = 1; + break; + case WOODS: + case TOWN: + c = 2; + break; + case OFFMAP: + case BLOCKED: + c = (Integer.MAX_VALUE / 2); + break; + } + + return c; + } + + @Override + public int defense() + { + return (isA(Terrain.TOWN) ? 1 : 0); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/HexSet.java b/core/src/ch/asynk/creepingarmor/game/HexSet.java new file mode 100644 index 0000000..bcbfa2d --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/HexSet.java @@ -0,0 +1,29 @@ +package ch.asynk.creepingarmor.game; + +import java.util.Collection; +import java.util.LinkedHashSet; + +import ch.asynk.creepingarmor.engine.Tile; + +public class HexSet extends LinkedHashSet +{ + private final Map map; + + public HexSet(Map map, int n) + { + super(n); + this.map = map; + } + + public void enable(int i, boolean enable) + { + for (Hex hex : this) + map.enableOverlayOn(hex, i, enable); + } + + @SuppressWarnings("unchecked") + public Collection asTiles() + { + return (Collection) this; + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/Hud.java b/core/src/ch/asynk/creepingarmor/game/Hud.java new file mode 100644 index 0000000..1220a2d --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Hud.java @@ -0,0 +1,307 @@ +package ch.asynk.creepingarmor.game; + +import java.util.LinkedList; + +import com.badlogic.gdx.Gdx; + +import com.badlogic.gdx.utils.Disposable; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Animation; +import ch.asynk.creepingarmor.game.State.StateType; +import ch.asynk.creepingarmor.ui.Position; +import ch.asynk.creepingarmor.ui.Msg; +import ch.asynk.creepingarmor.ui.OkCancel; +import ch.asynk.creepingarmor.ui.Widget; +import ch.asynk.creepingarmor.game.hud.PlayerInfo; +import ch.asynk.creepingarmor.game.hud.ActionButtons; +import ch.asynk.creepingarmor.game.hud.StatisticsPanel; +import ch.asynk.creepingarmor.game.hud.EngagementPanel; + +import ch.asynk.creepingarmor.CreepingArmor; + +public class Hud implements Disposable, Animation +{ + public static final float OFFSET = 10f; + public static final float NOTIFY_DURATION = 2f; + + private final CreepingArmor game; + private final Ctrl ctrl; + + private Object hit; + + public PlayerInfo playerInfo; + public ActionButtons actionButtons; + + private Msg msg; + private StatisticsPanel stats; + private EngagementPanel engagement; + private OkCancel okCancel; + private LinkedList dialogs = new LinkedList(); + + public enum OkCancelAction + { + EXIT_BOARD, + ABORT_TURN, + END_TURN, + END_DEPLOYMENT, + } + private OkCancelAction okCancelAction; + + public Hud(final Ctrl ctrl, final CreepingArmor game) + { + this.game = game; + this.ctrl = ctrl; + + TextureAtlas hudAtlas = game.factory.hudAtlas; + playerInfo = new PlayerInfo(ctrl, game.fontW, game.uiAtlas, hudAtlas); + actionButtons = new ActionButtons(ctrl, game.uiAtlas, hudAtlas); + actionButtons.hide(); + msg = new Msg(game.fontB, game.uiAtlas); + okCancel = new OkCancel(game.fontB, game.uiAtlas); + stats = new StatisticsPanel(game.fontB, game.uiAtlas); + engagement = new EngagementPanel(game.fontB, game.uiAtlas, hudAtlas); + } + + @Override + public void dispose() + { + playerInfo.dispose(); + actionButtons.dispose(); + msg.dispose(); + okCancel.dispose(); + engagement.dispose(); + stats.dispose(); + } + + public void resize(int left, int bottom, int width, int height) + { + Position.update(left, bottom, width, height); + playerInfo.updatePosition(); + actionButtons.updatePosition(); + msg.updatePosition(); + stats.updatePosition(); + engagement.updatePosition(); + okCancel.updatePosition(); + } + + public void update() + { + Position position = ctrl.battle.getHudPosition(ctrl.player); + playerInfo.update(ctrl.player, position); + actionButtons.update(position.horizontalMirror()); + } + + @Override + public boolean animate(float delta) + { + msg.animate(delta); + playerInfo.animate(delta); + engagement.animate(delta); + return false; + } + + public void draw(Batch batch, boolean debug) + { + draw(batch); + if (debug) + game.fontB.draw(batch, String.format("FPS: %d", Gdx.graphics.getFramesPerSecond()), 80, 25); + } + + @Override + public void draw(Batch batch) + { + playerInfo.draw(batch); + actionButtons.draw(batch); + msg.draw(batch); + okCancel.draw(batch); + engagement.draw(batch); + stats.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + playerInfo.drawDebug(debugShapes); + actionButtons.drawDebug(debugShapes); + msg.drawDebug(debugShapes); + okCancel.drawDebug(debugShapes); + engagement.drawDebug(debugShapes); + stats.drawDebug(debugShapes); + } + + public void pushNotify(String s) + { + notify(s, NOTIFY_DURATION, Position.TOP_CENTER, true); + } + + public void notify(String s) + { + notify(s, NOTIFY_DURATION, Position.TOP_CENTER, false); + } + + public void notify(String s, float duration, Position position, boolean push) + { + if (push) msg.pushWrite(s, duration, position); + else msg.write(s, duration, position); + } + + public boolean touchDown(float x, float y) + { + hit = null; + + if (dialogs.size() > 0) { + Widget dialog = dialogs.getFirst(); + if (dialog.hit(x, y)) { + hit = dialog; + return true; + } + return false; + } + + if (ctrl.isInAnimation()) + return false; + + if (hit == null) { + if (actionButtons.touchDown(x, y)) + hit = actionButtons; + else if (playerInfo.touchDown(x, y)) + hit = playerInfo; + } + + return (hit != null); + } + + public boolean touchUp(float x, float y) + { + if (hit == null) + return false; + + if (dialogs.size() > 0) { + Widget dialog = dialogs.getFirst(); + if (hit == dialog) { + if (dialog.hit(x, y)) + closeDialog(); + hit = null; + } + } else { + if (hit == actionButtons) { + actionButtons.touchUp(x, y); + } + else if (hit == playerInfo) { + playerInfo.touchUp(x, y); + } + + hit = null; + } + + return true; + } + + private void closeDialog() + { + Widget dialog = dialogs.removeFirst(); + dialog.visible = false; + + if (dialog == okCancel) + closeOkCancel(); + else if (dialog == stats) + ctrl.endGame(); + else if (dialog == engagement) + ctrl.engagementPanelClosed(); + + if (dialogs.size() > 0) + dialogs.getFirst().visible = true; + else + ctrl.blockMap = false; + } + + private void closeOkCancel() + { + boolean ok = okCancel.ok; + + switch(okCancelAction) { + case EXIT_BOARD: + ctrl.exitBoard(ok); + break; + case END_TURN: + if (ok) + ctrl.endPlayerTurn(false); + break; + case ABORT_TURN: + if (ok) + ctrl.endPlayerTurn(true); + break; + case END_DEPLOYMENT: + if (ok) + ctrl.endDeployment(); + break; + } + } + + public boolean dialogActive() + { + return (dialogs.size() > 0); + } + + private void pushDialog(Widget dialog) + { + ctrl.blockMap = true; + if (dialogs.size() != 0) + dialog.visible = false; + dialogs.addLast(dialog); + } + + public void notifyDeploymentDone() + { + this.okCancelAction = OkCancelAction.END_TURN; + okCancel.show("Deployment Phase completed."); + okCancel.noCancel(); + pushDialog(okCancel); + } + + public void notifyNoMoreAP() + { + this.okCancelAction = OkCancelAction.END_TURN; + okCancel.show("No more Action Point left."); + okCancel.noCancel(); + pushDialog(okCancel); + } + + public void askExitBoard() + { + this.okCancelAction = OkCancelAction.EXIT_BOARD; + okCancel.show("Do you want this unit to escape the battle field ?"); + pushDialog(okCancel); + } + + public void askEndOfTurn() + { + this.okCancelAction = OkCancelAction.ABORT_TURN; + okCancel.show("You still have Action Points left.\nEnd your Turn anyway ?"); + pushDialog(okCancel); + } + + public void askEndDeployment() + { + this.okCancelAction = OkCancelAction.END_DEPLOYMENT; + okCancel.show("Deployment unit count reached.\nEnd Deployment phase ?"); + pushDialog(okCancel); + } + + public void engagementSummary(Engagement e, float volume) + { + engagement.show(e, Position.BOTTOM_CENTER, volume); + pushDialog(engagement); + } + + public void victory(Player winner, Player loser) + { + stats.show(winner, loser, Position.MIDDLE_CENTER); + pushDialog(stats); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/Map.java b/core/src/ch/asynk/creepingarmor/game/Map.java new file mode 100644 index 0000000..00d720b --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Map.java @@ -0,0 +1,659 @@ +package ch.asynk.creepingarmor.game; + +import com.badlogic.gdx.audio.Sound; +import com.badlogic.gdx.assets.AssetManager; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.CreepingArmor; +import ch.asynk.creepingarmor.engine.Pawn; +import ch.asynk.creepingarmor.engine.Board; +import ch.asynk.creepingarmor.engine.Tile; +import ch.asynk.creepingarmor.engine.Faction; +import ch.asynk.creepingarmor.engine.Move; +import ch.asynk.creepingarmor.engine.SelectedTile; +import ch.asynk.creepingarmor.engine.ObjectiveSet; +import ch.asynk.creepingarmor.engine.OrderList; +import ch.asynk.creepingarmor.engine.Orientation; +import ch.asynk.creepingarmor.engine.Meteorology; +import ch.asynk.creepingarmor.engine.PathBuilder; +import ch.asynk.creepingarmor.engine.gfx.Moveable; +import ch.asynk.creepingarmor.engine.gfx.Animation; +import ch.asynk.creepingarmor.engine.gfx.animations.AnimationSequence; +import ch.asynk.creepingarmor.engine.gfx.animations.DiceAnimation; +import ch.asynk.creepingarmor.engine.gfx.animations.FireAnimation; +import ch.asynk.creepingarmor.engine.gfx.animations.TankFireAnimation; +import ch.asynk.creepingarmor.engine.gfx.animations.InfantryFireAnimation; +import ch.asynk.creepingarmor.engine.gfx.animations.PromoteAnimation; +import ch.asynk.creepingarmor.engine.gfx.animations.DestroyAnimation; +import ch.asynk.creepingarmor.engine.gfx.animations.SoundAnimation; +import ch.asynk.creepingarmor.engine.gfx.animations.RunnableAnimation; +import ch.asynk.creepingarmor.engine.gfx.animations.MoveToAnimation.MoveToAnimationCb; + +import ch.asynk.creepingarmor.ui.Position; + +public abstract class Map extends Board implements MoveToAnimationCb, ObjectiveSet.ObjectiveCb +{ + private final Ctrl ctrl; + + public final HexSet possibleMoves; + public final PathBuilder pathBuilder; + + public final UnitList moveableUnits; + public final UnitList possibleTargets; + public final UnitList engagementAssists; + public final UnitList activatedUnits; + public final UnitList breakUnits; + public final ObjectiveSet objectives; + + public final Meteorology meteorology; + + private final DestroyAnimation destroy; + private final Sound tankMoveSound; + private final Sound infantryMoveSound; + private Sound sound; + private long soundId = -1; + + private OrderList commands; + + protected abstract void setup(); + + public Map(final CreepingArmor game, Board.Config cfg, String textureName) + { + super(game.factory, cfg, game.manager.get(textureName, Texture.class), + new SelectedTile(game.manager.get("data/hex.png", Texture.class), new float[] {.2f, .1f, .1f, .1f, .2f, .1f} )); + this.ctrl = game.ctrl; + this.destroy = new DestroyAnimation(); + this.tankMoveSound = game.manager.get("sounds/tank_move.mp3", Sound.class); + this.infantryMoveSound = game.manager.get("sounds/infantry_move.mp3", Sound.class); + DiceAnimation.init(game.manager.get("data/dice.png", Texture.class), 16, 9, game.manager.get("sounds/dice.mp3", Sound.class)); + PromoteAnimation.init(game.manager.get("data/hud.atlas", TextureAtlas.class), + game.manager.get("sounds/promote_us.mp3", Sound.class), + game.manager.get("sounds/promote_ge.mp3", Sound.class)); + FireAnimation.init( + game.manager.get("data/infantry_fire.png", Texture.class), 1, 8, + game.manager.get("data/tank_fire.png", Texture.class), 1, 8, + game.manager.get("data/explosions.png", Texture.class), 16, 8, + game.manager.get("sounds/infantry_fire.mp3", Sound.class), + game.manager.get("sounds/tank_fire.mp3", Sound.class), + game.manager.get("sounds/tank_fire_short.mp3", Sound.class), + game.manager.get("sounds/explosion.mp3", Sound.class), + game.manager.get("sounds/explosion_short.mp3", Sound.class) + ); + + setup(); + + possibleMoves = new HexSet(this, 40); + pathBuilder = new PathBuilder(this, 10, 20, 5, 10); + moveableUnits = new UnitList(6); + + possibleTargets = new UnitList(10); + engagementAssists = new UnitList(6); + activatedUnits = new UnitList(7); + breakUnits = new UnitList(4); + + objectives = new ObjectiveSet(this, 4); + + meteorology = new Meteorology(); + commands = new OrderList(); + } + + @Override + public void dispose() + { + super.dispose(); + clearAll(); + destroy.dispose(); + pathBuilder.dispose(); + DiceAnimation.free(); + PromoteAnimation.free(); + FireAnimation.free(); + commands.dispose(); + Command.clearPool(); + Engagement.clearPool(); + } + + public void clearAll() + { + possibleMoves.clear(); + possibleTargets.clear(); + pathBuilder.clear(); + moveableUnits.clear(); + engagementAssists.clear(); + activatedUnits.clear(); + breakUnits.clear(); + } + + public Hex getHexAt(float x, float y) + { + return (Hex) getTileAt(x, y); + } + + public Hex getHex(int col, int row) + { + return (Hex) getTile(col, row); + } + + public void addObjective(int col, int row, Army army) + { + addObjective(col, row, army, true); + } + + public void addHoldObjective(int col, int row, Army army) + { + addObjective(col, row, army, false); + } + + private void addObjective(int col, int row, Army army, boolean persistent) + { + Hex hex = getHex(col, row); + objectives.add(hex, army, persistent); + showObjective(hex, army, !persistent); + } + + private void claim(Hex hex, Army army) + { + showObjective(hex, objectives.claim(hex, army)); + } + + private void unclaim(Hex hex) + { + showObjective(hex, objectives.unclaim(hex)); + } + + public int collectPossibleMoves(Unit unit) + { + if (!unit.canMove()) { + possibleMoves.clear(); + return 0; + } + return collectPossibleMoves(unit, possibleMoves.asTiles()); + } + + public int togglePathBuilderHex(Hex hex) + { + return pathBuilder.toggleCtrlTile(hex); + } + + public int collectPossibleTargets(Unit unit, UnitList foes) + { + if (!unit.canEngage()) { + possibleTargets.clear(); + return 0; + } + // return collectPossibleTargets(unit, possibleTargets); + return collectPossibleTargets(unit, foes.asPawns(), possibleTargets.asPawns()); + } + + public int collectMoveableUnits(Unit unit) + { + if (unit.canHQMove()) { + collectMoveAssists(unit, moveableUnits.asPawns()); + } else { + moveableUnits.clear(); + } + if (unit.canMove()) + moveableUnits.add(unit); + return moveableUnits.size(); + } + + public int collectAttackAssists(Unit unit, Unit target, UnitList units) + { + int s = collectAttackAssists(unit, target, units.asPawns(), engagementAssists.asPawns()); + activatedUnits.add(unit); + return s; + } + + public boolean toggleAttackAssist(Unit unit) + { + if (activatedUnits.contains(unit)) { + activatedUnits.remove(unit); + unit.hideAttack(); + unit.showAttackAssist(); + return false; + } else { + activatedUnits.add(unit); + unit.showAttack(); + unit.hideAttackAssist(); + return true; + } + } + + public void collectAndShowMovesAndAssits(Unit unit) + { + hidePossibleMoves(); + hideMoveableUnits(); + collectPossibleMoves(unit); + collectMoveableUnits(unit); + showPossibleMoves(); + showMoveableUnits(); + activatedUnits.clear(); + } + + // -> implement MoveToAnimationCb + + @Override + public void moveToAnimationEnter(Moveable moveable, float x, float y, float r) + { + claim(getHexAt(x, y), (Army) moveable.getFaction()); + } + + @Override + public void moveToAnimationLeave(Moveable moveable, float x, float y, float r) + { + unclaim(getHexAt(x, y)); + } + + @Override + public void moveToAnimationDone(Moveable moveable, float x, float y, float r) + { + } + + // <- implement MoveToAnimationCb + + private int process(Unit unit, Move move) + { + CreepingArmor.debug(" Move", String.format("%s %s", move.type, move.toString())); + + int r = 1; + + switch(move.type) { + case REGULAR: + initMove(unit); + movePawn(unit, move, this); + r = moveableUnits.size(); + break; + case EXIT: + initMove(unit); + movePawn(unit, move, this); + ctrl.player.unitWithdraw(unit); + r = moveableUnits.size(); + break; + case SET: + setPawnOnto(unit, move); + ctrl.player.unitEntry(unit); + claim((Hex) move.to, unit.getArmy()); + break; + case ENTER: + enterPawn(unit, move); + ctrl.player.unitEntry(unit); + claim((Hex) move.to, unit.getArmy()); + break; + default: + System.err.println(String.format("process wrong Move type %s", move.type)); + r = -1; + break; + } + + return r; + } + + private int promoteUnit(final Unit unit, final Player player) + { + activatedUnits.add(unit); + + Hex hex = unit.getHex(); + AnimationSequence seq = AnimationSequence.get(2); + seq.addAnimation(PromoteAnimation.get((unit.getArmy() == Army.US), hex.getX(), hex.getY(), ctrl.cfg.fxVolume)); + seq.addAnimation ( RunnableAnimation.get(unit, new Runnable() { + @Override + public void run() { + player.promote(unit); + } + })); + addAnimation(seq); + return 1; + } + + private int process(Command cmd) + { + CreepingArmor.debug("Command", cmd.toString()); + + int r = 1; + + switch(cmd.type) { + case MOVE: + r = process(cmd.unit, cmd.move); + break; + case PROMOTE: + r = promoteUnit(cmd.unit, cmd.player); + break; + case ENGAGE: + resolveEngagement(cmd.engagement); + r = doEngagement(cmd.engagement); + break; + default: + System.err.println(String.format("process wrong Command type %s", cmd.type)); + r = -1; + break; + } + + if (r != -1) + commands.add(cmd); + + return r; + } + + // Ctrl Methods + + public void init() + { + actionDone(); + } + + public void turnDone() + { + CreepingArmor.debug("TurnDone", String.format(" Processed Commands : %d", commands.size())); + + if (objectives.modifiedCount() > 0) + throw new RuntimeException("objectives not cleared"); + + // FIXME do something with these Commands + commands.dispose(); + } + + public void actionDone() + { + objectives.forget(); + } + + // STATES ENTRY -> + + public void showOnBoard(final Unit unit, Hex to, Orientation o) + { + setPawnOnto(unit, to, o); + } + + public boolean setOnBoard(final Unit unit, Hex to, Orientation entry) + { + commands.dispose(unit); + return (process(getMoveCommand(unit, Move.getSet(unit, to, entry))) == 1); + } + + public boolean enterBoard(final Unit unit, Hex to, int allowedMoves) + { + Orientation entry = findBestEntry(unit, to, allowedMoves); + if (entry == Orientation.KEEP) + return false; + + return (process(getMoveCommand(unit, Move.getEnter(unit, to, entry))) == 1); + } + + public int exitBoard(final Unit unit) + { + return process(getMoveCommand(unit, pathBuilder.getExitMove())); + } + + public int moveUnit(final Unit unit) + { + return process(getMoveCommand(unit, pathBuilder.getMove())); + } + + public void revertMoves() + { + for (Unit unit: activatedUnits) { + CreepingArmor.debug(" revertMove() " + unit); + revertLastPawnMove(unit); + commands.dispose(unit, Command.CommandType.MOVE); + } + activatedUnits.clear(); + objectives.revert(this); + } + + public void revertEnter(final Unit unit) + { + CreepingArmor.debug(" revertEnter() "+ unit); + removePawn(unit); + objectives.revert(this); + ctrl.player.revertUnitEntry(unit); + commands.dispose(unit); + unit.reset(); + } + + public boolean engageUnit(final Unit unit, final Unit target) + { + attack(unit, target, true); + + Command cmd = Command.get(ctrl.player); + cmd.setEngage(unit, target); + return (process(cmd) == 1); + } + + public void promoteUnit(final Unit unit) + { + Command cmd = Command.get(ctrl.player); + cmd.setPromote(unit); + process(cmd); + } + + // STATES ENTRY <- + + private Command getMoveCommand(Unit unit, Move move) + { + Command cmd = Command.get(ctrl.player); + cmd.setMove(unit, move); + return cmd; + } + + private void initMove(Unit unit) + { + moveableUnits.remove(unit); + activatedUnits.add(unit); + playMoveSound(unit); + } + + private void playMoveSound(Unit unit) + { + if (unit.isA(Unit.UnitType.INFANTRY)) + sound = infantryMoveSound; + else + sound = tankMoveSound; + soundId = sound.play(ctrl.cfg.fxVolume); + } + + @Override + protected void animationsOver() + { + if (soundId >= 0) { + addAnimation( SoundAnimation.get(SoundAnimation.Action.FADE_OUT, sound, soundId, ctrl.cfg.fxVolume, 0.5f)); + soundId = -1; + return; + } + ctrl.animationsOver(); + } + + private void addEngagementAnimation(Unit target) + { + FireAnimation.reset(); + Hex to = target.getHex(); + for (Unit u : activatedUnits) { + Hex from = u.getHex(); + float halfWidth = (u.getWidth() / 2f); + if (u.isA(Unit.UnitType.INFANTRY)) + addAnimation(InfantryFireAnimation.get(ctrl.cfg.fxVolume, from.getX(), from.getY(), to.getX(), to.getY(), halfWidth)); + else + addAnimation(TankFireAnimation.get(ctrl.cfg.fxVolume, from.getX(), from.getY(), to.getX(), to.getY(), halfWidth)); + } + } + + private void resolveEngagement(Engagement e) + { + int dice = e.d1 + e.d2; + + int distance = 0; + boolean mayReroll = false; + boolean night = (meteorology.day == Meteorology.Day.NIGHT); + boolean flankAttack = false; + boolean terrainBonus = true; + + for (Unit unit : activatedUnits) { + if (unit != e.attacker) + e.addAssist(unit); + if (unit.isAce()) + mayReroll = true; + if (unit.isFlankAttack()) + flankAttack = true; + if (unit.isA(Unit.UnitType.INFANTRY)) + terrainBonus = false; + if (night) { + if (distance < unit.attackDistance()) + distance = unit.attackDistance(); + } + } + + int cnt = activatedUnits.size(); + int def = e.defender.getDefense(e.attacker.getTile()); + int flk = (flankAttack ? Unit.FLANK_ATTACK_BONUS : 0); + int tdf = (terrainBonus ? e.defender.getTile().defense() : 0); + int wdf = 0; + if (night) { + if (distance > 3) + wdf = 3; + else if (distance > 2) + wdf = 2; + else if (distance > 1) + wdf = 1; + } + int s1 = (dice + cnt + flk); + int s2 = (def + tdf + wdf); + + boolean success = false; + if (dice == 2) { + success = false; + } else if (dice == 12) { + success = true; + } else { + success = (s1 >= s2); + } + if (!success && mayReroll) { + dice = e.d3 + e.d4; + s1 = (dice + cnt + flk); + if (dice == 2) { + success = false; + } else if (dice == 12) { + success = true; + } else { + success = (s1 >= s2); + } + } else { + e.d3 = 0; + e.d4 = 0; + } + + e.set(cnt, flk, def, tdf, wdf); + e.success = success; + } + + private int doEngagement(Engagement e) + { + breakUnits.clear(); + activatedUnits.clear(); + + activatedUnits.add(e.attacker); + for (Unit u : e.assists) + activatedUnits.add(u); + + for (Unit u : activatedUnits) { + u.engage(); + if (u.isA(Unit.UnitType.INFANTRY)) + breakUnits.add(u); + } + + if (e.success) { + unclaim(e.defender.getHex()); + removePawn(e.defender); + destroy.set(2f, e.defender); + addAnimation(destroy); + } + + if ((activatedUnits.size() == 1) && e.attacker.isA(Unit.UnitType.AT_GUN) && e.defender.isHardTarget()) + activatedUnits.clear(); + + ctrl.hud.engagementSummary(e, ctrl.cfg.fxVolume); + addEngagementAnimation(e.defender); + + return (e.success ? 1 : 0); + } + + // SHOW / HIDE + + public void togglePathOverlay(Hex hex) + { + boolean enable= !hex.isOverlayEnabled(Hex.MOVE); + enableOverlayOn(hex, Hex.MOVE, enable); + } + + private void showUnitsOverlay(UnitList units, int overlay, boolean on) + { + for (Unit unit : units) + unit.enableOverlay(overlay, on); + } + + public void showMoveableUnits() { showUnitsOverlay(moveableUnits, Unit.MOVE, true); } + public void hideMoveableUnits() { showUnitsOverlay(moveableUnits, Unit.MOVE, false); } + public void showPossibleTargets() { showUnitsOverlay(possibleTargets, Unit.TARGET, true); } + public void hidePossibleTargets() { showUnitsOverlay(possibleTargets, Unit.TARGET, false); } + public void showAttackAssists() { showUnitsOverlay(engagementAssists, Unit.MAY_FIRE, true); } + public void hideAttackAssists() { showUnitsOverlay(engagementAssists, Unit.FIRE, false); + showUnitsOverlay(engagementAssists, Unit.MAY_FIRE, false); } + public void showBreakUnits() { showUnitsOverlay(breakUnits, Unit.MOVE, true); } + public void hideBreakUnits() { showUnitsOverlay(breakUnits, Unit.MOVE, false); } + + public void showPossibleMoves() { possibleMoves.enable(Hex.AREA, true); } + public void hidePossibleMoves() { possibleMoves.enable(Hex.AREA, false); } + public void showPathBuilder() { pathBuilder.enable(Hex.AREA, true); } + public void hidePathBuilder() { pathBuilder.enable(Hex.AREA, false); } + public void showPath(Hex dst) { pathBuilder.enable(Hex.MOVE, true); showMove(dst); } + public void hidePath(Hex dst) { pathBuilder.enable(Hex.MOVE, false); hideMove(dst); } + + public void selectHex(Hex hex) { selectedTile.set(hex); } + public void unselectHex(Hex hex) { selectedTile.hide(); } + public void showMove(Hex hex) { enableOverlayOn(hex, Hex.MOVE, true); } + public void hideMove(Hex hex) { enableOverlayOn(hex, Hex.MOVE, false); } + public void showDirections(Hex hex) { enableOverlayOn(hex, Hex.DIRECTIONS, true); } + public void hideDirections(Hex hex) { enableOverlayOn(hex, Hex.DIRECTIONS, false); } + public void showOrientation(Hex hex, Orientation o) { enableOverlayOn(hex, Hex.ORIENTATION, o, true); } + public void hideOrientation(Hex hex) { enableOverlayOn(hex, Hex.ORIENTATION, false); } + public void showExit(Hex hex) { enableOverlayOn(hex, Hex.EXIT, true); } + public void hideExit(Hex hex) { enableOverlayOn(hex, Hex.EXIT, false); } + + public void showObjective(Hex hex, Army army, boolean hold) + { + if (hold) + enableOverlayOn(hex, Hex.OBJECTIVE_HOLD, true); + else + enableOverlayOn(hex, Hex.OBJECTIVE, true); + } + + + // -> implement ObjectiveSet.ObjectiveCb + + public void showObjective(Tile tile, Faction faction) + { + showObjective((Hex) tile, (Army) faction); + } + + // <- implement MoveToAnimationCb + + public void showObjective(Hex hex, Army army) + { + if (army == null) + army = Army.NONE; + switch(army) { + case GE: + enableOverlayOn(hex, Hex.OBJECTIVE_GE, true); + enableOverlayOn(hex, Hex.OBJECTIVE_US, false); + break; + case US: + enableOverlayOn(hex, Hex.OBJECTIVE_GE, false); + enableOverlayOn(hex, Hex.OBJECTIVE_US, true); + break; + case NONE: + default: + enableOverlayOn(hex, Hex.OBJECTIVE_GE, false); + enableOverlayOn(hex, Hex.OBJECTIVE_US, false); + break; + } + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/Player.java b/core/src/ch/asynk/creepingarmor/game/Player.java new file mode 100644 index 0000000..020118a --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Player.java @@ -0,0 +1,213 @@ +package ch.asynk.creepingarmor.game; + +import java.util.Random; +import java.util.List; + +import ch.asynk.creepingarmor.CreepingArmor; + +public class Player +{ + private static final float MOVE_TIME = 0.4f; + + private static Random rand = new Random(); + + private int turn; + private int apSpent; + private int actionPoints; + private boolean deploymentDone; + + public Army army; + public UnitList units; + public UnitList casualties; + public UnitList reinforcement; + public UnitList withdrawed; + + public int actionCount; + public int lostEngagementCount; + public int wonEngagementCount; + + public Player(final CreepingArmor game, Army army, int n) + { + this.army = army; + this.units = new UnitList(n); + this.casualties = new UnitList(n); + this.reinforcement = new UnitList(n); + this.withdrawed = new UnitList(n); + this.turn = 0; + this.apSpent = 0; + this.actionPoints = 0; + this.deploymentDone = false; + this.actionCount = 0; + this.lostEngagementCount = 0; + this.wonEngagementCount = 0; + } + + public String getName() + { + return army.toString(); + } + + public String toString() + { + return String.format("%s Turn:%d AP:%d units:%d casualties:%d", army, turn, actionPoints, units.size(), casualties.size()); + } + + public String getStats() + { + return String.format("%s\n%4d\n%4d\n%4d\n%4d\n%4d\n%4d", getName(), actionCount, unitsLeft(), withdrawed(), casualties(), wonEngagementCount, lostEngagementCount); + } + + public boolean is(Army army) + { + return (this.army == army); + } + + public boolean isEnemy(Unit unit) + { + return unit.isEnemy(army); + } + + public boolean isEnemy(Army other) + { + return army.isEnemy(other); + } + + public int unitsLeft() + { + return (units.size() + reinforcement.size()); + } + + public int reinforcement() + { + return reinforcement.size(); + } + + public int casualties() + { + return casualties.size(); + } + + public int withdrawed() + { + return withdrawed.size(); + } + + public void addUnit(Unit unit) + { + units.add(unit); + } + + public void addReinforcement(Unit unit) + { + reinforcement.add(unit); + } + + public void unitEntry(Unit unit) + { + reinforcement.remove(unit); + units.add(unit); + } + + public void revertUnitEntry(Unit unit) + { + units.remove(unit); + reinforcement.add(unit); + } + + public void casualty(Unit unit) + { + units.remove(unit); + casualties.add(unit); + } + + public void unitWithdraw(Unit unit) + { + units.remove(unit); + withdrawed.add(unit); + } + + public int getAp() + { + return ((apSpent < actionPoints) ? (apSpent + 1) : apSpent); + } + + public int getTurnDone() + { + return turn; + } + + public int getCurrentTurn() + { + return (turn + 1); + } + + public boolean apExhausted() + { + return (apSpent == actionPoints); + } + + public boolean isDeploymentDone() + { + return (deploymentDone || (reinforcement.size() == 0)); + } + + public void burnDownOneAp() + { + apSpent += 1; + actionCount += 1; + if (apSpent > actionPoints) CreepingArmor.debug("ERROR: spent too much AP, please report"); + } + + public void turnEnd() + { + if (deploymentDone) + turn += 1; + else + deploymentDone = (reinforcement.size() == 0); + for (Unit unit : units) + unit.reset(); + } + + public void turnStart() + { + if (isDeploymentDone()) + computeActionPoints(); + } + + public int d6() + { + return rand.nextInt(6) + 1; + } + + private void computeActionPoints() + { + this.actionPoints = 2; + if (d6() > 2) { + this.actionPoints += 1; + if (d6() > 3) + this.actionPoints += 1; + } + apSpent = 0; + } + + public boolean canPromote(Unit unit) + { + if (unit.isHq()) return false; + for (Unit p: casualties) + if (p.isHqOf(unit)) return true; + return false; + } + + public boolean promote(Unit unit) + { + for (Unit p: casualties) { + if (p.isHqOf(unit)) { + unit.promote(); + p.degrade(); + return true; + } + } + + return false; + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/State.java b/core/src/ch/asynk/creepingarmor/game/State.java new file mode 100644 index 0000000..a0af2e2 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/State.java @@ -0,0 +1,35 @@ +package ch.asynk.creepingarmor.game; + +public interface State +{ + enum StateType { + SELECT, + MOVE, + ROTATE, + ENGAGE, + BREAK, + PROMOTE, + ANIMATION, + REINFORCEMENT, + DEPLOYMENT, + WITHDRAW, + ABORT, + DONE + }; + + public void enter(StateType prevState); + + public void leave(StateType nextState); + + public StateType abort(); + + public StateType execute(); + + public void touchDown(); + + public void touchUp(); + + public boolean downInMap(float x, float y); + + public boolean upInMap(float x, float y); +} diff --git a/core/src/ch/asynk/creepingarmor/game/Unit.java b/core/src/ch/asynk/creepingarmor/game/Unit.java new file mode 100644 index 0000000..f209ea2 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Unit.java @@ -0,0 +1,361 @@ +package ch.asynk.creepingarmor.game; + +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; + +import ch.asynk.creepingarmor.engine.Pawn; +import ch.asynk.creepingarmor.engine.Tile; +import ch.asynk.creepingarmor.engine.HeadedPawn; +import ch.asynk.creepingarmor.engine.Orientation; +import ch.asynk.creepingarmor.game.Hex.Terrain; + +import ch.asynk.creepingarmor.CreepingArmor; + +public class Unit extends HeadedPawn +{ + public static final int MOVE = 0; + public static final int TARGET = 1; + public static final int FIRE = 2; + public static final int MAY_FIRE = 3; + public static final int ACE = 4; + public static final int HQ = 5; + public static final int HAS_FIRED = 6; + public static final int HAS_MOVED = 7; + + public static final int FLANK_ATTACK_BONUS = 1; + + public enum UnitType implements Pawn.PawnType + { + HARD_TARGET, + HARD_TARGET_HQ, + INFANTRY, + AT_GUN, + ARTILLERY + } + + public enum UnitId implements Pawn.PawnId + { + GE_AT_GUN("German Anti-Tank Gun"), + GE_INFANTRY("German Infantry"), + GE_KINGTIGER("German King Tiger"), + GE_PANZER_IV("German Panzer IV"), + GE_PANZER_IV_HQ("German Panzer IV HQ"), + GE_TIGER("German Tiger"), + GE_WESPE("German Wespe"), + + US_AT_GUN("US Anti-Tank Gun"), + US_INFANTRY("US Infantry"), + US_PERSHING("US Pershing"), + US_PERSHING_HQ("US Pershing HQ"), + US_PRIEST("US Priest"), + US_SHERMAN("US Sherman"), + US_SHERMAN_HQ("US Sherman HQ"), + US_WOLVERINE("US Wolverine"); + + private String s; + UnitId(String s) { this.s = s; } + public String toString() { return s; } + } + + public int rng; + public int def; + public int cdef; + public int mp; + public int mpLeft; + public UnitType type; + public UnitId id; + public boolean ace; + private boolean hasMoved; + private boolean hasFired; + + protected Unit(Army army, String pawn, String head, TextureAtlas pawns, TextureAtlas overlays) + { + super(army, pawn, head, pawns, overlays); + ace = false; + + } + + private void commonSetup() + { + mpLeft = mp; + enableOverlay(HQ, isHq()); + this.hasMoved = false; + this.hasFired = false; + updateDescr(); + } + + private void updateDescr() + { + if (cdef == -1) + this.descr = id.toString() + (ace ? " Ace " : "") + " (" + rng + "-" + def + "-" + mp + ")"; + else + this.descr = id.toString() + (ace ? " Ace " : "") + " (" + rng + "-" + def + "/" + cdef + "-" + mp + ")"; + } + + // hard tager + public Unit(Army army, UnitId id, UnitType type, int range, int defense, int movementPoints, String unit, String head, TextureAtlas pawns, TextureAtlas overlays) + { + this(army, unit, head, pawns, overlays); + this.rng = range; + this.def = defense; + this.cdef = -1; + this.mp = movementPoints; + this.id = id; + this.type = type; + commonSetup(); + } + + // soft tager + public Unit(Army army, UnitId id, UnitType type, int range, int defense, int concealedDefense, int movementPoints, String unit, String head, TextureAtlas pawns, TextureAtlas overlays) + { + this(army, unit, head, pawns, overlays); + this.rng = range; + this.def = defense; + this.cdef = concealedDefense; + this.mp = movementPoints; + this.id = id; + this.type = type; + commonSetup(); + } + + public Army getArmy() + { + return (Army) getFaction(); + } + + public Hex getHex() + { + return (Hex) getTile(); + } + + public boolean isAce() + { + return ace; + } + + public void setAce(boolean ace) + { + this.ace = ace; + updateDescr(); + enableOverlay(ACE, ace); + } + + @Override + public int getMovementPoints() + { + return mpLeft; + } + + @Override + public int getRoadMarchBonus() + { + return 1; + } + + @Override + public int getEngagementRangeFrom(Tile tile) + { + if (!isA(UnitType.INFANTRY) && tile.isA(Terrain.HILLS)) + return rng + 1; + return rng; + } + + @Override + public int getAngleOfAttack() + { + return orientation.getFrontSides(); + } + + @Override + public int getFlankSides() + { + return orientation.getBackSides(); + } + + @Override + public int getDefense(Tile tile) + { + if (!isHardTarget() && (tile.isA(Terrain.HILLS) || tile.isA(Terrain.WOODS) || tile.isA(Terrain.TOWN))) + return cdef; + + return def; + } + + @Override + public boolean isUnit() + { + return true; + } + + @Override + public boolean isA(PawnId i) + { + return (id == i); + } + + @Override + public boolean isA(PawnType t) + { + return (type == t); + } + + @Override + public boolean isHq() + { + return isA(UnitType.HARD_TARGET_HQ); + } + + @Override + public boolean isHqOf(Pawn other) + { + if (isA(UnitId.GE_PANZER_IV_HQ) && other.isA(UnitId.GE_PANZER_IV)) return true; + if (isA(UnitId.US_PERSHING_HQ) && other.isA(UnitId.US_PERSHING)) return true; + if (isA(UnitId.US_SHERMAN_HQ) && other.isA(UnitId.US_SHERMAN)) return true; + return false; + } + + public void promote() + { + if (isA(UnitId.GE_PANZER_IV)) + id = UnitId.GE_PANZER_IV_HQ; + else if (isA(UnitId.US_PERSHING)) + id = UnitId.US_PERSHING_HQ; + else if (isA(UnitId.US_SHERMAN)) + id = UnitId.US_SHERMAN_HQ; + else + return; + + type = UnitType.HARD_TARGET_HQ; + enableOverlay(HQ, true); + updateDescr(); + } + + public void degrade() + { + if (isA(UnitId.GE_PANZER_IV_HQ)) + id = UnitId.GE_PANZER_IV; + else if (isA(UnitId.US_PERSHING_HQ)) + id = UnitId.US_PERSHING; + else if (isA(UnitId.US_SHERMAN_HQ)) + id = UnitId.US_SHERMAN; + else + return; + + type = UnitType.HARD_TARGET; + enableOverlay(HQ, false); + updateDescr(); + } + + @Override + public boolean isHardTarget() + { + return (isA(UnitType.HARD_TARGET) || isA(UnitType.HARD_TARGET_HQ) || isA(UnitType.ARTILLERY)); + } + + @Override + public boolean canRotate() + { + return canMove(); + } + + @Override + public boolean canMove() + { + if (isHardTarget()) return !hasMoved; + return (!hasMoved && !hasFired); + } + + @Override + public boolean canEngage() + { + if (isHardTarget()) return !hasFired; + return (!hasMoved && !hasFired); + } + + @Override + public boolean canAssistEngagementWithoutLos() + { + return isA(UnitType.ARTILLERY); + } + + @Override + public boolean canEngage(Pawn other) + { + return (isEnemy(other) && canEngage()); + } + + public boolean canHQMove() + { + return (isHq() && ((move == null) || (!move.isEnter()))); + } + + public void setMoved() + { + hasMoved = true; + updateOverlays(); + } + + @Override + public void move() + { + int cost = move.cost; + + if (move.roadMarch && (cost > mpLeft)) + cost -= getRoadMarchBonus(); + + if (cost > mpLeft) + CreepingArmor.debug("ERROR: Movement point exceeded: " + cost + "/" + mpLeft + " please report"); + + if (move.isFinal()) + setMoved(); + + mpLeft -= cost; + } + + @Override + public void engage() + { + hasFired = true; + updateOverlays(); + } + + @Override + public void reset() + { + super.reset(); + mpLeft = mp; + hasFired = false; + hasMoved = false; + hideHasMoved(); + hideHasFired(); + } + + @Override + public void revertLastMove() + { + hasMoved = false; + mpLeft = mp; + updateOverlays(); + move = null; + } + + private void updateOverlays() + { + enableOverlay(HAS_MOVED, !canMove()); + enableOverlay(HAS_FIRED, !canEngage()); + } + + // SHOW / HIDE + public void showMoveable() { enableOverlay(MOVE, true); } + public void hideMoveable() { enableOverlay(MOVE, false); } + public void showTarget() { enableOverlay(TARGET, true); } + public void hideTarget() { enableOverlay(TARGET, false); } + public void showAttack() { enableOverlay(FIRE, true); } + public void hideAttack() { enableOverlay(FIRE, false); } + public void showAttackAssist() { enableOverlay(MAY_FIRE, true); } + public void hideAttackAssist() { enableOverlay(MAY_FIRE, false); } + public void showHasMoved() { enableOverlay(HAS_MOVED, true); } + public void hideHasMoved() { enableOverlay(HAS_MOVED, false); } + public void showHasFired() { enableOverlay(HAS_FIRED, true); } + public void hideHasFired() { enableOverlay(HAS_FIRED, false); } +} diff --git a/core/src/ch/asynk/creepingarmor/game/UnitList.java b/core/src/ch/asynk/creepingarmor/game/UnitList.java new file mode 100644 index 0000000..2e4ee27 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/UnitList.java @@ -0,0 +1,20 @@ +package ch.asynk.creepingarmor.game; + +import java.util.Collection; +import java.util.ArrayList; + +import ch.asynk.creepingarmor.engine.Pawn; + +public class UnitList extends ArrayList +{ + public UnitList(int n) + { + super(n); + } + + @SuppressWarnings("unchecked") + public Collection asPawns() + { + return (Collection) this; + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/Zone.java b/core/src/ch/asynk/creepingarmor/game/Zone.java new file mode 100644 index 0000000..f7c0a82 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/Zone.java @@ -0,0 +1,14 @@ +package ch.asynk.creepingarmor.game; + +import ch.asynk.creepingarmor.engine.Orientation; + +public class Zone extends HexSet +{ + public int allowedMoves; + public Orientation orientation; + + public Zone(Map map, int n) + { + super(map, n); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/battles/BattleCommon.java b/core/src/ch/asynk/creepingarmor/game/battles/BattleCommon.java new file mode 100644 index 0000000..fb1ab53 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/battles/BattleCommon.java @@ -0,0 +1,151 @@ +package ch.asynk.creepingarmor.game.battles; + +import java.util.Random; +import java.util.HashMap; +import java.util.ArrayList; + +import ch.asynk.creepingarmor.game.Army; +import ch.asynk.creepingarmor.game.Battle; +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.HexSet; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Unit.UnitId; +import ch.asynk.creepingarmor.game.State.StateType; + +public abstract class BattleCommon implements Battle +{ + protected final static Random random = new Random(); + + protected Factory.MapType mapType; + protected String name; + protected String description; + protected Factory factory; + protected Player usPlayer; + protected Player gePlayer; + protected ArrayList entryZone = new ArrayList(); + protected ArrayList exitZone = new ArrayList(); + protected HashMap unitEntry = new HashMap(); + protected HashMap unitExit = new HashMap(); + + public BattleCommon(Factory factory) + { + this.factory = factory; + } + + @Override + public void init() + { + this.usPlayer = factory.getPlayer(Army.US); + this.gePlayer = factory.getPlayer(Army.GE); + } + + @Override + public String toString() + { + return getName(); + } + + @Override + public String getName() + { + return name; + } + + @Override + public String getDescription() + { + return description; + } + + @Override + public Factory.MapType getMapType() + { + return mapType; + } + + @Override + public Map getMap() + { + return factory.getMap(mapType); + } + + @Override + public Player opponent(Player player) + { + if (player == usPlayer) + return gePlayer; + return usPlayer; + } + + @Override + public boolean deploymentDone(Player player) + { + return player.isDeploymentDone(); + } + + @Override + public StateType getState(Player player) + { + if (!player.isDeploymentDone()) + return StateType.DEPLOYMENT; + return StateType.SELECT; + } + + @Override + public boolean getReinforcement(Ctrl ctrl, Map map) + { + return false; + } + + @Override + public Zone getEntryZone(Unit unit) + { + return unitEntry.get(unit); + } + + @Override + public Zone getExitZone(Unit unit) + { + return unitExit.get(unit); + } + + public void addEntryZone(Zone entry) + { + entryZone.add(entry); + } + + public void addExitZone(Zone exit) + { + exitZone.add(exit); + exit.enable(Hex.EXIT, true); + } + + public void addReinforcement(Player player, Zone entryZone, UnitId unitId) + { + addReinforcement(player, entryZone, unitId, false); + } + + public void addReinforcement(Player player, Zone entryZone, Zone exitZone, UnitId unitId) + { + addReinforcement(player, entryZone, exitZone, unitId, false); + } + + public void addReinforcement(Player player, Zone entryZone, UnitId unitId, boolean ace) + { + addReinforcement(player, entryZone, null, unitId, ace); + } + + public void addReinforcement(Player player, Zone entryZone, Zone exitZone, UnitId unitId, boolean ace) + { + Unit unit = factory.getUnit(unitId); + unit.setAce(ace); + player.addReinforcement(unit); + unitEntry.put(unit, entryZone); + if (exitZone != null) + unitExit.put(unit, exitZone); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/battles/BattleCounterAttack.java b/core/src/ch/asynk/creepingarmor/game/battles/BattleCounterAttack.java new file mode 100644 index 0000000..a06d7cd --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/battles/BattleCounterAttack.java @@ -0,0 +1,150 @@ +package ch.asynk.creepingarmor.game.battles; + +import ch.asynk.creepingarmor.game.Army; +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Unit.UnitId; +import ch.asynk.creepingarmor.ui.Position; +import ch.asynk.creepingarmor.engine.Orientation; + +public class BattleCounterAttack extends BattleCommon +{ + public BattleCounterAttack(Factory factory) + { + super(factory); + name = "Counterattack"; + mapType = Factory.MapType.MAP_B; + } + + @Override + public Position getHudPosition(Player player) + { + return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); + } + + @Override + public Player getPlayer() + { + if (!gePlayer.isDeploymentDone()) + return gePlayer; + if (!usPlayer.isDeploymentDone()) + return usPlayer; + if (gePlayer.getTurnDone() == usPlayer.getTurnDone()) + return gePlayer; + return usPlayer; + } + + public Player checkVictory(Ctrl ctrl) + { + if (ctrl.opponent.unitsLeft() == 0) + return ctrl.player; + + if (gePlayer.withdrawed() >= 3) + return gePlayer; + + if ((ctrl.player.getTurnDone() < 9) || (ctrl.opponent.getTurnDone() < 9)) + return null; + + return usPlayer; + } + + @Override + public boolean getReinforcement(Ctrl ctrl, Map map) + { + if (ctrl.player.is(Army.GE)) + return false; + if (ctrl.player.getCurrentTurn() != 5) + return false; + + // hex row 1 + Zone usEntry = new Zone(map, 9); + usEntry.allowedMoves = (Orientation.SOUTH.s | Orientation.SOUTH_EAST.s | Orientation.SOUTH_WEST.s); + usEntry.add(map.getHex(9, 0)); + usEntry.add(map.getHex(9, 1)); + usEntry.add(map.getHex(10, 2)); + usEntry.add(map.getHex(10, 3)); + usEntry.add(map.getHex(11, 4)); + usEntry.add(map.getHex(11, 5)); + usEntry.add(map.getHex(12, 6)); + usEntry.add(map.getHex(12, 7)); + usEntry.add(map.getHex(13, 8)); + addEntryZone(usEntry); + + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_PRIEST); + + return true; + } + + @Override + public void setup(Ctrl ctrl, Map map) + { + // hex row 1 + Zone geExit = new Zone(map, 9); + geExit.orientation = Orientation.NORTH; + geExit.add(map.getHex(9, 0)); + geExit.add(map.getHex(9, 1)); + geExit.add(map.getHex(10, 2)); + geExit.add(map.getHex(10, 3)); + geExit.add(map.getHex(11, 4)); + geExit.add(map.getHex(11, 5)); + geExit.add(map.getHex(12, 6)); + geExit.add(map.getHex(12, 7)); + geExit.add(map.getHex(13, 8)); + addExitZone(geExit); + + // hex rows 8-9 + Zone geEntry = new Zone(map, 18); + geEntry.orientation = Orientation.NORTH; + for (int i = 0; i < 2; i++) { + geEntry.add(map.getHex((1 + i), 0)); + geEntry.add(map.getHex((1 + i), 1)); + geEntry.add(map.getHex((2 + i), 2)); + geEntry.add(map.getHex((2 + i), 3)); + geEntry.add(map.getHex((3 + i), 4)); + geEntry.add(map.getHex((3 + i), 5)); + geEntry.add(map.getHex((4 + i), 6)); + geEntry.add(map.getHex((4 + i), 7)); + geEntry.add(map.getHex((5 + i), 8)); + } + addEntryZone(geEntry); + + addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV_HQ); + addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV_HQ); + addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_TIGER); + addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_TIGER); + addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_WESPE); + + // hex rows 1-4 + Zone usEntry = new Zone(map, 36); + usEntry.orientation = Orientation.SOUTH; + for (int i = 0; i < 4; i++) { + usEntry.add(map.getHex((6 + i), 0)); + usEntry.add(map.getHex((6 + i), 1)); + usEntry.add(map.getHex((7 + i), 2)); + usEntry.add(map.getHex((7 + i), 3)); + usEntry.add(map.getHex((8 + i), 4)); + usEntry.add(map.getHex((8 + i), 5)); + usEntry.add(map.getHex((9 + i), 6)); + usEntry.add(map.getHex((9 + i), 7)); + usEntry.add(map.getHex((10 + i), 8)); + } + addEntryZone(usEntry); + + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); + addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/battles/BattleFrontalAssault.java b/core/src/ch/asynk/creepingarmor/game/battles/BattleFrontalAssault.java new file mode 100644 index 0000000..a7f5726 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/battles/BattleFrontalAssault.java @@ -0,0 +1,124 @@ +package ch.asynk.creepingarmor.game.battles; + +import ch.asynk.creepingarmor.game.Army; +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.HexSet; +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Unit.UnitId; +import ch.asynk.creepingarmor.ui.Position; +import ch.asynk.creepingarmor.engine.Orientation; + +public class BattleFrontalAssault extends BattleCommon +{ + public BattleFrontalAssault(Factory factory) + { + super(factory); + name = "Frontal Assault"; + mapType = Factory.MapType.MAP_A; + } + + + @Override + public Player getPlayer() + { + if (!gePlayer.isDeploymentDone()) { + int n = gePlayer.reinforcement(); + if (n > 4) + return gePlayer; + else { + if (usPlayer.isDeploymentDone()) + return gePlayer; + else + return usPlayer; + } + } + if (gePlayer.getTurnDone() == usPlayer.getTurnDone()) + return usPlayer; + return gePlayer; + } + + @Override + public Position getHudPosition(Player player) + { + return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); + } + + @Override + public boolean deploymentDone(Player player) + { + if (player.isDeploymentDone()) + return true; + return ((player.is(Army.GE) && (gePlayer.reinforcement.size() == 4))); + } + + @Override + public Player checkVictory(Ctrl ctrl) + { + if (ctrl.opponent.unitsLeft() == 0) + return ctrl.player; + + if ((ctrl.player.getTurnDone() < 10) || (ctrl.opponent.getTurnDone() < 10)) + return null; + + if (ctrl.map.objectives.count(Army.US) >= 2) + return usPlayer; + else + return gePlayer; + } + + @Override + public void setup(Ctrl ctrl, Map map) + { + // G9, E6, H4 + map.addObjective(2, 2, Army.NONE); + map.addObjective(6, 4, Army.NONE); + map.addObjective(6, 1, Army.NONE); + + // hex rows E-H + Zone geEntry = new Zone(map, 38); + geEntry.orientation = Orientation.NORTH_WEST; + for (int i = 2; i < 12; i++) + geEntry.add(map.getHex(i, 4)); + for (int i = 2; i < 11; i++) + geEntry.add(map.getHex(i, 3)); + for (int i = 1; i < 11; i++) + geEntry.add(map.getHex(i, 2)); + for (int i = 1; i < 10; i++) + geEntry.add(map.getHex(i, 1)); + addEntryZone(geEntry); + + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); + addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); + addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + + // hex rows A-B + Zone usEntry = new Zone(map, 19); + usEntry.orientation = Orientation.SOUTH_EAST; + for (int i = 4; i < 14; i++) + usEntry.add(map.getHex(i, 8)); + for (int i = 4; i < 13; i++) + usEntry.add(map.getHex(i, 7)); + addEntryZone(usEntry); + + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); + addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_PRIEST); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/battles/BattleHeadToHead.java b/core/src/ch/asynk/creepingarmor/game/battles/BattleHeadToHead.java new file mode 100644 index 0000000..26d2b1d --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/battles/BattleHeadToHead.java @@ -0,0 +1,118 @@ +package ch.asynk.creepingarmor.game.battles; + +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Army; +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.HexSet; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Unit.UnitId; +import ch.asynk.creepingarmor.ui.Position; +import ch.asynk.creepingarmor.engine.Orientation; + +public class BattleHeadToHead extends BattleCommon +{ + private Army firstArmy; + + public BattleHeadToHead(Factory factory) + { + super(factory); + name = "Head To Head"; + firstArmy = ((random.nextInt(2) == 0) ? Army.US : Army.GE); + mapType = Factory.MapType.MAP_A; + } + + @Override + public Player getPlayer() + { + if (gePlayer.getTurnDone() == usPlayer.getTurnDone()) + return ((firstArmy == Army.US) ? usPlayer : gePlayer); + else + return ((firstArmy == Army.US) ? gePlayer : usPlayer); + } + + @Override + public Position getHudPosition(Player player) + { + return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); + } + + @Override + public Player checkVictory(Ctrl ctrl) + { + if (ctrl.opponent.unitsLeft() == 0) + return ctrl.player; + + if ((ctrl.player.getTurnDone() < 10) || (ctrl.opponent.getTurnDone() < 10)) + return null; + + if (ctrl.map.objectives.count(Army.US) >= 2) + return usPlayer; + if (ctrl.map.objectives.count(Army.GE) >= 2) + return gePlayer; + + return null; + } + + @Override + public void setup(Ctrl ctrl, Map map) + { + // end deployment + usPlayer.turnEnd(); + gePlayer.turnEnd(); + + // B6, E6, H4 + map.addObjective(7, 7, Army.NONE); + map.addObjective(6, 4, Army.NONE); + map.addObjective(6, 1, Army.NONE); + + // southern hex row + Zone geEntry = new Zone(map, 9); + geEntry.allowedMoves = (Orientation.NORTH.s | Orientation.NORTH_EAST.s | Orientation.NORTH_WEST.s); + geEntry.add(map.getHex(0, 0)); + geEntry.add(map.getHex(1, 1)); + geEntry.add(map.getHex(1, 2)); + geEntry.add(map.getHex(2, 3)); + geEntry.add(map.getHex(2, 4)); + geEntry.add(map.getHex(3, 5)); + geEntry.add(map.getHex(3, 6)); + geEntry.add(map.getHex(4, 7)); + geEntry.add(map.getHex(4, 8)); + addEntryZone(geEntry); + + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); + addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); + addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + + // northern hex row + Zone usEntry = new Zone(map, 9); + usEntry.allowedMoves = (Orientation.SOUTH.s | Orientation.SOUTH_EAST.s | Orientation.SOUTH_WEST.s); + usEntry.add(map.getHex(9, 0)); + usEntry.add(map.getHex(9, 1)); + usEntry.add(map.getHex(10, 2)); + usEntry.add(map.getHex(10, 3)); + usEntry.add(map.getHex(11, 4)); + usEntry.add(map.getHex(11, 5)); + usEntry.add(map.getHex(12, 6)); + usEntry.add(map.getHex(12, 7)); + usEntry.add(map.getHex(13, 8)); + addEntryZone(usEntry); + + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); + addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_PRIEST); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/battles/BattleLastStand.java b/core/src/ch/asynk/creepingarmor/game/battles/BattleLastStand.java new file mode 100644 index 0000000..6d7e035 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/battles/BattleLastStand.java @@ -0,0 +1,136 @@ +package ch.asynk.creepingarmor.game.battles; + +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Army; +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.HexSet; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Unit.UnitId; +import ch.asynk.creepingarmor.ui.Position; +import ch.asynk.creepingarmor.engine.Orientation; + +public class BattleLastStand extends BattleCommon +{ + public BattleLastStand(Factory factory) + { + super(factory); + name = "Last Stand"; + mapType = Factory.MapType.MAP_B; + } + + @Override + public Position getHudPosition(Player player) + { + return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); + } + + @Override + public Player getPlayer() + { + if (!gePlayer.isDeploymentDone()) + return gePlayer; + if (!usPlayer.isDeploymentDone()) + return usPlayer; + if (gePlayer.getTurnDone() == usPlayer.getTurnDone()) + return usPlayer; + return gePlayer; + } + + public Player checkVictory(Ctrl ctrl) + { + if (ctrl.opponent.unitsLeft() == 0) + return ctrl.player; + + if ((ctrl.player.getTurnDone() < 8) || (ctrl.opponent.getTurnDone() < 8)) + return null; + + int gePoints = usPlayer.casualties(); + int usPoints = gePlayer.casualties(); + usPoints += ctrl.map.objectives.count(Army.US); + for (Unit unit : gePlayer.casualties) { + if (unit.isAce()) + usPoints += 1; + } + + if (usPoints > gePoints) + return usPlayer; + else + return gePlayer; + } + + @Override + public void setup(Ctrl ctrl, Map map) + { + // A7, E6, F6, G10 + map.addObjective(7, 8, Army.NONE); + map.addObjective(6, 4, Army.NONE); + map.addObjective(5, 3, Army.NONE); + map.addObjective(1, 2, Army.NONE); + + // 1 hex of E7 + Zone geEntry = new Zone(map, 7); + geEntry.orientation = Orientation.NORTH; + geEntry.add(map.getHex(5, 5)); + geEntry.add(map.getHex(4, 4)); + geEntry.add(map.getHex(4, 3)); + geEntry.add(map.getHex(5, 3)); + geEntry.add(map.getHex(6, 4)); + geEntry.add(map.getHex(6, 5)); + geEntry.add(map.getHex(5, 4)); + addEntryZone(geEntry); + + addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER, true); + addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); + addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); + + // hex rows 7-10 + geEntry = new Zone(map, 32); + geEntry.orientation = Orientation.NORTH; + for (int i = 0; i < 4; i++) { + geEntry.add(map.getHex(i, 0)); + geEntry.add(map.getHex((i + 1), 2)); + geEntry.add(map.getHex((i + 2), 4)); + geEntry.add(map.getHex((i + 3), 6)); + geEntry.add(map.getHex((i + 4), 8)); + } + for (int i = 0; i < 3; i++) { + geEntry.add(map.getHex((i + 1), 1)); + geEntry.add(map.getHex((i + 2), 3)); + geEntry.add(map.getHex((i + 3), 5)); + geEntry.add(map.getHex((i + 4), 7)); + } + addEntryZone(geEntry); + + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_WESPE); + + // hex rows hex row 1 + E2 + C2 + Zone usEntry = new Zone(map, 11); + usEntry.orientation = Orientation.SOUTH; + usEntry.add(map.getHex(9, 0)); + usEntry.add(map.getHex(9, 1)); + usEntry.add(map.getHex(10, 2)); + usEntry.add(map.getHex(10, 3)); + usEntry.add(map.getHex(11, 4)); + usEntry.add(map.getHex(11, 5)); + usEntry.add(map.getHex(12, 6)); + usEntry.add(map.getHex(12, 7)); + usEntry.add(map.getHex(13, 8)); + usEntry.add(map.getHex(10, 4)); + usEntry.add(map.getHex(11, 6)); + addEntryZone(usEntry); + + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); + addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/battles/BattleNightAction.java b/core/src/ch/asynk/creepingarmor/game/battles/BattleNightAction.java new file mode 100644 index 0000000..965327a --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/battles/BattleNightAction.java @@ -0,0 +1,153 @@ +package ch.asynk.creepingarmor.game.battles; + +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Army; +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.HexSet; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Unit.UnitId; +import ch.asynk.creepingarmor.ui.Position; +import ch.asynk.creepingarmor.engine.Orientation; +import ch.asynk.creepingarmor.engine.Meteorology; + +public class BattleNightAction extends BattleCommon +{ + public BattleNightAction(Factory factory) + { + super(factory); + name = "Night Action"; + mapType = Factory.MapType.MAP_B; + } + + @Override + public Position getHudPosition(Player player) + { + return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); + } + + @Override + public Player getPlayer() + { + if (!gePlayer.isDeploymentDone() || gePlayer.getCurrentTurn() == 1) + return gePlayer; + if (gePlayer.getTurnDone() > usPlayer.getTurnDone()) + return usPlayer; + return gePlayer; + } + + private boolean isClear(Map map, int col, int row) + { + Hex hex = map.getHex(col, row); + Unit unit = hex.getUnit(); + if ((unit != null) && unit.is(Army.GE)) { + map.selectHex(hex); + return false; + } + map.showMove(hex); + return true; + } + + public Player checkVictory(Ctrl ctrl) + { + if (ctrl.opponent.unitsLeft() == 0) + return ctrl.player; + + if ((ctrl.player.getTurnDone() < 9) || (ctrl.opponent.getTurnDone() < 9)) + return null; + + Map map = ctrl.map; + boolean clear = true; + clear &= isClear(map, 4, 8); + clear &= isClear(map, 5, 8); + clear &= isClear(map, 6, 8); + clear &= isClear(map, 7, 8); + clear &= isClear(map, 8, 8); + clear &= isClear(map, 8, 7); + clear &= isClear(map, 8, 6); + boolean upLeft = clear; + clear = true; + clear &= isClear(map, 8, 6); + clear &= isClear(map, 9, 6); + clear &= isClear(map, 10, 6); + clear &= isClear(map, 11, 6); + clear &= isClear(map, 12, 6); + boolean upRight = clear; + clear = true; + clear &= isClear(map, 1, 2); + clear &= isClear(map, 2, 3); + clear &= isClear(map, 3, 3); + clear &= isClear(map, 4, 3); + clear &= isClear(map, 5, 3); + clear &= isClear(map, 6, 4); + clear &= isClear(map, 7, 4); + clear &= isClear(map, 8, 4); + boolean bottomLeft = clear; + clear &= isClear(map, 8, 4); + clear &= isClear(map, 9, 4); + clear &= isClear(map, 10, 4); + clear &= isClear(map, 11, 4); + clear = true; + boolean bottomRight = clear; + // clear &= isClear(map, 8, 6); + // clear &= isClear(map, 8, 5); + // clear &= isClear(map, 8, 4); + // clear = true; + // boolean link = clear; + + if ((!upLeft || !upRight) && (!bottomLeft || !bottomRight)) + return gePlayer; + return usPlayer; + } + + @Override + public void setup(Ctrl ctrl, Map map) + { + map.meteorology.day = Meteorology.Day.NIGHT; + + // hex row I + Zone geEntry = new Zone(map, 10); + geEntry.orientation = Orientation.NORTH_EAST; + for (int i = 0; i < 10; i++) + geEntry.add(map.getHex(i, 0)); + addEntryZone(geEntry); + + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); + addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); + addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_INFANTRY); + addReinforcement(gePlayer, geEntry, UnitId.GE_INFANTRY); + + // hex rows A-B + Zone usEntry = new Zone(map, 19); + usEntry.orientation = Orientation.SOUTH; + for (int i = 0; i < 10; i++) { + usEntry.add(map.getHex((4 + i), 8)); + usEntry.add(map.getHex((3 + i), 6)); + usEntry.add(map.getHex((2 + i), 4)); + usEntry.add(map.getHex((1 + i), 2)); + } + for (int i = 0; i < 9; i++) { + usEntry.add(map.getHex((4 + i), 7)); + usEntry.add(map.getHex((3 + i), 5)); + usEntry.add(map.getHex((2 + i), 3)); + } + addEntryZone(usEntry); + + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); + addReinforcement(usPlayer, usEntry, UnitId.US_AT_GUN); + addReinforcement(usPlayer, usEntry, UnitId.US_INFANTRY); + addReinforcement(usPlayer, usEntry, UnitId.US_INFANTRY); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/battles/BattleStabToTheFlank.java b/core/src/ch/asynk/creepingarmor/game/battles/BattleStabToTheFlank.java new file mode 100644 index 0000000..d2d1457 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/battles/BattleStabToTheFlank.java @@ -0,0 +1,143 @@ +package ch.asynk.creepingarmor.game.battles; + +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Army; +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.HexSet; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Unit.UnitId; +import ch.asynk.creepingarmor.ui.Position; +import ch.asynk.creepingarmor.engine.Orientation; + +public class BattleStabToTheFlank extends BattleCommon +{ + public BattleStabToTheFlank(Factory factory) + { + super(factory); + name = "Stab To The Flank"; + mapType = Factory.MapType.MAP_B; + } + + @Override + public Position getHudPosition(Player player) + { + return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); + } + + @Override + public Player getPlayer() + { + if (!usPlayer.isDeploymentDone() || usPlayer.getCurrentTurn() == 1) + return usPlayer; + if (usPlayer.getTurnDone() > gePlayer.getTurnDone()) + return gePlayer; + return usPlayer; + } + + public Player checkVictory(Ctrl ctrl) + { + if (ctrl.opponent.unitsLeft() == 0) + return ctrl.player; + + if ((ctrl.player.getTurnDone() < 9) || (ctrl.opponent.getTurnDone() < 9)) + return null; + + int gePoints = usPlayer.casualties(); + int usPoints = gePlayer.casualties(); + usPoints += ctrl.map.objectives.count(Army.US); + + int withdrawed = usPlayer.withdrawed(); + if (withdrawed == 0) + gePoints += 1; + else + usPoints += withdrawed; + + if (usPoints > gePoints) + return usPlayer; + else + return gePlayer; + } + + @Override + public boolean getReinforcement(Ctrl ctrl, Map map) + { + if (ctrl.player.is(Army.US)) + return false; + if (ctrl.player.getCurrentTurn() != 3) + return false; + + // hex rows I + Zone geEntry = new Zone(map, 9); + geEntry.allowedMoves = (Orientation.SOUTH_WEST.s | Orientation.NORTH_WEST.s); + for (int i = 0; i < 10; i++) + geEntry.add(map.getHex(i, 0)); + addEntryZone(geEntry); + + addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER, true); + + return true; + } + + @Override + public void setup(Ctrl ctrl, Map map) + { + // F6, E6 + map.addHoldObjective(5, 3, Army.NONE); + map.addObjective(6, 4, Army.NONE); + + // hex rows D-I + Zone geEntry = new Zone(map, 57); + geEntry.orientation = Orientation.NORTH; + for (int i = 3; i < 12; i++) + geEntry.add(map.getHex(i, 5)); + for (int i = 2; i < 12; i++) + geEntry.add(map.getHex(i, 4)); + for (int i = 2; i < 11; i++) + geEntry.add(map.getHex(i, 3)); + for (int i = 1; i < 11; i++) + geEntry.add(map.getHex(i, 2)); + for (int i = 1; i < 10; i++) + geEntry.add(map.getHex(i, 1)); + for (int i = 0; i < 10; i++) + geEntry.add(map.getHex(i, 0)); + + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); + addReinforcement(gePlayer, geEntry, UnitId.GE_AT_GUN); + addReinforcement(gePlayer, geEntry, UnitId.GE_INFANTRY); + + // hex row I + Zone usExit = new Zone(map, 10); + usExit.orientation = Orientation.NORTH_EAST; + for (int i = 0; i < 10; i++) + geEntry.add(map.getHex(i, 0)); + addExitZone(usExit); + + // hex rows A-B + Zone usEntry = new Zone(map, 19); + usEntry.orientation = Orientation.SOUTH_EAST; + for (int i = 4; i < 13; i++) { + usEntry.add(map.getHex(i, 8)); + usEntry.add(map.getHex(i, 7)); + } + usEntry.add(map.getHex(13, 8)); + addEntryZone(usEntry); + + addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN_HQ); + addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN); + addReinforcement(usPlayer, usEntry, usExit, UnitId.US_INFANTRY); + addReinforcement(usPlayer, usEntry, usExit, UnitId.US_INFANTRY); + addReinforcement(usPlayer, usEntry, usExit, UnitId.US_PRIEST); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/battles/BattleTest.java b/core/src/ch/asynk/creepingarmor/game/battles/BattleTest.java new file mode 100644 index 0000000..6c1d6c1 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/battles/BattleTest.java @@ -0,0 +1,128 @@ +package ch.asynk.creepingarmor.game.battles; + +import ch.asynk.creepingarmor.game.Army; +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.HexSet; +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Unit.UnitId; +import ch.asynk.creepingarmor.ui.Position; +import ch.asynk.creepingarmor.engine.Orientation; + +public class BattleTest extends BattleCommon +{ + private Zone usExit; + + public BattleTest(Factory factory) + { + super(factory); + name = "*** Test ***"; + mapType = Factory.MapType.MAP_B; + } + + @Override + public Player getPlayer() + { + if (!gePlayer.isDeploymentDone()) + return gePlayer; + + if (gePlayer.getTurnDone() == usPlayer.getTurnDone()) + return usPlayer; + return gePlayer; + } + + @Override + public Position getHudPosition(Player player) + { + return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); + } + + @Override + public Player checkVictory(Ctrl ctrl) + { + if (usPlayer.getTurnDone() > 2) + return usPlayer; + return null; + } + + @Override + public boolean getReinforcement(Ctrl ctrl, Map map) + { + if (ctrl.player.is(Army.GE)) + return false; + if (ctrl.player.getCurrentTurn() != 2) + return false; + + Zone usEntry = new Zone(map, 1); + usEntry.allowedMoves = (Orientation.SOUTH.s | Orientation.SOUTH_EAST.s | Orientation.SOUTH_WEST.s); + usEntry.add(map.getHex(12, 6)); + addEntryZone(usEntry); + addReinforcement(usPlayer, usEntry, usExit, UnitId.US_WOLVERINE); + + return true; + } + + private Unit setUnit(Map map, Player player, UnitId unitId, int col, int row, Orientation orientation, Zone exitZone) + { + return setUnit(map, player, unitId, col, row, orientation, false, exitZone); + } + + private Unit setUnit(Map map, Player player, UnitId unitId, int col, int row, Orientation orientation, boolean ace, Zone exitZone) + { + Unit u = factory.getUnit(unitId); + u.setAce(ace); + if (exitZone != null) + unitExit.put(u, exitZone); + map.setOnBoard(u, map.getHex(col, row), orientation); + return u; + } + + @Override + public void setup(Ctrl ctrl, Map map) + { + map.addObjective(6, 4, Army.NONE); + map.addHoldObjective(5, 3, Army.NONE); + map.addObjective(3, 4, Army.NONE); + map.addHoldObjective(3, 3, Army.NONE); + + ctrl.player = gePlayer; + setUnit(map, gePlayer, UnitId.GE_WESPE, 5, 8, Orientation.NORTH, null); + setUnit(map, gePlayer, UnitId.GE_TIGER, 6, 4, Orientation.NORTH, null); + setUnit(map, gePlayer, UnitId.GE_PANZER_IV, 4, 5, Orientation.NORTH_WEST, null); + setUnit(map, gePlayer, UnitId.GE_INFANTRY, 1, 2, Orientation.NORTH_WEST, null); + setUnit(map, gePlayer, UnitId.GE_KINGTIGER, 1, 1, Orientation.NORTH_WEST, null); + Zone geEntry = new Zone(map, 6); + geEntry.orientation = Orientation.NORTH; + geEntry.add(map.getHex(1, 2)); + geEntry.add(map.getHex(1, 1)); + geEntry.add(map.getHex(3, 3)); + geEntry.add(map.getHex(3, 4)); + geEntry.add(map.getHex(4, 0)); + geEntry.add(map.getHex(5, 0)); + addEntryZone(geEntry); + addReinforcement(gePlayer, geEntry, UnitId.GE_AT_GUN); + + usExit = new Zone(map, 9); + usExit.orientation = Orientation.NORTH; + usExit.add(map.getHex(11, 4)); + usExit.add(map.getHex(11, 5)); + usExit.add(map.getHex(12, 6)); + addExitZone(usExit); + + ctrl.player = usPlayer; + usPlayer.casualty(factory.getUnit(UnitId.US_SHERMAN_HQ)); + setUnit(map, usPlayer, UnitId.US_PRIEST, 10, 8, Orientation.SOUTH_EAST, usExit); + setUnit(map, usPlayer, UnitId.US_SHERMAN, 7, 3, Orientation.SOUTH, true, usExit); + setUnit(map, usPlayer, UnitId.US_SHERMAN_HQ, 8, 4, Orientation.SOUTH, usExit); + setUnit(map, usPlayer, UnitId.US_WOLVERINE, 9, 7, Orientation.SOUTH_EAST, usExit); + setUnit(map, usPlayer, UnitId.US_PERSHING, 6, 6, Orientation.NORTH_EAST, usExit); + setUnit(map, usPlayer, UnitId.US_INFANTRY, 5, 3, Orientation.NORTH_WEST, usExit); + setUnit(map, usPlayer, UnitId.US_AT_GUN, 10, 3, Orientation.SOUTH, usExit); + usPlayer.turnEnd(); + map.init(); + map.turnDone(); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/battles/Factory.java b/core/src/ch/asynk/creepingarmor/game/battles/Factory.java new file mode 100644 index 0000000..4af2536 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/battles/Factory.java @@ -0,0 +1,192 @@ +package ch.asynk.creepingarmor.game.battles; + +import com.badlogic.gdx.utils.Disposable; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; + +import ch.asynk.creepingarmor.CreepingArmor; +import ch.asynk.creepingarmor.engine.Board; +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.Army; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Unit.UnitId; +import ch.asynk.creepingarmor.game.Unit.UnitType; +import ch.asynk.creepingarmor.game.Battle; +import ch.asynk.creepingarmor.game.battles.BattleHeadToHead; +import ch.asynk.creepingarmor.game.battles.BattleFrontalAssault; +import ch.asynk.creepingarmor.game.battles.BattleLastStand; +import ch.asynk.creepingarmor.game.battles.BattleCounterAttack; +import ch.asynk.creepingarmor.game.battles.BattleStabToTheFlank; +import ch.asynk.creepingarmor.game.battles.BattleNightAction; +import ch.asynk.creepingarmor.game.battles.BattleTest; + +public class Factory implements Board.TileBuilder, Disposable +{ + public enum MapType + { + MAP_A, + MAP_B + } + + public enum Scenarios + { + FAKE + } + + public boolean assetsLoaded; + public TextureAtlas hudAtlas; + public TextureAtlas pawnsAtlas; + public TextureAtlas pawnOverlaysAtlas; + public TextureAtlas tileOverlaysAtlas; + public Battle battles[]; + private final CreepingArmor game; + + public Factory(final CreepingArmor game) + { + this.game = game; + this.assetsLoaded = false; + battles = new Battle[] { + new BattleHeadToHead(this), + new BattleFrontalAssault(this), + new BattleLastStand(this), + new BattleCounterAttack(this), + new BattleStabToTheFlank(this), + new BattleNightAction(this), + new BattleTest(this), + }; + } + + public void assetsLoaded() + { + if (assetsLoaded) return; + int i = game.config.graphics.i; + this.hudAtlas = game.manager.get("data/hud.atlas", TextureAtlas.class); + this.tileOverlaysAtlas = game.manager.get("data/hex-overlays.atlas", TextureAtlas.class); + this.pawnsAtlas = game.manager.get(String.format("data/units%d.atlas", i), TextureAtlas.class); + this.pawnOverlaysAtlas = game.manager.get(String.format("data/unit-overlays%d.atlas", i), TextureAtlas.class); + this.assetsLoaded = true; + } + + @Override + public void dispose() + { + if (!assetsLoaded) return; + hudAtlas.dispose(); + pawnsAtlas.dispose(); + pawnOverlaysAtlas.dispose(); + tileOverlaysAtlas.dispose(); + this.assetsLoaded = false; + } + + private Board.Config config() + { + Board.Config cfg = new Board.Config(); + cfg.cols = 10; + cfg.rows = 9; + cfg.x0 = 86; + cfg.y0 = 182; + cfg.w = 189; + cfg.dw = 94; + cfg.s = 110; + cfg.dh = 53.6f; + cfg.h = cfg.s + cfg.dh; + cfg.slope = (cfg.dh / (float) cfg.dw); + + return cfg; + } + + public Map getMap(MapType t) + { + Board.Config cfg = config(); + + Map m = null; + switch(t) { + case MAP_A: + m = new MapA(game, config(), "data/map_a.png"); + break; + case MAP_B: + m = new MapB(game, config(), "data/map_b.png"); + break; + } + + return m; + } + + public Player getPlayer(Army army) + { + if (army == Army.US) + return new Player(game, Army.US, 10); + else + return new Player(game, Army.GE, 10); + } + + public Unit getUnit(UnitId id) + { + Unit u = null; + UnitType ut = UnitType.HARD_TARGET; + UnitType utHq = UnitType.HARD_TARGET_HQ; + switch(id) { + case GE_AT_GUN: + ut = UnitType.AT_GUN; + u = new Unit(Army.GE, id, ut, 3, 8, 9, 1, "ge-at-gun", "ge-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case GE_INFANTRY: + ut = UnitType.INFANTRY; + u = new Unit(Army.GE, id, ut, 1, 7, 10, 1, "ge-infantry", "ge-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case GE_KINGTIGER: + u = new Unit(Army.GE, id, ut, 3, 12, 1, "ge-kingtiger", "ge-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case GE_PANZER_IV: + u = new Unit(Army.GE, id, ut, 2, 9, 2, "ge-panzer-iv", "ge-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case GE_PANZER_IV_HQ: + u = new Unit(Army.GE, id, utHq, 2, 9, 2, "ge-panzer-iv", "ge-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case GE_TIGER: + u = new Unit(Army.GE, id, ut, 3, 11, 1, "ge-tiger", "ge-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case GE_WESPE: + ut = UnitType.ARTILLERY; + u = new Unit(Army.GE, id, ut, 5, 8, 1, "ge-wespe", "ge-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case US_AT_GUN: + ut = UnitType.AT_GUN; + u = new Unit(Army.US, id, ut, 1, 7, 10, 1, "us-at-gun", "us-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case US_INFANTRY: + ut = UnitType.INFANTRY; + u = new Unit(Army.US, id, ut, 1, 7, 10, 1, "us-infantry", "us-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case US_PERSHING: + u = new Unit(Army.US, id, ut, 3, 10, 2, "us-pershing", "us-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case US_PERSHING_HQ: + u = new Unit(Army.US, id, utHq, 3, 10, 2, "us-pershing", "us-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case US_PRIEST: + ut = UnitType.ARTILLERY; + u = new Unit(Army.US, id, ut, 5, 8, 1, "us-priest", "us-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case US_SHERMAN: + u = new Unit(Army.US, id, ut, 2, 9, 2, "us-sherman", "us-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case US_SHERMAN_HQ: + u = new Unit(Army.US, id, utHq, 2, 9, 2, "us-sherman", "us-head", pawnsAtlas, pawnOverlaysAtlas); + break; + case US_WOLVERINE: + u = new Unit(Army.US, id, ut, 3, 8, 3, "us-wolverine", "us-head", pawnsAtlas, pawnOverlaysAtlas); + break; + } + + return u; + } + + public Hex getNewTile(float x, float y, int col, int row, boolean offmap) + { + Hex hex = new Hex(x, y, col, row, tileOverlaysAtlas); + if (offmap) hex.terrain = Hex.Terrain.OFFMAP; + return hex; + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/battles/MapA.java b/core/src/ch/asynk/creepingarmor/game/battles/MapA.java new file mode 100644 index 0000000..11c2ddd --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/battles/MapA.java @@ -0,0 +1,77 @@ +package ch.asynk.creepingarmor.game.battles; + +import ch.asynk.creepingarmor.CreepingArmor; +import ch.asynk.creepingarmor.engine.Board; +import ch.asynk.creepingarmor.engine.Orientation; +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Hex; + +public class MapA extends Map +{ + public MapA(final CreepingArmor game, Board.Config cfg, String textureName) + { + super(game, cfg, textureName); + } + + @Override + protected void setup() + { + getHex(5, 1).terrain = Hex.Terrain.HILLS; + getHex(7, 3).terrain = Hex.Terrain.HILLS; + getHex(7, 8).terrain = Hex.Terrain.HILLS; + getHex(8, 8).terrain = Hex.Terrain.HILLS; + + getHex(5, 0).terrain = Hex.Terrain.WOODS; + getHex(6, 0).terrain = Hex.Terrain.WOODS; + getHex(3, 3).terrain = Hex.Terrain.WOODS; + getHex(4, 3).terrain = Hex.Terrain.WOODS; + getHex(10, 7).terrain = Hex.Terrain.WOODS; + getHex(11, 7).terrain = Hex.Terrain.WOODS; + getHex(11, 8).terrain = Hex.Terrain.WOODS; + + getHex(6, 1).terrain = Hex.Terrain.TOWN; + getHex(2, 2).terrain = Hex.Terrain.TOWN; + getHex(6, 4).terrain = Hex.Terrain.TOWN; + getHex(10, 5).terrain = Hex.Terrain.TOWN; + getHex(7, 7).terrain = Hex.Terrain.TOWN; + getHex(4, 6).terrain = Hex.Terrain.TOWN; + + getHex(10, 1).terrain = Hex.Terrain.OFFMAP; + getHex(11, 3).terrain = Hex.Terrain.OFFMAP; + getHex(12, 5).terrain = Hex.Terrain.OFFMAP; + getHex(13, 7).terrain = Hex.Terrain.OFFMAP; + + int N = Orientation.NORTH.s; + int S = Orientation.SOUTH.s; + int NE = Orientation.NORTH_EAST.s; + int NW = Orientation.NORTH_WEST.s; + int SE = Orientation.SOUTH_EAST.s; + int SW = Orientation.SOUTH_WEST.s; + + getHex(6, 1).roads = (NW | SW); + for (int i = 1; i < 11; i++) { + if (i == 6) + getHex(i, 2).roads = (NE | S | SW); + else if (i == 7) + getHex(i, 2).roads = (N | SE); + else + getHex(i, 2).roads = (N | S); + } + getHex(6, 3).roads = (NE | SW); + getHex(6, 4).roads = (N | NE | SW); + getHex(7, 4).roads = (N | S); + getHex(8, 4).roads = (NW | S); + getHex(6, 5).roads = (NE | SW); + getHex(8, 5).roads = (N | SW); + getHex(9, 5).roads = (N | S | NE); + getHex(10, 5).roads = (N | S); + getHex(11, 5).roads = (N | S); + getHex(3, 6).roads = (N | S); + getHex(4, 6).roads = (N | S); + getHex(5, 6).roads = (N | S); + getHex(6, 6).roads = (NE | NW | S); + getHex(8, 6).roads = (NE | SW); + getHex(7, 7).roads = (N | SE); + getHex(8, 7).roads = (NE | S); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/battles/MapB.java b/core/src/ch/asynk/creepingarmor/game/battles/MapB.java new file mode 100644 index 0000000..1248cea --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/battles/MapB.java @@ -0,0 +1,75 @@ +package ch.asynk.creepingarmor.game.battles; + +import ch.asynk.creepingarmor.CreepingArmor; +import ch.asynk.creepingarmor.engine.Board; +import ch.asynk.creepingarmor.engine.Orientation; +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Hex; + +public class MapB extends Map +{ + public MapB(final CreepingArmor game, Board.Config cfg, String textureName) + { + super(game, cfg, textureName); + } + + @Override + protected void setup() + { + getHex(4, 0).terrain = Hex.Terrain.HILLS; + getHex(5, 0).terrain = Hex.Terrain.HILLS; + getHex(1, 1).terrain = Hex.Terrain.HILLS; + getHex(9, 7).terrain = Hex.Terrain.HILLS; + getHex(10, 7).terrain = Hex.Terrain.HILLS; + + getHex(3, 0).terrain = Hex.Terrain.WOODS; + getHex(6, 0).terrain = Hex.Terrain.WOODS; + getHex(8, 1).terrain = Hex.Terrain.WOODS; + getHex(9, 2).terrain = Hex.Terrain.WOODS; + getHex(4, 5).terrain = Hex.Terrain.WOODS; + getHex(5, 6).terrain = Hex.Terrain.WOODS; + getHex(6, 6).terrain = Hex.Terrain.WOODS; + getHex(11, 8).terrain = Hex.Terrain.WOODS; + + getHex(1, 2).terrain = Hex.Terrain.TOWN; + getHex(5, 3).terrain = Hex.Terrain.TOWN; + getHex(6, 4).terrain = Hex.Terrain.TOWN; + getHex(7, 8).terrain = Hex.Terrain.TOWN; + + getHex(10, 1).terrain = Hex.Terrain.OFFMAP; + getHex(11, 3).terrain = Hex.Terrain.OFFMAP; + getHex(12, 5).terrain = Hex.Terrain.OFFMAP; + getHex(13, 7).terrain = Hex.Terrain.OFFMAP; + + int N = Orientation.NORTH.s; + int S = Orientation.SOUTH.s; + int NE = Orientation.NORTH_EAST.s; + int NW = Orientation.NORTH_WEST.s; + int SE = Orientation.SOUTH_EAST.s; + int SW = Orientation.SOUTH_WEST.s; + + getHex(1, 2).roads = (S | NW); + getHex(2, 3).roads = (SE | N); + getHex(3, 3).roads = (S | N); + getHex(4, 3).roads = (S | N); + getHex(5, 3).roads = (S | NW); + getHex(6, 4).roads = (SE | N); + getHex(7, 4).roads = (S | N); + getHex(8, 4).roads = (S | SW | N); + getHex(9, 4).roads = (S | N); + getHex(10, 4).roads = (S | N); + getHex(11, 4).roads = (S | N); + getHex(4, 8).roads = (S | N); + getHex(5, 8).roads = (S | N); + getHex(6, 8).roads = (S | N); + getHex(7, 8).roads = (S | N); + getHex(8, 8).roads = (S | NE); + getHex(8, 7).roads = (SW | NE); + getHex(8, 6).roads = (SW | NE | N); + getHex(8, 5).roads = (SW | NE); + getHex(9, 6).roads = (S | N); + getHex(10, 6).roads = (S | N); + getHex(11, 6).roads = (S | N); + getHex(12, 6).roads = (S | N); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/hud/ActionButtons.java b/core/src/ch/asynk/creepingarmor/game/hud/ActionButtons.java new file mode 100644 index 0000000..1e85a5e --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/hud/ActionButtons.java @@ -0,0 +1,185 @@ +package ch.asynk.creepingarmor.game.hud; + +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.State.StateType; +import ch.asynk.creepingarmor.ui.Widget; +import ch.asynk.creepingarmor.ui.Bg; +import ch.asynk.creepingarmor.ui.Position; + +public class ActionButtons extends Widget +{ + public static int PADDING = 5; + + private final Ctrl ctrl; + + public enum Buttons { + NONE(-1, 0), + PROMOTE(0, 1), + DONE(1, 2), + ABORT(2, 4), + LAST(3, 0); + + Buttons(int i, int b) + { + this.i = i; + this.b = b; + } + + public int i; + public int b; + } + + private Sprite bg; + private int idx; + private Bg buttons []; + private StateType states []; + + public ActionButtons(Ctrl ctrl, TextureAtlas uiAtlas, TextureAtlas hudAtlas) + { + this.bg = new Sprite(uiAtlas.findRegion("disabled")); + this.ctrl = ctrl; + this.visible = false; + this.position = Position.BOTTOM_RIGHT; + this.idx = Buttons.NONE.i; + + + this.buttons = new Bg[Buttons.LAST.i]; + this.buttons[Buttons.DONE.i] = new Bg(uiAtlas.findRegion("ok")); + this.buttons[Buttons.ABORT.i] = new Bg(uiAtlas.findRegion("cancel")); + this.buttons[Buttons.PROMOTE.i] = new Bg(hudAtlas.findRegion("promote")); + + this.states = new StateType[Buttons.LAST.i]; + this.states[Buttons.DONE.i] = StateType.DONE; + this.states[Buttons.ABORT.i] = StateType.ABORT; + this.states[Buttons.PROMOTE.i] = StateType.PROMOTE; + } + + @Override + public void dispose() + { + for (int i = 0; i < Buttons.LAST.i; i++) + buttons[i].dispose(); + } + + public void update(Position position) + { + setPosition(position); + updatePosition(); + } + + public void updatePosition() + { + if (!visible) return; + float dx = (position.getX(rect.width) - rect.x); + float dy = (position.getY(rect.height) - rect.y); + translate(dx, dy); + for (int i = 0; i < Buttons.LAST.i; i++) + buttons[i].translate(dx, dy); + } + + public void hide() + { + for (int i = 0; i < Buttons.LAST.i; i++) + buttons[i].visible = false; + this.visible = false; + } + + private float setButton(Bg btn, float x, float y) + { + btn.visible = true; + btn.setPosition(x, y); + return (y + btn.getHeight() + PADDING); + } + + public void show(int bits) + { + int b = bits; + int count = 0; + while (b > 0) { + if ((b & 0x01) == 1) + count += 1; + b /= 2; + } + + if (count == 0) { + this.visible = false; + return; + } + + rect.width = (buttons[0].getWidth() + (2 * PADDING)); + rect.height = ((buttons[0].getHeight() * count) + ((count + 1) * PADDING)); + rect.x = position.getX(rect.width); + rect.y = position.getY(rect.height); + + float x = (rect.x + PADDING); + float y = (rect.y + PADDING); + + b = 1; + for (int i = 0; i < Buttons.LAST.i; i++) { + if ((bits & b) == b) + y = setButton(buttons[i], x, y); + else + buttons[i].visible = false; + b *= 2; + } + + this.visible = true; + } + + public boolean touchDown(float x, float y) + { + idx = Buttons.NONE.i; + + if (!super.hit(x,y)) + return false; + + for (int i = 0; i < Buttons.LAST.i; i++) { + if (buttons[i].hit(x, y)) { + idx = i; + break; + } + } + + return (idx != Buttons.NONE.i); + } + + public boolean touchUp(float x, float y) + { + if (idx == Buttons.NONE.i) + return false; + + boolean ret = false; + + if (super.hit(x,y) && buttons[idx].hit(x, y)) { + ctrl.setState(states[idx]); + ret = true; + } + + idx = Buttons.NONE.i; + + return ret; + } + + @Override + public void draw(Batch batch) + { + if (!visible) return; + batch.draw(bg, rect.x, rect.y, rect.width, rect.height); + for (int i = 0; i < Buttons.LAST.i; i++) + buttons[i].draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer shapes) + { + if (!visible) return; + super.drawDebug(shapes); + for (int i = 0; i < Buttons.LAST.i; i++) + buttons[i].drawDebug(shapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/hud/EngagementPanel.java b/core/src/ch/asynk/creepingarmor/game/hud/EngagementPanel.java new file mode 100644 index 0000000..5471dfb --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/hud/EngagementPanel.java @@ -0,0 +1,255 @@ +package ch.asynk.creepingarmor.game.hud; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.game.Engagement; +import ch.asynk.creepingarmor.game.Army; +import ch.asynk.creepingarmor.engine.gfx.Animation; +import ch.asynk.creepingarmor.engine.gfx.animations.DiceAnimation; +import ch.asynk.creepingarmor.ui.Bg; +import ch.asynk.creepingarmor.ui.Label; +import ch.asynk.creepingarmor.ui.Patch; +import ch.asynk.creepingarmor.ui.Position; + +public class EngagementPanel extends Patch implements Animation +{ + private enum State { ROLL1, MOVE, ROLL2, RESULT }; + + public static int FLAG_HEIGHT = 24; + public static int OK_OFFSET = 10; + public static int PADDING = 20; + public static int VSPACING = 10; + public static int HSPACING = 5; + public static float MOVE_STEP = 2f; + + private State state; + private boolean reroll; + private float rerollY; + private Sprite usFlag; + private Sprite geFlag; + private Sprite winner; + private Sprite attackImg; + private Sprite defenseImg; + private Label attack; + private Label defense; + private Label attackR; + private Label defenseR; + private Bg okBtn; + private DiceAnimation d1Animation; + private DiceAnimation d2Animation; + private DiceAnimation d3Animation; + private DiceAnimation d4Animation; + + public EngagementPanel(BitmapFont font, TextureAtlas uiAtlas, TextureAtlas hudAtlas) + { + super(uiAtlas.createPatch("typewriter")); + usFlag = new Sprite(hudAtlas.findRegion("us-flag")); + geFlag = new Sprite(hudAtlas.findRegion("ge-flag")); + attackImg = new Sprite(hudAtlas.findRegion("attack")); + defenseImg = new Sprite(hudAtlas.findRegion("defense")); + this.attack = new Label(font); + this.defense = new Label(font); + this.attackR = new Label(font); + this.defenseR = new Label(font); + this.okBtn = new Bg(uiAtlas.findRegion("ok")); + this.visible = false; + this.d1Animation = new DiceAnimation(); + this.d2Animation = new DiceAnimation(); + this.d3Animation = new DiceAnimation(); + this.d4Animation = new DiceAnimation(); + } + + public void updatePosition() + { + if (!visible) return; + float dx = (position.getX(rect.width) - rect.x); + float dy = (position.getY(rect.height) - rect.y); + translate(dx, dy); + winner.translate(dx, dy); + attackImg.translate(dx, dy); + defenseImg.translate(dx, dy); + attack.translate(dx, dy); + defense.translate(dx, dy); + attackR.translate(dx, dy); + defenseR.translate(dx, dy); + okBtn.translate(dx, dy); + d1Animation.translate(dx, dy); + d2Animation.translate(dx, dy); + d3Animation.translate(dx, dy); + d4Animation.translate(dx, dy); + } + + public void show(Engagement e, Position position, float volume) + { + DiceAnimation.initSound(volume); + attack.write(String.format(" + %d + %d =", e.unitCount, e.flankBonus)); + if (e.weatherDefense == 0) + defense.write(String.format("%d + %d =", e.unitDefense, e.terrainDefense)); + else + defense.write(String.format("%d + %d + %d =", e.unitDefense, e.terrainDefense, e.weatherDefense)); + attackR.write(String.format(" %2d", e.attackSum)); + defenseR.write(String.format(" %2d", e.defenseSum)); + if (e.success) + winner = ((e.attacker.getArmy() == Army.US) ? usFlag : geFlag); + else + winner = ((e.attacker.getArmy() == Army.US) ? geFlag : usFlag); + + this.position = position; + placeElements(); + + state = State.ROLL1; + reroll = (e.d3 != 0); + + d1Animation.set(e.d1); + d2Animation.set(e.d2); + if (reroll) { + d3Animation.set(e.d3); + d4Animation.set(e.d4); + } + + visible = true; + } + + private void placeElements() + { + float w = attackR.getWidth(); + float w2 = defenseR.getWidth(); + if (w2 > w) + w = w2; + float height = (okBtn.getHeight() + attackImg.getHeight() + defenseImg.getHeight() + (2 * VSPACING) + (2 * PADDING)); + float width = (attackImg.getWidth() + (2 * d1Animation.getWidth()) + attack.getWidth() + w + (4 * HSPACING) + (2 * PADDING)); + float x = position.getX(width); + float y = position.getY(height); + setPosition(x, y, width, height); + + okBtn.setPosition((x + width - okBtn.getWidth() + OK_OFFSET), (y - OK_OFFSET)); + + x = getX() + PADDING; + y = getY() + PADDING; + winner.setPosition((getX() + (width / 2f) - (winner.getWidth() / 2f)), y); + y += (winner.getHeight() + VSPACING); + + defenseImg.setPosition(x, y); + y = (y + (defenseImg.getHeight() / 2f) - (defense.getHeight() / 2f)); + defenseR.setPosition((getX() + width - w - PADDING), y); + // x += (defenseImg.getWidth() + HSPACING); + defense.setPosition((defenseR.getX() - defense.getWidth() - HSPACING), y); + + x = getX() + PADDING; + y += defenseImg.getHeight() + VSPACING; + attackImg.setPosition(x, y); + x += (attackImg.getWidth() + HSPACING); + d1Animation.setPosition(x, y); + d3Animation.setPosition(x, y); + x += (d1Animation.getWidth() + HSPACING); + d2Animation.setPosition(x, (y)); + d4Animation.setPosition(x, y); + x += (d1Animation.getWidth() + HSPACING); + y = (y + (attackImg.getHeight() / 2f) - (attack.getHeight() / 2f)); + attack.setPosition(x, y); + attackR.setPosition(defenseR.getX(), y); + + rerollY = (d1Animation.getY() + d1Animation.getHeight() + VSPACING); + } + + @Override + public boolean hit(float x, float y) + { + return rect.contains(x, y); + } + + @Override + public boolean animate(float delta) + { + if (!visible) return true; + if (state == State.ROLL1) { + d1Animation.animate(delta); + d2Animation.animate(delta); + if (d1Animation.isDone() && d2Animation.isDone()) { + if (reroll) + state = State.MOVE; + else + state = State.RESULT; + } + } + + if (state == State.MOVE) { + float y = (d1Animation.getY() + MOVE_STEP); + if (y >= rerollY) { + y = rerollY; + state = State.ROLL2; + } + setPosition(getX(), getY(), getWidth(), (y + d1Animation.getHeight() + VSPACING - getY())); + d1Animation.setPosition(d1Animation.getX(), y); + d2Animation.setPosition(d2Animation.getX(), y); + } + + if (state == State.ROLL2) { + if (d1Animation.getY() < rerollY) { + d1Animation.setPosition(d1Animation.getX(), (d1Animation.getY() + d1Animation.getHeight() + VSPACING)); + d2Animation.setPosition(d2Animation.getX(), (d2Animation.getY() + d2Animation.getHeight() + VSPACING)); + } else { + d3Animation.animate(delta); + d4Animation.animate(delta); + if (d3Animation.isDone() && d4Animation.isDone()) + state = State.RESULT; + } + } + + return false; + } + + @Override + public void dispose() + { + super.dispose(); + attack.dispose(); + defense.dispose(); + attackR.dispose(); + defenseR.dispose(); + d1Animation.dispose(); + d2Animation.dispose(); + d3Animation.dispose(); + d4Animation.dispose(); + okBtn.dispose(); + } + + @Override + public void draw(Batch batch) + { + if (!visible) return; + super.draw(batch); + attackImg.draw(batch); + d1Animation.draw(batch); + d2Animation.draw(batch); + if ((state == State.ROLL2) || (reroll && (state == State.RESULT))) { + d3Animation.draw(batch); + d4Animation.draw(batch); + } + attack.draw(batch); + defenseImg.draw(batch); + defense.draw(batch); + defenseR.draw(batch); + okBtn.draw(batch); + if (state == State.RESULT) { + attackR.draw(batch); + winner.draw(batch); + } + } + + @Override + public void drawDebug(ShapeRenderer shapes) + { + if (!visible) return; + super.drawDebug(shapes); + attack.drawDebug(shapes); + defense.drawDebug(shapes); + attackR.drawDebug(shapes); + defenseR.drawDebug(shapes); + okBtn.drawDebug(shapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/hud/PlayerInfo.java b/core/src/ch/asynk/creepingarmor/game/hud/PlayerInfo.java new file mode 100644 index 0000000..fbd843b --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/hud/PlayerInfo.java @@ -0,0 +1,202 @@ +package ch.asynk.creepingarmor.game.hud; + +import com.badlogic.gdx.utils.Disposable; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Animation; +import ch.asynk.creepingarmor.engine.gfx.Drawable; + +import ch.asynk.creepingarmor.game.State.StateType; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.Hud; +import ch.asynk.creepingarmor.game.Army; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.ui.LabelImage; +import ch.asynk.creepingarmor.ui.Position; + +public class PlayerInfo implements Disposable, Drawable, Animation +{ + public static int PADDING = 5; + + private final Ctrl ctrl; + + private Object hit; + + private Sprite flag; + private Sprite usFlag; + private Sprite geFlag; + private LabelImage turns; + private LabelImage aps; + private LabelImage reinforcement; + public UnitDock unitDock; + private Position position; + + public PlayerInfo(Ctrl ctrl, BitmapFont font, TextureAtlas uiAtlas, TextureAtlas hudAtlas) + { + this.ctrl = ctrl; + this.position = Position.MIDDLE_CENTER; + usFlag = new Sprite(hudAtlas.findRegion("us-flag")); + geFlag = new Sprite(hudAtlas.findRegion("ge-flag")); + turns = new LabelImage(hudAtlas.findRegion("turns"), font, 5f); + aps = new LabelImage(hudAtlas.findRegion("aps"), font, 5f); + reinforcement = new LabelImage(hudAtlas.findRegion("reinforcement"), font, 5f); + unitDock = new UnitDock(ctrl, uiAtlas.findRegion("disabled"), hudAtlas.findRegion("reinforcement-selected"), 10f); + } + + @Override + public void dispose() + { + turns.dispose(); + aps.dispose(); + reinforcement.dispose(); + unitDock.dispose(); + } + + public void updatePosition() + { + float dx = (position.getX(usFlag.getWidth()) - usFlag.getX()); + float dy = (position.getY(usFlag.getHeight()) - usFlag.getY()); + usFlag.translate(dx, dy); + geFlag.translate(dx, dy); + turns.translate(dx, dy); + aps.translate(dx, dy); + reinforcement.translate(dx, dy); + unitDock.translate(dx, dy); + } + + public void setPosition(Position position) + { + if (this.position == position) + return; + this.position = position; + + float width = (usFlag.getWidth() + turns.getWidth() + aps.getWidth() + (2 * PADDING)); + float height = (usFlag.getHeight() + reinforcement.getHeight() + (1 * PADDING)); + float x = position.getX(width); + float y = position.getY(height); + + if (position.isLeft()) { + reinforcement.setPosition(x, y); + y += (reinforcement.getHeight() + PADDING); + usFlag.setPosition(x, y); + geFlag.setPosition(x, y); + x += (usFlag.getWidth() + PADDING); + turns.setPosition(x, y); + x += (turns.getWidth() + PADDING); + aps.setPosition(x, y); + } else { + x = (x + width); + reinforcement.setPosition((x - reinforcement.getWidth()), y); + y += (reinforcement.getHeight() + PADDING); + x -= usFlag.getWidth(); + usFlag.setPosition(x, y); + geFlag.setPosition(x, y); + x -= (turns.getWidth() + PADDING); + turns.setPosition(x, y); + x -= (aps.getWidth() + PADDING); + aps.setPosition(x, y); + } + aps.setLabelPosition(Position.TOP_RIGHT); + turns.setLabelPosition(Position.MIDDLE_CENTER); + reinforcement.setLabelPosition(Position.TOP_LEFT); + unitDock.setPosition(position, reinforcement.getY() - PADDING); + } + + public void update(Player player, Position position) + { + unitDock.hide(); + turns.write(String.format("%d", player.getCurrentTurn())); + aps.write(String.format("%d", player.getAp())); + int r = player.reinforcement(); + if (r == 0) { + reinforcement.visible = false; + } else { + reinforcement.visible = true; + reinforcement.write(String.format("%d", r)); + } + + if (player.is(Army.GE)) + flag = geFlag; + else + flag = usFlag; + + setPosition(position); + } + + public void blockEndOfTurn(boolean blocked) + { + turns.blocked = blocked; + } + + public boolean touchDown(float x, float y) + { + hit = null; + + if (reinforcement.hit(x, y)) + hit = reinforcement; + else if (unitDock.hit(x, y)) + hit = unitDock; + else if (turns.hit(x,y)) + hit = turns; + + return (hit != null); + } + + public boolean touchUp(float x, float y) + { + if (hit == null) + return false; + + if (hit == turns) { + if (turns.hit(x, y)) + ctrl.hud.askEndOfTurn(); + } + else if (hit == reinforcement) { + if (reinforcement.hit(x, y)) + ctrl.reinforcementHit(); + } + else if (hit == unitDock) { + if (unitDock.hit(x, y)) { + ctrl.hud.notify(unitDock.select(x, y).toString()); + ctrl.stateTouchUp(); + } + } + + hit = null; + + return true; + } + + @Override + public boolean animate(float delta) + { + unitDock.animate(delta); + return false; + } + + @Override + public void draw(Batch batch) + { + flag.draw(batch); + turns.draw(batch); + aps.draw(batch); + reinforcement.draw(batch); + unitDock.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer debugShapes) + { + turns.drawDebug(debugShapes); + aps.drawDebug(debugShapes); + reinforcement.drawDebug(debugShapes); + unitDock.drawDebug(debugShapes); + debugShapes.rect(flag.getX(), flag.getY(), flag.getWidth(), flag.getHeight()); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/hud/StatisticsPanel.java b/core/src/ch/asynk/creepingarmor/game/hud/StatisticsPanel.java new file mode 100644 index 0000000..e4a70ce --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/hud/StatisticsPanel.java @@ -0,0 +1,120 @@ +package ch.asynk.creepingarmor.game.hud; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.game.Player; +import ch.asynk.creepingarmor.ui.Bg; +import ch.asynk.creepingarmor.ui.Label; +import ch.asynk.creepingarmor.ui.Patch; +import ch.asynk.creepingarmor.ui.Position; + +public class StatisticsPanel extends Patch +{ + public static int OK_OFFSET = 10; + public static int PADDING = 20; + public static int VSPACING = 10; + public static int HSPACING = 10; + + private Label title; + private Label header; + private Label stats1; + private Label stats2; + private Bg okBtn; + + public StatisticsPanel(BitmapFont font, TextureAtlas atlas) + { + super(atlas.createPatch("typewriter")); + this.title = new Label(font); + this.header = new Label(font); + this.stats1 = new Label(font); + this.stats2 = new Label(font); + this.okBtn = new Bg(atlas.findRegion("ok")); + this.visible = false; + this.header.write("\nActions\nUnits Left\nUnits Withrawed\nCasualties\nWon Attacks\nLost Attacks"); + } + + public void updatePosition() + { + if (!visible) return; + float dx = (position.getX(rect.width) - rect.x); + float dy = (position.getY(rect.height) - rect.y); + translate(dx, dy); + title.translate(dx, dy); + header.translate(dx, dy); + stats1.translate(dx, dy); + stats2.translate(dx, dy); + okBtn.translate(dx, dy); + } + + public void show(Player winner, Player loser, Position position) + { + title.write(winner.getName() + " player won the battle in " + winner.getTurnDone() + " turns."); + stats1.write(winner.getStats()); + stats2.write(loser.getStats()); + + float height = (title.getHeight() + header.getHeight() + (2 * PADDING) + (1 * VSPACING)); + float width = (header.getWidth() + stats1.getWidth() + stats2.getWidth() + (2 * PADDING) + (4 * HSPACING)); + float w2 = (title.getWidth() + (2 * PADDING)); + if (w2 > width) width = w2; + float x = position.getX(width); + float y = position.getY(height); + setPosition(x, y, width, height); + + okBtn.setPosition((x + width - okBtn.getWidth() + OK_OFFSET), (y - OK_OFFSET)); + + y += PADDING; + x += PADDING; + header.setPosition(x, y); + stats1.setPosition((x + header.getWidth() + (2 * HSPACING)), y); + stats2.setPosition((stats1.getX() + stats1.getWidth() + (2 * HSPACING)), y); + y += (header.getHeight() + VSPACING); + title.setPosition(x, y); + visible = true; + } + + @Override + public boolean hit(float x, float y) + { + if (okBtn.hit(x, y)) + return true; + return false; + } + + @Override + public void dispose() + { + super.dispose(); + title.dispose(); + header.dispose(); + stats1.dispose(); + stats2.dispose(); + okBtn.dispose(); + } + + @Override + public void draw(Batch batch) + { + if (!visible) return; + super.draw(batch); + title.draw(batch); + header.draw(batch); + stats1.draw(batch); + stats2.draw(batch); + okBtn.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer shapes) + { + if (!visible) return; + super.drawDebug(shapes); + title.drawDebug(shapes); + header.drawDebug(shapes); + stats1.drawDebug(shapes); + stats2.drawDebug(shapes); + okBtn.drawDebug(shapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/hud/UnitDock.java b/core/src/ch/asynk/creepingarmor/game/hud/UnitDock.java new file mode 100644 index 0000000..b4a2f6f --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/hud/UnitDock.java @@ -0,0 +1,226 @@ +package ch.asynk.creepingarmor.game.hud; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.math.Matrix4; +import com.badlogic.gdx.math.Rectangle; + +import ch.asynk.creepingarmor.engine.gfx.Animation; +import ch.asynk.creepingarmor.engine.Orientation; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.UnitList; +import ch.asynk.creepingarmor.ui.Bg; +import ch.asynk.creepingarmor.ui.Position; + +public class UnitDock extends Bg implements Animation +{ + private static final float SCALE = 0.4f; + private static final float STEP = 5f; + private final Ctrl ctrl; + + private int n; + private float y; + private float to; + private float dx; + private float step; + private boolean show; + private boolean mvtDone; + public Unit selectedUnit; + private Sprite selected; + private UnitList units; + private Vector3 point; + private Matrix4 saved; + private Matrix4 transform; + private Rectangle scaledRect; + + public UnitDock(Ctrl ctrl, TextureRegion region, TextureRegion selected, float padding) + { + super(region); + this.ctrl = ctrl; + this.padding = padding; + this.mvtDone = true; + this.point = new Vector3(); + this.saved = new Matrix4(); + this.transform = new Matrix4(); + this.scaledRect = new Rectangle(); + this.selected = new Sprite(selected); + this.visible = false; + this.dx = 0f; + } + + @Override + public void translate(float _dx, float _dy) + { + this.y += _dy; + if (!visible) return; + super.translate(_dx, _dy); + for (Unit unit : units) + unit.translate(_dx, _dy); + to = position.getX(rect.width * SCALE); + transform.idt(); + transform.translate((rect.x + dx), (rect.y + rect.height), 0).scale(SCALE, SCALE, 0).translate(-rect.x, - (rect.y + rect.height), 0); + point.set(rect.x, rect.y, 0).mul(transform); + scaledRect.x = point.x; + scaledRect.y = point.y; + point.set((rect.x + rect.width), (rect.y + rect.height), 0).mul(transform); + scaledRect.width = point.x - scaledRect.x; + scaledRect.height = point.y - scaledRect.y; + } + + public void setPosition(Position position, float y) + { + if (this.position == position) + return; + this.position = position; + this.y = y; + this.step = (position.isLeft() ? STEP : -STEP); + this.mvtDone = true; + this.visible = false; + this.dx = 0f; + } + + @Override + public void dispose() + { + super.dispose(); + } + + @Override + public boolean hit(float x, float y) + { + return (visible && scaledRect.contains(x, y)); + } + + public Unit select(float x, float y) + { + int i = (int) ((scaledRect.y + scaledRect.height - y) / (scaledRect.height / units.size())); + selectedUnit = units.get(i); + return selectedUnit; + } + + public void hide() + { + if (!visible) return; + resize(); + to = rect.x; + + show = false; + mvtDone = false; + selectedUnit = null; + } + + public void show() + { + if (!resize()) + return; + to = position.getX(rect.width * SCALE); + + show = true; + mvtDone = false; + selectedUnit = null; + visible = true; + } + + private boolean resize() + { + int count = ctrl.player.reinforcement(); + if (count == 0) { + n = 0; + return false; + } + if (count == n) return true; + n = count; + + units = ctrl.player.reinforcement; + rect.width = units.get(0).getWidth() + (2 * padding); + rect.height = ((units.get(0).getHeight() * n) + ((n + 1) * padding)); + float scaledWidth = (rect.width * SCALE); + to = position.getX(scaledWidth); + rect.x = to + (position.isLeft() ? -scaledWidth : scaledWidth); + rect.y = y - rect.height; + + float px = rect.x; + float py = rect.y + rect.height; + float ph = units.get(0).getHeight(); + for (Unit unit : units) { + py -= (ph + padding); + // unit.setPosition(px, py, Orientation.SOUTH.r()); + unit.centerOn((px + (rect.width / 2)), py + (ph / 2)); + unit.setRotation(position.isLeft() ? Orientation.NORTH.r() : Orientation.SOUTH.r()); + } + + return true; + } + + @Override + public boolean animate(float delta) + { + if (!visible) return true; + if (mvtDone) return true; + + float x = (rect.x + dx); + if (show) { + if ((position.isLeft() && (x < to)) || (!position.isLeft() && x > to)) + dx += step; + else { + dx = (to - rect.x); + mvtDone = true; + } + } else { + if ((position.isLeft() && (x > to)) || (!position.isLeft() && x < to)) + dx -= step; + else { + dx = (to - rect.x); + mvtDone = true; + visible = false; + } + } + + transform.idt(); + transform.translate((rect.x + dx), (rect.y + rect.height), 0).scale(SCALE, SCALE, 0).translate(-rect.x, - (rect.y + rect.height), 0); + point.set(rect.x, rect.y, 0).mul(transform); + scaledRect.x = point.x; + scaledRect.y = point.y; + point.set((rect.x + rect.width), (rect.y + rect.height), 0).mul(transform); + scaledRect.width = point.x - scaledRect.x; + scaledRect.height = point.y - scaledRect.y; + return false; + } + + @Override + public void draw(Batch batch) + { + if (!visible) return; + + saved.set(batch.getTransformMatrix()); + batch.setTransformMatrix(transform); + + super.draw(batch); + for (Unit unit : units) { + unit.draw(batch); + if (unit == selectedUnit) { + selected.setCenter((unit.getX() + (unit.getWidth() / 2)), (unit.getY() + (unit.getHeight() / 2))); + selected.draw(batch); + } + } + + batch.setTransformMatrix(saved); + } + + @Override + public void drawDebug(ShapeRenderer shapes) + { + if (!visible) return; + + saved.set(shapes.getTransformMatrix()); + shapes.setTransformMatrix(transform); + + shapes.rect(rect.x, rect.y, rect.width, rect.height); + + shapes.setTransformMatrix(saved); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/states/StateAnimation.java b/core/src/ch/asynk/creepingarmor/game/states/StateAnimation.java new file mode 100644 index 0000000..512169a --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/states/StateAnimation.java @@ -0,0 +1,37 @@ +package ch.asynk.creepingarmor.game.states; + +public class StateAnimation extends StateCommon +{ + @Override + public void enter(StateType prevState) + { + ctrl.hud.actionButtons.hide(); + } + + @Override + public void leave(StateType nextState) + { + } + + @Override + public StateType abort() + { + return StateType.ABORT; + } + + @Override + public StateType execute() + { + return StateType.DONE; + } + + @Override + public void touchDown() + { + } + + @Override + public void touchUp() + { + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/states/StateBreak.java b/core/src/ch/asynk/creepingarmor/game/states/StateBreak.java new file mode 100644 index 0000000..3b474a5 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/states/StateBreak.java @@ -0,0 +1,90 @@ +package ch.asynk.creepingarmor.game.states; + +import ch.asynk.creepingarmor.engine.Orientation; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.hud.ActionButtons.Buttons; + +import ch.asynk.creepingarmor.CreepingArmor; + +public class StateBreak extends StateCommon +{ + private Orientation o = Orientation.KEEP; + + @Override + public void enter(StateType prevState) + { + activeUnit = null; + ctrl.hud.actionButtons.show(Buttons.DONE.b); + ctrl.hud.pushNotify("Break move possible"); + map.showBreakUnits(); + } + + @Override + public void leave(StateType nextState) + { + map.hideBreakUnits(); + map.hideMove(to); + map.hideDirections(to); + map.hideOrientation(to); + if (activeUnit != null) map.hideMove(activeUnit.getHex()); + } + + @Override + public StateType abort() + { + return StateType.ABORT; + } + + @Override + public StateType execute() + { + return StateType.DONE; + } + + @Override + public void touchDown() + { + } + + @Override + public void touchUp() + { + // TODO : cancel preview move before showing rotation + if (activeUnit == null) { + Unit unit = upHex.getUnit(); + if (map.breakUnits.contains(unit)) { + activeUnit = unit; + map.showMove(upHex); + map.showMove(to); + map.showDirections(to); + map.hideBreakUnits(); + } + } else { + o = Orientation.fromAdj(to, upHex); + + if (o == Orientation.KEEP) return; + + if (ctrl.cfg.mustValidate) { + map.hideDirections(to); + map.showOrientation(to, o); + ctrl.hud.actionButtons.show(Buttons.DONE.b); + } else { + doRotation(o); + ctrl.setState(StateType.ANIMATION); + } + } + } + + private void doRotation(Orientation o) + { + if (activeUnit == null) return; + + map.pathBuilder.init(activeUnit); + if (map.pathBuilder.build(to) == 1) { + map.pathBuilder.orientation = o; + map.moveUnit(activeUnit); + ctrl.setAfterAnimationState(StateType.DONE); + } else + CreepingArmor.debug("That's very wrong there should be only one path"); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/states/StateCommon.java b/core/src/ch/asynk/creepingarmor/game/states/StateCommon.java new file mode 100644 index 0000000..8ac4ab7 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/states/StateCommon.java @@ -0,0 +1,68 @@ +package ch.asynk.creepingarmor.game.states; + +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.State; + +import ch.asynk.creepingarmor.CreepingArmor; + +public abstract class StateCommon implements State +{ + protected static Ctrl ctrl; + protected static Map map; + + protected static Hex selectedHex = null; + protected static Hex downHex = null; + protected static Hex upHex = null; + protected static Hex to = null; + + protected boolean isEnemy; + protected static Unit activeUnit; + protected static Unit selectedUnit; + + protected StateCommon() + { + } + + public StateCommon(Ctrl ctrl, Map map) + { + this.ctrl = ctrl; + this.map = map; + } + + @Override + public boolean downInMap(float x, float y) + { + downHex = map.getHexAt(x, y); + return (downHex != null); + } + + @Override + public boolean upInMap(float x, float y) + { + upHex = map.getHexAt(x, y); + return (upHex != null); + } + + protected boolean hasUnit() + { + return (selectedUnit != null); + } + + protected void showPossibilities(Unit unit) + { + if (ctrl.cfg.showMoves && unit.canMove()) map.showPossibleMoves(); + if (ctrl.cfg.showTargets && unit.canEngage()) map.showPossibleTargets(); + if (ctrl.cfg.showMoveAssists && unit.canMove()) map.showMoveableUnits(); + unit.enableOverlay(Unit.MOVE, false); + } + + protected void hidePossibilities() + { + map.hidePossibleMoves(); + map.hidePossibleTargets(); + map.hideMoveableUnits(); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/states/StateDeployment.java b/core/src/ch/asynk/creepingarmor/game/states/StateDeployment.java new file mode 100644 index 0000000..891156f --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/states/StateDeployment.java @@ -0,0 +1,138 @@ +package ch.asynk.creepingarmor.game.states; + +import ch.asynk.creepingarmor.engine.Orientation; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.UnitList; +import ch.asynk.creepingarmor.game.hud.ActionButtons.Buttons; + +import ch.asynk.creepingarmor.CreepingArmor; + +public class StateDeployment extends StateCommon +{ + private boolean completed; + private Zone entryZone; + private UnitList deployedUnits = new UnitList(10); + + @Override + public void enter(StateType prevState) + { + if (selectedHex != null) + map.unselectHex(selectedHex); + completed = false; + entryZone = null; + selectedHex = null; + selectedUnit = null; + ctrl.hud.actionButtons.hide(); + ctrl.hud.playerInfo.unitDock.show(); + } + + @Override + public void leave(StateType nextState) + { + selectedUnit = null; + if (selectedHex != null) + map.unselectHex(selectedHex); + if (entryZone != null) + entryZone.enable(Hex.AREA, false); + ctrl.hud.playerInfo.unitDock.hide(); + } + + @Override + public StateType abort() + { + if (activeUnit != null) + undo(); + return StateType.DEPLOYMENT; + } + + @Override + public StateType execute() + { + deployedUnits.clear(); + return StateType.DONE; + } + + @Override + public void touchDown() + { + } + + @Override + public void touchUp() + { + Unit unit = ctrl.hud.playerInfo.unitDock.selectedUnit; + if (!completed && (unit != null) && (unit != activeUnit)) { + showEntryZone(unit); + } else if (selectedUnit != null) { + doRotation(Orientation.fromAdj(selectedHex, upHex)); + } else if (!completed && (entryZone != null) && (upHex != null)) { + if (upHex.isEmpty() && entryZone.contains(upHex)) + unitEnter(activeUnit); + } else { + unit = downHex.getUnit(); + if (deployedUnits.contains(unit)) { + showRotation(unit, downHex); + activeUnit = unit; + } + } + } + + private void showEntryZone(Unit unit) + { + activeUnit = unit; + if (entryZone != null) entryZone.enable(Hex.AREA, false); + entryZone = ctrl.battle.getEntryZone(activeUnit); + entryZone.enable(Hex.AREA, true); + } + + private void undo() + { + map.unselectHex(selectedHex); + map.hideDirections(selectedHex); + map.revertEnter(activeUnit); + activeUnit = null; + selectedUnit = null; + ctrl.hud.update(); + } + + private void unitEnter(Unit unit) + { + selectedUnit = unit; + selectedHex = upHex; + ctrl.player.reinforcement.remove(unit); + map.showOnBoard(unit, upHex, entryZone.orientation); + deployedUnits.add(unit); + entryZone.enable(Hex.AREA, false); + showRotation(unit, upHex); + ctrl.hud.update(); + } + + private void showRotation(Unit unit, Hex hex) + { + selectedUnit = unit; + selectedHex = hex; + map.selectHex(selectedHex); + map.showDirections(selectedHex); + ctrl.hud.playerInfo.unitDock.hide(); + ctrl.hud.actionButtons.show(Buttons.ABORT.b); + } + + private void doRotation(Orientation o) + { + map.unselectHex(selectedHex); + map.hideDirections(selectedHex); + + if (o != Orientation.KEEP) + map.setOnBoard(selectedUnit, selectedHex, o); + + ctrl.hud.actionButtons.hide(); + ctrl.hud.playerInfo.unitDock.show(); + entryZone = null; + activeUnit = null; + selectedUnit = null; + if (ctrl.checkDeploymentDone()) + completed = true; + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/states/StateEngage.java b/core/src/ch/asynk/creepingarmor/game/states/StateEngage.java new file mode 100644 index 0000000..a9dc074 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/states/StateEngage.java @@ -0,0 +1,105 @@ +package ch.asynk.creepingarmor.game.states; + +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.hud.ActionButtons.Buttons; + +import ch.asynk.creepingarmor.CreepingArmor; + +public class StateEngage extends StateCommon +{ + @Override + public void enter(StateType prevState) + { + map.possibleTargets.clear(); + ctrl.hud.actionButtons.show(ctrl.cfg.canCancel ? Buttons.ABORT.b : 0); + + // activeUnit is the target + if (prevState == StateType.SELECT) { + activeUnit = null; + // use selectedHex and selectedUnit + map.hidePossibleTargets(); + map.collectPossibleTargets(selectedUnit, ctrl.opponent.units); + map.showPossibleTargets(); + if (to != null) { + // quick fire -> replay touchUp + upHex = to; + touchUp(); + } + selectedUnit.showAttack(); + map.selectHex(selectedHex); + } else + CreepingArmor.debug("should not happen"); + } + + @Override + public void leave(StateType nextState) + { + selectedUnit.hideAttack(); + map.hideAttackAssists(); + map.hidePossibleTargets(); + map.unselectHex(selectedHex); + if (to != null) + map.unselectHex(to); + } + + @Override + public StateType abort() + { + map.activatedUnits.clear(); + return StateType.ABORT; + } + + @Override + public StateType execute() + { + StateType nextState = StateType.DONE; + if (map.engageUnit(selectedUnit, activeUnit)) { + ctrl.player.wonEngagementCount += 1; + ctrl.opponent.casualty(activeUnit); + if (map.breakUnits.size() > 0) { + nextState = StateType.BREAK; + } + } else { + ctrl.player.lostEngagementCount += 1; + } + + activeUnit.showTarget(); + ctrl.setAfterAnimationState(nextState); + return StateType.ANIMATION; + } + + @Override + public void touchDown() + { + } + + @Override + public void touchUp() + { + Unit unit = upHex.getUnit(); + + // activeUnit is the target, selectedTarget is the engagement leader + if (unit == selectedUnit) { + ctrl.setState(StateType.ABORT); + } else if ((activeUnit == null) && map.possibleTargets.contains(unit)) { + // ctrl.hud.notify("Engage " + unit); + map.hidePossibleTargets(); + to = upHex; + activeUnit = unit; + activeUnit.showTarget(); + map.collectAttackAssists(selectedUnit, activeUnit, ctrl.player.units); + map.showAttackAssists(); + ctrl.hud.actionButtons.show((ctrl.cfg.mustValidate ? Buttons.DONE.b : 0) | (ctrl.cfg.canCancel ? Buttons.ABORT.b : 0)); + } + else if (unit == activeUnit) { + ctrl.setState(StateType.DONE); + } + else if ((activeUnit != null) && map.engagementAssists.contains(unit)) { + map.toggleAttackAssist(unit); + // if(map.toggleAttackAssist(unit)) + // ctrl.hud.notify(unit + " will fire"); + // else + // ctrl.hud.notify(unit + " wont fire"); + } + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/states/StateMove.java b/core/src/ch/asynk/creepingarmor/game/states/StateMove.java new file mode 100644 index 0000000..9a586e3 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/states/StateMove.java @@ -0,0 +1,193 @@ +package ch.asynk.creepingarmor.game.states; + +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.hud.ActionButtons.Buttons; + +public class StateMove extends StateCommon +{ + @Override + public void enter(StateType prevState) + { + ctrl.hud.actionButtons.show( + ((map.activatedUnits.size() > 0) ? Buttons.DONE.b : 0) + | (ctrl.cfg.canCancel ? Buttons.ABORT.b : 0)); + + if (prevState == StateType.WITHDRAW) { + if (map.pathBuilder.size() == 1) + ctrl.setState(StateType.ROTATE); + return; + } + + map.pathBuilder.clear(); + + if (prevState == StateType.SELECT) { + // use selectedHex and selectedUnit + activeUnit = selectedUnit; + activeUnit.showMoveable(); + map.pathBuilder.init(activeUnit); + map.collectAndShowMovesAndAssits(activeUnit); + if (to != null) { + // quick move -> replay touchUp + upHex = to; + touchUp(); + } else + checkExit(activeUnit, activeUnit.getHex()); + } else { + // back from rotation -> chose next Pawn + if (selectedUnit.canMove()) { + changeUnit(selectedUnit); + } else { + changeUnit(map.moveableUnits.get(0)); + } + } + + activeUnit.enableOverlay(Unit.MOVE, false); + } + + @Override + public void leave(StateType nextState) + { + if (nextState == StateType.WITHDRAW) + return; + + // hide all but assists : want them when in rotation + activeUnit.hideMoveable(); + map.hidePossibleMoves(); + map.unselectHex(activeUnit.getHex()); + if (to != null) + map.hidePath(to); + + if (nextState != StateType.SELECT) { + if (to == null) + to = activeUnit.getHex(); + } + } + + @Override + public StateType abort() + { + hideAssists(); + if (activeUnit.justEntered()) { + map.revertEnter(activeUnit); + return StateType.ABORT; + } + int n = map.activatedUnits.size(); + if (n == 0) + return StateType.ABORT; + map.revertMoves(); + return StateType.ANIMATION; + } + + @Override + public StateType execute() + { + hideAssists(); + // be sure that the hq is activated + if (selectedUnit.canMove() && (map.activatedUnits.size() > 0)) + selectedUnit.setMoved(); + + return StateType.DONE; + } + + @Override + public void touchDown() + { + } + + @Override + public void touchUp() + { + if (upHex == activeUnit.getHex()) { + if (to != null) + map.hidePath(to); + to = null; + map.pathBuilder.clear(); + ctrl.setState(StateType.ROTATE); + return; + } + + int s = map.pathBuilder.size(); + + Unit unit = upHex.getUnit(); + + if (map.moveableUnits.contains(unit)) { + if(unit != activeUnit) + changeUnit(unit); + } else if ((s == 0) && map.possibleMoves.contains(upHex)) { + s = collectPaths(upHex); + } else if (map.pathBuilder.contains(upHex)) { + s = togglePoint(downHex, s); + } + + if (s == 1) { + if (!checkExit(activeUnit, upHex)) + ctrl.setState(StateType.ROTATE); + } + } + + private void hideAssists() + { + map.hideMoveableUnits(); + } + + private void changeUnit(Unit unit) + { + if (activeUnit != null ) { + map.unselectHex(activeUnit.getHex()); + if (activeUnit.canMove()) + activeUnit.enableOverlay(Unit.MOVE, true); + } + activeUnit = unit; + Hex hex = activeUnit.getHex(); + map.pathBuilder.init(activeUnit, hex); + activeUnit.showMoveable(); + map.hidePossibleMoves(); + map.collectPossibleMoves(activeUnit); + map.showPossibleMoves(); + map.selectHex(hex); + activeUnit.enableOverlay(Unit.MOVE, false); + ctrl.hud.notify(activeUnit.toString()); + checkExit(activeUnit, hex); + } + + private int collectPaths(Hex hex) + { + to = hex; + int s = map.pathBuilder.build(to); + map.showMove(to); + map.hidePossibleMoves(); + map.showPathBuilder(); + return s; + } + + private int togglePoint(Hex hex, int s) + { + if (hex == activeUnit.getHex()) { + // + } else if (hex == to) { + // + } else { + map.hidePathBuilder(); + map.togglePathOverlay(hex); + s = map.togglePathBuilderHex(hex); + map.showPathBuilder(); + } + + return s; + } + + private boolean checkExit(Unit unit, Hex hex) + { + if ((hex == unit.getHex()) && (unit.justEntered())) + return false; + Zone exitZone = ctrl.battle.getExitZone(unit); + if ((exitZone == null) || !exitZone.contains(hex)) + return false; + if ((unit.getHex() != hex) && !map.pathBuilder.canExit(exitZone.orientation)) + return false; + ctrl.setState(StateType.WITHDRAW); + return true; + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/states/StatePromote.java b/core/src/ch/asynk/creepingarmor/game/states/StatePromote.java new file mode 100644 index 0000000..92a0d7b --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/states/StatePromote.java @@ -0,0 +1,42 @@ +package ch.asynk.creepingarmor.game.states; + +import ch.asynk.creepingarmor.game.Unit; + +public class StatePromote extends StateCommon +{ + @Override + public void enter(StateType prevState) + { + ctrl.setAfterAnimationState(StateType.DONE); + ctrl.setState(StateType.ANIMATION); + map.promoteUnit(selectedUnit); + } + + @Override + public void leave(StateType nextState) + { + map.unselectHex(selectedHex); + } + + @Override + public StateType abort() + { + return StateType.ABORT; + } + + @Override + public StateType execute() + { + return StateType.DONE; + } + + @Override + public void touchDown() + { + } + + @Override + public void touchUp() + { + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/states/StateReinforcement.java b/core/src/ch/asynk/creepingarmor/game/states/StateReinforcement.java new file mode 100644 index 0000000..4d0cce4 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/states/StateReinforcement.java @@ -0,0 +1,87 @@ +package ch.asynk.creepingarmor.game.states; + +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.hud.ActionButtons.Buttons; + +public class StateReinforcement extends StateCommon +{ + private Zone entryZone; + + @Override + public void enter(StateType prevState) + { + map.clearAll(); + if (selectedHex != null) + map.unselectHex(selectedHex); + entryZone = null; + selectedHex = null; + ctrl.hud.playerInfo.unitDock.show(); + } + + @Override + public void leave(StateType nextState) + { + if (selectedHex != null) + map.unselectHex(selectedHex); + if (entryZone != null) + entryZone.enable(Hex.AREA, false); + ctrl.hud.playerInfo.unitDock.hide(); + } + + @Override + public StateType abort() + { + return StateType.ABORT; + } + + @Override + public StateType execute() + { + return StateType.DONE; + } + + @Override + public void touchDown() + { + } + + @Override + public void touchUp() + { + Unit unit = ctrl.hud.playerInfo.unitDock.selectedUnit; + if ((unit != null) && (unit != activeUnit)) + changeUnit(unit); + else if ((entryZone != null) && upHex.isEmpty() && entryZone.contains(upHex)) + unitEnter(activeUnit); + else + ctrl.setState(StateType.SELECT); + } + + private void changeUnit(Unit unit) + { + activeUnit = unit; + if (entryZone != null) + entryZone.enable(Hex.AREA, false); + entryZone = ctrl.battle.getEntryZone(activeUnit); + entryZone.enable(Hex.AREA, true); + ctrl.hud.actionButtons.show(((ctrl.cfg.canCancel) ? Buttons.ABORT.b : 0)); + } + + private void unitEnter(Unit unit) + { + selectedUnit = unit; + selectedHex = upHex; + map.selectHex(selectedHex); + entryZone.enable(Hex.AREA, false); + if (map.enterBoard(unit, upHex, entryZone.allowedMoves)) { + if (unit.getMovementPoints() > 0) + ctrl.setState(StateType.MOVE); + else + ctrl.setState(StateType.ROTATE); + } else { + ctrl.hud.notify("Can not enter the map at that position"); + } + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/states/StateRotate.java b/core/src/ch/asynk/creepingarmor/game/states/StateRotate.java new file mode 100644 index 0000000..4f8cf39 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/states/StateRotate.java @@ -0,0 +1,111 @@ +package ch.asynk.creepingarmor.game.states; + +import ch.asynk.creepingarmor.engine.Orientation; +import ch.asynk.creepingarmor.game.hud.ActionButtons.Buttons; + +import ch.asynk.creepingarmor.CreepingArmor; + +public class StateRotate extends StateCommon +{ + private boolean rotateOnly; + private boolean rotationSet; + + @Override + public void enter(StateType prevState) + { + ctrl.hud.actionButtons.show((ctrl.cfg.canCancel && (map.moveableUnits.size() > 1))? Buttons.ABORT.b : 0); + + if (activeUnit == null) + activeUnit = selectedUnit; + if (to == null) + to = activeUnit.getHex(); + + if (!map.pathBuilder.isSet()) { + map.pathBuilder.init(activeUnit); + map.pathBuilder.build(to); + } + + if (map.pathBuilder.size() != 1) + CreepingArmor.debug("ERROR: pathBuilder.size() == " + map.pathBuilder.size()); + + rotateOnly = (to == activeUnit.getHex()); + + if (!rotateOnly) + map.showPath(to); + map.selectHex(activeUnit.getHex()); + map.showDirections(to); + + rotationSet = false; + } + + @Override + public void leave(StateType nextState) + { + map.unselectHex(activeUnit.getHex()); + map.hidePath(to); + map.hideDirections(to); + map.hideOrientation(to); + map.pathBuilder.clear(); + to = null; + } + + @Override + public StateType abort() + { + StateType nextState = StateType.ABORT; + ctrl.hud.actionButtons.hide(); + if (activeUnit.justEntered()) { + map.revertEnter(activeUnit); + nextState = StateType.ABORT; + } else if (map.activatedUnits.size() == 0) { + map.hideMoveableUnits(); + } else { + nextState = StateType.MOVE; + } + return nextState; + } + + @Override + public StateType execute() + { + StateType whenDone = StateType.DONE; + + if (map.moveUnit(activeUnit) > 0) + whenDone = StateType.MOVE; + + ctrl.setAfterAnimationState(whenDone); + return StateType.ANIMATION; + } + + @Override + public void touchDown() + { + } + + @Override + public void touchUp() + { + if (rotationSet) return; + + Orientation o = Orientation.fromAdj(to, upHex); + if (o == Orientation.KEEP) { + ctrl.setState(StateType.ABORT); + return; + } + + if (!activeUnit.justEntered() && rotateOnly && (o == activeUnit.getOrientation())) + return; + + map.pathBuilder.orientation = o; + rotationSet = true; + + if (ctrl.cfg.mustValidate) { + map.hideDirections(to); + map.showOrientation(to, o); + ctrl.hud.actionButtons.show(Buttons.DONE.b | ((ctrl.cfg.canCancel) ? Buttons.ABORT.b : 0)); + } else { + execute(); + ctrl.setState(StateType.ANIMATION); + } + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/states/StateSelect.java b/core/src/ch/asynk/creepingarmor/game/states/StateSelect.java new file mode 100644 index 0000000..a0863e1 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/states/StateSelect.java @@ -0,0 +1,132 @@ +package ch.asynk.creepingarmor.game.states; + +import ch.asynk.creepingarmor.game.Map; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.Unit; +import ch.asynk.creepingarmor.game.Ctrl; +import ch.asynk.creepingarmor.game.hud.ActionButtons.Buttons; + +import ch.asynk.creepingarmor.CreepingArmor; + +public class StateSelect extends StateCommon +{ + public StateSelect(Ctrl ctrl, Map map) + { + super(ctrl, map); + } + + @Override + public void enter(StateType prevState) + { + to = null; + selectedHex = null; + selectedUnit = null; + activeUnit = null; + map.clearAll(); + ctrl.hud.actionButtons.hide(); + } + + @Override + public void leave(StateType nextState) + { + hidePossibilities(); + } + + @Override + public StateType abort() + { + if (selectedHex != null) + map.unselectHex(selectedHex); + hidePossibilities(); + map.clearAll(); + return StateType.ABORT; + } + + @Override + public StateType execute() + { + return StateType.DONE; + } + + @Override + public void touchDown() + { + } + + @Override + public void touchUp() + { + if (!isEnemy) { + if (map.possibleMoves.contains(upHex)) { + // quick move + to = upHex; + ctrl.setState(StateType.MOVE); + return; + } + if (map.possibleTargets.contains(upHex.getUnit())) { + // quick fire + to = upHex; + ctrl.setState(StateType.ENGAGE); + return; + } + } + + if (selectedHex != null) + map.unselectHex(selectedHex); + + hidePossibilities(); + if (upHex.isOffMap()) { + selectedUnit = null; + return; + } + + Unit unit = upHex.getUnit(); + + if (unit == null) { + isEnemy = false; + ctrl.hud.actionButtons.hide(); + map.clearAll(); + selectedUnit = null; + return; + } + + isEnemy = ctrl.player.isEnemy(unit); + if (!isEnemy && (unit == selectedUnit) && unit.canMove()) { + if (unit.isHq()) { + ctrl.hud.notify("HQ activation"); + select(upHex, unit, isEnemy); + ctrl.setState(StateType.MOVE); + } else { + // quick rotate + to = upHex; + ctrl.setState(StateType.ROTATE); + } + } else { + select(upHex, unit, isEnemy); + ctrl.hud.notify(selectedUnit.toString()); + } + } + + private void select(Hex hex, Unit unit, boolean isEnemy) + { + selectedHex = hex; + selectedUnit = unit; + + if (isEnemy && !ctrl.cfg.showEnemyPossibilities) + return; + + int moves = map.collectPossibleMoves(selectedUnit); + int targets = map.collectPossibleTargets(selectedUnit, (isEnemy ? ctrl.player.units : ctrl.opponent.units)); + + if (moves > 0) + map.collectMoveableUnits(selectedUnit); + + if ((moves > 0) || (targets > 0)) { + map.selectHex(selectedHex); + showPossibilities(selectedUnit); + } + + ctrl.hud.actionButtons.show((ctrl.player.canPromote(selectedUnit)) ? Buttons.PROMOTE.b : 0 ); + CreepingArmor.debug("Select", selectedHex.toString() + " " + selectedUnit + (isEnemy ? " enemy " : " friend ")); + } +} diff --git a/core/src/ch/asynk/creepingarmor/game/states/StateWithdraw.java b/core/src/ch/asynk/creepingarmor/game/states/StateWithdraw.java new file mode 100644 index 0000000..3d0dfdd --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/game/states/StateWithdraw.java @@ -0,0 +1,71 @@ +package ch.asynk.creepingarmor.game.states; + +import ch.asynk.creepingarmor.game.Zone; +import ch.asynk.creepingarmor.game.Hex; +import ch.asynk.creepingarmor.game.Unit; + +public class StateWithdraw extends StateCommon +{ + @Override + public void enter(StateType prevState) + { + ctrl.hud.askExitBoard(); + } + + @Override + public void leave(StateType nextState) + { + } + + @Override + public StateType abort() + { + return StateType.MOVE; + } + + @Override + public StateType execute() + { + if (activeUnit == null) + activeUnit = selectedUnit; + + ctrl.setAfterAnimationState(withdraw(activeUnit)); + return StateType.ANIMATION; + } + + @Override + public void touchDown() + { + } + + @Override + public void touchUp() + { + } + + private StateType withdraw(Unit unit) + { + Zone exitZone = ctrl.battle.getExitZone(unit); + Hex hex = unit.getHex(); + + // rotation + if (map.pathBuilder.to == null) + map.pathBuilder.build(hex); + + Hex exitHex = (Hex) map.pathBuilder.to; + if (!exitZone.contains(exitHex)) + throw new RuntimeException(String.format("%s not in exitZone", exitHex)); + + map.pathBuilder.setExit(exitZone.orientation); + + unit.hideMoveable(); + if (to != null) + map.hidePath(to); + map.hidePossibleMoves(); + map.unselectHex(hex); + + if (map.exitBoard(unit) > 0) + return StateType.MOVE; + return StateType.DONE; + } +} diff --git a/core/src/ch/asynk/creepingarmor/loading/LoadingBar.java b/core/src/ch/asynk/creepingarmor/loading/LoadingBar.java new file mode 100644 index 0000000..61de99a --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/loading/LoadingBar.java @@ -0,0 +1,32 @@ +package ch.asynk.creepingarmor.loading; + +import com.badlogic.gdx.graphics.g2d.Animation; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.scenes.scene2d.Actor; + +public class LoadingBar extends Actor +{ + Animation animation; + TextureRegion reg; + float stateTime; + + public LoadingBar(Animation animation) + { + this.animation = animation; + reg = animation.getKeyFrame(0); + } + + @Override + public void act(float delta) + { + stateTime += delta; + reg = animation.getKeyFrame(stateTime); + } + + @Override + public void draw(Batch batch, float parentAlpha) + { + batch.draw(reg, getX(), getY()); + } +} diff --git a/core/src/ch/asynk/creepingarmor/menu/MainMenu.java b/core/src/ch/asynk/creepingarmor/menu/MainMenu.java new file mode 100644 index 0000000..1c1a9f9 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/menu/MainMenu.java @@ -0,0 +1,67 @@ +package ch.asynk.creepingarmor.menu; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; + +import ch.asynk.creepingarmor.ui.Menu; + +public class MainMenu extends Menu +{ + public enum Items implements Menu.MenuItem + { + EXIT(0), + OPTIONS(1), + TUTORIALS(2), + SCENARIOS(3), + NONE(4); + public int i; + Items(int i) + { + this.i = i; + } + public int i() { return i; } + public int last() { return NONE.i; } + }; + + public MainMenu(BitmapFont font, TextureAtlas atlas) + { + super(Items.NONE, font, atlas.createPatch("typewriter")); + + label(Items.OPTIONS).write("Options"); + label(Items.TUTORIALS).write("Tutorials"); + label(Items.SCENARIOS).write("Scenarios"); + label(Items.EXIT).write("Exit"); + + this.visible = true; + } + + public Items getMenu() + { + return (Items) menuItem; + } + + @Override + public boolean hit(float x, float y) + { + boolean ret = false; + menuItem = Items.NONE; + + if (!visible) return ret; + + if (label(Items.SCENARIOS).hit(x, y)) { + menuItem = Items.SCENARIOS; + ret = true; + } else if (label(Items.TUTORIALS).hit(x, y)) { + menuItem = Items.TUTORIALS; + ret = true; + } else if (label(Items.OPTIONS).hit(x, y)) { + menuItem = Items.OPTIONS; + ret = true; + } else if (label(Items.EXIT).hit(x, y)) { + Gdx.app.exit(); + } + + return ret; + } +} diff --git a/core/src/ch/asynk/creepingarmor/menu/OptionsMenu.java b/core/src/ch/asynk/creepingarmor/menu/OptionsMenu.java new file mode 100644 index 0000000..c933df3 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/menu/OptionsMenu.java @@ -0,0 +1,257 @@ +package ch.asynk.creepingarmor.menu; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; + +import ch.asynk.creepingarmor.ui.Label; +import ch.asynk.creepingarmor.ui.Bg; +import ch.asynk.creepingarmor.ui.Patch; +import ch.asynk.creepingarmor.ui.OkCancel; + +import ch.asynk.creepingarmor.CreepingArmor; + +public class OptionsMenu extends Patch +{ + public static int PADDING = 40; + public static int OK_PADDING = 10; + public static int TITLE_PADDING = 30; + public static int VSPACING = 5; + public static int HSPACING = 30; + public static String CHECK = "#"; + + private final CreepingArmor game; + private final BitmapFont font; + + private String [] checkStrings = { + "Debug", + "Must Validate", + "Can Cancel", + "Show Enemy Possibilities", + "Show Moves Assists", + "Show Targets", + "Show Moves", + }; + private String [] fxStrings = { "OFF", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "ON" }; + + private float checkDy; + private Label title; + private Label fxVolume; + private Label fxVolumeValue; + private Label graphics; + private Label graphicsValue; + private Label gameMode; + private Label gameModeValue; + private Label [] checkLabels; + private boolean [] checkValues; + private OkCancel okCancel; + protected Bg okBtn; + + public OptionsMenu(CreepingArmor game, BitmapFont font, TextureAtlas atlas) + { + super(atlas.createPatch("typewriter")); + this.game = game; + this.font = font; + this.okCancel = new OkCancel(font, atlas); + this.okBtn = new Bg(atlas.findRegion("ok")); + this.title = new Label(font); + this.title.write("- Options"); + this.fxVolume = new Label(font); + this.fxVolume.write("Fx Volume"); + this.fxVolumeValue = new Label(font); + this.fxVolumeValue.write(fxStrings[(int) (game.config.fxVolume * 10)]); + this.graphics = new Label(font); + this.graphics.write("Graphics"); + this.graphicsValue = new Label(font); + this.graphicsValue.write(game.config.graphics.s); + this.gameMode = new Label(font); + this.gameMode.write("Game mode"); + this.gameModeValue = new Label(font); + this.gameModeValue.write(game.config.gameMode.s); + this.checkValues = new boolean[checkStrings.length]; + this.checkLabels = new Label[checkStrings.length]; + for (int i = 0; i < checkLabels.length; i++) { + Label l = new Label(font, 5f); + l.write(checkStrings[i]); + this.checkLabels[i] = l; + } + getValues(); + GlyphLayout layout = new GlyphLayout(); + layout.setText(font, CHECK); + checkDy = layout.height + 5; + + this.visible = false; + } + + private void getValues() + { + checkValues[6] = game.config.showMoves; + checkValues[5] = game.config.showTargets; + checkValues[4] = game.config.showMoveAssists; + checkValues[3] = game.config.showEnemyPossibilities; + checkValues[2] = game.config.canCancel; + checkValues[1] = game.config.mustValidate; + checkValues[0] = game.config.debug; + } + + private boolean apply() + { + game.config.showMoves = checkValues[6]; + game.config.showTargets = checkValues[5]; + game.config.showMoveAssists = checkValues[4]; + game.config.showEnemyPossibilities = checkValues[3]; + game.config.canCancel = checkValues[2]; + game.config.mustValidate = checkValues[1]; + game.config.debug = checkValues[0]; + if (!game.config.gameModeImplemented()) { + this.visible = false; + okCancel.show(String.format("'%s' Game Mode not implemented yet.", game.config.gameMode.s)); + okCancel.noCancel(); + return false; + } + return true; + } + + private void cycleFxVolume() + { + int i = (int) (game.config.fxVolume * 10) + 1; + if (i > 10) i = 0; + float fx = fxVolumeValue.getX(); + float fy = fxVolumeValue.getY(); + fxVolumeValue.write(fxStrings[i]); + fxVolumeValue.setPosition(fx, fy); + game.config.fxVolume = (i / 10f); + } + + private void cycleGraphics() + { + game.config.graphics = game.config.graphics.next(); + float fx = graphicsValue.getX(); + float fy = graphicsValue.getY(); + graphicsValue.write(game.config.graphics.s); + graphicsValue.setPosition(fx, fy); + } + + private void cycleGameMode() + { + game.config.gameMode = game.config.gameMode.next(); + float fx = gameModeValue.getX(); + float fy = gameModeValue.getY(); + gameModeValue.write(game.config.gameMode.s); + gameModeValue.setPosition(fx, fy); + } + + public void setPosition() + { + float h = (title.getHeight() + TITLE_PADDING + ((checkLabels.length - 1) * VSPACING) + (2 * PADDING)); + for (int i = 0; i < checkLabels.length; i++) + h += checkLabels[i].getHeight(); + h += (graphics.getHeight() + VSPACING); + h += (gameMode.getHeight() + VSPACING); + h += (fxVolume.getHeight() + VSPACING); + + float w = title.getWidth(); + for (int i = 0; i < checkLabels.length; i++) { + float t = checkLabels[i].getWidth(); + if (t > w) + w = t; + } + w += (2 * PADDING) + HSPACING; + + float x = position.getX(w); + float y = position.getY(h); + setPosition(x, y, w, h); + + okBtn.setPosition((x + w - okBtn.getWidth() + OK_PADDING), (y - OK_PADDING)); + + y += PADDING; + x += PADDING + HSPACING; + float dy = (VSPACING + checkLabels[0].getHeight()); + + graphics.setPosition(x, y); + graphicsValue.setPosition((x + graphics.getWidth() + 10), y); + y += dy; + gameMode.setPosition(x, y); + gameModeValue.setPosition((x + gameMode.getWidth() + 10), y); + y += dy; + fxVolume.setPosition(x, y); + fxVolumeValue.setPosition((x + fxVolume.getWidth() + 10), y); + y += dy; + for (int i = 0; i < checkLabels.length; i++) { + checkLabels[i].setPosition(x, y); + y += dy; + } + y += (TITLE_PADDING - VSPACING); + title.setPosition(x, y); + } + + @Override + public boolean hit(float x, float y) + { + if (okCancel.hit(x, y)) { + this.visible = true; + okCancel.visible = false; + return false; + } + + if (!visible) return false; + + if (okBtn.hit(x, y)) { + return apply(); + } else if (fxVolume.hit(x, y) || fxVolumeValue.hit(x, y)) { + cycleFxVolume(); + } else if (graphics.hit(x, y) || graphicsValue.hit(x, y)) { + cycleGraphics(); + } else if (gameMode.hit(x, y) || gameModeValue.hit(x, y)) { + cycleGameMode(); + } else { + for (int i = 0; i < checkLabels.length; i++) { + if (checkLabels[i].hit(x, y)) + checkValues[i] =! checkValues[i]; + } + } + + return false; + } + + @Override + public void dispose() + { + super.dispose(); + title.dispose(); + okBtn.dispose(); + okCancel.dispose(); + fxVolume.dispose(); + fxVolumeValue.dispose(); + graphics.dispose(); + graphicsValue.dispose(); + gameMode.dispose(); + gameModeValue.dispose(); + for (int i = 0; i < checkLabels.length; i++) + checkLabels[i].dispose(); + } + + @Override + public void draw(Batch batch) + { + okCancel.draw(batch); + + if (!visible) return; + super.draw(batch); + title.draw(batch); + okBtn.draw(batch); + fxVolume.draw(batch); + fxVolumeValue.draw(batch); + graphics.draw(batch); + graphicsValue.draw(batch); + gameMode.draw(batch); + gameModeValue.draw(batch); + for (int i = 0; i < checkLabels.length; i++) { + Label l = checkLabels[i]; + l.draw(batch); + if (checkValues[i]) + font.draw(batch, CHECK, (l.getX() - HSPACING) , l.getY() + checkDy); + } + } +} diff --git a/core/src/ch/asynk/creepingarmor/menu/ScenariosMenu.java b/core/src/ch/asynk/creepingarmor/menu/ScenariosMenu.java new file mode 100644 index 0000000..ad71500 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/menu/ScenariosMenu.java @@ -0,0 +1,141 @@ +package ch.asynk.creepingarmor.menu; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; + +import ch.asynk.creepingarmor.ui.Label; +import ch.asynk.creepingarmor.ui.Bg; +import ch.asynk.creepingarmor.ui.Patch; +import ch.asynk.creepingarmor.CreepingArmor; +import ch.asynk.creepingarmor.game.Battle; + +public class ScenariosMenu extends Patch +{ + public static int PADDING = 40; + public static int BTN_PADDING = 10; + public static int TITLE_PADDING = 30; + public static int VSPACING = 5; + public static int HSPACING = 30; + public static String CHECK = "#"; + + private final CreepingArmor game; + private final BitmapFont font; + + private float checkDy; + private Label title; + protected Bg okBtn; + protected Bg cancelBtn; + private Label [] battleLabels; + + public boolean launch; + + public ScenariosMenu(CreepingArmor game, BitmapFont font, TextureAtlas atlas) + { + super(atlas.createPatch("typewriter")); + this.game = game; + this.font = font; + this.okBtn = new Bg(atlas.findRegion("ok")); + this.cancelBtn = new Bg(atlas.findRegion("cancel")); + this.title = new Label(font); + this.title.write("- Scenarios"); + this.battleLabels = new Label[game.factory.battles.length]; + for (int i = 0; i < battleLabels.length; i++) { + Label l = new Label(font, 8f); + l.write(game.factory.battles[i].getName()); + battleLabels[i] = l; + } + GlyphLayout layout = new GlyphLayout(); + layout.setText(font, CHECK); + checkDy = layout.height + 9; + + this.visible = false; + this.launch = false; + } + + public void setPosition() + { + float h = (title.getHeight() + TITLE_PADDING + ((battleLabels.length - 1) * VSPACING) + (2 * PADDING)); + for (int i = 0; i < battleLabels.length; i++) + h += battleLabels[i].getHeight(); + + float w = title.getWidth(); + for (int i = 0; i < battleLabels.length; i++) { + float t = battleLabels[i].getWidth(); + if (t > w) + w = t; + } + w += (2 * PADDING) + HSPACING; + + float x = position.getX(w); + float y = position.getY(h); + setPosition(x, y, w, h); + + okBtn.setPosition((x + w - okBtn.getWidth() + BTN_PADDING), (y - BTN_PADDING)); + cancelBtn.setPosition((x - BTN_PADDING), okBtn.getY()); + + y += PADDING; + x += PADDING + HSPACING; + float dy = (VSPACING + battleLabels[0].getHeight()); + + for (int i = (battleLabels.length - 1); i > -1; i--) { + battleLabels[i].setPosition(x, y); + y += dy; + } + y += (TITLE_PADDING - VSPACING); + title.setPosition(x, y); + } + + @Override + public boolean hit(float x, float y) + { + if (!visible) return false; + + if (okBtn.hit(x, y)) { + this.launch = (game.config.battle != null); + return true; + } else if (cancelBtn.hit(x, y)) { + this.launch = false; + return true; + } else { + for (int i = 0; i w) + w = msg.getWidth(); + w += (2 * PADDING); + + float x = position.getX(w); + float y = position.getY(h); + setPosition(x, y, w, h); + + okBtn.setPosition((x + w - okBtn.getWidth() + OK_PADDING), (y - OK_PADDING)); + + y += PADDING; + x += PADDING; + + msg.setPosition(x, y); + + y += (msg.getHeight() + TITLE_PADDING); + title.setPosition(x, y); + } + + @Override + public boolean hit(float x, float y) + { + if (!visible) return false; + + if (okBtn.hit(x, y)) + return true; + + return false; + } + + @Override + public void dispose() + { + super.dispose(); + title.dispose(); + msg.dispose(); + okBtn.dispose(); + } + + @Override + public void draw(Batch batch) + { + if (!visible) return; + super.draw(batch); + title.draw(batch); + msg.draw(batch); + okBtn.draw(batch); + } +} diff --git a/core/src/ch/asynk/creepingarmor/screens/GameCamera.java b/core/src/ch/asynk/creepingarmor/screens/GameCamera.java new file mode 100644 index 0000000..475ac1f --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/screens/GameCamera.java @@ -0,0 +1,188 @@ +package ch.asynk.creepingarmor.screens; + +import com.badlogic.gdx.Gdx; + +import com.badlogic.gdx.graphics.OrthographicCamera; + +import com.badlogic.gdx.math.Rectangle; +import com.badlogic.gdx.math.Matrix4; +import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.math.MathUtils; + +public class GameCamera extends OrthographicCamera +{ + private static final float ZEROF = 0.01f; + + private int screenWidth; + private int screenHeight; + private float zoomOut; + private float zoomIn; + private float viewportAspect; + private float widthFactor; + private float heightFactor; + private Rectangle virtual; + private Rectangle window; + private Matrix4 hudMatrix; + private Matrix4 hudInvProjMatrix; + private int hudCorrection; + private int hudLeft; + private int hudBottom; + + public GameCamera(float virtualWidth, float virtualHeight, float zoomOut, float zoomIn, int hudCorrection) + { + super(virtualWidth, virtualHeight); + this.zoomOut = zoomOut; + this.zoomIn = zoomIn; + this.viewportAspect = (viewportWidth / viewportHeight); + this.virtual = new Rectangle(); + this.virtual.set(0, 0, virtualWidth, virtualHeight); + this.window = new Rectangle(); + this.hudMatrix = new Matrix4(); + this.hudInvProjMatrix = new Matrix4(); + this.hudLeft = 0; + this.hudBottom = 0; + this.hudCorrection = hudCorrection; + } + + public void updateViewport(int screenWidth, int screenHeight) + { + this.screenWidth = screenWidth; + this.screenHeight = screenHeight; + + float aspect = (screenWidth / (float) screenHeight); + float diff = (viewportAspect - aspect); + + if (diff < -ZEROF) { + window.width = java.lang.Math.min((screenHeight * viewportAspect / zoom), screenWidth); + window.height = screenHeight; + window.x = ((screenWidth - window.width) / 2f); + window.y = 0f; + viewportWidth = (viewportHeight * (window.width / window.height)); + hudBottom = hudCorrection; + hudLeft = (int) (hudBottom * viewportWidth / viewportHeight); + } else if (diff > ZEROF) { + window.width = screenWidth; + window.height = java.lang.Math.min((screenWidth * viewportAspect / zoom), screenHeight); + window.x = 0f; + window.y = ((screenHeight - window.height) / 2f); + viewportHeight = (viewportWidth * (window.height / window.width)); + hudLeft = hudCorrection; + hudBottom = (int) (hudLeft / viewportWidth * viewportHeight); + } + + Gdx.gl.glViewport((int)window.x, (int)window.y, (int)window.width, (int)window.height); + + this.widthFactor = (viewportWidth / screenWidth); + this.heightFactor = (viewportHeight / screenHeight); + + clampPosition(); + update(true); + hudMatrix.set(combined); + hudMatrix.setToOrtho2D(getHudLeft(), getHudBottom(), getHudWidth(), getHudHeight()); + hudInvProjMatrix.set(hudMatrix); + Matrix4.inv(hudInvProjMatrix.val); + } + + public Matrix4 getHudMatrix() + { + return hudMatrix; + } + + public int getScreenWidth() + { + return screenWidth; + } + + public int getScreenHeight() + { + return screenHeight; + } + + public int getHudLeft() + { + return hudLeft; + } + + public int getHudBottom() + { + return hudBottom; + } + + public int getHudWidth() + { + return (int) window.width - (2 * getHudLeft()); + } + + public int getHudHeight() + { + return (int) window.height - (2 * getHudBottom()); + } + + public void centerOnWorld() + { + position.set((viewportWidth / 2f), (viewportHeight / 2f), 0f); + } + + public void zoom(float dz) + { + zoom += dz; + clampZoom(); + updateViewport(screenWidth, screenHeight); + } + + public void translate(float dx, float dy) + { + float deltaX = (dx * zoom * widthFactor); + float deltaY = (dy * zoom * heightFactor); + translate(deltaX, -deltaY, 0); + clampPosition(); + update(true); + } + + public void clampZoom() + { + zoom = MathUtils.clamp(zoom, zoomIn, zoomOut); + } + + public void clampPosition() + { + float cx = (viewportWidth * zoom); + float cy = (viewportHeight * zoom); + + if ((virtual.width - cx) > ZEROF) { + cx /= 2f; + position.x = MathUtils.clamp(position.x, cx, (virtual.width - cx)); + } else + position.x = (virtual.width / 2f); + + if ((virtual.height - cy) > ZEROF) { + cy /= 2f; + position.y = MathUtils.clamp(position.y, cy, (virtual.height - cy)); + } else + position.y = (virtual.height / 2f); + } + + public void debug() + { + System.err.println(String.format(" VIEWPORT: %dx%d * %.2f -> %dx%d", (int)viewportWidth, (int)viewportHeight, + zoom, (int)(viewportWidth * zoom), (int)(viewportHeight * zoom))); + System.err.println(String.format(" WINDOW: %d;%d %dx%d", (int)window.x, (int)window.y, (int)window.width, (int)window.height)); + System.err.println("MATRIX:" + combined.toString()); + } + + public void unproject(int x, int y, Vector3 v) + { + unproject(v.set(x, y, 0), window.x, window.y, window.width, window.height); + } + + public void unprojectHud(float x, float y, Vector3 v) + { + x = x - window.x; + y = Gdx.graphics.getHeight() - y - 1; + y = y - window.y; + v.x = (2 * x) / window.width - 1; + v.y = (2 * y) / window.height - 1; + v.z = 2 * v.z - 1; + v.prj(hudInvProjMatrix); + } +} diff --git a/core/src/ch/asynk/creepingarmor/screens/GameScreen.java b/core/src/ch/asynk/creepingarmor/screens/GameScreen.java new file mode 100644 index 0000000..52b5139 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/screens/GameScreen.java @@ -0,0 +1,217 @@ +package ch.asynk.creepingarmor.screens; + +import com.badlogic.gdx.Gdx; + +import com.badlogic.gdx.Screen; +import com.badlogic.gdx.Input; +import com.badlogic.gdx.InputAdapter; +import com.badlogic.gdx.InputMultiplexer; +import com.badlogic.gdx.input.GestureDetector; +import com.badlogic.gdx.input.GestureDetector.GestureAdapter; + +import com.badlogic.gdx.graphics.GL20; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import com.badlogic.gdx.math.Vector2; + +import ch.asynk.creepingarmor.CreepingArmor; + +import ch.asynk.creepingarmor.game.Ctrl; + +public class GameScreen implements Screen +{ + private static boolean DEBUG = false; + + private static final float INPUT_DELAY = 0.1f; + private static final float ZOOM_IN_MAX = 0.3f; + private static final float ZOOM_OUT_MAX = 1f; + private static final float ZOOM_GESTURE_FACTOR = .01f; + private static final float ZOOM_SCROLL_FACTOR = .1f; + private static final int DRAGGED_Z_INDEX = 10; + private static final int DRAG_THRESHOLD = 6; + + private final GameCamera cam; + + private final SpriteBatch batch; + private ShapeRenderer debugShapes = null; + + private final CreepingArmor game; + private Ctrl ctrl; + + private int dragged; + private boolean blocked; + private float inputDelay = 0f; + private Vector2 dragPos = new Vector2(); + + public GameScreen(final CreepingArmor game) + { + DEBUG = game.config.debug; + + this.game = game; + this.dragged = 0; + this.blocked = false; + + this.batch = new SpriteBatch(); + this.ctrl = new Ctrl(game, game.config.battle); + this.cam = new GameCamera(ctrl.map.getWidth(), ctrl.map.getHeight(), ZOOM_OUT_MAX, ZOOM_IN_MAX, game.hudCorrection); + + if (DEBUG) this.debugShapes = new ShapeRenderer(); + + Gdx.input.setInputProcessor(getMultiplexer()); + } + + + private InputMultiplexer getMultiplexer() + { + final InputMultiplexer multiplexer = new InputMultiplexer(); + multiplexer.addProcessor(new GestureDetector(new GestureAdapter() { + @Override + public boolean zoom(float initialDistance, float distance) + { + if (initialDistance > distance) + cam.zoom(ZOOM_GESTURE_FACTOR); + else + cam.zoom(-ZOOM_GESTURE_FACTOR); + ctrl.hud.resize(cam.getHudLeft(), cam.getHudBottom(), cam.getHudWidth(), cam.getHudHeight()); + blocked = true; + inputDelay = INPUT_DELAY; + return true; + } + })); + multiplexer.addProcessor(new InputAdapter() { + @Override + public boolean touchDragged(int x, int y, int pointer) + { + dragged += 1; + cam.translate((dragPos.x - x), (dragPos.y - y)); + dragPos.set(x, y); + return true; + } + @Override + public boolean touchDown(int x, int y, int pointer, int button) + { + if (blocked) return true; + if (button == Input.Buttons.LEFT) { + dragPos.set(x, y); + cam.unproject(x, y, ctrl.mapTouch); + cam.unprojectHud(x, y, ctrl.hudTouch); + ctrl.touchDown(); + } + return true; + } + @Override + public boolean touchUp(int x, int y, int pointer, int button) + { + if (blocked) return true; + if (dragged > DRAG_THRESHOLD) { + dragged = 0; + return true; + } + dragged = 0; + if (button == Input.Buttons.LEFT) { + cam.unproject(x, y, ctrl.mapTouch); + cam.unprojectHud(x, y, ctrl.hudTouch); + ctrl.touchUp(); + } + return true; + } + @Override + public boolean scrolled(int amount) + { + cam.zoom(amount * ZOOM_SCROLL_FACTOR); + ctrl.hud.resize(cam.getHudLeft(), cam.getHudBottom(), cam.getHudWidth(), cam.getHudHeight()); + return true; + } + }); + + return multiplexer; + } + + @Override + public void render(float delta) + { + if (inputDelay > 0f) { + inputDelay -= delta; + if (inputDelay <= 0f) + blocked = false; + } + + ctrl.hud.animate(delta); + ctrl.map.animate(delta); + + Gdx.gl.glClearColor(0, 0, 0, 1); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + + // cam.update(); + batch.setProjectionMatrix(cam.combined); + batch.begin(); + ctrl.map.draw(batch); + batch.end(); + + + if (DEBUG) { + Gdx.gl.glEnable(GL20.GL_BLEND); + debugShapes.setAutoShapeType(true); + debugShapes.setProjectionMatrix(cam.combined); + debugShapes.begin(); + ctrl.map.drawDebug(debugShapes); + debugShapes.end(); + } + + batch.setProjectionMatrix(cam.getHudMatrix()); + batch.begin(); + ctrl.hud.draw(batch, DEBUG); + batch.end(); + + if (DEBUG) { + Gdx.gl.glEnable(GL20.GL_BLEND); + debugShapes.setAutoShapeType(true); + debugShapes.setProjectionMatrix(cam.getHudMatrix()); + debugShapes.begin(); + ctrl.hud.drawDebug(debugShapes); + debugShapes.end(); + } + } + + @Override + public void resize(int width, int height) + { + // CreepingArmor.debug("GameScreen", "resize (" + width + "," + height + ")"); + cam.updateViewport(width, height); + ctrl.hud.resize(cam.getHudLeft(), cam.getHudBottom(), cam.getHudWidth(), cam.getHudHeight()); + } + + @Override + public void dispose() + { + // CreepingArmor.debug("GameScreen", "dispose()"); + batch.dispose(); + ctrl.dispose(); + if (DEBUG) debugShapes.dispose(); + } + + @Override + public void show() + { + // CreepingArmor.debug("GameScreen", "show()"); + } + + @Override + public void hide() + { + // CreepingArmor.debug("GameScreen", "hide()"); + } + + @Override + public void pause() + { + // CreepingArmor.debug("GameScreen", "pause()"); + } + + @Override + public void resume() + { + // CreepingArmor.debug("GameScreen", "resume()"); + } +} diff --git a/core/src/ch/asynk/creepingarmor/screens/MenuCamera.java b/core/src/ch/asynk/creepingarmor/screens/MenuCamera.java new file mode 100644 index 0000000..40b09d4 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/screens/MenuCamera.java @@ -0,0 +1,113 @@ +package ch.asynk.creepingarmor.screens; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.math.Matrix4; +import com.badlogic.gdx.math.Rectangle; + +public class MenuCamera extends OrthographicCamera +{ + private static final float ZEROF = 0.01f; + + private float virtualAspect; + private final Rectangle virtual; + private final Rectangle window; + private int hudLeft; + private int hudBottom; + private int hudCorrection; + + private Matrix4 uiMatrix; + private Matrix4 uiInvProjMatrix; + + public MenuCamera(int cx, int cy, int width, int height, int hudCorrection) + { + super(width, height); + this.virtual = new Rectangle(); + this.virtual.set(cx, cy, width, height); + this.virtualAspect = (virtual.width / virtual.height); + this.window = new Rectangle(); + this.window.set(0, 0, 0, 0); + this.position.set(virtual.x, virtual.y, 0f); + this.hudLeft = 0; + this.hudBottom = 0; + this.hudCorrection = hudCorrection; + + this.uiMatrix = new Matrix4(); + this.uiInvProjMatrix = new Matrix4(); + } + + public void updateViewport(int screenWidth, int screenHeight) + { + float aspect = (screenWidth / (float) screenHeight); + float diff = (virtualAspect - aspect); + + if (diff < -ZEROF) { + viewportWidth = (virtual.height * aspect); + viewportHeight = virtual.height; + } else if (diff > ZEROF) { + viewportWidth = virtual.width; + viewportHeight = (virtual.width / aspect); + } + + window.width = screenWidth; + window.height = screenHeight; + hudLeft = hudCorrection; + hudBottom = (int) (hudLeft / aspect); + + Gdx.gl.glViewport((int)window.x, (int)window.y, (int)window.width, (int)window.height); + + update(true); + + uiMatrix.set(combined); + uiMatrix.setToOrtho2D(getHudLeft(), getHudBottom(), getHudWidth(), getHudHeight()); + uiInvProjMatrix.set(uiMatrix); + Matrix4.inv(uiInvProjMatrix.val); + } + + public float getScreenWidth() + { + return window.width; + } + + public float getScreenHeight() + { + return window.height; + } + + public int getHudLeft() + { + return hudLeft; + } + + public int getHudBottom() + { + return hudBottom; + } + + public int getHudWidth() + { + return (int) window.width - (2 * getHudLeft()); + } + + public int getHudHeight() + { + return (int) window.height - (2 * getHudBottom()); + } + + public void uiUnproject(float x, float y, Vector3 v) + { + x = x - window.x; + y = Gdx.graphics.getHeight() - y - 1; + y = y - window.y; + v.x = (2 * x) / window.width - 1; + v.y = (2 * y) / window.height - 1; + v.z = 2 * v.z - 1; + v.prj(uiInvProjMatrix); + } + + public Matrix4 uiCombined() + { + return uiMatrix; + } +} diff --git a/core/src/ch/asynk/creepingarmor/screens/MenuScreen.java b/core/src/ch/asynk/creepingarmor/screens/MenuScreen.java new file mode 100644 index 0000000..536b72f --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/screens/MenuScreen.java @@ -0,0 +1,264 @@ +package ch.asynk.creepingarmor.screens; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Screen; +import com.badlogic.gdx.InputAdapter; +import com.badlogic.gdx.graphics.GL20; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.math.Interpolation; + +import ch.asynk.creepingarmor.CreepingArmor; +import ch.asynk.creepingarmor.ui.Position; +import ch.asynk.creepingarmor.menu.MainMenu; +import ch.asynk.creepingarmor.menu.OptionsMenu; +import ch.asynk.creepingarmor.menu.ScenariosMenu; +import ch.asynk.creepingarmor.menu.TutorialsMenu; + +public class MenuScreen implements Screen +{ + private final CreepingArmor game; + + private final int OFFSET = 20; + private final int V_WIDTH = 1600; + private final int V_HEIGHT = 1125; + private final int V_CENTER_X = 1000; + private final int V_CENTER_Y = 890; + + private float percent; + private float delay = 0.0f; + private float dx; + private float dy; + private int[] xPath = { 369, 558, 747, 936, 1125, 1030, 936, 1125, 1314, 1408, 1597}; + private int[] yPath = { 565, 565, 565, 565, 565, 729, 892, 892, 892, 1056, 1056}; + private int n = xPath.length; + + private boolean ready; + private boolean gameAssetsLoading; + private Texture bg; + + private Sprite unit; + private Sprite move; + private Sprite from; + private Sprite to; + private Sprite geFlag; + private Sprite usFlag; + private Sprite lnl; + private Sprite logo; + + private MainMenu mainMenu; + private OptionsMenu optionsMenu; + private ScenariosMenu scenariosMenu; + private TutorialsMenu tutorialsMenu; + + private final MenuCamera camera; + private final SpriteBatch batch; + private Vector3 touch = new Vector3(); + + public MenuScreen(final CreepingArmor game) + { + this.game = game; + this.batch = new SpriteBatch(); + + float width = Gdx.graphics.getWidth(); + float height = Gdx.graphics.getHeight(); + + this.camera = new MenuCamera(V_CENTER_X, V_CENTER_Y, V_WIDTH, V_HEIGHT, game.hudCorrection); + + this.gameAssetsLoading = false; + + this.bg = game.manager.get("data/map_a.png", Texture.class); + + this.unit = new Sprite(game.menuAtlas.findRegion("unit")); + this.move = new Sprite(game.menuAtlas.findRegion("move")); + this.from = new Sprite(game.menuAtlas.findRegion("from")); + this.to = new Sprite(game.menuAtlas.findRegion("to")); + this.usFlag = new Sprite(game.menuAtlas.findRegion("us-flag")); + this.geFlag = new Sprite(game.menuAtlas.findRegion("ge-flag")); + this.lnl = new Sprite(game.menuAtlas.findRegion("lnl")); + this.logo = new Sprite(game.menuAtlas.findRegion("logo")); + + this.mainMenu = new MainMenu(game.fontB, game.uiAtlas); + this.optionsMenu = new OptionsMenu(game, game.fontB, game.uiAtlas); + this.scenariosMenu = new ScenariosMenu(game, game.fontB, game.uiAtlas); + this.tutorialsMenu = new TutorialsMenu(game, game.fontB, game.uiAtlas); + + this.game.config.battle = null; + + Gdx.input.setInputProcessor(new InputAdapter() { + @Override + public boolean touchDown(int x, int y, int pointer, int button) + { + camera.uiUnproject(x, y, touch); + return hit(touch.x, touch.y); + } + }); + } + + private boolean hit(float x, float y) + { + if (mainMenu.hit(x, y)) { + mainMenu.visible = false; + showNextMenu(); + return true; + } else if (optionsMenu.hit(x, y)) { + mainMenu.visible = true; + optionsMenu.visible = false; + return true; + } else if (scenariosMenu.hit(x, y)) { + mainMenu.visible = true; + scenariosMenu.visible = false; + if (scenariosMenu.launch) + startLoading(); + return true; + } else if (tutorialsMenu.hit(x, y)) { + mainMenu.visible = true; + tutorialsMenu.visible = false; + return true; + } + + return false; + } + + private void showNextMenu() + { + MainMenu.Items item = mainMenu.getMenu(); + + if (item == MainMenu.Items.OPTIONS) + optionsMenu.visible = true; + else if (item == MainMenu.Items.SCENARIOS) + scenariosMenu.visible = true; + else if (item == MainMenu.Items.TUTORIALS) + tutorialsMenu.visible = true; + } + + private void startLoading() + { + mainMenu.visible = false; + game.loadGameAssets(); + gameAssetsLoading = true; + } + + private void gameAssetsLoadingCompleted() + { + CreepingArmor.debug("LoadScreen", "assets ready : " + (Gdx.app.getJavaHeap()/1024.0f) + "KB"); + game.switchToGame(); + dispose(); + } + + @Override + public void render(float delta) + { + float x = xPath[0]; + float y = yPath[0]; + if (gameAssetsLoading) { + if (game.manager.update()) { + delay += delta; + if (delay >= 0.6f) + gameAssetsLoadingCompleted(); + } + + percent = Interpolation.linear.apply(percent, game.manager.getProgress(), 0.1f); + int idx = (int) (percent * 10); + float fraction = ((percent * 100 ) % 10 / 10); + x = (xPath[idx] + ((xPath[idx + 1] - xPath[idx]) * fraction)); + y = (yPath[idx] + ((yPath[idx + 1] - yPath[idx]) * fraction)); + } + + Gdx.gl.glClearColor(0, 0, 0, 1); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + + batch.setProjectionMatrix(camera.combined); + batch.begin(); + batch.draw(bg, 0, 0); + from.draw(batch); + to.draw(batch); + usFlag.draw(batch); + geFlag.draw(batch); + for (int i = 1; i < (n - 1); i++) + drawCentered(batch, move, xPath[i], yPath[i]); + drawCentered(batch, unit, (int) (x + dx), (int) (y + dy)); + batch.end(); + + batch.setProjectionMatrix(camera.uiCombined()); + batch.begin(); + batch.draw(logo, OFFSET, (camera.getScreenHeight() - logo.getRegionHeight() - OFFSET)); + batch.draw(lnl, (camera.getScreenWidth() - lnl.getRegionWidth() - (2 * OFFSET)), (2 * OFFSET)); + mainMenu.draw(batch); + optionsMenu.draw(batch); + scenariosMenu.draw(batch); + tutorialsMenu.draw(batch); + batch.end(); + } + + private void drawCentered(SpriteBatch batch, TextureRegion region, int x, int y) + { + batch.draw(region, (x - (region.getRegionWidth() / 2f)), (y - (region.getRegionHeight() / 2f))); + } + + private void setCenteredPosition(Sprite sprite, int x, int y) + { + sprite.setPosition((x - (sprite.getWidth() / 2f)), (y - (sprite.getHeight() / 2f))); + } + + private void update(int width, int height) + { + camera.updateViewport(width, height); + Position.update(camera.getHudLeft(), camera.getHudBottom(), camera.getHudWidth(), camera.getHudHeight()); + + setCenteredPosition(from, xPath[0], yPath[0]); + setCenteredPosition(to, xPath[n - 1], yPath[n - 1]); + setCenteredPosition(usFlag, xPath[0], yPath[0]); + setCenteredPosition(geFlag, xPath[n - 1], yPath[n - 1]); + + mainMenu.setPosition(); + optionsMenu.setPosition(); + scenariosMenu.setPosition(); + tutorialsMenu.setPosition(); + } + + @Override + public void resize(int width, int height) + { + update(width, height); + } + + @Override + public void dispose() + { + mainMenu.dispose(); + optionsMenu.dispose(); + scenariosMenu.dispose(); + tutorialsMenu.dispose(); + } + + @Override + public void show() + { + int width = (int) Gdx.graphics.getWidth(); + int height = (int) Gdx.graphics.getHeight(); + update(width, height); + } + + @Override + public void hide() + { + // CreepingArmor.debug("MenuScreen", "hide()"); + } + + @Override + public void pause() + { + // CreepingArmor.debug("MenuScreen", "pause()"); + } + + @Override + public void resume() + { + // CreepingArmor.debug("MenuScreen", "resume()"); + } +} diff --git a/core/src/ch/asynk/creepingarmor/ui/Bg.java b/core/src/ch/asynk/creepingarmor/ui/Bg.java new file mode 100644 index 0000000..fbacbf0 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/ui/Bg.java @@ -0,0 +1,28 @@ +package ch.asynk.creepingarmor.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; + +public class Bg extends Widget +{ + private TextureRegion region; + + public Bg(TextureRegion region) + { + super(); + this.region = region; + setPosition(0, 0, region.getRegionWidth(), region.getRegionHeight()); + } + + @Override + public void dispose() + { + } + + @Override + public void draw(Batch batch) + { + if (!visible) return; + batch.draw(region, rect.x, rect.y, rect.width, rect.height); + } +} diff --git a/core/src/ch/asynk/creepingarmor/ui/Label.java b/core/src/ch/asynk/creepingarmor/ui/Label.java new file mode 100644 index 0000000..3137976 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/ui/Label.java @@ -0,0 +1,72 @@ +package ch.asynk.creepingarmor.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; + +public class Label extends Widget +{ + private BitmapFont font; + private GlyphLayout layout; + private float dx; + private float dy; + protected String text; + + public Label(BitmapFont font) + { + this(font, 0f); + } + + public Label(BitmapFont font, float padding) + { + this(font, padding, Position.MIDDLE_CENTER); + } + + public Label(BitmapFont font, float padding, Position position) + { + super(); + this.font = font; + this.padding = padding; + this.position = position; + this.layout = new GlyphLayout(); + } + + @Override + public void dispose() + { + } + + @Override + public void translate(float dx, float dy) + { + setPosition((rect.x + dx), (rect.y + dy)); + } + + @Override + public void setPosition(float x, float y) + { + this.layout.setText(font, (text == null) ? "" : text); + setPosition(x, y, (layout.width + (2 * padding)), (layout.height + (2 * padding))); + this.dx = (x + padding); + this.dy = (y + padding + layout.height); + } + + public void write(String text) + { + this.text = text; + setPosition(position); + } + + public void write(String text, float x, float y) + { + this.text = text; + setPosition(x, y); + } + + @Override + public void draw(Batch batch) + { + if (!visible) return; + font.draw(batch, layout, dx, dy); + } +} diff --git a/core/src/ch/asynk/creepingarmor/ui/LabelImage.java b/core/src/ch/asynk/creepingarmor/ui/LabelImage.java new file mode 100644 index 0000000..a4c9d44 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/ui/LabelImage.java @@ -0,0 +1,72 @@ +package ch.asynk.creepingarmor.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +public class LabelImage extends Bg +{ + private Label label; + + public LabelImage(TextureRegion region, BitmapFont font) + { + this(region, font, 0f); + } + + public LabelImage(TextureRegion region, BitmapFont font, float padding) + { + this(region, font, padding, Position.MIDDLE_CENTER); + } + + public LabelImage(TextureRegion region, BitmapFont font, float padding, Position position) + { + super(region); + this.label = new Label(font, padding, position); + } + + @Override + public void dispose() + { + label.dispose(); + } + + @Override + public void translate(float dx, float dy) + { + super.translate(dx, dy); + label.translate(dx, dy); + } + + public void setPosition(float x, float y) + { + super.setPosition(x, y); + label.setPosition(x, y); + } + + public void setLabelPosition(Position position) + { + label.setPosition(position, this); + } + + public void write(String text) + { + this.label.write(text); + } + + @Override + public void draw(Batch batch) + { + if (!visible) return; + super.draw(batch); + label.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer shapes) + { + if (!visible) return; + super.drawDebug(shapes); + label.drawDebug(shapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/ui/LabelStack.java b/core/src/ch/asynk/creepingarmor/ui/LabelStack.java new file mode 100644 index 0000000..03e4b2e --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/ui/LabelStack.java @@ -0,0 +1,72 @@ +package ch.asynk.creepingarmor.ui; + +import java.util.ArrayDeque; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; + +import ch.asynk.creepingarmor.engine.gfx.Animation; + +public class LabelStack extends Label implements Animation +{ + class MsgInfo + { + String text; + float duration; + Position position; + MsgInfo(String text, float duration, Position position) + { + this.text = text; + this.duration = duration; + this.position = position; + } + } + + private float duration; + private float elapsed; + private ArrayDeque stack; + + public LabelStack(BitmapFont font, float padding) + { + super(font, padding); + this.visible = false; + this.stack = new ArrayDeque(); + } + + public void pushWrite(String text, float duration, Position position) + { + if (visible) + stack.push(new MsgInfo(text, duration, position)); + else + write(text, duration, position); + } + + public void write(String text, float duration, Position position) + { + this.position = position; + write(text, duration); + } + + public void write(String text, float duration) + { + this.duration = duration; + this.visible = true; + this.elapsed = 0f; + write(text); + } + + @Override + public boolean animate(float delta) + { + if (!visible) return true; + elapsed += delta; + if (elapsed >= duration) { + visible = false; + if (stack.size() > 0) { + MsgInfo info = stack.pop(); + write(info.text, info.duration, info.position); + } + } + return false; + } +} diff --git a/core/src/ch/asynk/creepingarmor/ui/Menu.java b/core/src/ch/asynk/creepingarmor/ui/Menu.java new file mode 100644 index 0000000..1744e93 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/ui/Menu.java @@ -0,0 +1,93 @@ +package ch.asynk.creepingarmor.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.NinePatch; + +public class Menu extends Patch +{ + public static int PADDING = 40; + public static int VSPACING = 8; + + protected Label []labels; + + public interface MenuItem + { + public int last(); + public int i(); + }; + + protected MenuItem menuItem; + + public Menu(MenuItem menuItem, BitmapFont font, NinePatch ninePatch) + { + super(ninePatch); + this.menuItem = menuItem; + this.labels = new Label[menuItem.last()]; + for (int i = 0; i< menuItem.last(); i ++) + labels[i] = new Label(font, 10); + } + + protected Label label(MenuItem m) + { + return labels[m.i()]; + } + + protected float widestLabel() + { + float w = 0f; + for (int i = 0; i< menuItem.last(); i ++) { + float t = labels[i].getWidth(); + if (t> w) + w = t; + } + return w; + } + + protected float highestLabel() + { + float h = 0f; + for (int i = 0; i< menuItem.last(); i ++) { + float t = labels[i].getHeight(); + if (t> h) + h = t; + } + return h; + } + + public void setPosition() + { + float lh = highestLabel(); + float h = ((menuItem.last() * lh) + (2 * PADDING) + ((menuItem.last() - 1) * VSPACING)); + float w = (widestLabel() + (2 * PADDING)); + float x = position.getX(w); + float y = position.getY(h); + setPosition(x, y, w, h); + + y += PADDING; + x += PADDING; + float dy = (VSPACING + lh); + + for (int i = 0; i< menuItem.last(); i ++) { + labels[i].setPosition(x, y); + y += dy; + } + } + + @Override + public void dispose() + { + super.dispose(); + for (int i = 0; i < menuItem.last(); i ++) + labels[i].dispose(); + } + + @Override + public void draw(Batch batch) + { + if (!visible) return; + super.draw(batch); + for (int i = 0; i < menuItem.last(); i ++) + labels[i].draw(batch); + } +} diff --git a/core/src/ch/asynk/creepingarmor/ui/Msg.java b/core/src/ch/asynk/creepingarmor/ui/Msg.java new file mode 100644 index 0000000..f91c653 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/ui/Msg.java @@ -0,0 +1,79 @@ +package ch.asynk.creepingarmor.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +public class Msg extends Patch +{ + private LabelStack label; + + public Msg(BitmapFont font, TextureAtlas atlas) + { + super(atlas.createPatch("typewriter")); + label = new LabelStack(font, 20f); + } + + @Override + public void dispose() + { + super.dispose(); + label.dispose(); + } + + public void updatePosition() + { + if (!visible) return; + float dx = (position.getX(rect.width) - rect.x); + float dy = (position.getY(rect.height) - rect.y); + translate(dx, dy); + label.translate(dx, dy); + } + + public void write(String text, float duration) + { + label.write(text, duration); + resize(); + } + + public void write(String text, float duration, Position position) + { + this.position = position; + label.write(text, duration, position); + resize(); + } + + public void pushWrite(String text, float duration, Position position) + { + this.position = position; + label.pushWrite(text, duration, position); + resize(); + } + + private void resize() + { + setPosition(label.getX(), label.getY(), label.getWidth(), label.getHeight()); + } + + public boolean animate(float delta) + { + return label.animate(delta); + } + + @Override + public void draw(Batch batch) + { + if (!label.visible) return; + super.draw(batch); + label.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer shapes) + { + if (!label.visible) return; + super.drawDebug(shapes); + label.drawDebug(shapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/ui/OkCancel.java b/core/src/ch/asynk/creepingarmor/ui/OkCancel.java new file mode 100644 index 0000000..298c765 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/ui/OkCancel.java @@ -0,0 +1,115 @@ +package ch.asynk.creepingarmor.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +public class OkCancel extends Patch +{ + public static int PADDING = 20; + public static int VSPACING = 10; + public static int HSPACING = 10; + + public boolean ok; + protected Label label; + protected Bg okBtn; + protected Bg cancelBtn; + + public OkCancel(BitmapFont font, TextureAtlas atlas) + { + super(atlas.createPatch("typewriter")); + this.label = new Label(font); + this.okBtn = new Bg(atlas.findRegion("ok")); + this.cancelBtn = new Bg(atlas.findRegion("cancel")); + this.visible = false; + } + + public void updatePosition() + { + if (!visible) return; + float dx = (position.getX(rect.width) - rect.x); + float dy = (position.getY(rect.height) - rect.y); + translate(dx, dy); + label.translate(dx, dy); + okBtn.translate(dx, dy); + cancelBtn.translate(dx, dy); + } + + public void show(String msg) + { + show(msg, Position.MIDDLE_CENTER); + } + + public void show(String msg, Position position) + { + label.write(msg); + + float height = (label.getHeight() + okBtn.getHeight() + (2 * PADDING) + (2 * VSPACING)); + float width = (label.getWidth() + (2 * PADDING)); + float w2 = (okBtn.getWidth() + cancelBtn.getWidth() + (2 * PADDING) + (1 * HSPACING)); + if (w2 > width) + width = w2; + float x = position.getX(width); + float y = position.getY(height); + setPosition(x, y, width, height); + + okBtn.setPosition((x + width - okBtn.getWidth() - PADDING), (y + PADDING)); + cancelBtn.setPosition((x + PADDING), okBtn.getY()); + label.setPosition((x + PADDING), (y + PADDING + okBtn.getHeight() + VSPACING)); + cancelBtn.visible = true; + visible = true; + ok = false; + } + + public void noCancel() + { + cancelBtn.visible = false; + } + + @Override + public boolean hit(float x, float y) + { + if (!cancelBtn.visible && super.hit(x, y)) { + ok = true; + return true; + } + if (okBtn.hit(x, y)) { + ok = true; + return true; + } else if (cancelBtn.hit(x, y)) { + ok = false; + return true; + } + return false; + } + + @Override + public void dispose() + { + super.dispose(); + label.dispose(); + okBtn.dispose(); + cancelBtn.dispose(); + } + + @Override + public void draw(Batch batch) + { + if (!visible) return; + super.draw(batch); + label.draw(batch); + okBtn.draw(batch); + cancelBtn.draw(batch); + } + + @Override + public void drawDebug(ShapeRenderer shapes) + { + if (!visible) return; + super.drawDebug(shapes); + label.drawDebug(shapes); + okBtn.drawDebug(shapes); + cancelBtn.drawDebug(shapes); + } +} diff --git a/core/src/ch/asynk/creepingarmor/ui/Patch.java b/core/src/ch/asynk/creepingarmor/ui/Patch.java new file mode 100644 index 0000000..ec68c20 --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/ui/Patch.java @@ -0,0 +1,28 @@ +package ch.asynk.creepingarmor.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.NinePatch; + +public class Patch extends Widget +{ + private NinePatch patch; + + public Patch(NinePatch patch) + { + super(); + this.patch = patch; + setPosition(0, 0, patch.getTotalWidth(), patch.getTotalHeight()); + } + + @Override + public void dispose() + { + } + + @Override + public void draw(Batch batch) + { + if (!visible) return; + patch.draw(batch, rect.x, rect.y, rect.width, rect.height); + } +} diff --git a/core/src/ch/asynk/creepingarmor/ui/Position.java b/core/src/ch/asynk/creepingarmor/ui/Position.java new file mode 100644 index 0000000..f15c14a --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/ui/Position.java @@ -0,0 +1,239 @@ +package ch.asynk.creepingarmor.ui; + +import com.badlogic.gdx.Gdx; +import ch.asynk.creepingarmor.game.Hud; + +public enum Position +{ + TOP_LEFT, + TOP_RIGHT, + TOP_CENTER, + MIDDLE_LEFT, + MIDDLE_RIGHT, + MIDDLE_CENTER, + BOTTOM_LEFT, + BOTTOM_RIGHT, + BOTTOM_CENTER; + + public Position verticalMirror() + { + Position p = this; + switch(this) { + case TOP_LEFT: + p = TOP_RIGHT; + break; + case MIDDLE_LEFT: + p = MIDDLE_RIGHT; + break; + case BOTTOM_LEFT: + p = BOTTOM_RIGHT; + break; + case TOP_RIGHT: + p = TOP_LEFT; + break; + case MIDDLE_RIGHT: + p = MIDDLE_LEFT; + break; + case BOTTOM_RIGHT: + p = BOTTOM_LEFT; + break; + } + return p; + } + + public Position horizontalMirror() + { + Position p = this; + switch(this) { + case TOP_LEFT: + p = BOTTOM_LEFT; + break; + case TOP_CENTER: + p = BOTTOM_CENTER; + break; + case TOP_RIGHT: + p = BOTTOM_RIGHT; + break; + case BOTTOM_LEFT: + p = TOP_LEFT; + break; + case BOTTOM_CENTER: + p = TOP_CENTER; + break; + case BOTTOM_RIGHT: + p = TOP_RIGHT; + break; + } + return p; + } + + public boolean isLeft() + { + boolean r = false; + switch(this) { + case TOP_LEFT: + case MIDDLE_LEFT: + case BOTTOM_LEFT: + r = true; + break; + default: + r = false; + break; + } + return r; + } + + public boolean isRight() + { + boolean r = false; + switch(this) { + case TOP_RIGHT: + case MIDDLE_RIGHT: + case BOTTOM_RIGHT: + r = true; + break; + default: + r = false; + break; + } + return r; + } + + public boolean isCenter() + { + boolean r = false; + switch(this) { + case TOP_CENTER: + case MIDDLE_CENTER: + case BOTTOM_CENTER: + r = true; + break; + default: + r = false; + break; + } + return r; + } + + private static int hudLeft = 0; + private static int hudBottom = 0; + private static int hudWidth = Gdx.graphics.getWidth(); + private static int hudHeight = Gdx.graphics.getHeight(); + + public static void update(int width, int height) + { + update(0, 0, width, height); + } + + public static void update(int left, int bottom, int width, int height) + { + hudLeft = left; + hudBottom = bottom; + hudWidth = width; + hudHeight = height; + } + + public float getX(float width) + { + float x = hudLeft; + switch(this) { + case TOP_LEFT: + case MIDDLE_LEFT: + case BOTTOM_LEFT: + x += Hud.OFFSET; + break; + case TOP_CENTER: + case MIDDLE_CENTER: + case BOTTOM_CENTER: + x += ((hudWidth - width) / 2); + break; + case TOP_RIGHT: + case MIDDLE_RIGHT: + case BOTTOM_RIGHT: + x += (hudWidth - width - Hud.OFFSET); + break; + default: + x += ((hudWidth - width) / 2); + break; + } + return x; + } + + public float getY(float height) + { + float y = hudBottom; + switch(this) { + case TOP_LEFT: + case TOP_CENTER: + case TOP_RIGHT: + y += (hudHeight - height - Hud.OFFSET); + break; + case MIDDLE_LEFT: + case MIDDLE_CENTER: + case MIDDLE_RIGHT: + y += ((hudHeight - height) / 2); + break; + case BOTTOM_LEFT: + case BOTTOM_CENTER: + case BOTTOM_RIGHT: + y += Hud.OFFSET; + break; + default: + y += ((hudHeight - height) / 2); + break; + } + return y; + } + + public float getX(Widget widget, float width) + { + float x = 0; + switch(this) { + case TOP_LEFT: + case MIDDLE_LEFT: + case BOTTOM_LEFT: + x = widget.getX(); + break; + case TOP_CENTER: + case MIDDLE_CENTER: + case BOTTOM_CENTER: + x = (widget.getX() + ((widget.getWidth() - width) / 2)); + break; + case TOP_RIGHT: + case MIDDLE_RIGHT: + case BOTTOM_RIGHT: + x = (widget.getX() + widget.getWidth() - width); + break; + default: + x = (widget.getX() + ((widget.getWidth() - width) / 2)); + break; + } + return x; + } + + public float getY(Widget widget, float height) + { + float y = 0; + switch(this) { + case TOP_LEFT: + case TOP_CENTER: + case TOP_RIGHT: + y = (widget.getY() + widget.getHeight() - height); + break; + case MIDDLE_LEFT: + case MIDDLE_CENTER: + case MIDDLE_RIGHT: + y = (widget.getY() + ((widget.getHeight() - height) / 2)); + break; + case BOTTOM_LEFT: + case BOTTOM_CENTER: + case BOTTOM_RIGHT: + y = widget.getY(); + break; + default: + y = (widget.getY() + ((widget.getHeight() - height) / 2)); + break; + } + return y; + } +} diff --git a/core/src/ch/asynk/creepingarmor/ui/Widget.java b/core/src/ch/asynk/creepingarmor/ui/Widget.java new file mode 100644 index 0000000..1acd63e --- /dev/null +++ b/core/src/ch/asynk/creepingarmor/ui/Widget.java @@ -0,0 +1,93 @@ +package ch.asynk.creepingarmor.ui; + +import com.badlogic.gdx.utils.Disposable; +import com.badlogic.gdx.math.Rectangle; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.creepingarmor.engine.gfx.Drawable; + +public abstract class Widget implements Disposable, Drawable +{ + public boolean blocked; + public boolean visible; + protected float padding; + protected Rectangle rect; + protected Position position; + protected Widget parent; + + protected Widget() + { + this.parent = null; + this.blocked = false; + this.visible = true; + this.padding = 0f; + this.rect = new Rectangle(0, 0, 0, 0); + this.position = Position.MIDDLE_CENTER; + } + + public float getX() { return rect.x; } + public float getY() { return rect.y; } + public float getWidth() { return rect.width; } + public float getHeight() { return rect.height; } + + public void translate(float dx, float dy) + { + rect.x += dx; + rect.y += dy; + } + + public void setPosition(Rectangle r) + { + rect.set(r); + } + + public void setPosition(float x, float y) + { + rect.x = x; + rect.y = y; + } + + public void setPosition(float x, float y, float w, float h) + { + rect.set(x, y, w, h); + } + + public void setPosition(Position position) + { + this.position = position; + setParent(this.parent); + } + + public void setPosition(Position position, Widget parent) + { + this.position = position; + setParent(parent); + } + + public void setParent(Widget parent) + { + this.parent = parent; + if (parent == null) { + rect.x = position.getX(rect.width); + rect.y = position.getY(rect.height); + } else { + rect.x = position.getX(parent, rect.width); + rect.y = position.getY(parent, rect.height); + } + // might trigger something if overriden + setPosition(rect.x, rect.y); + } + + public boolean hit(float x, float y) + { + if (blocked || !visible) return false; + return rect.contains(x, y); + } + + @Override + public void drawDebug(ShapeRenderer shapes) + { + if (!visible) return; + shapes.rect(rect.x, rect.y, rect.width, rect.height); + } +} diff --git a/core/src/ch/asynk/tankontank/TankOnTank.java b/core/src/ch/asynk/tankontank/TankOnTank.java deleted file mode 100644 index 390fca2..0000000 --- a/core/src/ch/asynk/tankontank/TankOnTank.java +++ /dev/null @@ -1,222 +0,0 @@ -package ch.asynk.tankontank; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Game; -import com.badlogic.gdx.assets.AssetManager; -import com.badlogic.gdx.audio.Sound; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; - -import ch.asynk.tankontank.screens.MenuScreen; -import ch.asynk.tankontank.screens.GameScreen; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.Config; -import ch.asynk.tankontank.game.battles.Factory; - -public class TankOnTank extends Game -{ - public AssetManager manager; - public Factory factory; - public Ctrl ctrl; - public Config config; - public int hudCorrection; - - public TextureAtlas uiAtlas; - public TextureAtlas menuAtlas; - public BitmapFont fontB; - public BitmapFont fontW; - - public enum State - { - MENU, - GAME, - NONE - } - private State state; - - public static void debug(String msg) - { - debug("", msg); - } - - public static void debug(String dom, String msg) - { - Gdx.app.debug(dom, msg); - } - - @Override - public void create () - { - Gdx.app.setLogLevel(Gdx.app.LOG_DEBUG); - this.hudCorrection = ((int) (125 * Gdx.graphics.getDensity()) - 75); - debug("TankOnTank", "create() [" + Gdx.graphics.getWidth() + ";" + Gdx.graphics.getHeight() + "] " + Gdx.graphics.getDensity() + " -> " + hudCorrection); - - manager = new AssetManager(); - factory = new Factory(this); - config = new Config(); - - state = State.NONE; - loadUiAssets(); - switchToMenu(); - } - - public void switchToMenu() - { - if (state == State.GAME) { - unloadGameAssets(); - factory.dispose(); - ctrl.dispose(); - getScreen().dispose(); - } - loadMenuAssets(); - state = State.MENU; - setScreen(new MenuScreen(this)); - } - - public void switchToGame() - { - unloadMenuAssets(); - getScreen().dispose(); - factory.assetsLoaded(); - state = State.GAME; - setScreen(new GameScreen(this)); - } - - public void loadGameAssets() - { - if (config.battle.getMapType() == Factory.MapType.MAP_A) - manager.load("data/map_a.png", Texture.class); - if (config.battle.getMapType() == Factory.MapType.MAP_B) - manager.load("data/map_b.png", Texture.class); - int i = config.graphics.i; - manager.load(String.format("data/units%d.atlas",i), TextureAtlas.class); - manager.load(String.format("data/unit-overlays%d.atlas", i), TextureAtlas.class); - manager.load("data/hex.png", Texture.class); - manager.load("data/hud.atlas", TextureAtlas.class); - manager.load("data/hex-overlays.atlas", TextureAtlas.class); - manager.load("data/dice.png", Texture.class); - manager.load("data/infantry_fire.png", Texture.class); - manager.load("data/tank_fire.png", Texture.class); - manager.load("data/explosions.png", Texture.class); - manager.load("sounds/dice.mp3", Sound.class); - manager.load("sounds/tank_move.mp3", Sound.class); - manager.load("sounds/infantry_move.mp3", Sound.class); - manager.load("sounds/infantry_fire.mp3", Sound.class); - manager.load("sounds/tank_fire.mp3", Sound.class); - manager.load("sounds/tank_fire_short.mp3", Sound.class); - manager.load("sounds/explosion.mp3", Sound.class); - manager.load("sounds/explosion_short.mp3", Sound.class); - manager.load("sounds/promote_us.mp3", Sound.class); - manager.load("sounds/promote_ge.mp3", Sound.class); - debug("TankOnTank", " assets loaded : " + (Gdx.app.getJavaHeap()/1024.0f) + "KB"); - } - - private void unloadGameAssets() - { - if (config.battle.getMapType() == Factory.MapType.MAP_A) - manager.unload("data/map_a.png"); - if (config.battle.getMapType() == Factory.MapType.MAP_B) - manager.unload("data/map_b.png"); - int i = config.graphics.i; - manager.unload(String.format("data/units%d.atlas",i)); - manager.unload(String.format("data/unit-overlays%d.atlas", i)); - manager.unload("data/hex.png"); - manager.unload("data/hud.atlas"); - manager.unload("data/hex-overlays.atlas"); - manager.unload("data/dice.png"); - manager.unload("data/infantry_fire.png"); - manager.unload("data/tank_fire.png"); - manager.unload("data/explosions.png"); - manager.unload("sounds/dice.mp3"); - manager.unload("sounds/tank_move.mp3"); - manager.unload("sounds/infantry_move.mp3"); - manager.unload("sounds/infantry_fire.mp3"); - manager.unload("sounds/tank_fire.mp3"); - manager.unload("sounds/tank_fire_short.mp3"); - manager.unload("sounds/explosion.mp3"); - manager.unload("sounds/explosion_short.mp3"); - manager.unload("sounds/promote_us.mp3"); - manager.unload("sounds/promote_ge.mp3"); - debug("TankOnTank", " assets unloaded : " + (Gdx.app.getJavaHeap()/1024.0f) + "KB"); - } - - private void loadUiAssets() - { - manager.load("data/ui.atlas", TextureAtlas.class); - manager.finishLoading(); - uiAtlas = manager.get("data/ui.atlas", TextureAtlas.class); - fontB = new BitmapFont(Gdx.files.internal("skin/veteran.fnt"), uiAtlas.findRegion("veteran-black")); - fontW = new BitmapFont(Gdx.files.internal("skin/veteran.fnt"), uiAtlas.findRegion("veteran-white")); - } - - private void unloadUiAssets() - { - fontB.dispose(); - fontW.dispose(); - manager.unload("data/ui.atlas"); - } - - private void loadMenuAssets() - { - manager.load("data/map_a.png", Texture.class); - manager.load("data/menu.atlas", TextureAtlas.class); - manager.finishLoading(); - menuAtlas = manager.get("data/menu.atlas", TextureAtlas.class); - } - - private void unloadMenuAssets() - { - manager.unload("data/map_a.png"); - manager.unload("data/menu.atlas"); - } - - // @Override - // public void render () - // { - // Gdx.gl.glClearColor(0, 0, 0, 1); - // Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); - // super.render(); - // } - - // @Override - // public void resize(int width, int height) - // { - // debug("TankOnTank", "resize(" + width + ", " + height + ")"); - // super.resize(width, height); - // } - - @Override - public void dispose() - { - debug("TankOnTank", "dispose()"); - debug("TankOnTank", "diagnostics:\n" + manager.getDiagnostics() ); - getScreen().dispose(); - unloadUiAssets(); - switch(state) { - case MENU: - unloadMenuAssets(); - break; - case GAME: - unloadGameAssets(); - factory.dispose(); - ctrl.dispose(); - break; - } - debug("TankOnTank", "diagnostics:\n" + manager.getDiagnostics() ); - manager.clear(); - manager.dispose(); - } - - // @Override - // public void pause() - // { - // debug("TankOnTank", "pause()"); - // } - - // @Override - // public void resume() - // { - // debug("TankOnTank", "resume()"); - // } -} diff --git a/core/src/ch/asynk/tankontank/engine/Attack.java b/core/src/ch/asynk/tankontank/engine/Attack.java deleted file mode 100644 index bc99b67..0000000 --- a/core/src/ch/asynk/tankontank/engine/Attack.java +++ /dev/null @@ -1,28 +0,0 @@ -package ch.asynk.tankontank.engine; - -public class Attack -{ - public Pawn attacker; - public Pawn target; - public int distance; - public boolean isClear; - public boolean isFlank; - - public Attack(Pawn attacker) - { - this.attacker = attacker; - } - - public String toString() - { - return String.format("attack : %s -> %s dist:%d clear:%b flank:%b", attacker, target, distance, isClear, isFlank); - } - - public void reset() - { - target = null; - distance = 0;; - isClear = false; - isFlank = false; - } -} diff --git a/core/src/ch/asynk/tankontank/engine/Board.java b/core/src/ch/asynk/tankontank/engine/Board.java deleted file mode 100644 index b11eae4..0000000 --- a/core/src/ch/asynk/tankontank/engine/Board.java +++ /dev/null @@ -1,554 +0,0 @@ -package ch.asynk.tankontank.engine; - -import java.util.Iterator; -import java.util.Collection; -import java.util.ArrayList; -import java.util.LinkedHashSet; - -import com.badlogic.gdx.Gdx; - -import com.badlogic.gdx.utils.Disposable; - -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import com.badlogic.gdx.math.Matrix4; - -import ch.asynk.tankontank.engine.gfx.Animation; -import ch.asynk.tankontank.engine.gfx.animations.AnimationSequence; -import ch.asynk.tankontank.engine.gfx.animations.RunnableAnimation; -import ch.asynk.tankontank.engine.gfx.animations.MoveToAnimation.MoveToAnimationCb; - -public abstract class Board implements Disposable, Animation -{ - private int cols; - private int rows; - private final Tile neighbours[] = new Tile[6]; - - public interface TileBuilder - { - public Tile getNewTile(float x, float y, int col, int row, boolean offmap); - } - - public static class Config - { - public int cols; - public int rows; - public int x0; // bottom left x offset - public int y0; // bottom left y offset - public int w; // hex width - public int dw; // half hex : w/2 - public int s; // hex side - public float dh; // hex top : s/2 - public float h; // square height : s + dh - public float slope; // north-west side slope : (dh / (float) dw) - } - - private Config cfg; - private Tile[] tiles; - private SearchBoard searchBoard; - private Sprite board; - private Orientation sides[]; - - private boolean transform; - private Matrix4 prevTransform; - private Matrix4 nextTransform; - - private int tileCount = 0; - private int pawnCount = 0; - private int animationCount = 0; - private final ArrayList animations = new ArrayList(2); - private final ArrayList nextAnimations = new ArrayList(2); - private final LinkedHashSet tilesToDraw = new LinkedHashSet(); - - protected SelectedTile selectedTile; - - protected Board(int cols, int rows) - { - // add a frame of OFFMAP Tiles - this.cols = (cols + 2); - this.rows = (rows + 2); - searchBoard = new SearchBoard(this, cols, rows); - initSides(); - } - - public Board(TileBuilder tileBuilder, Config cfg, Texture boardTexture, SelectedTile selectedTile) - { - board = new Sprite(boardTexture); - this.cfg = cfg; - // add a frame of OFFMAP Tiles - this.cols = (cfg.cols + 2); - this.rows = (cfg.rows + 2); - this.tiles = new Tile[this.cols * this.rows]; - searchBoard = new SearchBoard(this, cfg.cols, cfg.rows); - - int idx = 0; - boolean evenRow = false; - float y = cfg.y0 - cfg.dh + cfg.s - cfg.h; - for (int i = -1; i < (cfg.rows + 1); i++) { - float x = cfg.x0 + cfg.dw - cfg.w; - if (!evenRow) x += cfg.dw; - for ( int j = -1; j < (cfg.cols + 1); j ++) { - boolean offmap = ((j < 0) || (i < 0) || (j >= cfg.cols) || (i >= cfg.rows)); - this.tiles[idx] = tileBuilder.getNewTile(x, y, (j + ((i + 1) / 2)), i, offmap); - idx += 1; - x += cfg.w; - } - y += cfg.h; - evenRow = !evenRow; - } - - initSides(); - - this.selectedTile = selectedTile; - } - - private void initSides() - { - this.sides = new Orientation[6]; - sides[0] = Orientation.NORTH; - sides[1] = Orientation.NORTH_EAST; - sides[2] = Orientation.SOUTH_EAST; - sides[3] = Orientation.SOUTH; - sides[4] = Orientation.SOUTH_WEST; - sides[5] = Orientation.NORTH_WEST; - } - - @Override - public void dispose() - { - for (int i = 0; i < (this.cols * this.rows); i++) - tiles[i].dispose(); - tilesToDraw.clear(); - for (int i = 0, n = nextAnimations.size(); i < n; i++) - nextAnimations.get(i).dispose(); - animations.clear(); - for (int i = 0, n = animations.size(); i < n; i++) - animations.get(i).dispose(); - animations.clear(); - if (selectedTile != null) - selectedTile.dispose(); - Move.clearPool(); - Path.clearPool(); - } - - public float getWidth() - { - return board.getWidth(); - } - - public float getHeight() - { - return board.getHeight(); - } - - public void setPosition(float x, float y) - { - board.setPosition(x, y); - if ((x != 0.0f) || (y != 0.0f)) { - transform = true; - prevTransform = new Matrix4(); - nextTransform = new Matrix4(); - nextTransform.translate(x, y, 0); - } else - transform = false; - } - - public Orientation getSide(int i) - { - return sides[i]; - } - - protected int getTileOffset(int col, int row) - { - col = (col + 1 - ((row + 1) / 2)); - row = (row + 1); - if ((col < 0) || (row < 0) || (row >= this.rows) || (col >= this.cols)) - return -1; - - return (col + (row * this.cols)); - } - - protected Tile getTile(int col, int row) - { - int offset = getTileOffset(col, row); - if (offset < 0) - return null; - return tiles[offset]; - } - - public void setAdjacentTiles(Tile tile, Tile tiles[]) - { - tiles[0] = getAdjTileAt(tile, sides[0].opposite()); - tiles[1] = getAdjTileAt(tile, sides[1].opposite()); - tiles[2] = getAdjTileAt(tile, sides[2].opposite()); - tiles[3] = getAdjTileAt(tile, sides[3].opposite()); - tiles[4] = getAdjTileAt(tile, sides[4].opposite()); - tiles[5] = getAdjTileAt(tile, sides[5].opposite()); - } - - public Tile getAdjTileAt(Tile tile, Orientation o) - { - Tile t = null; - switch(o) { - case NORTH: - t = getTile((tile.col + 1), tile.row); - break; - case NORTH_EAST: - t = getTile(tile.col, (tile.row - 1)); - break; - case SOUTH_EAST: - t = getTile((tile.col - 1), (tile.row - 1)); - break; - case SOUTH: - t = getTile((tile.col - 1), tile.row); - break; - case SOUTH_WEST: - t = getTile(tile.col, (tile.row + 1)); - break; - case NORTH_WEST: - t = getTile((tile.col + 1), (tile.row + 1)); - break; - } - return t; - } - - protected abstract void animationsOver(); - - protected void addAnimation(Animation a) - { - nextAnimations.add(a); - } - - public int animationCount() - { - return animations.size(); - } - - private void stats() - { - boolean print = false; - - if (tileCount != tilesToDraw.size()) { - tileCount = tilesToDraw.size(); - print = true; - } - - if (animationCount != animations.size()) { - animationCount = animations.size(); - print = true; - } - - if (print) - Gdx.app.debug("Board", " tiles:" + tileCount + " pawns:" + pawnCount + " animations:" + animationCount); - } - - public boolean animate(float delta) - { - boolean over = (animations.size() > 0); - Iterator iter = animations.iterator(); - while (iter.hasNext()) { - Animation a = iter.next(); - if (a.animate(delta)) - iter.remove(); - } - if (over && (animations.size() == 0)) - animationsOver(); - - for (int i = 0, n = nextAnimations.size(); i < n; i++) - animations.add(nextAnimations.get(i)); - nextAnimations.clear(); - - selectedTile.animate(delta); - - return true; - } - - public void draw(Batch batch) - { - board.draw(batch); - - if (transform) { - prevTransform.set(batch.getTransformMatrix()); - batch.setTransformMatrix(nextTransform); - } - - Iterator tileIter = tilesToDraw.iterator(); - while (tileIter.hasNext()) - tileIter.next().draw(batch); - - Iterator animationIter = animations.iterator(); - while (animationIter.hasNext()) - animationIter.next().draw(batch); - - selectedTile.draw(batch); - - if (transform) - batch.setTransformMatrix(prevTransform); - } - - public void drawDebug(ShapeRenderer debugShapes) - { - stats(); - if (transform) { - prevTransform.set(debugShapes.getTransformMatrix()); - debugShapes.setTransformMatrix(nextTransform); - } - - Iterator iter = tilesToDraw.iterator(); - while (iter.hasNext()) - iter.next().drawDebug(debugShapes); - - Iterator animationIter = animations.iterator(); - while (animationIter.hasNext()) - animationIter.next().drawDebug(debugShapes); - - if (transform) - debugShapes.setTransformMatrix(prevTransform); - } - - protected int collectPossibleMoves(Pawn pawn, Collection moves) - { - return searchBoard.possibleMovesFrom(pawn, moves); - } - - protected int collectPossibleTargets(Pawn pawn, Collection targets) - { - return searchBoard.possibleTargetsFrom(pawn, targets); - } - - protected int collectPossibleTargets(Pawn pawn, Collection units, Collection targets) - { - targets.clear(); - for (Pawn target : units) { - if (pawn.canEngage(target) && searchBoard.canAttack(pawn, target, true)) - targets.add(target); - } - - return targets.size(); - } - - protected int collectMoveAssists(Pawn pawn, Collection assists) - { - assists.clear(); - setAdjacentTiles(pawn.getTile(), neighbours); - for (int i = 0; i < 6; i++) { - Tile tile = neighbours[i]; - if (tile != null) { - Iterator pawns = tile.iterator(); - while(pawns.hasNext()) { - Pawn p = pawns.next(); - if (!pawn.isEnemy(p) && p.canMove()) - assists.add(p); - } - } - } - return assists.size(); - } - - protected int collectAttackAssists(Pawn pawn, Pawn target, Collection units, Collection assists) - { - assists.clear(); - for (Pawn p : units) { - if ((p != pawn) && p.canEngage(target) && searchBoard.canAttack(p, target, !p.canAssistEngagementWithoutLos())) - assists.add(p); - } - - return assists.size(); - } - - public Orientation findBestEntry(Pawn pawn, Tile to, int allowedMoves) - { - Orientation entry = Orientation.KEEP; - int cost = Integer.MAX_VALUE; - boolean road = false; - - setAdjacentTiles(to, neighbours); - for (int i = 0; i < 6; i++) { - Tile t = neighbours[i]; - if (t.isOffMap()) { - Orientation o = Orientation.fromAdj(t.col, t.row, to.col, to.row); - if (o.isInSides(allowedMoves)) { - o = o.opposite(); - boolean r = to.road(o); - int c = to.costFrom(pawn, o); - if ((c < cost) || (r && (c == cost))) { - entry = o; - cost = c; - road = r; - } - } - } - } - - return entry.opposite(); - } - - public void enableOverlayOn(Tile tile, int i, boolean enable) - { - if(tile.enableOverlay(i, enable)) - tilesToDraw.add(tile); - else - tilesToDraw.remove(tile); - } - - public void enableOverlayOn(Tile tile, int i, Orientation o, boolean enable) - { - if(tile.enableOverlay(i, enable, o.r())) - tilesToDraw.add(tile); - else - tilesToDraw.remove(tile); - } - - private int pushPawnOnto(Pawn pawn, Tile tile) - { - if (!tile.isOffMap()) - tilesToDraw.add(tile); - return tile.push(pawn); - } - - public int removePawn(Pawn pawn) - { - Tile tile = pawn.getTile(); - if (tile == null) - return 0; - int n = tile.remove(pawn); - if (!tile.mustBeDrawn()) - tilesToDraw.remove(tile); - return n; - } - - public Pawn setPawnOnto(Pawn pawn, Move move) - { - pawn.move(move); - return setPawnOnto(pawn, move.to, move.orientation); - } - - public Pawn setPawnOnto(Pawn pawn, Tile tile, Orientation o) - { - pawn.setOnTile(tile, o.r()); - pushPawnOnto(pawn, tile); - return pawn; - } - - private RunnableAnimation getSetPawnOntoAnimation(final Pawn pawn) - { - return RunnableAnimation.get(pawn, new Runnable() { - @Override - public void run() { - Tile to = pawn.move.to; - if (!to.isOffMap()) - setPawnOnto(pawn, to, pawn.move.orientation); - } - }); - } - - protected void movePawn(final Pawn pawn, Move move, MoveToAnimationCb cb) - { - pawn.move(move); - removePawn(pawn); - - AnimationSequence seq = pawn.getMoveAnimation(move.iterator(), (move.steps() + 1), cb); - seq.addAnimation(getSetPawnOntoAnimation(pawn)); - addAnimation(seq); - } - - protected void enterPawn(final Pawn pawn, Move move) - { - pawn.move(move); - setPawnOnto(pawn, move.to, move.orientation); - } - - protected void revertLastPawnMove(final Pawn pawn) - { - removePawn(pawn); - - addAnimation(RunnableAnimation.get(pawn, new Runnable() { - @Override - public void run() { - pushPawnOnto(pawn, pawn.getTile()); - } - })); - - pawn.revertLastMove(); - } - - public void attack(final Pawn pawn, final Pawn target, boolean clearVisibility) - { - if (!pawn.canEngage(target) || !searchBoard.canAttack(pawn, target, clearVisibility)) - throw new RuntimeException(String.format("%s cannot attack %s", pawn, target)); - } - - public Tile getTileAt(float mx, float my) - { - // compute row - float y = (my - cfg.y0); - int row = (int) (y / cfg.h); - boolean oddRow = ((row % 2) == 1); - if (y < 0.f) { - row = -1; - oddRow = true; - } - - // compute col - float x = (mx - cfg.x0); - if (oddRow) x -= cfg.dw; - int col = (int) (x / cfg.w); - if (x < 0.f) - col = -1; - - int colOffset = ((row + 1) / 2); - - // check upper boundaries - float dy = (y - (row * cfg.h)); - if (dy > cfg.s) { - dy -= cfg.s; - float dx = (x - (col * cfg.w)); - col += colOffset; - if (dx < cfg.dw) { - if ((dx * cfg.slope) < dy) { - // upper left corner - row += 1; - colOffset = ((row +1) / 2); - } - } else { - if (((cfg.w - dx) * cfg.slope) < dy) { - // upper right corner - row += 1; - col += 1; - colOffset = ((row +1) / 2); - } - } - } else - col += colOffset; - - return getTile(col, row); - } - - public int distance(Tile from, Tile to) - { - return distance(from.col, from.row, to.col, to.row); - } - - public int distance(int col0, int row0, int col1, int row1) - { - int dx = Math.abs(col1 - col0); - int dy = Math.abs(row1 - row0); - int dz = Math.abs((col0 - row0) - (col1 - row1)); - - if (dx > dy) { - if (dx > dz) - return dx; - else - return dz; - } else { - if (dy > dz) - return dy; - else - return dz; - } - } -} - diff --git a/core/src/ch/asynk/tankontank/engine/Faction.java b/core/src/ch/asynk/tankontank/engine/Faction.java deleted file mode 100644 index c697894..0000000 --- a/core/src/ch/asynk/tankontank/engine/Faction.java +++ /dev/null @@ -1,6 +0,0 @@ -package ch.asynk.tankontank.engine; - -public interface Faction -{ - public boolean isEnemy(Faction other); -} diff --git a/core/src/ch/asynk/tankontank/engine/HeadedPawn.java b/core/src/ch/asynk/tankontank/engine/HeadedPawn.java deleted file mode 100644 index 7da5b8b..0000000 --- a/core/src/ch/asynk/tankontank/engine/HeadedPawn.java +++ /dev/null @@ -1,88 +0,0 @@ -package ch.asynk.tankontank.engine; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import com.badlogic.gdx.math.Vector3; - -public abstract class HeadedPawn extends Pawn -{ - private Sprite head; - protected Orientation orientation; - - public HeadedPawn(Faction faction, String pawn, String head, TextureAtlas pawns, TextureAtlas overlays) - { - super(faction, pawn, pawns, overlays); - this.head = new Sprite(pawns.findRegion(head)); - this.orientation = Orientation.KEEP; - this.descr += " " + orientation; - } - - @Override - public void dispose() - { - super.dispose(); - } - - @Override - public void setAlpha(float alpha) - { - super.setAlpha(alpha); - head.setAlpha(alpha); - } - - @Override - public float getRotation() - { - return orientation.r(); - } - - @Override - public Orientation getOrientation() - { - return orientation; - } - - @Override - public void setPosition(float x, float y) - { - super.setPosition(x, y); - float cx = x + (getWidth() / 2f); - float cy = y + (getHeight() / 2f); - head.setPosition((cx - (head.getWidth() / 2f)), (cy - (head.getHeight() / 2f))); - } - - @Override - public void setRotation(float z) - { - getPosition().z = z; - head.setRotation(z); - this.orientation = Orientation.fromRotation(z); - } - - @Override - public void setPosition(float x, float y, float z) - { - setPosition(x, y); - setRotation(z); - } - - @Override - public void draw(Batch batch) - { - head.draw(batch); - super.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - float w = head.getWidth(); - float h = head.getHeight(); - debugShapes.rect(head.getX(), head.getY(), (w / 2f), (h / 2f), w, h, head.getScaleX(), head.getScaleY(), head.getRotation()); - super.drawDebug(debugShapes); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/Meteorology.java b/core/src/ch/asynk/tankontank/engine/Meteorology.java deleted file mode 100644 index 4ece6ce..0000000 --- a/core/src/ch/asynk/tankontank/engine/Meteorology.java +++ /dev/null @@ -1,24 +0,0 @@ -package ch.asynk.tankontank.engine; - -public class Meteorology -{ - public enum Day { DAY, NIGHT }; - public enum Season { SUMMER, SPRING, WINTER, FALL }; - public enum Weather { CLEAR, RAIN, SNOW, WIND }; - - public Day day; - public Season season; - public Weather weather; - - public Meteorology() - { - clear(); - } - - public void clear() - { - day = Day.DAY; - season = Season.SUMMER; - weather = Weather.CLEAR; - } -} diff --git a/core/src/ch/asynk/tankontank/engine/Move.java b/core/src/ch/asynk/tankontank/engine/Move.java deleted file mode 100644 index 06035c3..0000000 --- a/core/src/ch/asynk/tankontank/engine/Move.java +++ /dev/null @@ -1,158 +0,0 @@ -package ch.asynk.tankontank.engine; - -import java.util.Iterator; - -import com.badlogic.gdx.utils.Pool; -import com.badlogic.gdx.math.Vector3; - -public class Move extends Path implements Iterable -{ - public enum MoveType - { - REGULAR, - SET, - ENTER, - EXIT; - } - - private static final Pool movePool = new Pool() - { - @Override - protected Move newObject() { - return new Move(); - } - }; - - public static Move get(Pawn pawn, Tile from, Tile to, Orientation orientation, Path path) - { - Move m = movePool.obtain(); - m.pawn = pawn; - m.from = from; - m.to = to; - m.orientation = orientation; - if (path != null) { - m.init(path.tiles.size()); - m.cost = path.cost; - m.roadMarch = path.roadMarch; - for (Tile tile : path.tiles) - m.tiles.add(tile); - } else { - m.init(0); - } - - return m; - } - - public static void clearPool() - { - movePool.clear(); - } - - public static Move getEnter(Pawn pawn, Tile to, Orientation orientation) - { - Move m = get(pawn, null, to, orientation, null); - m.type = MoveType.ENTER; - m.cost = to.costFrom(pawn, orientation); - return m; - } - - public static Move getSet(Pawn pawn, Tile to, Orientation orientation) - { - Move m = get(pawn, null, to, orientation, null); - m.type = MoveType.SET; - m.cost = 0; - return m; - } - - public Pawn pawn; - public Tile from; - public Tile to; - public Orientation orientation; - public MoveType type; - - public Move() - { - super(); - this.pawn = null; - this.from = null; - this.to = null; - this.orientation = Orientation.KEEP; - this.type = MoveType.REGULAR; - } - - @Override - public void reset() - { - pawn = null; - from = null; - to = null; - orientation = Orientation.KEEP; - type = MoveType.REGULAR; - super.reset(); - } - - @Override - public void dispose() - { - tiles.clear(); - movePool.free(this); - } - - public boolean isSet() - { - return (type == MoveType.SET); - } - - public boolean isEnter() - { - return (type == MoveType.ENTER); - } - - public boolean isRegular() - { - return (type == MoveType.REGULAR); - } - - public boolean isFinal() - { - return (type != MoveType.ENTER); - } - - public int steps() - { - int steps = 0; - - Tile tile = from; - Orientation o = pawn.getOrientation(); - for (Tile next : tiles) { - Orientation nextO = Orientation.fromMove(tile.col, tile.row, next.col, next.row); - if (nextO != o) { - steps += 2; - o = nextO; - } else - steps += 1; - tile = next; - } - if (orientation != Orientation.fromMove(tile.col, tile.row, to.col, to.row)) - steps += 2; - else - steps +=1; - - return steps; - } - - @Override - public String toString() - { - if (from == null) - return String.format("%s %s c:%d", to.toShort(), orientation, cost); - else - return String.format("%s->%s %s c:%d", from.toShort(), to.toShort(), orientation, cost); - } - - @Override - public Iterator iterator() - { - return new PathIterator(pawn, from, to, orientation, tiles); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/Objective.java b/core/src/ch/asynk/tankontank/engine/Objective.java deleted file mode 100644 index 1686122..0000000 --- a/core/src/ch/asynk/tankontank/engine/Objective.java +++ /dev/null @@ -1,49 +0,0 @@ -package ch.asynk.tankontank.engine; - -public class Objective -{ - protected Faction curFaction; - protected Faction prevFaction; - private boolean persistent; - - public Objective(Faction faction, boolean persistent) - { - this.curFaction = faction; - this.prevFaction = faction; - this.persistent = persistent; - } - - public boolean is(Faction faction) - { - return (curFaction == faction); - } - - public Faction faction() - { - return curFaction; - } - - public boolean set(Faction faction) - { - if (faction == curFaction) - return false; - - prevFaction = curFaction; - curFaction = faction; - return true; - } - - public boolean unset() - { - if (persistent) - return false; - revert(); - return true; - } - - public Faction revert() - { - curFaction = prevFaction; - return curFaction; - } -} diff --git a/core/src/ch/asynk/tankontank/engine/ObjectiveSet.java b/core/src/ch/asynk/tankontank/engine/ObjectiveSet.java deleted file mode 100644 index 2effb6b..0000000 --- a/core/src/ch/asynk/tankontank/engine/ObjectiveSet.java +++ /dev/null @@ -1,78 +0,0 @@ -package ch.asynk.tankontank.engine; - -import java.util.Collection; -import java.util.HashMap; - -public class ObjectiveSet extends HashMap -{ - public interface ObjectiveCb - { - public void showObjective(Tile tile, Faction faction); - } - - private final Board board; - private final HashMap modified; - - public ObjectiveSet(Board board, int n) - { - super(n); - this.board = board; - this.modified = new HashMap(10); - } - - public void add(Tile tile, Faction faction, boolean persistent) - { - put(tile, new Objective(faction, persistent)); - } - - public int count(Faction faction) - { - int n = 0; - for (Objective objective : values()) { - if (objective.is(faction)) - n += 1; - } - return n; - } - - public Faction claim(Tile tile, Faction faction) - { - Objective objective = get(tile); - if (objective == null) - return null; - - if (objective.set(faction)) - modified.put(objective, tile); - return objective.faction(); - } - - public Faction unclaim(Tile tile) - { - Objective objective = get(tile); - if (objective == null) - return null; - - if (objective.unset()) - modified.remove(objective); - return objective.faction(); - } - - public void forget() - { - modified.clear(); - } - - public int modifiedCount() - { - return modified.size(); - } - - public void revert(ObjectiveCb cb) - { - for (Objective objective : modified.keySet()) { - objective.revert(); - cb.showObjective(modified.get(objective), objective.faction()); - } - modified.clear(); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/Order.java b/core/src/ch/asynk/tankontank/engine/Order.java deleted file mode 100644 index 47269d2..0000000 --- a/core/src/ch/asynk/tankontank/engine/Order.java +++ /dev/null @@ -1,16 +0,0 @@ -package ch.asynk.tankontank.engine; - -import java.lang.Comparable; - -import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.utils.Pool; -import com.badlogic.gdx.utils.Json; - -public abstract class Order implements Disposable, Pool.Poolable, Json.Serializable, Comparable -{ - public interface OrderType - { - } - - public abstract boolean isA(OrderType type); -} diff --git a/core/src/ch/asynk/tankontank/engine/OrderList.java b/core/src/ch/asynk/tankontank/engine/OrderList.java deleted file mode 100644 index 17836da..0000000 --- a/core/src/ch/asynk/tankontank/engine/OrderList.java +++ /dev/null @@ -1,64 +0,0 @@ -package ch.asynk.tankontank.engine; - -import java.util.LinkedList; -import java.util.Iterator; - -import com.badlogic.gdx.utils.Json; -import com.badlogic.gdx.utils.JsonValue; -import com.badlogic.gdx.utils.JsonWriter.OutputType; - -public class OrderList extends LinkedList implements Json.Serializable -{ - public void dispose(Pawn pawn) - { - Iterator it = iterator(); - while(it.hasNext()) { - Order order = it.next(); - if (order.compareTo(pawn) == 0) { - it.remove(); - order.dispose(); - } - } - } - - public void dispose(Pawn pawn, Order.OrderType type) - { - Iterator it = iterator(); - while(it.hasNext()) { - Order order = it.next(); - if ((order.compareTo(pawn) == 0) && (order.isA(type))) { - it.remove(); - order.dispose(); - } - } - } - - public void dispose() - { - for (Order o : this) - o.dispose(); - clear(); - } - - public String toJson() - { - Json json = new Json(); - json.setOutputType(OutputType.json); - return json.toJson(this); - } - - @Override - public void write(Json json) - { - json.writeArrayStart("commands"); - for (Order o : this) - json.writeValue(o); - json.writeArrayEnd(); - } - - @Override - public void read(Json json, JsonValue jsonMap) - { - // TODO read(Json json, JsonValue jsonMap) - } -} diff --git a/core/src/ch/asynk/tankontank/engine/Orientation.java b/core/src/ch/asynk/tankontank/engine/Orientation.java deleted file mode 100644 index 550bb9f..0000000 --- a/core/src/ch/asynk/tankontank/engine/Orientation.java +++ /dev/null @@ -1,134 +0,0 @@ -package ch.asynk.tankontank.engine; - -public enum Orientation -{ - ALL(0, 63), - KEEP(0, 0), - NORTH(270, 1), - NORTH_EAST(210, 2), - SOUTH_EAST(150, 4), - SOUTH(90, 8), - SOUTH_WEST (30, 16), - NORTH_WEST(330, 32); - - public static int offset = 0; - public static float delta = 5f; - private final int r; - public final int s; - - Orientation(int r, int s) { this.r = r; this.s = s; } - - public float r() { return offset + r; } - - public boolean isInSides(int sides) - { - return ((sides & s) == s); - } - - public Orientation left() - { - if (this == NORTH) return NORTH_WEST; - else return fromSide(s >> 1); - } - - public Orientation right() - { - if (this == NORTH_WEST) return NORTH; - else return fromSide(s << 1); - } - - public Orientation opposite() - { - return left().left().left(); - } - - public int allBut() - { - return ALL.s & (s ^ 0xFFFF); - } - - public int getFrontSides() - { - return s | left().s | right().s; - } - - public int getBackSides() - { - return opposite().getFrontSides(); - } - - public static Orientation fromSide(int s) - { - if (s == NORTH.s) return NORTH; - else if (s == NORTH_EAST.s) return NORTH_EAST; - else if (s == SOUTH_EAST.s) return SOUTH_EAST; - else if (s == SOUTH.s) return SOUTH; - else if (s == SOUTH_WEST.s) return SOUTH_WEST; - else if (s == NORTH_WEST.s) return NORTH_WEST; - else return KEEP; - } - - public static Orientation fromRotation(float r) - { - if (r < 0) r += 360f; - if ((r > (NORTH.r - 5f)) && (r < (NORTH.r + 5f))) return NORTH; - else if ((r > (NORTH_EAST.r - delta)) && (r < (NORTH_EAST.r + delta))) return NORTH_EAST; - else if ((r > (SOUTH_EAST.r - delta)) && (r < (SOUTH_EAST.r + delta))) return SOUTH_EAST; - else if ((r > (SOUTH.r - delta)) && (r < (SOUTH.r + delta))) return SOUTH; - else if ((r > (SOUTH_WEST.r - delta)) && (r < (SOUTH_WEST.r + delta))) return SOUTH_WEST; - else if ((r > (NORTH_WEST.r - delta)) && (r < (NORTH_WEST.r + delta))) return NORTH_WEST; - else return KEEP; - } - - public static Orientation fromMove(int col0, int row0, int col1, int row1) - { - int dx = col1 - col0; - int dy = row1 - row0; - - if (dy == 0) { - if (dx == 0) return KEEP; - if (dx > 0) return NORTH; - return SOUTH; - } - if (dy > 0) { - if (dx > 0) return NORTH_WEST; - return SOUTH_WEST; - } else { - if (dx < 0) return SOUTH_EAST; - return NORTH_EAST; - } - } - - public static Orientation fromAdj(Tile from, Tile to) - { - return fromAdj(from.col, from.row, to.col, to.row); - } - - public static Orientation fromAdj(int col0, int row0, int col1, int row1) - { - Orientation o = KEEP; - - if (row1 == row0) { - if (col1 == (col0 - 1)) { - o = SOUTH; - } else if (col1 == (col0 + 1)) { - o = NORTH; - } - } else if (row1 == (row0 - 1)) { - if (col1 == (col0 - 1)) { - o = SOUTH_EAST; - } else if (col1 == col0) { - o = NORTH_EAST; - } - - } else if (row1 == (row0 + 1)) { - if (col1 == col0) { - o = SOUTH_WEST; - } else if (col1 == (col0 + 1)) { - o = NORTH_WEST; - } - } - - return o; - } -} diff --git a/core/src/ch/asynk/tankontank/engine/Path.java b/core/src/ch/asynk/tankontank/engine/Path.java deleted file mode 100644 index 8ed7f8d..0000000 --- a/core/src/ch/asynk/tankontank/engine/Path.java +++ /dev/null @@ -1,62 +0,0 @@ -package ch.asynk.tankontank.engine; - -import java.util.ArrayList; - -import com.badlogic.gdx.utils.Pool; -import com.badlogic.gdx.utils.Disposable; - -public class Path implements Disposable, Pool.Poolable -{ - private static final Pool pathPool = new Pool() { - @Override - protected Path newObject() { - return new Path(); - } - }; - - public static Path get(int size) - { - Path p = pathPool.obtain(); - p.init(size); - return p; - } - - public static void clearPool() - { - pathPool.clear(); - } - - public int cost; - public boolean roadMarch; - public ArrayList tiles; - - public Path() - { - this.cost = -1; - this.roadMarch = true; - this.tiles = null; - } - - protected void init(int size) - { - if (tiles == null) - tiles = new ArrayList(size); - else - tiles. ensureCapacity(size); - } - - @Override - public void reset() - { - cost = -1; - roadMarch = true; - tiles.clear(); - } - - @Override - public void dispose() - { - tiles.clear(); - pathPool.free(this); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/PathBuilder.java b/core/src/ch/asynk/tankontank/engine/PathBuilder.java deleted file mode 100644 index d63b0b0..0000000 --- a/core/src/ch/asynk/tankontank/engine/PathBuilder.java +++ /dev/null @@ -1,266 +0,0 @@ -package ch.asynk.tankontank.engine; - -import java.util.ArrayList; -import java.util.List; -import java.util.LinkedList; -import java.util.HashSet; -import java.util.LinkedHashSet; - -import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.math.Vector3; - -public class PathBuilder implements Disposable -{ - private final Board board; - - public Pawn pawn; - public Tile from; - public Tile to; - public int distance; - public Orientation orientation; - private List stack; - private List ctrlTiles; - private List paths; - private List filteredPaths; - private HashSet tiles; - - public PathBuilder(Board board, int tSize, int stSize, int ftSize, int vectSize) - { - this.board = board; - this.tiles = new LinkedHashSet(tSize); - this.stack = new ArrayList(stSize); - this.ctrlTiles = new ArrayList(ftSize); - this.paths = new LinkedList(); - this.filteredPaths = new LinkedList(); - this.to = null; - this.pawn = null; - this.orientation = Orientation.KEEP; - } - - public void init(Pawn pawn, Tile from) - { - this.pawn = pawn; - this.from = from; - } - - public void init(Pawn pawn) - { - init(pawn, pawn.getTile()); - } - - public void initRotation(Pawn pawn, Orientation o) - { - init(pawn, pawn.getTile()); - build(pawn.getTile()); - orientation = o; - } - - public boolean isSet() - { - return (to != null); - } - - @Override - public void dispose() - { - clear(); - } - - public void clear() - { - this.to = null; - this.distance = -1; - this.orientation = Orientation.KEEP; - for (Path path : this.paths) path.dispose(); - this.tiles.clear(); - this.stack.clear(); - this.ctrlTiles.clear(); - this.paths.clear(); - this.filteredPaths.clear(); - } - - public int size() - { - if (ctrlTiles.size() == 0) - return paths.size(); - return filteredPaths.size(); - } - - public boolean contains(Tile tile) - { - return tiles.contains(tile); - } - - public void enable(int i, boolean enable) - { - for (Tile tile : tiles) - board.enableOverlayOn(tile, i, enable); - } - - public int build(Tile to) - { - clear(); - this.to = to; - // from and to are not part of the path - this.distance = board.distance(from, to); - if (distance < 2) { - Orientation o = Orientation.fromMove(to.col, to.row, from.col, from.row); - Path path = Path.get(0); - path.roadMarch = to.road(o); - path.cost = to.costFrom(pawn, o); - paths.add(path); - } else { - findAllPaths(from, pawn.getMovementPoints(), true); - } - - // printToErr("paths", paths); - stack.clear(); - return paths.size(); - } - - private void findAllPaths(Tile from, int mvtLeft, boolean roadMarch) - { - Tile moves[] = new Tile[6]; - board.setAdjacentTiles(from, moves); - - for(int i = 0; i < 6; i++) { - Tile next = moves[i]; - if ((next == null) || next.isOffMap()) continue; - - Orientation o = board.getSide(i); - int m = (mvtLeft - next.costFrom(pawn, o)); - boolean r = roadMarch & next.road(o); - - int l = (m + (r ? pawn.getRoadMarchBonus() : 0)); - - if ((board.distance(next, to) <= l)) { - if (next == to) { - Path path = Path.get(stack.size() + 1); - for (Tile t: stack) { - path.tiles.add(t); - tiles.add(t); - } - path.roadMarch = r; - path.cost = (pawn.getMovementPoints() - m); - paths.add(path); - } else { - stack.add(next); - findAllPaths(next, m, r); - stack.remove(stack.size() - 1); - } - } - } - } - - public int toggleCtrlTile(Tile tile) - { - if (ctrlTiles.contains(tile)) - ctrlTiles.remove(tile); - else - ctrlTiles.add(tile); - return filterPaths(); - } - - private int filterPaths() - { - int s = ctrlTiles.size(); - - tiles.clear(); - filteredPaths.clear(); - for (Path path : paths) { - int ok = 0; - for (Tile filter : ctrlTiles) { - if (path.tiles.contains(filter)) - ok += 1; - } - if (ok == s) { - if (path.tiles.size() == (s + 0)) { // from and to are not part of the path - filteredPaths.clear(); - filteredPaths.add(path); - tiles.clear(); - for (Tile tile : path.tiles) tiles.add(tile); - break; - } else { - filteredPaths.add(path); - for (Tile tile : path.tiles) tiles.add(tile); - } - } - } - - // printToErr("filteredPaths", filteredPaths); - return filteredPaths.size(); - } - - public int pathCost(int i) - { - return paths.get(i).cost; - } - - public Move getMove() - { - if (size() != 1) { - System.err.println("ask for only move but they are many"); - return null; - } - - return Move.get(pawn, from, to, orientation, getPath(0)); - } - - public Move getExitMove() - { - Move move = getMove(); - move.type = Move.MoveType.EXIT; - return move; - } - - public boolean canExit(Orientation o) - { - List ps; - if (ctrlTiles.size() == 0) - ps = paths; - else - ps = filteredPaths; - - int mvt = pawn.getMovementPoints(); - int rBonus = pawn.getRoadMarchBonus(); - boolean road = to.road(o); - int cost = to.exitCost(); - - for (Path p : ps) { - int c = (p.cost + cost); - if ((c <= mvt) || (p.roadMarch && road && (c <= (mvt + rBonus)))) - return true; - } - return false; - } - - public Path getPath(int i) - { - if (ctrlTiles.size() == 0) - return paths.get(i); - return filteredPaths.get(i); - } - - public void setExit(Orientation o) - { - orientation = o; - Path path = getPath(0); - if (from != to) { - path.cost += 1; - path.tiles.add(to); - } - to = board.getAdjTileAt(to, o); - } - - private void printToErr(String what, List paths) - { - System.err.println(what + pawn + " ("+paths.size()+") " + from + " -> " + to); - for (Path path : paths) { - System.err.println(String.format(" - path (l:%d c:%d r:%b)", path.tiles.size(), path.cost, path.roadMarch)); - for(Tile tile : path.tiles) - System.err.println(" " + tile.toString()); - } - System.err.println(); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/PathIterator.java b/core/src/ch/asynk/tankontank/engine/PathIterator.java deleted file mode 100644 index 083f9c2..0000000 --- a/core/src/ch/asynk/tankontank/engine/PathIterator.java +++ /dev/null @@ -1,73 +0,0 @@ -package ch.asynk.tankontank.engine; - -import java.util.List; -import java.util.Iterator; - -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.math.Vector3; - -public class PathIterator implements Iterator -{ - private Pawn pawn; - private Tile to; - private Orientation o; - private Orientation orientation; - private Tile tile; - private Vector2 pos = new Vector2(); - private Vector3 v = new Vector3(); - private int i; - private List path; - - public PathIterator(Pawn pawn, Tile from, Tile to, Orientation orientation, List path) - { - this.pawn = pawn; - this.to = to; - this.tile = from; - this.orientation = orientation; - this.path = path; - this.o = pawn.getOrientation(); - this.v.set(pawn.getPosition().x, pawn.getPosition().y, o.r()); - this.i = 0; - } - - @Override - public boolean hasNext() - { - if ((tile == to) && (o == orientation)) - return false; - return true; - } - - @Override - public Vector3 next() - { - if (tile == to) { - v.z = orientation.r(); - o = orientation; - return v; - } - Tile nextTile; - if (i < path.size()) - nextTile = path.get(i); - else - nextTile = to; - Orientation nextO = Orientation.fromMove(tile.col, tile.row, nextTile.col, nextTile.row); - if (nextO != o) { - v.z = nextO.r(); - o = nextO; - return v; - } - pawn.getPosAt(nextTile, pos); - v.x = pos.x; - v.y = pos.y; - tile = nextTile; - i += 1; - return v; - } - - @Override - public void remove() - { - throw new UnsupportedOperationException(); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/Pawn.java b/core/src/ch/asynk/tankontank/engine/Pawn.java deleted file mode 100644 index 3209cc1..0000000 --- a/core/src/ch/asynk/tankontank/engine/Pawn.java +++ /dev/null @@ -1,365 +0,0 @@ -package ch.asynk.tankontank.engine; - -import java.util.Iterator; - -import com.badlogic.gdx.utils.Disposable; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.math.Vector3; - -import ch.asynk.tankontank.engine.gfx.Moveable; -import ch.asynk.tankontank.engine.gfx.StackedImages; -import ch.asynk.tankontank.engine.gfx.animations.MoveToAnimation; -import ch.asynk.tankontank.engine.gfx.animations.RunnableAnimation; -import ch.asynk.tankontank.engine.gfx.animations.AnimationSequence; - -public abstract class Pawn implements Moveable, Disposable -{ - public interface PawnType - { - } - - public interface PawnId - { - } - - private static final float MOVE_TIME = 0.4f; - - private Vector3 position; - private Vector3 prevPosition; - private Tile tile; - private Tile prevTile; - protected Faction faction; - protected String descr; - private Sprite sprite; - private StackedImages overlays; - protected Attack attack; - protected Move move; - - public abstract int getMovementPoints(); - public abstract int getRoadMarchBonus(); - public abstract int getAngleOfAttack(); - public abstract int getFlankSides(); - public abstract int getEngagementRangeFrom(Tile tile); - public abstract int getDefense(Tile tile); - - public abstract boolean isUnit(); - public abstract boolean isA(PawnId id); - public abstract boolean isA(PawnType type); - public abstract boolean isHq(); - public abstract boolean isHqOf(Pawn other); - public abstract boolean isHardTarget(); - - public abstract boolean canMove(); - public abstract boolean canRotate(); - public abstract boolean canEngage(); - public abstract boolean canEngage(Pawn other); - public abstract boolean canAssistEngagementWithoutLos(); - - public abstract void move(); - public abstract void engage(); - - public abstract void revertLastMove(); - - protected Pawn() - { - this.tile = null; - this.prevTile = null; - this.position = new Vector3(0f, 0f, 0f); - this.prevPosition = new Vector3(0f, 0f, 0f); - this.attack = new Attack(this); - } - - public Pawn(Faction faction, String name, TextureAtlas pawns, TextureAtlas overlays) - { - this(); - this.faction = faction; - this.descr = descr; - this.sprite = new Sprite(pawns.findRegion(name)); - this.overlays = new StackedImages(overlays); - } - - @Override - public String toString() - { - return descr; - } - - @Override - public void dispose() - { - } - - @Override - public Faction getFaction() - { - return faction; - } - - public void reset() - { - move = null; - attack.reset(); - } - - public void move(Move move) - { - switch(move.type) - { - case REGULAR: - if ((this.move != null) && (!this.move.isEnter())) - throw new RuntimeException("try to override an existing move instance"); - break; - case ENTER: - if (this.move != null) - throw new RuntimeException("try to override an existing move instance"); - break; - case SET: - break; - default: - throw new RuntimeException("unsupported MoveType"); - } - - this.move = move; - move(); - } - - public void setAttack(Pawn target, int distance) - { - attack.reset(); - attack.target = target; - attack.distance = distance; - } - - public boolean justEntered() - { - return ((move != null) && move.isEnter()); - } - - public boolean is(Faction faction) - { - return (this.faction == faction); - } - - public boolean isEnemy(Faction other) - { - return faction.isEnemy(other); - } - - public boolean isEnemy(Pawn other) - { - return faction.isEnemy(other.faction); - } - - public boolean isFlankAttack() - { - return (attack.isClear && attack.isFlank); - } - - public int attackDistance() - { - return attack.distance; - } - - public Tile getTile() - { - return tile; - } - - public Tile getPreviousTile() - { - return prevTile; - } - - public Vector3 getPosition() - { - return position; - } - - public Vector3 getPreviousPosition() - { - return prevPosition; - } - - private void revertPosition() - { - this.tile = this.prevTile; - this.prevTile = null; - position.set(prevPosition); - prevPosition.set(0f, 0f, 0f); - setPosition(position.x, position.y, position.z); - } - - public float getCenterX() - { - return (getX() + (getWidth() / 2f)); - } - - public float getCenterY() - { - return (getY() + (getHeight() / 2f)); - } - - public Vector2 getPosAt(Tile tile, Vector2 pos) - { - float x = (tile.getX() - (getWidth() / 2f)); - float y = (tile.getY() - (getHeight() / 2f)); - if (pos == null) - return new Vector2(x, y); - else - pos.set(x, y); - return pos; - } - - public void setOnTile(Tile tile, float z) - { - this.prevTile = this.tile; - this.tile = tile; - float x = (tile.getX() - (getWidth() / 2f)); - float y = (tile.getY() - (getHeight() / 2f)); - setPosition(x, y, z); - } - - @Override - public void setAlpha(float alpha) - { - sprite.setAlpha(alpha); - overlays.setAlpha(alpha); - } - - @Override - public float getX() - { - return sprite.getX(); - } - - @Override - public float getY() - { - return sprite.getY(); - } - - @Override - public float getWidth() - { - return sprite.getWidth(); - } - - @Override - public float getHeight() - { - return sprite.getHeight(); - } - - @Override - public float getRotation() - { - return sprite.getRotation(); - } - - public Orientation getOrientation() - { - return Orientation.fromRotation(getRotation()); - } - - public void translate(float dx, float dy) - { - setPosition((getX() + dx), (getY() + dy)); - } - - public void centerOn(float x, float y) - { - setPosition((x - (getWidth() / 2f)), (y - (getHeight() / 2f))); - } - - @Override - public void setPosition(float x, float y) - { - position.set(x, y, 0f); - sprite.setPosition(x, y); - float cx = x + (getWidth() / 2f); - float cy = y + (getHeight() / 2f); - overlays.centerOn(cx, cy); - } - - public void setRotation(float z) - { - position.z = z; - sprite.setRotation(z); - overlays.setRotation(z); - } - - @Override - public void setPosition(float x, float y, float z) - { - setPosition(x, y); - setRotation(z); - } - - public boolean hasOverlayEnabled() - { - return overlays.isEnabled(); - } - - public boolean enableOverlay(int i, boolean enable) - { - overlays.enable(i, enable); - if (enable) return true; - return hasOverlayEnabled(); - } - - public AnimationSequence getRotateAnimation(float z, int size) - { - prevPosition.set(position); - AnimationSequence seq = AnimationSequence.get(1 + size); - seq.addAnimation(MoveToAnimation.get(this, position.x, position.y, z, MOVE_TIME)); - - return seq; - } - - public AnimationSequence getMoveAnimation(Iterator vectors, int size, MoveToAnimation.MoveToAnimationCb cb) - { - prevPosition.set(position); - AnimationSequence seq = AnimationSequence.get(size); - while (vectors.hasNext()) - seq.addAnimation(MoveToAnimation.get(this, vectors.next(), MOVE_TIME, cb)); - - return seq; - } - - public AnimationSequence getRevertLastMoveAnimation(int size) - { - AnimationSequence seq = AnimationSequence.get(2 + size); - seq.addAnimation(MoveToAnimation.get(this, prevPosition, MOVE_TIME)); - seq.addAnimation(RunnableAnimation.get(this, new Runnable() { - @Override - public void run() { - revertPosition(); - } - })); - - return seq; - } - - @Override - public void draw(Batch batch) - { - sprite.draw(batch); - overlays.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - float w = sprite.getWidth(); - float h = sprite.getHeight(); - debugShapes.rect(sprite.getX(), sprite.getY(), (w / 2f), (h / 2f), w, h, sprite.getScaleX(), sprite.getScaleY(), sprite.getRotation()); - overlays.drawDebug(debugShapes); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/SearchBoard.java b/core/src/ch/asynk/tankontank/engine/SearchBoard.java deleted file mode 100644 index 199a7a7..0000000 --- a/core/src/ch/asynk/tankontank/engine/SearchBoard.java +++ /dev/null @@ -1,545 +0,0 @@ -package ch.asynk.tankontank.engine; - -import java.util.List; -import java.util.ArrayList; -import java.util.Set; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.ArrayDeque; -import java.util.Iterator; -import java.util.Collection; - -public class SearchBoard -{ - public class Node - { - public int col; - public int row; - public int search; - public int remaining; - public Node parent; - public boolean roadMarch; - - public Node(int col, int row) - { - this.col = col; - this.row = row; - } - - @Override - public String toString() - { - return col + ";" + row; - } - } - - private int cols; - private int rows; - private Board board; - private int searchCount; - private Node nodes[]; - - private ArrayDeque stack; - private LinkedList queue; - private ArrayDeque roadMarch; - private List los; - - public SearchBoard(Board board, int cols, int rows) - { - this.cols = cols; - this.rows = rows; - this.board = board; - this.searchCount = 0; - - this.nodes = new Node[cols * rows]; - for (int j = 0; j < rows; j++) { - int dx = ((j + 1) / 2); - for (int i = 0; i < cols; i++) - nodes[i + (j * cols)] = new Node((i + dx), j); - } - - this.queue = new LinkedList(); - this.stack = new ArrayDeque(20); - this.roadMarch = new ArrayDeque(5); - this.los = new ArrayList(10); - } - - private boolean inMap(int col, int row) - { - if ((row < 0) || (row >= rows)) - return false; - - int colOffset = ((row + 1) / 2); - if ((col < colOffset) || ((col - colOffset) >= cols)) - return false; - - return true; - } - - private Tile getTile(Node node) - { - return board.getTile(node.col, node.row); - } - - private Node getNode(Tile tile) - { - return getNode(tile.col, tile.row); - } - - protected Node getNode(int col, int row) - { - int colOffset = ((row + 1) / 2); - if ((col < colOffset) || (row < 0) || (row >= rows) || ((col - colOffset) >= cols)) - return null; - - return nodes[((col - colOffset)) + (row * cols)]; - } - - public int distance(Node from, Node to) - { - return board.distance(from.col, from.row, to.col, to.row); - } - - public void adjacentMoves(Node src, Node a[]) - { - // move to enter dst by sides[i] - a[0] = getNode((src.col - 1), src.row); - a[1] = getNode(src.col, (src.row + 1)); - a[2] = getNode((src.col + 1), (src.row + 1)); - a[3] = getNode((src.col + 1), src.row); - a[4] = getNode(src.col, (src.row - 1)); - a[5] = getNode((src.col - 1), (src.row - 1)); - } - - public int possibleMovesFrom(Pawn pawn, Collection moves) - { - moves.clear(); - searchCount += 1; - - Node adjacents[] = new Node[6]; - - Node from = getNode(pawn.getTile()); - from.parent = null; - from.search = searchCount; - from.remaining = pawn.getMovementPoints(); - from.roadMarch = true; - - if (from.remaining <= 0) - return moves.size(); - - int roadMarchBonus = pawn.getRoadMarchBonus(); - boolean first = true; - - stack.push(from); - - while (stack.size() != 0) { - Node src = stack.pop(); - - if (src.remaining < 0) - continue; - if (src.remaining == 0) { - if (src.roadMarch) - roadMarch.push(src); - continue; - } - - adjacentMoves(src, adjacents); - - for(int i = 0; i < 6; i++) { - Node dst = adjacents[i]; - if (dst != null) { - - Tile t = getTile(dst); - int cost = t.costFrom(pawn, board.getSide(i)); - boolean mayMoveOne = first && t.atLeastOneMove(pawn); - int r = src.remaining - cost; - boolean roadMarch = (src.roadMarch && t.road(board.getSide(i))); - - if (dst.search == searchCount) { - if ((r >= 0) && ((r > dst.remaining) || (roadMarch && ((r + roadMarchBonus) >= dst.remaining)))) { - dst.remaining = r; - dst.parent = src; - dst.roadMarch = roadMarch; - stack.push(dst); - moves.add(getTile(dst)); - } - } else { - dst.search = searchCount; - if ((r >= 0) || mayMoveOne) { - dst.parent = src; - dst.remaining = r; - dst.roadMarch = roadMarch; - stack.push(dst); - moves.add(getTile(dst)); - } else { - dst.parent = null; - dst.remaining = -1; - } - } - } - } - first = false; - } - - for (Node n : roadMarch) n.remaining = roadMarchBonus; - while(roadMarch.size() != 0) { - Node src = roadMarch.pop(); - - adjacentMoves(src, adjacents); - - for(int i = 0; i < 6; i++) { - Node dst = adjacents[i]; - if (dst != null) { - - Tile t = getTile(dst); - if (!t.road(board.getSide(i))) - continue; - int cost = t.costFrom(pawn, board.getSide(i)); - int r = src.remaining - cost; - - if (dst.search == searchCount) { - if ((r >= 0) && (r > dst.remaining)) { - dst.remaining = r; - dst.parent = src; - dst.roadMarch = true; - roadMarch.push(dst); - moves.add(getTile(dst)); - } - } else { - dst.search = searchCount; - if (r >= 0) { - dst.parent = src; - dst.remaining = r; - dst.roadMarch = true; - roadMarch.push(dst); - moves.add(getTile(dst)); - } else { - dst.parent = null; - dst.remaining = -1; - } - } - } - } - } - - return moves.size(); - } - - private void adjacentTargets(Node src, int angle, Node a[]) - { - // move in allowed directions - if (Orientation.NORTH.isInSides(angle)) - a[0] = getNode((src.col + 1), src.row); - else - a[0] = null; - - if (Orientation.NORTH_EAST.isInSides(angle)) - a[1] = getNode(src.col, (src.row - 1)); - else - a[1] = null; - - if (Orientation.SOUTH_EAST.isInSides(angle)) - a[2] = getNode((src.col - 1), (src.row - 1)); - else - a[2] = null; - - if (Orientation.SOUTH.isInSides(angle)) - a[3] = getNode((src.col - 1), src.row); - else - a[3] = null; - - if (Orientation.SOUTH_WEST.isInSides(angle)) - a[4] = getNode(src.col, (src.row + 1)); - else - a[4] = null; - - if (Orientation.NORTH_WEST.isInSides(angle)) - a[5] = getNode((src.col + 1), (src.row + 1)); - else - a[5] = null; - } - - public int possibleTargetsFrom(Pawn pawn, Collection targets) - { - targets.clear(); - searchCount += 1; - - Node adjacents[] = new Node[6]; - - int range = pawn.getEngagementRangeFrom(pawn.getTile()); - int angle = pawn.getAngleOfAttack(); - int extendedAngle = pawn.getOrientation().opposite().allBut(); - - Node from = getNode(pawn.getTile()); - from.search = searchCount; - from.remaining = range; - - if (range <= 0) - return targets.size(); - - queue.add(from); - - boolean first = true; - while (queue.size() != 0) { - Node src = queue.remove(); - - if (src.remaining <= 0) - continue; - - if (!first && (((range - src.remaining) % 2) == 0)) - adjacentTargets(src, extendedAngle, adjacents); - else - adjacentTargets(src, angle, adjacents); - - first = false; - int rangeLeft = src.remaining - 1; - - for(int i = 0; i < 6; i++) { - Node dst = adjacents[i]; - if (dst != null) { - if (dst.search == searchCount) { - if ((rangeLeft > dst.remaining)) - dst.remaining = rangeLeft; - } else { - dst.search = searchCount; - dst.remaining = rangeLeft; - queue.add(dst); - Tile t = getTile(dst); - if (hasClearLineOfSight(from, dst, angle)) { - Iterator it = t.iterator(); - while (it.hasNext()) { - Pawn target = it.next(); - if (pawn.canEngage(target)) - targets.add(target); - } - } - } - } - } - } - - return targets.size(); - } - - public boolean canAttack(Pawn pawn, Pawn target, boolean clearVisibility) - { - Node from = getNode(pawn.getTile()); - Node to = getNode(target.getTile()); - - pawn.setAttack(target, distance(from, to)); - - if (pawn.attack.distance > pawn.getEngagementRangeFrom(pawn.getTile())) - return false; - - List los = lineOfSight(from.col, from.row, to.col, to.row, clearVisibility); - Node last = los.get(los.size() -1); - if (last != to) - return false; - - if (!validatePathAngle(pawn.getAngleOfAttack(), los)) - return false; - - pawn.attack.isClear = isClearAttack(getTile(from), los); - pawn.attack.isFlank = isFlankAttack(target.getFlankSides(), los); - - return true; - } - - private boolean hasClearLineOfSight(Node from, Node to, int angleOfAttack) - { - List los = lineOfSight(from.col, from.row, to.col, to.row, true); - Node last = los.get(los.size() -1); - if ((last.col != to.col) || (last.row != to.row)) - return false; - return validatePathAngle(angleOfAttack, los); - } - - private boolean isFlankAttack(int angle, List los) - { - Node from = los.get(los.size() - 2); - Node to = los.get(los.size() - 1); - Orientation o = Orientation.fromMove(to.col, to.row, from.col, from.row); - return o.isInSides(angle); - } - - private boolean isClearAttack(Tile from, List los) - { - int n = los.size() - 1; - for (int i = 1; i < n; i++) { - if (getTile(los.get(i)).blockLineOfSightFrom(from)) - return false; - } - return true; - } - - private boolean validatePathAngle(int angle, List los) - { - int forth = 0; - Node prev = null; - for (Node next : los) { - if (prev != null) { - Orientation o = Orientation.fromMove(prev.col, prev.row, next.col, next.row); - if (!o.isInSides(angle)) { - forth -= 1; - if (forth < 0) - return false; - } - forth += 1; - } - prev = next; - } - - return true; - } - - public List lineOfSight(int x0, int y0, int x1, int y1, boolean clearVisibility) - { - los.clear(); - Tile from = board.getTile(x0, y0); - - // orthogonal axis - int ox0 = x0 - ((y0 +1) / 2); - int ox1 = x1 - ((y1 +1) / 2); - - int dy = y1 - y0; - int dx = ox1 - ox0; - - int xs = 1; - int ys = 1; - if (dx < 0) xs = -1; - if (dy < 0) ys = -1; - boolean sig = !(((dx < 0) && (dy >= 0)) || ((dx >= 0) && (dy < 0))); - - dy = Math.abs(dy); - dx = Math.abs(2 * dx); - if ((dy % 2) == 1) { - if ((y0 % 2) == 0) dx += xs; - else { - dx -= xs; - Math.abs(dx); - } - } - - if (dx == 0) - return verticalLineOfSight(x0, y0, x1, y1, clearVisibility); - if (dx == (3 * dy)) - return diagonalLineOfSight(x0, y0, x1, y1, clearVisibility); - - int dx3 = 3 * dx; - int dy3 = 3 * dy; - - int x = x0; - int y = y0; - int e = -2 * dx; - - boolean flat = (dx > (3 * dy)); - boolean diag = (dx == (3 * dy)); - - los.add(getNode(x, y)); - while((x != x1) || (y != y1)) { - if (e > 0) { - e -= (dy3 + dx3); - y += ys; - if (!sig) - x -= xs; - } else { - e += dy3; - if ((e > -dx) || (!flat && (e == -dx))) { - e -= dx3; - y += ys; - if (sig) - x += xs; - } else if ((e < -dx3) || (diag && (e == -dx3))) { - e += dx3; - y -= ys; - if (!sig) - x += xs; - } else { - e += dy3; - x += xs; - } - } - los.add(getNode(x, y)); - if(clearVisibility && board.getTile(x, y).blockLineOfSightFrom(from)) return los; - } - - return los; - } - - private List verticalLineOfSight(int x0, int y0, int x1, int y1, boolean clearVisibility) - { - Tile from = board.getTile(x0, y0); - - int d = ( (y1 > y0) ? 1 : -1); - int x = x0; - int y = y0; - - Tile t = null; - los.add(getNode(x, y)); - while((x != x1) || (y != y1)) { - boolean ok = false; - - y += d; - t = board.getTile(x, y); - if (!t.isOffMap()) los.add(getNode(x, y)); - if (!clearVisibility || !t.blockLineOfSightFrom(from)) - ok = true; - - x += d; - t = board.getTile(x, y); - if (!t.isOffMap()) los.add(getNode(x, y)); - if (!clearVisibility || !t.blockLineOfSightFrom(from)) - ok = true; - - if (!ok) - return los; - - y += d; - t = board.getTile(x, y); - if (!t.isOffMap()) los.add(getNode(x, y)); - } - - return los; - } - - private List diagonalLineOfSight(int x0, int y0, int x1, int y1, boolean clearVisibility) - { - Tile from = board.getTile(x0, y0); - - int dy = ( (y1 > y0) ? 1 : -1); - int dx = ( (x1 > x0) ? 1 : -1); - boolean sig = !(((dx < 0) && (dy >= 0)) || ((dx >= 0) && (dy < 0))); - - int x = x0; - int y = y0; - - Tile t = null; - los.add(getNode(x, y)); - while((x != x1) || (y != y1)) { - boolean ok = false; - - x += dx; - t = board.getTile(x, y); - if (!t.isOffMap()) los.add(getNode(x, y)); - if (!clearVisibility || !t.blockLineOfSightFrom(from)) - ok = true; - - y += dy; - if (!sig) - x -= dx; - t = board.getTile(x, y); - if (!t.isOffMap()) los.add(getNode(x, y)); - if (!clearVisibility || !t.blockLineOfSightFrom(from)) - ok = true; - - if (!ok) - return los; - - x += dx; - t = board.getTile(x, y); - if (!t.isOffMap()) los.add(getNode(x, y)); - } - - return los; - } -} diff --git a/core/src/ch/asynk/tankontank/engine/SelectedTile.java b/core/src/ch/asynk/tankontank/engine/SelectedTile.java deleted file mode 100644 index 2c44ac9..0000000 --- a/core/src/ch/asynk/tankontank/engine/SelectedTile.java +++ /dev/null @@ -1,80 +0,0 @@ -package ch.asynk.tankontank.engine; - -import com.badlogic.gdx.utils.Disposable; - -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Drawable; -import ch.asynk.tankontank.engine.gfx.Animation; -import ch.asynk.tankontank.engine.gfx.animations.Sprites; - -public class SelectedTile implements Disposable, Drawable, Animation -{ - private Sprites sprites; - public Tile tile; - public boolean visible; - public float x; - public float y; - private float elapsed; - private int frame; - private float[] seq; - - public SelectedTile(Texture texture, float[] seq) - { - this.sprites = new Sprites(texture, seq.length, 1); - this.visible = false; - this.tile = null; - this.elapsed = 0f; - this.seq = seq; - } - - public void hide() - { - tile = null; - visible = false; - } - - public void set(Tile tile) - { - this.visible = true; - this.tile = tile; - this.frame = 0; - this.elapsed = 0f; - this.x = (tile.getX() - (sprites.width / 2f)); - this.y = (tile.getY() - (sprites.height / 2f)); - } - - public void dispose() - { - sprites.dispose(); - } - - @Override - public boolean animate(float delta) - { - if (visible) { - elapsed += delta; - if (elapsed > seq[frame]) { - frame = ((frame + 1) % sprites.frames.length); - elapsed = 0f; - } - } - return false; - } - - @Override - public void draw(Batch batch) - { - if (visible) - batch.draw(sprites.frames[frame], x, y); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - if (visible) - debugShapes.rect(x, y, sprites.width, sprites.height); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/Tile.java b/core/src/ch/asynk/tankontank/engine/Tile.java deleted file mode 100644 index 5f10fb1..0000000 --- a/core/src/ch/asynk/tankontank/engine/Tile.java +++ /dev/null @@ -1,175 +0,0 @@ -package ch.asynk.tankontank.engine; - -import java.util.List; -import java.util.Iterator; -import java.util.ArrayDeque; - -import com.badlogic.gdx.utils.Disposable; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; -import com.badlogic.gdx.math.Vector2; - -import ch.asynk.tankontank.engine.Board; -import ch.asynk.tankontank.engine.gfx.Drawable; -import ch.asynk.tankontank.engine.gfx.StackedImages; - -public abstract class Tile implements Drawable, Disposable, Iterable -{ - public interface TileTerrain - { - } - - protected int col; - protected int row; - protected float x; - protected float y; - private StackedImages overlays; - protected ArrayDeque stack; - - public abstract int defense(); - public abstract int exitCost(); - public abstract int costFrom(Pawn pawn, Orientation side); - - public abstract boolean isOffMap(); - public abstract boolean isA(TileTerrain terrain); - public abstract boolean road(Orientation side); - public abstract boolean atLeastOneMove(Pawn pawn); - public abstract boolean blockLineOfSightFrom(Tile tile); - - protected Tile(int col, int row) - { - this.col = col; - this.row = row; - } - - public Tile(float x, float y, int col, int row, TextureAtlas atlas) - { - this.stack = new ArrayDeque(); - this.x = x; - this.y = y; - this.col = col; - this.row = row; - this.overlays = new StackedImages(atlas); - this.overlays.centerOn(x, y); - } - - public float getX() { return x; } - public float getY() { return y; } - public int getCol() { return col; } - public int getRow() { return row; } - - @Override - public String toString() - { - return String.format("(%d;%d) %s", col, row, (isOffMap() ? "x" : "")); - } - - public String toShort() - { - return String.format("(%d;%d)", col, row); - } - - @Override - public void dispose() - { - stack.clear(); - overlays.dispose(); - } - - public boolean isEmpty() - { - return stack.isEmpty(); - } - - public Iterator iterator() - { - return stack.iterator(); - } - - public int push(Pawn pawn) - { - if (!stack.contains(pawn)) - stack.push(pawn); - return stack.size(); - } - - public int remove(Pawn pawn) - { - stack.remove(pawn); - return stack.size(); - } - - private Pawn getTopPawn() - { - if (isEmpty()) return null; - return stack.getFirst(); - } - - public boolean hasUnits() - { - if (isEmpty()) return false; - Iterator itr = iterator(); - while(itr.hasNext()) { - if (itr.next().isUnit()) - return true; - } - return false; - } - - public boolean mustBeDrawn() - { - if (!isEmpty()) return true; - return hasOverlayEnabled(); - } - - public boolean disableOverlays() - { - overlays.disableAll(); - return !isEmpty(); - } - - public boolean hasOverlayEnabled() - { - return overlays.isEnabled(); - } - - public boolean isOverlayEnabled(int i) - { - return overlays.isEnabled(i); - } - - public boolean enableOverlay(int i, boolean enable) - { - overlays.enable(i, enable); - if (enable) return true; - return mustBeDrawn(); - } - - public boolean enableOverlay(int i, boolean enable, float r) - { - overlays.enable(i, enable); - overlays.rotate(i, r); - if (enable) return true; - return mustBeDrawn(); - } - - @Override - public void draw(Batch batch) - { - overlays.draw(batch); - Pawn pawn = getTopPawn(); - if (pawn != null) - pawn.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - overlays.drawDebug(debugShapes); - Pawn pawn = getTopPawn(); - if (pawn != null) - pawn.drawDebug(debugShapes); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/Animation.java b/core/src/ch/asynk/tankontank/engine/gfx/Animation.java deleted file mode 100644 index 595c0da..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/Animation.java +++ /dev/null @@ -1,8 +0,0 @@ -package ch.asynk.tankontank.engine.gfx; - -import com.badlogic.gdx.utils.Disposable; - -public interface Animation extends Disposable, Drawable -{ - public boolean animate(float delta); -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/Drawable.java b/core/src/ch/asynk/tankontank/engine/gfx/Drawable.java deleted file mode 100644 index 433a019..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/Drawable.java +++ /dev/null @@ -1,10 +0,0 @@ -package ch.asynk.tankontank.engine.gfx; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -public interface Drawable -{ - public void draw(Batch batch); - public void drawDebug(ShapeRenderer debugShapes); -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/Moveable.java b/core/src/ch/asynk/tankontank/engine/gfx/Moveable.java deleted file mode 100644 index 0f57595..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/Moveable.java +++ /dev/null @@ -1,16 +0,0 @@ -package ch.asynk.tankontank.engine.gfx; - -import ch.asynk.tankontank.engine.Faction; - -public interface Moveable extends Drawable -{ - public void setAlpha(float alpha); - public float getX(); - public float getY(); - public float getWidth(); - public float getHeight(); - public float getRotation(); - public void setPosition(float x, float y); - public void setPosition(float x, float y, float r); - public Faction getFaction(); -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/StackedImages.java b/core/src/ch/asynk/tankontank/engine/gfx/StackedImages.java deleted file mode 100644 index cb91016..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/StackedImages.java +++ /dev/null @@ -1,99 +0,0 @@ -package ch.asynk.tankontank.engine.gfx; - -import com.badlogic.gdx.utils.Disposable; - -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; -import com.badlogic.gdx.utils.Array; - -public class StackedImages implements Drawable, Disposable -{ - private boolean enabled[]; - private Array sprites; - - public StackedImages(TextureAtlas atlas) - { - this.sprites = atlas.createSprites(); - this.enabled = new boolean[sprites.size]; - } - - @Override - public void dispose() - { - } - - public void disableAll() - { - for (int i = 0; i < sprites.size; i++) - enabled[i] = false; - } - - public void enable(int i, boolean enable) - { - enabled[i] = enable; - } - - public boolean isEnabled(int i) - { - return enabled[i]; - } - - public boolean isEnabled() - { - for (int i = 0; i < sprites.size; i++) - if (enabled[i]) return true; - return false; - } - - public void setAlpha(float alpha) - { - for (int i = 0, n = sprites.size; i < n; i++) - sprites.get(i).setAlpha(alpha); - } - - public void rotate(int i, float r) - { - sprites.get(i).setRotation(r); - } - - public void setRotation(float r) - { - for (int i = 0, n = sprites.size; i < n; i++) - sprites.get(i).setRotation(r); - } - - public void translate(float dx, float dy) - { - for (int i = 0, n = sprites.size; i < n; i++) - sprites.get(i).translate(dx, dy); - } - - public void centerOn(float cx, float cy) - { - for (int i = 0, n = sprites.size; i < n; i++) { - float x = (cx - (sprites.get(i).getWidth() / 2f)); - float y = (cy - (sprites.get(i).getHeight() / 2f)); - sprites.get(i).setPosition(x, y); - } - } - - @Override - public void draw(Batch batch) - { - for (int i = 0, n = sprites.size; i < n; i++) { - if (enabled[i]) - sprites.get(i).draw(batch); - } - } - - @Override - public void drawDebug(ShapeRenderer shapes) - { - Sprite sprite = sprites.get(0); - float w = sprite.getWidth(); - float h = sprite.getHeight(); - shapes.rect(sprite.getX(), sprite.getY(), (w / 2f), (h / 2f), w, h, sprite.getScaleX(), sprite.getScaleY(), sprite.getRotation()); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/AnimationSequence.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/AnimationSequence.java deleted file mode 100644 index 4a111f3..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/AnimationSequence.java +++ /dev/null @@ -1,76 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import java.util.ArrayList; - -import com.badlogic.gdx.utils.Pool; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Animation; - -public class AnimationSequence implements Animation, Pool.Poolable -{ - private ArrayList animations; - - private static final Pool animationSequencePool = new Pool() { - @Override - protected AnimationSequence newObject() { - return new AnimationSequence(); - } - }; - - public static AnimationSequence get(int capacity) - { - AnimationSequence seq = animationSequencePool.obtain(); - if (seq.animations == null) - seq.animations = new ArrayList(capacity); - else - seq.animations.ensureCapacity(capacity); - - return seq; - } - - @Override - public void reset() - { - for (int i = 0, n = animations.size(); i < n; i++) - animations.get(i).dispose(); - animations.clear(); - } - - @Override - public void dispose() - { - animationSequencePool.free(this); - } - - public void addAnimation(Animation animation) - { - animations.add(animation); - } - - @Override - public boolean animate(float delta) - { - if(animations.isEmpty()) return true; - - Animation animation = animations.get(0); - if (animation.animate(delta)) { - animations.remove(0); - } - - return (animations.isEmpty()); - } - - @Override - public void draw(Batch batch) - { - animations.get(0).draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - animations.get(0).drawDebug(debugShapes); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/DestroyAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/DestroyAnimation.java deleted file mode 100644 index da05d1a..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/DestroyAnimation.java +++ /dev/null @@ -1,62 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Moveable; -import ch.asynk.tankontank.engine.gfx.Animation; - -public class DestroyAnimation implements Disposable, Animation -{ - private static final float DELAY = 1.5f; - private static final float DURATION = 1.5f; - - private Moveable moveable; - private float x; - private float y; - private int alphaP; - private float elapsed; - - @Override - public void dispose() - { - } - - public void set(float duration, Moveable moveable) - { - this.moveable = moveable; - this.alphaP = 0; - this.elapsed = 0f; - this.x = (moveable.getX() + (moveable.getWidth() / 2f)); - this.y = (moveable.getY() + (moveable.getHeight() / 2f)); - } - - @Override - public boolean animate(float delta) - { - elapsed += delta; - if (elapsed < DELAY) - return false; - - int a = (int) (((elapsed - DELAY) / DURATION) * 10); - if (a != alphaP) { - alphaP = a; - moveable.setAlpha(1f - (alphaP / 10f)); - } - - return (elapsed >= (DELAY + DURATION)); - } - - @Override - public void draw(Batch batch) - { - moveable.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - moveable.drawDebug(debugShapes); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/DiceAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/DiceAnimation.java deleted file mode 100644 index fbedea6..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/DiceAnimation.java +++ /dev/null @@ -1,141 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import java.util.Random; - -import com.badlogic.gdx.audio.Sound; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Drawable; -import ch.asynk.tankontank.engine.gfx.Animation; - -public class DiceAnimation implements Animation, Drawable -{ - private static final float DURATION = 0.7f; - private static final float DURATION_SCATTERING = 0.5f; - private static final int DICE_DIMENSION = 24; - - private static Random random = new Random(); - private static Sprites dice; - private static Sound sound; - private static double sndId; - private static float volume; - private static int[][] rolls = new int[][]{ - { 25, 40, 55, 70, 85, 100, 115, 99, 83, 67, 51, 36, 37, 52, 67, 66, 65, 64 }, - { 58, 74, 59, 60, 45, 62, 78, 94, 109, 108, 123, 106, 89, 71, 70, 69, 68 }, - { 106, 121, 120, 103, 86, 70, 54, 37, 20, 19, 18, 34, 50, 51, 52, 69, 86, 103, 119, 128 }, - { 95, 79, 93, 92, 91, 90, 104, 103, 102, 85, 84, 67, 66, 65, 49, 32, 16, 0 }, - { 22, 39, 56, 73, 90, 107, 124, 128, 113, 98, 83, 68, 53, 38, 23, 0, 25, 42, 59, 76 }, - { 79, 78, 61, 76, 91, 106, 121, 120, 119, 102, 101, 84, 68, 52, 37, 38, 39, 40, 41, 58, 75, 74, 73, 72 }, - }; - - private float x; - private float y; - private int frame; - private int[] roll; - private float elapsed; - private float duration; - // public boolean stop; - - public static void init(Texture texture, int cols, int rows, Sound s) - { - dice = new Sprites(texture, cols, rows); - sound = s; - sndId = -1; - } - - public static void initSound(float v) - { - sndId = -1; - volume = v; - } - - public static void free() - { - sound.dispose(); - dice.dispose(); - } - - public void translate(float dx, float dy) - { - x += dx; - y += dy; - } - - public float getX() - { - return x; - } - - public float getY() - { - return y; - } - - public int getWidth() - { - return DICE_DIMENSION; - } - - public int getHeight() - { - return DICE_DIMENSION; - } - - public void setPosition(float x, float y) - { - this.x = x; - this.y = y; - } - - public void set(int result) - { - this.frame = 0; - this.elapsed = 0f; - this.roll = rolls[result - 1]; - this.duration = DURATION + (DURATION_SCATTERING * random.nextFloat()); - // this.stop = false; - } - - public boolean isDone() - { - return (elapsed >= duration); - } - - @Override - public void dispose() - { - } - - @Override - public boolean animate(float delta) - { - // if (stop) - // return true; - elapsed += delta; - if (elapsed < duration) { - int idx = (int) (roll.length * elapsed / duration); - if (idx >= roll.length) - idx = (roll.length -1); - frame = roll[idx]; - } - if (sndId == -1) - sndId = sound.play(volume); - - return false; - } - - @Override - public void draw(Batch batch) - { - batch.draw(dice.frames[frame], x, y, DICE_DIMENSION, DICE_DIMENSION); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - debugShapes.rect(x, y, dice.frames[frame].getRegionWidth(), dice.frames[frame].getRegionHeight()); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/FireAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/FireAnimation.java deleted file mode 100644 index a13c234..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/FireAnimation.java +++ /dev/null @@ -1,87 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import java.util.Random; - -import com.badlogic.gdx.audio.Sound; -import com.badlogic.gdx.graphics.Texture; - -public class FireAnimation -{ - public static Random random = new Random(); - - public static Sprites infantryFire; - public static Sprites tankFire; - public static Sprites explosion; - - public static Sound infantryFireSnd; - public static Sound tankFireSnd; - public static Sound tankFireSndLong; - public static Sound explosionSnd; - public static Sound explosionSndLong; - - public static double infantryFireSndLongId; - public static double tankFireSndLongId; - public static double explosionSndLongId; - - public static void init( - Texture infantryFireT, int iCols, int iRows, - Texture tankFireT, int sCols, int sRows, - Texture explosionT, int eCols, int eRows, - Sound infantryFireS, - Sound tankFireS, - Sound tankFireLongS, - Sound explosionS, - Sound explosionLongS) - { - infantryFire = new Sprites(infantryFireT, iCols, iRows); - tankFire = new Sprites(tankFireT, sCols, sRows); - explosion = new Sprites(explosionT, eCols, eRows); - infantryFireSnd = infantryFireS; - tankFireSnd = tankFireS; - tankFireSndLong = tankFireLongS; - explosionSnd = explosionS; - explosionSndLong = explosionLongS; - - reset(); - } - - public static void reset() - { - infantryFireSndLongId = -1; - tankFireSndLongId = -1; - explosionSndLongId = -1; - } - - public static void free() - { - tankFire.dispose(); - explosion.dispose(); - - tankFireSnd.dispose(); - tankFireSndLong.dispose(); - explosionSnd.dispose(); - explosionSndLong.dispose(); - } - - public static void infantryFireSndPlay(float volume) - { - if (infantryFireSndLongId == -1) - infantryFireSndLongId = infantryFireSnd.play(volume); - } - - public static void tankFireSndPlay(float volume) - { - if (tankFireSndLongId == -1) - tankFireSndLongId = tankFireSndLong.play(volume); - else - tankFireSnd.play(volume); - } - - public static void explosionSndPlay(float volume) - { - if (explosionSndLongId == -1) - explosionSndLongId = explosionSndLong.play(volume); - else - explosionSnd.play(volume); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/InfantryFireAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/InfantryFireAnimation.java deleted file mode 100644 index 81c8713..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/InfantryFireAnimation.java +++ /dev/null @@ -1,222 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import java.util.Random; - -import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.utils.Pool; - -import com.badlogic.gdx.audio.Sound; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Drawable; -import ch.asynk.tankontank.engine.gfx.Animation; - -public class InfantryFireAnimation implements Disposable, Animation, Pool.Poolable -{ - class Shot - { - public TextureRegion fireRegion; - public float fire_a; - public float fire_x; - public float fire_y; - public float fire_w; - public float fire_dx; - public float fire_dy; - public float fire_dw; - - public boolean fired; - public boolean hit; - public boolean completed; - - public float fire_time; - public float hit_time; - public float end_time; - - public int hit_frame; - - public Shot(TextureRegion region) - { - this.fireRegion = region; - } - - public void set(float delay, float x0, float y0, float x1, float y1, float w, float a) - { - float dx = (x1 - x0); - float dy = (y1 - y0); - - // timing - float fire_duration = ((FireAnimation.random.nextFloat() * TIME_SCATTERING) + (w / SHOT_SPEED)); - float hit_duration = (FireAnimation.infantryFire.rows * HIT_FRAME_DURATION); - - this.fired = false; - this.fire_time = delay; - this.hit_time = (this.fire_time + fire_duration); - this.end_time = (this.hit_time + hit_duration); - - // fire vars - this.fire_a = a; - this.fire_x = x0; - this.fire_y = y0; - this.fire_w = 0; - this.fire_dx = (dx / fire_duration); - this.fire_dy = (dy / fire_duration); - this.fire_dw = (w / fire_duration); - this.hit_frame = 0; - } - - public boolean animate(float delta) - { - if (!fired && (elapsed < fire_time)) - return false; - - if (!fired) { - fired = true; - FireAnimation.infantryFireSndPlay(volume); - } - - if (!hit && (elapsed < hit_time)) { - fire_w += (fire_dw * delta); - fire_x += (fire_dx * delta); - fire_y += (fire_dy * delta); - fireRegion.setRegionWidth((int) fire_w); - return false; - } - - if (!hit) - hit = true; - - if (elapsed < end_time) { - int frame = (int) ((elapsed - hit_time) / HIT_FRAME_DURATION); - if (frame != hit_frame) { - hit_frame = frame; - fireRegion.setRegion(FireAnimation.infantryFire.frames[hit_frame]); - fireRegion.setRegionWidth((int) fire_w); - } - return false; - } - - completed = true; - return true; - } - - public void draw(Batch batch) - { - if (fired && !completed) - batch.draw(fireRegion, fire_x, fire_y, 0, 0, fireRegion.getRegionWidth(), fireRegion.getRegionHeight(), 1f, 1f, fire_a); - } - } - - private static final int SHOT_COUNT = 19; - private static final float SHOT_DELAY = (1.6f / SHOT_COUNT); - private static final float SHOT_SCATTERING = 40f; - private static final float TIME_SCATTERING = 0.6f; - private static final float START_DELAY = 0.8f; - private static final float SHOT_SPEED = 1000f; - private static final float HIT_FRAME_DURATION = 0.05f; - - private Shot[] shots; - - private float elapsed; - - private float volume; - - private static final Pool fireAnimationPool = new Pool() { - @Override - protected InfantryFireAnimation newObject() { - return new InfantryFireAnimation(); - } - }; - - public static InfantryFireAnimation get(float volume, float x0, float y0, float x1, float y1, float halfWidth) - { - InfantryFireAnimation a = fireAnimationPool.obtain(); - a.set(volume, x0, y0, x1, y1, halfWidth); - return a; - } - - public InfantryFireAnimation() - { - this.shots = new Shot[SHOT_COUNT]; - for (int i = 0; i < shots.length; i++) - shots[i] = new Shot(new TextureRegion(FireAnimation.infantryFire.frames[0])); - } - - private void set(float volume, float x0, float y0, float x1, float y1, float halfWidth) - { - this.volume = volume; - this.elapsed = 0f; - - float delay = START_DELAY + (FireAnimation.random.nextFloat() * TIME_SCATTERING); - - y0 -= (FireAnimation.infantryFire.height / 2.0f); - double r = Math.atan2((y0 - y1), (x0 - x1)); - x0 -= ((float) (Math.cos(r) * halfWidth)); - y0 -= ((float) (Math.sin(r) * halfWidth)); - - float dx = (x1 - x0); - float dy = (y1 - y0); - float w = (float) Math.sqrt((dx * dx) + (dy * dy)); - double dr = (Math.atan2(halfWidth, w) / 2f); - - double a = (r + (dr / 2f)); - double da = (dr / (float) SHOT_COUNT); - - for (Shot shot : shots) { - float x = (float) (x0 - (Math.cos(a) * w)); - float y = (float) (y0 - (Math.sin(a) * w)); - - shot.set(delay, x0, y0, x, y, w, (float) Math.toDegrees(a)); - - delay += SHOT_DELAY; - a -= 2 * (da * FireAnimation.random.nextFloat()); - } - } - - @Override - public void reset() - { - } - - @Override - public void dispose() - { - fireAnimationPool.free(this); - } - - @Override - public boolean animate(float delta) - { - elapsed += delta; - - boolean completed = true; - for (Shot shot : shots) - completed &= shot.animate(delta); - - return completed; - } - - @Override - public void draw(Batch batch) - { - for (Shot shot : shots) - shot.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - // debugShapes.end(); - // debugShapes.begin(ShapeRenderer.ShapeType.Line); - // debugShapes.identity(); - // debugShapes.translate(fire_x, fire_y, 0); - // debugShapes.rotate(0, 0, 1, fire_a); - // debugShapes.translate(-fire_x, -fire_y, 0); - // debugShapes.rect(fire_x, fire_y, fire_w, FireAnimation.infantryFire.height); - // debugShapes.end(); - // debugShapes.begin(ShapeRenderer.ShapeType.Line); - // debugShapes.identity(); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/MoveToAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/MoveToAnimation.java deleted file mode 100644 index ac09367..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/MoveToAnimation.java +++ /dev/null @@ -1,126 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import com.badlogic.gdx.math.Vector3; -import com.badlogic.gdx.utils.Pool; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Moveable; - -public class MoveToAnimation extends TimedAnimation -{ - public interface MoveToAnimationCb { - void moveToAnimationLeave(Moveable moveable, float x, float y, float r); - void moveToAnimationEnter(Moveable moveable, float x, float y, float r); - void moveToAnimationDone(Moveable moveable, float x, float y, float r); - } - - private Moveable moveable; - private float fromX; - private float fromY; - private float fromR; - private float toX; - private float toY; - private float toR; - private float rDelta; - private boolean notified; - private MoveToAnimationCb cb; - - private static final Pool moveToAnimationPool = new Pool() { - @Override - protected MoveToAnimation newObject() { - return new MoveToAnimation(); - } - }; - - public static MoveToAnimation get(Moveable moveable, Vector3 v, float duration) - { - return get(moveable, v.x, v.y, v.z, duration); - } - - public static MoveToAnimation get(Moveable moveable, Vector3 v, float duration, MoveToAnimationCb cb) - { - return get(moveable, v.x, v.y, v.z, duration, cb); - } - - public static MoveToAnimation get(Moveable moveable, float x, float y, float r, float duration) - { - return get(moveable, x, y, r, duration, null); - } - - public static MoveToAnimation get(Moveable moveable, float x, float y, float r, float duration, MoveToAnimationCb cb) - { - MoveToAnimation a = moveToAnimationPool.obtain(); - - a.moveable = moveable; - a.toX = x; - a.toY = y; - a.toR = r; - a.duration = duration; - a.cb = cb; - a.rDelta = 0; - a.notified = false; - - return a; - } - - @Override - public void dispose() - { - moveToAnimationPool.free(this); - } - - @Override - protected void begin() - { - fromX = moveable.getX(); - fromY = moveable.getY(); - fromR = moveable.getRotation(); - notified = ((fromX == toX) && (fromY == toY)); - - if (Math.abs(toR - fromR) <= 180.f) - rDelta = (toR - fromR); - else { - if (toR > fromR) - rDelta = (toR - 360 - fromR); - else - rDelta = (toR + 360 - fromR); - } - } - - @Override - protected void end() - { - if (cb != null) - cb.moveToAnimationDone(moveable, (toX + (moveable.getWidth() / 2)), (toY + (moveable.getHeight() / 2)), toR); - dispose(); - } - - @Override - protected void update(float percent) - { - if ((cb != null) && !notified && (percent >= 0.5)) { - float dw = (moveable.getWidth() / 2); - float dh = (moveable.getHeight() / 2); - cb.moveToAnimationLeave(moveable, (fromX + dw), (fromY + dh), fromR); - cb.moveToAnimationEnter(moveable, (toX + dw), (toY + dh), toR); - notified = true; - } - if (percent == 1f) - moveable.setPosition(toX, toY, (int) toR); - else - moveable.setPosition(fromX + ((toX - fromX) * percent), fromY + ((toY - fromY) * percent), (fromR + (rDelta * percent))); - } - - @Override - public void draw(Batch batch) - { - moveable.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - moveable.drawDebug(debugShapes); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/PromoteAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/PromoteAnimation.java deleted file mode 100644 index d9f84d9..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/PromoteAnimation.java +++ /dev/null @@ -1,98 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import java.lang.Math; - -import com.badlogic.gdx.audio.Sound; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Drawable; -import ch.asynk.tankontank.engine.gfx.Animation; - -public class PromoteAnimation implements Animation, Drawable -{ - private static PromoteAnimation instance = new PromoteAnimation(); - - private static final float DURATION = 0.3f; - private static final float MAX_SCALE = 2f; - - private static Sound usSound; - private static Sound geSound; - private static Sound snd; - private static TextureRegion region; - - private float x0; - private float y0; - private float x; - private float y; - private float scale; - private float step; - private float volume; - private float elapsed; - - public static void init(TextureAtlas atlas, Sound usSnd, Sound geSnd) - { - region = atlas.findRegion("stars"); - usSound = usSnd; - geSound = geSnd; - } - - public static void free() - { - } - - protected void PromoteAnimation() - { - } - - public static PromoteAnimation get(boolean us, float x, float y, float v) - { - x = (x - (region.getRegionWidth() / 2.0f)); - y = (y - (region.getRegionHeight() / 2.0f)); - - instance.volume = v; - instance.x0 = x; - instance.y0 = y; - instance.scale = 0f; - instance.elapsed = 0f; - snd = (us ? usSound : geSound); - - return instance; - } - - @Override - public void dispose() - { - } - - @Override - public boolean animate(float delta) - { - elapsed += delta; - if (elapsed >= DURATION) { - snd.play(volume); - return true; - } - - float s = MAX_SCALE * (float) Math.sin(Math.PI / DURATION * elapsed); - scale = 1f + s; - x = x0 - ((region.getRegionWidth() * scale) / 4f); - y = y0 - ((region.getRegionHeight() * scale) / 4f); - - return false; - } - - @Override - public void draw(Batch batch) - { - batch.draw(region, x, y, 0, 0, region.getRegionWidth(), region.getRegionHeight(), scale, scale, 0f); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - debugShapes.rect(x, y, region.getRegionWidth(), region.getRegionHeight()); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/RunnableAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/RunnableAnimation.java deleted file mode 100644 index 4f81f33..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/RunnableAnimation.java +++ /dev/null @@ -1,67 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import com.badlogic.gdx.utils.Pool; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Moveable; -import ch.asynk.tankontank.engine.gfx.Animation; - -public class RunnableAnimation implements Animation, Pool.Poolable -{ - private Runnable runnable; - private Moveable moveable; - private boolean ran; - - private static final Pool runnableAnimationPool = new Pool() { - @Override - protected RunnableAnimation newObject() { - return new RunnableAnimation(); - } - }; - - public static RunnableAnimation get(Moveable moveable, Runnable runnable) - { - RunnableAnimation a = runnableAnimationPool.obtain(); - a.runnable = runnable; - a.moveable = moveable; - return a; - } - - @Override - public void reset() - { - ran = false; - } - - @Override - public void dispose() - { - runnableAnimationPool.free(this); - } - - @Override - public boolean animate(float delta) - { - if (ran) return true; - - runnable.run(); - runnable = null; - ran = true; - dispose(); - - return true; - } - - @Override - public void draw(Batch batch) - { - moveable.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - moveable.drawDebug(debugShapes); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/SoundAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/SoundAnimation.java deleted file mode 100644 index 797b09b..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/SoundAnimation.java +++ /dev/null @@ -1,83 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import com.badlogic.gdx.utils.Pool; -import com.badlogic.gdx.audio.Sound; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -public class SoundAnimation extends TimedAnimation -{ - public enum Action - { - FADE_IN, - FADE_OUT - }; - - private Sound sound; - private long soundId; - private Action action; - private float volume; - - private static final Pool soundAnimationPool = new Pool() { - @Override - protected SoundAnimation newObject() { - return new SoundAnimation(); - } - }; - - public static SoundAnimation get(Action action, Sound sound, long soundId, float volume, float duration) - { - SoundAnimation a = soundAnimationPool.obtain(); - - a.action = action; - a.sound = sound; - a.soundId = soundId; - a.volume = volume; - a.duration = duration; - - return a; - } - - @Override - public void dispose() - { - soundAnimationPool.free(this); - } - - @Override - protected void begin() - { - } - - @Override - protected void end() - { - dispose(); - } - - @Override - protected void update(float percent) - { - float v; - switch(action) { - case FADE_IN: - v = ( volume * percent); - sound.setVolume(soundId, v); - break; - case FADE_OUT: - v = (volume - ( volume * percent)); - sound.setVolume(soundId, v); - break; - } - } - - @Override - public void draw(Batch batch) - { - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/SpriteAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/SpriteAnimation.java deleted file mode 100644 index 7a94810..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/SpriteAnimation.java +++ /dev/null @@ -1,76 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import java.util.Random; - -import com.badlogic.gdx.utils.Disposable; - -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Drawable; -import ch.asynk.tankontank.engine.gfx.Animation; - -public class SpriteAnimation implements Disposable, Animation -{ - private static Random random = new Random(); - private Sprites sprites; - private float duration; - private float frameDuration; - private float elapsed; - private float x0; - private float y0; - private float x1; - private float y1; - private int randFreq; - - public SpriteAnimation(Texture texture, int cols, int rows, int randFreq) - { - this.sprites = new Sprites(texture, cols, rows); - this.randFreq = randFreq; - } - - @Override - public void dispose() - { - sprites.dispose(); - } - - public void init(float duration, float x, float y) - { - this.duration = duration; - this.frameDuration = (duration / (float) sprites.frames.length); - this.x0 = x - (sprites.width / 2f); - this.y0 = y - (sprites.height / 2f); - this.elapsed = 0f; - randPos(); - } - - private void randPos() - { - this.x1 = this.x0 + (random.nextInt(sprites.width) - (sprites.width / 2)); - this.y1 = this.y0 + (random.nextInt(sprites.height) - (sprites.height / 2)); - } - - @Override - public boolean animate(float delta) - { - elapsed += delta; - return (elapsed >= duration); - } - - @Override - public void draw(Batch batch) - { - int n = (((int)(elapsed / frameDuration)) % sprites.frames.length); - if ((n > 0) && (n % randFreq) == 0) - randPos(); - batch.draw(sprites.frames[n], x1, y1); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/Sprites.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/Sprites.java deleted file mode 100644 index a3bf2a4..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/Sprites.java +++ /dev/null @@ -1,38 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.TextureRegion; - -public class Sprites implements Disposable -{ - public Texture texture; - public TextureRegion[] frames; - public final int width; - public final int height; - public final int cols; - public final int rows; - - public Sprites(Texture texture, int cols, int rows) - { - this.cols = cols; - this.rows = rows; - this.width = (texture.getWidth() / cols); - this.height = (texture.getHeight() / rows); - this.texture = texture; - TextureRegion[][] tmp = TextureRegion.split(texture, width, height); - frames = new TextureRegion[cols * rows]; - int idx = 0; - for (int i = 0; i < rows; i++) { - for (int j = 0; j < cols; j++) { - frames[idx++] = tmp[i][j]; - } - } - } - - @Override - public void dispose() - { - texture.dispose(); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/TankFireAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/TankFireAnimation.java deleted file mode 100644 index 8411bac..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/TankFireAnimation.java +++ /dev/null @@ -1,196 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import java.util.Random; - -import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.utils.Pool; - -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Drawable; -import ch.asynk.tankontank.engine.gfx.Animation; - -public class TankFireAnimation implements Disposable, Animation, Pool.Poolable -{ - private static final float SHOT_SCATTERING = 60f; - private static final float TIME_SCATTERING = 0.6f; - private static final float START_DELAY = 0.8f; - private static final float SHOT_SPEED = 900f; - private static final float EXPLOSION_FRAME_DURATION = 0.07f; - - private TextureRegion fireRegion; - private float fire_a; - private float fire_x; - private float fire_y; - private float fire_w; - private float fire_dx; - private float fire_dy; - private float fire_dw; - - private float smoke_df; - private int smoke_frame; - - private float explosion_x; - private float explosion_y; - private float explosion_df; - private int explosion_frame; - - private boolean fired; - private boolean hit; - private float elapsed; - private float fire_time; - private float hit_time; - private float end_time; - - private float volume; - - private static final Pool fireAnimationPool = new Pool() { - @Override - protected TankFireAnimation newObject() { - return new TankFireAnimation(); - } - }; - - public static TankFireAnimation get(float volume, float x0, float y0, float x1, float y1, float halfWidth) - { - TankFireAnimation a = fireAnimationPool.obtain(); - a.set(volume, x0, y0, x1, y1, halfWidth); - return a; - } - - public TankFireAnimation() - { - this.fireRegion = new TextureRegion(FireAnimation.tankFire.frames[0]); - } - - private void set(float volume, float x0, float y0, float x1, float y1, float halfWidth) - { - this.fired = false; - this.hit = false; - this.volume = volume; - - // fire geometry - y0 -= (FireAnimation.tankFire.height / 2.0f); - x1 += ((SHOT_SCATTERING * FireAnimation.random.nextFloat()) - (SHOT_SCATTERING / 2f)); - y1 += ((SHOT_SCATTERING * FireAnimation.random.nextFloat()) - (SHOT_SCATTERING / 2f)); - - double r = Math.atan2((y0 - y1), (x0 - x1)); - float xadj = (float) (Math.cos(r) * halfWidth); - float yadj = (float) (Math.sin(r) * halfWidth); - x0 -= xadj; - y0 -= yadj; - - float a = (float) Math.toDegrees(r); - float dx = (x1 - x0); - float dy = (y1 - y0); - float w = (float) Math.sqrt((dx * dx) + (dy * dy)); - - // timing - float delay = START_DELAY + (FireAnimation.random.nextFloat() * TIME_SCATTERING); - float fire_duration = ((FireAnimation.random.nextFloat() * TIME_SCATTERING) + (w / SHOT_SPEED)); - float explosion_duration = (FireAnimation.explosion.cols * EXPLOSION_FRAME_DURATION); - - this.elapsed = 0f; - this.fire_time = delay; - this.hit_time = (fire_time + fire_duration); - this.end_time = (hit_time + explosion_duration); - - // fire vars - this.fire_a = a; - this.fire_x = x0; - this.fire_y = y0; - this.fire_w = 0; - this.fire_dx = (dx / fire_duration); - this.fire_dy = (dy / fire_duration); - this.fire_dw = (w / fire_duration); - - // smoke var - this.smoke_df = (FireAnimation.tankFire.rows / explosion_duration); - this.smoke_frame = 0; - - // explosion vars - this.explosion_x = (x1 - (FireAnimation.explosion.width / 2.0f)); - this.explosion_y = (y1 - (FireAnimation.explosion.height / 2.0f)); - this.explosion_df = (FireAnimation.explosion.cols / explosion_duration); - this.explosion_frame = (FireAnimation.random.nextInt(FireAnimation.explosion.rows) * FireAnimation.explosion.cols); - } - - @Override - public void reset() - { - } - - @Override - public void dispose() - { - fireAnimationPool.free(this); - } - - @Override - public boolean animate(float delta) - { - elapsed += delta; - - if (!fired && (elapsed < fire_time)) - return false; - - if (!fired) { - fired = true; - FireAnimation.tankFireSndPlay(volume); - } - - if (!hit && (elapsed < hit_time)) { - fire_w += (fire_dw * delta); - fire_x += (fire_dx * delta); - fire_y += (fire_dy * delta); - fireRegion.setRegionWidth((int) fire_w); - return false; - } - - if (!hit) { - hit = true; - FireAnimation.explosionSndPlay(volume); - } - - if (elapsed < end_time) { - int frame = (int) ((elapsed - hit_time) * smoke_df); - if (frame != smoke_frame) { - smoke_frame = frame; - fireRegion.setRegion(FireAnimation.tankFire.frames[smoke_frame]); - fireRegion.setRegionWidth((int) fire_w); - } - return false; - } - - return true; - } - - @Override - public void draw(Batch batch) - { - if (fired) - batch.draw(fireRegion, fire_x, fire_y, 0, 0, fireRegion.getRegionWidth(), fireRegion.getRegionHeight(), 1f, 1f, fire_a); - - if (hit) { - int frame = (explosion_frame + (int) ((elapsed - hit_time) * explosion_df)); - batch.draw(FireAnimation.explosion.frames[frame], explosion_x, explosion_y); - } - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - debugShapes.end(); - debugShapes.begin(ShapeRenderer.ShapeType.Line); - debugShapes.identity(); - debugShapes.translate(fire_x, fire_y, 0); - debugShapes.rotate(0, 0, 1, fire_a); - debugShapes.translate(-fire_x, -fire_y, 0); - debugShapes.rect(fire_x, fire_y, fire_w, FireAnimation.tankFire.height); - debugShapes.end(); - debugShapes.begin(ShapeRenderer.ShapeType.Line); - debugShapes.identity(); - } -} diff --git a/core/src/ch/asynk/tankontank/engine/gfx/animations/TimedAnimation.java b/core/src/ch/asynk/tankontank/engine/gfx/animations/TimedAnimation.java deleted file mode 100644 index 96eed32..0000000 --- a/core/src/ch/asynk/tankontank/engine/gfx/animations/TimedAnimation.java +++ /dev/null @@ -1,48 +0,0 @@ -package ch.asynk.tankontank.engine.gfx.animations; - -import com.badlogic.gdx.utils.Pool; - -import ch.asynk.tankontank.engine.gfx.Animation; - -public abstract class TimedAnimation implements Animation, Pool.Poolable -{ - private float time; - private boolean began; - private boolean completed; - protected float duration; - - abstract protected void begin(); - abstract protected void end(); - abstract protected void update(float percent); - - @Override - public void reset() - { - time = 0f; - began = false; - completed = false; - } - - @Override - public boolean animate(float delta) - { - if (completed) return true; - - if (!began) { - begin(); - began = true; - } - - time += delta; - completed = (time >= duration); - - if (!completed) { - update(time / duration); - return false; - } - - update(1); - end(); - return true; - } -} diff --git a/core/src/ch/asynk/tankontank/game/Army.java b/core/src/ch/asynk/tankontank/game/Army.java deleted file mode 100644 index 7a5454e..0000000 --- a/core/src/ch/asynk/tankontank/game/Army.java +++ /dev/null @@ -1,30 +0,0 @@ -package ch.asynk.tankontank.game; - -import ch.asynk.tankontank.engine.Faction; - -public enum Army implements Faction -{ - NONE("None"), - GE("German"), - US("US"), - USSR("Soviet"), - EN("English"); - - private String s; - - Army(String s) { - this.s = s; - } - - @Override - public String toString() - { - return s; - } - - @Override - public boolean isEnemy(Faction other) - { - return (this != other); - } -} diff --git a/core/src/ch/asynk/tankontank/game/Battle.java b/core/src/ch/asynk/tankontank/game/Battle.java deleted file mode 100644 index 8625dd4..0000000 --- a/core/src/ch/asynk/tankontank/game/Battle.java +++ /dev/null @@ -1,40 +0,0 @@ -package ch.asynk.tankontank.game; - -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.game.battles.Factory.MapType; -import ch.asynk.tankontank.ui.Position; - -public interface Battle -{ - public void init(); - - public String getName(); - - public String getDescription(); - - public Player getPlayer(); - - public Player opponent(Player player); - - public MapType getMapType(); - - public Map getMap(); - - public Player checkVictory(Ctrl ctrl); - - public boolean getReinforcement(Ctrl ctrl, Map map); - - public Zone getEntryZone(Unit unit); - - public Zone getExitZone(Unit unit); - - public Position getHudPosition(Player player); - - public State.StateType getState(Player player); - - public boolean deploymentDone(Player player); - - public void setup(Ctrl ctrl, Map map); -} diff --git a/core/src/ch/asynk/tankontank/game/Command.java b/core/src/ch/asynk/tankontank/game/Command.java deleted file mode 100644 index 7416713..0000000 --- a/core/src/ch/asynk/tankontank/game/Command.java +++ /dev/null @@ -1,225 +0,0 @@ -package ch.asynk.tankontank.game; - -import java.util.List; - -import com.badlogic.gdx.utils.Pool; -import com.badlogic.gdx.utils.Json; -import com.badlogic.gdx.utils.JsonValue; - -import ch.asynk.tankontank.engine.Order; -import ch.asynk.tankontank.engine.Move; -import ch.asynk.tankontank.engine.Pawn; -import ch.asynk.tankontank.engine.Tile; - -public class Command extends Order -{ - public enum CommandType implements Order.OrderType - { - NONE, - MOVE, - ENGAGE, - PROMOTE, - END_OF_TURN; - } - - private static final Pool commandPool = new Pool() - { - @Override - protected Command newObject() { - return new Command(); - } - }; - - public static void clearPool() - { - commandPool.clear(); - } - - public static Command get(Player player) - { - Command c = commandPool.obtain(); - c.player = player; - c.ap = player.getAp(); - c.turn = player.getCurrentTurn(); - return c; - } - - public CommandType type; - public Player player; - public int ap; - public int turn; - public Unit unit; - public Unit.UnitId unitId; - public Unit.UnitType unitType; - public Tile unitTile; - public Move move; - public Engagement engagement; - - private Command() - { - reset(); - } - - @Override - public void dispose() - { - commandPool.free(this); - } - - @Override - public void reset() - { - this.type = CommandType.NONE; - this.player = null; - this.unit = null; - if (this.move != null) { - this.move.dispose(); - this.move = null; - } - if (this.engagement != null) { - this.engagement.dispose(); - this.engagement = null; - } - } - - @Override - public int compareTo(Pawn pawn) - { - if (pawn == unit) - return 0; - return 1; - } - - @Override - public boolean isA(OrderType type) - { - return (type == this.type); - } - - @Override - public String toString() - { - return String.format("%s : %s", type, unit.id); - } - - public void setMove(Unit unit, Move move) - { - this.type = CommandType.MOVE; - this.move = move; - setUnit(unit); - } - - public void setPromote(Unit unit) - { - this.type = CommandType.PROMOTE; - setUnit(unit); - } - - public void setEngage(Unit unit, Unit target) - { - this.type = CommandType.ENGAGE; - this.engagement = Engagement.get(unit, target); - setUnit(unit); - } - - private void setUnit(Unit unit) - { - this.unit = unit; - this.unitId = unit.id; - this.unitType = unit.type; - this.unitTile = unit.getTile(); - } - - @Override - public void write(Json json) - { - json.writeValue("type", type); - json.writeObjectStart("player"); - json.writeValue("army", player.getName()); - json.writeValue("turn", turn); - json.writeValue("aps", ap); - json.writeObjectEnd(); - json.writeObjectStart("unit"); - json.writeValue("id", unitId); - json.writeValue("type", unitType); - json.writeValue("ace", unit.ace); - writeTile(json, "tile", unitTile); - json.writeObjectEnd(); - if (move != null) writeMove(json, "move", move); - if (engagement != null) writeEngagement(json, "engagement", engagement); - } - - private void writeMove(Json json, String key, Move m) - { - json.writeObjectStart(key); - json.writeValue("type", move.type); - writeTile(json, "from", move.from); - writeTile(json, "to", move.to); - json.writeValue("orientation", move.orientation.r()); - writeTiles(json, "path", move.tiles); - json.writeObjectEnd(); - } - - private void writeEngagement(Json json, String key, Engagement e) - { - json.writeObjectStart(key); - writeUnit(json, "attacker", e.attacker); - writeUnit(json, "defender", e.defender); - writeUnits(json, "assists", e.assists); - json.writeObjectStart("dice"); - json.writeValue("d1", e.d1); - json.writeValue("d2", e.d2); - json.writeValue("d3", e.d3); - json.writeValue("d4", e.d4); - json.writeObjectEnd(); - json.writeObjectStart("results"); - json.writeValue("success", e.success); - json.writeValue("attackSum", e.attackSum); - json.writeValue("defenseSum", e.defenseSum); - json.writeObjectEnd(); - json.writeObjectEnd(); - } - - private void writeUnit(Json json, String key, Unit u) - { - if (key != null) json.writeObjectStart(key); - else json.writeObjectStart(); - json.writeValue("id", u.id); - json.writeValue("ace", u.ace); - json.writeValue("army", u.getArmy()); - writeTile(json, "tile", u.getTile()); - json.writeObjectEnd(); - } - - private void writeUnits(Json json, String key, List units) - { - json.writeArrayStart(key); - for (Unit u : units) - writeUnit(json, null, u); - json.writeArrayEnd(); - } - - private void writeTile(Json json, String key, Tile t) - { - if (t == null) return; - if (key != null) json.writeObjectStart(key); - else json.writeObjectStart(); - json.writeValue("col", t.getCol()); - json.writeValue("row", t.getRow()); - json.writeObjectEnd(); - } - - private void writeTiles(Json json, String key, List tiles) - { - json.writeArrayStart(key); - for (Tile t : tiles) - writeTile(json, null, t); - json.writeArrayEnd(); - } - - @Override - public void read(Json json, JsonValue jsonMap) - { - // FIXME Command.read(Json, JsonValue); - } -} diff --git a/core/src/ch/asynk/tankontank/game/Config.java b/core/src/ch/asynk/tankontank/game/Config.java deleted file mode 100644 index aa0084a..0000000 --- a/core/src/ch/asynk/tankontank/game/Config.java +++ /dev/null @@ -1,76 +0,0 @@ -package ch.asynk.tankontank.game; - -public class Config -{ - public enum Graphics { - MINE("mine", 0), - ORIGINAL("original", 1); - public String s; - public int i; - Graphics(String s, int i) - { - this.s = s; - this.i = i; - } - public Graphics next() - { - if (this == ORIGINAL) - return MINE; - return ORIGINAL; - } - }; - - public enum GameMode - { - SOLO("Solo", 0), - PVE("Player vs AI", 1), - PVP("Player vs Player", 2); - public String s; - public int i; - GameMode(String s, int i) - { - this.s = s; - this.i = i; - } - public GameMode next() - { - if (this == SOLO) - return PVE; - if(this == PVE) - return PVP; - return SOLO; - } - }; - - public GameMode gameMode; - public boolean showMoves; - public boolean showTargets; - public boolean showMoveAssists; - public boolean canCancel; - public boolean mustValidate; - public boolean showEnemyPossibilities; - public boolean debug; - public Battle battle; - public float fxVolume; - public Graphics graphics; - - public Config() - { - this.gameMode = GameMode.SOLO; - this.debug = false; - this.showMoves = true; - this.showTargets = true; - this.showMoveAssists = true; - this.canCancel = false; - this.mustValidate = false; - this.showEnemyPossibilities = false; - this.graphics = Graphics.MINE; - this.battle = null; - this.fxVolume = 1f; - } - - public boolean gameModeImplemented() - { - return (gameMode == GameMode.SOLO); - } -} diff --git a/core/src/ch/asynk/tankontank/game/Ctrl.java b/core/src/ch/asynk/tankontank/game/Ctrl.java deleted file mode 100644 index b410651..0000000 --- a/core/src/ch/asynk/tankontank/game/Ctrl.java +++ /dev/null @@ -1,336 +0,0 @@ -package ch.asynk.tankontank.game; - -import com.badlogic.gdx.utils.Disposable; - -import com.badlogic.gdx.math.Vector3; - -import ch.asynk.tankontank.TankOnTank; -import ch.asynk.tankontank.ui.Position; -import ch.asynk.tankontank.game.State.StateType; -import ch.asynk.tankontank.game.states.StateSelect; -import ch.asynk.tankontank.game.states.StateMove; -import ch.asynk.tankontank.game.states.StateRotate; -import ch.asynk.tankontank.game.states.StatePromote; -import ch.asynk.tankontank.game.states.StateEngage; -import ch.asynk.tankontank.game.states.StateBreak; -import ch.asynk.tankontank.game.states.StateAnimation; -import ch.asynk.tankontank.game.states.StateReinforcement; -import ch.asynk.tankontank.game.states.StateDeployment; -import ch.asynk.tankontank.game.states.StateWithdraw; - -public class Ctrl implements Disposable -{ - private final TankOnTank game; - public final Battle battle; - - public Map map; - public Hud hud; - public Config cfg; - public Player player; - public Player opponent; - public boolean blockMap; - public boolean blockHud; - - public Vector3 mapTouch = new Vector3(); - public Vector3 hudTouch = new Vector3(); - - private State selectState; - private State pathState; - private State rotateState; - private State promoteState; - private State engageState; - private State breakState; - private State animationState; - private State reinforcementState; - private State deploymentState; - private State withdrawState; - - private int animationCount = 0; - - private State state; - private StateType stateType; - private StateType stateAfterAnimation; - - public Ctrl(final TankOnTank game, final Battle battle) - { - this.game = game; - this.battle = battle; - this.cfg = game.config; - game.ctrl = this; - - battle.init(); - - this.map = battle.getMap(); - battle.setup(this, map); - this.map.init(); - this.player = battle.getPlayer(); - this.opponent = battle.opponent(player); - - this.selectState = new StateSelect(this, map); - this.pathState = new StateMove(); - this.rotateState = new StateRotate(); - this.promoteState = new StatePromote(); - this.engageState = new StateEngage(); - this.breakState = new StateBreak(); - this.animationState = new StateAnimation(); - this.reinforcementState = new StateReinforcement(); - this.deploymentState = new StateDeployment(); - this.withdrawState = new StateWithdraw(); - - this.state = selectState; - this.stateType = StateType.DONE; - - this.hud = new Hud(this, game); - this.blockMap = false; - this.blockHud = false; - - hud.notify(battle.toString(), 2, Position.MIDDLE_CENTER, false); - startPlayerTurn(); - } - - @Override - public void dispose() - { - hud.dispose(); - map.dispose(); - } - - public Player getPlayer(Army army) - { - return (player.is(army) ? player : opponent); - } - - public boolean isInAction() - { - return (state != selectState); - } - - public void animationsOver() - { - if (hud.dialogActive()) - return; - if (stateType == StateType.ANIMATION) - leaveAnimationState(); - } - - private void leaveAnimationState() - { - - StateType tmp = stateAfterAnimation; - stateAfterAnimation = StateType.DONE; - setState(tmp); - } - - private void startPlayerTurn() - { - player.turnStart(); - // hud.notify(player.getName() + "'s turn", 2, Position.MIDDLE_CENTER, true); - if (battle.getReinforcement(this, map)) - hud.notify("You have reinforcement", 2, Position.MIDDLE_CENTER, true); - hud.update(); - setState(battle.getState(player)); - } - - private void endPlayerTurn() - { - player.turnEnd(); - Player winner = battle.checkVictory(this); - if (winner != null) - hud.victory(winner, ((winner == player) ? opponent : player)); - } - - private StateType actionAborted() - { - hud.notify("Action canceled"); - StateType nextState = this.state.abort(); - - if (nextState == StateType.ABORT) - nextState = battle.getState(player); - - return nextState; - } - - private void turnDone() - { - map.turnDone(); - endPlayerTurn(); - player = battle.getPlayer(); - opponent = battle.opponent(player); - startPlayerTurn(); - } - - private StateType actionDone() - { - StateType nextState = this.state.execute(); - - if (nextState == StateType.DONE) { - map.actionDone(); - if (map.activatedUnits.size() > 0) { - TankOnTank.debug("Ctrl", "burn down 1AP"); - hud.notify("1 Action Point burnt", 0.6f, Position.BOTTOM_CENTER, false); - player.burnDownOneAp(); - hud.update(); - } - if (player.apExhausted()) - hud.notifyNoMoreAP(); - } - - if (nextState == StateType.DONE) - nextState = battle.getState(player); - - return nextState; - } - - private StateType deploymentDone() - { - map.actionDone(); - return this.state.execute(); - } - - public void setState(StateType nextState) - { - if (nextState == StateType.ABORT) - nextState = actionAborted(); - else if (nextState == StateType.DONE) { - if (stateType == StateType.DEPLOYMENT) - nextState = deploymentDone(); - else - nextState = actionDone(); - } - - if (stateType == StateType.ANIMATION) { - this.blockMap = hud.dialogActive(); - } - hud.playerInfo.blockEndOfTurn(nextState != StateType.SELECT); - - this.state.leave(nextState); - - TankOnTank.debug("Ctrl", String.format(" %s -> %s : %s", stateType, nextState, player)); - - switch(nextState) { - case SELECT: - this.state = selectState; - break; - case MOVE: - this.state = pathState; - break; - case ROTATE: - this.state = rotateState; - break; - case PROMOTE: - this.state = promoteState; - break; - case ENGAGE: - this.state = engageState; - break; - case BREAK: - this.state = breakState; - break; - case WITHDRAW: - this.state = withdrawState; - break; - case ANIMATION: - this.blockMap = true; - this.state = animationState; - break; - case REINFORCEMENT: - this.state = reinforcementState; - break; - case DEPLOYMENT: - this.state = deploymentState; - break; - default: - break; - } - - StateType tmp = stateType; - stateType = nextState; - - this.state.enter(tmp); - - } - - public void touchDown() - { - if (!blockHud && hud.touchDown(hudTouch.x, hudTouch.y)) - return; - - if (!blockMap && state.downInMap(mapTouch.x, mapTouch.y)) - state.touchDown(); - } - - public void touchUp() - { - if (!blockHud && hud.touchUp(hudTouch.x, hudTouch.y)) - return; - - if (!blockMap && state.upInMap(mapTouch.x, mapTouch.y)) - state.touchUp(); - } - - public void stateTouchUp() - { - state.downInMap(-1, -1); - state.upInMap(-1, -1); - state.touchUp(); - } - - public boolean isInAnimation() - { - return (this.stateType == StateType.ANIMATION); - } - - public void setAfterAnimationState(StateType after) - { - stateAfterAnimation = after; - } - - public boolean checkDeploymentDone() - { - boolean done = battle.deploymentDone(player); - if (done) - hud.askEndDeployment(); - return done; - } - - public void reinforcementHit() - { - if (this.stateType == StateType.SELECT) - setState(StateType.REINFORCEMENT); - else if (this.stateType == StateType.REINFORCEMENT) - setState(StateType.SELECT); - } - - // Hud callbacks - public void engagementPanelClosed() - { - if (animationCount == 0) - leaveAnimationState(); - } - - public void endDeployment() - { - setState(StateType.DONE); - turnDone(); - } - - public void endGame() - { - game.switchToMenu(); - } - - public void endPlayerTurn(boolean abort) - { - if (abort) - state.abort(); - turnDone(); - } - - public void exitBoard(boolean doit) - { - if (doit) - setState(StateType.DONE); - else - setState(StateType.ABORT); - } -} diff --git a/core/src/ch/asynk/tankontank/game/Engagement.java b/core/src/ch/asynk/tankontank/game/Engagement.java deleted file mode 100644 index 1dc7ce6..0000000 --- a/core/src/ch/asynk/tankontank/game/Engagement.java +++ /dev/null @@ -1,114 +0,0 @@ -package ch.asynk.tankontank.game; - -import java.util.List; -import java.util.LinkedList; -import java.util.Random; - -import com.badlogic.gdx.utils.Pool; -import com.badlogic.gdx.utils.Disposable; - -public class Engagement implements Disposable, Pool.Poolable -{ - private static Random rand = new Random(); - - private static final Pool engagementPool = new Pool() { - @Override - protected Engagement newObject() { - return new Engagement(); - } - }; - - public static Engagement get(Unit attacker, Unit defender) - { - Engagement e = engagementPool.obtain(); - e.attacker = attacker; - e.defender = defender; - e.diceRoll(); - - return e; - } - - public static void clearPool() - { - engagementPool.clear(); - } - - public Unit attacker; - public Unit defender; - public List assists; - public boolean success; - public int d1; - public int d2; - public int d3; - public int d4; - public int unitCount; - public int flankBonus; - public int unitDefense; - public int terrainDefense; - public int weatherDefense; - public int attackSum; - public int defenseSum; - - public Engagement() - { - assists = new LinkedList(); - reset(); - } - - @Override - public void reset() - { - attacker = null; - defender = null; - assists.clear(); - } - - @Override - public void dispose() - { - assists.clear(); - engagementPool.free(this); - } - - public void addAssist(Unit unit) - { - assists.add(unit); - } - - private void diceRoll() - { - d1 = rand.nextInt(6) + 1; - d2 = rand.nextInt(6) + 1; - d3 = rand.nextInt(6) + 1; - d4 = rand.nextInt(6) + 1; - } - - public void set(int cnt, int flk, int def, int tdf, int wdf) - { - this.unitCount = cnt; - this.flankBonus = flk; - this.unitDefense = def; - this.terrainDefense = tdf; - this.weatherDefense = wdf; - if (d3 == 0) - this.attackSum = (d1 + d2 + unitCount + flankBonus); - else - this.attackSum = (d3 + d4 + unitCount + flankBonus); - this.defenseSum = (unitDefense + terrainDefense + weatherDefense); - } - - - @Override - public String toString() - { - int a, b; - if (d3 == 0) { - a = d1; - b = d2; - } else { - a = d3; - b = d4; - } - return String.format("Engagement : (%d + %d + %d + %d) vs (%d + %d + %d) -> %b", a, b, unitCount, flankBonus, unitDefense, terrainDefense, weatherDefense, success); - } -} diff --git a/core/src/ch/asynk/tankontank/game/Hex.java b/core/src/ch/asynk/tankontank/game/Hex.java deleted file mode 100644 index e86612d..0000000 --- a/core/src/ch/asynk/tankontank/game/Hex.java +++ /dev/null @@ -1,138 +0,0 @@ -package ch.asynk.tankontank.game; - -import java.util.List; -import java.util.Iterator; - -import com.badlogic.gdx.graphics.g2d.TextureAtlas; - -import ch.asynk.tankontank.engine.Board; -import ch.asynk.tankontank.engine.Pawn; -import ch.asynk.tankontank.engine.Tile; -import ch.asynk.tankontank.engine.Orientation; -import ch.asynk.tankontank.game.Unit.UnitType; - -public class Hex extends Tile -{ - public enum Terrain implements TileTerrain - { - OFFMAP, - BLOCKED, - CLEAR, - HILLS, - WOODS, - TOWN - } - - public static final int FOG = 0; - public static final int SELECT = 1; - public static final int AREA = 2; - public static final int MOVE = 3; - public static final int DIRECTIONS = 4; - public static final int ORIENTATION = 5; - public static final int OBJECTIVE = 6; - public static final int OBJECTIVE_HOLD = 7; - public static final int OBJECTIVE_GE = 8; - public static final int OBJECTIVE_US = 9; - public static final int EXIT = 10; - - public Terrain terrain; - public int roads; - - public String toString() - { - return String.format("(%d;%d) [%f;%f] t:%s r:%d", col, row, x, y, terrain, roads); - } - - public String toShort() - { - return String.format("(%d;%d)", col, row); - } - - public Hex(float x, float y, int col, int row, TextureAtlas atlas) - { - super(x, y, col, row, atlas); - this.terrain = Terrain.CLEAR; - this.roads = 0; - } - - public Unit getUnit() - { - return (Unit) stack.peekFirst(); - } - - @Override - public boolean isA(TileTerrain terrain) - { - return (this.terrain == terrain); - } - - @Override - public boolean isOffMap() - { - return isA(Terrain.OFFMAP); - } - - @Override - public boolean blockLineOfSightFrom(Tile tile) - { - if (isA(Terrain.CLEAR) && !hasUnits()) - return false; - - if (tile.isA(Terrain.HILLS) && isA(Terrain.CLEAR)) - return false; - - return true; - } - - @Override - public boolean atLeastOneMove(Pawn pawn) - { - if (hasUnits() || isA(Terrain.BLOCKED) || isA(Terrain.OFFMAP)) - return false; - return true; - } - - @Override - public boolean road(Orientation side) - { - return (side.s == (roads & side.s)); - } - - @Override - public int exitCost() - { - return 1; - } - - @Override - public int costFrom(Pawn pawn, Orientation side) - { - if (side == Orientation.KEEP) return 0; - if (hasUnits()) return (Integer.MAX_VALUE / 2); - if (road(side)) return 1; - - int c = 0; - switch(terrain) { - case CLEAR: - case HILLS: - c = 1; - break; - case WOODS: - case TOWN: - c = 2; - break; - case OFFMAP: - case BLOCKED: - c = (Integer.MAX_VALUE / 2); - break; - } - - return c; - } - - @Override - public int defense() - { - return (isA(Terrain.TOWN) ? 1 : 0); - } -} diff --git a/core/src/ch/asynk/tankontank/game/HexSet.java b/core/src/ch/asynk/tankontank/game/HexSet.java deleted file mode 100644 index 2f78a89..0000000 --- a/core/src/ch/asynk/tankontank/game/HexSet.java +++ /dev/null @@ -1,29 +0,0 @@ -package ch.asynk.tankontank.game; - -import java.util.Collection; -import java.util.LinkedHashSet; - -import ch.asynk.tankontank.engine.Tile; - -public class HexSet extends LinkedHashSet -{ - private final Map map; - - public HexSet(Map map, int n) - { - super(n); - this.map = map; - } - - public void enable(int i, boolean enable) - { - for (Hex hex : this) - map.enableOverlayOn(hex, i, enable); - } - - @SuppressWarnings("unchecked") - public Collection asTiles() - { - return (Collection) this; - } -} diff --git a/core/src/ch/asynk/tankontank/game/Hud.java b/core/src/ch/asynk/tankontank/game/Hud.java deleted file mode 100644 index 204dcb5..0000000 --- a/core/src/ch/asynk/tankontank/game/Hud.java +++ /dev/null @@ -1,307 +0,0 @@ -package ch.asynk.tankontank.game; - -import java.util.LinkedList; - -import com.badlogic.gdx.Gdx; - -import com.badlogic.gdx.utils.Disposable; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Animation; -import ch.asynk.tankontank.game.State.StateType; -import ch.asynk.tankontank.ui.Position; -import ch.asynk.tankontank.ui.Msg; -import ch.asynk.tankontank.ui.OkCancel; -import ch.asynk.tankontank.ui.Widget; -import ch.asynk.tankontank.game.hud.PlayerInfo; -import ch.asynk.tankontank.game.hud.ActionButtons; -import ch.asynk.tankontank.game.hud.StatisticsPanel; -import ch.asynk.tankontank.game.hud.EngagementPanel; - -import ch.asynk.tankontank.TankOnTank; - -public class Hud implements Disposable, Animation -{ - public static final float OFFSET = 10f; - public static final float NOTIFY_DURATION = 2f; - - private final TankOnTank game; - private final Ctrl ctrl; - - private Object hit; - - public PlayerInfo playerInfo; - public ActionButtons actionButtons; - - private Msg msg; - private StatisticsPanel stats; - private EngagementPanel engagement; - private OkCancel okCancel; - private LinkedList dialogs = new LinkedList(); - - public enum OkCancelAction - { - EXIT_BOARD, - ABORT_TURN, - END_TURN, - END_DEPLOYMENT, - } - private OkCancelAction okCancelAction; - - public Hud(final Ctrl ctrl, final TankOnTank game) - { - this.game = game; - this.ctrl = ctrl; - - TextureAtlas hudAtlas = game.factory.hudAtlas; - playerInfo = new PlayerInfo(ctrl, game.fontW, game.uiAtlas, hudAtlas); - actionButtons = new ActionButtons(ctrl, game.uiAtlas, hudAtlas); - actionButtons.hide(); - msg = new Msg(game.fontB, game.uiAtlas); - okCancel = new OkCancel(game.fontB, game.uiAtlas); - stats = new StatisticsPanel(game.fontB, game.uiAtlas); - engagement = new EngagementPanel(game.fontB, game.uiAtlas, hudAtlas); - } - - @Override - public void dispose() - { - playerInfo.dispose(); - actionButtons.dispose(); - msg.dispose(); - okCancel.dispose(); - engagement.dispose(); - stats.dispose(); - } - - public void resize(int left, int bottom, int width, int height) - { - Position.update(left, bottom, width, height); - playerInfo.updatePosition(); - actionButtons.updatePosition(); - msg.updatePosition(); - stats.updatePosition(); - engagement.updatePosition(); - okCancel.updatePosition(); - } - - public void update() - { - Position position = ctrl.battle.getHudPosition(ctrl.player); - playerInfo.update(ctrl.player, position); - actionButtons.update(position.horizontalMirror()); - } - - @Override - public boolean animate(float delta) - { - msg.animate(delta); - playerInfo.animate(delta); - engagement.animate(delta); - return false; - } - - public void draw(Batch batch, boolean debug) - { - draw(batch); - if (debug) - game.fontB.draw(batch, String.format("FPS: %d", Gdx.graphics.getFramesPerSecond()), 80, 25); - } - - @Override - public void draw(Batch batch) - { - playerInfo.draw(batch); - actionButtons.draw(batch); - msg.draw(batch); - okCancel.draw(batch); - engagement.draw(batch); - stats.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - playerInfo.drawDebug(debugShapes); - actionButtons.drawDebug(debugShapes); - msg.drawDebug(debugShapes); - okCancel.drawDebug(debugShapes); - engagement.drawDebug(debugShapes); - stats.drawDebug(debugShapes); - } - - public void pushNotify(String s) - { - notify(s, NOTIFY_DURATION, Position.TOP_CENTER, true); - } - - public void notify(String s) - { - notify(s, NOTIFY_DURATION, Position.TOP_CENTER, false); - } - - public void notify(String s, float duration, Position position, boolean push) - { - if (push) msg.pushWrite(s, duration, position); - else msg.write(s, duration, position); - } - - public boolean touchDown(float x, float y) - { - hit = null; - - if (dialogs.size() > 0) { - Widget dialog = dialogs.getFirst(); - if (dialog.hit(x, y)) { - hit = dialog; - return true; - } - return false; - } - - if (ctrl.isInAnimation()) - return false; - - if (hit == null) { - if (actionButtons.touchDown(x, y)) - hit = actionButtons; - else if (playerInfo.touchDown(x, y)) - hit = playerInfo; - } - - return (hit != null); - } - - public boolean touchUp(float x, float y) - { - if (hit == null) - return false; - - if (dialogs.size() > 0) { - Widget dialog = dialogs.getFirst(); - if (hit == dialog) { - if (dialog.hit(x, y)) - closeDialog(); - hit = null; - } - } else { - if (hit == actionButtons) { - actionButtons.touchUp(x, y); - } - else if (hit == playerInfo) { - playerInfo.touchUp(x, y); - } - - hit = null; - } - - return true; - } - - private void closeDialog() - { - Widget dialog = dialogs.removeFirst(); - dialog.visible = false; - - if (dialog == okCancel) - closeOkCancel(); - else if (dialog == stats) - ctrl.endGame(); - else if (dialog == engagement) - ctrl.engagementPanelClosed(); - - if (dialogs.size() > 0) - dialogs.getFirst().visible = true; - else - ctrl.blockMap = false; - } - - private void closeOkCancel() - { - boolean ok = okCancel.ok; - - switch(okCancelAction) { - case EXIT_BOARD: - ctrl.exitBoard(ok); - break; - case END_TURN: - if (ok) - ctrl.endPlayerTurn(false); - break; - case ABORT_TURN: - if (ok) - ctrl.endPlayerTurn(true); - break; - case END_DEPLOYMENT: - if (ok) - ctrl.endDeployment(); - break; - } - } - - public boolean dialogActive() - { - return (dialogs.size() > 0); - } - - private void pushDialog(Widget dialog) - { - ctrl.blockMap = true; - if (dialogs.size() != 0) - dialog.visible = false; - dialogs.addLast(dialog); - } - - public void notifyDeploymentDone() - { - this.okCancelAction = OkCancelAction.END_TURN; - okCancel.show("Deployment Phase completed."); - okCancel.noCancel(); - pushDialog(okCancel); - } - - public void notifyNoMoreAP() - { - this.okCancelAction = OkCancelAction.END_TURN; - okCancel.show("No more Action Point left."); - okCancel.noCancel(); - pushDialog(okCancel); - } - - public void askExitBoard() - { - this.okCancelAction = OkCancelAction.EXIT_BOARD; - okCancel.show("Do you want this unit to escape the battle field ?"); - pushDialog(okCancel); - } - - public void askEndOfTurn() - { - this.okCancelAction = OkCancelAction.ABORT_TURN; - okCancel.show("You still have Action Points left.\nEnd your Turn anyway ?"); - pushDialog(okCancel); - } - - public void askEndDeployment() - { - this.okCancelAction = OkCancelAction.END_DEPLOYMENT; - okCancel.show("Deployment unit count reached.\nEnd Deployment phase ?"); - pushDialog(okCancel); - } - - public void engagementSummary(Engagement e, float volume) - { - engagement.show(e, Position.BOTTOM_CENTER, volume); - pushDialog(engagement); - } - - public void victory(Player winner, Player loser) - { - stats.show(winner, loser, Position.MIDDLE_CENTER); - pushDialog(stats); - } -} diff --git a/core/src/ch/asynk/tankontank/game/Map.java b/core/src/ch/asynk/tankontank/game/Map.java deleted file mode 100644 index a924f29..0000000 --- a/core/src/ch/asynk/tankontank/game/Map.java +++ /dev/null @@ -1,659 +0,0 @@ -package ch.asynk.tankontank.game; - -import com.badlogic.gdx.audio.Sound; -import com.badlogic.gdx.assets.AssetManager; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.TankOnTank; -import ch.asynk.tankontank.engine.Pawn; -import ch.asynk.tankontank.engine.Board; -import ch.asynk.tankontank.engine.Tile; -import ch.asynk.tankontank.engine.Faction; -import ch.asynk.tankontank.engine.Move; -import ch.asynk.tankontank.engine.SelectedTile; -import ch.asynk.tankontank.engine.ObjectiveSet; -import ch.asynk.tankontank.engine.OrderList; -import ch.asynk.tankontank.engine.Orientation; -import ch.asynk.tankontank.engine.Meteorology; -import ch.asynk.tankontank.engine.PathBuilder; -import ch.asynk.tankontank.engine.gfx.Moveable; -import ch.asynk.tankontank.engine.gfx.Animation; -import ch.asynk.tankontank.engine.gfx.animations.AnimationSequence; -import ch.asynk.tankontank.engine.gfx.animations.DiceAnimation; -import ch.asynk.tankontank.engine.gfx.animations.FireAnimation; -import ch.asynk.tankontank.engine.gfx.animations.TankFireAnimation; -import ch.asynk.tankontank.engine.gfx.animations.InfantryFireAnimation; -import ch.asynk.tankontank.engine.gfx.animations.PromoteAnimation; -import ch.asynk.tankontank.engine.gfx.animations.DestroyAnimation; -import ch.asynk.tankontank.engine.gfx.animations.SoundAnimation; -import ch.asynk.tankontank.engine.gfx.animations.RunnableAnimation; -import ch.asynk.tankontank.engine.gfx.animations.MoveToAnimation.MoveToAnimationCb; - -import ch.asynk.tankontank.ui.Position; - -public abstract class Map extends Board implements MoveToAnimationCb, ObjectiveSet.ObjectiveCb -{ - private final Ctrl ctrl; - - public final HexSet possibleMoves; - public final PathBuilder pathBuilder; - - public final UnitList moveableUnits; - public final UnitList possibleTargets; - public final UnitList engagementAssists; - public final UnitList activatedUnits; - public final UnitList breakUnits; - public final ObjectiveSet objectives; - - public final Meteorology meteorology; - - private final DestroyAnimation destroy; - private final Sound tankMoveSound; - private final Sound infantryMoveSound; - private Sound sound; - private long soundId = -1; - - private OrderList commands; - - protected abstract void setup(); - - public Map(final TankOnTank game, Board.Config cfg, String textureName) - { - super(game.factory, cfg, game.manager.get(textureName, Texture.class), - new SelectedTile(game.manager.get("data/hex.png", Texture.class), new float[] {.2f, .1f, .1f, .1f, .2f, .1f} )); - this.ctrl = game.ctrl; - this.destroy = new DestroyAnimation(); - this.tankMoveSound = game.manager.get("sounds/tank_move.mp3", Sound.class); - this.infantryMoveSound = game.manager.get("sounds/infantry_move.mp3", Sound.class); - DiceAnimation.init(game.manager.get("data/dice.png", Texture.class), 16, 9, game.manager.get("sounds/dice.mp3", Sound.class)); - PromoteAnimation.init(game.manager.get("data/hud.atlas", TextureAtlas.class), - game.manager.get("sounds/promote_us.mp3", Sound.class), - game.manager.get("sounds/promote_ge.mp3", Sound.class)); - FireAnimation.init( - game.manager.get("data/infantry_fire.png", Texture.class), 1, 8, - game.manager.get("data/tank_fire.png", Texture.class), 1, 8, - game.manager.get("data/explosions.png", Texture.class), 16, 8, - game.manager.get("sounds/infantry_fire.mp3", Sound.class), - game.manager.get("sounds/tank_fire.mp3", Sound.class), - game.manager.get("sounds/tank_fire_short.mp3", Sound.class), - game.manager.get("sounds/explosion.mp3", Sound.class), - game.manager.get("sounds/explosion_short.mp3", Sound.class) - ); - - setup(); - - possibleMoves = new HexSet(this, 40); - pathBuilder = new PathBuilder(this, 10, 20, 5, 10); - moveableUnits = new UnitList(6); - - possibleTargets = new UnitList(10); - engagementAssists = new UnitList(6); - activatedUnits = new UnitList(7); - breakUnits = new UnitList(4); - - objectives = new ObjectiveSet(this, 4); - - meteorology = new Meteorology(); - commands = new OrderList(); - } - - @Override - public void dispose() - { - super.dispose(); - clearAll(); - destroy.dispose(); - pathBuilder.dispose(); - DiceAnimation.free(); - PromoteAnimation.free(); - FireAnimation.free(); - commands.dispose(); - Command.clearPool(); - Engagement.clearPool(); - } - - public void clearAll() - { - possibleMoves.clear(); - possibleTargets.clear(); - pathBuilder.clear(); - moveableUnits.clear(); - engagementAssists.clear(); - activatedUnits.clear(); - breakUnits.clear(); - } - - public Hex getHexAt(float x, float y) - { - return (Hex) getTileAt(x, y); - } - - public Hex getHex(int col, int row) - { - return (Hex) getTile(col, row); - } - - public void addObjective(int col, int row, Army army) - { - addObjective(col, row, army, true); - } - - public void addHoldObjective(int col, int row, Army army) - { - addObjective(col, row, army, false); - } - - private void addObjective(int col, int row, Army army, boolean persistent) - { - Hex hex = getHex(col, row); - objectives.add(hex, army, persistent); - showObjective(hex, army, !persistent); - } - - private void claim(Hex hex, Army army) - { - showObjective(hex, objectives.claim(hex, army)); - } - - private void unclaim(Hex hex) - { - showObjective(hex, objectives.unclaim(hex)); - } - - public int collectPossibleMoves(Unit unit) - { - if (!unit.canMove()) { - possibleMoves.clear(); - return 0; - } - return collectPossibleMoves(unit, possibleMoves.asTiles()); - } - - public int togglePathBuilderHex(Hex hex) - { - return pathBuilder.toggleCtrlTile(hex); - } - - public int collectPossibleTargets(Unit unit, UnitList foes) - { - if (!unit.canEngage()) { - possibleTargets.clear(); - return 0; - } - // return collectPossibleTargets(unit, possibleTargets); - return collectPossibleTargets(unit, foes.asPawns(), possibleTargets.asPawns()); - } - - public int collectMoveableUnits(Unit unit) - { - if (unit.canHQMove()) { - collectMoveAssists(unit, moveableUnits.asPawns()); - } else { - moveableUnits.clear(); - } - if (unit.canMove()) - moveableUnits.add(unit); - return moveableUnits.size(); - } - - public int collectAttackAssists(Unit unit, Unit target, UnitList units) - { - int s = collectAttackAssists(unit, target, units.asPawns(), engagementAssists.asPawns()); - activatedUnits.add(unit); - return s; - } - - public boolean toggleAttackAssist(Unit unit) - { - if (activatedUnits.contains(unit)) { - activatedUnits.remove(unit); - unit.hideAttack(); - unit.showAttackAssist(); - return false; - } else { - activatedUnits.add(unit); - unit.showAttack(); - unit.hideAttackAssist(); - return true; - } - } - - public void collectAndShowMovesAndAssits(Unit unit) - { - hidePossibleMoves(); - hideMoveableUnits(); - collectPossibleMoves(unit); - collectMoveableUnits(unit); - showPossibleMoves(); - showMoveableUnits(); - activatedUnits.clear(); - } - - // -> implement MoveToAnimationCb - - @Override - public void moveToAnimationEnter(Moveable moveable, float x, float y, float r) - { - claim(getHexAt(x, y), (Army) moveable.getFaction()); - } - - @Override - public void moveToAnimationLeave(Moveable moveable, float x, float y, float r) - { - unclaim(getHexAt(x, y)); - } - - @Override - public void moveToAnimationDone(Moveable moveable, float x, float y, float r) - { - } - - // <- implement MoveToAnimationCb - - private int process(Unit unit, Move move) - { - TankOnTank.debug(" Move", String.format("%s %s", move.type, move.toString())); - - int r = 1; - - switch(move.type) { - case REGULAR: - initMove(unit); - movePawn(unit, move, this); - r = moveableUnits.size(); - break; - case EXIT: - initMove(unit); - movePawn(unit, move, this); - ctrl.player.unitWithdraw(unit); - r = moveableUnits.size(); - break; - case SET: - setPawnOnto(unit, move); - ctrl.player.unitEntry(unit); - claim((Hex) move.to, unit.getArmy()); - break; - case ENTER: - enterPawn(unit, move); - ctrl.player.unitEntry(unit); - claim((Hex) move.to, unit.getArmy()); - break; - default: - System.err.println(String.format("process wrong Move type %s", move.type)); - r = -1; - break; - } - - return r; - } - - private int promoteUnit(final Unit unit, final Player player) - { - activatedUnits.add(unit); - - Hex hex = unit.getHex(); - AnimationSequence seq = AnimationSequence.get(2); - seq.addAnimation(PromoteAnimation.get((unit.getArmy() == Army.US), hex.getX(), hex.getY(), ctrl.cfg.fxVolume)); - seq.addAnimation ( RunnableAnimation.get(unit, new Runnable() { - @Override - public void run() { - player.promote(unit); - } - })); - addAnimation(seq); - return 1; - } - - private int process(Command cmd) - { - TankOnTank.debug("Command", cmd.toString()); - - int r = 1; - - switch(cmd.type) { - case MOVE: - r = process(cmd.unit, cmd.move); - break; - case PROMOTE: - r = promoteUnit(cmd.unit, cmd.player); - break; - case ENGAGE: - resolveEngagement(cmd.engagement); - r = doEngagement(cmd.engagement); - break; - default: - System.err.println(String.format("process wrong Command type %s", cmd.type)); - r = -1; - break; - } - - if (r != -1) - commands.add(cmd); - - return r; - } - - // Ctrl Methods - - public void init() - { - actionDone(); - } - - public void turnDone() - { - TankOnTank.debug("TurnDone", String.format(" Processed Commands : %d", commands.size())); - - if (objectives.modifiedCount() > 0) - throw new RuntimeException("objectives not cleared"); - - // FIXME do something with these Commands - commands.dispose(); - } - - public void actionDone() - { - objectives.forget(); - } - - // STATES ENTRY -> - - public void showOnBoard(final Unit unit, Hex to, Orientation o) - { - setPawnOnto(unit, to, o); - } - - public boolean setOnBoard(final Unit unit, Hex to, Orientation entry) - { - commands.dispose(unit); - return (process(getMoveCommand(unit, Move.getSet(unit, to, entry))) == 1); - } - - public boolean enterBoard(final Unit unit, Hex to, int allowedMoves) - { - Orientation entry = findBestEntry(unit, to, allowedMoves); - if (entry == Orientation.KEEP) - return false; - - return (process(getMoveCommand(unit, Move.getEnter(unit, to, entry))) == 1); - } - - public int exitBoard(final Unit unit) - { - return process(getMoveCommand(unit, pathBuilder.getExitMove())); - } - - public int moveUnit(final Unit unit) - { - return process(getMoveCommand(unit, pathBuilder.getMove())); - } - - public void revertMoves() - { - for (Unit unit: activatedUnits) { - TankOnTank.debug(" revertMove() " + unit); - revertLastPawnMove(unit); - commands.dispose(unit, Command.CommandType.MOVE); - } - activatedUnits.clear(); - objectives.revert(this); - } - - public void revertEnter(final Unit unit) - { - TankOnTank.debug(" revertEnter() "+ unit); - removePawn(unit); - objectives.revert(this); - ctrl.player.revertUnitEntry(unit); - commands.dispose(unit); - unit.reset(); - } - - public boolean engageUnit(final Unit unit, final Unit target) - { - attack(unit, target, true); - - Command cmd = Command.get(ctrl.player); - cmd.setEngage(unit, target); - return (process(cmd) == 1); - } - - public void promoteUnit(final Unit unit) - { - Command cmd = Command.get(ctrl.player); - cmd.setPromote(unit); - process(cmd); - } - - // STATES ENTRY <- - - private Command getMoveCommand(Unit unit, Move move) - { - Command cmd = Command.get(ctrl.player); - cmd.setMove(unit, move); - return cmd; - } - - private void initMove(Unit unit) - { - moveableUnits.remove(unit); - activatedUnits.add(unit); - playMoveSound(unit); - } - - private void playMoveSound(Unit unit) - { - if (unit.isA(Unit.UnitType.INFANTRY)) - sound = infantryMoveSound; - else - sound = tankMoveSound; - soundId = sound.play(ctrl.cfg.fxVolume); - } - - @Override - protected void animationsOver() - { - if (soundId >= 0) { - addAnimation( SoundAnimation.get(SoundAnimation.Action.FADE_OUT, sound, soundId, ctrl.cfg.fxVolume, 0.5f)); - soundId = -1; - return; - } - ctrl.animationsOver(); - } - - private void addEngagementAnimation(Unit target) - { - FireAnimation.reset(); - Hex to = target.getHex(); - for (Unit u : activatedUnits) { - Hex from = u.getHex(); - float halfWidth = (u.getWidth() / 2f); - if (u.isA(Unit.UnitType.INFANTRY)) - addAnimation(InfantryFireAnimation.get(ctrl.cfg.fxVolume, from.getX(), from.getY(), to.getX(), to.getY(), halfWidth)); - else - addAnimation(TankFireAnimation.get(ctrl.cfg.fxVolume, from.getX(), from.getY(), to.getX(), to.getY(), halfWidth)); - } - } - - private void resolveEngagement(Engagement e) - { - int dice = e.d1 + e.d2; - - int distance = 0; - boolean mayReroll = false; - boolean night = (meteorology.day == Meteorology.Day.NIGHT); - boolean flankAttack = false; - boolean terrainBonus = true; - - for (Unit unit : activatedUnits) { - if (unit != e.attacker) - e.addAssist(unit); - if (unit.isAce()) - mayReroll = true; - if (unit.isFlankAttack()) - flankAttack = true; - if (unit.isA(Unit.UnitType.INFANTRY)) - terrainBonus = false; - if (night) { - if (distance < unit.attackDistance()) - distance = unit.attackDistance(); - } - } - - int cnt = activatedUnits.size(); - int def = e.defender.getDefense(e.attacker.getTile()); - int flk = (flankAttack ? Unit.FLANK_ATTACK_BONUS : 0); - int tdf = (terrainBonus ? e.defender.getTile().defense() : 0); - int wdf = 0; - if (night) { - if (distance > 3) - wdf = 3; - else if (distance > 2) - wdf = 2; - else if (distance > 1) - wdf = 1; - } - int s1 = (dice + cnt + flk); - int s2 = (def + tdf + wdf); - - boolean success = false; - if (dice == 2) { - success = false; - } else if (dice == 12) { - success = true; - } else { - success = (s1 >= s2); - } - if (!success && mayReroll) { - dice = e.d3 + e.d4; - s1 = (dice + cnt + flk); - if (dice == 2) { - success = false; - } else if (dice == 12) { - success = true; - } else { - success = (s1 >= s2); - } - } else { - e.d3 = 0; - e.d4 = 0; - } - - e.set(cnt, flk, def, tdf, wdf); - e.success = success; - } - - private int doEngagement(Engagement e) - { - breakUnits.clear(); - activatedUnits.clear(); - - activatedUnits.add(e.attacker); - for (Unit u : e.assists) - activatedUnits.add(u); - - for (Unit u : activatedUnits) { - u.engage(); - if (u.isA(Unit.UnitType.INFANTRY)) - breakUnits.add(u); - } - - if (e.success) { - unclaim(e.defender.getHex()); - removePawn(e.defender); - destroy.set(2f, e.defender); - addAnimation(destroy); - } - - if ((activatedUnits.size() == 1) && e.attacker.isA(Unit.UnitType.AT_GUN) && e.defender.isHardTarget()) - activatedUnits.clear(); - - ctrl.hud.engagementSummary(e, ctrl.cfg.fxVolume); - addEngagementAnimation(e.defender); - - return (e.success ? 1 : 0); - } - - // SHOW / HIDE - - public void togglePathOverlay(Hex hex) - { - boolean enable= !hex.isOverlayEnabled(Hex.MOVE); - enableOverlayOn(hex, Hex.MOVE, enable); - } - - private void showUnitsOverlay(UnitList units, int overlay, boolean on) - { - for (Unit unit : units) - unit.enableOverlay(overlay, on); - } - - public void showMoveableUnits() { showUnitsOverlay(moveableUnits, Unit.MOVE, true); } - public void hideMoveableUnits() { showUnitsOverlay(moveableUnits, Unit.MOVE, false); } - public void showPossibleTargets() { showUnitsOverlay(possibleTargets, Unit.TARGET, true); } - public void hidePossibleTargets() { showUnitsOverlay(possibleTargets, Unit.TARGET, false); } - public void showAttackAssists() { showUnitsOverlay(engagementAssists, Unit.MAY_FIRE, true); } - public void hideAttackAssists() { showUnitsOverlay(engagementAssists, Unit.FIRE, false); - showUnitsOverlay(engagementAssists, Unit.MAY_FIRE, false); } - public void showBreakUnits() { showUnitsOverlay(breakUnits, Unit.MOVE, true); } - public void hideBreakUnits() { showUnitsOverlay(breakUnits, Unit.MOVE, false); } - - public void showPossibleMoves() { possibleMoves.enable(Hex.AREA, true); } - public void hidePossibleMoves() { possibleMoves.enable(Hex.AREA, false); } - public void showPathBuilder() { pathBuilder.enable(Hex.AREA, true); } - public void hidePathBuilder() { pathBuilder.enable(Hex.AREA, false); } - public void showPath(Hex dst) { pathBuilder.enable(Hex.MOVE, true); showMove(dst); } - public void hidePath(Hex dst) { pathBuilder.enable(Hex.MOVE, false); hideMove(dst); } - - public void selectHex(Hex hex) { selectedTile.set(hex); } - public void unselectHex(Hex hex) { selectedTile.hide(); } - public void showMove(Hex hex) { enableOverlayOn(hex, Hex.MOVE, true); } - public void hideMove(Hex hex) { enableOverlayOn(hex, Hex.MOVE, false); } - public void showDirections(Hex hex) { enableOverlayOn(hex, Hex.DIRECTIONS, true); } - public void hideDirections(Hex hex) { enableOverlayOn(hex, Hex.DIRECTIONS, false); } - public void showOrientation(Hex hex, Orientation o) { enableOverlayOn(hex, Hex.ORIENTATION, o, true); } - public void hideOrientation(Hex hex) { enableOverlayOn(hex, Hex.ORIENTATION, false); } - public void showExit(Hex hex) { enableOverlayOn(hex, Hex.EXIT, true); } - public void hideExit(Hex hex) { enableOverlayOn(hex, Hex.EXIT, false); } - - public void showObjective(Hex hex, Army army, boolean hold) - { - if (hold) - enableOverlayOn(hex, Hex.OBJECTIVE_HOLD, true); - else - enableOverlayOn(hex, Hex.OBJECTIVE, true); - } - - - // -> implement ObjectiveSet.ObjectiveCb - - public void showObjective(Tile tile, Faction faction) - { - showObjective((Hex) tile, (Army) faction); - } - - // <- implement MoveToAnimationCb - - public void showObjective(Hex hex, Army army) - { - if (army == null) - army = Army.NONE; - switch(army) { - case GE: - enableOverlayOn(hex, Hex.OBJECTIVE_GE, true); - enableOverlayOn(hex, Hex.OBJECTIVE_US, false); - break; - case US: - enableOverlayOn(hex, Hex.OBJECTIVE_GE, false); - enableOverlayOn(hex, Hex.OBJECTIVE_US, true); - break; - case NONE: - default: - enableOverlayOn(hex, Hex.OBJECTIVE_GE, false); - enableOverlayOn(hex, Hex.OBJECTIVE_US, false); - break; - } - } -} diff --git a/core/src/ch/asynk/tankontank/game/Player.java b/core/src/ch/asynk/tankontank/game/Player.java deleted file mode 100644 index d9048bf..0000000 --- a/core/src/ch/asynk/tankontank/game/Player.java +++ /dev/null @@ -1,213 +0,0 @@ -package ch.asynk.tankontank.game; - -import java.util.Random; -import java.util.List; - -import ch.asynk.tankontank.TankOnTank; - -public class Player -{ - private static final float MOVE_TIME = 0.4f; - - private static Random rand = new Random(); - - private int turn; - private int apSpent; - private int actionPoints; - private boolean deploymentDone; - - public Army army; - public UnitList units; - public UnitList casualties; - public UnitList reinforcement; - public UnitList withdrawed; - - public int actionCount; - public int lostEngagementCount; - public int wonEngagementCount; - - public Player(final TankOnTank game, Army army, int n) - { - this.army = army; - this.units = new UnitList(n); - this.casualties = new UnitList(n); - this.reinforcement = new UnitList(n); - this.withdrawed = new UnitList(n); - this.turn = 0; - this.apSpent = 0; - this.actionPoints = 0; - this.deploymentDone = false; - this.actionCount = 0; - this.lostEngagementCount = 0; - this.wonEngagementCount = 0; - } - - public String getName() - { - return army.toString(); - } - - public String toString() - { - return String.format("%s Turn:%d AP:%d units:%d casualties:%d", army, turn, actionPoints, units.size(), casualties.size()); - } - - public String getStats() - { - return String.format("%s\n%4d\n%4d\n%4d\n%4d\n%4d\n%4d", getName(), actionCount, unitsLeft(), withdrawed(), casualties(), wonEngagementCount, lostEngagementCount); - } - - public boolean is(Army army) - { - return (this.army == army); - } - - public boolean isEnemy(Unit unit) - { - return unit.isEnemy(army); - } - - public boolean isEnemy(Army other) - { - return army.isEnemy(other); - } - - public int unitsLeft() - { - return (units.size() + reinforcement.size()); - } - - public int reinforcement() - { - return reinforcement.size(); - } - - public int casualties() - { - return casualties.size(); - } - - public int withdrawed() - { - return withdrawed.size(); - } - - public void addUnit(Unit unit) - { - units.add(unit); - } - - public void addReinforcement(Unit unit) - { - reinforcement.add(unit); - } - - public void unitEntry(Unit unit) - { - reinforcement.remove(unit); - units.add(unit); - } - - public void revertUnitEntry(Unit unit) - { - units.remove(unit); - reinforcement.add(unit); - } - - public void casualty(Unit unit) - { - units.remove(unit); - casualties.add(unit); - } - - public void unitWithdraw(Unit unit) - { - units.remove(unit); - withdrawed.add(unit); - } - - public int getAp() - { - return ((apSpent < actionPoints) ? (apSpent + 1) : apSpent); - } - - public int getTurnDone() - { - return turn; - } - - public int getCurrentTurn() - { - return (turn + 1); - } - - public boolean apExhausted() - { - return (apSpent == actionPoints); - } - - public boolean isDeploymentDone() - { - return (deploymentDone || (reinforcement.size() == 0)); - } - - public void burnDownOneAp() - { - apSpent += 1; - actionCount += 1; - if (apSpent > actionPoints) TankOnTank.debug("ERROR: spent too much AP, please report"); - } - - public void turnEnd() - { - if (deploymentDone) - turn += 1; - else - deploymentDone = (reinforcement.size() == 0); - for (Unit unit : units) - unit.reset(); - } - - public void turnStart() - { - if (isDeploymentDone()) - computeActionPoints(); - } - - public int d6() - { - return rand.nextInt(6) + 1; - } - - private void computeActionPoints() - { - this.actionPoints = 2; - if (d6() > 2) { - this.actionPoints += 1; - if (d6() > 3) - this.actionPoints += 1; - } - apSpent = 0; - } - - public boolean canPromote(Unit unit) - { - if (unit.isHq()) return false; - for (Unit p: casualties) - if (p.isHqOf(unit)) return true; - return false; - } - - public boolean promote(Unit unit) - { - for (Unit p: casualties) { - if (p.isHqOf(unit)) { - unit.promote(); - p.degrade(); - return true; - } - } - - return false; - } -} diff --git a/core/src/ch/asynk/tankontank/game/State.java b/core/src/ch/asynk/tankontank/game/State.java deleted file mode 100644 index efbf7f9..0000000 --- a/core/src/ch/asynk/tankontank/game/State.java +++ /dev/null @@ -1,35 +0,0 @@ -package ch.asynk.tankontank.game; - -public interface State -{ - enum StateType { - SELECT, - MOVE, - ROTATE, - ENGAGE, - BREAK, - PROMOTE, - ANIMATION, - REINFORCEMENT, - DEPLOYMENT, - WITHDRAW, - ABORT, - DONE - }; - - public void enter(StateType prevState); - - public void leave(StateType nextState); - - public StateType abort(); - - public StateType execute(); - - public void touchDown(); - - public void touchUp(); - - public boolean downInMap(float x, float y); - - public boolean upInMap(float x, float y); -} diff --git a/core/src/ch/asynk/tankontank/game/Unit.java b/core/src/ch/asynk/tankontank/game/Unit.java deleted file mode 100644 index dcca201..0000000 --- a/core/src/ch/asynk/tankontank/game/Unit.java +++ /dev/null @@ -1,361 +0,0 @@ -package ch.asynk.tankontank.game; - -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; - -import ch.asynk.tankontank.engine.Pawn; -import ch.asynk.tankontank.engine.Tile; -import ch.asynk.tankontank.engine.HeadedPawn; -import ch.asynk.tankontank.engine.Orientation; -import ch.asynk.tankontank.game.Hex.Terrain; - -import ch.asynk.tankontank.TankOnTank; - -public class Unit extends HeadedPawn -{ - public static final int MOVE = 0; - public static final int TARGET = 1; - public static final int FIRE = 2; - public static final int MAY_FIRE = 3; - public static final int ACE = 4; - public static final int HQ = 5; - public static final int HAS_FIRED = 6; - public static final int HAS_MOVED = 7; - - public static final int FLANK_ATTACK_BONUS = 1; - - public enum UnitType implements Pawn.PawnType - { - HARD_TARGET, - HARD_TARGET_HQ, - INFANTRY, - AT_GUN, - ARTILLERY - } - - public enum UnitId implements Pawn.PawnId - { - GE_AT_GUN("German Anti-Tank Gun"), - GE_INFANTRY("German Infantry"), - GE_KINGTIGER("German King Tiger"), - GE_PANZER_IV("German Panzer IV"), - GE_PANZER_IV_HQ("German Panzer IV HQ"), - GE_TIGER("German Tiger"), - GE_WESPE("German Wespe"), - - US_AT_GUN("US Anti-Tank Gun"), - US_INFANTRY("US Infantry"), - US_PERSHING("US Pershing"), - US_PERSHING_HQ("US Pershing HQ"), - US_PRIEST("US Priest"), - US_SHERMAN("US Sherman"), - US_SHERMAN_HQ("US Sherman HQ"), - US_WOLVERINE("US Wolverine"); - - private String s; - UnitId(String s) { this.s = s; } - public String toString() { return s; } - } - - public int rng; - public int def; - public int cdef; - public int mp; - public int mpLeft; - public UnitType type; - public UnitId id; - public boolean ace; - private boolean hasMoved; - private boolean hasFired; - - protected Unit(Army army, String pawn, String head, TextureAtlas pawns, TextureAtlas overlays) - { - super(army, pawn, head, pawns, overlays); - ace = false; - - } - - private void commonSetup() - { - mpLeft = mp; - enableOverlay(HQ, isHq()); - this.hasMoved = false; - this.hasFired = false; - updateDescr(); - } - - private void updateDescr() - { - if (cdef == -1) - this.descr = id.toString() + (ace ? " Ace " : "") + " (" + rng + "-" + def + "-" + mp + ")"; - else - this.descr = id.toString() + (ace ? " Ace " : "") + " (" + rng + "-" + def + "/" + cdef + "-" + mp + ")"; - } - - // hard tager - public Unit(Army army, UnitId id, UnitType type, int range, int defense, int movementPoints, String unit, String head, TextureAtlas pawns, TextureAtlas overlays) - { - this(army, unit, head, pawns, overlays); - this.rng = range; - this.def = defense; - this.cdef = -1; - this.mp = movementPoints; - this.id = id; - this.type = type; - commonSetup(); - } - - // soft tager - public Unit(Army army, UnitId id, UnitType type, int range, int defense, int concealedDefense, int movementPoints, String unit, String head, TextureAtlas pawns, TextureAtlas overlays) - { - this(army, unit, head, pawns, overlays); - this.rng = range; - this.def = defense; - this.cdef = concealedDefense; - this.mp = movementPoints; - this.id = id; - this.type = type; - commonSetup(); - } - - public Army getArmy() - { - return (Army) getFaction(); - } - - public Hex getHex() - { - return (Hex) getTile(); - } - - public boolean isAce() - { - return ace; - } - - public void setAce(boolean ace) - { - this.ace = ace; - updateDescr(); - enableOverlay(ACE, ace); - } - - @Override - public int getMovementPoints() - { - return mpLeft; - } - - @Override - public int getRoadMarchBonus() - { - return 1; - } - - @Override - public int getEngagementRangeFrom(Tile tile) - { - if (!isA(UnitType.INFANTRY) && tile.isA(Terrain.HILLS)) - return rng + 1; - return rng; - } - - @Override - public int getAngleOfAttack() - { - return orientation.getFrontSides(); - } - - @Override - public int getFlankSides() - { - return orientation.getBackSides(); - } - - @Override - public int getDefense(Tile tile) - { - if (!isHardTarget() && (tile.isA(Terrain.HILLS) || tile.isA(Terrain.WOODS) || tile.isA(Terrain.TOWN))) - return cdef; - - return def; - } - - @Override - public boolean isUnit() - { - return true; - } - - @Override - public boolean isA(PawnId i) - { - return (id == i); - } - - @Override - public boolean isA(PawnType t) - { - return (type == t); - } - - @Override - public boolean isHq() - { - return isA(UnitType.HARD_TARGET_HQ); - } - - @Override - public boolean isHqOf(Pawn other) - { - if (isA(UnitId.GE_PANZER_IV_HQ) && other.isA(UnitId.GE_PANZER_IV)) return true; - if (isA(UnitId.US_PERSHING_HQ) && other.isA(UnitId.US_PERSHING)) return true; - if (isA(UnitId.US_SHERMAN_HQ) && other.isA(UnitId.US_SHERMAN)) return true; - return false; - } - - public void promote() - { - if (isA(UnitId.GE_PANZER_IV)) - id = UnitId.GE_PANZER_IV_HQ; - else if (isA(UnitId.US_PERSHING)) - id = UnitId.US_PERSHING_HQ; - else if (isA(UnitId.US_SHERMAN)) - id = UnitId.US_SHERMAN_HQ; - else - return; - - type = UnitType.HARD_TARGET_HQ; - enableOverlay(HQ, true); - updateDescr(); - } - - public void degrade() - { - if (isA(UnitId.GE_PANZER_IV_HQ)) - id = UnitId.GE_PANZER_IV; - else if (isA(UnitId.US_PERSHING_HQ)) - id = UnitId.US_PERSHING; - else if (isA(UnitId.US_SHERMAN_HQ)) - id = UnitId.US_SHERMAN; - else - return; - - type = UnitType.HARD_TARGET; - enableOverlay(HQ, false); - updateDescr(); - } - - @Override - public boolean isHardTarget() - { - return (isA(UnitType.HARD_TARGET) || isA(UnitType.HARD_TARGET_HQ) || isA(UnitType.ARTILLERY)); - } - - @Override - public boolean canRotate() - { - return canMove(); - } - - @Override - public boolean canMove() - { - if (isHardTarget()) return !hasMoved; - return (!hasMoved && !hasFired); - } - - @Override - public boolean canEngage() - { - if (isHardTarget()) return !hasFired; - return (!hasMoved && !hasFired); - } - - @Override - public boolean canAssistEngagementWithoutLos() - { - return isA(UnitType.ARTILLERY); - } - - @Override - public boolean canEngage(Pawn other) - { - return (isEnemy(other) && canEngage()); - } - - public boolean canHQMove() - { - return (isHq() && ((move == null) || (!move.isEnter()))); - } - - public void setMoved() - { - hasMoved = true; - updateOverlays(); - } - - @Override - public void move() - { - int cost = move.cost; - - if (move.roadMarch && (cost > mpLeft)) - cost -= getRoadMarchBonus(); - - if (cost > mpLeft) - TankOnTank.debug("ERROR: Movement point exceeded: " + cost + "/" + mpLeft + " please report"); - - if (move.isFinal()) - setMoved(); - - mpLeft -= cost; - } - - @Override - public void engage() - { - hasFired = true; - updateOverlays(); - } - - @Override - public void reset() - { - super.reset(); - mpLeft = mp; - hasFired = false; - hasMoved = false; - hideHasMoved(); - hideHasFired(); - } - - @Override - public void revertLastMove() - { - hasMoved = false; - mpLeft = mp; - updateOverlays(); - move = null; - } - - private void updateOverlays() - { - enableOverlay(HAS_MOVED, !canMove()); - enableOverlay(HAS_FIRED, !canEngage()); - } - - // SHOW / HIDE - public void showMoveable() { enableOverlay(MOVE, true); } - public void hideMoveable() { enableOverlay(MOVE, false); } - public void showTarget() { enableOverlay(TARGET, true); } - public void hideTarget() { enableOverlay(TARGET, false); } - public void showAttack() { enableOverlay(FIRE, true); } - public void hideAttack() { enableOverlay(FIRE, false); } - public void showAttackAssist() { enableOverlay(MAY_FIRE, true); } - public void hideAttackAssist() { enableOverlay(MAY_FIRE, false); } - public void showHasMoved() { enableOverlay(HAS_MOVED, true); } - public void hideHasMoved() { enableOverlay(HAS_MOVED, false); } - public void showHasFired() { enableOverlay(HAS_FIRED, true); } - public void hideHasFired() { enableOverlay(HAS_FIRED, false); } -} diff --git a/core/src/ch/asynk/tankontank/game/UnitList.java b/core/src/ch/asynk/tankontank/game/UnitList.java deleted file mode 100644 index 4019add..0000000 --- a/core/src/ch/asynk/tankontank/game/UnitList.java +++ /dev/null @@ -1,20 +0,0 @@ -package ch.asynk.tankontank.game; - -import java.util.Collection; -import java.util.ArrayList; - -import ch.asynk.tankontank.engine.Pawn; - -public class UnitList extends ArrayList -{ - public UnitList(int n) - { - super(n); - } - - @SuppressWarnings("unchecked") - public Collection asPawns() - { - return (Collection) this; - } -} diff --git a/core/src/ch/asynk/tankontank/game/Zone.java b/core/src/ch/asynk/tankontank/game/Zone.java deleted file mode 100644 index de3a0d9..0000000 --- a/core/src/ch/asynk/tankontank/game/Zone.java +++ /dev/null @@ -1,14 +0,0 @@ -package ch.asynk.tankontank.game; - -import ch.asynk.tankontank.engine.Orientation; - -public class Zone extends HexSet -{ - public int allowedMoves; - public Orientation orientation; - - public Zone(Map map, int n) - { - super(map, n); - } -} diff --git a/core/src/ch/asynk/tankontank/game/battles/BattleCommon.java b/core/src/ch/asynk/tankontank/game/battles/BattleCommon.java deleted file mode 100644 index 413b8ab..0000000 --- a/core/src/ch/asynk/tankontank/game/battles/BattleCommon.java +++ /dev/null @@ -1,151 +0,0 @@ -package ch.asynk.tankontank.game.battles; - -import java.util.Random; -import java.util.HashMap; -import java.util.ArrayList; - -import ch.asynk.tankontank.game.Army; -import ch.asynk.tankontank.game.Battle; -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.HexSet; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Unit.UnitId; -import ch.asynk.tankontank.game.State.StateType; - -public abstract class BattleCommon implements Battle -{ - protected final static Random random = new Random(); - - protected Factory.MapType mapType; - protected String name; - protected String description; - protected Factory factory; - protected Player usPlayer; - protected Player gePlayer; - protected ArrayList entryZone = new ArrayList(); - protected ArrayList exitZone = new ArrayList(); - protected HashMap unitEntry = new HashMap(); - protected HashMap unitExit = new HashMap(); - - public BattleCommon(Factory factory) - { - this.factory = factory; - } - - @Override - public void init() - { - this.usPlayer = factory.getPlayer(Army.US); - this.gePlayer = factory.getPlayer(Army.GE); - } - - @Override - public String toString() - { - return getName(); - } - - @Override - public String getName() - { - return name; - } - - @Override - public String getDescription() - { - return description; - } - - @Override - public Factory.MapType getMapType() - { - return mapType; - } - - @Override - public Map getMap() - { - return factory.getMap(mapType); - } - - @Override - public Player opponent(Player player) - { - if (player == usPlayer) - return gePlayer; - return usPlayer; - } - - @Override - public boolean deploymentDone(Player player) - { - return player.isDeploymentDone(); - } - - @Override - public StateType getState(Player player) - { - if (!player.isDeploymentDone()) - return StateType.DEPLOYMENT; - return StateType.SELECT; - } - - @Override - public boolean getReinforcement(Ctrl ctrl, Map map) - { - return false; - } - - @Override - public Zone getEntryZone(Unit unit) - { - return unitEntry.get(unit); - } - - @Override - public Zone getExitZone(Unit unit) - { - return unitExit.get(unit); - } - - public void addEntryZone(Zone entry) - { - entryZone.add(entry); - } - - public void addExitZone(Zone exit) - { - exitZone.add(exit); - exit.enable(Hex.EXIT, true); - } - - public void addReinforcement(Player player, Zone entryZone, UnitId unitId) - { - addReinforcement(player, entryZone, unitId, false); - } - - public void addReinforcement(Player player, Zone entryZone, Zone exitZone, UnitId unitId) - { - addReinforcement(player, entryZone, exitZone, unitId, false); - } - - public void addReinforcement(Player player, Zone entryZone, UnitId unitId, boolean ace) - { - addReinforcement(player, entryZone, null, unitId, ace); - } - - public void addReinforcement(Player player, Zone entryZone, Zone exitZone, UnitId unitId, boolean ace) - { - Unit unit = factory.getUnit(unitId); - unit.setAce(ace); - player.addReinforcement(unit); - unitEntry.put(unit, entryZone); - if (exitZone != null) - unitExit.put(unit, exitZone); - } -} diff --git a/core/src/ch/asynk/tankontank/game/battles/BattleCounterAttack.java b/core/src/ch/asynk/tankontank/game/battles/BattleCounterAttack.java deleted file mode 100644 index bcc08f2..0000000 --- a/core/src/ch/asynk/tankontank/game/battles/BattleCounterAttack.java +++ /dev/null @@ -1,150 +0,0 @@ -package ch.asynk.tankontank.game.battles; - -import ch.asynk.tankontank.game.Army; -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Unit.UnitId; -import ch.asynk.tankontank.ui.Position; -import ch.asynk.tankontank.engine.Orientation; - -public class BattleCounterAttack extends BattleCommon -{ - public BattleCounterAttack(Factory factory) - { - super(factory); - name = "Counterattack"; - mapType = Factory.MapType.MAP_B; - } - - @Override - public Position getHudPosition(Player player) - { - return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); - } - - @Override - public Player getPlayer() - { - if (!gePlayer.isDeploymentDone()) - return gePlayer; - if (!usPlayer.isDeploymentDone()) - return usPlayer; - if (gePlayer.getTurnDone() == usPlayer.getTurnDone()) - return gePlayer; - return usPlayer; - } - - public Player checkVictory(Ctrl ctrl) - { - if (ctrl.opponent.unitsLeft() == 0) - return ctrl.player; - - if (gePlayer.withdrawed() >= 3) - return gePlayer; - - if ((ctrl.player.getTurnDone() < 9) || (ctrl.opponent.getTurnDone() < 9)) - return null; - - return usPlayer; - } - - @Override - public boolean getReinforcement(Ctrl ctrl, Map map) - { - if (ctrl.player.is(Army.GE)) - return false; - if (ctrl.player.getCurrentTurn() != 5) - return false; - - // hex row 1 - Zone usEntry = new Zone(map, 9); - usEntry.allowedMoves = (Orientation.SOUTH.s | Orientation.SOUTH_EAST.s | Orientation.SOUTH_WEST.s); - usEntry.add(map.getHex(9, 0)); - usEntry.add(map.getHex(9, 1)); - usEntry.add(map.getHex(10, 2)); - usEntry.add(map.getHex(10, 3)); - usEntry.add(map.getHex(11, 4)); - usEntry.add(map.getHex(11, 5)); - usEntry.add(map.getHex(12, 6)); - usEntry.add(map.getHex(12, 7)); - usEntry.add(map.getHex(13, 8)); - addEntryZone(usEntry); - - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_PRIEST); - - return true; - } - - @Override - public void setup(Ctrl ctrl, Map map) - { - // hex row 1 - Zone geExit = new Zone(map, 9); - geExit.orientation = Orientation.NORTH; - geExit.add(map.getHex(9, 0)); - geExit.add(map.getHex(9, 1)); - geExit.add(map.getHex(10, 2)); - geExit.add(map.getHex(10, 3)); - geExit.add(map.getHex(11, 4)); - geExit.add(map.getHex(11, 5)); - geExit.add(map.getHex(12, 6)); - geExit.add(map.getHex(12, 7)); - geExit.add(map.getHex(13, 8)); - addExitZone(geExit); - - // hex rows 8-9 - Zone geEntry = new Zone(map, 18); - geEntry.orientation = Orientation.NORTH; - for (int i = 0; i < 2; i++) { - geEntry.add(map.getHex((1 + i), 0)); - geEntry.add(map.getHex((1 + i), 1)); - geEntry.add(map.getHex((2 + i), 2)); - geEntry.add(map.getHex((2 + i), 3)); - geEntry.add(map.getHex((3 + i), 4)); - geEntry.add(map.getHex((3 + i), 5)); - geEntry.add(map.getHex((4 + i), 6)); - geEntry.add(map.getHex((4 + i), 7)); - geEntry.add(map.getHex((5 + i), 8)); - } - addEntryZone(geEntry); - - addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV_HQ); - addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV_HQ); - addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_TIGER); - addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_TIGER); - addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, geExit, UnitId.GE_WESPE); - - // hex rows 1-4 - Zone usEntry = new Zone(map, 36); - usEntry.orientation = Orientation.SOUTH; - for (int i = 0; i < 4; i++) { - usEntry.add(map.getHex((6 + i), 0)); - usEntry.add(map.getHex((6 + i), 1)); - usEntry.add(map.getHex((7 + i), 2)); - usEntry.add(map.getHex((7 + i), 3)); - usEntry.add(map.getHex((8 + i), 4)); - usEntry.add(map.getHex((8 + i), 5)); - usEntry.add(map.getHex((9 + i), 6)); - usEntry.add(map.getHex((9 + i), 7)); - usEntry.add(map.getHex((10 + i), 8)); - } - addEntryZone(usEntry); - - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); - addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - } -} diff --git a/core/src/ch/asynk/tankontank/game/battles/BattleFrontalAssault.java b/core/src/ch/asynk/tankontank/game/battles/BattleFrontalAssault.java deleted file mode 100644 index e3436cf..0000000 --- a/core/src/ch/asynk/tankontank/game/battles/BattleFrontalAssault.java +++ /dev/null @@ -1,124 +0,0 @@ -package ch.asynk.tankontank.game.battles; - -import ch.asynk.tankontank.game.Army; -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.HexSet; -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Unit.UnitId; -import ch.asynk.tankontank.ui.Position; -import ch.asynk.tankontank.engine.Orientation; - -public class BattleFrontalAssault extends BattleCommon -{ - public BattleFrontalAssault(Factory factory) - { - super(factory); - name = "Frontal Assault"; - mapType = Factory.MapType.MAP_A; - } - - - @Override - public Player getPlayer() - { - if (!gePlayer.isDeploymentDone()) { - int n = gePlayer.reinforcement(); - if (n > 4) - return gePlayer; - else { - if (usPlayer.isDeploymentDone()) - return gePlayer; - else - return usPlayer; - } - } - if (gePlayer.getTurnDone() == usPlayer.getTurnDone()) - return usPlayer; - return gePlayer; - } - - @Override - public Position getHudPosition(Player player) - { - return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); - } - - @Override - public boolean deploymentDone(Player player) - { - if (player.isDeploymentDone()) - return true; - return ((player.is(Army.GE) && (gePlayer.reinforcement.size() == 4))); - } - - @Override - public Player checkVictory(Ctrl ctrl) - { - if (ctrl.opponent.unitsLeft() == 0) - return ctrl.player; - - if ((ctrl.player.getTurnDone() < 10) || (ctrl.opponent.getTurnDone() < 10)) - return null; - - if (ctrl.map.objectives.count(Army.US) >= 2) - return usPlayer; - else - return gePlayer; - } - - @Override - public void setup(Ctrl ctrl, Map map) - { - // G9, E6, H4 - map.addObjective(2, 2, Army.NONE); - map.addObjective(6, 4, Army.NONE); - map.addObjective(6, 1, Army.NONE); - - // hex rows E-H - Zone geEntry = new Zone(map, 38); - geEntry.orientation = Orientation.NORTH_WEST; - for (int i = 2; i < 12; i++) - geEntry.add(map.getHex(i, 4)); - for (int i = 2; i < 11; i++) - geEntry.add(map.getHex(i, 3)); - for (int i = 1; i < 11; i++) - geEntry.add(map.getHex(i, 2)); - for (int i = 1; i < 10; i++) - geEntry.add(map.getHex(i, 1)); - addEntryZone(geEntry); - - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); - addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); - addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - - // hex rows A-B - Zone usEntry = new Zone(map, 19); - usEntry.orientation = Orientation.SOUTH_EAST; - for (int i = 4; i < 14; i++) - usEntry.add(map.getHex(i, 8)); - for (int i = 4; i < 13; i++) - usEntry.add(map.getHex(i, 7)); - addEntryZone(usEntry); - - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); - addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_PRIEST); - } -} diff --git a/core/src/ch/asynk/tankontank/game/battles/BattleHeadToHead.java b/core/src/ch/asynk/tankontank/game/battles/BattleHeadToHead.java deleted file mode 100644 index 0bb6e7e..0000000 --- a/core/src/ch/asynk/tankontank/game/battles/BattleHeadToHead.java +++ /dev/null @@ -1,118 +0,0 @@ -package ch.asynk.tankontank.game.battles; - -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Army; -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.HexSet; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Unit.UnitId; -import ch.asynk.tankontank.ui.Position; -import ch.asynk.tankontank.engine.Orientation; - -public class BattleHeadToHead extends BattleCommon -{ - private Army firstArmy; - - public BattleHeadToHead(Factory factory) - { - super(factory); - name = "Head To Head"; - firstArmy = ((random.nextInt(2) == 0) ? Army.US : Army.GE); - mapType = Factory.MapType.MAP_A; - } - - @Override - public Player getPlayer() - { - if (gePlayer.getTurnDone() == usPlayer.getTurnDone()) - return ((firstArmy == Army.US) ? usPlayer : gePlayer); - else - return ((firstArmy == Army.US) ? gePlayer : usPlayer); - } - - @Override - public Position getHudPosition(Player player) - { - return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); - } - - @Override - public Player checkVictory(Ctrl ctrl) - { - if (ctrl.opponent.unitsLeft() == 0) - return ctrl.player; - - if ((ctrl.player.getTurnDone() < 10) || (ctrl.opponent.getTurnDone() < 10)) - return null; - - if (ctrl.map.objectives.count(Army.US) >= 2) - return usPlayer; - if (ctrl.map.objectives.count(Army.GE) >= 2) - return gePlayer; - - return null; - } - - @Override - public void setup(Ctrl ctrl, Map map) - { - // end deployment - usPlayer.turnEnd(); - gePlayer.turnEnd(); - - // B6, E6, H4 - map.addObjective(7, 7, Army.NONE); - map.addObjective(6, 4, Army.NONE); - map.addObjective(6, 1, Army.NONE); - - // southern hex row - Zone geEntry = new Zone(map, 9); - geEntry.allowedMoves = (Orientation.NORTH.s | Orientation.NORTH_EAST.s | Orientation.NORTH_WEST.s); - geEntry.add(map.getHex(0, 0)); - geEntry.add(map.getHex(1, 1)); - geEntry.add(map.getHex(1, 2)); - geEntry.add(map.getHex(2, 3)); - geEntry.add(map.getHex(2, 4)); - geEntry.add(map.getHex(3, 5)); - geEntry.add(map.getHex(3, 6)); - geEntry.add(map.getHex(4, 7)); - geEntry.add(map.getHex(4, 8)); - addEntryZone(geEntry); - - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); - addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); - addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - - // northern hex row - Zone usEntry = new Zone(map, 9); - usEntry.allowedMoves = (Orientation.SOUTH.s | Orientation.SOUTH_EAST.s | Orientation.SOUTH_WEST.s); - usEntry.add(map.getHex(9, 0)); - usEntry.add(map.getHex(9, 1)); - usEntry.add(map.getHex(10, 2)); - usEntry.add(map.getHex(10, 3)); - usEntry.add(map.getHex(11, 4)); - usEntry.add(map.getHex(11, 5)); - usEntry.add(map.getHex(12, 6)); - usEntry.add(map.getHex(12, 7)); - usEntry.add(map.getHex(13, 8)); - addEntryZone(usEntry); - - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); - addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_PRIEST); - } -} diff --git a/core/src/ch/asynk/tankontank/game/battles/BattleLastStand.java b/core/src/ch/asynk/tankontank/game/battles/BattleLastStand.java deleted file mode 100644 index a8b1952..0000000 --- a/core/src/ch/asynk/tankontank/game/battles/BattleLastStand.java +++ /dev/null @@ -1,136 +0,0 @@ -package ch.asynk.tankontank.game.battles; - -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Army; -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.HexSet; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Unit.UnitId; -import ch.asynk.tankontank.ui.Position; -import ch.asynk.tankontank.engine.Orientation; - -public class BattleLastStand extends BattleCommon -{ - public BattleLastStand(Factory factory) - { - super(factory); - name = "Last Stand"; - mapType = Factory.MapType.MAP_B; - } - - @Override - public Position getHudPosition(Player player) - { - return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); - } - - @Override - public Player getPlayer() - { - if (!gePlayer.isDeploymentDone()) - return gePlayer; - if (!usPlayer.isDeploymentDone()) - return usPlayer; - if (gePlayer.getTurnDone() == usPlayer.getTurnDone()) - return usPlayer; - return gePlayer; - } - - public Player checkVictory(Ctrl ctrl) - { - if (ctrl.opponent.unitsLeft() == 0) - return ctrl.player; - - if ((ctrl.player.getTurnDone() < 8) || (ctrl.opponent.getTurnDone() < 8)) - return null; - - int gePoints = usPlayer.casualties(); - int usPoints = gePlayer.casualties(); - usPoints += ctrl.map.objectives.count(Army.US); - for (Unit unit : gePlayer.casualties) { - if (unit.isAce()) - usPoints += 1; - } - - if (usPoints > gePoints) - return usPlayer; - else - return gePlayer; - } - - @Override - public void setup(Ctrl ctrl, Map map) - { - // A7, E6, F6, G10 - map.addObjective(7, 8, Army.NONE); - map.addObjective(6, 4, Army.NONE); - map.addObjective(5, 3, Army.NONE); - map.addObjective(1, 2, Army.NONE); - - // 1 hex of E7 - Zone geEntry = new Zone(map, 7); - geEntry.orientation = Orientation.NORTH; - geEntry.add(map.getHex(5, 5)); - geEntry.add(map.getHex(4, 4)); - geEntry.add(map.getHex(4, 3)); - geEntry.add(map.getHex(5, 3)); - geEntry.add(map.getHex(6, 4)); - geEntry.add(map.getHex(6, 5)); - geEntry.add(map.getHex(5, 4)); - addEntryZone(geEntry); - - addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER, true); - addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); - addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); - - // hex rows 7-10 - geEntry = new Zone(map, 32); - geEntry.orientation = Orientation.NORTH; - for (int i = 0; i < 4; i++) { - geEntry.add(map.getHex(i, 0)); - geEntry.add(map.getHex((i + 1), 2)); - geEntry.add(map.getHex((i + 2), 4)); - geEntry.add(map.getHex((i + 3), 6)); - geEntry.add(map.getHex((i + 4), 8)); - } - for (int i = 0; i < 3; i++) { - geEntry.add(map.getHex((i + 1), 1)); - geEntry.add(map.getHex((i + 2), 3)); - geEntry.add(map.getHex((i + 3), 5)); - geEntry.add(map.getHex((i + 4), 7)); - } - addEntryZone(geEntry); - - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_WESPE); - - // hex rows hex row 1 + E2 + C2 - Zone usEntry = new Zone(map, 11); - usEntry.orientation = Orientation.SOUTH; - usEntry.add(map.getHex(9, 0)); - usEntry.add(map.getHex(9, 1)); - usEntry.add(map.getHex(10, 2)); - usEntry.add(map.getHex(10, 3)); - usEntry.add(map.getHex(11, 4)); - usEntry.add(map.getHex(11, 5)); - usEntry.add(map.getHex(12, 6)); - usEntry.add(map.getHex(12, 7)); - usEntry.add(map.getHex(13, 8)); - usEntry.add(map.getHex(10, 4)); - usEntry.add(map.getHex(11, 6)); - addEntryZone(usEntry); - - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); - addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - } -} diff --git a/core/src/ch/asynk/tankontank/game/battles/BattleNightAction.java b/core/src/ch/asynk/tankontank/game/battles/BattleNightAction.java deleted file mode 100644 index ddcb9ae..0000000 --- a/core/src/ch/asynk/tankontank/game/battles/BattleNightAction.java +++ /dev/null @@ -1,153 +0,0 @@ -package ch.asynk.tankontank.game.battles; - -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Army; -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.HexSet; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Unit.UnitId; -import ch.asynk.tankontank.ui.Position; -import ch.asynk.tankontank.engine.Orientation; -import ch.asynk.tankontank.engine.Meteorology; - -public class BattleNightAction extends BattleCommon -{ - public BattleNightAction(Factory factory) - { - super(factory); - name = "Night Action"; - mapType = Factory.MapType.MAP_B; - } - - @Override - public Position getHudPosition(Player player) - { - return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); - } - - @Override - public Player getPlayer() - { - if (!gePlayer.isDeploymentDone() || gePlayer.getCurrentTurn() == 1) - return gePlayer; - if (gePlayer.getTurnDone() > usPlayer.getTurnDone()) - return usPlayer; - return gePlayer; - } - - private boolean isClear(Map map, int col, int row) - { - Hex hex = map.getHex(col, row); - Unit unit = hex.getUnit(); - if ((unit != null) && unit.is(Army.GE)) { - map.selectHex(hex); - return false; - } - map.showMove(hex); - return true; - } - - public Player checkVictory(Ctrl ctrl) - { - if (ctrl.opponent.unitsLeft() == 0) - return ctrl.player; - - if ((ctrl.player.getTurnDone() < 9) || (ctrl.opponent.getTurnDone() < 9)) - return null; - - Map map = ctrl.map; - boolean clear = true; - clear &= isClear(map, 4, 8); - clear &= isClear(map, 5, 8); - clear &= isClear(map, 6, 8); - clear &= isClear(map, 7, 8); - clear &= isClear(map, 8, 8); - clear &= isClear(map, 8, 7); - clear &= isClear(map, 8, 6); - boolean upLeft = clear; - clear = true; - clear &= isClear(map, 8, 6); - clear &= isClear(map, 9, 6); - clear &= isClear(map, 10, 6); - clear &= isClear(map, 11, 6); - clear &= isClear(map, 12, 6); - boolean upRight = clear; - clear = true; - clear &= isClear(map, 1, 2); - clear &= isClear(map, 2, 3); - clear &= isClear(map, 3, 3); - clear &= isClear(map, 4, 3); - clear &= isClear(map, 5, 3); - clear &= isClear(map, 6, 4); - clear &= isClear(map, 7, 4); - clear &= isClear(map, 8, 4); - boolean bottomLeft = clear; - clear &= isClear(map, 8, 4); - clear &= isClear(map, 9, 4); - clear &= isClear(map, 10, 4); - clear &= isClear(map, 11, 4); - clear = true; - boolean bottomRight = clear; - // clear &= isClear(map, 8, 6); - // clear &= isClear(map, 8, 5); - // clear &= isClear(map, 8, 4); - // clear = true; - // boolean link = clear; - - if ((!upLeft || !upRight) && (!bottomLeft || !bottomRight)) - return gePlayer; - return usPlayer; - } - - @Override - public void setup(Ctrl ctrl, Map map) - { - map.meteorology.day = Meteorology.Day.NIGHT; - - // hex row I - Zone geEntry = new Zone(map, 10); - geEntry.orientation = Orientation.NORTH_EAST; - for (int i = 0; i < 10; i++) - geEntry.add(map.getHex(i, 0)); - addEntryZone(geEntry); - - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); - addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); - addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_INFANTRY); - addReinforcement(gePlayer, geEntry, UnitId.GE_INFANTRY); - - // hex rows A-B - Zone usEntry = new Zone(map, 19); - usEntry.orientation = Orientation.SOUTH; - for (int i = 0; i < 10; i++) { - usEntry.add(map.getHex((4 + i), 8)); - usEntry.add(map.getHex((3 + i), 6)); - usEntry.add(map.getHex((2 + i), 4)); - usEntry.add(map.getHex((1 + i), 2)); - } - for (int i = 0; i < 9; i++) { - usEntry.add(map.getHex((4 + i), 7)); - usEntry.add(map.getHex((3 + i), 5)); - usEntry.add(map.getHex((2 + i), 3)); - } - addEntryZone(usEntry); - - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, UnitId.US_WOLVERINE); - addReinforcement(usPlayer, usEntry, UnitId.US_AT_GUN); - addReinforcement(usPlayer, usEntry, UnitId.US_INFANTRY); - addReinforcement(usPlayer, usEntry, UnitId.US_INFANTRY); - } -} diff --git a/core/src/ch/asynk/tankontank/game/battles/BattleStabToTheFlank.java b/core/src/ch/asynk/tankontank/game/battles/BattleStabToTheFlank.java deleted file mode 100644 index 5e910d4..0000000 --- a/core/src/ch/asynk/tankontank/game/battles/BattleStabToTheFlank.java +++ /dev/null @@ -1,143 +0,0 @@ -package ch.asynk.tankontank.game.battles; - -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Army; -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.HexSet; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Unit.UnitId; -import ch.asynk.tankontank.ui.Position; -import ch.asynk.tankontank.engine.Orientation; - -public class BattleStabToTheFlank extends BattleCommon -{ - public BattleStabToTheFlank(Factory factory) - { - super(factory); - name = "Stab To The Flank"; - mapType = Factory.MapType.MAP_B; - } - - @Override - public Position getHudPosition(Player player) - { - return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); - } - - @Override - public Player getPlayer() - { - if (!usPlayer.isDeploymentDone() || usPlayer.getCurrentTurn() == 1) - return usPlayer; - if (usPlayer.getTurnDone() > gePlayer.getTurnDone()) - return gePlayer; - return usPlayer; - } - - public Player checkVictory(Ctrl ctrl) - { - if (ctrl.opponent.unitsLeft() == 0) - return ctrl.player; - - if ((ctrl.player.getTurnDone() < 9) || (ctrl.opponent.getTurnDone() < 9)) - return null; - - int gePoints = usPlayer.casualties(); - int usPoints = gePlayer.casualties(); - usPoints += ctrl.map.objectives.count(Army.US); - - int withdrawed = usPlayer.withdrawed(); - if (withdrawed == 0) - gePoints += 1; - else - usPoints += withdrawed; - - if (usPoints > gePoints) - return usPlayer; - else - return gePlayer; - } - - @Override - public boolean getReinforcement(Ctrl ctrl, Map map) - { - if (ctrl.player.is(Army.US)) - return false; - if (ctrl.player.getCurrentTurn() != 3) - return false; - - // hex rows I - Zone geEntry = new Zone(map, 9); - geEntry.allowedMoves = (Orientation.SOUTH_WEST.s | Orientation.NORTH_WEST.s); - for (int i = 0; i < 10; i++) - geEntry.add(map.getHex(i, 0)); - addEntryZone(geEntry); - - addReinforcement(gePlayer, geEntry, UnitId.GE_TIGER, true); - - return true; - } - - @Override - public void setup(Ctrl ctrl, Map map) - { - // F6, E6 - map.addHoldObjective(5, 3, Army.NONE); - map.addObjective(6, 4, Army.NONE); - - // hex rows D-I - Zone geEntry = new Zone(map, 57); - geEntry.orientation = Orientation.NORTH; - for (int i = 3; i < 12; i++) - geEntry.add(map.getHex(i, 5)); - for (int i = 2; i < 12; i++) - geEntry.add(map.getHex(i, 4)); - for (int i = 2; i < 11; i++) - geEntry.add(map.getHex(i, 3)); - for (int i = 1; i < 11; i++) - geEntry.add(map.getHex(i, 2)); - for (int i = 1; i < 10; i++) - geEntry.add(map.getHex(i, 1)); - for (int i = 0; i < 10; i++) - geEntry.add(map.getHex(i, 0)); - - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV_HQ); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_PANZER_IV); - addReinforcement(gePlayer, geEntry, UnitId.GE_AT_GUN); - addReinforcement(gePlayer, geEntry, UnitId.GE_INFANTRY); - - // hex row I - Zone usExit = new Zone(map, 10); - usExit.orientation = Orientation.NORTH_EAST; - for (int i = 0; i < 10; i++) - geEntry.add(map.getHex(i, 0)); - addExitZone(usExit); - - // hex rows A-B - Zone usEntry = new Zone(map, 19); - usEntry.orientation = Orientation.SOUTH_EAST; - for (int i = 4; i < 13; i++) { - usEntry.add(map.getHex(i, 8)); - usEntry.add(map.getHex(i, 7)); - } - usEntry.add(map.getHex(13, 8)); - addEntryZone(usEntry); - - addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN_HQ); - addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, usExit, UnitId.US_SHERMAN); - addReinforcement(usPlayer, usEntry, usExit, UnitId.US_INFANTRY); - addReinforcement(usPlayer, usEntry, usExit, UnitId.US_INFANTRY); - addReinforcement(usPlayer, usEntry, usExit, UnitId.US_PRIEST); - } -} diff --git a/core/src/ch/asynk/tankontank/game/battles/BattleTest.java b/core/src/ch/asynk/tankontank/game/battles/BattleTest.java deleted file mode 100644 index e844d15..0000000 --- a/core/src/ch/asynk/tankontank/game/battles/BattleTest.java +++ /dev/null @@ -1,128 +0,0 @@ -package ch.asynk.tankontank.game.battles; - -import ch.asynk.tankontank.game.Army; -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.HexSet; -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Unit.UnitId; -import ch.asynk.tankontank.ui.Position; -import ch.asynk.tankontank.engine.Orientation; - -public class BattleTest extends BattleCommon -{ - private Zone usExit; - - public BattleTest(Factory factory) - { - super(factory); - name = "*** Test ***"; - mapType = Factory.MapType.MAP_B; - } - - @Override - public Player getPlayer() - { - if (!gePlayer.isDeploymentDone()) - return gePlayer; - - if (gePlayer.getTurnDone() == usPlayer.getTurnDone()) - return usPlayer; - return gePlayer; - } - - @Override - public Position getHudPosition(Player player) - { - return (player.is(Army.US) ? Position.TOP_RIGHT: Position.TOP_LEFT); - } - - @Override - public Player checkVictory(Ctrl ctrl) - { - if (usPlayer.getTurnDone() > 2) - return usPlayer; - return null; - } - - @Override - public boolean getReinforcement(Ctrl ctrl, Map map) - { - if (ctrl.player.is(Army.GE)) - return false; - if (ctrl.player.getCurrentTurn() != 2) - return false; - - Zone usEntry = new Zone(map, 1); - usEntry.allowedMoves = (Orientation.SOUTH.s | Orientation.SOUTH_EAST.s | Orientation.SOUTH_WEST.s); - usEntry.add(map.getHex(12, 6)); - addEntryZone(usEntry); - addReinforcement(usPlayer, usEntry, usExit, UnitId.US_WOLVERINE); - - return true; - } - - private Unit setUnit(Map map, Player player, UnitId unitId, int col, int row, Orientation orientation, Zone exitZone) - { - return setUnit(map, player, unitId, col, row, orientation, false, exitZone); - } - - private Unit setUnit(Map map, Player player, UnitId unitId, int col, int row, Orientation orientation, boolean ace, Zone exitZone) - { - Unit u = factory.getUnit(unitId); - u.setAce(ace); - if (exitZone != null) - unitExit.put(u, exitZone); - map.setOnBoard(u, map.getHex(col, row), orientation); - return u; - } - - @Override - public void setup(Ctrl ctrl, Map map) - { - map.addObjective(6, 4, Army.NONE); - map.addHoldObjective(5, 3, Army.NONE); - map.addObjective(3, 4, Army.NONE); - map.addHoldObjective(3, 3, Army.NONE); - - ctrl.player = gePlayer; - setUnit(map, gePlayer, UnitId.GE_WESPE, 5, 8, Orientation.NORTH, null); - setUnit(map, gePlayer, UnitId.GE_TIGER, 6, 4, Orientation.NORTH, null); - setUnit(map, gePlayer, UnitId.GE_PANZER_IV, 4, 5, Orientation.NORTH_WEST, null); - setUnit(map, gePlayer, UnitId.GE_INFANTRY, 1, 2, Orientation.NORTH_WEST, null); - setUnit(map, gePlayer, UnitId.GE_KINGTIGER, 1, 1, Orientation.NORTH_WEST, null); - Zone geEntry = new Zone(map, 6); - geEntry.orientation = Orientation.NORTH; - geEntry.add(map.getHex(1, 2)); - geEntry.add(map.getHex(1, 1)); - geEntry.add(map.getHex(3, 3)); - geEntry.add(map.getHex(3, 4)); - geEntry.add(map.getHex(4, 0)); - geEntry.add(map.getHex(5, 0)); - addEntryZone(geEntry); - addReinforcement(gePlayer, geEntry, UnitId.GE_AT_GUN); - - usExit = new Zone(map, 9); - usExit.orientation = Orientation.NORTH; - usExit.add(map.getHex(11, 4)); - usExit.add(map.getHex(11, 5)); - usExit.add(map.getHex(12, 6)); - addExitZone(usExit); - - ctrl.player = usPlayer; - usPlayer.casualty(factory.getUnit(UnitId.US_SHERMAN_HQ)); - setUnit(map, usPlayer, UnitId.US_PRIEST, 10, 8, Orientation.SOUTH_EAST, usExit); - setUnit(map, usPlayer, UnitId.US_SHERMAN, 7, 3, Orientation.SOUTH, true, usExit); - setUnit(map, usPlayer, UnitId.US_SHERMAN_HQ, 8, 4, Orientation.SOUTH, usExit); - setUnit(map, usPlayer, UnitId.US_WOLVERINE, 9, 7, Orientation.SOUTH_EAST, usExit); - setUnit(map, usPlayer, UnitId.US_PERSHING, 6, 6, Orientation.NORTH_EAST, usExit); - setUnit(map, usPlayer, UnitId.US_INFANTRY, 5, 3, Orientation.NORTH_WEST, usExit); - setUnit(map, usPlayer, UnitId.US_AT_GUN, 10, 3, Orientation.SOUTH, usExit); - usPlayer.turnEnd(); - map.init(); - map.turnDone(); - } -} diff --git a/core/src/ch/asynk/tankontank/game/battles/Factory.java b/core/src/ch/asynk/tankontank/game/battles/Factory.java deleted file mode 100644 index 7002e43..0000000 --- a/core/src/ch/asynk/tankontank/game/battles/Factory.java +++ /dev/null @@ -1,192 +0,0 @@ -package ch.asynk.tankontank.game.battles; - -import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; - -import ch.asynk.tankontank.TankOnTank; -import ch.asynk.tankontank.engine.Board; -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.Army; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Unit.UnitId; -import ch.asynk.tankontank.game.Unit.UnitType; -import ch.asynk.tankontank.game.Battle; -import ch.asynk.tankontank.game.battles.BattleHeadToHead; -import ch.asynk.tankontank.game.battles.BattleFrontalAssault; -import ch.asynk.tankontank.game.battles.BattleLastStand; -import ch.asynk.tankontank.game.battles.BattleCounterAttack; -import ch.asynk.tankontank.game.battles.BattleStabToTheFlank; -import ch.asynk.tankontank.game.battles.BattleNightAction; -import ch.asynk.tankontank.game.battles.BattleTest; - -public class Factory implements Board.TileBuilder, Disposable -{ - public enum MapType - { - MAP_A, - MAP_B - } - - public enum Scenarios - { - FAKE - } - - public boolean assetsLoaded; - public TextureAtlas hudAtlas; - public TextureAtlas pawnsAtlas; - public TextureAtlas pawnOverlaysAtlas; - public TextureAtlas tileOverlaysAtlas; - public Battle battles[]; - private final TankOnTank game; - - public Factory(final TankOnTank game) - { - this.game = game; - this.assetsLoaded = false; - battles = new Battle[] { - new BattleHeadToHead(this), - new BattleFrontalAssault(this), - new BattleLastStand(this), - new BattleCounterAttack(this), - new BattleStabToTheFlank(this), - new BattleNightAction(this), - new BattleTest(this), - }; - } - - public void assetsLoaded() - { - if (assetsLoaded) return; - int i = game.config.graphics.i; - this.hudAtlas = game.manager.get("data/hud.atlas", TextureAtlas.class); - this.tileOverlaysAtlas = game.manager.get("data/hex-overlays.atlas", TextureAtlas.class); - this.pawnsAtlas = game.manager.get(String.format("data/units%d.atlas", i), TextureAtlas.class); - this.pawnOverlaysAtlas = game.manager.get(String.format("data/unit-overlays%d.atlas", i), TextureAtlas.class); - this.assetsLoaded = true; - } - - @Override - public void dispose() - { - if (!assetsLoaded) return; - hudAtlas.dispose(); - pawnsAtlas.dispose(); - pawnOverlaysAtlas.dispose(); - tileOverlaysAtlas.dispose(); - this.assetsLoaded = false; - } - - private Board.Config config() - { - Board.Config cfg = new Board.Config(); - cfg.cols = 10; - cfg.rows = 9; - cfg.x0 = 86; - cfg.y0 = 182; - cfg.w = 189; - cfg.dw = 94; - cfg.s = 110; - cfg.dh = 53.6f; - cfg.h = cfg.s + cfg.dh; - cfg.slope = (cfg.dh / (float) cfg.dw); - - return cfg; - } - - public Map getMap(MapType t) - { - Board.Config cfg = config(); - - Map m = null; - switch(t) { - case MAP_A: - m = new MapA(game, config(), "data/map_a.png"); - break; - case MAP_B: - m = new MapB(game, config(), "data/map_b.png"); - break; - } - - return m; - } - - public Player getPlayer(Army army) - { - if (army == Army.US) - return new Player(game, Army.US, 10); - else - return new Player(game, Army.GE, 10); - } - - public Unit getUnit(UnitId id) - { - Unit u = null; - UnitType ut = UnitType.HARD_TARGET; - UnitType utHq = UnitType.HARD_TARGET_HQ; - switch(id) { - case GE_AT_GUN: - ut = UnitType.AT_GUN; - u = new Unit(Army.GE, id, ut, 3, 8, 9, 1, "ge-at-gun", "ge-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case GE_INFANTRY: - ut = UnitType.INFANTRY; - u = new Unit(Army.GE, id, ut, 1, 7, 10, 1, "ge-infantry", "ge-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case GE_KINGTIGER: - u = new Unit(Army.GE, id, ut, 3, 12, 1, "ge-kingtiger", "ge-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case GE_PANZER_IV: - u = new Unit(Army.GE, id, ut, 2, 9, 2, "ge-panzer-iv", "ge-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case GE_PANZER_IV_HQ: - u = new Unit(Army.GE, id, utHq, 2, 9, 2, "ge-panzer-iv", "ge-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case GE_TIGER: - u = new Unit(Army.GE, id, ut, 3, 11, 1, "ge-tiger", "ge-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case GE_WESPE: - ut = UnitType.ARTILLERY; - u = new Unit(Army.GE, id, ut, 5, 8, 1, "ge-wespe", "ge-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case US_AT_GUN: - ut = UnitType.AT_GUN; - u = new Unit(Army.US, id, ut, 1, 7, 10, 1, "us-at-gun", "us-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case US_INFANTRY: - ut = UnitType.INFANTRY; - u = new Unit(Army.US, id, ut, 1, 7, 10, 1, "us-infantry", "us-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case US_PERSHING: - u = new Unit(Army.US, id, ut, 3, 10, 2, "us-pershing", "us-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case US_PERSHING_HQ: - u = new Unit(Army.US, id, utHq, 3, 10, 2, "us-pershing", "us-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case US_PRIEST: - ut = UnitType.ARTILLERY; - u = new Unit(Army.US, id, ut, 5, 8, 1, "us-priest", "us-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case US_SHERMAN: - u = new Unit(Army.US, id, ut, 2, 9, 2, "us-sherman", "us-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case US_SHERMAN_HQ: - u = new Unit(Army.US, id, utHq, 2, 9, 2, "us-sherman", "us-head", pawnsAtlas, pawnOverlaysAtlas); - break; - case US_WOLVERINE: - u = new Unit(Army.US, id, ut, 3, 8, 3, "us-wolverine", "us-head", pawnsAtlas, pawnOverlaysAtlas); - break; - } - - return u; - } - - public Hex getNewTile(float x, float y, int col, int row, boolean offmap) - { - Hex hex = new Hex(x, y, col, row, tileOverlaysAtlas); - if (offmap) hex.terrain = Hex.Terrain.OFFMAP; - return hex; - } -} diff --git a/core/src/ch/asynk/tankontank/game/battles/MapA.java b/core/src/ch/asynk/tankontank/game/battles/MapA.java deleted file mode 100644 index 3f18e39..0000000 --- a/core/src/ch/asynk/tankontank/game/battles/MapA.java +++ /dev/null @@ -1,77 +0,0 @@ -package ch.asynk.tankontank.game.battles; - -import ch.asynk.tankontank.TankOnTank; -import ch.asynk.tankontank.engine.Board; -import ch.asynk.tankontank.engine.Orientation; -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Hex; - -public class MapA extends Map -{ - public MapA(final TankOnTank game, Board.Config cfg, String textureName) - { - super(game, cfg, textureName); - } - - @Override - protected void setup() - { - getHex(5, 1).terrain = Hex.Terrain.HILLS; - getHex(7, 3).terrain = Hex.Terrain.HILLS; - getHex(7, 8).terrain = Hex.Terrain.HILLS; - getHex(8, 8).terrain = Hex.Terrain.HILLS; - - getHex(5, 0).terrain = Hex.Terrain.WOODS; - getHex(6, 0).terrain = Hex.Terrain.WOODS; - getHex(3, 3).terrain = Hex.Terrain.WOODS; - getHex(4, 3).terrain = Hex.Terrain.WOODS; - getHex(10, 7).terrain = Hex.Terrain.WOODS; - getHex(11, 7).terrain = Hex.Terrain.WOODS; - getHex(11, 8).terrain = Hex.Terrain.WOODS; - - getHex(6, 1).terrain = Hex.Terrain.TOWN; - getHex(2, 2).terrain = Hex.Terrain.TOWN; - getHex(6, 4).terrain = Hex.Terrain.TOWN; - getHex(10, 5).terrain = Hex.Terrain.TOWN; - getHex(7, 7).terrain = Hex.Terrain.TOWN; - getHex(4, 6).terrain = Hex.Terrain.TOWN; - - getHex(10, 1).terrain = Hex.Terrain.OFFMAP; - getHex(11, 3).terrain = Hex.Terrain.OFFMAP; - getHex(12, 5).terrain = Hex.Terrain.OFFMAP; - getHex(13, 7).terrain = Hex.Terrain.OFFMAP; - - int N = Orientation.NORTH.s; - int S = Orientation.SOUTH.s; - int NE = Orientation.NORTH_EAST.s; - int NW = Orientation.NORTH_WEST.s; - int SE = Orientation.SOUTH_EAST.s; - int SW = Orientation.SOUTH_WEST.s; - - getHex(6, 1).roads = (NW | SW); - for (int i = 1; i < 11; i++) { - if (i == 6) - getHex(i, 2).roads = (NE | S | SW); - else if (i == 7) - getHex(i, 2).roads = (N | SE); - else - getHex(i, 2).roads = (N | S); - } - getHex(6, 3).roads = (NE | SW); - getHex(6, 4).roads = (N | NE | SW); - getHex(7, 4).roads = (N | S); - getHex(8, 4).roads = (NW | S); - getHex(6, 5).roads = (NE | SW); - getHex(8, 5).roads = (N | SW); - getHex(9, 5).roads = (N | S | NE); - getHex(10, 5).roads = (N | S); - getHex(11, 5).roads = (N | S); - getHex(3, 6).roads = (N | S); - getHex(4, 6).roads = (N | S); - getHex(5, 6).roads = (N | S); - getHex(6, 6).roads = (NE | NW | S); - getHex(8, 6).roads = (NE | SW); - getHex(7, 7).roads = (N | SE); - getHex(8, 7).roads = (NE | S); - } -} diff --git a/core/src/ch/asynk/tankontank/game/battles/MapB.java b/core/src/ch/asynk/tankontank/game/battles/MapB.java deleted file mode 100644 index c0f23a2..0000000 --- a/core/src/ch/asynk/tankontank/game/battles/MapB.java +++ /dev/null @@ -1,75 +0,0 @@ -package ch.asynk.tankontank.game.battles; - -import ch.asynk.tankontank.TankOnTank; -import ch.asynk.tankontank.engine.Board; -import ch.asynk.tankontank.engine.Orientation; -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Hex; - -public class MapB extends Map -{ - public MapB(final TankOnTank game, Board.Config cfg, String textureName) - { - super(game, cfg, textureName); - } - - @Override - protected void setup() - { - getHex(4, 0).terrain = Hex.Terrain.HILLS; - getHex(5, 0).terrain = Hex.Terrain.HILLS; - getHex(1, 1).terrain = Hex.Terrain.HILLS; - getHex(9, 7).terrain = Hex.Terrain.HILLS; - getHex(10, 7).terrain = Hex.Terrain.HILLS; - - getHex(3, 0).terrain = Hex.Terrain.WOODS; - getHex(6, 0).terrain = Hex.Terrain.WOODS; - getHex(8, 1).terrain = Hex.Terrain.WOODS; - getHex(9, 2).terrain = Hex.Terrain.WOODS; - getHex(4, 5).terrain = Hex.Terrain.WOODS; - getHex(5, 6).terrain = Hex.Terrain.WOODS; - getHex(6, 6).terrain = Hex.Terrain.WOODS; - getHex(11, 8).terrain = Hex.Terrain.WOODS; - - getHex(1, 2).terrain = Hex.Terrain.TOWN; - getHex(5, 3).terrain = Hex.Terrain.TOWN; - getHex(6, 4).terrain = Hex.Terrain.TOWN; - getHex(7, 8).terrain = Hex.Terrain.TOWN; - - getHex(10, 1).terrain = Hex.Terrain.OFFMAP; - getHex(11, 3).terrain = Hex.Terrain.OFFMAP; - getHex(12, 5).terrain = Hex.Terrain.OFFMAP; - getHex(13, 7).terrain = Hex.Terrain.OFFMAP; - - int N = Orientation.NORTH.s; - int S = Orientation.SOUTH.s; - int NE = Orientation.NORTH_EAST.s; - int NW = Orientation.NORTH_WEST.s; - int SE = Orientation.SOUTH_EAST.s; - int SW = Orientation.SOUTH_WEST.s; - - getHex(1, 2).roads = (S | NW); - getHex(2, 3).roads = (SE | N); - getHex(3, 3).roads = (S | N); - getHex(4, 3).roads = (S | N); - getHex(5, 3).roads = (S | NW); - getHex(6, 4).roads = (SE | N); - getHex(7, 4).roads = (S | N); - getHex(8, 4).roads = (S | SW | N); - getHex(9, 4).roads = (S | N); - getHex(10, 4).roads = (S | N); - getHex(11, 4).roads = (S | N); - getHex(4, 8).roads = (S | N); - getHex(5, 8).roads = (S | N); - getHex(6, 8).roads = (S | N); - getHex(7, 8).roads = (S | N); - getHex(8, 8).roads = (S | NE); - getHex(8, 7).roads = (SW | NE); - getHex(8, 6).roads = (SW | NE | N); - getHex(8, 5).roads = (SW | NE); - getHex(9, 6).roads = (S | N); - getHex(10, 6).roads = (S | N); - getHex(11, 6).roads = (S | N); - getHex(12, 6).roads = (S | N); - } -} diff --git a/core/src/ch/asynk/tankontank/game/hud/ActionButtons.java b/core/src/ch/asynk/tankontank/game/hud/ActionButtons.java deleted file mode 100644 index a2dcf12..0000000 --- a/core/src/ch/asynk/tankontank/game/hud/ActionButtons.java +++ /dev/null @@ -1,185 +0,0 @@ -package ch.asynk.tankontank.game.hud; - -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.State.StateType; -import ch.asynk.tankontank.ui.Widget; -import ch.asynk.tankontank.ui.Bg; -import ch.asynk.tankontank.ui.Position; - -public class ActionButtons extends Widget -{ - public static int PADDING = 5; - - private final Ctrl ctrl; - - public enum Buttons { - NONE(-1, 0), - PROMOTE(0, 1), - DONE(1, 2), - ABORT(2, 4), - LAST(3, 0); - - Buttons(int i, int b) - { - this.i = i; - this.b = b; - } - - public int i; - public int b; - } - - private Sprite bg; - private int idx; - private Bg buttons []; - private StateType states []; - - public ActionButtons(Ctrl ctrl, TextureAtlas uiAtlas, TextureAtlas hudAtlas) - { - this.bg = new Sprite(uiAtlas.findRegion("disabled")); - this.ctrl = ctrl; - this.visible = false; - this.position = Position.BOTTOM_RIGHT; - this.idx = Buttons.NONE.i; - - - this.buttons = new Bg[Buttons.LAST.i]; - this.buttons[Buttons.DONE.i] = new Bg(uiAtlas.findRegion("ok")); - this.buttons[Buttons.ABORT.i] = new Bg(uiAtlas.findRegion("cancel")); - this.buttons[Buttons.PROMOTE.i] = new Bg(hudAtlas.findRegion("promote")); - - this.states = new StateType[Buttons.LAST.i]; - this.states[Buttons.DONE.i] = StateType.DONE; - this.states[Buttons.ABORT.i] = StateType.ABORT; - this.states[Buttons.PROMOTE.i] = StateType.PROMOTE; - } - - @Override - public void dispose() - { - for (int i = 0; i < Buttons.LAST.i; i++) - buttons[i].dispose(); - } - - public void update(Position position) - { - setPosition(position); - updatePosition(); - } - - public void updatePosition() - { - if (!visible) return; - float dx = (position.getX(rect.width) - rect.x); - float dy = (position.getY(rect.height) - rect.y); - translate(dx, dy); - for (int i = 0; i < Buttons.LAST.i; i++) - buttons[i].translate(dx, dy); - } - - public void hide() - { - for (int i = 0; i < Buttons.LAST.i; i++) - buttons[i].visible = false; - this.visible = false; - } - - private float setButton(Bg btn, float x, float y) - { - btn.visible = true; - btn.setPosition(x, y); - return (y + btn.getHeight() + PADDING); - } - - public void show(int bits) - { - int b = bits; - int count = 0; - while (b > 0) { - if ((b & 0x01) == 1) - count += 1; - b /= 2; - } - - if (count == 0) { - this.visible = false; - return; - } - - rect.width = (buttons[0].getWidth() + (2 * PADDING)); - rect.height = ((buttons[0].getHeight() * count) + ((count + 1) * PADDING)); - rect.x = position.getX(rect.width); - rect.y = position.getY(rect.height); - - float x = (rect.x + PADDING); - float y = (rect.y + PADDING); - - b = 1; - for (int i = 0; i < Buttons.LAST.i; i++) { - if ((bits & b) == b) - y = setButton(buttons[i], x, y); - else - buttons[i].visible = false; - b *= 2; - } - - this.visible = true; - } - - public boolean touchDown(float x, float y) - { - idx = Buttons.NONE.i; - - if (!super.hit(x,y)) - return false; - - for (int i = 0; i < Buttons.LAST.i; i++) { - if (buttons[i].hit(x, y)) { - idx = i; - break; - } - } - - return (idx != Buttons.NONE.i); - } - - public boolean touchUp(float x, float y) - { - if (idx == Buttons.NONE.i) - return false; - - boolean ret = false; - - if (super.hit(x,y) && buttons[idx].hit(x, y)) { - ctrl.setState(states[idx]); - ret = true; - } - - idx = Buttons.NONE.i; - - return ret; - } - - @Override - public void draw(Batch batch) - { - if (!visible) return; - batch.draw(bg, rect.x, rect.y, rect.width, rect.height); - for (int i = 0; i < Buttons.LAST.i; i++) - buttons[i].draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer shapes) - { - if (!visible) return; - super.drawDebug(shapes); - for (int i = 0; i < Buttons.LAST.i; i++) - buttons[i].drawDebug(shapes); - } -} diff --git a/core/src/ch/asynk/tankontank/game/hud/EngagementPanel.java b/core/src/ch/asynk/tankontank/game/hud/EngagementPanel.java deleted file mode 100644 index 9e9df1c..0000000 --- a/core/src/ch/asynk/tankontank/game/hud/EngagementPanel.java +++ /dev/null @@ -1,255 +0,0 @@ -package ch.asynk.tankontank.game.hud; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.game.Engagement; -import ch.asynk.tankontank.game.Army; -import ch.asynk.tankontank.engine.gfx.Animation; -import ch.asynk.tankontank.engine.gfx.animations.DiceAnimation; -import ch.asynk.tankontank.ui.Bg; -import ch.asynk.tankontank.ui.Label; -import ch.asynk.tankontank.ui.Patch; -import ch.asynk.tankontank.ui.Position; - -public class EngagementPanel extends Patch implements Animation -{ - private enum State { ROLL1, MOVE, ROLL2, RESULT }; - - public static int FLAG_HEIGHT = 24; - public static int OK_OFFSET = 10; - public static int PADDING = 20; - public static int VSPACING = 10; - public static int HSPACING = 5; - public static float MOVE_STEP = 2f; - - private State state; - private boolean reroll; - private float rerollY; - private Sprite usFlag; - private Sprite geFlag; - private Sprite winner; - private Sprite attackImg; - private Sprite defenseImg; - private Label attack; - private Label defense; - private Label attackR; - private Label defenseR; - private Bg okBtn; - private DiceAnimation d1Animation; - private DiceAnimation d2Animation; - private DiceAnimation d3Animation; - private DiceAnimation d4Animation; - - public EngagementPanel(BitmapFont font, TextureAtlas uiAtlas, TextureAtlas hudAtlas) - { - super(uiAtlas.createPatch("typewriter")); - usFlag = new Sprite(hudAtlas.findRegion("us-flag")); - geFlag = new Sprite(hudAtlas.findRegion("ge-flag")); - attackImg = new Sprite(hudAtlas.findRegion("attack")); - defenseImg = new Sprite(hudAtlas.findRegion("defense")); - this.attack = new Label(font); - this.defense = new Label(font); - this.attackR = new Label(font); - this.defenseR = new Label(font); - this.okBtn = new Bg(uiAtlas.findRegion("ok")); - this.visible = false; - this.d1Animation = new DiceAnimation(); - this.d2Animation = new DiceAnimation(); - this.d3Animation = new DiceAnimation(); - this.d4Animation = new DiceAnimation(); - } - - public void updatePosition() - { - if (!visible) return; - float dx = (position.getX(rect.width) - rect.x); - float dy = (position.getY(rect.height) - rect.y); - translate(dx, dy); - winner.translate(dx, dy); - attackImg.translate(dx, dy); - defenseImg.translate(dx, dy); - attack.translate(dx, dy); - defense.translate(dx, dy); - attackR.translate(dx, dy); - defenseR.translate(dx, dy); - okBtn.translate(dx, dy); - d1Animation.translate(dx, dy); - d2Animation.translate(dx, dy); - d3Animation.translate(dx, dy); - d4Animation.translate(dx, dy); - } - - public void show(Engagement e, Position position, float volume) - { - DiceAnimation.initSound(volume); - attack.write(String.format(" + %d + %d =", e.unitCount, e.flankBonus)); - if (e.weatherDefense == 0) - defense.write(String.format("%d + %d =", e.unitDefense, e.terrainDefense)); - else - defense.write(String.format("%d + %d + %d =", e.unitDefense, e.terrainDefense, e.weatherDefense)); - attackR.write(String.format(" %2d", e.attackSum)); - defenseR.write(String.format(" %2d", e.defenseSum)); - if (e.success) - winner = ((e.attacker.getArmy() == Army.US) ? usFlag : geFlag); - else - winner = ((e.attacker.getArmy() == Army.US) ? geFlag : usFlag); - - this.position = position; - placeElements(); - - state = State.ROLL1; - reroll = (e.d3 != 0); - - d1Animation.set(e.d1); - d2Animation.set(e.d2); - if (reroll) { - d3Animation.set(e.d3); - d4Animation.set(e.d4); - } - - visible = true; - } - - private void placeElements() - { - float w = attackR.getWidth(); - float w2 = defenseR.getWidth(); - if (w2 > w) - w = w2; - float height = (okBtn.getHeight() + attackImg.getHeight() + defenseImg.getHeight() + (2 * VSPACING) + (2 * PADDING)); - float width = (attackImg.getWidth() + (2 * d1Animation.getWidth()) + attack.getWidth() + w + (4 * HSPACING) + (2 * PADDING)); - float x = position.getX(width); - float y = position.getY(height); - setPosition(x, y, width, height); - - okBtn.setPosition((x + width - okBtn.getWidth() + OK_OFFSET), (y - OK_OFFSET)); - - x = getX() + PADDING; - y = getY() + PADDING; - winner.setPosition((getX() + (width / 2f) - (winner.getWidth() / 2f)), y); - y += (winner.getHeight() + VSPACING); - - defenseImg.setPosition(x, y); - y = (y + (defenseImg.getHeight() / 2f) - (defense.getHeight() / 2f)); - defenseR.setPosition((getX() + width - w - PADDING), y); - // x += (defenseImg.getWidth() + HSPACING); - defense.setPosition((defenseR.getX() - defense.getWidth() - HSPACING), y); - - x = getX() + PADDING; - y += defenseImg.getHeight() + VSPACING; - attackImg.setPosition(x, y); - x += (attackImg.getWidth() + HSPACING); - d1Animation.setPosition(x, y); - d3Animation.setPosition(x, y); - x += (d1Animation.getWidth() + HSPACING); - d2Animation.setPosition(x, (y)); - d4Animation.setPosition(x, y); - x += (d1Animation.getWidth() + HSPACING); - y = (y + (attackImg.getHeight() / 2f) - (attack.getHeight() / 2f)); - attack.setPosition(x, y); - attackR.setPosition(defenseR.getX(), y); - - rerollY = (d1Animation.getY() + d1Animation.getHeight() + VSPACING); - } - - @Override - public boolean hit(float x, float y) - { - return rect.contains(x, y); - } - - @Override - public boolean animate(float delta) - { - if (!visible) return true; - if (state == State.ROLL1) { - d1Animation.animate(delta); - d2Animation.animate(delta); - if (d1Animation.isDone() && d2Animation.isDone()) { - if (reroll) - state = State.MOVE; - else - state = State.RESULT; - } - } - - if (state == State.MOVE) { - float y = (d1Animation.getY() + MOVE_STEP); - if (y >= rerollY) { - y = rerollY; - state = State.ROLL2; - } - setPosition(getX(), getY(), getWidth(), (y + d1Animation.getHeight() + VSPACING - getY())); - d1Animation.setPosition(d1Animation.getX(), y); - d2Animation.setPosition(d2Animation.getX(), y); - } - - if (state == State.ROLL2) { - if (d1Animation.getY() < rerollY) { - d1Animation.setPosition(d1Animation.getX(), (d1Animation.getY() + d1Animation.getHeight() + VSPACING)); - d2Animation.setPosition(d2Animation.getX(), (d2Animation.getY() + d2Animation.getHeight() + VSPACING)); - } else { - d3Animation.animate(delta); - d4Animation.animate(delta); - if (d3Animation.isDone() && d4Animation.isDone()) - state = State.RESULT; - } - } - - return false; - } - - @Override - public void dispose() - { - super.dispose(); - attack.dispose(); - defense.dispose(); - attackR.dispose(); - defenseR.dispose(); - d1Animation.dispose(); - d2Animation.dispose(); - d3Animation.dispose(); - d4Animation.dispose(); - okBtn.dispose(); - } - - @Override - public void draw(Batch batch) - { - if (!visible) return; - super.draw(batch); - attackImg.draw(batch); - d1Animation.draw(batch); - d2Animation.draw(batch); - if ((state == State.ROLL2) || (reroll && (state == State.RESULT))) { - d3Animation.draw(batch); - d4Animation.draw(batch); - } - attack.draw(batch); - defenseImg.draw(batch); - defense.draw(batch); - defenseR.draw(batch); - okBtn.draw(batch); - if (state == State.RESULT) { - attackR.draw(batch); - winner.draw(batch); - } - } - - @Override - public void drawDebug(ShapeRenderer shapes) - { - if (!visible) return; - super.drawDebug(shapes); - attack.drawDebug(shapes); - defense.drawDebug(shapes); - attackR.drawDebug(shapes); - defenseR.drawDebug(shapes); - okBtn.drawDebug(shapes); - } -} diff --git a/core/src/ch/asynk/tankontank/game/hud/PlayerInfo.java b/core/src/ch/asynk/tankontank/game/hud/PlayerInfo.java deleted file mode 100644 index 45ee5dc..0000000 --- a/core/src/ch/asynk/tankontank/game/hud/PlayerInfo.java +++ /dev/null @@ -1,202 +0,0 @@ -package ch.asynk.tankontank.game.hud; - -import com.badlogic.gdx.utils.Disposable; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Animation; -import ch.asynk.tankontank.engine.gfx.Drawable; - -import ch.asynk.tankontank.game.State.StateType; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.Hud; -import ch.asynk.tankontank.game.Army; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.ui.LabelImage; -import ch.asynk.tankontank.ui.Position; - -public class PlayerInfo implements Disposable, Drawable, Animation -{ - public static int PADDING = 5; - - private final Ctrl ctrl; - - private Object hit; - - private Sprite flag; - private Sprite usFlag; - private Sprite geFlag; - private LabelImage turns; - private LabelImage aps; - private LabelImage reinforcement; - public UnitDock unitDock; - private Position position; - - public PlayerInfo(Ctrl ctrl, BitmapFont font, TextureAtlas uiAtlas, TextureAtlas hudAtlas) - { - this.ctrl = ctrl; - this.position = Position.MIDDLE_CENTER; - usFlag = new Sprite(hudAtlas.findRegion("us-flag")); - geFlag = new Sprite(hudAtlas.findRegion("ge-flag")); - turns = new LabelImage(hudAtlas.findRegion("turns"), font, 5f); - aps = new LabelImage(hudAtlas.findRegion("aps"), font, 5f); - reinforcement = new LabelImage(hudAtlas.findRegion("reinforcement"), font, 5f); - unitDock = new UnitDock(ctrl, uiAtlas.findRegion("disabled"), hudAtlas.findRegion("reinforcement-selected"), 10f); - } - - @Override - public void dispose() - { - turns.dispose(); - aps.dispose(); - reinforcement.dispose(); - unitDock.dispose(); - } - - public void updatePosition() - { - float dx = (position.getX(usFlag.getWidth()) - usFlag.getX()); - float dy = (position.getY(usFlag.getHeight()) - usFlag.getY()); - usFlag.translate(dx, dy); - geFlag.translate(dx, dy); - turns.translate(dx, dy); - aps.translate(dx, dy); - reinforcement.translate(dx, dy); - unitDock.translate(dx, dy); - } - - public void setPosition(Position position) - { - if (this.position == position) - return; - this.position = position; - - float width = (usFlag.getWidth() + turns.getWidth() + aps.getWidth() + (2 * PADDING)); - float height = (usFlag.getHeight() + reinforcement.getHeight() + (1 * PADDING)); - float x = position.getX(width); - float y = position.getY(height); - - if (position.isLeft()) { - reinforcement.setPosition(x, y); - y += (reinforcement.getHeight() + PADDING); - usFlag.setPosition(x, y); - geFlag.setPosition(x, y); - x += (usFlag.getWidth() + PADDING); - turns.setPosition(x, y); - x += (turns.getWidth() + PADDING); - aps.setPosition(x, y); - } else { - x = (x + width); - reinforcement.setPosition((x - reinforcement.getWidth()), y); - y += (reinforcement.getHeight() + PADDING); - x -= usFlag.getWidth(); - usFlag.setPosition(x, y); - geFlag.setPosition(x, y); - x -= (turns.getWidth() + PADDING); - turns.setPosition(x, y); - x -= (aps.getWidth() + PADDING); - aps.setPosition(x, y); - } - aps.setLabelPosition(Position.TOP_RIGHT); - turns.setLabelPosition(Position.MIDDLE_CENTER); - reinforcement.setLabelPosition(Position.TOP_LEFT); - unitDock.setPosition(position, reinforcement.getY() - PADDING); - } - - public void update(Player player, Position position) - { - unitDock.hide(); - turns.write(String.format("%d", player.getCurrentTurn())); - aps.write(String.format("%d", player.getAp())); - int r = player.reinforcement(); - if (r == 0) { - reinforcement.visible = false; - } else { - reinforcement.visible = true; - reinforcement.write(String.format("%d", r)); - } - - if (player.is(Army.GE)) - flag = geFlag; - else - flag = usFlag; - - setPosition(position); - } - - public void blockEndOfTurn(boolean blocked) - { - turns.blocked = blocked; - } - - public boolean touchDown(float x, float y) - { - hit = null; - - if (reinforcement.hit(x, y)) - hit = reinforcement; - else if (unitDock.hit(x, y)) - hit = unitDock; - else if (turns.hit(x,y)) - hit = turns; - - return (hit != null); - } - - public boolean touchUp(float x, float y) - { - if (hit == null) - return false; - - if (hit == turns) { - if (turns.hit(x, y)) - ctrl.hud.askEndOfTurn(); - } - else if (hit == reinforcement) { - if (reinforcement.hit(x, y)) - ctrl.reinforcementHit(); - } - else if (hit == unitDock) { - if (unitDock.hit(x, y)) { - ctrl.hud.notify(unitDock.select(x, y).toString()); - ctrl.stateTouchUp(); - } - } - - hit = null; - - return true; - } - - @Override - public boolean animate(float delta) - { - unitDock.animate(delta); - return false; - } - - @Override - public void draw(Batch batch) - { - flag.draw(batch); - turns.draw(batch); - aps.draw(batch); - reinforcement.draw(batch); - unitDock.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer debugShapes) - { - turns.drawDebug(debugShapes); - aps.drawDebug(debugShapes); - reinforcement.drawDebug(debugShapes); - unitDock.drawDebug(debugShapes); - debugShapes.rect(flag.getX(), flag.getY(), flag.getWidth(), flag.getHeight()); - } -} diff --git a/core/src/ch/asynk/tankontank/game/hud/StatisticsPanel.java b/core/src/ch/asynk/tankontank/game/hud/StatisticsPanel.java deleted file mode 100644 index 9ad75a6..0000000 --- a/core/src/ch/asynk/tankontank/game/hud/StatisticsPanel.java +++ /dev/null @@ -1,120 +0,0 @@ -package ch.asynk.tankontank.game.hud; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.game.Player; -import ch.asynk.tankontank.ui.Bg; -import ch.asynk.tankontank.ui.Label; -import ch.asynk.tankontank.ui.Patch; -import ch.asynk.tankontank.ui.Position; - -public class StatisticsPanel extends Patch -{ - public static int OK_OFFSET = 10; - public static int PADDING = 20; - public static int VSPACING = 10; - public static int HSPACING = 10; - - private Label title; - private Label header; - private Label stats1; - private Label stats2; - private Bg okBtn; - - public StatisticsPanel(BitmapFont font, TextureAtlas atlas) - { - super(atlas.createPatch("typewriter")); - this.title = new Label(font); - this.header = new Label(font); - this.stats1 = new Label(font); - this.stats2 = new Label(font); - this.okBtn = new Bg(atlas.findRegion("ok")); - this.visible = false; - this.header.write("\nActions\nUnits Left\nUnits Withrawed\nCasualties\nWon Attacks\nLost Attacks"); - } - - public void updatePosition() - { - if (!visible) return; - float dx = (position.getX(rect.width) - rect.x); - float dy = (position.getY(rect.height) - rect.y); - translate(dx, dy); - title.translate(dx, dy); - header.translate(dx, dy); - stats1.translate(dx, dy); - stats2.translate(dx, dy); - okBtn.translate(dx, dy); - } - - public void show(Player winner, Player loser, Position position) - { - title.write(winner.getName() + " player won the battle in " + winner.getTurnDone() + " turns."); - stats1.write(winner.getStats()); - stats2.write(loser.getStats()); - - float height = (title.getHeight() + header.getHeight() + (2 * PADDING) + (1 * VSPACING)); - float width = (header.getWidth() + stats1.getWidth() + stats2.getWidth() + (2 * PADDING) + (4 * HSPACING)); - float w2 = (title.getWidth() + (2 * PADDING)); - if (w2 > width) width = w2; - float x = position.getX(width); - float y = position.getY(height); - setPosition(x, y, width, height); - - okBtn.setPosition((x + width - okBtn.getWidth() + OK_OFFSET), (y - OK_OFFSET)); - - y += PADDING; - x += PADDING; - header.setPosition(x, y); - stats1.setPosition((x + header.getWidth() + (2 * HSPACING)), y); - stats2.setPosition((stats1.getX() + stats1.getWidth() + (2 * HSPACING)), y); - y += (header.getHeight() + VSPACING); - title.setPosition(x, y); - visible = true; - } - - @Override - public boolean hit(float x, float y) - { - if (okBtn.hit(x, y)) - return true; - return false; - } - - @Override - public void dispose() - { - super.dispose(); - title.dispose(); - header.dispose(); - stats1.dispose(); - stats2.dispose(); - okBtn.dispose(); - } - - @Override - public void draw(Batch batch) - { - if (!visible) return; - super.draw(batch); - title.draw(batch); - header.draw(batch); - stats1.draw(batch); - stats2.draw(batch); - okBtn.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer shapes) - { - if (!visible) return; - super.drawDebug(shapes); - title.drawDebug(shapes); - header.drawDebug(shapes); - stats1.drawDebug(shapes); - stats2.drawDebug(shapes); - okBtn.drawDebug(shapes); - } -} diff --git a/core/src/ch/asynk/tankontank/game/hud/UnitDock.java b/core/src/ch/asynk/tankontank/game/hud/UnitDock.java deleted file mode 100644 index 05824e0..0000000 --- a/core/src/ch/asynk/tankontank/game/hud/UnitDock.java +++ /dev/null @@ -1,226 +0,0 @@ -package ch.asynk.tankontank.game.hud; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; -import com.badlogic.gdx.math.Vector3; -import com.badlogic.gdx.math.Matrix4; -import com.badlogic.gdx.math.Rectangle; - -import ch.asynk.tankontank.engine.gfx.Animation; -import ch.asynk.tankontank.engine.Orientation; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.UnitList; -import ch.asynk.tankontank.ui.Bg; -import ch.asynk.tankontank.ui.Position; - -public class UnitDock extends Bg implements Animation -{ - private static final float SCALE = 0.4f; - private static final float STEP = 5f; - private final Ctrl ctrl; - - private int n; - private float y; - private float to; - private float dx; - private float step; - private boolean show; - private boolean mvtDone; - public Unit selectedUnit; - private Sprite selected; - private UnitList units; - private Vector3 point; - private Matrix4 saved; - private Matrix4 transform; - private Rectangle scaledRect; - - public UnitDock(Ctrl ctrl, TextureRegion region, TextureRegion selected, float padding) - { - super(region); - this.ctrl = ctrl; - this.padding = padding; - this.mvtDone = true; - this.point = new Vector3(); - this.saved = new Matrix4(); - this.transform = new Matrix4(); - this.scaledRect = new Rectangle(); - this.selected = new Sprite(selected); - this.visible = false; - this.dx = 0f; - } - - @Override - public void translate(float _dx, float _dy) - { - this.y += _dy; - if (!visible) return; - super.translate(_dx, _dy); - for (Unit unit : units) - unit.translate(_dx, _dy); - to = position.getX(rect.width * SCALE); - transform.idt(); - transform.translate((rect.x + dx), (rect.y + rect.height), 0).scale(SCALE, SCALE, 0).translate(-rect.x, - (rect.y + rect.height), 0); - point.set(rect.x, rect.y, 0).mul(transform); - scaledRect.x = point.x; - scaledRect.y = point.y; - point.set((rect.x + rect.width), (rect.y + rect.height), 0).mul(transform); - scaledRect.width = point.x - scaledRect.x; - scaledRect.height = point.y - scaledRect.y; - } - - public void setPosition(Position position, float y) - { - if (this.position == position) - return; - this.position = position; - this.y = y; - this.step = (position.isLeft() ? STEP : -STEP); - this.mvtDone = true; - this.visible = false; - this.dx = 0f; - } - - @Override - public void dispose() - { - super.dispose(); - } - - @Override - public boolean hit(float x, float y) - { - return (visible && scaledRect.contains(x, y)); - } - - public Unit select(float x, float y) - { - int i = (int) ((scaledRect.y + scaledRect.height - y) / (scaledRect.height / units.size())); - selectedUnit = units.get(i); - return selectedUnit; - } - - public void hide() - { - if (!visible) return; - resize(); - to = rect.x; - - show = false; - mvtDone = false; - selectedUnit = null; - } - - public void show() - { - if (!resize()) - return; - to = position.getX(rect.width * SCALE); - - show = true; - mvtDone = false; - selectedUnit = null; - visible = true; - } - - private boolean resize() - { - int count = ctrl.player.reinforcement(); - if (count == 0) { - n = 0; - return false; - } - if (count == n) return true; - n = count; - - units = ctrl.player.reinforcement; - rect.width = units.get(0).getWidth() + (2 * padding); - rect.height = ((units.get(0).getHeight() * n) + ((n + 1) * padding)); - float scaledWidth = (rect.width * SCALE); - to = position.getX(scaledWidth); - rect.x = to + (position.isLeft() ? -scaledWidth : scaledWidth); - rect.y = y - rect.height; - - float px = rect.x; - float py = rect.y + rect.height; - float ph = units.get(0).getHeight(); - for (Unit unit : units) { - py -= (ph + padding); - // unit.setPosition(px, py, Orientation.SOUTH.r()); - unit.centerOn((px + (rect.width / 2)), py + (ph / 2)); - unit.setRotation(position.isLeft() ? Orientation.NORTH.r() : Orientation.SOUTH.r()); - } - - return true; - } - - @Override - public boolean animate(float delta) - { - if (!visible) return true; - if (mvtDone) return true; - - float x = (rect.x + dx); - if (show) { - if ((position.isLeft() && (x < to)) || (!position.isLeft() && x > to)) - dx += step; - else { - dx = (to - rect.x); - mvtDone = true; - } - } else { - if ((position.isLeft() && (x > to)) || (!position.isLeft() && x < to)) - dx -= step; - else { - dx = (to - rect.x); - mvtDone = true; - visible = false; - } - } - - transform.idt(); - transform.translate((rect.x + dx), (rect.y + rect.height), 0).scale(SCALE, SCALE, 0).translate(-rect.x, - (rect.y + rect.height), 0); - point.set(rect.x, rect.y, 0).mul(transform); - scaledRect.x = point.x; - scaledRect.y = point.y; - point.set((rect.x + rect.width), (rect.y + rect.height), 0).mul(transform); - scaledRect.width = point.x - scaledRect.x; - scaledRect.height = point.y - scaledRect.y; - return false; - } - - @Override - public void draw(Batch batch) - { - if (!visible) return; - - saved.set(batch.getTransformMatrix()); - batch.setTransformMatrix(transform); - - super.draw(batch); - for (Unit unit : units) { - unit.draw(batch); - if (unit == selectedUnit) { - selected.setCenter((unit.getX() + (unit.getWidth() / 2)), (unit.getY() + (unit.getHeight() / 2))); - selected.draw(batch); - } - } - - batch.setTransformMatrix(saved); - } - - @Override - public void drawDebug(ShapeRenderer shapes) - { - if (!visible) return; - - saved.set(shapes.getTransformMatrix()); - shapes.setTransformMatrix(transform); - - shapes.rect(rect.x, rect.y, rect.width, rect.height); - - shapes.setTransformMatrix(saved); - } -} diff --git a/core/src/ch/asynk/tankontank/game/states/StateAnimation.java b/core/src/ch/asynk/tankontank/game/states/StateAnimation.java deleted file mode 100644 index 2e115a9..0000000 --- a/core/src/ch/asynk/tankontank/game/states/StateAnimation.java +++ /dev/null @@ -1,37 +0,0 @@ -package ch.asynk.tankontank.game.states; - -public class StateAnimation extends StateCommon -{ - @Override - public void enter(StateType prevState) - { - ctrl.hud.actionButtons.hide(); - } - - @Override - public void leave(StateType nextState) - { - } - - @Override - public StateType abort() - { - return StateType.ABORT; - } - - @Override - public StateType execute() - { - return StateType.DONE; - } - - @Override - public void touchDown() - { - } - - @Override - public void touchUp() - { - } -} diff --git a/core/src/ch/asynk/tankontank/game/states/StateBreak.java b/core/src/ch/asynk/tankontank/game/states/StateBreak.java deleted file mode 100644 index 9b87c23..0000000 --- a/core/src/ch/asynk/tankontank/game/states/StateBreak.java +++ /dev/null @@ -1,90 +0,0 @@ -package ch.asynk.tankontank.game.states; - -import ch.asynk.tankontank.engine.Orientation; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.hud.ActionButtons.Buttons; - -import ch.asynk.tankontank.TankOnTank; - -public class StateBreak extends StateCommon -{ - private Orientation o = Orientation.KEEP; - - @Override - public void enter(StateType prevState) - { - activeUnit = null; - ctrl.hud.actionButtons.show(Buttons.DONE.b); - ctrl.hud.pushNotify("Break move possible"); - map.showBreakUnits(); - } - - @Override - public void leave(StateType nextState) - { - map.hideBreakUnits(); - map.hideMove(to); - map.hideDirections(to); - map.hideOrientation(to); - if (activeUnit != null) map.hideMove(activeUnit.getHex()); - } - - @Override - public StateType abort() - { - return StateType.ABORT; - } - - @Override - public StateType execute() - { - return StateType.DONE; - } - - @Override - public void touchDown() - { - } - - @Override - public void touchUp() - { - // TODO : cancel preview move before showing rotation - if (activeUnit == null) { - Unit unit = upHex.getUnit(); - if (map.breakUnits.contains(unit)) { - activeUnit = unit; - map.showMove(upHex); - map.showMove(to); - map.showDirections(to); - map.hideBreakUnits(); - } - } else { - o = Orientation.fromAdj(to, upHex); - - if (o == Orientation.KEEP) return; - - if (ctrl.cfg.mustValidate) { - map.hideDirections(to); - map.showOrientation(to, o); - ctrl.hud.actionButtons.show(Buttons.DONE.b); - } else { - doRotation(o); - ctrl.setState(StateType.ANIMATION); - } - } - } - - private void doRotation(Orientation o) - { - if (activeUnit == null) return; - - map.pathBuilder.init(activeUnit); - if (map.pathBuilder.build(to) == 1) { - map.pathBuilder.orientation = o; - map.moveUnit(activeUnit); - ctrl.setAfterAnimationState(StateType.DONE); - } else - TankOnTank.debug("That's very wrong there should be only one path"); - } -} diff --git a/core/src/ch/asynk/tankontank/game/states/StateCommon.java b/core/src/ch/asynk/tankontank/game/states/StateCommon.java deleted file mode 100644 index a5cc875..0000000 --- a/core/src/ch/asynk/tankontank/game/states/StateCommon.java +++ /dev/null @@ -1,68 +0,0 @@ -package ch.asynk.tankontank.game.states; - -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.State; - -import ch.asynk.tankontank.TankOnTank; - -public abstract class StateCommon implements State -{ - protected static Ctrl ctrl; - protected static Map map; - - protected static Hex selectedHex = null; - protected static Hex downHex = null; - protected static Hex upHex = null; - protected static Hex to = null; - - protected boolean isEnemy; - protected static Unit activeUnit; - protected static Unit selectedUnit; - - protected StateCommon() - { - } - - public StateCommon(Ctrl ctrl, Map map) - { - this.ctrl = ctrl; - this.map = map; - } - - @Override - public boolean downInMap(float x, float y) - { - downHex = map.getHexAt(x, y); - return (downHex != null); - } - - @Override - public boolean upInMap(float x, float y) - { - upHex = map.getHexAt(x, y); - return (upHex != null); - } - - protected boolean hasUnit() - { - return (selectedUnit != null); - } - - protected void showPossibilities(Unit unit) - { - if (ctrl.cfg.showMoves && unit.canMove()) map.showPossibleMoves(); - if (ctrl.cfg.showTargets && unit.canEngage()) map.showPossibleTargets(); - if (ctrl.cfg.showMoveAssists && unit.canMove()) map.showMoveableUnits(); - unit.enableOverlay(Unit.MOVE, false); - } - - protected void hidePossibilities() - { - map.hidePossibleMoves(); - map.hidePossibleTargets(); - map.hideMoveableUnits(); - } -} diff --git a/core/src/ch/asynk/tankontank/game/states/StateDeployment.java b/core/src/ch/asynk/tankontank/game/states/StateDeployment.java deleted file mode 100644 index 91b5bd5..0000000 --- a/core/src/ch/asynk/tankontank/game/states/StateDeployment.java +++ /dev/null @@ -1,138 +0,0 @@ -package ch.asynk.tankontank.game.states; - -import ch.asynk.tankontank.engine.Orientation; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.UnitList; -import ch.asynk.tankontank.game.hud.ActionButtons.Buttons; - -import ch.asynk.tankontank.TankOnTank; - -public class StateDeployment extends StateCommon -{ - private boolean completed; - private Zone entryZone; - private UnitList deployedUnits = new UnitList(10); - - @Override - public void enter(StateType prevState) - { - if (selectedHex != null) - map.unselectHex(selectedHex); - completed = false; - entryZone = null; - selectedHex = null; - selectedUnit = null; - ctrl.hud.actionButtons.hide(); - ctrl.hud.playerInfo.unitDock.show(); - } - - @Override - public void leave(StateType nextState) - { - selectedUnit = null; - if (selectedHex != null) - map.unselectHex(selectedHex); - if (entryZone != null) - entryZone.enable(Hex.AREA, false); - ctrl.hud.playerInfo.unitDock.hide(); - } - - @Override - public StateType abort() - { - if (activeUnit != null) - undo(); - return StateType.DEPLOYMENT; - } - - @Override - public StateType execute() - { - deployedUnits.clear(); - return StateType.DONE; - } - - @Override - public void touchDown() - { - } - - @Override - public void touchUp() - { - Unit unit = ctrl.hud.playerInfo.unitDock.selectedUnit; - if (!completed && (unit != null) && (unit != activeUnit)) { - showEntryZone(unit); - } else if (selectedUnit != null) { - doRotation(Orientation.fromAdj(selectedHex, upHex)); - } else if (!completed && (entryZone != null) && (upHex != null)) { - if (upHex.isEmpty() && entryZone.contains(upHex)) - unitEnter(activeUnit); - } else { - unit = downHex.getUnit(); - if (deployedUnits.contains(unit)) { - showRotation(unit, downHex); - activeUnit = unit; - } - } - } - - private void showEntryZone(Unit unit) - { - activeUnit = unit; - if (entryZone != null) entryZone.enable(Hex.AREA, false); - entryZone = ctrl.battle.getEntryZone(activeUnit); - entryZone.enable(Hex.AREA, true); - } - - private void undo() - { - map.unselectHex(selectedHex); - map.hideDirections(selectedHex); - map.revertEnter(activeUnit); - activeUnit = null; - selectedUnit = null; - ctrl.hud.update(); - } - - private void unitEnter(Unit unit) - { - selectedUnit = unit; - selectedHex = upHex; - ctrl.player.reinforcement.remove(unit); - map.showOnBoard(unit, upHex, entryZone.orientation); - deployedUnits.add(unit); - entryZone.enable(Hex.AREA, false); - showRotation(unit, upHex); - ctrl.hud.update(); - } - - private void showRotation(Unit unit, Hex hex) - { - selectedUnit = unit; - selectedHex = hex; - map.selectHex(selectedHex); - map.showDirections(selectedHex); - ctrl.hud.playerInfo.unitDock.hide(); - ctrl.hud.actionButtons.show(Buttons.ABORT.b); - } - - private void doRotation(Orientation o) - { - map.unselectHex(selectedHex); - map.hideDirections(selectedHex); - - if (o != Orientation.KEEP) - map.setOnBoard(selectedUnit, selectedHex, o); - - ctrl.hud.actionButtons.hide(); - ctrl.hud.playerInfo.unitDock.show(); - entryZone = null; - activeUnit = null; - selectedUnit = null; - if (ctrl.checkDeploymentDone()) - completed = true; - } -} diff --git a/core/src/ch/asynk/tankontank/game/states/StateEngage.java b/core/src/ch/asynk/tankontank/game/states/StateEngage.java deleted file mode 100644 index 865907e..0000000 --- a/core/src/ch/asynk/tankontank/game/states/StateEngage.java +++ /dev/null @@ -1,105 +0,0 @@ -package ch.asynk.tankontank.game.states; - -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.hud.ActionButtons.Buttons; - -import ch.asynk.tankontank.TankOnTank; - -public class StateEngage extends StateCommon -{ - @Override - public void enter(StateType prevState) - { - map.possibleTargets.clear(); - ctrl.hud.actionButtons.show(ctrl.cfg.canCancel ? Buttons.ABORT.b : 0); - - // activeUnit is the target - if (prevState == StateType.SELECT) { - activeUnit = null; - // use selectedHex and selectedUnit - map.hidePossibleTargets(); - map.collectPossibleTargets(selectedUnit, ctrl.opponent.units); - map.showPossibleTargets(); - if (to != null) { - // quick fire -> replay touchUp - upHex = to; - touchUp(); - } - selectedUnit.showAttack(); - map.selectHex(selectedHex); - } else - TankOnTank.debug("should not happen"); - } - - @Override - public void leave(StateType nextState) - { - selectedUnit.hideAttack(); - map.hideAttackAssists(); - map.hidePossibleTargets(); - map.unselectHex(selectedHex); - if (to != null) - map.unselectHex(to); - } - - @Override - public StateType abort() - { - map.activatedUnits.clear(); - return StateType.ABORT; - } - - @Override - public StateType execute() - { - StateType nextState = StateType.DONE; - if (map.engageUnit(selectedUnit, activeUnit)) { - ctrl.player.wonEngagementCount += 1; - ctrl.opponent.casualty(activeUnit); - if (map.breakUnits.size() > 0) { - nextState = StateType.BREAK; - } - } else { - ctrl.player.lostEngagementCount += 1; - } - - activeUnit.showTarget(); - ctrl.setAfterAnimationState(nextState); - return StateType.ANIMATION; - } - - @Override - public void touchDown() - { - } - - @Override - public void touchUp() - { - Unit unit = upHex.getUnit(); - - // activeUnit is the target, selectedTarget is the engagement leader - if (unit == selectedUnit) { - ctrl.setState(StateType.ABORT); - } else if ((activeUnit == null) && map.possibleTargets.contains(unit)) { - // ctrl.hud.notify("Engage " + unit); - map.hidePossibleTargets(); - to = upHex; - activeUnit = unit; - activeUnit.showTarget(); - map.collectAttackAssists(selectedUnit, activeUnit, ctrl.player.units); - map.showAttackAssists(); - ctrl.hud.actionButtons.show((ctrl.cfg.mustValidate ? Buttons.DONE.b : 0) | (ctrl.cfg.canCancel ? Buttons.ABORT.b : 0)); - } - else if (unit == activeUnit) { - ctrl.setState(StateType.DONE); - } - else if ((activeUnit != null) && map.engagementAssists.contains(unit)) { - map.toggleAttackAssist(unit); - // if(map.toggleAttackAssist(unit)) - // ctrl.hud.notify(unit + " will fire"); - // else - // ctrl.hud.notify(unit + " wont fire"); - } - } -} diff --git a/core/src/ch/asynk/tankontank/game/states/StateMove.java b/core/src/ch/asynk/tankontank/game/states/StateMove.java deleted file mode 100644 index 9a8195d..0000000 --- a/core/src/ch/asynk/tankontank/game/states/StateMove.java +++ /dev/null @@ -1,193 +0,0 @@ -package ch.asynk.tankontank.game.states; - -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.hud.ActionButtons.Buttons; - -public class StateMove extends StateCommon -{ - @Override - public void enter(StateType prevState) - { - ctrl.hud.actionButtons.show( - ((map.activatedUnits.size() > 0) ? Buttons.DONE.b : 0) - | (ctrl.cfg.canCancel ? Buttons.ABORT.b : 0)); - - if (prevState == StateType.WITHDRAW) { - if (map.pathBuilder.size() == 1) - ctrl.setState(StateType.ROTATE); - return; - } - - map.pathBuilder.clear(); - - if (prevState == StateType.SELECT) { - // use selectedHex and selectedUnit - activeUnit = selectedUnit; - activeUnit.showMoveable(); - map.pathBuilder.init(activeUnit); - map.collectAndShowMovesAndAssits(activeUnit); - if (to != null) { - // quick move -> replay touchUp - upHex = to; - touchUp(); - } else - checkExit(activeUnit, activeUnit.getHex()); - } else { - // back from rotation -> chose next Pawn - if (selectedUnit.canMove()) { - changeUnit(selectedUnit); - } else { - changeUnit(map.moveableUnits.get(0)); - } - } - - activeUnit.enableOverlay(Unit.MOVE, false); - } - - @Override - public void leave(StateType nextState) - { - if (nextState == StateType.WITHDRAW) - return; - - // hide all but assists : want them when in rotation - activeUnit.hideMoveable(); - map.hidePossibleMoves(); - map.unselectHex(activeUnit.getHex()); - if (to != null) - map.hidePath(to); - - if (nextState != StateType.SELECT) { - if (to == null) - to = activeUnit.getHex(); - } - } - - @Override - public StateType abort() - { - hideAssists(); - if (activeUnit.justEntered()) { - map.revertEnter(activeUnit); - return StateType.ABORT; - } - int n = map.activatedUnits.size(); - if (n == 0) - return StateType.ABORT; - map.revertMoves(); - return StateType.ANIMATION; - } - - @Override - public StateType execute() - { - hideAssists(); - // be sure that the hq is activated - if (selectedUnit.canMove() && (map.activatedUnits.size() > 0)) - selectedUnit.setMoved(); - - return StateType.DONE; - } - - @Override - public void touchDown() - { - } - - @Override - public void touchUp() - { - if (upHex == activeUnit.getHex()) { - if (to != null) - map.hidePath(to); - to = null; - map.pathBuilder.clear(); - ctrl.setState(StateType.ROTATE); - return; - } - - int s = map.pathBuilder.size(); - - Unit unit = upHex.getUnit(); - - if (map.moveableUnits.contains(unit)) { - if(unit != activeUnit) - changeUnit(unit); - } else if ((s == 0) && map.possibleMoves.contains(upHex)) { - s = collectPaths(upHex); - } else if (map.pathBuilder.contains(upHex)) { - s = togglePoint(downHex, s); - } - - if (s == 1) { - if (!checkExit(activeUnit, upHex)) - ctrl.setState(StateType.ROTATE); - } - } - - private void hideAssists() - { - map.hideMoveableUnits(); - } - - private void changeUnit(Unit unit) - { - if (activeUnit != null ) { - map.unselectHex(activeUnit.getHex()); - if (activeUnit.canMove()) - activeUnit.enableOverlay(Unit.MOVE, true); - } - activeUnit = unit; - Hex hex = activeUnit.getHex(); - map.pathBuilder.init(activeUnit, hex); - activeUnit.showMoveable(); - map.hidePossibleMoves(); - map.collectPossibleMoves(activeUnit); - map.showPossibleMoves(); - map.selectHex(hex); - activeUnit.enableOverlay(Unit.MOVE, false); - ctrl.hud.notify(activeUnit.toString()); - checkExit(activeUnit, hex); - } - - private int collectPaths(Hex hex) - { - to = hex; - int s = map.pathBuilder.build(to); - map.showMove(to); - map.hidePossibleMoves(); - map.showPathBuilder(); - return s; - } - - private int togglePoint(Hex hex, int s) - { - if (hex == activeUnit.getHex()) { - // - } else if (hex == to) { - // - } else { - map.hidePathBuilder(); - map.togglePathOverlay(hex); - s = map.togglePathBuilderHex(hex); - map.showPathBuilder(); - } - - return s; - } - - private boolean checkExit(Unit unit, Hex hex) - { - if ((hex == unit.getHex()) && (unit.justEntered())) - return false; - Zone exitZone = ctrl.battle.getExitZone(unit); - if ((exitZone == null) || !exitZone.contains(hex)) - return false; - if ((unit.getHex() != hex) && !map.pathBuilder.canExit(exitZone.orientation)) - return false; - ctrl.setState(StateType.WITHDRAW); - return true; - } -} diff --git a/core/src/ch/asynk/tankontank/game/states/StatePromote.java b/core/src/ch/asynk/tankontank/game/states/StatePromote.java deleted file mode 100644 index 9f327e7..0000000 --- a/core/src/ch/asynk/tankontank/game/states/StatePromote.java +++ /dev/null @@ -1,42 +0,0 @@ -package ch.asynk.tankontank.game.states; - -import ch.asynk.tankontank.game.Unit; - -public class StatePromote extends StateCommon -{ - @Override - public void enter(StateType prevState) - { - ctrl.setAfterAnimationState(StateType.DONE); - ctrl.setState(StateType.ANIMATION); - map.promoteUnit(selectedUnit); - } - - @Override - public void leave(StateType nextState) - { - map.unselectHex(selectedHex); - } - - @Override - public StateType abort() - { - return StateType.ABORT; - } - - @Override - public StateType execute() - { - return StateType.DONE; - } - - @Override - public void touchDown() - { - } - - @Override - public void touchUp() - { - } -} diff --git a/core/src/ch/asynk/tankontank/game/states/StateReinforcement.java b/core/src/ch/asynk/tankontank/game/states/StateReinforcement.java deleted file mode 100644 index 3ac5c95..0000000 --- a/core/src/ch/asynk/tankontank/game/states/StateReinforcement.java +++ /dev/null @@ -1,87 +0,0 @@ -package ch.asynk.tankontank.game.states; - -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.hud.ActionButtons.Buttons; - -public class StateReinforcement extends StateCommon -{ - private Zone entryZone; - - @Override - public void enter(StateType prevState) - { - map.clearAll(); - if (selectedHex != null) - map.unselectHex(selectedHex); - entryZone = null; - selectedHex = null; - ctrl.hud.playerInfo.unitDock.show(); - } - - @Override - public void leave(StateType nextState) - { - if (selectedHex != null) - map.unselectHex(selectedHex); - if (entryZone != null) - entryZone.enable(Hex.AREA, false); - ctrl.hud.playerInfo.unitDock.hide(); - } - - @Override - public StateType abort() - { - return StateType.ABORT; - } - - @Override - public StateType execute() - { - return StateType.DONE; - } - - @Override - public void touchDown() - { - } - - @Override - public void touchUp() - { - Unit unit = ctrl.hud.playerInfo.unitDock.selectedUnit; - if ((unit != null) && (unit != activeUnit)) - changeUnit(unit); - else if ((entryZone != null) && upHex.isEmpty() && entryZone.contains(upHex)) - unitEnter(activeUnit); - else - ctrl.setState(StateType.SELECT); - } - - private void changeUnit(Unit unit) - { - activeUnit = unit; - if (entryZone != null) - entryZone.enable(Hex.AREA, false); - entryZone = ctrl.battle.getEntryZone(activeUnit); - entryZone.enable(Hex.AREA, true); - ctrl.hud.actionButtons.show(((ctrl.cfg.canCancel) ? Buttons.ABORT.b : 0)); - } - - private void unitEnter(Unit unit) - { - selectedUnit = unit; - selectedHex = upHex; - map.selectHex(selectedHex); - entryZone.enable(Hex.AREA, false); - if (map.enterBoard(unit, upHex, entryZone.allowedMoves)) { - if (unit.getMovementPoints() > 0) - ctrl.setState(StateType.MOVE); - else - ctrl.setState(StateType.ROTATE); - } else { - ctrl.hud.notify("Can not enter the map at that position"); - } - } -} diff --git a/core/src/ch/asynk/tankontank/game/states/StateRotate.java b/core/src/ch/asynk/tankontank/game/states/StateRotate.java deleted file mode 100644 index d297840..0000000 --- a/core/src/ch/asynk/tankontank/game/states/StateRotate.java +++ /dev/null @@ -1,111 +0,0 @@ -package ch.asynk.tankontank.game.states; - -import ch.asynk.tankontank.engine.Orientation; -import ch.asynk.tankontank.game.hud.ActionButtons.Buttons; - -import ch.asynk.tankontank.TankOnTank; - -public class StateRotate extends StateCommon -{ - private boolean rotateOnly; - private boolean rotationSet; - - @Override - public void enter(StateType prevState) - { - ctrl.hud.actionButtons.show((ctrl.cfg.canCancel && (map.moveableUnits.size() > 1))? Buttons.ABORT.b : 0); - - if (activeUnit == null) - activeUnit = selectedUnit; - if (to == null) - to = activeUnit.getHex(); - - if (!map.pathBuilder.isSet()) { - map.pathBuilder.init(activeUnit); - map.pathBuilder.build(to); - } - - if (map.pathBuilder.size() != 1) - TankOnTank.debug("ERROR: pathBuilder.size() == " + map.pathBuilder.size()); - - rotateOnly = (to == activeUnit.getHex()); - - if (!rotateOnly) - map.showPath(to); - map.selectHex(activeUnit.getHex()); - map.showDirections(to); - - rotationSet = false; - } - - @Override - public void leave(StateType nextState) - { - map.unselectHex(activeUnit.getHex()); - map.hidePath(to); - map.hideDirections(to); - map.hideOrientation(to); - map.pathBuilder.clear(); - to = null; - } - - @Override - public StateType abort() - { - StateType nextState = StateType.ABORT; - ctrl.hud.actionButtons.hide(); - if (activeUnit.justEntered()) { - map.revertEnter(activeUnit); - nextState = StateType.ABORT; - } else if (map.activatedUnits.size() == 0) { - map.hideMoveableUnits(); - } else { - nextState = StateType.MOVE; - } - return nextState; - } - - @Override - public StateType execute() - { - StateType whenDone = StateType.DONE; - - if (map.moveUnit(activeUnit) > 0) - whenDone = StateType.MOVE; - - ctrl.setAfterAnimationState(whenDone); - return StateType.ANIMATION; - } - - @Override - public void touchDown() - { - } - - @Override - public void touchUp() - { - if (rotationSet) return; - - Orientation o = Orientation.fromAdj(to, upHex); - if (o == Orientation.KEEP) { - ctrl.setState(StateType.ABORT); - return; - } - - if (!activeUnit.justEntered() && rotateOnly && (o == activeUnit.getOrientation())) - return; - - map.pathBuilder.orientation = o; - rotationSet = true; - - if (ctrl.cfg.mustValidate) { - map.hideDirections(to); - map.showOrientation(to, o); - ctrl.hud.actionButtons.show(Buttons.DONE.b | ((ctrl.cfg.canCancel) ? Buttons.ABORT.b : 0)); - } else { - execute(); - ctrl.setState(StateType.ANIMATION); - } - } -} diff --git a/core/src/ch/asynk/tankontank/game/states/StateSelect.java b/core/src/ch/asynk/tankontank/game/states/StateSelect.java deleted file mode 100644 index 387fbb0..0000000 --- a/core/src/ch/asynk/tankontank/game/states/StateSelect.java +++ /dev/null @@ -1,132 +0,0 @@ -package ch.asynk.tankontank.game.states; - -import ch.asynk.tankontank.game.Map; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.Unit; -import ch.asynk.tankontank.game.Ctrl; -import ch.asynk.tankontank.game.hud.ActionButtons.Buttons; - -import ch.asynk.tankontank.TankOnTank; - -public class StateSelect extends StateCommon -{ - public StateSelect(Ctrl ctrl, Map map) - { - super(ctrl, map); - } - - @Override - public void enter(StateType prevState) - { - to = null; - selectedHex = null; - selectedUnit = null; - activeUnit = null; - map.clearAll(); - ctrl.hud.actionButtons.hide(); - } - - @Override - public void leave(StateType nextState) - { - hidePossibilities(); - } - - @Override - public StateType abort() - { - if (selectedHex != null) - map.unselectHex(selectedHex); - hidePossibilities(); - map.clearAll(); - return StateType.ABORT; - } - - @Override - public StateType execute() - { - return StateType.DONE; - } - - @Override - public void touchDown() - { - } - - @Override - public void touchUp() - { - if (!isEnemy) { - if (map.possibleMoves.contains(upHex)) { - // quick move - to = upHex; - ctrl.setState(StateType.MOVE); - return; - } - if (map.possibleTargets.contains(upHex.getUnit())) { - // quick fire - to = upHex; - ctrl.setState(StateType.ENGAGE); - return; - } - } - - if (selectedHex != null) - map.unselectHex(selectedHex); - - hidePossibilities(); - if (upHex.isOffMap()) { - selectedUnit = null; - return; - } - - Unit unit = upHex.getUnit(); - - if (unit == null) { - isEnemy = false; - ctrl.hud.actionButtons.hide(); - map.clearAll(); - selectedUnit = null; - return; - } - - isEnemy = ctrl.player.isEnemy(unit); - if (!isEnemy && (unit == selectedUnit) && unit.canMove()) { - if (unit.isHq()) { - ctrl.hud.notify("HQ activation"); - select(upHex, unit, isEnemy); - ctrl.setState(StateType.MOVE); - } else { - // quick rotate - to = upHex; - ctrl.setState(StateType.ROTATE); - } - } else { - select(upHex, unit, isEnemy); - ctrl.hud.notify(selectedUnit.toString()); - } - } - - private void select(Hex hex, Unit unit, boolean isEnemy) - { - selectedHex = hex; - selectedUnit = unit; - - if (isEnemy && !ctrl.cfg.showEnemyPossibilities) - return; - - int moves = map.collectPossibleMoves(selectedUnit); - int targets = map.collectPossibleTargets(selectedUnit, (isEnemy ? ctrl.player.units : ctrl.opponent.units)); - - if (moves > 0) - map.collectMoveableUnits(selectedUnit); - - if ((moves > 0) || (targets > 0)) { - map.selectHex(selectedHex); - showPossibilities(selectedUnit); - } - - ctrl.hud.actionButtons.show((ctrl.player.canPromote(selectedUnit)) ? Buttons.PROMOTE.b : 0 ); - TankOnTank.debug("Select", selectedHex.toString() + " " + selectedUnit + (isEnemy ? " enemy " : " friend ")); - } -} diff --git a/core/src/ch/asynk/tankontank/game/states/StateWithdraw.java b/core/src/ch/asynk/tankontank/game/states/StateWithdraw.java deleted file mode 100644 index 87c33b8..0000000 --- a/core/src/ch/asynk/tankontank/game/states/StateWithdraw.java +++ /dev/null @@ -1,71 +0,0 @@ -package ch.asynk.tankontank.game.states; - -import ch.asynk.tankontank.game.Zone; -import ch.asynk.tankontank.game.Hex; -import ch.asynk.tankontank.game.Unit; - -public class StateWithdraw extends StateCommon -{ - @Override - public void enter(StateType prevState) - { - ctrl.hud.askExitBoard(); - } - - @Override - public void leave(StateType nextState) - { - } - - @Override - public StateType abort() - { - return StateType.MOVE; - } - - @Override - public StateType execute() - { - if (activeUnit == null) - activeUnit = selectedUnit; - - ctrl.setAfterAnimationState(withdraw(activeUnit)); - return StateType.ANIMATION; - } - - @Override - public void touchDown() - { - } - - @Override - public void touchUp() - { - } - - private StateType withdraw(Unit unit) - { - Zone exitZone = ctrl.battle.getExitZone(unit); - Hex hex = unit.getHex(); - - // rotation - if (map.pathBuilder.to == null) - map.pathBuilder.build(hex); - - Hex exitHex = (Hex) map.pathBuilder.to; - if (!exitZone.contains(exitHex)) - throw new RuntimeException(String.format("%s not in exitZone", exitHex)); - - map.pathBuilder.setExit(exitZone.orientation); - - unit.hideMoveable(); - if (to != null) - map.hidePath(to); - map.hidePossibleMoves(); - map.unselectHex(hex); - - if (map.exitBoard(unit) > 0) - return StateType.MOVE; - return StateType.DONE; - } -} diff --git a/core/src/ch/asynk/tankontank/loading/LoadingBar.java b/core/src/ch/asynk/tankontank/loading/LoadingBar.java deleted file mode 100644 index 2b14713..0000000 --- a/core/src/ch/asynk/tankontank/loading/LoadingBar.java +++ /dev/null @@ -1,32 +0,0 @@ -package ch.asynk.tankontank.loading; - -import com.badlogic.gdx.graphics.g2d.Animation; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.scenes.scene2d.Actor; - -public class LoadingBar extends Actor -{ - Animation animation; - TextureRegion reg; - float stateTime; - - public LoadingBar(Animation animation) - { - this.animation = animation; - reg = animation.getKeyFrame(0); - } - - @Override - public void act(float delta) - { - stateTime += delta; - reg = animation.getKeyFrame(stateTime); - } - - @Override - public void draw(Batch batch, float parentAlpha) - { - batch.draw(reg, getX(), getY()); - } -} diff --git a/core/src/ch/asynk/tankontank/menu/MainMenu.java b/core/src/ch/asynk/tankontank/menu/MainMenu.java deleted file mode 100644 index 8147f46..0000000 --- a/core/src/ch/asynk/tankontank/menu/MainMenu.java +++ /dev/null @@ -1,67 +0,0 @@ -package ch.asynk.tankontank.menu; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; - -import ch.asynk.tankontank.ui.Menu; - -public class MainMenu extends Menu -{ - public enum Items implements Menu.MenuItem - { - EXIT(0), - OPTIONS(1), - TUTORIALS(2), - SCENARIOS(3), - NONE(4); - public int i; - Items(int i) - { - this.i = i; - } - public int i() { return i; } - public int last() { return NONE.i; } - }; - - public MainMenu(BitmapFont font, TextureAtlas atlas) - { - super(Items.NONE, font, atlas.createPatch("typewriter")); - - label(Items.OPTIONS).write("Options"); - label(Items.TUTORIALS).write("Tutorials"); - label(Items.SCENARIOS).write("Scenarios"); - label(Items.EXIT).write("Exit"); - - this.visible = true; - } - - public Items getMenu() - { - return (Items) menuItem; - } - - @Override - public boolean hit(float x, float y) - { - boolean ret = false; - menuItem = Items.NONE; - - if (!visible) return ret; - - if (label(Items.SCENARIOS).hit(x, y)) { - menuItem = Items.SCENARIOS; - ret = true; - } else if (label(Items.TUTORIALS).hit(x, y)) { - menuItem = Items.TUTORIALS; - ret = true; - } else if (label(Items.OPTIONS).hit(x, y)) { - menuItem = Items.OPTIONS; - ret = true; - } else if (label(Items.EXIT).hit(x, y)) { - Gdx.app.exit(); - } - - return ret; - } -} diff --git a/core/src/ch/asynk/tankontank/menu/OptionsMenu.java b/core/src/ch/asynk/tankontank/menu/OptionsMenu.java deleted file mode 100644 index c866d30..0000000 --- a/core/src/ch/asynk/tankontank/menu/OptionsMenu.java +++ /dev/null @@ -1,257 +0,0 @@ -package ch.asynk.tankontank.menu; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.GlyphLayout; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; - -import ch.asynk.tankontank.ui.Label; -import ch.asynk.tankontank.ui.Bg; -import ch.asynk.tankontank.ui.Patch; -import ch.asynk.tankontank.ui.OkCancel; - -import ch.asynk.tankontank.TankOnTank; - -public class OptionsMenu extends Patch -{ - public static int PADDING = 40; - public static int OK_PADDING = 10; - public static int TITLE_PADDING = 30; - public static int VSPACING = 5; - public static int HSPACING = 30; - public static String CHECK = "#"; - - private final TankOnTank game; - private final BitmapFont font; - - private String [] checkStrings = { - "Debug", - "Must Validate", - "Can Cancel", - "Show Enemy Possibilities", - "Show Moves Assists", - "Show Targets", - "Show Moves", - }; - private String [] fxStrings = { "OFF", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "ON" }; - - private float checkDy; - private Label title; - private Label fxVolume; - private Label fxVolumeValue; - private Label graphics; - private Label graphicsValue; - private Label gameMode; - private Label gameModeValue; - private Label [] checkLabels; - private boolean [] checkValues; - private OkCancel okCancel; - protected Bg okBtn; - - public OptionsMenu(TankOnTank game, BitmapFont font, TextureAtlas atlas) - { - super(atlas.createPatch("typewriter")); - this.game = game; - this.font = font; - this.okCancel = new OkCancel(font, atlas); - this.okBtn = new Bg(atlas.findRegion("ok")); - this.title = new Label(font); - this.title.write("- Options"); - this.fxVolume = new Label(font); - this.fxVolume.write("Fx Volume"); - this.fxVolumeValue = new Label(font); - this.fxVolumeValue.write(fxStrings[(int) (game.config.fxVolume * 10)]); - this.graphics = new Label(font); - this.graphics.write("Graphics"); - this.graphicsValue = new Label(font); - this.graphicsValue.write(game.config.graphics.s); - this.gameMode = new Label(font); - this.gameMode.write("Game mode"); - this.gameModeValue = new Label(font); - this.gameModeValue.write(game.config.gameMode.s); - this.checkValues = new boolean[checkStrings.length]; - this.checkLabels = new Label[checkStrings.length]; - for (int i = 0; i < checkLabels.length; i++) { - Label l = new Label(font, 5f); - l.write(checkStrings[i]); - this.checkLabels[i] = l; - } - getValues(); - GlyphLayout layout = new GlyphLayout(); - layout.setText(font, CHECK); - checkDy = layout.height + 5; - - this.visible = false; - } - - private void getValues() - { - checkValues[6] = game.config.showMoves; - checkValues[5] = game.config.showTargets; - checkValues[4] = game.config.showMoveAssists; - checkValues[3] = game.config.showEnemyPossibilities; - checkValues[2] = game.config.canCancel; - checkValues[1] = game.config.mustValidate; - checkValues[0] = game.config.debug; - } - - private boolean apply() - { - game.config.showMoves = checkValues[6]; - game.config.showTargets = checkValues[5]; - game.config.showMoveAssists = checkValues[4]; - game.config.showEnemyPossibilities = checkValues[3]; - game.config.canCancel = checkValues[2]; - game.config.mustValidate = checkValues[1]; - game.config.debug = checkValues[0]; - if (!game.config.gameModeImplemented()) { - this.visible = false; - okCancel.show(String.format("'%s' Game Mode not implemented yet.", game.config.gameMode.s)); - okCancel.noCancel(); - return false; - } - return true; - } - - private void cycleFxVolume() - { - int i = (int) (game.config.fxVolume * 10) + 1; - if (i > 10) i = 0; - float fx = fxVolumeValue.getX(); - float fy = fxVolumeValue.getY(); - fxVolumeValue.write(fxStrings[i]); - fxVolumeValue.setPosition(fx, fy); - game.config.fxVolume = (i / 10f); - } - - private void cycleGraphics() - { - game.config.graphics = game.config.graphics.next(); - float fx = graphicsValue.getX(); - float fy = graphicsValue.getY(); - graphicsValue.write(game.config.graphics.s); - graphicsValue.setPosition(fx, fy); - } - - private void cycleGameMode() - { - game.config.gameMode = game.config.gameMode.next(); - float fx = gameModeValue.getX(); - float fy = gameModeValue.getY(); - gameModeValue.write(game.config.gameMode.s); - gameModeValue.setPosition(fx, fy); - } - - public void setPosition() - { - float h = (title.getHeight() + TITLE_PADDING + ((checkLabels.length - 1) * VSPACING) + (2 * PADDING)); - for (int i = 0; i < checkLabels.length; i++) - h += checkLabels[i].getHeight(); - h += (graphics.getHeight() + VSPACING); - h += (gameMode.getHeight() + VSPACING); - h += (fxVolume.getHeight() + VSPACING); - - float w = title.getWidth(); - for (int i = 0; i < checkLabels.length; i++) { - float t = checkLabels[i].getWidth(); - if (t > w) - w = t; - } - w += (2 * PADDING) + HSPACING; - - float x = position.getX(w); - float y = position.getY(h); - setPosition(x, y, w, h); - - okBtn.setPosition((x + w - okBtn.getWidth() + OK_PADDING), (y - OK_PADDING)); - - y += PADDING; - x += PADDING + HSPACING; - float dy = (VSPACING + checkLabels[0].getHeight()); - - graphics.setPosition(x, y); - graphicsValue.setPosition((x + graphics.getWidth() + 10), y); - y += dy; - gameMode.setPosition(x, y); - gameModeValue.setPosition((x + gameMode.getWidth() + 10), y); - y += dy; - fxVolume.setPosition(x, y); - fxVolumeValue.setPosition((x + fxVolume.getWidth() + 10), y); - y += dy; - for (int i = 0; i < checkLabels.length; i++) { - checkLabels[i].setPosition(x, y); - y += dy; - } - y += (TITLE_PADDING - VSPACING); - title.setPosition(x, y); - } - - @Override - public boolean hit(float x, float y) - { - if (okCancel.hit(x, y)) { - this.visible = true; - okCancel.visible = false; - return false; - } - - if (!visible) return false; - - if (okBtn.hit(x, y)) { - return apply(); - } else if (fxVolume.hit(x, y) || fxVolumeValue.hit(x, y)) { - cycleFxVolume(); - } else if (graphics.hit(x, y) || graphicsValue.hit(x, y)) { - cycleGraphics(); - } else if (gameMode.hit(x, y) || gameModeValue.hit(x, y)) { - cycleGameMode(); - } else { - for (int i = 0; i < checkLabels.length; i++) { - if (checkLabels[i].hit(x, y)) - checkValues[i] =! checkValues[i]; - } - } - - return false; - } - - @Override - public void dispose() - { - super.dispose(); - title.dispose(); - okBtn.dispose(); - okCancel.dispose(); - fxVolume.dispose(); - fxVolumeValue.dispose(); - graphics.dispose(); - graphicsValue.dispose(); - gameMode.dispose(); - gameModeValue.dispose(); - for (int i = 0; i < checkLabels.length; i++) - checkLabels[i].dispose(); - } - - @Override - public void draw(Batch batch) - { - okCancel.draw(batch); - - if (!visible) return; - super.draw(batch); - title.draw(batch); - okBtn.draw(batch); - fxVolume.draw(batch); - fxVolumeValue.draw(batch); - graphics.draw(batch); - graphicsValue.draw(batch); - gameMode.draw(batch); - gameModeValue.draw(batch); - for (int i = 0; i < checkLabels.length; i++) { - Label l = checkLabels[i]; - l.draw(batch); - if (checkValues[i]) - font.draw(batch, CHECK, (l.getX() - HSPACING) , l.getY() + checkDy); - } - } -} diff --git a/core/src/ch/asynk/tankontank/menu/ScenariosMenu.java b/core/src/ch/asynk/tankontank/menu/ScenariosMenu.java deleted file mode 100644 index 7cd6499..0000000 --- a/core/src/ch/asynk/tankontank/menu/ScenariosMenu.java +++ /dev/null @@ -1,141 +0,0 @@ -package ch.asynk.tankontank.menu; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.GlyphLayout; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; - -import ch.asynk.tankontank.ui.Label; -import ch.asynk.tankontank.ui.Bg; -import ch.asynk.tankontank.ui.Patch; -import ch.asynk.tankontank.TankOnTank; -import ch.asynk.tankontank.game.Battle; - -public class ScenariosMenu extends Patch -{ - public static int PADDING = 40; - public static int BTN_PADDING = 10; - public static int TITLE_PADDING = 30; - public static int VSPACING = 5; - public static int HSPACING = 30; - public static String CHECK = "#"; - - private final TankOnTank game; - private final BitmapFont font; - - private float checkDy; - private Label title; - protected Bg okBtn; - protected Bg cancelBtn; - private Label [] battleLabels; - - public boolean launch; - - public ScenariosMenu(TankOnTank game, BitmapFont font, TextureAtlas atlas) - { - super(atlas.createPatch("typewriter")); - this.game = game; - this.font = font; - this.okBtn = new Bg(atlas.findRegion("ok")); - this.cancelBtn = new Bg(atlas.findRegion("cancel")); - this.title = new Label(font); - this.title.write("- Scenarios"); - this.battleLabels = new Label[game.factory.battles.length]; - for (int i = 0; i < battleLabels.length; i++) { - Label l = new Label(font, 8f); - l.write(game.factory.battles[i].getName()); - battleLabels[i] = l; - } - GlyphLayout layout = new GlyphLayout(); - layout.setText(font, CHECK); - checkDy = layout.height + 9; - - this.visible = false; - this.launch = false; - } - - public void setPosition() - { - float h = (title.getHeight() + TITLE_PADDING + ((battleLabels.length - 1) * VSPACING) + (2 * PADDING)); - for (int i = 0; i < battleLabels.length; i++) - h += battleLabels[i].getHeight(); - - float w = title.getWidth(); - for (int i = 0; i < battleLabels.length; i++) { - float t = battleLabels[i].getWidth(); - if (t > w) - w = t; - } - w += (2 * PADDING) + HSPACING; - - float x = position.getX(w); - float y = position.getY(h); - setPosition(x, y, w, h); - - okBtn.setPosition((x + w - okBtn.getWidth() + BTN_PADDING), (y - BTN_PADDING)); - cancelBtn.setPosition((x - BTN_PADDING), okBtn.getY()); - - y += PADDING; - x += PADDING + HSPACING; - float dy = (VSPACING + battleLabels[0].getHeight()); - - for (int i = (battleLabels.length - 1); i > -1; i--) { - battleLabels[i].setPosition(x, y); - y += dy; - } - y += (TITLE_PADDING - VSPACING); - title.setPosition(x, y); - } - - @Override - public boolean hit(float x, float y) - { - if (!visible) return false; - - if (okBtn.hit(x, y)) { - this.launch = (game.config.battle != null); - return true; - } else if (cancelBtn.hit(x, y)) { - this.launch = false; - return true; - } else { - for (int i = 0; i w) - w = msg.getWidth(); - w += (2 * PADDING); - - float x = position.getX(w); - float y = position.getY(h); - setPosition(x, y, w, h); - - okBtn.setPosition((x + w - okBtn.getWidth() + OK_PADDING), (y - OK_PADDING)); - - y += PADDING; - x += PADDING; - - msg.setPosition(x, y); - - y += (msg.getHeight() + TITLE_PADDING); - title.setPosition(x, y); - } - - @Override - public boolean hit(float x, float y) - { - if (!visible) return false; - - if (okBtn.hit(x, y)) - return true; - - return false; - } - - @Override - public void dispose() - { - super.dispose(); - title.dispose(); - msg.dispose(); - okBtn.dispose(); - } - - @Override - public void draw(Batch batch) - { - if (!visible) return; - super.draw(batch); - title.draw(batch); - msg.draw(batch); - okBtn.draw(batch); - } -} diff --git a/core/src/ch/asynk/tankontank/screens/GameCamera.java b/core/src/ch/asynk/tankontank/screens/GameCamera.java deleted file mode 100644 index 52ef271..0000000 --- a/core/src/ch/asynk/tankontank/screens/GameCamera.java +++ /dev/null @@ -1,188 +0,0 @@ -package ch.asynk.tankontank.screens; - -import com.badlogic.gdx.Gdx; - -import com.badlogic.gdx.graphics.OrthographicCamera; - -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Matrix4; -import com.badlogic.gdx.math.Vector3; -import com.badlogic.gdx.math.MathUtils; - -public class GameCamera extends OrthographicCamera -{ - private static final float ZEROF = 0.01f; - - private int screenWidth; - private int screenHeight; - private float zoomOut; - private float zoomIn; - private float viewportAspect; - private float widthFactor; - private float heightFactor; - private Rectangle virtual; - private Rectangle window; - private Matrix4 hudMatrix; - private Matrix4 hudInvProjMatrix; - private int hudCorrection; - private int hudLeft; - private int hudBottom; - - public GameCamera(float virtualWidth, float virtualHeight, float zoomOut, float zoomIn, int hudCorrection) - { - super(virtualWidth, virtualHeight); - this.zoomOut = zoomOut; - this.zoomIn = zoomIn; - this.viewportAspect = (viewportWidth / viewportHeight); - this.virtual = new Rectangle(); - this.virtual.set(0, 0, virtualWidth, virtualHeight); - this.window = new Rectangle(); - this.hudMatrix = new Matrix4(); - this.hudInvProjMatrix = new Matrix4(); - this.hudLeft = 0; - this.hudBottom = 0; - this.hudCorrection = hudCorrection; - } - - public void updateViewport(int screenWidth, int screenHeight) - { - this.screenWidth = screenWidth; - this.screenHeight = screenHeight; - - float aspect = (screenWidth / (float) screenHeight); - float diff = (viewportAspect - aspect); - - if (diff < -ZEROF) { - window.width = java.lang.Math.min((screenHeight * viewportAspect / zoom), screenWidth); - window.height = screenHeight; - window.x = ((screenWidth - window.width) / 2f); - window.y = 0f; - viewportWidth = (viewportHeight * (window.width / window.height)); - hudBottom = hudCorrection; - hudLeft = (int) (hudBottom * viewportWidth / viewportHeight); - } else if (diff > ZEROF) { - window.width = screenWidth; - window.height = java.lang.Math.min((screenWidth * viewportAspect / zoom), screenHeight); - window.x = 0f; - window.y = ((screenHeight - window.height) / 2f); - viewportHeight = (viewportWidth * (window.height / window.width)); - hudLeft = hudCorrection; - hudBottom = (int) (hudLeft / viewportWidth * viewportHeight); - } - - Gdx.gl.glViewport((int)window.x, (int)window.y, (int)window.width, (int)window.height); - - this.widthFactor = (viewportWidth / screenWidth); - this.heightFactor = (viewportHeight / screenHeight); - - clampPosition(); - update(true); - hudMatrix.set(combined); - hudMatrix.setToOrtho2D(getHudLeft(), getHudBottom(), getHudWidth(), getHudHeight()); - hudInvProjMatrix.set(hudMatrix); - Matrix4.inv(hudInvProjMatrix.val); - } - - public Matrix4 getHudMatrix() - { - return hudMatrix; - } - - public int getScreenWidth() - { - return screenWidth; - } - - public int getScreenHeight() - { - return screenHeight; - } - - public int getHudLeft() - { - return hudLeft; - } - - public int getHudBottom() - { - return hudBottom; - } - - public int getHudWidth() - { - return (int) window.width - (2 * getHudLeft()); - } - - public int getHudHeight() - { - return (int) window.height - (2 * getHudBottom()); - } - - public void centerOnWorld() - { - position.set((viewportWidth / 2f), (viewportHeight / 2f), 0f); - } - - public void zoom(float dz) - { - zoom += dz; - clampZoom(); - updateViewport(screenWidth, screenHeight); - } - - public void translate(float dx, float dy) - { - float deltaX = (dx * zoom * widthFactor); - float deltaY = (dy * zoom * heightFactor); - translate(deltaX, -deltaY, 0); - clampPosition(); - update(true); - } - - public void clampZoom() - { - zoom = MathUtils.clamp(zoom, zoomIn, zoomOut); - } - - public void clampPosition() - { - float cx = (viewportWidth * zoom); - float cy = (viewportHeight * zoom); - - if ((virtual.width - cx) > ZEROF) { - cx /= 2f; - position.x = MathUtils.clamp(position.x, cx, (virtual.width - cx)); - } else - position.x = (virtual.width / 2f); - - if ((virtual.height - cy) > ZEROF) { - cy /= 2f; - position.y = MathUtils.clamp(position.y, cy, (virtual.height - cy)); - } else - position.y = (virtual.height / 2f); - } - - public void debug() - { - System.err.println(String.format(" VIEWPORT: %dx%d * %.2f -> %dx%d", (int)viewportWidth, (int)viewportHeight, - zoom, (int)(viewportWidth * zoom), (int)(viewportHeight * zoom))); - System.err.println(String.format(" WINDOW: %d;%d %dx%d", (int)window.x, (int)window.y, (int)window.width, (int)window.height)); - System.err.println("MATRIX:" + combined.toString()); - } - - public void unproject(int x, int y, Vector3 v) - { - unproject(v.set(x, y, 0), window.x, window.y, window.width, window.height); - } - - public void unprojectHud(float x, float y, Vector3 v) - { - x = x - window.x; - y = Gdx.graphics.getHeight() - y - 1; - y = y - window.y; - v.x = (2 * x) / window.width - 1; - v.y = (2 * y) / window.height - 1; - v.z = 2 * v.z - 1; - v.prj(hudInvProjMatrix); - } -} diff --git a/core/src/ch/asynk/tankontank/screens/GameScreen.java b/core/src/ch/asynk/tankontank/screens/GameScreen.java deleted file mode 100644 index d5fa401..0000000 --- a/core/src/ch/asynk/tankontank/screens/GameScreen.java +++ /dev/null @@ -1,217 +0,0 @@ -package ch.asynk.tankontank.screens; - -import com.badlogic.gdx.Gdx; - -import com.badlogic.gdx.Screen; -import com.badlogic.gdx.Input; -import com.badlogic.gdx.InputAdapter; -import com.badlogic.gdx.InputMultiplexer; -import com.badlogic.gdx.input.GestureDetector; -import com.badlogic.gdx.input.GestureDetector.GestureAdapter; - -import com.badlogic.gdx.graphics.GL20; -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import com.badlogic.gdx.math.Vector2; - -import ch.asynk.tankontank.TankOnTank; - -import ch.asynk.tankontank.game.Ctrl; - -public class GameScreen implements Screen -{ - private static boolean DEBUG = false; - - private static final float INPUT_DELAY = 0.1f; - private static final float ZOOM_IN_MAX = 0.3f; - private static final float ZOOM_OUT_MAX = 1f; - private static final float ZOOM_GESTURE_FACTOR = .01f; - private static final float ZOOM_SCROLL_FACTOR = .1f; - private static final int DRAGGED_Z_INDEX = 10; - private static final int DRAG_THRESHOLD = 6; - - private final GameCamera cam; - - private final SpriteBatch batch; - private ShapeRenderer debugShapes = null; - - private final TankOnTank game; - private Ctrl ctrl; - - private int dragged; - private boolean blocked; - private float inputDelay = 0f; - private Vector2 dragPos = new Vector2(); - - public GameScreen(final TankOnTank game) - { - DEBUG = game.config.debug; - - this.game = game; - this.dragged = 0; - this.blocked = false; - - this.batch = new SpriteBatch(); - this.ctrl = new Ctrl(game, game.config.battle); - this.cam = new GameCamera(ctrl.map.getWidth(), ctrl.map.getHeight(), ZOOM_OUT_MAX, ZOOM_IN_MAX, game.hudCorrection); - - if (DEBUG) this.debugShapes = new ShapeRenderer(); - - Gdx.input.setInputProcessor(getMultiplexer()); - } - - - private InputMultiplexer getMultiplexer() - { - final InputMultiplexer multiplexer = new InputMultiplexer(); - multiplexer.addProcessor(new GestureDetector(new GestureAdapter() { - @Override - public boolean zoom(float initialDistance, float distance) - { - if (initialDistance > distance) - cam.zoom(ZOOM_GESTURE_FACTOR); - else - cam.zoom(-ZOOM_GESTURE_FACTOR); - ctrl.hud.resize(cam.getHudLeft(), cam.getHudBottom(), cam.getHudWidth(), cam.getHudHeight()); - blocked = true; - inputDelay = INPUT_DELAY; - return true; - } - })); - multiplexer.addProcessor(new InputAdapter() { - @Override - public boolean touchDragged(int x, int y, int pointer) - { - dragged += 1; - cam.translate((dragPos.x - x), (dragPos.y - y)); - dragPos.set(x, y); - return true; - } - @Override - public boolean touchDown(int x, int y, int pointer, int button) - { - if (blocked) return true; - if (button == Input.Buttons.LEFT) { - dragPos.set(x, y); - cam.unproject(x, y, ctrl.mapTouch); - cam.unprojectHud(x, y, ctrl.hudTouch); - ctrl.touchDown(); - } - return true; - } - @Override - public boolean touchUp(int x, int y, int pointer, int button) - { - if (blocked) return true; - if (dragged > DRAG_THRESHOLD) { - dragged = 0; - return true; - } - dragged = 0; - if (button == Input.Buttons.LEFT) { - cam.unproject(x, y, ctrl.mapTouch); - cam.unprojectHud(x, y, ctrl.hudTouch); - ctrl.touchUp(); - } - return true; - } - @Override - public boolean scrolled(int amount) - { - cam.zoom(amount * ZOOM_SCROLL_FACTOR); - ctrl.hud.resize(cam.getHudLeft(), cam.getHudBottom(), cam.getHudWidth(), cam.getHudHeight()); - return true; - } - }); - - return multiplexer; - } - - @Override - public void render(float delta) - { - if (inputDelay > 0f) { - inputDelay -= delta; - if (inputDelay <= 0f) - blocked = false; - } - - ctrl.hud.animate(delta); - ctrl.map.animate(delta); - - Gdx.gl.glClearColor(0, 0, 0, 1); - Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); - - // cam.update(); - batch.setProjectionMatrix(cam.combined); - batch.begin(); - ctrl.map.draw(batch); - batch.end(); - - - if (DEBUG) { - Gdx.gl.glEnable(GL20.GL_BLEND); - debugShapes.setAutoShapeType(true); - debugShapes.setProjectionMatrix(cam.combined); - debugShapes.begin(); - ctrl.map.drawDebug(debugShapes); - debugShapes.end(); - } - - batch.setProjectionMatrix(cam.getHudMatrix()); - batch.begin(); - ctrl.hud.draw(batch, DEBUG); - batch.end(); - - if (DEBUG) { - Gdx.gl.glEnable(GL20.GL_BLEND); - debugShapes.setAutoShapeType(true); - debugShapes.setProjectionMatrix(cam.getHudMatrix()); - debugShapes.begin(); - ctrl.hud.drawDebug(debugShapes); - debugShapes.end(); - } - } - - @Override - public void resize(int width, int height) - { - // TankOnTank.debug("GameScreen", "resize (" + width + "," + height + ")"); - cam.updateViewport(width, height); - ctrl.hud.resize(cam.getHudLeft(), cam.getHudBottom(), cam.getHudWidth(), cam.getHudHeight()); - } - - @Override - public void dispose() - { - // TankOnTank.debug("GameScreen", "dispose()"); - batch.dispose(); - ctrl.dispose(); - if (DEBUG) debugShapes.dispose(); - } - - @Override - public void show() - { - // TankOnTank.debug("GameScreen", "show()"); - } - - @Override - public void hide() - { - // TankOnTank.debug("GameScreen", "hide()"); - } - - @Override - public void pause() - { - // TankOnTank.debug("GameScreen", "pause()"); - } - - @Override - public void resume() - { - // TankOnTank.debug("GameScreen", "resume()"); - } -} diff --git a/core/src/ch/asynk/tankontank/screens/MenuCamera.java b/core/src/ch/asynk/tankontank/screens/MenuCamera.java deleted file mode 100644 index 9e27f16..0000000 --- a/core/src/ch/asynk/tankontank/screens/MenuCamera.java +++ /dev/null @@ -1,113 +0,0 @@ -package ch.asynk.tankontank.screens; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.OrthographicCamera; -import com.badlogic.gdx.math.Vector3; -import com.badlogic.gdx.math.Matrix4; -import com.badlogic.gdx.math.Rectangle; - -public class MenuCamera extends OrthographicCamera -{ - private static final float ZEROF = 0.01f; - - private float virtualAspect; - private final Rectangle virtual; - private final Rectangle window; - private int hudLeft; - private int hudBottom; - private int hudCorrection; - - private Matrix4 uiMatrix; - private Matrix4 uiInvProjMatrix; - - public MenuCamera(int cx, int cy, int width, int height, int hudCorrection) - { - super(width, height); - this.virtual = new Rectangle(); - this.virtual.set(cx, cy, width, height); - this.virtualAspect = (virtual.width / virtual.height); - this.window = new Rectangle(); - this.window.set(0, 0, 0, 0); - this.position.set(virtual.x, virtual.y, 0f); - this.hudLeft = 0; - this.hudBottom = 0; - this.hudCorrection = hudCorrection; - - this.uiMatrix = new Matrix4(); - this.uiInvProjMatrix = new Matrix4(); - } - - public void updateViewport(int screenWidth, int screenHeight) - { - float aspect = (screenWidth / (float) screenHeight); - float diff = (virtualAspect - aspect); - - if (diff < -ZEROF) { - viewportWidth = (virtual.height * aspect); - viewportHeight = virtual.height; - } else if (diff > ZEROF) { - viewportWidth = virtual.width; - viewportHeight = (virtual.width / aspect); - } - - window.width = screenWidth; - window.height = screenHeight; - hudLeft = hudCorrection; - hudBottom = (int) (hudLeft / aspect); - - Gdx.gl.glViewport((int)window.x, (int)window.y, (int)window.width, (int)window.height); - - update(true); - - uiMatrix.set(combined); - uiMatrix.setToOrtho2D(getHudLeft(), getHudBottom(), getHudWidth(), getHudHeight()); - uiInvProjMatrix.set(uiMatrix); - Matrix4.inv(uiInvProjMatrix.val); - } - - public float getScreenWidth() - { - return window.width; - } - - public float getScreenHeight() - { - return window.height; - } - - public int getHudLeft() - { - return hudLeft; - } - - public int getHudBottom() - { - return hudBottom; - } - - public int getHudWidth() - { - return (int) window.width - (2 * getHudLeft()); - } - - public int getHudHeight() - { - return (int) window.height - (2 * getHudBottom()); - } - - public void uiUnproject(float x, float y, Vector3 v) - { - x = x - window.x; - y = Gdx.graphics.getHeight() - y - 1; - y = y - window.y; - v.x = (2 * x) / window.width - 1; - v.y = (2 * y) / window.height - 1; - v.z = 2 * v.z - 1; - v.prj(uiInvProjMatrix); - } - - public Matrix4 uiCombined() - { - return uiMatrix; - } -} diff --git a/core/src/ch/asynk/tankontank/screens/MenuScreen.java b/core/src/ch/asynk/tankontank/screens/MenuScreen.java deleted file mode 100644 index 9486413..0000000 --- a/core/src/ch/asynk/tankontank/screens/MenuScreen.java +++ /dev/null @@ -1,264 +0,0 @@ -package ch.asynk.tankontank.screens; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Screen; -import com.badlogic.gdx.InputAdapter; -import com.badlogic.gdx.graphics.GL20; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.math.Vector3; -import com.badlogic.gdx.math.Interpolation; - -import ch.asynk.tankontank.TankOnTank; -import ch.asynk.tankontank.ui.Position; -import ch.asynk.tankontank.menu.MainMenu; -import ch.asynk.tankontank.menu.OptionsMenu; -import ch.asynk.tankontank.menu.ScenariosMenu; -import ch.asynk.tankontank.menu.TutorialsMenu; - -public class MenuScreen implements Screen -{ - private final TankOnTank game; - - private final int OFFSET = 20; - private final int V_WIDTH = 1600; - private final int V_HEIGHT = 1125; - private final int V_CENTER_X = 1000; - private final int V_CENTER_Y = 890; - - private float percent; - private float delay = 0.0f; - private float dx; - private float dy; - private int[] xPath = { 369, 558, 747, 936, 1125, 1030, 936, 1125, 1314, 1408, 1597}; - private int[] yPath = { 565, 565, 565, 565, 565, 729, 892, 892, 892, 1056, 1056}; - private int n = xPath.length; - - private boolean ready; - private boolean gameAssetsLoading; - private Texture bg; - - private Sprite unit; - private Sprite move; - private Sprite from; - private Sprite to; - private Sprite geFlag; - private Sprite usFlag; - private Sprite lnl; - private Sprite logo; - - private MainMenu mainMenu; - private OptionsMenu optionsMenu; - private ScenariosMenu scenariosMenu; - private TutorialsMenu tutorialsMenu; - - private final MenuCamera camera; - private final SpriteBatch batch; - private Vector3 touch = new Vector3(); - - public MenuScreen(final TankOnTank game) - { - this.game = game; - this.batch = new SpriteBatch(); - - float width = Gdx.graphics.getWidth(); - float height = Gdx.graphics.getHeight(); - - this.camera = new MenuCamera(V_CENTER_X, V_CENTER_Y, V_WIDTH, V_HEIGHT, game.hudCorrection); - - this.gameAssetsLoading = false; - - this.bg = game.manager.get("data/map_a.png", Texture.class); - - this.unit = new Sprite(game.menuAtlas.findRegion("unit")); - this.move = new Sprite(game.menuAtlas.findRegion("move")); - this.from = new Sprite(game.menuAtlas.findRegion("from")); - this.to = new Sprite(game.menuAtlas.findRegion("to")); - this.usFlag = new Sprite(game.menuAtlas.findRegion("us-flag")); - this.geFlag = new Sprite(game.menuAtlas.findRegion("ge-flag")); - this.lnl = new Sprite(game.menuAtlas.findRegion("lnl")); - this.logo = new Sprite(game.menuAtlas.findRegion("logo")); - - this.mainMenu = new MainMenu(game.fontB, game.uiAtlas); - this.optionsMenu = new OptionsMenu(game, game.fontB, game.uiAtlas); - this.scenariosMenu = new ScenariosMenu(game, game.fontB, game.uiAtlas); - this.tutorialsMenu = new TutorialsMenu(game, game.fontB, game.uiAtlas); - - this.game.config.battle = null; - - Gdx.input.setInputProcessor(new InputAdapter() { - @Override - public boolean touchDown(int x, int y, int pointer, int button) - { - camera.uiUnproject(x, y, touch); - return hit(touch.x, touch.y); - } - }); - } - - private boolean hit(float x, float y) - { - if (mainMenu.hit(x, y)) { - mainMenu.visible = false; - showNextMenu(); - return true; - } else if (optionsMenu.hit(x, y)) { - mainMenu.visible = true; - optionsMenu.visible = false; - return true; - } else if (scenariosMenu.hit(x, y)) { - mainMenu.visible = true; - scenariosMenu.visible = false; - if (scenariosMenu.launch) - startLoading(); - return true; - } else if (tutorialsMenu.hit(x, y)) { - mainMenu.visible = true; - tutorialsMenu.visible = false; - return true; - } - - return false; - } - - private void showNextMenu() - { - MainMenu.Items item = mainMenu.getMenu(); - - if (item == MainMenu.Items.OPTIONS) - optionsMenu.visible = true; - else if (item == MainMenu.Items.SCENARIOS) - scenariosMenu.visible = true; - else if (item == MainMenu.Items.TUTORIALS) - tutorialsMenu.visible = true; - } - - private void startLoading() - { - mainMenu.visible = false; - game.loadGameAssets(); - gameAssetsLoading = true; - } - - private void gameAssetsLoadingCompleted() - { - TankOnTank.debug("LoadScreen", "assets ready : " + (Gdx.app.getJavaHeap()/1024.0f) + "KB"); - game.switchToGame(); - dispose(); - } - - @Override - public void render(float delta) - { - float x = xPath[0]; - float y = yPath[0]; - if (gameAssetsLoading) { - if (game.manager.update()) { - delay += delta; - if (delay >= 0.6f) - gameAssetsLoadingCompleted(); - } - - percent = Interpolation.linear.apply(percent, game.manager.getProgress(), 0.1f); - int idx = (int) (percent * 10); - float fraction = ((percent * 100 ) % 10 / 10); - x = (xPath[idx] + ((xPath[idx + 1] - xPath[idx]) * fraction)); - y = (yPath[idx] + ((yPath[idx + 1] - yPath[idx]) * fraction)); - } - - Gdx.gl.glClearColor(0, 0, 0, 1); - Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); - - batch.setProjectionMatrix(camera.combined); - batch.begin(); - batch.draw(bg, 0, 0); - from.draw(batch); - to.draw(batch); - usFlag.draw(batch); - geFlag.draw(batch); - for (int i = 1; i < (n - 1); i++) - drawCentered(batch, move, xPath[i], yPath[i]); - drawCentered(batch, unit, (int) (x + dx), (int) (y + dy)); - batch.end(); - - batch.setProjectionMatrix(camera.uiCombined()); - batch.begin(); - batch.draw(logo, OFFSET, (camera.getScreenHeight() - logo.getRegionHeight() - OFFSET)); - batch.draw(lnl, (camera.getScreenWidth() - lnl.getRegionWidth() - (2 * OFFSET)), (2 * OFFSET)); - mainMenu.draw(batch); - optionsMenu.draw(batch); - scenariosMenu.draw(batch); - tutorialsMenu.draw(batch); - batch.end(); - } - - private void drawCentered(SpriteBatch batch, TextureRegion region, int x, int y) - { - batch.draw(region, (x - (region.getRegionWidth() / 2f)), (y - (region.getRegionHeight() / 2f))); - } - - private void setCenteredPosition(Sprite sprite, int x, int y) - { - sprite.setPosition((x - (sprite.getWidth() / 2f)), (y - (sprite.getHeight() / 2f))); - } - - private void update(int width, int height) - { - camera.updateViewport(width, height); - Position.update(camera.getHudLeft(), camera.getHudBottom(), camera.getHudWidth(), camera.getHudHeight()); - - setCenteredPosition(from, xPath[0], yPath[0]); - setCenteredPosition(to, xPath[n - 1], yPath[n - 1]); - setCenteredPosition(usFlag, xPath[0], yPath[0]); - setCenteredPosition(geFlag, xPath[n - 1], yPath[n - 1]); - - mainMenu.setPosition(); - optionsMenu.setPosition(); - scenariosMenu.setPosition(); - tutorialsMenu.setPosition(); - } - - @Override - public void resize(int width, int height) - { - update(width, height); - } - - @Override - public void dispose() - { - mainMenu.dispose(); - optionsMenu.dispose(); - scenariosMenu.dispose(); - tutorialsMenu.dispose(); - } - - @Override - public void show() - { - int width = (int) Gdx.graphics.getWidth(); - int height = (int) Gdx.graphics.getHeight(); - update(width, height); - } - - @Override - public void hide() - { - // TankOnTank.debug("MenuScreen", "hide()"); - } - - @Override - public void pause() - { - // TankOnTank.debug("MenuScreen", "pause()"); - } - - @Override - public void resume() - { - // TankOnTank.debug("MenuScreen", "resume()"); - } -} diff --git a/core/src/ch/asynk/tankontank/ui/Bg.java b/core/src/ch/asynk/tankontank/ui/Bg.java deleted file mode 100644 index 7a87c26..0000000 --- a/core/src/ch/asynk/tankontank/ui/Bg.java +++ /dev/null @@ -1,28 +0,0 @@ -package ch.asynk.tankontank.ui; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; - -public class Bg extends Widget -{ - private TextureRegion region; - - public Bg(TextureRegion region) - { - super(); - this.region = region; - setPosition(0, 0, region.getRegionWidth(), region.getRegionHeight()); - } - - @Override - public void dispose() - { - } - - @Override - public void draw(Batch batch) - { - if (!visible) return; - batch.draw(region, rect.x, rect.y, rect.width, rect.height); - } -} diff --git a/core/src/ch/asynk/tankontank/ui/Label.java b/core/src/ch/asynk/tankontank/ui/Label.java deleted file mode 100644 index 041f44d..0000000 --- a/core/src/ch/asynk/tankontank/ui/Label.java +++ /dev/null @@ -1,72 +0,0 @@ -package ch.asynk.tankontank.ui; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.GlyphLayout; - -public class Label extends Widget -{ - private BitmapFont font; - private GlyphLayout layout; - private float dx; - private float dy; - protected String text; - - public Label(BitmapFont font) - { - this(font, 0f); - } - - public Label(BitmapFont font, float padding) - { - this(font, padding, Position.MIDDLE_CENTER); - } - - public Label(BitmapFont font, float padding, Position position) - { - super(); - this.font = font; - this.padding = padding; - this.position = position; - this.layout = new GlyphLayout(); - } - - @Override - public void dispose() - { - } - - @Override - public void translate(float dx, float dy) - { - setPosition((rect.x + dx), (rect.y + dy)); - } - - @Override - public void setPosition(float x, float y) - { - this.layout.setText(font, (text == null) ? "" : text); - setPosition(x, y, (layout.width + (2 * padding)), (layout.height + (2 * padding))); - this.dx = (x + padding); - this.dy = (y + padding + layout.height); - } - - public void write(String text) - { - this.text = text; - setPosition(position); - } - - public void write(String text, float x, float y) - { - this.text = text; - setPosition(x, y); - } - - @Override - public void draw(Batch batch) - { - if (!visible) return; - font.draw(batch, layout, dx, dy); - } -} diff --git a/core/src/ch/asynk/tankontank/ui/LabelImage.java b/core/src/ch/asynk/tankontank/ui/LabelImage.java deleted file mode 100644 index 4f28924..0000000 --- a/core/src/ch/asynk/tankontank/ui/LabelImage.java +++ /dev/null @@ -1,72 +0,0 @@ -package ch.asynk.tankontank.ui; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -public class LabelImage extends Bg -{ - private Label label; - - public LabelImage(TextureRegion region, BitmapFont font) - { - this(region, font, 0f); - } - - public LabelImage(TextureRegion region, BitmapFont font, float padding) - { - this(region, font, padding, Position.MIDDLE_CENTER); - } - - public LabelImage(TextureRegion region, BitmapFont font, float padding, Position position) - { - super(region); - this.label = new Label(font, padding, position); - } - - @Override - public void dispose() - { - label.dispose(); - } - - @Override - public void translate(float dx, float dy) - { - super.translate(dx, dy); - label.translate(dx, dy); - } - - public void setPosition(float x, float y) - { - super.setPosition(x, y); - label.setPosition(x, y); - } - - public void setLabelPosition(Position position) - { - label.setPosition(position, this); - } - - public void write(String text) - { - this.label.write(text); - } - - @Override - public void draw(Batch batch) - { - if (!visible) return; - super.draw(batch); - label.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer shapes) - { - if (!visible) return; - super.drawDebug(shapes); - label.drawDebug(shapes); - } -} diff --git a/core/src/ch/asynk/tankontank/ui/LabelStack.java b/core/src/ch/asynk/tankontank/ui/LabelStack.java deleted file mode 100644 index f730d0d..0000000 --- a/core/src/ch/asynk/tankontank/ui/LabelStack.java +++ /dev/null @@ -1,72 +0,0 @@ -package ch.asynk.tankontank.ui; - -import java.util.ArrayDeque; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.BitmapFont; - -import ch.asynk.tankontank.engine.gfx.Animation; - -public class LabelStack extends Label implements Animation -{ - class MsgInfo - { - String text; - float duration; - Position position; - MsgInfo(String text, float duration, Position position) - { - this.text = text; - this.duration = duration; - this.position = position; - } - } - - private float duration; - private float elapsed; - private ArrayDeque stack; - - public LabelStack(BitmapFont font, float padding) - { - super(font, padding); - this.visible = false; - this.stack = new ArrayDeque(); - } - - public void pushWrite(String text, float duration, Position position) - { - if (visible) - stack.push(new MsgInfo(text, duration, position)); - else - write(text, duration, position); - } - - public void write(String text, float duration, Position position) - { - this.position = position; - write(text, duration); - } - - public void write(String text, float duration) - { - this.duration = duration; - this.visible = true; - this.elapsed = 0f; - write(text); - } - - @Override - public boolean animate(float delta) - { - if (!visible) return true; - elapsed += delta; - if (elapsed >= duration) { - visible = false; - if (stack.size() > 0) { - MsgInfo info = stack.pop(); - write(info.text, info.duration, info.position); - } - } - return false; - } -} diff --git a/core/src/ch/asynk/tankontank/ui/Menu.java b/core/src/ch/asynk/tankontank/ui/Menu.java deleted file mode 100644 index 1cd61ca..0000000 --- a/core/src/ch/asynk/tankontank/ui/Menu.java +++ /dev/null @@ -1,93 +0,0 @@ -package ch.asynk.tankontank.ui; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.NinePatch; - -public class Menu extends Patch -{ - public static int PADDING = 40; - public static int VSPACING = 8; - - protected Label []labels; - - public interface MenuItem - { - public int last(); - public int i(); - }; - - protected MenuItem menuItem; - - public Menu(MenuItem menuItem, BitmapFont font, NinePatch ninePatch) - { - super(ninePatch); - this.menuItem = menuItem; - this.labels = new Label[menuItem.last()]; - for (int i = 0; i< menuItem.last(); i ++) - labels[i] = new Label(font, 10); - } - - protected Label label(MenuItem m) - { - return labels[m.i()]; - } - - protected float widestLabel() - { - float w = 0f; - for (int i = 0; i< menuItem.last(); i ++) { - float t = labels[i].getWidth(); - if (t> w) - w = t; - } - return w; - } - - protected float highestLabel() - { - float h = 0f; - for (int i = 0; i< menuItem.last(); i ++) { - float t = labels[i].getHeight(); - if (t> h) - h = t; - } - return h; - } - - public void setPosition() - { - float lh = highestLabel(); - float h = ((menuItem.last() * lh) + (2 * PADDING) + ((menuItem.last() - 1) * VSPACING)); - float w = (widestLabel() + (2 * PADDING)); - float x = position.getX(w); - float y = position.getY(h); - setPosition(x, y, w, h); - - y += PADDING; - x += PADDING; - float dy = (VSPACING + lh); - - for (int i = 0; i< menuItem.last(); i ++) { - labels[i].setPosition(x, y); - y += dy; - } - } - - @Override - public void dispose() - { - super.dispose(); - for (int i = 0; i < menuItem.last(); i ++) - labels[i].dispose(); - } - - @Override - public void draw(Batch batch) - { - if (!visible) return; - super.draw(batch); - for (int i = 0; i < menuItem.last(); i ++) - labels[i].draw(batch); - } -} diff --git a/core/src/ch/asynk/tankontank/ui/Msg.java b/core/src/ch/asynk/tankontank/ui/Msg.java deleted file mode 100644 index c2069b7..0000000 --- a/core/src/ch/asynk/tankontank/ui/Msg.java +++ /dev/null @@ -1,79 +0,0 @@ -package ch.asynk.tankontank.ui; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -public class Msg extends Patch -{ - private LabelStack label; - - public Msg(BitmapFont font, TextureAtlas atlas) - { - super(atlas.createPatch("typewriter")); - label = new LabelStack(font, 20f); - } - - @Override - public void dispose() - { - super.dispose(); - label.dispose(); - } - - public void updatePosition() - { - if (!visible) return; - float dx = (position.getX(rect.width) - rect.x); - float dy = (position.getY(rect.height) - rect.y); - translate(dx, dy); - label.translate(dx, dy); - } - - public void write(String text, float duration) - { - label.write(text, duration); - resize(); - } - - public void write(String text, float duration, Position position) - { - this.position = position; - label.write(text, duration, position); - resize(); - } - - public void pushWrite(String text, float duration, Position position) - { - this.position = position; - label.pushWrite(text, duration, position); - resize(); - } - - private void resize() - { - setPosition(label.getX(), label.getY(), label.getWidth(), label.getHeight()); - } - - public boolean animate(float delta) - { - return label.animate(delta); - } - - @Override - public void draw(Batch batch) - { - if (!label.visible) return; - super.draw(batch); - label.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer shapes) - { - if (!label.visible) return; - super.drawDebug(shapes); - label.drawDebug(shapes); - } -} diff --git a/core/src/ch/asynk/tankontank/ui/OkCancel.java b/core/src/ch/asynk/tankontank/ui/OkCancel.java deleted file mode 100644 index ba61642..0000000 --- a/core/src/ch/asynk/tankontank/ui/OkCancel.java +++ /dev/null @@ -1,115 +0,0 @@ -package ch.asynk.tankontank.ui; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -public class OkCancel extends Patch -{ - public static int PADDING = 20; - public static int VSPACING = 10; - public static int HSPACING = 10; - - public boolean ok; - protected Label label; - protected Bg okBtn; - protected Bg cancelBtn; - - public OkCancel(BitmapFont font, TextureAtlas atlas) - { - super(atlas.createPatch("typewriter")); - this.label = new Label(font); - this.okBtn = new Bg(atlas.findRegion("ok")); - this.cancelBtn = new Bg(atlas.findRegion("cancel")); - this.visible = false; - } - - public void updatePosition() - { - if (!visible) return; - float dx = (position.getX(rect.width) - rect.x); - float dy = (position.getY(rect.height) - rect.y); - translate(dx, dy); - label.translate(dx, dy); - okBtn.translate(dx, dy); - cancelBtn.translate(dx, dy); - } - - public void show(String msg) - { - show(msg, Position.MIDDLE_CENTER); - } - - public void show(String msg, Position position) - { - label.write(msg); - - float height = (label.getHeight() + okBtn.getHeight() + (2 * PADDING) + (2 * VSPACING)); - float width = (label.getWidth() + (2 * PADDING)); - float w2 = (okBtn.getWidth() + cancelBtn.getWidth() + (2 * PADDING) + (1 * HSPACING)); - if (w2 > width) - width = w2; - float x = position.getX(width); - float y = position.getY(height); - setPosition(x, y, width, height); - - okBtn.setPosition((x + width - okBtn.getWidth() - PADDING), (y + PADDING)); - cancelBtn.setPosition((x + PADDING), okBtn.getY()); - label.setPosition((x + PADDING), (y + PADDING + okBtn.getHeight() + VSPACING)); - cancelBtn.visible = true; - visible = true; - ok = false; - } - - public void noCancel() - { - cancelBtn.visible = false; - } - - @Override - public boolean hit(float x, float y) - { - if (!cancelBtn.visible && super.hit(x, y)) { - ok = true; - return true; - } - if (okBtn.hit(x, y)) { - ok = true; - return true; - } else if (cancelBtn.hit(x, y)) { - ok = false; - return true; - } - return false; - } - - @Override - public void dispose() - { - super.dispose(); - label.dispose(); - okBtn.dispose(); - cancelBtn.dispose(); - } - - @Override - public void draw(Batch batch) - { - if (!visible) return; - super.draw(batch); - label.draw(batch); - okBtn.draw(batch); - cancelBtn.draw(batch); - } - - @Override - public void drawDebug(ShapeRenderer shapes) - { - if (!visible) return; - super.drawDebug(shapes); - label.drawDebug(shapes); - okBtn.drawDebug(shapes); - cancelBtn.drawDebug(shapes); - } -} diff --git a/core/src/ch/asynk/tankontank/ui/Patch.java b/core/src/ch/asynk/tankontank/ui/Patch.java deleted file mode 100644 index 4056a3c..0000000 --- a/core/src/ch/asynk/tankontank/ui/Patch.java +++ /dev/null @@ -1,28 +0,0 @@ -package ch.asynk.tankontank.ui; - -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.NinePatch; - -public class Patch extends Widget -{ - private NinePatch patch; - - public Patch(NinePatch patch) - { - super(); - this.patch = patch; - setPosition(0, 0, patch.getTotalWidth(), patch.getTotalHeight()); - } - - @Override - public void dispose() - { - } - - @Override - public void draw(Batch batch) - { - if (!visible) return; - patch.draw(batch, rect.x, rect.y, rect.width, rect.height); - } -} diff --git a/core/src/ch/asynk/tankontank/ui/Position.java b/core/src/ch/asynk/tankontank/ui/Position.java deleted file mode 100644 index 1257cb6..0000000 --- a/core/src/ch/asynk/tankontank/ui/Position.java +++ /dev/null @@ -1,239 +0,0 @@ -package ch.asynk.tankontank.ui; - -import com.badlogic.gdx.Gdx; -import ch.asynk.tankontank.game.Hud; - -public enum Position -{ - TOP_LEFT, - TOP_RIGHT, - TOP_CENTER, - MIDDLE_LEFT, - MIDDLE_RIGHT, - MIDDLE_CENTER, - BOTTOM_LEFT, - BOTTOM_RIGHT, - BOTTOM_CENTER; - - public Position verticalMirror() - { - Position p = this; - switch(this) { - case TOP_LEFT: - p = TOP_RIGHT; - break; - case MIDDLE_LEFT: - p = MIDDLE_RIGHT; - break; - case BOTTOM_LEFT: - p = BOTTOM_RIGHT; - break; - case TOP_RIGHT: - p = TOP_LEFT; - break; - case MIDDLE_RIGHT: - p = MIDDLE_LEFT; - break; - case BOTTOM_RIGHT: - p = BOTTOM_LEFT; - break; - } - return p; - } - - public Position horizontalMirror() - { - Position p = this; - switch(this) { - case TOP_LEFT: - p = BOTTOM_LEFT; - break; - case TOP_CENTER: - p = BOTTOM_CENTER; - break; - case TOP_RIGHT: - p = BOTTOM_RIGHT; - break; - case BOTTOM_LEFT: - p = TOP_LEFT; - break; - case BOTTOM_CENTER: - p = TOP_CENTER; - break; - case BOTTOM_RIGHT: - p = TOP_RIGHT; - break; - } - return p; - } - - public boolean isLeft() - { - boolean r = false; - switch(this) { - case TOP_LEFT: - case MIDDLE_LEFT: - case BOTTOM_LEFT: - r = true; - break; - default: - r = false; - break; - } - return r; - } - - public boolean isRight() - { - boolean r = false; - switch(this) { - case TOP_RIGHT: - case MIDDLE_RIGHT: - case BOTTOM_RIGHT: - r = true; - break; - default: - r = false; - break; - } - return r; - } - - public boolean isCenter() - { - boolean r = false; - switch(this) { - case TOP_CENTER: - case MIDDLE_CENTER: - case BOTTOM_CENTER: - r = true; - break; - default: - r = false; - break; - } - return r; - } - - private static int hudLeft = 0; - private static int hudBottom = 0; - private static int hudWidth = Gdx.graphics.getWidth(); - private static int hudHeight = Gdx.graphics.getHeight(); - - public static void update(int width, int height) - { - update(0, 0, width, height); - } - - public static void update(int left, int bottom, int width, int height) - { - hudLeft = left; - hudBottom = bottom; - hudWidth = width; - hudHeight = height; - } - - public float getX(float width) - { - float x = hudLeft; - switch(this) { - case TOP_LEFT: - case MIDDLE_LEFT: - case BOTTOM_LEFT: - x += Hud.OFFSET; - break; - case TOP_CENTER: - case MIDDLE_CENTER: - case BOTTOM_CENTER: - x += ((hudWidth - width) / 2); - break; - case TOP_RIGHT: - case MIDDLE_RIGHT: - case BOTTOM_RIGHT: - x += (hudWidth - width - Hud.OFFSET); - break; - default: - x += ((hudWidth - width) / 2); - break; - } - return x; - } - - public float getY(float height) - { - float y = hudBottom; - switch(this) { - case TOP_LEFT: - case TOP_CENTER: - case TOP_RIGHT: - y += (hudHeight - height - Hud.OFFSET); - break; - case MIDDLE_LEFT: - case MIDDLE_CENTER: - case MIDDLE_RIGHT: - y += ((hudHeight - height) / 2); - break; - case BOTTOM_LEFT: - case BOTTOM_CENTER: - case BOTTOM_RIGHT: - y += Hud.OFFSET; - break; - default: - y += ((hudHeight - height) / 2); - break; - } - return y; - } - - public float getX(Widget widget, float width) - { - float x = 0; - switch(this) { - case TOP_LEFT: - case MIDDLE_LEFT: - case BOTTOM_LEFT: - x = widget.getX(); - break; - case TOP_CENTER: - case MIDDLE_CENTER: - case BOTTOM_CENTER: - x = (widget.getX() + ((widget.getWidth() - width) / 2)); - break; - case TOP_RIGHT: - case MIDDLE_RIGHT: - case BOTTOM_RIGHT: - x = (widget.getX() + widget.getWidth() - width); - break; - default: - x = (widget.getX() + ((widget.getWidth() - width) / 2)); - break; - } - return x; - } - - public float getY(Widget widget, float height) - { - float y = 0; - switch(this) { - case TOP_LEFT: - case TOP_CENTER: - case TOP_RIGHT: - y = (widget.getY() + widget.getHeight() - height); - break; - case MIDDLE_LEFT: - case MIDDLE_CENTER: - case MIDDLE_RIGHT: - y = (widget.getY() + ((widget.getHeight() - height) / 2)); - break; - case BOTTOM_LEFT: - case BOTTOM_CENTER: - case BOTTOM_RIGHT: - y = widget.getY(); - break; - default: - y = (widget.getY() + ((widget.getHeight() - height) / 2)); - break; - } - return y; - } -} diff --git a/core/src/ch/asynk/tankontank/ui/Widget.java b/core/src/ch/asynk/tankontank/ui/Widget.java deleted file mode 100644 index e49833a..0000000 --- a/core/src/ch/asynk/tankontank/ui/Widget.java +++ /dev/null @@ -1,93 +0,0 @@ -package ch.asynk.tankontank.ui; - -import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; - -import ch.asynk.tankontank.engine.gfx.Drawable; - -public abstract class Widget implements Disposable, Drawable -{ - public boolean blocked; - public boolean visible; - protected float padding; - protected Rectangle rect; - protected Position position; - protected Widget parent; - - protected Widget() - { - this.parent = null; - this.blocked = false; - this.visible = true; - this.padding = 0f; - this.rect = new Rectangle(0, 0, 0, 0); - this.position = Position.MIDDLE_CENTER; - } - - public float getX() { return rect.x; } - public float getY() { return rect.y; } - public float getWidth() { return rect.width; } - public float getHeight() { return rect.height; } - - public void translate(float dx, float dy) - { - rect.x += dx; - rect.y += dy; - } - - public void setPosition(Rectangle r) - { - rect.set(r); - } - - public void setPosition(float x, float y) - { - rect.x = x; - rect.y = y; - } - - public void setPosition(float x, float y, float w, float h) - { - rect.set(x, y, w, h); - } - - public void setPosition(Position position) - { - this.position = position; - setParent(this.parent); - } - - public void setPosition(Position position, Widget parent) - { - this.position = position; - setParent(parent); - } - - public void setParent(Widget parent) - { - this.parent = parent; - if (parent == null) { - rect.x = position.getX(rect.width); - rect.y = position.getY(rect.height); - } else { - rect.x = position.getX(parent, rect.width); - rect.y = position.getY(parent, rect.height); - } - // might trigger something if overriden - setPosition(rect.x, rect.y); - } - - public boolean hit(float x, float y) - { - if (blocked || !visible) return false; - return rect.contains(x, y); - } - - @Override - public void drawDebug(ShapeRenderer shapes) - { - if (!visible) return; - shapes.rect(rect.x, rect.y, rect.width, rect.height); - } -} diff --git a/core/test/ch/asynk/tankontank/BoardUtils.java b/core/test/ch/asynk/tankontank/BoardUtils.java index e18b9d1..215a9e5 100644 --- a/core/test/ch/asynk/tankontank/BoardUtils.java +++ b/core/test/ch/asynk/tankontank/BoardUtils.java @@ -1,4 +1,4 @@ -package ch.asynk.tankontank; +package ch.asynk.creepingarmor; import java.util.List; import java.util.ArrayList; @@ -7,8 +7,8 @@ import java.util.HashSet; import org.junit.Test; import org.junit.Before; -import ch.asynk.tankontank.engine.Tile; -import ch.asynk.tankontank.engine.Path; +import ch.asynk.creepingarmor.engine.Tile; +import ch.asynk.creepingarmor.engine.Path; import static org.junit.Assert.assertTrue; diff --git a/core/test/ch/asynk/tankontank/Helpers.java b/core/test/ch/asynk/tankontank/Helpers.java index dcde75f..2781fed 100644 --- a/core/test/ch/asynk/tankontank/Helpers.java +++ b/core/test/ch/asynk/tankontank/Helpers.java @@ -1,15 +1,15 @@ -package ch.asynk.tankontank; +package ch.asynk.creepingarmor; import java.util.List; import java.util.ArrayList; import java.util.HashSet; -import ch.asynk.tankontank.engine.Pawn; -import ch.asynk.tankontank.engine.Tile; -import ch.asynk.tankontank.engine.Board; -import ch.asynk.tankontank.engine.Orientation; -import ch.asynk.tankontank.engine.SearchBoard; -import ch.asynk.tankontank.engine.PathBuilder; +import ch.asynk.creepingarmor.engine.Pawn; +import ch.asynk.creepingarmor.engine.Tile; +import ch.asynk.creepingarmor.engine.Board; +import ch.asynk.creepingarmor.engine.Orientation; +import ch.asynk.creepingarmor.engine.SearchBoard; +import ch.asynk.creepingarmor.engine.PathBuilder; public class Helpers { diff --git a/core/test/ch/asynk/tankontank/LineOfSightTest.java b/core/test/ch/asynk/tankontank/LineOfSightTest.java index ee8d629..07f7a45 100644 --- a/core/test/ch/asynk/tankontank/LineOfSightTest.java +++ b/core/test/ch/asynk/tankontank/LineOfSightTest.java @@ -1,12 +1,12 @@ -package ch.asynk.tankontank; +package ch.asynk.creepingarmor; import java.util.List; import org.junit.Test; import org.junit.Before; -import ch.asynk.tankontank.engine.SearchBoard; -import ch.asynk.tankontank.engine.SearchBoard.Node; +import ch.asynk.creepingarmor.engine.SearchBoard; +import ch.asynk.creepingarmor.engine.SearchBoard.Node; import static org.junit.Assert.assertTrue; diff --git a/desktop/build.gradle b/desktop/build.gradle index c16064c..4129d73 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -3,7 +3,7 @@ apply plugin: "java" sourceCompatibility = 1.7 sourceSets.main.java.srcDirs = [ "src/" ] -project.ext.mainClassName = "ch.asynk.tankontank.desktop.DesktopLauncher" +project.ext.mainClassName = "ch.asynk.creepingarmor.desktop.DesktopLauncher" project.ext.assetsDir = new File("../android/assets"); task run(dependsOn: classes, type: JavaExec) { diff --git a/desktop/src/ch/asynk/tankontank/desktop/DesktopLauncher.java b/desktop/src/ch/asynk/tankontank/desktop/DesktopLauncher.java index 6e86535..127f995 100644 --- a/desktop/src/ch/asynk/tankontank/desktop/DesktopLauncher.java +++ b/desktop/src/ch/asynk/tankontank/desktop/DesktopLauncher.java @@ -1,18 +1,18 @@ -package ch.asynk.tankontank.desktop; +package ch.asynk.creepingarmor.desktop; import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; import com.badlogic.gdx.Files; -import ch.asynk.tankontank.TankOnTank; +import ch.asynk.creepingarmor.CreepingArmor; public class DesktopLauncher { public static void main (String[] arg) { LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); - config.title = "Tank On Tank"; + config.title = "Creeping Armor"; config.width = 1024; config.height = 768; // config.fullscreen = true; config.addIcon("data/icon.png", Files.FileType.Internal); - new LwjglApplication(new TankOnTank(), config); + new LwjglApplication(new CreepingArmor(), config); } } diff --git a/html/build.gradle b/html/build.gradle index 9f7b699..174f80b 100644 --- a/html/build.gradle +++ b/html/build.gradle @@ -7,8 +7,8 @@ gwt { minHeapSize="1G" src = files(file("src/")) // Needs to be in front of "modules" below. - modules 'ch.asynk.tankontank.GdxDefinition' - devModules 'ch.asynk.tankontank.GdxDefinitionSuperdev' + modules 'ch.asynk.creepingarmor.GdxDefinition' + devModules 'ch.asynk.creepingarmor.GdxDefinitionSuperdev' project.webAppDirName = 'webapp' compiler { diff --git a/html/src/ch/asynk/tankontank/GdxDefinition.gwt.xml b/html/src/ch/asynk/tankontank/GdxDefinition.gwt.xml index 6f24d10..8f9d33b 100644 --- a/html/src/ch/asynk/tankontank/GdxDefinition.gwt.xml +++ b/html/src/ch/asynk/tankontank/GdxDefinition.gwt.xml @@ -4,8 +4,8 @@ - - + + diff --git a/html/src/ch/asynk/tankontank/GdxDefinitionSuperdev.gwt.xml b/html/src/ch/asynk/tankontank/GdxDefinitionSuperdev.gwt.xml index 2d4cf8c..d557126 100644 --- a/html/src/ch/asynk/tankontank/GdxDefinitionSuperdev.gwt.xml +++ b/html/src/ch/asynk/tankontank/GdxDefinitionSuperdev.gwt.xml @@ -4,8 +4,8 @@ - - + + diff --git a/html/src/ch/asynk/tankontank/client/HtmlLauncher.java b/html/src/ch/asynk/tankontank/client/HtmlLauncher.java index 70b4814..a766198 100644 --- a/html/src/ch/asynk/tankontank/client/HtmlLauncher.java +++ b/html/src/ch/asynk/tankontank/client/HtmlLauncher.java @@ -1,9 +1,9 @@ -package ch.asynk.tankontank.client; +package ch.asynk.creepingarmor.client; import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.backends.gwt.GwtApplication; import com.badlogic.gdx.backends.gwt.GwtApplicationConfiguration; -import ch.asynk.tankontank.TankOnTank; +import ch.asynk.creepingarmor.CreepingArmor; public class HtmlLauncher extends GwtApplication { @@ -14,6 +14,6 @@ public class HtmlLauncher extends GwtApplication { @Override public ApplicationListener getApplicationListener () { - return new TankOnTank(); + return new CreepingArmor(); } } \ No newline at end of file diff --git a/html/webapp/index.html b/html/webapp/index.html index 87549fc..235926f 100644 --- a/html/webapp/index.html +++ b/html/webapp/index.html @@ -1,7 +1,7 @@ - TankOnTank + CreepingArmor diff --git a/ios/build.gradle b/ios/build.gradle index 4bbbefe..8ade426 100644 --- a/ios/build.gradle +++ b/ios/build.gradle @@ -4,7 +4,7 @@ sourceCompatibility = '1.7' [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' ext { - mainClassName = "ch.asynk.tankontank.IOSLauncher" + mainClassName = "ch.asynk.creepingarmor.IOSLauncher" } // Extracts native libs (*.a) from the native-ios.jar and places them diff --git a/ios/robovm.properties b/ios/robovm.properties index 12ffe95..529e500 100644 --- a/ios/robovm.properties +++ b/ios/robovm.properties @@ -1,6 +1,6 @@ app.version=1.0 -app.id=ch.asynk.tankontank.IOSLauncher -app.mainclass=ch.asynk.tankontank.IOSLauncher +app.id=ch.asynk.creepingarmor.IOSLauncher +app.mainclass=ch.asynk.creepingarmor.IOSLauncher app.executable=IOSLauncher app.build=1 -app.name=TankOnTank +app.name=CreepingArmor diff --git a/ios/src/ch/asynk/tankontank/IOSLauncher.java b/ios/src/ch/asynk/tankontank/IOSLauncher.java index e9636d9..f49e6b2 100644 --- a/ios/src/ch/asynk/tankontank/IOSLauncher.java +++ b/ios/src/ch/asynk/tankontank/IOSLauncher.java @@ -1,17 +1,17 @@ -package ch.asynk.tankontank; +package ch.asynk.creepingarmor; import org.robovm.apple.foundation.NSAutoreleasePool; import org.robovm.apple.uikit.UIApplication; import com.badlogic.gdx.backends.iosrobovm.IOSApplication; import com.badlogic.gdx.backends.iosrobovm.IOSApplicationConfiguration; -import ch.asynk.tankontank.TankOnTank; +import ch.asynk.creepingarmor.CreepingArmor; public class IOSLauncher extends IOSApplication.Delegate { @Override protected IOSApplication createApplication() { IOSApplicationConfiguration config = new IOSApplicationConfiguration(); - return new IOSApplication(new TankOnTank(), config); + return new IOSApplication(new CreepingArmor(), config); } public static void main(String[] argv) { diff --git a/run b/run index 4c60f55..2640b0a 100755 --- a/run +++ b/run @@ -34,7 +34,7 @@ case "$1" in shift; ARGS="desktop:dist $@" gradlew_do - scp ./desktop/build/libs/desktop-1.0.jar erratic:/var/www/public/TankOnTank.jar + scp ./desktop/build/libs/desktop-1.0.jar erratic:/var/www/public/CreepingArmor.jar ;; "f") # java -cp gdx.jar:gdx-natives.jar:gdx-backend-lwjgl.jar:gdx-backend-lwjgl-natives.jar:extensions/gdx-tools/gdx-tools.jar:hiero.jar com.badlogic.gdx.tools.hiero.Hiero diff --git a/tools/debug_pools.patch b/tools/debug_pools.patch index fffb0fc..db732f4 100644 --- a/tools/debug_pools.patch +++ b/tools/debug_pools.patch @@ -1,7 +1,7 @@ -diff --git a/core/src/ch/asynk/tankontank/engine/Move.java b/core/src/ch/asynk/tankontank/engine/Move.java +diff --git a/core/src/ch/asynk/creepingarmor/engine/Move.java b/core/src/ch/asynk/creepingarmor/engine/Move.java index 06035c3..1bb55b1 100644 ---- a/core/src/ch/asynk/tankontank/engine/Move.java -+++ b/core/src/ch/asynk/tankontank/engine/Move.java +--- a/core/src/ch/asynk/creepingarmor/engine/Move.java ++++ b/core/src/ch/asynk/creepingarmor/engine/Move.java @@ -15,12 +15,30 @@ public class Move extends Path implements Iterable EXIT; } @@ -33,10 +33,10 @@ index 06035c3..1bb55b1 100644 }; public static Move get(Pawn pawn, Tile from, Tile to, Orientation orientation, Path path) -diff --git a/core/src/ch/asynk/tankontank/game/Command.java b/core/src/ch/asynk/tankontank/game/Command.java +diff --git a/core/src/ch/asynk/creepingarmor/game/Command.java b/core/src/ch/asynk/creepingarmor/game/Command.java index 0d39e6c..db3c910 100644 ---- a/core/src/ch/asynk/tankontank/game/Command.java -+++ b/core/src/ch/asynk/tankontank/game/Command.java +--- a/core/src/ch/asynk/creepingarmor/game/Command.java ++++ b/core/src/ch/asynk/creepingarmor/game/Command.java @@ -19,12 +19,30 @@ public class Command extends Order END_OF_TURN; } @@ -68,10 +68,10 @@ index 0d39e6c..db3c910 100644 }; public static void clearPool() -diff --git a/core/src/ch/asynk/tankontank/game/Engagement.java b/core/src/ch/asynk/tankontank/game/Engagement.java +diff --git a/core/src/ch/asynk/creepingarmor/game/Engagement.java b/core/src/ch/asynk/creepingarmor/game/Engagement.java index 8f01008..d06ac6d 100644 ---- a/core/src/ch/asynk/tankontank/game/Engagement.java -+++ b/core/src/ch/asynk/tankontank/game/Engagement.java +--- a/core/src/ch/asynk/creepingarmor/game/Engagement.java ++++ b/core/src/ch/asynk/creepingarmor/game/Engagement.java @@ -8,11 +8,29 @@ import com.badlogic.gdx.utils.Disposable; public class Engagement implements Disposable, Pool.Poolable -- cgit v1.1-2-g2b99