diff --git a/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java b/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java index e46912371..2ec175a0e 100644 --- a/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java @@ -1,16 +1,18 @@ package com.csse3200.game.components.maingame; +import com.badlogic.gdx.Input; import com.badlogic.gdx.audio.Sound; -import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.ui.*; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.utils.Array; import com.csse3200.game.GdxGame; import com.csse3200.game.entities.factories.PauseMenuFactory; +import com.csse3200.game.screens.MainGameScreen; import com.csse3200.game.screens.TowerType; import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.ui.ButtonFactory; @@ -27,14 +29,15 @@ public class MainGameDisplay extends UIComponent { private static final float Z_INDEX = 2f; private final Table towerTable = new Table(); private final Table buttonTable = new Table(); - private String[] sounds = { + private final String[] sounds = { "sounds/ui/click/click_01.ogg", "sounds/ui/open_close/open_01.ogg" }; private Sound click; private Sound openSound; - private GdxGame game; + private final GdxGame game; private Array towers = new Array<>(); + private final Array towerButtons = new Array<>(); private ImageButton tower1; private ImageButton tower2; private ImageButton tower3; @@ -107,10 +110,16 @@ private void addActors() { ServiceLocator.setTowerTypes(towers); tower1 = new ImageButton(skin, towers.get(0).getSkinName()); + towerButtons.add(tower1); tower2 = new ImageButton(skin, towers.get(1).getSkinName()); + towerButtons.add(tower2); tower3 = new ImageButton(skin, towers.get(2).getSkinName()); + towerButtons.add(tower3); tower4 = new ImageButton(skin, towers.get(3).getSkinName()); + towerButtons.add(tower4); tower5 = new ImageButton(skin, towers.get(4).getSkinName()); + towerButtons.add(tower5); + TextButton pauseBtn = ButtonFactory.createButton("Pause"); // Spawns a pause menu when the button is pressed. @@ -121,6 +130,23 @@ public void changed(ChangeEvent changeEvent, Actor actor) { logger.debug("Pause button clicked"); openSound.play(0.4f); PauseMenuFactory.createPauseMenu(game); + ServiceLocator.getTimeSource().setPaused(true); + } + }); + + // Pause menu escape key opening listener + stage.addListener( + new InputListener() { + @Override + public boolean keyUp(InputEvent event, int keycode) { + if ((keycode == Input.Keys.ESCAPE) && !ServiceLocator.getTimeSource().getPaused()) { + game.getScreen().pause(); + openSound.play(0.4f); + PauseMenuFactory.createPauseMenu(game); + ServiceLocator.getTimeSource().setPaused(true); + return true; + } + return false; } }); @@ -133,15 +159,14 @@ public void clicked(InputEvent event, float x, float y) { TowerType selected = ServiceLocator.getCurrencyService().getTower(); if (selected == towers.get(0) ) { ServiceLocator.getCurrencyService().setTowerType(null); - tower1.setChecked(false); + + towerToggle(null); } else { ServiceLocator.getCurrencyService().setTowerType(towers.get(0)); - tower1.setChecked(true); - tower2.setChecked(false); - tower3.setChecked(false); - tower4.setChecked(false); - tower5.setChecked(false); + + towerToggle(tower1); + } click.play(0.4f); } @@ -158,14 +183,14 @@ public void clicked(InputEvent event, float x, float y) { TowerType selected = ServiceLocator.getCurrencyService().getTower(); if (selected == towers.get(1) ) { ServiceLocator.getCurrencyService().setTowerType(null); - tower2.setChecked(false); + + towerToggle(null); + } else { ServiceLocator.getCurrencyService().setTowerType(towers.get(1)); - tower1.setChecked(false); - tower2.setChecked(true); - tower3.setChecked(false); - tower4.setChecked(false); - tower5.setChecked(false); + + towerToggle(tower2); + } click.play(0.4f); } @@ -181,17 +206,16 @@ public void clicked(InputEvent event, float x, float y) { TowerType selected = ServiceLocator.getCurrencyService().getTower(); if (selected == towers.get(2)) { ServiceLocator.getCurrencyService().setTowerType(null); - tower3.setChecked(false); + + towerToggle(null); + } else { ServiceLocator.getCurrencyService().setTowerType(towers.get(2)); if (ServiceLocator.getCurrencyService().getScrap().getAmount() >= Integer.parseInt(towers.get(2).getPrice())) { - tower3.setDisabled(false); - tower1.setChecked(false); - tower2.setChecked(false); - tower3.setChecked(true); - tower4.setChecked(false); - tower5.setChecked(false); + + towerToggle(tower3); + } else { tower3.setDisabled(true); } @@ -211,14 +235,14 @@ public void clicked(InputEvent event, float x, float y) { TowerType selected = ServiceLocator.getCurrencyService().getTower(); if (selected == towers.get(3)) { ServiceLocator.getCurrencyService().setTowerType(null); - tower4.setChecked(false); + + towerToggle(null); + } else { ServiceLocator.getCurrencyService().setTowerType(towers.get(3)); - tower1.setChecked(false); - tower2.setChecked(false); - tower3.setChecked(false); - tower4.setChecked(true); - tower5.setChecked(false); + + towerToggle(tower4); + } click.play(0.4f); } @@ -234,14 +258,14 @@ public void clicked(InputEvent event, float x, float y) { TowerType selected = ServiceLocator.getCurrencyService().getTower(); if (selected == towers.get(4)) { ServiceLocator.getCurrencyService().setTowerType(null); - tower5.setChecked(false); + + towerToggle(null); + } else { ServiceLocator.getCurrencyService().setTowerType(towers.get(4)); - tower1.setChecked(false); - tower2.setChecked(false); - tower3.setChecked(false); - tower4.setChecked(false); - tower5.setChecked(true); + + towerToggle(tower5); + } click.play(0.4f); } @@ -249,6 +273,7 @@ public void clicked(InputEvent event, float x, float y) { TextTooltip tower5Tooltip = new TextTooltip(towers.get(4).getDescription(), getSkin()); tower5.addListener(tower5Tooltip); + // Scale all the tower build buttons down // Add all buttons to their respective tables and position them towerTable.add(tower1).padRight(10f); @@ -270,43 +295,55 @@ public void clicked(InputEvent event, float x, float y) { @Override public void draw(SpriteBatch batch) { // draw is handled by the stage - if (ServiceLocator.getCurrencyService().getTower() == null) { + towerUpdate(); + } - tower1.setChecked(false); - tower2.setChecked(false); - tower3.setChecked(false); - tower4.setChecked(false); - tower5.setChecked(false); - } - int balance = ServiceLocator.getCurrencyService().getScrap().getAmount(); - if (Integer.parseInt(towers.get(0).getPrice()) > balance) { - tower1.setDisabled(true); - } else { - tower1.setDisabled(false); - } - if (Integer.parseInt(towers.get(1).getPrice()) > balance) { - tower2.setDisabled(true); - } else { - tower2.setDisabled(false); - } - if (Integer.parseInt(towers.get(2).getPrice()) > balance) { - tower3.setDisabled(true); + /** + * Update function for the tower build menu buttons that is called with every draw, updates button states + * depending on button selection and currency balance + */ + private void towerUpdate() { + // no tower selected, set all to off + if (ServiceLocator.getCurrencyService().getTower() == null) { + // toggle all buttons to off + towerToggle(null); } else { - tower3.setDisabled(false); + // for handling shortcut key selection of tower build buttons + for (int i = 0; i < towerButtons.size; i++) { + if (ServiceLocator.getCurrencyService().getTower() == towers.get(i)) { + towerToggle(towerButtons.get(i)); + } + } } - if (Integer.parseInt(towers.get(3).getPrice()) > balance) { - tower4.setDisabled(true); - } else { - tower4.setDisabled(false); + // update button state based on currency balance + int balance = ServiceLocator.getCurrencyService().getScrap().getAmount(); + for (int i = 0; i < towerButtons.size; i++) { + towerButtons.get(i).setDisabled(Integer.parseInt(towers.get(i).getPrice()) > balance); } - if (Integer.parseInt(towers.get(4).getPrice()) > balance) { - tower5.setDisabled(true); + } + + /** + * Helper method for toggling tower build buttons. The expected behaviour is that if one button is pressed, + * all other buttons should be set to off. If a null button value is passed in then all buttons are set to off. + *

+ * @param towerButton the ImageButton which is being set to on, all others will be toggled off. If null, all buttons + * will be set to off + */ + private void towerToggle(ImageButton towerButton) { + if (towerButton == null) { + // set all buttons to off, disable if isDisabled + for (ImageButton button : towerButtons) { + button.setChecked(false); +// button.setDisabled(isDisabled); + } } else { - tower5.setDisabled(false); + // set the button corresponding to towerButton to on, all others to off + for (ImageButton button : towerButtons) { + button.setChecked(button == towerButton); +// button.setDisabled(isDisabled && button == towerButton); } - + } } - @Override public float getZIndex() { return Z_INDEX; diff --git a/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java b/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java index 6c4af2008..119b22041 100644 --- a/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java @@ -1,22 +1,12 @@ package com.csse3200.game.components.maingame; import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.scenes.scene2d.Actor; -import com.badlogic.gdx.scenes.scene2d.InputEvent; -import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.actions.Actions; import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction; -import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; -import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; -import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; -import com.badlogic.gdx.scenes.scene2d.utils.Drawable; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Null; -import com.csse3200.game.screens.TowerType; import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.ui.ButtonFactory; import com.csse3200.game.ui.UIComponent; @@ -34,7 +24,6 @@ public class UIElementsDisplay extends UIComponent { private TextButton remainingMobsButton; private TextButton timerButton; private LevelProgressBar progressbar; - private final int timer = 110; @Override public void create() { @@ -67,7 +56,7 @@ private void addActors() { } public void updateLevelProgressBar() { - float totalSecs = (ServiceLocator.getTimeSource().getTime() / 1000); + float totalSecs = ((float) ServiceLocator.getTimeSource().getTime() / 1000); progressbar.setValue(totalSecs); } diff --git a/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuButtonComponent.java b/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuButtonComponent.java index e0241e660..1a644ca19 100644 --- a/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuButtonComponent.java +++ b/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuButtonComponent.java @@ -1,15 +1,23 @@ package com.csse3200.game.components.pausemenu; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.scenes.scene2d.Actor; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.Touchable; +import com.badlogic.gdx.scenes.scene2d.actions.Actions; +import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction; import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.ui.Window; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.csse3200.game.GdxGame; +import com.csse3200.game.components.maingame.MainGameDisplay; +import com.csse3200.game.entities.factories.PauseMenuFactory; import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.ui.ButtonFactory; import com.csse3200.game.ui.UIComponent; @@ -65,6 +73,7 @@ public void changed(ChangeEvent changeEvent, Actor actor) { logger.debug("Continue button clicked"); click.play(0.5f); closeSound.play(0.5f); + ServiceLocator.getTimeSource().setPaused(false); entity.dispose(); } }); @@ -96,7 +105,25 @@ public void changed(ChangeEvent changeEvent, Actor actor) { } }); - window.setKeepWithinStage(true); + window.addListener( + new InputListener() { + + @Override + public boolean keyUp (InputEvent event, int keycode) { + if (keycode == Input.Keys.ESCAPE && ServiceLocator.getTimeSource().getPaused()) { + logger.debug("Closing pause menu with escape key"); + click.play(0.5f); + closeSound.play(0.5f); + ServiceLocator.getTimeSource().setPaused(false); + entity.dispose(); + return true; + } + return false; + } + } + ); + +// window.setKeepWithinStage(true); window.setResizable(true); window.setModal(true); window.setTouchable(Touchable.enabled); @@ -114,6 +141,7 @@ public void changed(ChangeEvent changeEvent, Actor actor) { window.setHeight(windowSizeY); window.setX((ServiceLocator.getRenderService().getStage().getWidth() / 2) - (windowSizeX / 2)); window.setY((ServiceLocator.getRenderService().getStage().getHeight() / 2) - (windowSizeY / 2)); + window.addAction(Actions.fadeIn(0.8f, Interpolation.bounceIn)); stage.addActor(window); } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java index c9f5c2b33..6ea6dd9d3 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java @@ -40,11 +40,11 @@ public class TowerCombatTask extends DefaultTask implements PriorityTask { private final float maxRange; private Vector2 towerPosition = new Vector2(10, 10); // initial placeholder value - will be overwritten private final Vector2 maxRangePosition = new Vector2(); - private PhysicsEngine physics; - private GameTime timeSource; + private final PhysicsEngine physics; + private final GameTime timeSource; private long endTime; private final RaycastHit hit = new RaycastHit(); - private static final Logger logger = LoggerFactory.getLogger(ForestGameArea.class); + private static final Logger logger = LoggerFactory.getLogger(TowerCombatTask.class); private boolean shoot = true; private enum STATE { @@ -154,26 +154,8 @@ public void updateTowerState() { Entity newProjectile = ProjectileFactory.createFireBall(PhysicsLayer.NPC, new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f)); newProjectile.setScale(1.1f, 0.8f); - newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.5), (float) (owner.getEntity().getPosition().y)); + newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.5), (owner.getEntity().getPosition().y)); ServiceLocator.getEntityService().register(newProjectile); - - // * TEMPRORARYYYYYYYY PLS DON'T DELETE THIS - // PIERCE FIREBALL - // Entity pierceFireball = ProjectileFactory.createPierceFireBall(PhysicsLayer.NPC, new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f,2f)); - // pierceFireball.setPosition((float) (owner.getEntity().getPosition().x + 0), (float) (owner.getEntity().getPosition().y + 0.4)); - // ServiceLocator.getEntityService().register(pierceFireball); - - // RICOCHET FIREBALL - // Entity ricochetProjectile = ProjectileFactory.createRicochetFireball(PhysicsLayer.NPC, new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f,2f), 0); - - // ricochetProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0), (float) (owner.getEntity().getPosition().y + 0.4)); - // ServiceLocator.getEntityService().register(ricochetProjectile); - - // SPLIT FIREWORKS FIREBALLL - // Entity splitFireWorksProjectile = ProjectileFactory.createSplitFireWorksFireball(PhysicsLayer.NPC, new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f,2f), 16); - - // splitFireWorksProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.75), (float) (owner.getEntity().getPosition().y + 0.4)); - // ServiceLocator.getEntityService().register(splitFireWorksProjectile); } } shoot = !shoot; diff --git a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java index df1361a55..7f7d9cd00 100644 --- a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java +++ b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java @@ -11,7 +11,6 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.csse3200.game.GdxGame; import com.csse3200.game.areas.ForestGameArea; import com.csse3200.game.components.gamearea.PerformanceDisplay; @@ -85,7 +84,7 @@ public class MainGameScreen extends ScreenAdapter { private final Renderer renderer; private final PhysicsEngine physicsEngine; private final InputComponent buildHandler; - private InputComponent upgradedInputHandler; + private final InputComponent upgradedInputHandler; static int screenWidth = Gdx.graphics.getWidth(); static int screenHeight = Gdx.graphics.getHeight(); private Entity ui; @@ -108,8 +107,6 @@ public MainGameScreen(GdxGame game) { batch = new SpriteBatch(); - Stage stage = new Stage(new ScreenViewport()); - logger.debug("Initialising main game screen services"); ServiceLocator.registerTimeSource(new GameTime()); diff --git a/source/core/src/main/com/csse3200/game/services/GameEndService.java b/source/core/src/main/com/csse3200/game/services/GameEndService.java index c25b196a4..8be490699 100644 --- a/source/core/src/main/com/csse3200/game/services/GameEndService.java +++ b/source/core/src/main/com/csse3200/game/services/GameEndService.java @@ -55,7 +55,7 @@ public void updateEngineerCount() { * @return the warning threshold int */ public float getThreshold() { - return (float)( STARTING_COUNT); + return (float)(0.3 * STARTING_COUNT); } /** diff --git a/source/core/src/main/com/csse3200/game/services/GameTime.java b/source/core/src/main/com/csse3200/game/services/GameTime.java index ad60c9e59..fce525778 100644 --- a/source/core/src/main/com/csse3200/game/services/GameTime.java +++ b/source/core/src/main/com/csse3200/game/services/GameTime.java @@ -11,6 +11,8 @@ public class GameTime { private final long startTime; private float timeScale = 1f; + private boolean paused = false; + public GameTime() { startTime = TimeUtils.millis(); logger.debug("Setting game start time to {}", startTime); @@ -44,4 +46,12 @@ public long getTime() { public long getTimeSince(long lastTime) { return getTime() - lastTime; } + + public boolean getPaused() { + return paused; + } + + public void setPaused(boolean status) { + paused = status; + } }