From 847ecf475ec3cc115e9c2ef4097e3c79d26fbf0a Mon Sep 17 00:00:00 2001 From: marcomarrelli Date: Thu, 15 Feb 2024 17:56:45 +0100 Subject: [PATCH] Added Level Manager --- src/main/java/pvzclone/PvzStart.java | 5 +- .../pvzclone/controller/api/Controller.java | 9 +- .../controller/impl/ControllerImpl.java | 27 +++--- src/main/java/pvzclone/model/api/Level.java | 39 ++++++++ src/main/java/pvzclone/model/api/World.java | 13 +++ .../java/pvzclone/model/impl/GameImpl.java | 28 ++++-- .../pvzclone/model/impl/GameStateImpl.java | 3 +- .../java/pvzclone/model/impl/LevelImpl.java | 58 +++++++++++- .../pvzclone/model/impl/LevelsManager.java | 89 +++++++++++++++++++ .../java/pvzclone/model/impl/WorldImpl.java | 10 +++ .../java/pvzclone/view/impl/LevelPanel.java | 14 ++- 11 files changed, 264 insertions(+), 31 deletions(-) create mode 100644 src/main/java/pvzclone/model/impl/LevelsManager.java diff --git a/src/main/java/pvzclone/PvzStart.java b/src/main/java/pvzclone/PvzStart.java index 775d63d..aa95438 100644 --- a/src/main/java/pvzclone/PvzStart.java +++ b/src/main/java/pvzclone/PvzStart.java @@ -5,7 +5,10 @@ /** * Plants Vs Zombies Application's Entry Point. * - * @author Sofia Caberletti, Margherita Zanchini, Sofia Lotti, Marco Marrelli. + * @author Sofia Caberletti + * @author Margherita Zanchini + * @author Sofia Lotti + * @author Marco Marrelli */ public final class PvzStart { diff --git a/src/main/java/pvzclone/controller/api/Controller.java b/src/main/java/pvzclone/controller/api/Controller.java index 7b1eace..01db1b6 100644 --- a/src/main/java/pvzclone/controller/api/Controller.java +++ b/src/main/java/pvzclone/controller/api/Controller.java @@ -66,7 +66,14 @@ public interface Controller extends ViewEventListener { * Retrieves the number of the chosen level if the level was chosen, * if not returns an empty Optional. * - * @return number of the level the we chose; + * @return number of the level the we chose. */ Optional getChosenLevel(); + + /** + * Returns the number of levels available in the application. + * + * @return number of levels available in the application. + */ + int getLevelCount(); } diff --git a/src/main/java/pvzclone/controller/impl/ControllerImpl.java b/src/main/java/pvzclone/controller/impl/ControllerImpl.java index d542e5a..e2688a0 100644 --- a/src/main/java/pvzclone/controller/impl/ControllerImpl.java +++ b/src/main/java/pvzclone/controller/impl/ControllerImpl.java @@ -9,7 +9,7 @@ import pvzclone.model.api.Game; import pvzclone.model.api.World; import pvzclone.model.impl.GameImpl; -import pvzclone.model.impl.LevelImpl; +import pvzclone.model.impl.LevelsManager; import pvzclone.model.impl.Pair; import pvzclone.model.impl.WorldImpl; import pvzclone.view.api.View; @@ -20,8 +20,9 @@ */ public final class ControllerImpl implements Controller { - private static final long PERIOD = 80; - + private static final long PERIOD = 60; + private static final int LEVEL_COUNT = 10; + private World world; private View view; private Game game; @@ -30,6 +31,8 @@ public final class ControllerImpl implements Controller { @Override public void initGame() { this.world = new WorldImpl(); + this.world.setLevelManager(new LevelsManager(LEVEL_COUNT)); + this.view = new SwingViewImpl(this); this.chosenLevel = Optional.empty(); } @@ -46,7 +49,7 @@ private void mainLoop() { if (this.world == null || this.view == null) { return; } - this.world.setLevel(new LevelImpl()); + this.world.setLevel(this.world.getLevelManager().getLevel(chosenLevel)); this.game = new GameImpl(this.world); this.world.setGame(game); long startTime = System.currentTimeMillis(); @@ -112,12 +115,12 @@ public Optional getChosenLevel() { return this.chosenLevel; } - /* - * @Override - * public void notifyWorldEvent(WorldEvent ev) { - * //qua ho un dubbio, se è gia il model che gestisce le collisioni interne - * //già lui controlla che ci siano state cose - * //il controller lo comunica alla view? - * } - */ + @Override + public int getLevelCount() { + if (this.world.getLevelManager() == null) { + throw new IllegalStateException("There are no valid levels to load!"); + } + + return this.world.getLevelManager().getLevelCount(); + } } diff --git a/src/main/java/pvzclone/model/api/Level.java b/src/main/java/pvzclone/model/api/Level.java index 21aa7fc..900fe38 100644 --- a/src/main/java/pvzclone/model/api/Level.java +++ b/src/main/java/pvzclone/model/api/Level.java @@ -2,11 +2,50 @@ /** * This interface models a Level. + * + * @author Marco Marrelli */ public interface Level { /** + * Returns the numbers of zombie in one level. + * * @return the numbers of zombie in one level. */ int getZombieCount(); + /** + * Returns the numbers of zombie waves in one level. + * The value is based on the zombie count. + * + * @return the numbers of zombie waves in one level. + */ + int getZombieWaveCount(); + + /** + * Returns the sun spawn rate. + * + * @return the sun spawn rate. + */ + long getSunSpawnRate(); + + /** + * Returns the zombie spawn rate. + * + * @return the zombie spawn rate. + */ + long getZombieSpawnRate(); + + /** + * Returns the sun spawn rate. + * + * @return the sun decrement spawn rate. + */ + long getSunSpawnRateDecrementRange(); + + /** + * Returns the zombie spawn rate. + * + * @return the zombie decrement spawn rate. + */ + long getZombieSpawnRateDecrementRange(); } diff --git a/src/main/java/pvzclone/model/api/World.java b/src/main/java/pvzclone/model/api/World.java index e3d36f7..c18ce27 100644 --- a/src/main/java/pvzclone/model/api/World.java +++ b/src/main/java/pvzclone/model/api/World.java @@ -1,5 +1,7 @@ package pvzclone.model.api; +import pvzclone.model.impl.LevelsManager; + /** * Interface of the Model of the game. * It contains methods to set the Level and Game that will @@ -22,6 +24,13 @@ public interface World { */ void setGame(Game game); + /** + * Sets the level manager. + * + * @param levelsManager the level manager of the World. + */ + void setLevelManager(LevelsManager levelsManager); + /** * @return the level. */ @@ -32,4 +41,8 @@ public interface World { */ Game getGame(); + /** + * @return the level manager. + */ + LevelsManager getLevelManager(); } diff --git a/src/main/java/pvzclone/model/impl/GameImpl.java b/src/main/java/pvzclone/model/impl/GameImpl.java index 8048e3c..40a00a0 100644 --- a/src/main/java/pvzclone/model/impl/GameImpl.java +++ b/src/main/java/pvzclone/model/impl/GameImpl.java @@ -13,6 +13,7 @@ import pvzclone.view.impl.SwingViewImpl; import java.util.HashSet; +import java.util.Random; /** * class that implements the interface Game. @@ -21,13 +22,12 @@ public final class GameImpl implements Game { // sun private static final int HOUSE_X_POSITION = 150; - private static final long DELTA_TIME_SUN = 3000; - private static final int BULLET_SPEED = 10; + private static final int BULLET_SPEED = 15; // zombie private static final int DELTA_ZOMBIE = 10; - private static final long DELTA_TIME_ZOMBIE_START = 12_000; - private static final int DEC_ZOMBIE_TIME_GENERATE = 500; + private static final long DEC_ZOMBIE_TIME_GENERATE = 250; + // base plant private static final int PLANT_COST = 100; @@ -51,7 +51,11 @@ public final class GameImpl implements Game { private long timeOfLastCreatedSun; private long timeOfLastCreatedZombie; - private long deltaTimeZombie = DELTA_TIME_ZOMBIE_START; + + private long deltaTimeSun; + private long deltaTimeZombie; + private long deltaTimeSunDecrement; + private long deltaTimeZombieDecrement; /** * @@ -62,6 +66,11 @@ public GameImpl(final World world) { this.gameState = new GameStateImpl(this.world.getLevel().getZombieCount()); this.sunFactory = new SunsFactory(); this.zombiesFactory = new ZombiesFactory(); + + this.deltaTimeSun = this.world.getLevel().getSunSpawnRate(); + this.deltaTimeZombie = this.world.getLevel().getZombieSpawnRate(); + this.deltaTimeSunDecrement = this.world.getLevel().getSunSpawnRateDecrementRange(); + this.deltaTimeZombieDecrement = this.world.getLevel().getZombieSpawnRateDecrementRange(); } @Override @@ -114,9 +123,11 @@ private boolean hasDeltaTimePassed(final long previousTime, final long currentTi } private void newSunGenerate(final long currentTime) { - if (this.hasDeltaTimePassed(this.timeOfLastCreatedSun, currentTime, DELTA_TIME_SUN)) { - this.suns.add((SunImpl) this.sunFactory.createEntity()); + if (this.hasDeltaTimePassed(this.timeOfLastCreatedSun, currentTime, this.deltaTimeSun)) { this.timeOfLastCreatedSun = currentTime; + this.suns.add((SunImpl) this.sunFactory.createEntity()); + final long deltaDecrement = new Random().nextLong((2 * this.deltaTimeSunDecrement)) - this.deltaTimeSunDecrement; + this.deltaTimeSun = this.deltaTimeSun - deltaDecrement; } } @@ -125,7 +136,8 @@ private void newZombieGenerate(final long elapsed) { && this.gameState.getZombiesGenerated() < this.world.getLevel().getZombieCount()) { this.timeOfLastCreatedZombie = elapsed; this.zombies.add((Zombie) this.zombiesFactory.createEntity()); - this.deltaTimeZombie = this.deltaTimeZombie - DEC_ZOMBIE_TIME_GENERATE; + final long deltaDecrement = new Random().nextLong((2 * this.deltaTimeZombieDecrement)) - this.deltaTimeZombieDecrement; + this.deltaTimeZombie = this.deltaTimeZombie - deltaDecrement; this.gameState.incZombiesGenerated(); } } diff --git a/src/main/java/pvzclone/model/impl/GameStateImpl.java b/src/main/java/pvzclone/model/impl/GameStateImpl.java index a08521f..aa1c974 100644 --- a/src/main/java/pvzclone/model/impl/GameStateImpl.java +++ b/src/main/java/pvzclone/model/impl/GameStateImpl.java @@ -14,6 +14,7 @@ public final class GameStateImpl implements GameState { private static final int INC_SUN = 25; + private final int INITIAL_SUNS = 100; private final int totZombies; private int killedZombies; private int zombiesGenerated; @@ -29,7 +30,7 @@ public final class GameStateImpl implements GameState { public GameStateImpl(final int totZombies) { this.totZombies = totZombies; this.killedZombies = 0; - this.sunScore = 100; + this.sunScore = INITIAL_SUNS; this.winState = Optional.empty(); } diff --git a/src/main/java/pvzclone/model/impl/LevelImpl.java b/src/main/java/pvzclone/model/impl/LevelImpl.java index ab0667a..73393bf 100644 --- a/src/main/java/pvzclone/model/impl/LevelImpl.java +++ b/src/main/java/pvzclone/model/impl/LevelImpl.java @@ -5,15 +5,65 @@ /** * Class that implements a Level. * - * @author Sofia Lotti. + * @author Marco Marrelli */ -public final class LevelImpl implements Level { +public class LevelImpl implements Level { - private static final int TOTAL_ZOMBIES = 5; + private final int zombieCount; + private final int zombieWaveCount; + private final long sunSpawnRate; + private final long zombieSpawnRate; + private final long sunSpawnRateDecrementRange; + private final long zombieSpawnRateDecrementRange; + + public LevelImpl() { + this.zombieCount = LevelsManager.ZOMBIE_COUNT; + this.zombieWaveCount = 1; + this.sunSpawnRate = LevelsManager.SUN_SPAWN_RATE; + this.sunSpawnRateDecrementRange = LevelsManager.SUN_SPAWN_RATE_DECREMENT_RANGE; + this.zombieSpawnRate = LevelsManager.ZOMBIE_SPAWN_RATE; + this.zombieSpawnRateDecrementRange = LevelsManager.ZOMBIE_SPAWN_RATE_DECREMENT_RANGE; + } + + public LevelImpl(final int zombieCount, final int zombieWaveCount, + final long sunSpawnRate, final long zombieSpawnRate, + final long sunSpawnRateDecrementRange, + final long zombieSpawnRateDecrementRange) { + this.zombieCount = zombieCount; + this.zombieWaveCount = zombieWaveCount; + this.sunSpawnRate = sunSpawnRate; + this.sunSpawnRateDecrementRange = sunSpawnRateDecrementRange; + this.zombieSpawnRate = zombieSpawnRate; + this.zombieSpawnRateDecrementRange = zombieSpawnRateDecrementRange; + } @Override public int getZombieCount() { - return TOTAL_ZOMBIES; + return this.zombieCount; + } + + @Override + public int getZombieWaveCount() { + return this.zombieWaveCount; + } + + @Override + public long getSunSpawnRate() { + return this.sunSpawnRate; } + @Override + public long getZombieSpawnRate() { + return this.zombieSpawnRate; + } + + @Override + public long getSunSpawnRateDecrementRange() { + return this.sunSpawnRateDecrementRange; + } + + @Override + public long getZombieSpawnRateDecrementRange() { + return this.zombieSpawnRateDecrementRange; + } } diff --git a/src/main/java/pvzclone/model/impl/LevelsManager.java b/src/main/java/pvzclone/model/impl/LevelsManager.java new file mode 100644 index 0000000..6388fc8 --- /dev/null +++ b/src/main/java/pvzclone/model/impl/LevelsManager.java @@ -0,0 +1,89 @@ +package pvzclone.model.impl; + +import java.util.List; +import java.util.Optional; +import java.util.ArrayList; + +public class LevelsManager { + private final static int MIN_LEVELS = 1; + private final static int MAX_LEVELS = 5; + + private final List levelList; + + public static final int ZOMBIE_COUNT = 5; + private static final int ZOMBIE_COUNT_STEP = 4; + public static final long SUN_SPAWN_RATE = 3000; + private static final long SUN_SPAWN_RATE_STEP = 120; + public static final long ZOMBIE_SPAWN_RATE = 12_000; + private static final long ZOMBIE_SPAWN_RATE_STEP = -300; + public static final long SUN_SPAWN_RATE_DECREMENT_RANGE = 25; + public static final long ZOMBIE_SPAWN_RATE_DECREMENT_RANGE = 75; + + public LevelsManager(int levelNumber) { + this.levelList = new ArrayList<>(); + + if (levelNumber < MIN_LEVELS ) { + levelNumber = MIN_LEVELS; + } + else if (levelNumber > MAX_LEVELS) { + levelNumber = MAX_LEVELS; + } + + for (int l=0; l index) { + if (index.isEmpty()) { + throw new IllegalStateException("No valid level selected!"); + } + + if (index.get() >= this.getLevelCount()) { + return this.getLevel(Optional.of(this.getLevelCount()-1)); + } + else if (index.get() < 0) { + return this.getLevel(Optional.of(0)); + } + return this.levelList.get(index.get()); + } + + public List getLevelList() { + if (this.levelList == null || this.levelList.isEmpty()) { + throw new IllegalStateException("There are no valid levels to load!"); + } + + return this.levelList; + } +} diff --git a/src/main/java/pvzclone/model/impl/WorldImpl.java b/src/main/java/pvzclone/model/impl/WorldImpl.java index 1c91b57..9439996 100644 --- a/src/main/java/pvzclone/model/impl/WorldImpl.java +++ b/src/main/java/pvzclone/model/impl/WorldImpl.java @@ -13,6 +13,7 @@ public final class WorldImpl implements World { private Level level; private Game game; + private LevelsManager levelManager; @Override public void setLevel(final Level level) { @@ -24,6 +25,11 @@ public void setGame(final Game game) { this.game = game; } + @Override + public void setLevelManager(final LevelsManager levelManager) { + this.levelManager = levelManager; + } + @Override public Level getLevel() { return this.level; @@ -34,4 +40,8 @@ public Game getGame() { return this.game; } + @Override + public LevelsManager getLevelManager() { + return this.levelManager; + } } diff --git a/src/main/java/pvzclone/view/impl/LevelPanel.java b/src/main/java/pvzclone/view/impl/LevelPanel.java index 79e15f8..b35e711 100644 --- a/src/main/java/pvzclone/view/impl/LevelPanel.java +++ b/src/main/java/pvzclone/view/impl/LevelPanel.java @@ -10,14 +10,15 @@ import javax.swing.ImageIcon; import javax.swing.JButton; - public class LevelPanel extends GenericPanel { private static final int LAYOUT_HGAP = 20; private static final int LAYOUT_VGAP = 50; private static final String BUTTON_TEXTURE = "/images/tombstoneTexture.jpg"; private static final Dimension MENU_BUTTON_DIMENSION = new Dimension( - SwingViewImpl.APPLICATION_WIDTH / 6, SwingViewImpl.APPLICATION_HEIGHT / 8); + SwingViewImpl.APPLICATION_WIDTH / 6, SwingViewImpl.APPLICATION_HEIGHT / 8 + ); private final SwingViewImpl parent; + private final int levelCount; /** * Level Panel Constructor. @@ -33,7 +34,13 @@ public LevelPanel(SwingViewImpl parent, String backgroundSource) { new FlowLayout(FlowLayout.CENTER, LAYOUT_HGAP, SwingViewImpl.APPLICATION_HEIGHT / 2 - LAYOUT_VGAP)); final ImageIcon texture = new ImageIcon(getClass().getResource(BUTTON_TEXTURE)); - for(int i=0; i<5; i++) { + this.levelCount = this.parent.getController().getLevelCount(); + + if (this.levelCount <= 0) { + throw new IllegalStateException("There are no valid levels to load!"); + } + + for(int i=0; i