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.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class DialogueMenu extends TextBox implements Serializable {
|
||||
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 double LINE_SPACING = 1.5;
|
||||
public static final int FREQUENCY = 2;
|
||||
public BufferedImageWrapper PORTRAIT;
|
||||
public BufferedImageWrapper portrait;
|
||||
public int currentFrame = 0;
|
||||
public int frameCounter = 0;
|
||||
public 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);
|
||||
PORTRAIT = portrait;
|
||||
this.portrait = portrait;
|
||||
checkForNarrator();
|
||||
this.isNarrator = isNarrator;
|
||||
}
|
||||
|
||||
// check if the person speaking is currently the narrator, and adjust the newX value accordingly
|
||||
public void checkForNarrator() {
|
||||
if (isNarrator) {
|
||||
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) {
|
||||
// only draw currentFrame number of text characters; this animates the process of drawing the text
|
||||
text = text.substring(0, currentFrame);
|
||||
// only set the background color if it is not null
|
||||
if (backgroundColor != null) {
|
||||
g.setColor(textColor);
|
||||
// if the person speaking is the narrator, draw the textbox to the right of the portrait
|
||||
if (isNarrator) {
|
||||
g.drawImage(PORTRAIT.image, newX - PORTRAIT_WIDTH - PADDING, newY, PORTRAIT_WIDTH, yHeight, null);
|
||||
} else {
|
||||
g.drawImage(PORTRAIT.image, GamePanel.GAME_WIDTH - PORTRAIT_WIDTH - PADDING, newY, PORTRAIT_WIDTH, yHeight, null);
|
||||
g.drawImage(portrait.image, newX - PORTRAIT_WIDTH - PADDING, newY, PORTRAIT_WIDTH, yHeight, null);
|
||||
} 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);
|
||||
}
|
||||
// create border and set it to a width of 4.0
|
||||
((Graphics2D)g).setStroke(new BasicStroke(4f));
|
||||
// draw the border
|
||||
g.drawRect(newX, newY, xWidth, yHeight - 4);
|
||||
// set color of the rectangle inside the border, and draw it
|
||||
g.setColor(backgroundColor);
|
||||
g.fillRect(newX, newY, xWidth, yHeight - 4);
|
||||
}
|
||||
// set text color and draw it
|
||||
g.setColor(textColor);
|
||||
drawCenteredString(g, newY, newX, text);
|
||||
}
|
||||
|
||||
// draw a centered string
|
||||
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(" ");
|
||||
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("");
|
||||
// get font size
|
||||
FontMetrics metrics = g.getFontMetrics();
|
||||
// declare temporary variables used in the for loop, and initialize them
|
||||
int currentLineWidth = 0, lastLineIndex = 0;
|
||||
for (String s: newText) {
|
||||
// add width of new word to current line width
|
||||
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)) {
|
||||
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);
|
||||
lines.add(s + " ");
|
||||
lastLineIndex ++;
|
||||
}
|
||||
}
|
||||
// leave TOP_PADDING + (metrics.getAscent() - metrics.getDescent()) * LINE_SPACING)
|
||||
// space between the top of the dialogue box and the text
|
||||
y += TOP_PADDING;
|
||||
// center y (half is above y value, half is below y value)
|
||||
for (String s: lines) {
|
||||
// add spacing since last line
|
||||
y += (metrics.getAscent() - metrics.getDescent()) * LINE_SPACING;
|
||||
// draw string
|
||||
// draw actual string
|
||||
g.drawString(s + "\n", x + PADDING, y);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
// if more than FREQUENCY ticks has passed since the last text animation, animate by drawing one more char
|
||||
if (frameCounter >= FREQUENCY) {
|
||||
frameCounter -= FREQUENCY;
|
||||
currentFrame += 1;
|
||||
}
|
||||
// set font of string to be drawn
|
||||
g.setFont(font);
|
||||
drawCenteredTextBox(g, text, backgroundColor, textColor);
|
||||
// increment the frame counter
|
||||
frameCounter++;
|
||||
// if the text has been completely drawn (nothing left to animate), return true
|
||||
if (currentFrame >= text.length()) {
|
||||
currentFrame = 0;
|
||||
return true;
|
||||
} else {
|
||||
} else { // otherwise, 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.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&&realX<p.x+Player.PLAYER_WIDTH&&y-p.y<Player.PLAYER_HEIGHT&&p.y-y<height){
|
||||
return true;
|
||||
}
|
||||
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 {
|
||||
lifeSpan--;
|
||||
if(lifeSpan<=0){
|
||||
|
@ -56,9 +64,6 @@ public class FireBall extends GenericSprite{
|
|||
dead = true;
|
||||
GameFrame.game.player.reset();
|
||||
}
|
||||
// if(y<0||y>GameFrame.game.HEIGHT){
|
||||
// dead = true;
|
||||
// }
|
||||
}
|
||||
public void draw(Graphics g) throws IOException {
|
||||
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
|
||||
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.UnsupportedAudioFileException;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class GameFrame extends JFrame{
|
||||
|
||||
|
@ -25,50 +21,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] " + e.toString().replace("Exception", "NotAnError"));
|
||||
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<Middleware>)FileManager.
|
||||
readObjectFromFile("local/controls", Arrays.asList("java.util.ArrayList", "Middleware"));
|
||||
} catch (IOException | ClassNotFoundException | ClassCastException | SecurityException e) {
|
||||
game.middlewareArray = new ArrayList<Middleware>();
|
||||
}
|
||||
*/
|
||||
// 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"));
|
||||
|
|
|
@ -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
|
||||
|
||||
*/
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
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.UnsupportedAudioFileException;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
@ -15,7 +18,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 +31,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 +64,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 +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){
|
||||
if(tile==null){return false;}
|
||||
if(!tile.collision){
|
||||
|
@ -87,6 +90,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 +113,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 {
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
public class GlobalState implements Serializable {
|
||||
// each object takes GlobalState.second * 5 ticks to explode
|
||||
public static final int second = 10;
|
||||
}
|
||||
|
|
|
@ -12,26 +12,30 @@ public class LevelManager implements Serializable {
|
|||
public static String filePath;
|
||||
|
||||
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){
|
||||
// remove all current bombs and fireballs
|
||||
GameFrame.game.bombs.clear();
|
||||
GameFrame.game.fireballs.clear();
|
||||
// set the player velocity to zero
|
||||
GameFrame.game.player.yVelocity = 0;
|
||||
GameFrame.game.player.xVelocity = 0;
|
||||
GameFrame.game.level = level;
|
||||
// change spawn coordinates, bomb count, and save file path based on level inputted
|
||||
if(level == 1){
|
||||
//-400/450
|
||||
// spawn coordinates: -400/450
|
||||
xSpawn = -400;
|
||||
ySpawn = 450;
|
||||
filePath = "saves/Level1.txt";
|
||||
bombs = 8;
|
||||
} else if(level == 2){
|
||||
//-400/400
|
||||
// spawn coordinates: -400/400
|
||||
xSpawn = -400;
|
||||
ySpawn = 400;
|
||||
filePath = "saves/Level2.txt";
|
||||
bombs = 3;
|
||||
} else if(level == 3){
|
||||
//-800/100
|
||||
// spawn coordinates: -800/100
|
||||
xSpawn = -800;
|
||||
ySpawn = 100;
|
||||
filePath = "saves/Level3.txt";
|
||||
|
@ -43,24 +47,34 @@ public class LevelManager implements Serializable {
|
|||
filePath = "saves/Level4.txt";
|
||||
bombs = 5;
|
||||
} else if(level == 5){
|
||||
//-1100/350
|
||||
xSpawn = 1800;
|
||||
ySpawn = 150;
|
||||
//-1100/460
|
||||
xSpawn = -1100;
|
||||
ySpawn = 350;
|
||||
filePath = "saves/Level5.txt";
|
||||
bombs = 1;
|
||||
}
|
||||
try {
|
||||
// load map into GamePanel
|
||||
MapReader.inputMap(filePath);
|
||||
// if the player has not died yet (i.e., first time seeing the dialogue), load it
|
||||
if (!hasDied) {
|
||||
// do not load dialogue if there is no dialogue to load
|
||||
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")) {
|
||||
// delete the first item in the array so the villain does not say "$Villain"
|
||||
GameFrame.game.dialogueArray.remove(0);
|
||||
// display portrait on right side of screen
|
||||
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.frameCounter = 0;
|
||||
// tell the GameFrame to load the DialogueMenu
|
||||
GameFrame.game.isDialogue = true;
|
||||
}
|
||||
}
|
||||
|
@ -70,12 +84,15 @@ public class LevelManager implements Serializable {
|
|||
// temporary boolean, so only declared here
|
||||
boolean stillTutorial = true;
|
||||
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("/")) {
|
||||
stillTutorial = false;
|
||||
} 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]));
|
||||
} 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]));
|
||||
}
|
||||
}
|
||||
|
@ -87,6 +104,7 @@ public class LevelManager implements Serializable {
|
|||
}
|
||||
|
||||
|
||||
//Gives the player bombs
|
||||
public static void setBombs(){
|
||||
if(GameFrame.game.level == 1){
|
||||
bombs = 8;
|
||||
|
@ -100,9 +118,11 @@ public class LevelManager implements Serializable {
|
|||
bombs = 1;
|
||||
}
|
||||
}
|
||||
// overloaded setLevel that accepts only a level argument
|
||||
public static void setLevel(int level) {
|
||||
setLevel(level, false);
|
||||
}
|
||||
// go to the next level
|
||||
public static void nextLevel(){
|
||||
setLevel(GameFrame.game.level+1);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// Eric Li, Charlie Zhao, ICS4U, Finished 5/30/2022
|
||||
/* Main class starts the game
|
||||
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.UnsupportedAudioFileException;
|
||||
import java.io.*;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class MapReader implements Serializable {
|
||||
//Input game map
|
||||
// loads game map into GamePanel
|
||||
/*
|
||||
1: Normal Grass
|
||||
2: Left Grass:
|
||||
|
@ -23,28 +27,36 @@ public class MapReader implements Serializable {
|
|||
// h k Shooting
|
||||
// m
|
||||
public static void inputMap(String filePath) throws IOException, SpriteException, UnsupportedAudioFileException, LineUnavailableException {
|
||||
int TileX, TileY;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int TileX = 0;
|
||||
int TileY = 0;
|
||||
// clears existing enemies, particles, fireball shooters, and fireballs
|
||||
GameFrame.game.enemy.clear();
|
||||
GameFrame.game.particleTiles.clear();
|
||||
GameFrame.game.shootingTiles.clear();
|
||||
GameFrame.game.fireballs.clear();
|
||||
// clears current map
|
||||
for(int i=0; i<GameFrame.game.map.length; i++){
|
||||
Arrays.fill(GameFrame.game.map[i], null);
|
||||
}
|
||||
// read new map file
|
||||
String file = FileManager.readFile(filePath);
|
||||
// converts characters in map file into Tiles
|
||||
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'){
|
||||
y+=1;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
// 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;
|
||||
// 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'){
|
||||
newTile("img/tiles/terrain/grass.png", x, y, TileX, TileY);
|
||||
} 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);
|
||||
} else if(file.charAt(i)=='g'){
|
||||
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);
|
||||
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));
|
||||
|
||||
} else if(file.charAt(i)=='+') {
|
||||
} else if(file.charAt(i)=='+') { // this tile will send the player to the next level when the player steps on it
|
||||
newTile("img/tiles/boxes/finish.png", x, y, TileX, TileY);
|
||||
GameFrame.game.map[x][y].isFinish = 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);
|
||||
GameFrame.game.map[x][y].collision = false;
|
||||
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);
|
||||
GameFrame.game.map[x][y].nonBombCollide = true;
|
||||
GameFrame.game.map[x][y].kills = true;
|
||||
if(y>0&&GameFrame.game.map[x][y-1]==null) {
|
||||
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);
|
||||
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);
|
||||
GameFrame.game.map[x][y].shootingDir = "left";
|
||||
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.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 {
|
||||
String filePath = mapFilePath.replace(".txt", "-dialogue.txt");
|
||||
return FileManager.readFile(filePath).split("\n");
|
||||
String filePath = mapFilePath.replace(".txt", "-dialogue.txt"); // format path to open the dialogue file instead
|
||||
return FileManager.readFile(filePath).split("\n"); // read and split file, before returning
|
||||
}
|
||||
|
||||
public static ArrayList<String[]> inputSign(String signFilePath) throws IOException {
|
||||
String filePath = signFilePath.replace(".txt", "-signs.txt");
|
||||
// return sign array given the filePath inputted in inputMath for further processing in LevelManager
|
||||
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");
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
||||
*/
|
||||
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.UnsupportedAudioFileException;
|
||||
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{
|
||||
|
||||
|
@ -31,7 +32,7 @@ public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
|||
public Graphics graphics;
|
||||
public BackgroundImage background;
|
||||
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 int playerFrame, enemyFrame;
|
||||
// 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;
|
||||
|
||||
// image imports begin here
|
||||
public BufferedImageWrapper backgroundImage = new BufferedImageWrapper(("img/backgrounds/pointyMountains.png"));
|
||||
|
||||
public MenuPanel(CameraPanel gameFrame) throws IOException, SpriteException, UnsupportedAudioFileException, LineUnavailableException {
|
||||
this.gameFrame = gameFrame;
|
||||
// initialize shared camera to ensure that the background stays consistent between MenuPanel and SettingPanel
|
||||
camera = gameFrame.camera;
|
||||
|
||||
// create title textbox
|
||||
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");
|
||||
enter = new TextBox(400, 600, 100, GAME_WIDTH, standardFont, "Start Game", "game-start");
|
||||
settings = new TextBox(500, 600, 100, GAME_WIDTH, standardFont, "Settings", "settings");
|
||||
textBoxArray.add(enter);
|
||||
textBoxArray.add(settings);
|
||||
// if there is a loadable save, isContinue is set to true and the Continue textbox is selectable
|
||||
if (GameFrame.game.isContinue) {
|
||||
textBoxArray.add(0, continueGame);
|
||||
}
|
||||
|
||||
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.addKeyListener(this); //start listening for keyboard input
|
||||
// request focus when the CardLayout selects this game
|
||||
// this allows the OS to forward HID input to this panel
|
||||
this.addComponentListener(new ComponentAdapter() {
|
||||
|
||||
@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
|
||||
addMouseListener(new MouseAdapter() {
|
||||
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)) {
|
||||
keyPressed(new KeyEvent(new Component() {
|
||||
}, 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() {
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
// check if the mouse is now hovering over a text box; if it is, select that textbox
|
||||
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
|
||||
public void draw(Graphics g, int playerFrame, int enemyFrame){
|
||||
// draw background
|
||||
background.draw(g);
|
||||
// draw title
|
||||
title.draw(g,null, Color.black);
|
||||
// if there is no loadable save, gray out the Continue textbox
|
||||
if (!GameFrame.game.isContinue) {
|
||||
continueGame.draw(g, null, Color.gray);
|
||||
}
|
||||
// draw each selectable textBox in the textbox array
|
||||
for (TextBox t: textBoxArray) {
|
||||
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);
|
||||
}
|
||||
|
||||
//call the move methods in other classes to update positions
|
||||
//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
|
||||
public void move(){
|
||||
// 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()
|
||||
// e.x., a child could override doAction() to launch someFunction()
|
||||
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
|
||||
|
@ -135,7 +145,8 @@ public class MenuPanel extends JPanel implements Runnable, KeyListener{
|
|||
|
||||
//only move objects around and update screen if enough time has passed
|
||||
if(delta >= 1){
|
||||
move();
|
||||
doAction();
|
||||
// shift the camera to cause the parallax effect
|
||||
camera.x += 10;
|
||||
repaint();
|
||||
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) {
|
||||
for (TextBox t: textBoxArray) {
|
||||
// select the textbox hovered over if it is hovering over a textbox
|
||||
if (t.isHover(e.getX(), e.getY())) {
|
||||
currentBox = textBoxArray.indexOf(t);
|
||||
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
|
||||
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);
|
||||
// if the keypress is ENTER, run the action indicated by the connected textbox's id
|
||||
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")){
|
||||
gameStart = true;
|
||||
}
|
||||
// always unpause game, no matter what screen is navigated to
|
||||
GameFrame.game.isPaused = false;
|
||||
// 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")) {
|
||||
try {
|
||||
// remove the old GamePanel from the CardLayout CameraPanel
|
||||
GameFrame.main.remove(GameFrame.game);
|
||||
// stop the run() while loop, effectively killing the thread
|
||||
GameFrame.game.isRunning = false;
|
||||
// reset player velocities to prevent race conditions
|
||||
GameFrame.game.player.xVelocity = 0;
|
||||
GameFrame.game.player.yVelocity = 0;
|
||||
// reset the tile map to prevent race conditions
|
||||
GameFrame.game.map = new Tile[1000][18];
|
||||
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;
|
||||
textBoxArray.add(continueGame);
|
||||
// start the game
|
||||
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) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
// switch to the game panel
|
||||
((CardLayout)gameFrame.getLayout()).show(gameFrame, "game");
|
||||
} else {
|
||||
// switch to the panel indicated by the id of the textbox
|
||||
((CardLayout) gameFrame.getLayout()).show(gameFrame, textBoxArray.get(currentBox).id);
|
||||
}
|
||||
} else {
|
||||
// if the keypress is not ENTER, either select the textbox above or below the currently selected textbox
|
||||
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.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Middleware implements Serializable {
|
||||
|
||||
public static ArrayList<Integer> allOldCode = new ArrayList<Integer>();
|
||||
public static ArrayList<Integer> allNewCode = new ArrayList<Integer>();
|
||||
public static ArrayList<Integer> allOldCode = new ArrayList<>();
|
||||
public static ArrayList<Integer> allNewCode = new ArrayList<>();
|
||||
public final int oldCode;
|
||||
public final int newCode;
|
||||
public boolean isDestroyed = false;
|
||||
|
||||
// create new Middleware which intercepts newCode and replaces it with oldCode
|
||||
Middleware(int oldCode, int newCode) {
|
||||
// if (!canCreate(oldCode, newCode)) {
|
||||
// TODO: replace with more appropriate exception
|
||||
// throw new DuplicateRequestException();
|
||||
// }
|
||||
allOldCode.add(oldCode);
|
||||
allNewCode.add(newCode);
|
||||
this.oldCode = oldCode;
|
||||
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) {
|
||||
return e.getKeyCode() == newCode && !isDestroyed;
|
||||
}
|
||||
|
||||
// intercepts the key if it has been found to be interceptable
|
||||
public KeyEvent interceptKey(KeyEvent e) {
|
||||
e.setKeyCode(oldCode);
|
||||
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
|
||||
public boolean equals(Object o) {
|
||||
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.UnsupportedAudioFileException;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.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
|
||||
public int npcWidth;
|
||||
public int npcHeight;
|
||||
|
@ -22,7 +20,6 @@ public class NonPlayer extends GenericSprite implements Serializable {
|
|||
public int health;
|
||||
|
||||
public double fadeCounter;
|
||||
// private final Sound bump;
|
||||
|
||||
public BufferedImageWrapper[][][] spriteArray;
|
||||
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.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
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.UnsupportedAudioFileException;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.IOException;
|
||||
import java.security.Key;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class SettingPanel extends MenuPanel {
|
||||
|
||||
|
@ -87,7 +84,7 @@ public class SettingPanel extends MenuPanel {
|
|||
}
|
||||
|
||||
// move is repurposed to change key bind
|
||||
public void move() {
|
||||
public void doAction() {
|
||||
changeKeyBind();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class SingleTile extends Tile implements Serializable {
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
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 {
|
||||
transient public Sound sound;
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
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.Serializable;
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import java.awt.event.KeyEvent;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public final class UtilityFunction {
|
||||
|
|
Loading…
Reference in New Issue