Merge remote-tracking branch 'origin/master'
# Conflicts: # src/LevelManager.javamaster
commit
045c1e3afd
|
@ -0,0 +1 @@
|
||||||
|
Press P to skip to the next level.
|
|
@ -1,8 +1,10 @@
|
||||||
|
// Eric Li, Charlie Zhao, ICS4U, Finished 6/17/2022
|
||||||
|
// displays dialogue, animates dialogue, and renders box that contains dialogue as well as the portraits of the characters
|
||||||
|
// that speak to the players
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
public class DialogueMenu extends TextBox implements Serializable {
|
public class DialogueMenu extends TextBox implements Serializable {
|
||||||
public static final int PORTRAIT_WIDTH = 200;
|
public static final int PORTRAIT_WIDTH = 200;
|
||||||
|
@ -10,18 +12,19 @@ public class DialogueMenu extends TextBox implements Serializable {
|
||||||
public static final int TOP_PADDING = 10;
|
public static final int TOP_PADDING = 10;
|
||||||
public static final double LINE_SPACING = 1.5;
|
public static final double LINE_SPACING = 1.5;
|
||||||
public static final int FREQUENCY = 2;
|
public static final int FREQUENCY = 2;
|
||||||
public BufferedImageWrapper PORTRAIT;
|
public BufferedImageWrapper portrait;
|
||||||
public int currentFrame = 0;
|
public int currentFrame = 0;
|
||||||
public int frameCounter = 0;
|
public int frameCounter = 0;
|
||||||
public boolean isNarrator;
|
public boolean isNarrator;
|
||||||
|
|
||||||
public DialogueMenu(int y, int yHeight, Font font, BufferedImageWrapper portrait, boolean isNarrator) {
|
public DialogueMenu(int y, int yHeight, Font font, BufferedImageWrapper portrait, boolean isNarrator) {
|
||||||
super(y, GamePanel.GAME_WIDTH - PORTRAIT_WIDTH - PADDING*3, yHeight, 0, font, null, null);
|
super(y, GamePanel.GAME_WIDTH - PORTRAIT_WIDTH - PADDING*3, yHeight, 0, font, null, null);
|
||||||
PORTRAIT = portrait;
|
this.portrait = portrait;
|
||||||
checkForNarrator();
|
checkForNarrator();
|
||||||
this.isNarrator = isNarrator;
|
this.isNarrator = isNarrator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if the person speaking is currently the narrator, and adjust the newX value accordingly
|
||||||
public void checkForNarrator() {
|
public void checkForNarrator() {
|
||||||
if (isNarrator) {
|
if (isNarrator) {
|
||||||
newX = PORTRAIT_WIDTH + PADDING*2;
|
newX = PORTRAIT_WIDTH + PADDING*2;
|
||||||
|
@ -30,64 +33,85 @@ public class DialogueMenu extends TextBox implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// draw a centered text box
|
||||||
public void drawCenteredTextBox(Graphics g, String text, Color backgroundColor, Color textColor) {
|
public void drawCenteredTextBox(Graphics g, String text, Color backgroundColor, Color textColor) {
|
||||||
|
// only draw currentFrame number of text characters; this animates the process of drawing the text
|
||||||
text = text.substring(0, currentFrame);
|
text = text.substring(0, currentFrame);
|
||||||
|
// only set the background color if it is not null
|
||||||
if (backgroundColor != null) {
|
if (backgroundColor != null) {
|
||||||
g.setColor(textColor);
|
g.setColor(textColor);
|
||||||
|
// if the person speaking is the narrator, draw the textbox to the right of the portrait
|
||||||
if (isNarrator) {
|
if (isNarrator) {
|
||||||
g.drawImage(PORTRAIT.image, newX - PORTRAIT_WIDTH - PADDING, newY, PORTRAIT_WIDTH, yHeight, null);
|
g.drawImage(portrait.image, newX - PORTRAIT_WIDTH - PADDING, newY, PORTRAIT_WIDTH, yHeight, null);
|
||||||
} else {
|
} else { // otherwise, draw the textbox to the left of the portrait
|
||||||
g.drawImage(PORTRAIT.image, GamePanel.GAME_WIDTH - PORTRAIT_WIDTH - PADDING, newY, PORTRAIT_WIDTH, yHeight, null);
|
g.drawImage(portrait.image, GamePanel.GAME_WIDTH - PORTRAIT_WIDTH - PADDING, newY, PORTRAIT_WIDTH, yHeight, null);
|
||||||
}
|
}
|
||||||
|
// create border and set it to a width of 4.0
|
||||||
((Graphics2D)g).setStroke(new BasicStroke(4f));
|
((Graphics2D)g).setStroke(new BasicStroke(4f));
|
||||||
|
// draw the border
|
||||||
g.drawRect(newX, newY, xWidth, yHeight - 4);
|
g.drawRect(newX, newY, xWidth, yHeight - 4);
|
||||||
|
// set color of the rectangle inside the border, and draw it
|
||||||
g.setColor(backgroundColor);
|
g.setColor(backgroundColor);
|
||||||
g.fillRect(newX, newY, xWidth, yHeight - 4);
|
g.fillRect(newX, newY, xWidth, yHeight - 4);
|
||||||
}
|
}
|
||||||
|
// set text color and draw it
|
||||||
g.setColor(textColor);
|
g.setColor(textColor);
|
||||||
drawCenteredString(g, newY, newX, text);
|
drawCenteredString(g, newY, newX, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// draw a centered string
|
||||||
public static void drawCenteredString(Graphics g, int y, int x, String text) {
|
public static void drawCenteredString(Graphics g, int y, int x, String text) {
|
||||||
// split text by spaces
|
// split text by spaces (into individual words)
|
||||||
String[] newText = text.split(" ");
|
String[] newText = text.split(" ");
|
||||||
ArrayList<String> lines = new ArrayList<String>();
|
// create new ArrayList that will compose of every line in the new text
|
||||||
|
ArrayList<String> lines = new ArrayList<>();
|
||||||
|
// add an empty line; this line will eventually have more text added to it
|
||||||
lines.add("");
|
lines.add("");
|
||||||
// get font size
|
// get font size
|
||||||
FontMetrics metrics = g.getFontMetrics();
|
FontMetrics metrics = g.getFontMetrics();
|
||||||
|
// declare temporary variables used in the for loop, and initialize them
|
||||||
int currentLineWidth = 0, lastLineIndex = 0;
|
int currentLineWidth = 0, lastLineIndex = 0;
|
||||||
for (String s: newText) {
|
for (String s: newText) {
|
||||||
|
// add width of new word to current line width
|
||||||
currentLineWidth += metrics.stringWidth(s + " ");
|
currentLineWidth += metrics.stringWidth(s + " ");
|
||||||
|
// if the newLineWidth still fits in the dialogue box, add it to the current line
|
||||||
if (currentLineWidth - metrics.stringWidth(" ") < (GamePanel.GAME_WIDTH - PORTRAIT_WIDTH - PADDING*5)) {
|
if (currentLineWidth - metrics.stringWidth(" ") < (GamePanel.GAME_WIDTH - PORTRAIT_WIDTH - PADDING*5)) {
|
||||||
lines.set(lastLineIndex, lines.get(lastLineIndex) + s + " ");
|
lines.set(lastLineIndex, lines.get(lastLineIndex) + s + " ");
|
||||||
} else {
|
} else { // otherwise, create a new line, set the current line width to the current width, and increment the current line index
|
||||||
currentLineWidth = metrics.stringWidth(s);
|
currentLineWidth = metrics.stringWidth(s);
|
||||||
lines.add(s + " ");
|
lines.add(s + " ");
|
||||||
lastLineIndex ++;
|
lastLineIndex ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// leave TOP_PADDING + (metrics.getAscent() - metrics.getDescent()) * LINE_SPACING)
|
||||||
|
// space between the top of the dialogue box and the text
|
||||||
y += TOP_PADDING;
|
y += TOP_PADDING;
|
||||||
// center y (half is above y value, half is below y value)
|
|
||||||
for (String s: lines) {
|
for (String s: lines) {
|
||||||
|
// add spacing since last line
|
||||||
y += (metrics.getAscent() - metrics.getDescent()) * LINE_SPACING;
|
y += (metrics.getAscent() - metrics.getDescent()) * LINE_SPACING;
|
||||||
// draw string
|
// draw actual string
|
||||||
g.drawString(s + "\n", x + PADDING, y);
|
g.drawString(s + "\n", x + PADDING, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean draw(Graphics g, String text, Color backgroundColor, Color textColor) {
|
public boolean draw(Graphics g, String text, Color backgroundColor, Color textColor) {
|
||||||
|
// before every draw, check if the status of the current person speaking changed
|
||||||
checkForNarrator();
|
checkForNarrator();
|
||||||
|
// if more than FREQUENCY ticks has passed since the last text animation, animate by drawing one more char
|
||||||
if (frameCounter >= FREQUENCY) {
|
if (frameCounter >= FREQUENCY) {
|
||||||
frameCounter -= FREQUENCY;
|
frameCounter -= FREQUENCY;
|
||||||
currentFrame += 1;
|
currentFrame += 1;
|
||||||
}
|
}
|
||||||
|
// set font of string to be drawn
|
||||||
g.setFont(font);
|
g.setFont(font);
|
||||||
drawCenteredTextBox(g, text, backgroundColor, textColor);
|
drawCenteredTextBox(g, text, backgroundColor, textColor);
|
||||||
|
// increment the frame counter
|
||||||
frameCounter++;
|
frameCounter++;
|
||||||
|
// if the text has been completely drawn (nothing left to animate), return true
|
||||||
if (currentFrame >= text.length()) {
|
if (currentFrame >= text.length()) {
|
||||||
currentFrame = 0;
|
currentFrame = 0;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else { // otherwise, return false
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
|
// 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.io.IOException;
|
|
||||||
import java.nio.file.FileSystemException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
import javax.sound.sampled.LineUnavailableException;
|
import javax.sound.sampled.LineUnavailableException;
|
||||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class GameFrame extends JFrame{
|
public class GameFrame extends JFrame{
|
||||||
|
|
||||||
|
@ -25,50 +21,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] " + e.toString().replace("Exception", "NotAnError"));
|
||||||
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"));
|
||||||
|
|
|
@ -9,21 +9,21 @@ Implements KeyListener interface to listen for keyboard input
|
||||||
Implements Runnable interface to use "threading" - let the game do two things at once
|
Implements Runnable interface to use "threading" - let the game do two things at once
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.sound.sampled.LineUnavailableException;
|
||||||
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
import javax.sound.sampled.LineUnavailableException;
|
|
||||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import static java.nio.file.StandardCopyOption.ATOMIC_MOVE;
|
import static java.nio.file.StandardCopyOption.ATOMIC_MOVE;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
/* 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
|
||||||
|
|
||||||
In 2D GUI, basically everything is a rectangle even if it doesn't look like it!
|
In 2D GUI, basically everything is a rectangle even if it doesn't look like it!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@ -15,7 +18,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 +31,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 +64,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 +78,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 +90,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 +113,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 {
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
|
// Eric Li, Charlie Zhao, ICS4U, Finished 6/19/2022
|
||||||
|
// determines the standard time unit for exploding objects (i.e., bombs)
|
||||||
|
// while not very useful now, GlobalState was added to increase extensibility in the future
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
public class GlobalState implements Serializable {
|
public class GlobalState implements Serializable {
|
||||||
|
// each object takes GlobalState.second * 5 ticks to explode
|
||||||
public static final int second = 10;
|
public static final int second = 10;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,26 +12,30 @@ public class LevelManager implements Serializable {
|
||||||
public static String filePath;
|
public static String filePath;
|
||||||
|
|
||||||
public static int bombs;
|
public static int bombs;
|
||||||
|
// set current level, then load the map, enemies, dialogue, signs, and bomb count for that level
|
||||||
public static void setLevel(int level, boolean hasDied){
|
public static void setLevel(int level, boolean hasDied){
|
||||||
|
// remove all current bombs and fireballs
|
||||||
GameFrame.game.bombs.clear();
|
GameFrame.game.bombs.clear();
|
||||||
GameFrame.game.fireballs.clear();
|
GameFrame.game.fireballs.clear();
|
||||||
|
// set the player velocity to zero
|
||||||
GameFrame.game.player.yVelocity = 0;
|
GameFrame.game.player.yVelocity = 0;
|
||||||
GameFrame.game.player.xVelocity = 0;
|
GameFrame.game.player.xVelocity = 0;
|
||||||
GameFrame.game.level = level;
|
GameFrame.game.level = level;
|
||||||
|
// change spawn coordinates, bomb count, and save file path based on level inputted
|
||||||
if(level == 1){
|
if(level == 1){
|
||||||
//-400/450
|
// spawn coordinates: -400/450
|
||||||
xSpawn = -400;
|
xSpawn = -400;
|
||||||
ySpawn = 450;
|
ySpawn = 450;
|
||||||
filePath = "saves/Level1.txt";
|
filePath = "saves/Level1.txt";
|
||||||
bombs = 8;
|
bombs = 8;
|
||||||
} else if(level == 2){
|
} else if(level == 2){
|
||||||
//-400/400
|
// spawn coordinates: -400/400
|
||||||
xSpawn = -400;
|
xSpawn = -400;
|
||||||
ySpawn = 400;
|
ySpawn = 400;
|
||||||
filePath = "saves/Level2.txt";
|
filePath = "saves/Level2.txt";
|
||||||
bombs = 3;
|
bombs = 3;
|
||||||
} else if(level == 3){
|
} else if(level == 3){
|
||||||
//-800/100
|
// spawn coordinates: -800/100
|
||||||
xSpawn = -800;
|
xSpawn = -800;
|
||||||
ySpawn = 100;
|
ySpawn = 100;
|
||||||
filePath = "saves/Level3.txt";
|
filePath = "saves/Level3.txt";
|
||||||
|
@ -43,24 +47,34 @@ public class LevelManager implements Serializable {
|
||||||
filePath = "saves/Level4.txt";
|
filePath = "saves/Level4.txt";
|
||||||
bombs = 5;
|
bombs = 5;
|
||||||
} else if(level == 5){
|
} else if(level == 5){
|
||||||
//-1100/350
|
//-1100/460
|
||||||
xSpawn = 1800;
|
xSpawn = -1100;
|
||||||
ySpawn = 150;
|
ySpawn = 350;
|
||||||
filePath = "saves/Level5.txt";
|
filePath = "saves/Level5.txt";
|
||||||
bombs = 1;
|
bombs = 1;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
// load map into GamePanel
|
||||||
MapReader.inputMap(filePath);
|
MapReader.inputMap(filePath);
|
||||||
|
// if the player has not died yet (i.e., first time seeing the dialogue), load it
|
||||||
if (!hasDied) {
|
if (!hasDied) {
|
||||||
|
// do not load dialogue if there is no dialogue to load
|
||||||
if (!(MapReader.inputDialogue(filePath)[0].equals("$Empty"))) {
|
if (!(MapReader.inputDialogue(filePath)[0].equals("$Empty"))) {
|
||||||
GameFrame.game.dialogueArray = new ArrayList<String>(Arrays.asList(MapReader.inputDialogue(filePath)));
|
// convert dialogue from String[] to ArrayList<String>, and load it into GamePanel
|
||||||
|
GameFrame.game.dialogueArray = new ArrayList<>(Arrays.asList(MapReader.inputDialogue(filePath)));
|
||||||
|
// if the dialogue file starts with $Villain, have the portrait display on the right side of the screen, and display the alternate portrait
|
||||||
if (GameFrame.game.dialogueArray.get(0).contains("$Villain")) {
|
if (GameFrame.game.dialogueArray.get(0).contains("$Villain")) {
|
||||||
|
// delete the first item in the array so the villain does not say "$Villain"
|
||||||
GameFrame.game.dialogueArray.remove(0);
|
GameFrame.game.dialogueArray.remove(0);
|
||||||
|
// display portrait on right side of screen
|
||||||
GameFrame.game.dialogueMenu.isNarrator = false;
|
GameFrame.game.dialogueMenu.isNarrator = false;
|
||||||
GameFrame.game.dialogueMenu.PORTRAIT = GameFrame.game.villainPortrait;
|
// change portrait
|
||||||
|
GameFrame.game.dialogueMenu.portrait = GameFrame.game.villainPortrait;
|
||||||
}
|
}
|
||||||
|
// reset dialogue frame to zero, so it restarts the animation every time the dialogue is loaded
|
||||||
GameFrame.game.dialogueMenu.currentFrame = 0;
|
GameFrame.game.dialogueMenu.currentFrame = 0;
|
||||||
GameFrame.game.dialogueMenu.frameCounter = 0;
|
GameFrame.game.dialogueMenu.frameCounter = 0;
|
||||||
|
// tell the GameFrame to load the DialogueMenu
|
||||||
GameFrame.game.isDialogue = true;
|
GameFrame.game.isDialogue = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,12 +84,15 @@ public class LevelManager implements Serializable {
|
||||||
// temporary boolean, so only declared here
|
// temporary boolean, so only declared here
|
||||||
boolean stillTutorial = true;
|
boolean stillTutorial = true;
|
||||||
for (String[] sA: MapReader.inputSign(filePath)) {
|
for (String[] sA: MapReader.inputSign(filePath)) {
|
||||||
|
// if the line contains "/", skip the line, stop adding signs to tutorialSign and instead add signs to loreSign
|
||||||
|
// this is important because loreSigns and tutorialSigns have different colours and font types
|
||||||
if (sA[0].contains("/")) {
|
if (sA[0].contains("/")) {
|
||||||
stillTutorial = false;
|
stillTutorial = false;
|
||||||
} else if (stillTutorial) {
|
} else if (stillTutorial) {
|
||||||
//System.out.println("" + sA[0] + sA[1]);
|
// add sign to tutorialSign
|
||||||
GameFrame.game.tutorialSign.add(new WallSign(Integer.parseInt(sA[0]), Integer.parseInt(sA[1]), GamePanel.tutorialFont, sA[2]));
|
GameFrame.game.tutorialSign.add(new WallSign(Integer.parseInt(sA[0]), Integer.parseInt(sA[1]), GamePanel.tutorialFont, sA[2]));
|
||||||
} else {
|
} else {
|
||||||
|
// add sign to loreSign if stillTutorial is false
|
||||||
GameFrame.game.loreSign.add(new WallSign(Integer.parseInt(sA[0]), Integer.parseInt(sA[1]), GamePanel.loreFont, sA[2]));
|
GameFrame.game.loreSign.add(new WallSign(Integer.parseInt(sA[0]), Integer.parseInt(sA[1]), GamePanel.loreFont, sA[2]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,6 +104,7 @@ public class LevelManager implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Gives the player bombs
|
||||||
public static void setBombs(){
|
public static void setBombs(){
|
||||||
if(GameFrame.game.level == 1){
|
if(GameFrame.game.level == 1){
|
||||||
bombs = 8;
|
bombs = 8;
|
||||||
|
@ -100,9 +118,11 @@ public class LevelManager implements Serializable {
|
||||||
bombs = 1;
|
bombs = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// overloaded setLevel that accepts only a level argument
|
||||||
public static void setLevel(int level) {
|
public static void setLevel(int level) {
|
||||||
setLevel(level, false);
|
setLevel(level, false);
|
||||||
}
|
}
|
||||||
|
// go to the next level
|
||||||
public static void nextLevel(){
|
public static void nextLevel(){
|
||||||
setLevel(GameFrame.game.level+1);
|
setLevel(GameFrame.game.level+1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// Eric Li, Charlie Zhao, ICS4U, Finished 5/30/2022
|
||||||
/* Main class starts the game
|
/* Main class starts the game
|
||||||
All it does is run the constructor in GameFrame class
|
All it does is run the constructor in GameFrame class
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
|
// Eric Li, Charlie Zhao, ICS4U, Finished 6/16/2022
|
||||||
|
// reads map, dialogue, and signs from files and loads them into GamePanel
|
||||||
|
|
||||||
import javax.sound.sampled.LineUnavailableException;
|
import javax.sound.sampled.LineUnavailableException;
|
||||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
import java.io.*;
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class MapReader implements Serializable {
|
public class MapReader implements Serializable {
|
||||||
//Input game map
|
// loads game map into GamePanel
|
||||||
/*
|
/*
|
||||||
1: Normal Grass
|
1: Normal Grass
|
||||||
2: Left Grass:
|
2: Left Grass:
|
||||||
|
@ -23,28 +27,36 @@ public class MapReader implements Serializable {
|
||||||
// h k Shooting
|
// h k Shooting
|
||||||
// m
|
// m
|
||||||
public static void inputMap(String filePath) throws IOException, SpriteException, UnsupportedAudioFileException, LineUnavailableException {
|
public static void inputMap(String filePath) throws IOException, SpriteException, UnsupportedAudioFileException, LineUnavailableException {
|
||||||
|
int TileX, TileY;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
int TileX = 0;
|
// clears existing enemies, particles, fireball shooters, and fireballs
|
||||||
int TileY = 0;
|
|
||||||
GameFrame.game.enemy.clear();
|
GameFrame.game.enemy.clear();
|
||||||
GameFrame.game.particleTiles.clear();
|
GameFrame.game.particleTiles.clear();
|
||||||
GameFrame.game.shootingTiles.clear();
|
GameFrame.game.shootingTiles.clear();
|
||||||
GameFrame.game.fireballs.clear();
|
GameFrame.game.fireballs.clear();
|
||||||
|
// clears current map
|
||||||
for(int i=0; i<GameFrame.game.map.length; i++){
|
for(int i=0; i<GameFrame.game.map.length; i++){
|
||||||
Arrays.fill(GameFrame.game.map[i], null);
|
Arrays.fill(GameFrame.game.map[i], null);
|
||||||
}
|
}
|
||||||
|
// read new map file
|
||||||
String file = FileManager.readFile(filePath);
|
String file = FileManager.readFile(filePath);
|
||||||
|
// converts characters in map file into Tiles
|
||||||
for(int i=0; i<file.length(); i++){
|
for(int i=0; i<file.length(); i++){
|
||||||
|
// if a newline is reached, reset x position to 0 and increase y position by 1
|
||||||
if(file.charAt(i)=='\n'){
|
if(file.charAt(i)=='\n'){
|
||||||
y+=1;
|
y+=1;
|
||||||
x=0;
|
x=0;
|
||||||
}
|
}
|
||||||
|
// each x position translates into an actual pixel position of x*Tile.length - (GamePanel.GAME_WIDTH/2) on the screen
|
||||||
TileX = x*Tile.length - (GamePanel.GAME_WIDTH/2);
|
TileX = x*Tile.length - (GamePanel.GAME_WIDTH/2);
|
||||||
if(y==0){
|
if(y==0){ // if the tile is on the first row, it's shifted to the right to adjust for the start of the file
|
||||||
TileX += Tile.length;
|
TileX += Tile.length;
|
||||||
}
|
}
|
||||||
|
// each y position translates into an actual pixel position of y*Tile.length on the screen; please note that Tile.length was used
|
||||||
|
// instead of something like Tile.height because Tiles are rectangles
|
||||||
TileY = y*Tile.length;
|
TileY = y*Tile.length;
|
||||||
|
// if the char at the specific position in the file matches one of the options below, a tile with an image located at filePath is inserted at that position with newTile()
|
||||||
if(file.charAt(i)=='1'){
|
if(file.charAt(i)=='1'){
|
||||||
newTile("img/tiles/terrain/grass.png", x, y, TileX, TileY);
|
newTile("img/tiles/terrain/grass.png", x, y, TileX, TileY);
|
||||||
} else if(file.charAt(i)=='2'){
|
} else if(file.charAt(i)=='2'){
|
||||||
|
@ -77,31 +89,30 @@ public class MapReader implements Serializable {
|
||||||
newTile("img/tiles/terrain/cornerBottomLeft.png", x, y, TileX, TileY);
|
newTile("img/tiles/terrain/cornerBottomLeft.png", x, y, TileX, TileY);
|
||||||
} else if(file.charAt(i)=='g'){
|
} else if(file.charAt(i)=='g'){
|
||||||
newTile("img/tiles/terrain/cornerBottomRight.png", x, y, TileX, TileY);
|
newTile("img/tiles/terrain/cornerBottomRight.png", x, y, TileX, TileY);
|
||||||
} else if(file.charAt(i)=='b'){
|
} else if(file.charAt(i)=='b'){ // this tile has its breakable variable set to true after being created by newTile() to let it be blown up by explosions
|
||||||
newTile("img/tiles/boxes/box.png", x, y, TileX, TileY);
|
newTile("img/tiles/boxes/box.png", x, y, TileX, TileY);
|
||||||
GameFrame.game.map[x][y].breakable = true;
|
GameFrame.game.map[x][y].breakable = true;
|
||||||
} else if(file.charAt(i)=='!'){
|
} else if(file.charAt(i)=='!'){ // instead of adding a tile, add an enemy slime at this location
|
||||||
GameFrame.game.enemy.add(new NonPlayer(TileX, TileY, GameFrame.game.slimeSpriteArray, 50, 28, 100));
|
GameFrame.game.enemy.add(new NonPlayer(TileX, TileY, GameFrame.game.slimeSpriteArray, 50, 28, 100));
|
||||||
|
} else if(file.charAt(i)=='+') { // this tile will send the player to the next level when the player steps on it
|
||||||
} else if(file.charAt(i)=='+') {
|
|
||||||
newTile("img/tiles/boxes/finish.png", x, y, TileX, TileY);
|
newTile("img/tiles/boxes/finish.png", x, y, TileX, TileY);
|
||||||
GameFrame.game.map[x][y].isFinish = true;
|
GameFrame.game.map[x][y].isFinish = true;
|
||||||
GameFrame.game.map[x][y].nonBombCollide = true;
|
GameFrame.game.map[x][y].nonBombCollide = true;
|
||||||
} else if(file.charAt(i)=='v'){
|
} else if(file.charAt(i)=='v'){ // this tile is a tile that is part of the background; it is not subject to collisions or bomb explosions
|
||||||
newTile("img/tiles/background/wall.png", x, y, TileX, TileY);
|
newTile("img/tiles/background/wall.png", x, y, TileX, TileY);
|
||||||
GameFrame.game.map[x][y].collision = false;
|
GameFrame.game.map[x][y].collision = false;
|
||||||
GameFrame.game.map[x][y].replaceAble = true;
|
GameFrame.game.map[x][y].replaceAble = true;
|
||||||
} else if(file.charAt(i)=='l'){
|
} else if(file.charAt(i)=='l'){ // this tile will kill you on contact; lava tiles also generate particles
|
||||||
newTile("img/tiles/terrain/lava.png", x, y, TileX, TileY);
|
newTile("img/tiles/terrain/lava.png", x, y, TileX, TileY);
|
||||||
GameFrame.game.map[x][y].nonBombCollide = true;
|
GameFrame.game.map[x][y].nonBombCollide = true;
|
||||||
GameFrame.game.map[x][y].kills = true;
|
GameFrame.game.map[x][y].kills = true;
|
||||||
if(y>0&&GameFrame.game.map[x][y-1]==null) {
|
if(y>0&&GameFrame.game.map[x][y-1]==null) {
|
||||||
GameFrame.game.particleTiles.add(GameFrame.game.map[x][y]);
|
GameFrame.game.particleTiles.add(GameFrame.game.map[x][y]);
|
||||||
}
|
}
|
||||||
} else if(file.charAt(i)=='o'){
|
} else if(file.charAt(i)=='o'){ // steel tiles can be picked up and moved
|
||||||
newTile("img/tiles/boxes/steel.png", x, y, TileX, TileY);
|
newTile("img/tiles/boxes/steel.png", x, y, TileX, TileY);
|
||||||
GameFrame.game.map[x][y].movable = true;
|
GameFrame.game.map[x][y].movable = true;
|
||||||
} else if(file.charAt(i)=='h'){
|
} else if(file.charAt(i)=='h'){ // the following tiles shoot fireballs in the directions indicated; these fireballs kill players on contact
|
||||||
newTile("img/tiles/boxes/boxShootLeft.png", x, y, TileX, TileY);
|
newTile("img/tiles/boxes/boxShootLeft.png", x, y, TileX, TileY);
|
||||||
GameFrame.game.map[x][y].shootingDir = "left";
|
GameFrame.game.map[x][y].shootingDir = "left";
|
||||||
GameFrame.game.shootingTiles.add(GameFrame.game.map[x][y]);
|
GameFrame.game.shootingTiles.add(GameFrame.game.map[x][y]);
|
||||||
|
@ -118,25 +129,28 @@ public class MapReader implements Serializable {
|
||||||
GameFrame.game.map[x][y].shootingDir = "down";
|
GameFrame.game.map[x][y].shootingDir = "down";
|
||||||
GameFrame.game.shootingTiles.add(GameFrame.game.map[x][y]);
|
GameFrame.game.shootingTiles.add(GameFrame.game.map[x][y]);
|
||||||
}
|
}
|
||||||
x+=1;
|
x+=1; // increment x value by one after every character read
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return dialogue array given the filePath inputted in inputMath for further processing in LevelManager
|
||||||
public static String[] inputDialogue(String mapFilePath) throws IOException {
|
public static String[] inputDialogue(String mapFilePath) throws IOException {
|
||||||
String filePath = mapFilePath.replace(".txt", "-dialogue.txt");
|
String filePath = mapFilePath.replace(".txt", "-dialogue.txt"); // format path to open the dialogue file instead
|
||||||
return FileManager.readFile(filePath).split("\n");
|
return FileManager.readFile(filePath).split("\n"); // read and split file, before returning
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayList<String[]> inputSign(String signFilePath) throws IOException {
|
// return sign array given the filePath inputted in inputMath for further processing in LevelManager
|
||||||
String filePath = signFilePath.replace(".txt", "-signs.txt");
|
public static ArrayList<String[]> inputSign(String mapFilePath) throws IOException {
|
||||||
|
String filePath = mapFilePath.replace(".txt", "-signs.txt"); // format path to open the sign file instead
|
||||||
String[] temporaryStringArray = FileManager.readFile(filePath).split("\n");
|
String[] temporaryStringArray = FileManager.readFile(filePath).split("\n");
|
||||||
ArrayList<String[]> returnArray = new ArrayList<String[]>();
|
ArrayList<String[]> returnArray = new ArrayList<>(); // create new ArrayList<String[]> and populate it with details about the text
|
||||||
for (String s: temporaryStringArray) {
|
for (String s: temporaryStringArray) {
|
||||||
returnArray.add(s.split(" ", 3));
|
returnArray.add(s.split(" ", 3)); // s[0] = x, s[1] = y, s[2] = text; given that the text often has spaces, the amount of items resulting from the split was limited to three
|
||||||
}
|
}
|
||||||
return returnArray;
|
return returnArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// populate GamePanel tile array with new tile with TileX and TileY positions
|
||||||
public static void newTile(String filePath, int x, int y, int TileX, int TileY) throws IOException, SpriteException {
|
public static void newTile(String filePath, int x, int y, int TileX, int TileY) throws IOException, SpriteException {
|
||||||
GameFrame.game.map[x][y]=(new SingleTile(TileX,TileY, new BufferedImageWrapper((filePath))));
|
GameFrame.game.map[x][y]=(new SingleTile(TileX,TileY, new BufferedImageWrapper((filePath))));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* GamePanel class acts as the main "game loop" - continuously runs the game and calls whatever needs to be called
|
// Eric Li, Charlie Zhao, ICS4U, Finished 6/17/2022
|
||||||
|
/* MenuPanel class acts as the menu - launches the other panels that need to be called
|
||||||
|
|
||||||
Child of JPanel because JPanel contains methods for drawing to the screen
|
Child of JPanel because JPanel contains methods for drawing to the screen
|
||||||
|
|
||||||
|
@ -7,15 +8,15 @@ Implements KeyListener interface to listen for keyboard input
|
||||||
Implements Runnable interface to use "threading" - let the game do two things at once
|
Implements Runnable interface to use "threading" - let the game do two things at once
|
||||||
|
|
||||||
*/
|
*/
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.*;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import javax.sound.sampled.LineUnavailableException;
|
import javax.sound.sampled.LineUnavailableException;
|
||||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
||||||
public Graphics graphics;
|
public Graphics graphics;
|
||||||
public BackgroundImage background;
|
public BackgroundImage background;
|
||||||
public TextBox title, enter, settings, continueGame;
|
public TextBox title, enter, settings, continueGame;
|
||||||
public ArrayList<TextBox> textBoxArray = new ArrayList<TextBox>();
|
public ArrayList<TextBox> textBoxArray = new ArrayList<>();
|
||||||
public Font standardFont = new Font(Font.MONOSPACED, Font.BOLD, 60);
|
public Font standardFont = new Font(Font.MONOSPACED, Font.BOLD, 60);
|
||||||
public int playerFrame, enemyFrame;
|
public int playerFrame, enemyFrame;
|
||||||
// keeps track of how many ticks has elapsed since last frame change
|
// keeps track of how many ticks has elapsed since last frame change
|
||||||
|
@ -39,28 +40,30 @@ public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
||||||
|
|
||||||
public static boolean gameStart = false;
|
public static boolean gameStart = false;
|
||||||
|
|
||||||
// image imports begin here
|
|
||||||
public BufferedImageWrapper backgroundImage = new BufferedImageWrapper(("img/backgrounds/pointyMountains.png"));
|
public BufferedImageWrapper backgroundImage = new BufferedImageWrapper(("img/backgrounds/pointyMountains.png"));
|
||||||
|
|
||||||
public MenuPanel(CameraPanel gameFrame) throws IOException, SpriteException, UnsupportedAudioFileException, LineUnavailableException {
|
public MenuPanel(CameraPanel gameFrame) throws IOException, SpriteException, UnsupportedAudioFileException, LineUnavailableException {
|
||||||
this.gameFrame = gameFrame;
|
this.gameFrame = gameFrame;
|
||||||
|
// initialize shared camera to ensure that the background stays consistent between MenuPanel and SettingPanel
|
||||||
camera = gameFrame.camera;
|
camera = gameFrame.camera;
|
||||||
|
// create title textbox
|
||||||
title = new TextBox(100, 400, 100, GAME_WIDTH, standardFont, "Platformer", null);
|
title = new TextBox(100, 400, 100, GAME_WIDTH, standardFont, "Platformer", null);
|
||||||
|
// initialize selectable menu options and add the text boxes to the textBoxArray, which controls which text box is currently highlighted
|
||||||
continueGame = new TextBox(300, 600, 100, GAME_WIDTH, standardFont, "Continue", "game");
|
continueGame = new TextBox(300, 600, 100, GAME_WIDTH, standardFont, "Continue", "game");
|
||||||
enter = new TextBox(400, 600, 100, GAME_WIDTH, standardFont, "Start Game", "game-start");
|
enter = new TextBox(400, 600, 100, GAME_WIDTH, standardFont, "Start Game", "game-start");
|
||||||
settings = new TextBox(500, 600, 100, GAME_WIDTH, standardFont, "Settings", "settings");
|
settings = new TextBox(500, 600, 100, GAME_WIDTH, standardFont, "Settings", "settings");
|
||||||
textBoxArray.add(enter);
|
textBoxArray.add(enter);
|
||||||
textBoxArray.add(settings);
|
textBoxArray.add(settings);
|
||||||
|
// if there is a loadable save, isContinue is set to true and the Continue textbox is selectable
|
||||||
if (GameFrame.game.isContinue) {
|
if (GameFrame.game.isContinue) {
|
||||||
textBoxArray.add(0, continueGame);
|
textBoxArray.add(0, continueGame);
|
||||||
}
|
}
|
||||||
|
|
||||||
background = new BackgroundImage(0, 0, backgroundImage, GAME_WIDTH, GAME_HEIGHT, 10, camera);
|
background = new BackgroundImage(0, 0, backgroundImage, GAME_WIDTH, GAME_HEIGHT, 10, camera);
|
||||||
// the height of 35 is set because it is half of the original tile height (i.e., 70px)
|
|
||||||
this.setFocusable(true); //make everything in this class appear on the screen
|
this.setFocusable(true); //make everything in this class appear on the screen
|
||||||
this.addKeyListener(this); //start listening for keyboard input
|
this.addKeyListener(this); //start listening for keyboard input
|
||||||
// request focus when the CardLayout selects this game
|
// request focus when the CardLayout selects this game
|
||||||
|
// this allows the OS to forward HID input to this panel
|
||||||
this.addComponentListener(new ComponentAdapter() {
|
this.addComponentListener(new ComponentAdapter() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,6 +76,7 @@ public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
||||||
//add the MousePressed method from the MouseAdapter - by doing this we can listen for mouse input. We do this differently from the KeyListener because MouseAdapter has SEVEN mandatory methods - we only need one of them, and we don't want to make 6 empty methods
|
//add the MousePressed method from the MouseAdapter - by doing this we can listen for mouse input. We do this differently from the KeyListener because MouseAdapter has SEVEN mandatory methods - we only need one of them, and we don't want to make 6 empty methods
|
||||||
addMouseListener(new MouseAdapter() {
|
addMouseListener(new MouseAdapter() {
|
||||||
public void mousePressed(MouseEvent e) {
|
public void mousePressed(MouseEvent e) {
|
||||||
|
// check if the mouse is hovering over a textbox; if it is, run the action connected to the textbox
|
||||||
if (hoverCheck(e)) {
|
if (hoverCheck(e)) {
|
||||||
keyPressed(new KeyEvent(new Component() {
|
keyPressed(new KeyEvent(new Component() {
|
||||||
}, 0, -1, 0, KeyEvent.VK_ENTER, (char)KeyEvent.VK_ENTER));
|
}, 0, -1, 0, KeyEvent.VK_ENTER, (char)KeyEvent.VK_ENTER));
|
||||||
|
@ -81,6 +85,7 @@ public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
||||||
});
|
});
|
||||||
addMouseMotionListener(new MouseMotionAdapter() {
|
addMouseMotionListener(new MouseMotionAdapter() {
|
||||||
public void mouseMoved(MouseEvent e) {
|
public void mouseMoved(MouseEvent e) {
|
||||||
|
// check if the mouse is now hovering over a text box; if it is, select that textbox
|
||||||
hoverCheck(e);
|
hoverCheck(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -103,20 +108,25 @@ public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
||||||
|
|
||||||
//call the draw methods in each class to update positions as things move
|
//call the draw methods in each class to update positions as things move
|
||||||
public void draw(Graphics g, int playerFrame, int enemyFrame){
|
public void draw(Graphics g, int playerFrame, int enemyFrame){
|
||||||
|
// draw background
|
||||||
background.draw(g);
|
background.draw(g);
|
||||||
|
// draw title
|
||||||
title.draw(g,null, Color.black);
|
title.draw(g,null, Color.black);
|
||||||
|
// if there is no loadable save, gray out the Continue textbox
|
||||||
if (!GameFrame.game.isContinue) {
|
if (!GameFrame.game.isContinue) {
|
||||||
continueGame.draw(g, null, Color.gray);
|
continueGame.draw(g, null, Color.gray);
|
||||||
}
|
}
|
||||||
|
// draw each selectable textBox in the textbox array
|
||||||
for (TextBox t: textBoxArray) {
|
for (TextBox t: textBoxArray) {
|
||||||
t.draw(g, null, Color.cyan);
|
t.draw(g, null, Color.cyan);
|
||||||
}
|
}
|
||||||
|
// overwrite the selectable text box with a background color and a different text color (blue instead of cyan)
|
||||||
textBoxArray.get(currentBox).draw(g, Color.gray, Color.blue);
|
textBoxArray.get(currentBox).draw(g, Color.gray, Color.blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
//call the move methods in other classes to update positions
|
// this function does nothing, but was retained to allow the children of this class to implement their own functions without also having to reimplement run()
|
||||||
//this method is constantly called from run(). By doing this, movements appear fluid and natural. If we take this out the movements appear sluggish and laggy
|
// e.x., a child could override doAction() to launch someFunction()
|
||||||
public void move(){
|
public void doAction(){
|
||||||
}
|
}
|
||||||
|
|
||||||
//run() method is what makes the game continue running without end. It calls other methods to move objects, check for collision, and update the screen
|
//run() method is what makes the game continue running without end. It calls other methods to move objects, check for collision, and update the screen
|
||||||
|
@ -135,7 +145,8 @@ public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
||||||
|
|
||||||
//only move objects around and update screen if enough time has passed
|
//only move objects around and update screen if enough time has passed
|
||||||
if(delta >= 1){
|
if(delta >= 1){
|
||||||
move();
|
doAction();
|
||||||
|
// shift the camera to cause the parallax effect
|
||||||
camera.x += 10;
|
camera.x += 10;
|
||||||
repaint();
|
repaint();
|
||||||
delta--;
|
delta--;
|
||||||
|
@ -143,8 +154,10 @@ public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if the mouse is hovering over a textbox; if the mouse is hovering over a textbox, select the textbox hovered over
|
||||||
public boolean hoverCheck(MouseEvent e) {
|
public boolean hoverCheck(MouseEvent e) {
|
||||||
for (TextBox t: textBoxArray) {
|
for (TextBox t: textBoxArray) {
|
||||||
|
// select the textbox hovered over if it is hovering over a textbox
|
||||||
if (t.isHover(e.getX(), e.getY())) {
|
if (t.isHover(e.getX(), e.getY())) {
|
||||||
currentBox = textBoxArray.indexOf(t);
|
currentBox = textBoxArray.indexOf(t);
|
||||||
return true;
|
return true;
|
||||||
|
@ -155,35 +168,48 @@ public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
||||||
|
|
||||||
//if a key is pressed, we'll send it over to the Player class for processing
|
//if a key is pressed, we'll send it over to the Player class for processing
|
||||||
public void keyPressed(KeyEvent e) {
|
public void keyPressed(KeyEvent e) {
|
||||||
|
// intercept keypresses and replace them with previously defined keypresses through the Middleware class
|
||||||
e = UtilityFunction.intercept(e, GameFrame.game.middlewareArray);
|
e = UtilityFunction.intercept(e, GameFrame.game.middlewareArray);
|
||||||
|
// if the keypress is ENTER, run the action indicated by the connected textbox's id
|
||||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||||
|
// indicate that the game is starting if the player presses "Continue" or "New Game"
|
||||||
if(textBoxArray.get(currentBox).id.contains("game")){
|
if(textBoxArray.get(currentBox).id.contains("game")){
|
||||||
gameStart = true;
|
gameStart = true;
|
||||||
}
|
}
|
||||||
// always unpause game, no matter what screen is navigated to
|
// always unpause game, no matter what screen is navigated to
|
||||||
GameFrame.game.isPaused = false;
|
GameFrame.game.isPaused = false;
|
||||||
// logic for different screens starts here
|
// logic for different screens starts here
|
||||||
|
// if the user presses "New Game", reset GamePanel and navigate to it
|
||||||
if (textBoxArray.get(currentBox).id.equals("game-start")) {
|
if (textBoxArray.get(currentBox).id.equals("game-start")) {
|
||||||
try {
|
try {
|
||||||
|
// remove the old GamePanel from the CardLayout CameraPanel
|
||||||
GameFrame.main.remove(GameFrame.game);
|
GameFrame.main.remove(GameFrame.game);
|
||||||
|
// stop the run() while loop, effectively killing the thread
|
||||||
GameFrame.game.isRunning = false;
|
GameFrame.game.isRunning = false;
|
||||||
|
// reset player velocities to prevent race conditions
|
||||||
GameFrame.game.player.xVelocity = 0;
|
GameFrame.game.player.xVelocity = 0;
|
||||||
GameFrame.game.player.yVelocity = 0;
|
GameFrame.game.player.yVelocity = 0;
|
||||||
|
// reset the tile map to prevent race conditions
|
||||||
GameFrame.game.map = new Tile[1000][18];
|
GameFrame.game.map = new Tile[1000][18];
|
||||||
GameFrame.game = new GamePanel(GameFrame.main); //run GamePanel constructor
|
GameFrame.game = new GamePanel(GameFrame.main); //run GamePanel constructor
|
||||||
|
// make it so that the game can be resumed if the player leaves
|
||||||
GameFrame.game.isContinue = true;
|
GameFrame.game.isContinue = true;
|
||||||
textBoxArray.add(continueGame);
|
textBoxArray.add(continueGame);
|
||||||
|
// start the game
|
||||||
GameFrame.game.startThread();
|
GameFrame.game.startThread();
|
||||||
GameFrame.main.add(GameFrame.game, "game", 0);
|
// add the game to the CardLayout CameraPanel, enabling navigation
|
||||||
|
GameFrame.main.add(GameFrame.game, "game");
|
||||||
} catch (IOException | SpriteException | UnsupportedAudioFileException | LineUnavailableException ex) {
|
} catch (IOException | SpriteException | UnsupportedAudioFileException | LineUnavailableException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
// switch to the game panel
|
||||||
((CardLayout)gameFrame.getLayout()).show(gameFrame, "game");
|
((CardLayout)gameFrame.getLayout()).show(gameFrame, "game");
|
||||||
} else {
|
} else {
|
||||||
|
// switch to the panel indicated by the id of the textbox
|
||||||
((CardLayout) gameFrame.getLayout()).show(gameFrame, textBoxArray.get(currentBox).id);
|
((CardLayout) gameFrame.getLayout()).show(gameFrame, textBoxArray.get(currentBox).id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// if the keypress is not ENTER, either select the textbox above or below the currently selected textbox
|
||||||
currentBox = UtilityFunction.processBox(e, currentBox, textBoxArray);
|
currentBox = UtilityFunction.processBox(e, currentBox, textBoxArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +1,38 @@
|
||||||
import com.sun.jdi.request.DuplicateRequestException;
|
// Eric Li, Charlie Zhao, ICS4U, Finished 6/16/2022
|
||||||
|
// intercepts keystrokes and substitutes new keystrokes in the place of the old keystrokes
|
||||||
|
// allows for arbitrary replacement of keystrokes, including chained replacement of keystrokes if necessary
|
||||||
|
// although those features have not yet been implemented
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class Middleware implements Serializable {
|
public class Middleware implements Serializable {
|
||||||
|
|
||||||
public static ArrayList<Integer> allOldCode = new ArrayList<Integer>();
|
public static ArrayList<Integer> allOldCode = new ArrayList<>();
|
||||||
public static ArrayList<Integer> allNewCode = new ArrayList<Integer>();
|
public static ArrayList<Integer> allNewCode = new ArrayList<>();
|
||||||
public final int oldCode;
|
public final int oldCode;
|
||||||
public final int newCode;
|
public final int newCode;
|
||||||
public boolean isDestroyed = false;
|
public boolean isDestroyed = false;
|
||||||
|
|
||||||
|
// create new Middleware which intercepts newCode and replaces it with oldCode
|
||||||
Middleware(int oldCode, int newCode) {
|
Middleware(int oldCode, int newCode) {
|
||||||
// if (!canCreate(oldCode, newCode)) {
|
|
||||||
// TODO: replace with more appropriate exception
|
|
||||||
// throw new DuplicateRequestException();
|
|
||||||
// }
|
|
||||||
allOldCode.add(oldCode);
|
allOldCode.add(oldCode);
|
||||||
allNewCode.add(newCode);
|
allNewCode.add(newCode);
|
||||||
this.oldCode = oldCode;
|
this.oldCode = oldCode;
|
||||||
this.newCode = newCode;
|
this.newCode = newCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checks if the keypress can be intercepted (i.e., if it is the same keyCode as newCode)
|
||||||
public boolean canIntercept(KeyEvent e) {
|
public boolean canIntercept(KeyEvent e) {
|
||||||
return e.getKeyCode() == newCode && !isDestroyed;
|
return e.getKeyCode() == newCode && !isDestroyed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// intercepts the key if it has been found to be interceptable
|
||||||
public KeyEvent interceptKey(KeyEvent e) {
|
public KeyEvent interceptKey(KeyEvent e) {
|
||||||
e.setKeyCode(oldCode);
|
e.setKeyCode(oldCode);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() {
|
|
||||||
allOldCode.remove(oldCode);
|
|
||||||
allNewCode.remove(newCode);
|
|
||||||
isDestroyed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean canCreate(int oldCode, int newCode) {
|
|
||||||
return (!allOldCode.contains(oldCode) && !allNewCode.contains(newCode));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
/* Eric Li, ICS4U, Completed 5/29/2022
|
/* Eric Li, ICS4U, Completed 6/19/2022
|
||||||
|
|
||||||
Paddle class defines behaviours for the left and right player-controlled paddles */
|
NonPlayer class defines behaviour for enemies and characters that are not controlled by the player */
|
||||||
|
|
||||||
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.*;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
public class NonPlayer extends GenericSprite implements Serializable {
|
public class NonPlayer extends GenericSprite implements Serializable {
|
||||||
public final int SPEED = 3;
|
|
||||||
// please note that these are not static, in contrast to the player class, as different enemies will have different heights
|
// please note that these are not static, in contrast to the player class, as different enemies will have different heights
|
||||||
public int npcWidth;
|
public int npcWidth;
|
||||||
public int npcHeight;
|
public int npcHeight;
|
||||||
|
@ -22,7 +20,6 @@ public class NonPlayer extends GenericSprite implements Serializable {
|
||||||
public int health;
|
public int health;
|
||||||
|
|
||||||
public double fadeCounter;
|
public double fadeCounter;
|
||||||
// private final Sound bump;
|
|
||||||
|
|
||||||
public BufferedImageWrapper[][][] spriteArray;
|
public BufferedImageWrapper[][][] spriteArray;
|
||||||
public NonPlayer(int x, int y, BufferedImageWrapper[][][] sprites, int npcWidth, int npcHeight, int health) throws UnsupportedAudioFileException, LineUnavailableException, IOException {
|
public NonPlayer(int x, int y, BufferedImageWrapper[][][] sprites, int npcWidth, int npcHeight, int health) throws UnsupportedAudioFileException, LineUnavailableException, IOException {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectStreamClass;
|
import java.io.ObjectStreamClass;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SafeObjectInputStream extends ObjectInputStream {
|
public class SafeObjectInputStream extends ObjectInputStream {
|
||||||
|
|
|
@ -10,14 +10,11 @@ Implements Runnable interface to use "threading" - let the game do two things at
|
||||||
|
|
||||||
import javax.sound.sampled.LineUnavailableException;
|
import javax.sound.sampled.LineUnavailableException;
|
||||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
import javax.swing.*;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.KeyEvent;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.event.MouseEvent;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.Key;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class SettingPanel extends MenuPanel {
|
public class SettingPanel extends MenuPanel {
|
||||||
|
|
||||||
|
@ -87,7 +84,7 @@ public class SettingPanel extends MenuPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
// move is repurposed to change key bind
|
// move is repurposed to change key bind
|
||||||
public void move() {
|
public void doAction() {
|
||||||
changeKeyBind();
|
changeKeyBind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
public class SingleTile extends Tile implements Serializable {
|
public class SingleTile extends Tile implements Serializable {
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import javax.sound.sampled.LineUnavailableException;
|
import javax.sound.sampled.LineUnavailableException;
|
||||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import javax.sound.sampled.AudioInputStream;
|
|
||||||
import javax.sound.sampled.AudioSystem;
|
|
||||||
import javax.sound.sampled.Clip;
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
public class SoundWrapper implements Serializable {
|
public class SoundWrapper implements Serializable {
|
||||||
transient public Sound sound;
|
transient public Sound sound;
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
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.*;
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInputStream;
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public final class UtilityFunction {
|
public final class UtilityFunction {
|
||||||
|
|
Loading…
Reference in New Issue