Add more comments

master
John 2022-06-20 14:45:05 -07:00
parent 1c3cecb6e3
commit 20f5d4b3b5
4 changed files with 47 additions and 36 deletions

View File

@ -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.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException; import javax.sound.sampled.UnsupportedAudioFileException;
import java.awt.*; import java.awt.*;
@ -11,7 +14,7 @@ public class FireBall extends GenericSprite{
private int lifeSpan; 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) { public FireBall(int x, int y, int xv, int yv, String dir,int height, int width) {
super(x, y, height, width); super(x, y, height, width);
xVelocity = xv; xVelocity = xv;
@ -30,16 +33,21 @@ public class FireBall extends GenericSprite{
lifeSpan = 1000; lifeSpan = 1000;
} }
// update realX position of fireball (is affected by camera.x instead of being pure x)
public void update(){ public void update(){
realX = x-GameFrame.game.camera.x; realX = x-GameFrame.game.camera.x;
} }
// check if fireball will collide with the player
public boolean collidePlayer(Player p){ public boolean collidePlayer(Player p){
if(realX+width>p.x&&realX<p.x+Player.PLAYER_WIDTH&&y-p.y<Player.PLAYER_HEIGHT&&p.y-y<height){ if(realX+width>p.x&&realX<p.x+Player.PLAYER_WIDTH&&y-p.y<Player.PLAYER_HEIGHT&&p.y-y<height){
return true; return true;
} }
return false; return false;
} }
// kills fireball if fireball has existed for longer than lifeSpan ticks
// moves fireball and kills it if it hits a block or a player
// kills player and resets level if it hits a player
public void move() throws UnsupportedAudioFileException, LineUnavailableException, IOException { public void move() throws UnsupportedAudioFileException, LineUnavailableException, IOException {
lifeSpan--; lifeSpan--;
if(lifeSpan<=0){ if(lifeSpan<=0){
@ -56,9 +64,6 @@ public class FireBall extends GenericSprite{
dead = true; dead = true;
GameFrame.game.player.reset(); GameFrame.game.player.reset();
} }
// if(y<0||y>GameFrame.game.HEIGHT){
// dead = true;
// }
} }
public void draw(Graphics g) throws IOException { public void draw(Graphics g) throws IOException {
g.drawImage(GamePanel.getImage(spritePath),x-GameFrame.game.camera.x,y,null); g.drawImage(GamePanel.getImage(spritePath),x-GameFrame.game.camera.x,y,null);

View File

@ -1,8 +1,9 @@
// Eric Li, Charlie Zhao, ICS4U, Completed 6/20/2022
/* GameFrame class establishes the frame (window) for the game /* GameFrame class establishes the frame (window) for the game
It is a child of JFrame because JFrame manages frames 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.awt.*;
import java.io.IOException; import java.io.IOException;
import java.nio.file.FileSystemException; import java.nio.file.FileSystemException;
@ -25,50 +26,55 @@ public class GameFrame extends JFrame{
public GameFrame(){ public GameFrame(){
try { try {
// CameraPanel is child of JPanel with camera object
main = new CameraPanel(); main = new CameraPanel();
// CardLayout is used to allow navigating between the different "cards" in the menu
main.setLayout(new CardLayout()); main.setLayout(new CardLayout());
try { 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; game.gameFrame = main;
// shows that the game can be continued, as it was loaded from the file
game.isContinue = true; game.isContinue = true;
// requests focus from OS; this is needed because otherwise Windows will not pass keystrokes to game
game.requestFocusable(); game.requestFocusable();
// add mouse listener to game
game.addMouseListener(); game.addMouseListener();
} catch (IOException | ClassNotFoundException | ClassCastException | SecurityException e) { } 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 game = new GamePanel(main); //run GamePanel constructor
} }
// delete saves to prevent unexpected behaviour // start game thread to allow the game to run
try {
Files.deleteIfExists(Path.of("local/game_state.dat"));
Files.deleteIfExists(Path.of("local/temp_state.dat"));
} catch (FileSystemException e) {
System.out.println(e);
}
game.startThread(); game.startThread();
// save game after load to prevent lag spikes during the game // save game after load to prevent lag spikes during the game
FileManager.writeObjectToFile("local\\temp_state.dat", game); FileManager.writeObjectToFile("local\\temp_state.dat", game);
/* // create menu screen and settings screen
try {
// read previously saved controls
// SafeObjectInputStream was implemented to prevent arbitrary code execution from occurring if the save files were modified
game.middlewareArray = (ArrayList<Middleware>)FileManager.
readObjectFromFile("local/controls", Arrays.asList("java.util.ArrayList", "Middleware"));
} catch (IOException | ClassNotFoundException | ClassCastException | SecurityException e) {
game.middlewareArray = new ArrayList<Middleware>();
}
*/
menu = new MenuPanel(main); menu = new MenuPanel(main);
settings = new SettingPanel(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(menu, "menu");
main.add(settings, "settings"); main.add(settings, "settings");
main.add(game, "game"); main.add(game, "game");
} catch (IOException | SpriteException | UnsupportedAudioFileException | LineUnavailableException e) { } 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); throw new RuntimeException(e);
} }
this.add(main); 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) // set game icon and ignore exception (failing to set icon doesn't otherwise break program)
try { try {
this.setIconImage(GamePanel.getImage("img/misc/favicon.png")); this.setIconImage(GamePanel.getImage("img/misc/favicon.png"));

View File

@ -316,8 +316,6 @@ public class GamePanel extends JPanel implements Runnable, KeyListener, Serializ
if (particles.get(i).lifeSpan <= 0) { if (particles.get(i).lifeSpan <= 0) {
particles.remove(i); particles.remove(i);
} }
} else {
throw new RuntimeException(); // TODO: remove stack trace
} }
} }
// show bomb trajectory preview if player is able to throw a bomb // show bomb trajectory preview if player is able to throw a bomb

View File

@ -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 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 yVelocity;
public double xVelocity; public double xVelocity;
public final double SPEED = 20; //movement speed of ball
public final double speedCapx = 50; public final double speedCapx = 50;
public final double speedCapy = 20; public final double speedCapy = 20;
@ -29,7 +29,6 @@ public class GenericSprite extends Rectangle implements Serializable {
public boolean isPlayer = false; public boolean isPlayer = false;
//constructor creates ball at given location with given dimensions //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){ public GenericSprite(int x, int y, int height, int width){
super(x, y, width, height); super(x, y, width, height);
WIDTH = width; 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(){ public void capSpeed(){
if(xVelocity>speedCapx){ if(xVelocity>speedCapx){
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){ public boolean collide(Tile tile, double x, double y){
if(tile==null){return false;} if(tile==null){return false;}
if(!tile.collision){ if(!tile.collision){
@ -87,6 +88,7 @@ public class GenericSprite extends Rectangle implements Serializable {
return false; 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 { public boolean canUpdate(double x, double y) throws UnsupportedAudioFileException, LineUnavailableException, IOException {
boolean canUpdate = true; boolean canUpdate = true;
int lowX = Math.max(0, (this.x+GamePanel.GAME_WIDTH/2)/Tile.length-4); 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; 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 { public void draw(Graphics g) throws IOException, UnsupportedAudioFileException, LineUnavailableException {