diff --git a/src/main/java/main/GameManager.java b/src/main/java/main/GameManager.java index cd88b9e..065abbd 100644 --- a/src/main/java/main/GameManager.java +++ b/src/main/java/main/GameManager.java @@ -17,6 +17,9 @@ public class GameManager extends Application { + // TODO: Consider organizing related fields into separate classes or enums + // TODO: Consider making fields private where appropriate and providing getter methods + ActionHandler aHandler = new ActionHandler(this); public UI ui = new UI(this); public Player player = new Player(this); @@ -27,6 +30,8 @@ public class GameManager extends Application { public long elapsedTime; private TimeManager timeManager; + // TODO: Consider using a map or list to manage events and monsters + public Event01 ev1 = new Event01(this); public Event02 ev2 = new Event02(this); public Event03 ev3 = new Event03(this); @@ -41,7 +46,11 @@ public class GameManager extends Application { Music music = new Music(); SoundEffect se = new SoundEffect(); + // Ev3 is never used + //SOUND + // TODO: Consider using an enum or configuration file for sound resources + public URL mainTheme = getClass().getClassLoader().getResource("mainTheme.wav"); public URL monsterTheme = getClass().getClassLoader().getResource("monsterTheme.wav"); public URL casinoMusic = getClass().getClassLoader().getResource("casinoMusic.wav"); @@ -76,24 +85,29 @@ public void start(Stage primaryStage) { } + // TODO: Consider adding a method to manage game state (e.g., pausing, resuming) + public void playSE(URL url) { + // TODO: Add null check for url se.setFile(url); se.play(url); } public void playMusic(URL url){ + // TODO: Add null check for url music.setFile(url); music.play(url); music.loop(url); } public void stopMusic(URL url){ - + // TODO: Add null check for url music.stop(url); } public void startGameTimer() { + // TODO: Consider resetting elapsedTime here startTime = System.nanoTime(); gameTimer = new AnimationTimer() { @Override @@ -117,6 +131,7 @@ public void stopGameTimer() { } public void updateTimerUI() { + // TODO: Consider moving this formatting logic to a utility class // Format the time as minutes and seconds long seconds = elapsedTime / 1000; long minutes = seconds / 60; @@ -129,4 +144,8 @@ public void showLeaderboard() { List leaderboard = timeManager.getFormattedFastestTimes(); ui.displayLeaderboard(leaderboard); // Add a method in UI to display the leaderboard } + // Consider adding methods for game state management (e.g., startNewGame, endGame) + // Consider adding methods for handling player actions and game events + // Consider implementing a logging system for debugging and tracking game events + // Consider adding unit tests for game logic } diff --git a/src/main/java/main/Music.java b/src/main/java/main/Music.java index 0053b11..894b21c 100644 --- a/src/main/java/main/Music.java +++ b/src/main/java/main/Music.java @@ -12,28 +12,42 @@ public class Music { Clip clip; + // TODO: Consider making clip private and providing getter/setter methods if needed + public void setFile(URL name){ + // TODO: Add null check for 'name' parameter try{ AudioInputStream sound = AudioSystem.getAudioInputStream(name); clip = AudioSystem.getClip(); clip.open(sound); + // TODO: Add null check for 'name' parameter } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) { + e.printStackTrace(); + // TODO: Consider more specific error handling for different exception types throw new RuntimeException(e); } } public void play(URL name){ + // TODO: Add null check for 'clip' + // TODO: Consider removing 'name' parameter as it's not used in this method clip.setFramePosition(0); clip.start(); } public void loop(URL name){ - + // TODO: Add null check for 'clip' + // TODO: Consider removing 'name' parameter as it's not used in this method clip.loop(Clip.LOOP_CONTINUOUSLY); } - public void stop(URL name){ + public void stop(URL name) { + // TODO: Add null check for 'clip' + // TODO: Consider removing 'name' parameter as it's not used in this method clip.stop(); } + // TODO: Consider adding a method to release resources (close the clip) when it's no longer needed + // TODO: Consider adding volume control methods + // TODO: Consider adding a method to check if the clip is currently playing } diff --git a/src/main/java/main/Player.java b/src/main/java/main/Player.java index cd20c21..fc98300 100644 --- a/src/main/java/main/Player.java +++ b/src/main/java/main/Player.java @@ -2,22 +2,28 @@ /** * this class handles the player logic + * TODO: Consider adding more detailed class description */ public class Player { GameManager gm; + // TODO: Consider making gm private and providing a getter method if needed public int playerMaxLife; public int playerLife; + // TODO: Consider making these variables private and providing getter/setter methods public int hasFlashlight; public int hasPistol; public int hasAk47; + // TODO: Consider using boolean instead of int for these item flags + // TODO: Consider using an enum or a more flexible data structure for inventory management public Player(GameManager gm) { this.gm = gm; + // TODO: Consider calling setPlayerDefaultStatus() here to initialize player status } public void setPlayerDefaultStatus() { @@ -29,9 +35,10 @@ public void setPlayerDefaultStatus() { hasAk47 = 0; updatePlayerStatus(); + // TODO: Consider adding a method to reset player status to full health } public void updatePlayerStatus() { - + // TODO: Consider extracting the life icon update logic to a separate method int i = 0; while (i < 5) { gm.ui.lifeLabels[i].setVisible(false); @@ -48,9 +55,15 @@ public void updatePlayerStatus() { } // CHECK PLAYER ITEMS + // TODO: Consider extracting the item visibility update logic to a separate method + gm.ui.flashlightLabel.setVisible(hasFlashlight == 1); gm.ui.pistolLabel.setVisible(hasPistol == 1); gm.ui.ak47Label.setVisible(hasAk47 == 1); } + + // Consider adding methods for player actions (e.g., takeDamage, heal, pickUpItem) + // Consider adding a method to check if the player is alive + // Consider adding methods to manage inventory (e.g., addItem, removeItem) } diff --git a/src/main/java/main/SoundEffect.java b/src/main/java/main/SoundEffect.java index 6410d8e..d597626 100644 --- a/src/main/java/main/SoundEffect.java +++ b/src/main/java/main/SoundEffect.java @@ -11,20 +11,31 @@ public class SoundEffect { Clip clip; + // TODO: Consider making clip private and providing getter/setter methods if needed public void setFile(URL name){ - + // TODO: Add null check for 'name' parameter try{ AudioInputStream sound = AudioSystem.getAudioInputStream(name); clip = AudioSystem.getClip(); clip.open(sound); + // TODO: Consider closing the AudioInputStream after opening the clip } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) { + // TODO: Consider more specific error handling for different exception types throw new RuntimeException(e); } } public void play(URL name){ + // TODO: Add null check for 'clip' + // TODO: Consider removing 'name' parameter as it's not used in this method clip.setFramePosition(0); clip.start(); + + // Consider adding a stop() method to stop the sound effect + // Consider adding a method to release resources (close the clip) when it's no longer needed + // Consider adding volume control methods + // Consider adding a method to check if the sound effect is currently playing + // Consider implementing a sound effect pool to manage multiple sound effects efficiently } } diff --git a/src/main/java/main/TimeManager.java b/src/main/java/main/TimeManager.java index 25d9b19..c786923 100644 --- a/src/main/java/main/TimeManager.java +++ b/src/main/java/main/TimeManager.java @@ -2,6 +2,7 @@ /** * This class handles the leaderboard times + * TODO: Consider adding more detailed class description */ import java.io.*; @@ -13,6 +14,7 @@ public class TimeManager { private static final String BINARY_FILE_NAME = "fastest_times.dat"; private static final String LEADERBOARD_FILE_NAME = "leaderboard.csv"; public ArrayList fastestTimes = new ArrayList<>(); + // TODO: Consider making fastestTimes private and providing a getter method public TimeManager() { loadTimes(); @@ -35,7 +37,7 @@ public void addTime(long time) { fastestTimes.add(time); Collections.sort(fastestTimes); if (fastestTimes.size() > 10) { - fastestTimes.remove(fastestTimes.size() - 1); + fastestTimes.removeLast(); } saveTimes(); saveLeaderboard(); // Save to leaderboard file as well @@ -92,7 +94,7 @@ void loadLeaderboard() { System.err.println("Error loading leaderboard: " + e.getMessage()); } } - public class TimeUtils { + public static class TimeUtils { public static String formatTime(long millis) { long seconds = millis / 1000; long minutes = seconds / 60; diff --git a/src/main/java/main/UI.java b/src/main/java/main/UI.java index be2b253..58ca7fb 100644 --- a/src/main/java/main/UI.java +++ b/src/main/java/main/UI.java @@ -42,6 +42,8 @@ public class UI { //GAME OVER UI public Label titleLabel; public Button restartButton; + private int width; + private int height; public UI(GameManager gm) { this.gm = gm; @@ -83,7 +85,7 @@ public void createTitleScreen(Stage primaryStage) { //START BUTTON Button startButton = new Button("Start"); startButton.setStyle("-fx-font-family: 'Arial'; -fx-font-size: 24px; -fx-background-color: white;"); - startButton.setLayoutX((800 - 150) / 2); // Center horizontally (approximate for button width) + startButton.setLayoutX((double) (800 - 150) / 2); // Center horizontally (approximate for button width) startButton.setLayoutY(400); // Center vertically (approximate for button height) // Start button functionality @@ -229,6 +231,8 @@ public ImageView createObjectAndReturn(int bgNum, int objx, int objy, int objWid } public void createArrowButton(int bgNum, int x, int y, int width, int height, String arrowFileName, String command) { + this.width = width; + this.height = height; // Arrow Button Image Image arrowImage = new Image(Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream(arrowFileName))); Button arrowButton = new Button(); diff --git a/src/main/java/monsters/Hondaur.java b/src/main/java/monsters/Hondaur.java index 84afd64..28ced83 100644 --- a/src/main/java/monsters/Hondaur.java +++ b/src/main/java/monsters/Hondaur.java @@ -8,10 +8,14 @@ public class Hondaur extends Monster { private ImageView anthony; // Reference for anthony private ImageView blood; // Reference for blood + // TODO: Consider making these ImageViews final if they're not reassigned + public Hondaur(GameManager gm) { super(gm,4,4, "Hondaur", 1); + // TODO: Consider adding validation for the parameters } public void addToScene() { + // TODO: Consider extracting magic numbers (300, 100, 200, 283) to constants gm.ui.createObject(3, 300,100,200,283,"Hondaur_2.png", "Look","Talk", "Attack", "lookHondaur", @@ -20,6 +24,7 @@ public void addToScene() { @Override public void lookHondaur() { + // TODO: Consider using a switch statement or enum for different monster states if(currentLife >0) { gm.ui.messageText.setText("You see a fearsome weakened " + monster+ " ready to rev its engine."); gm.playSE(gm.monsterRoar); @@ -31,6 +36,7 @@ public void lookHondaur() { } @Override public void talkHondaur() { + // TODO: Consider combining this method with lookHondaur to reduce code duplication if(currentLife >0) { gm.ui.messageText.setText("The "+monster+" growls at you, its engine roaring."); gm.playSE(gm.monsterRoar); @@ -42,11 +48,14 @@ public void talkHondaur() { } @Override public void attackHondaur() { + // TODO: Consider extracting the attack logic to a separate method currentLife--; gm.player.playerLife -=1; gm.player.updatePlayerStatus(); gm.ui.messageText.setText("You attack the "+monster+" with your fists! (Its health decreases)"); + + // TODO: Consider extracting the player death check to a separate method if(gm.player.playerLife <=0){ gm.sChanger.showGameOverScreen(3); gm.ui.messageText.setText("You baka! You tested your luck!"); @@ -122,4 +131,7 @@ public void lookSponge() {} public void talkSponge() {} @Override public void followSponge() {} + // Consider adding documentation for public methods + // Consider implementing a more flexible system for monster interactions + // Consider adding unit tests for this class } diff --git a/src/main/java/monsters/Monster.java b/src/main/java/monsters/Monster.java index caa7cc4..7a2a92d 100644 --- a/src/main/java/monsters/Monster.java +++ b/src/main/java/monsters/Monster.java @@ -10,7 +10,11 @@ public abstract class Monster { protected String monster; protected int attackDamage; + // TODO: Consider making currentLife private and providing a getter method + // TODO: Consider using final for fields that don't change after initialization + public Monster(GameManager gm,int currentLife,int maxLife, String monster, int attackDamage) { + // TODO: Add parameter validation (e.g., check for null gm, non-negative life and damage) this.gm = gm; this.currentLife = currentLife; this.maxLife = maxLife; @@ -19,6 +23,9 @@ public Monster(GameManager gm,int currentLife,int maxLife, String monster, int a } public abstract void reset(); + + // TODO: Consider grouping related methods (e.g., all Hondaur methods together) + // TODO: Consider using an enum or interface to define different monster types public abstract void lookHondaur(); public abstract void talkHondaur(); public abstract void attackHondaur(); @@ -35,6 +42,15 @@ public Monster(GameManager gm,int currentLife,int maxLife, String monster, int a public abstract void talkWheeler(); public abstract void attackWheeler(); + // Consider adding a generic interaction method to reduce the number of abstract methods + // e.g., public abstract void interact(MonsterType type, InteractionType interaction); + // Consider adding common monster behaviors (e.g., takeDamage, isAlive) + // Consider adding a method to get monster stats (e.g., getStats()) + // Consider adding a method to update monster state (e.g., updateState()) + // Add JavaDoc comments for the class and methods + // Consider implementing a builder pattern for complex monster creation + // Consider adding unit tests for common monster behaviors + diff --git a/src/main/java/monsters/Wheeler.java b/src/main/java/monsters/Wheeler.java index f13aa07..eeae034 100644 --- a/src/main/java/monsters/Wheeler.java +++ b/src/main/java/monsters/Wheeler.java @@ -6,11 +6,14 @@ public class Wheeler extends Monster { private ImageView blood; // Reference for blood + // TODO: Consider making blood final if it's not reassigned public Wheeler(GameManager gm) { super(gm,4,4, "Wheeler", 2); } + // TODO: Consider adding validation for the parameters public void addToScene() { + // TODO: Consider extracting magic numbers (50, 95, 200, 283) to constants gm.ui.createObject(5, 50,95,200,283,"wheel.png", "Look","Talk", "Attack", "lookWheeler", @@ -19,6 +22,7 @@ public void addToScene() { @Override public void lookWheeler() { + // TODO: Consider using a switch statement or enum for different monster states if(currentLife >0) { gm.ui.messageText.setText("You see the " + monster+ " ready to run you over."); gm.playSE(gm.monsterRoar); @@ -31,6 +35,7 @@ public void lookWheeler() { @Override public void talkWheeler() { + // TODO: Consider combining this method with lookWheeler to reduce code duplication if(currentLife >0) { gm.ui.messageText.setText(monster+" roars at you! (He is scared of the glock)."); gm.playSE(gm.monsterRoar); @@ -43,11 +48,17 @@ public void talkWheeler() { @Override public void attackWheeler() { + // TODO: Consider extracting the attack logic to a separate method currentLife-=2; gm.player.playerLife -=1; gm.player.updatePlayerStatus(); gm.ui.messageText.setText("You shoot "+monster+" with your glock! (Its health decreases by 2)"); - if(gm.player.playerLife <=0){ + // TODO: Consider extracting the player death check to a separate method + + if (gm.player.playerLife <=0) { + + // Duplicate if statement + gm.sChanger.showGameOverScreen(5); gm.ui.messageText.setText("You baka! You tested your luck!"); } @@ -106,4 +117,8 @@ public void lookTheodoor() {} public void talkTheodoor() {} @Override public void attackTheodoor() {} + + // Consider adding documentation for public methods + // Consider implementing a more flexible system for monster interactions + // Consider adding unit tests for this class } diff --git a/src/test/java/main/GameManagerTest.java b/src/test/java/main/GameManagerTest.java index b8c43db..1b99307 100644 --- a/src/test/java/main/GameManagerTest.java +++ b/src/test/java/main/GameManagerTest.java @@ -86,4 +86,14 @@ void testStopGameTimer() { assertNotNull(gameManager.gameTimer); } + // Add test for updateTimerUI method + // Test showLeaderboard method + // Add test for game state changes (e.g., starting a new game, ending a game) + // Test interaction between GameManager and Player class + // Add tests for monster interactions (e.g., player attacking a monster) + // Test scene changing functionality + // Add tests for handling different sound resources + // Test error handling for missing or corrupt resource files + // Add integration tests for GameManager with actual UI components + // Test performance under high load (e.g., rapid timer updates) } \ No newline at end of file diff --git a/src/test/java/main/TimeManagerTest.java b/src/test/java/main/TimeManagerTest.java index 32893df..b61abee 100644 --- a/src/test/java/main/TimeManagerTest.java +++ b/src/test/java/main/TimeManagerTest.java @@ -104,4 +104,14 @@ void testSaveLeaderboard() throws IOException { // Verify that saveLeaderboard was called verify(mockedTimeManager, times(1)).saveLeaderboard(); } +// Add test for edge cases (e.g., adding more than 10 times) +// Test behavior when adding duplicate times +// Add test for loading from an empty file +// Test exception handling for file I/O operations +// Add test for time formatting with hours (e.g., "01:30:45") +// Test concurrent access to TimeManager methods +// Add integration test with actual file I/O +// Test performance with a large number of times +// Add test for clearing all times +// Test behavior when adding invalid times (e.g., negative values) } \ No newline at end of file