diff --git a/src/FireBall.java b/src/FireBall.java index a589ff3..b0213f9 100644 --- a/src/FireBall.java +++ b/src/FireBall.java @@ -1,3 +1,6 @@ +// Eric Li, Charlie Zhao, ICS4U, Finished 6/19/2022 +// fireball object that is shot by fireball tiles; this kills players and forces them to dodge + import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.UnsupportedAudioFileException; import java.awt.*; @@ -11,7 +14,7 @@ public class FireBall extends GenericSprite{ private int lifeSpan; - + // called every time GamePanel.updateShootingBlock is called public FireBall(int x, int y, int xv, int yv, String dir,int height, int width) { super(x, y, height, width); xVelocity = xv; @@ -30,16 +33,21 @@ public class FireBall extends GenericSprite{ lifeSpan = 1000; } + // update realX position of fireball (is affected by camera.x instead of being pure x) public void update(){ realX = x-GameFrame.game.camera.x; } + // check if fireball will collide with the player public boolean collidePlayer(Player p){ if(realX+width>p.x&&realXGameFrame.game.HEIGHT){ -// dead = true; -// } } public void draw(Graphics g) throws IOException { g.drawImage(GamePanel.getImage(spritePath),x-GameFrame.game.camera.x,y,null); diff --git a/src/GameFrame.java b/src/GameFrame.java index f421a33..f0eab5a 100644 --- a/src/GameFrame.java +++ b/src/GameFrame.java @@ -1,8 +1,9 @@ +// Eric Li, Charlie Zhao, ICS4U, Completed 6/20/2022 /* GameFrame class establishes the frame (window) for the game It is a child of JFrame because JFrame manages frames -Runs the constructor in GamePanel class - -*/ +Creates new JPanel child, and adds GamePanel, MenuPanel, and SettingPanel classes to it, allowing for navigation between them +Also initializes and deserializes them as necessary +*/ import java.awt.*; import java.io.IOException; import java.nio.file.FileSystemException; @@ -25,50 +26,55 @@ public class GameFrame extends JFrame{ public GameFrame(){ try { + // CameraPanel is child of JPanel with camera object main = new CameraPanel(); + // CardLayout is used to allow navigating between the different "cards" in the menu main.setLayout(new CardLayout()); try { - game = (GamePanel)FileManager.readObjectFromFile("local/game_state.dat", Arrays.asList("Any")); + // attempts to read GamePanel object from file + // if it succeeds, this becomes the main game + // the second argument includes all the classes that are used by the GamePanel object + // this ensures that attempting to execute malicious code by tampering with saves will be more difficult, as payloads would have to stick to these classes + // please note that it is not a perfect mitigation though + game = (GamePanel)FileManager.readObjectFromFile("local/game_state.dat", + Arrays.asList("GamePanel", "javax.swing.JPanel", "javax.swing.JComponent", "java.awt.Container", + "java.awt.Component", "javax.swing.plaf.ColorUIResource", "java.awt.Color", + "javax.swing.plaf.FontUIResource", "java.awt.Font", "java.util.Locale", "java.awt.Dimension", + "java.awt.ComponentOrientation", "[Ljava.awt.Component;", "java.awt.FlowLayout", + "javax.swing.event.EventListenerList", "BackgroundImage", "BufferedImageWrapper", + "java.lang.Boolean", "Camera", "BombDirectionShow", "StickyBomb", "GenericSprite", + "java.awt.Rectangle", "java.util.ArrayList", "DialogueMenu", "TextBox", "NonPlayer", + "[[[LBufferedImageWrapper;", "[[LBufferedImageWrapper;", "[LBufferedImageWrapper;", "PauseMenu", + "WallSign", "[[LTile;", "[LTile;", "SingleTile", "Tile", "Particle", "Player")); game.gameFrame = main; + // shows that the game can be continued, as it was loaded from the file game.isContinue = true; + // requests focus from OS; this is needed because otherwise Windows will not pass keystrokes to game game.requestFocusable(); + // add mouse listener to game game.addMouseListener(); } catch (IOException | ClassNotFoundException | ClassCastException | SecurityException e) { - System.out.println(e); + // if an exception occurs during serialization, it is not a game-breaking exception; it is logged in the console and a new game is created + System.out.println("[LOG] NotAnError: " + e); game = new GamePanel(main); //run GamePanel constructor } - // delete saves to prevent unexpected behaviour - try { - Files.deleteIfExists(Path.of("local/game_state.dat")); - Files.deleteIfExists(Path.of("local/temp_state.dat")); - } catch (FileSystemException e) { - System.out.println(e); - } + // start game thread to allow the game to run game.startThread(); // save game after load to prevent lag spikes during the game FileManager.writeObjectToFile("local\\temp_state.dat", game); - /* - try { - // read previously saved controls - // SafeObjectInputStream was implemented to prevent arbitrary code execution from occurring if the save files were modified - game.middlewareArray = (ArrayList)FileManager. - readObjectFromFile("local/controls", Arrays.asList("java.util.ArrayList", "Middleware")); - } catch (IOException | ClassNotFoundException | ClassCastException | SecurityException e) { - game.middlewareArray = new ArrayList(); - } - */ + // create menu screen and settings screen menu = new MenuPanel(main); settings = new SettingPanel(main); + // adds all three panels to the CardLayout CameraPanel main, to allow for navigation between them + // the menu screen is added first because it is the first screen to show upon loading the game main.add(menu, "menu"); main.add(settings, "settings"); main.add(game, "game"); } catch (IOException | SpriteException | UnsupportedAudioFileException | LineUnavailableException e) { - // TODO: handle IO errors gracefully - // exceptions are raised when tiles are not found or are of incorrect dimensions throw new RuntimeException(e); } this.add(main); - this.setTitle("GUI is cool!"); //set title for frame + this.setTitle("Kenney"); //set title for frame // set game icon and ignore exception (failing to set icon doesn't otherwise break program) try { this.setIconImage(GamePanel.getImage("img/misc/favicon.png")); diff --git a/src/GamePanel.java b/src/GamePanel.java index 2f3dc54..4958e16 100644 --- a/src/GamePanel.java +++ b/src/GamePanel.java @@ -316,8 +316,6 @@ public class GamePanel extends JPanel implements Runnable, KeyListener, Serializ if (particles.get(i).lifeSpan <= 0) { particles.remove(i); } - } else { - throw new RuntimeException(); // TODO: remove stack trace } } // show bomb trajectory preview if player is able to throw a bomb diff --git a/src/GenericSprite.java b/src/GenericSprite.java index 587aa5b..b2b8f91 100644 --- a/src/GenericSprite.java +++ b/src/GenericSprite.java @@ -1,4 +1,5 @@ -/* PlayerBall class defines behaviours for the player-controlled ball +// Eric Li, Charlie Zhao, ICS4U, completed 6/10/2022 +/* GenericSprite class defines behaviours for all objects that move child of Rectangle because that makes it easy to draw and check for collision @@ -15,7 +16,6 @@ public class GenericSprite extends Rectangle implements Serializable { public double yVelocity; public double xVelocity; - public final double SPEED = 20; //movement speed of ball public final double speedCapx = 50; public final double speedCapy = 20; @@ -29,7 +29,6 @@ public class GenericSprite extends Rectangle implements Serializable { public boolean isPlayer = false; //constructor creates ball at given location with given dimensions - // TODO: reverse order of height and width public GenericSprite(int x, int y, int height, int width){ super(x, y, width, height); WIDTH = width; @@ -63,6 +62,7 @@ public class GenericSprite extends Rectangle implements Serializable { } + // caps x and y velocity at speedCapx and speedCapy respectively public void capSpeed(){ if(xVelocity>speedCapx){ xVelocity = speedCapx; @@ -76,6 +76,7 @@ public class GenericSprite extends Rectangle implements Serializable { } } + // checks if the sprite is colliding with a tile public boolean collide(Tile tile, double x, double y){ if(tile==null){return false;} if(!tile.collision){ @@ -87,6 +88,7 @@ public class GenericSprite extends Rectangle implements Serializable { return false; } + // checks if the sprite can move x in the x plane and y in the y plane public boolean canUpdate(double x, double y) throws UnsupportedAudioFileException, LineUnavailableException, IOException { boolean canUpdate = true; int lowX = Math.max(0, (this.x+GamePanel.GAME_WIDTH/2)/Tile.length-4); @@ -109,8 +111,8 @@ public class GenericSprite extends Rectangle implements Serializable { } return canUpdate; } - //called frequently from the GamePanel class - //draws the current location of the ball to the screen + + //draws the current location of the sprite to the screen public void draw(Graphics g) throws IOException, UnsupportedAudioFileException, LineUnavailableException {