From a306731307b860327960dde8cb297248aa370c22 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Sat, 31 Dec 2022 22:57:17 +0000 Subject: [PATCH 01/12] #22 Refactored Menu and Printing; reduced clutter on game launch --- pom.xml | 2 +- src/com/redomar/game/HelpMenu.java | 37 ++-- src/com/redomar/game/InputHandler.java | 96 ++++------- src/com/redomar/game/entities/Player.java | 8 +- src/com/redomar/game/menu/Menu.java | 163 ++++-------------- src/com/redomar/game/menu/MenuInput.java | 17 +- src/com/redomar/game/script/Printing.java | 49 ++---- .../com/redomar/game/script/PrintingTest.java | 10 +- 8 files changed, 134 insertions(+), 248 deletions(-) diff --git a/pom.xml b/pom.xml index 199fa6a..e98648c 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ junit junit - 4.13.1 + 4.13 test diff --git a/src/com/redomar/game/HelpMenu.java b/src/com/redomar/game/HelpMenu.java index da9709a..101e65a 100644 --- a/src/com/redomar/game/HelpMenu.java +++ b/src/com/redomar/game/HelpMenu.java @@ -1,23 +1,29 @@ package com.redomar.game; +import javax.imageio.ImageIO; +import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; -import javax.imageio.ImageIO; -import javax.swing.*; +import java.net.URL; +import java.util.concurrent.atomic.AtomicReference; /** * Credit to Gagandeep Bali @ stackoverflow */ public class HelpMenu { - private MyPanel contentPane; + private final JFrame frame = new JFrame("Help Menu"); + + private static void run() { + Runnable runnable = () -> new HelpMenu().displayGUI(); + EventQueue.invokeLater(runnable); + } private void displayGUI() { - JFrame frame = new JFrame("Help Menu"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - contentPane = new MyPanel(); + MyPanel contentPane = new MyPanel(); frame.setContentPane(contentPane); frame.setLocationRelativeTo(null); @@ -26,13 +32,23 @@ private void displayGUI() { frame.setVisible(true); } - private class MyPanel extends JPanel { + public void helpMenuLaunch() { + run(); + } + + public void helpMenuClose() { + frame.setVisible(false); + frame.dispose(); + } + + private static class MyPanel extends JPanel { private BufferedImage image; private MyPanel() { try { - image = ImageIO.read(MyPanel.class.getResource("/controls/controls.png")); + AtomicReference controlsImageResource = new AtomicReference<>(MyPanel.class.getResource("/controls/controls.png")); + image = ImageIO.read(controlsImageResource.get()); } catch (IOException ioe) { ioe.printStackTrace(); } @@ -40,7 +56,7 @@ private MyPanel() { @Override public Dimension getPreferredSize() { - return image == null ? new Dimension(400, 300): new Dimension(image.getWidth(), image.getHeight()); + return image == null ? new Dimension(400, 300) : new Dimension(image.getWidth(), image.getHeight()); } @Override @@ -49,9 +65,4 @@ protected void paintComponent(Graphics g) { g.drawImage(image, 0, 0, this); } } - - public static void run() { - Runnable runnable = () -> new HelpMenu().displayGUI(); - EventQueue.invokeLater(runnable); - } } diff --git a/src/com/redomar/game/InputHandler.java b/src/com/redomar/game/InputHandler.java index b39185b..4d0676a 100644 --- a/src/com/redomar/game/InputHandler.java +++ b/src/com/redomar/game/InputHandler.java @@ -11,23 +11,21 @@ public class InputHandler implements KeyListener { - private boolean isAzertyCountry; - private Key up = new Key(); - private Key down = new Key(); - private Key left = new Key(); - private Key right = new Key(); - private Printing print = new Printing(); - private int map; + private final boolean isAzertyCountry; + private final Printing print = new Printing(); + private final PopUp popup = new PopUp(); + private final Key UP_KEY = new Key(); + private final Key DOWN_KEY = new Key(); + private final Key LEFT_KEY = new Key(); + private final Key RIGHT_KEY = new Key(); private boolean ignoreInput = false; private boolean toggleMusic = false; - private PopUp popup = new PopUp(); public InputHandler(Game game) { InputContext context = InputContext.getInstance(); // Important to know whether the keyboard is in Azerty or Qwerty. // Azerty countries used QZSD instead of WASD keys. - isAzertyCountry = context.getLocale().getCountry().equals("BE") - || context.getLocale().getCountry().equals("FR"); + isAzertyCountry = context.getLocale().getCountry().equals("BE") || context.getLocale().getCountry().equals("FR"); game.addKeyListener(this); } @@ -45,33 +43,31 @@ public void keyTyped(KeyEvent e) { private void toggleKey(int keyCode, boolean isPressed) { if (!isIgnoreInput()) { - if (keyCode == KeyEvent.VK_Z && isAzertyCountry || keyCode == KeyEvent.VK_W && !isAzertyCountry - || keyCode == KeyEvent.VK_UP) { - up.toggle(isPressed); + if (keyCode == KeyEvent.VK_Z && isAzertyCountry || keyCode == KeyEvent.VK_W && !isAzertyCountry || keyCode == KeyEvent.VK_UP) { + UP_KEY.toggle(isPressed); } - if (keyCode == KeyEvent.VK_Q && isAzertyCountry || keyCode == KeyEvent.VK_A && !isAzertyCountry - || keyCode == KeyEvent.VK_LEFT) { - left.toggle(isPressed); + if (keyCode == KeyEvent.VK_Q && isAzertyCountry || keyCode == KeyEvent.VK_A && !isAzertyCountry || keyCode == KeyEvent.VK_LEFT) { + LEFT_KEY.toggle(isPressed); } if (keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_DOWN) { - down.toggle(isPressed); + DOWN_KEY.toggle(isPressed); } if (keyCode == KeyEvent.VK_D || keyCode == KeyEvent.VK_RIGHT) { - right.toggle(isPressed); + RIGHT_KEY.toggle(isPressed); } } if (isIgnoreInput()) { - up.toggle(false); - down.toggle(false); - left.toggle(false); - right.toggle(false); + UP_KEY.toggle(false); + DOWN_KEY.toggle(false); + LEFT_KEY.toggle(false); + RIGHT_KEY.toggle(false); } if (keyCode == KeyEvent.VK_M) { - if(!toggleMusic){ + if (!toggleMusic) { Game.getBackgroundMusic().play(); print.print("Playing Music", PrintTypes.MUSIC); toggleMusic = true; @@ -80,9 +76,8 @@ private void toggleKey(int keyCode, boolean isPressed) { if (keyCode == KeyEvent.VK_COMMA) { Game.getBackgroundMusic().stop(); - if(toggleMusic) - print.print("Stopping Music", PrintTypes.MUSIC); - toggleMusic = false; + if (toggleMusic) print.print("Stopping Music", PrintTypes.MUSIC); + toggleMusic = false; } @@ -137,14 +132,13 @@ private void toggleKey(int keyCode, boolean isPressed) { private void quitGame() { Game.setClosing(true); - print.removeLog(); + if (!print.removeLog()) System.err.println("Could not delete Log file"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } - Game.getLevel().removeEntity( - Game.getPlayer().getSanitisedUsername()); + Game.getLevel().removeEntity(Game.getPlayer().getSanitisedUsername()); Game.setRunning(false); Game.getFrame().dispose(); System.exit(0); @@ -154,44 +148,20 @@ public void untoggle(boolean toggle) { this.ignoreInput = toggle; } - public int getMap() { - return map; + public Key getUP_KEY() { + return UP_KEY; } - public void setMap(int map) { - this.map = map; + public Key getDOWN_KEY() { + return DOWN_KEY; } - public Key getUp() { - return up; + public Key getLEFT_KEY() { + return LEFT_KEY; } - public void setUp(Key up) { - this.up = up; - } - - public Key getDown() { - return down; - } - - public void setDown(Key down) { - this.down = down; - } - - public Key getLeft() { - return left; - } - - public void setLeft(Key left) { - this.left = left; - } - - public Key getRight() { - return right; - } - - public void setRight(Key right) { - this.right = right; + public Key getRIGHT_KEY() { + return RIGHT_KEY; } public boolean isIgnoreInput() { @@ -202,10 +172,11 @@ private void setIgnoreInput(boolean ignoreInput) { this.ignoreInput = ignoreInput; } - public class Key { + public static class Key { private int numTimesPressed = 0; private boolean pressed = false; + @Deprecated public int getNumTimesPressed() { return numTimesPressed; } @@ -221,6 +192,7 @@ void toggle(boolean isPressed) { } } + @Deprecated public void off() { pressed = false; numTimesPressed = 0; diff --git a/src/com/redomar/game/entities/Player.java b/src/com/redomar/game/entities/Player.java index 5b9a0cf..6a5d0b2 100644 --- a/src/com/redomar/game/entities/Player.java +++ b/src/com/redomar/game/entities/Player.java @@ -57,16 +57,16 @@ public void tick() { double ya = 0; if (input != null) { - if (input.getUp().isPressed() && input.isIgnoreInput() == false) { + if (input.getUP_KEY().isPressed() && input.isIgnoreInput() == false) { ya -= speed; } - if (input.getDown().isPressed() && input.isIgnoreInput() == false) { + if (input.getDOWN_KEY().isPressed() && input.isIgnoreInput() == false) { ya += speed; } - if (input.getLeft().isPressed() && input.isIgnoreInput() == false) { + if (input.getLEFT_KEY().isPressed() && input.isIgnoreInput() == false) { xa -= speed; } - if (input.getRight().isPressed() && input.isIgnoreInput() == false) { + if (input.getRIGHT_KEY().isPressed() && input.isIgnoreInput() == false) { xa += speed; } } diff --git a/src/com/redomar/game/menu/Menu.java b/src/com/redomar/game/menu/Menu.java index 6726d68..ec68f05 100644 --- a/src/com/redomar/game/menu/Menu.java +++ b/src/com/redomar/game/menu/Menu.java @@ -13,96 +13,54 @@ import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.image.BufferStrategy; +import java.net.URL; +import java.util.concurrent.atomic.AtomicReference; public class Menu implements Runnable { + private static final int VOLUME_IN_DB = -20; + private static final String NAME = "Menu"; private static final int WIDTH = 160; private static final int HEIGHT = (WIDTH / 3 * 2); private static final int SCALE = 3; - private static final String NAME = "Menu"; - private static boolean running = false; private static boolean selectedStart = true; private static boolean selectedExit = false; - private static boolean gameOver = false; + private static DedicatedJFrame frame; - private static DedicatedJFrame frame;// = new DedicatedJFrame(WIDTH, HEIGHT, - private static final JDialog dialog = new JDialog(); - // SCALE, NAME); - private Font font = new Font(); - private MouseListener Mouse = new Mouse(); - private KeyListener Key = new MenuInput(); + private final Font font = new Font(); + private final MouseListener menuMouseListener = new Mouse(); + private final KeyListener menuKeyListener = new MenuInput(); - private Color selected = new Color(0xFFFF8800); - private Color deSelected = new Color(0xFFCC5500); - - public static synchronized void stop() { - running = false; - } + private final Color SELECTED_COLOUR = new Color(0xFFFF8800); + private final Color UNSELECTED_COLOUR = new Color(0xFFCC5500); public static void play() { try { - JSplash splash = new JSplash( - Game.class.getResource("/splash/splash.png"), true, true, - false, Game.getGameVersion(), null, Color.RED, Color.ORANGE); + // Splash screen + AtomicReference splashImageResource = new AtomicReference<>(Game.class.getResource("/splash/splash.png")); + JSplash splash = new JSplash(splashImageResource.get(), true, true, false, Game.getGameVersion(), null, Color.RED, Color.ORANGE); splash.toFront(); splash.requestFocus(); splash.splashOn(); - splash.setProgress(20, "Loading Music"); + + // Background tasks Game.setBackgroundMusic(new AudioHandler("/music/Towards The End.wav")); - splash.setProgress(50, "Setting Volume"); - Game.getBackgroundMusic().setVolume(-20); - splash.setProgress(60, "Acquiring data: Multiplayer"); - Thread.sleep(125); + Game.getBackgroundMusic().setVolume(VOLUME_IN_DB); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - String multiMsg = "Sorry but multiplayer has been disabled on this version.\nIf you would like multiplayer checkout Alpha 1.6"; - dialog.setAlwaysOnTop(true); - JOptionPane.showMessageDialog(dialog, multiMsg, - "Multiplayer Warning", JOptionPane.WARNING_MESSAGE); - // Game.setJdata_Host(JOptionPane.showConfirmDialog(Game.getGame(), - // "Do you want to be the HOST?")); - Game.setJdata_Host(1); - if (Game.getJdata_Host() != 1) { // Game.getJdata_Host() == 1 - Game.setJdata_IP(JOptionPane.showInputDialog(dialog, - "Enter the name \nleave blank for local")); - } - Thread.sleep(125); - splash.setProgress(70, "Acquiring data: Username"); - String s = JOptionPane.showInputDialog(dialog, - "Enter a name"); - if (s != null) { - Game.setJdata_UserName(s); - } - Thread.sleep(125); - splash.setProgress(90, "Collecting Player Data"); - Object[] options = {"African", "Caucasian"}; - int n = JOptionPane.showOptionDialog(dialog, - "Choose a race for the character to be", "Choose a race", - JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, - null, options, options[0]); - if (n == 0) { - Game.setAlternateColsR(true); - } else { - Game.setAlternateColsR(false); - } - Thread.sleep(250); - Object[] options1 = {"Orange", "Black"}; - int n1 = JOptionPane.showOptionDialog(dialog, - "Which Colour do you want the shirt to be?", - "Choose a shirt Colour", JOptionPane.YES_NO_OPTION, - JOptionPane.QUESTION_MESSAGE, null, options1, options1[0]); - if (n1 == 0) { - Game.setAlternateColsS(true); - } else { - Game.setAlternateColsS(false); - } - splash.setProgress(100, "Connecting as" + Game.getJdata_UserName()); - Thread.sleep(250); - splash.splashOff(); + Game.setAlternateColsR(true); + Game.setAlternateColsS(true); + splash.setProgress(100, "Connecting as " + Game.getJdata_UserName()); + Thread.sleep(650); + + // Frame Init frame = new DedicatedJFrame(WIDTH, HEIGHT, SCALE, NAME); - frame.getFrame(); frame.getFrame().setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.requestFocus(); + + // Hide splash + splash.splashOff(); + splash.removeAll(); } catch (Exception e) { e.printStackTrace(); } @@ -112,10 +70,6 @@ public static DedicatedJFrame getFrame() { return Menu.frame; } - public static void setFrame(DedicatedJFrame frame) { - Menu.frame = frame; - } - public static boolean isRunning() { return running; } @@ -140,20 +94,8 @@ public static void setSelectedExit(boolean selectedExit) { Menu.selectedExit = selectedExit; } - public static int getWidth() { - return WIDTH; - } - - public static int getHeight() { - return HEIGHT; - } - - public static boolean isGameOver() { - return gameOver; - } - - public static void setGameOver(boolean gameOver) { - Menu.gameOver = gameOver; + public static synchronized void stop() { + running = false; } public synchronized void start() { @@ -184,12 +126,6 @@ public void run() { shouldRender = true; } - try { - Thread.sleep(2); - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (shouldRender) { frames++; render(); @@ -197,8 +133,7 @@ public void run() { if (System.currentTimeMillis() - lastTimer >= 1000) { lastTimer += 1000; - frame.getFrame().setTitle( - "Frames: " + frames + " Ticks: " + ticks); + frame.getFrame().setTitle("Frames: " + frames + " Ticks: " + ticks); frames = 0; ticks = 0; } @@ -207,9 +142,9 @@ public void run() { private void render() { // frame.getFrame().getContentPane().setBackground(Color.GREEN); - frame.addMouseMotionListener((MouseMotionListener) Mouse); - frame.addMouseListener(Mouse); - frame.addKeyListener(Key); + frame.addMouseMotionListener((MouseMotionListener) menuMouseListener); + frame.addMouseListener(menuMouseListener); + frame.addKeyListener(menuKeyListener); BufferStrategy bs = frame.getBufferStrategy(); if (bs == null) { frame.createBufferStrategy(3); @@ -222,14 +157,8 @@ private void render() { g.fillRect(0, 0, WIDTH * 3, HEIGHT * 3); g.setColor(new Color(0xFFFF9900)); g.setFont(font.getArial()); - if (isGameOver()) { - g.drawString("GAME OVER... What will you do now?", 35, 30); - } else { - String name = (Game.getJdata_UserName().length() >= 1) ? WordUtils - .capitalizeFully(Game.getJdata_UserName()).toString() - : "Player"; - g.drawString("Welcome to JavaGame " + name, 35, 30); - } + String name = (Game.getJdata_UserName().length() >= 1) ? WordUtils.capitalizeFully(Game.getJdata_UserName()) : "Player"; + g.drawString("Welcome to JavaGame " + name, 35, 30); g.drawLine(0, HEIGHT * 3, 0, 0); g.drawLine(0, 0, (WIDTH * 3), 0); g.drawLine((WIDTH * 3), 0, (WIDTH * 3), (HEIGHT * 3)); @@ -246,11 +175,11 @@ private void paintButtons(boolean start, boolean exit, Graphics g) { if (!start) { g.setColor(new Color(0xFFBB4400)); g.fillRect(35, 40, (frame.getWidth() - 67), 113); - g.setColor(getDeSelected()); + g.setColor(UNSELECTED_COLOUR); } else { g.setColor(new Color(0xFFDD6600)); g.fillRect(35, 40, (frame.getWidth() - 67), 113); - g.setColor(getSelected()); + g.setColor(SELECTED_COLOUR); } g.fillRect(35, 40, (frame.getWidth() - 70), 110); g.setColor(Color.BLACK); @@ -259,31 +188,15 @@ private void paintButtons(boolean start, boolean exit, Graphics g) { if (!exit) { g.setColor(new Color(0xFFBB4400)); g.fillRect(35, 170, (frame.getWidth() - 67), 113); - g.setColor(getDeSelected()); + g.setColor(UNSELECTED_COLOUR); } else { g.setColor(new Color(0xFFDD6600)); g.fillRect(35, 170, (frame.getWidth() - 67), 113); - g.setColor(getSelected()); + g.setColor(SELECTED_COLOUR); } g.fillRect(35, 170, (frame.getWidth() - 70), 110); g.setColor(Color.BLACK); g.drawString("Exit", 220, 220); } - public Color getSelected() { - return selected; - } - - public void setSelected(Color selected) { - this.selected = selected; - } - - public Color getDeSelected() { - return deSelected; - } - - public void setDeSelected(Color deSelected) { - this.deSelected = deSelected; - } - } diff --git a/src/com/redomar/game/menu/MenuInput.java b/src/com/redomar/game/menu/MenuInput.java index 59642ff..599f15e 100644 --- a/src/com/redomar/game/menu/MenuInput.java +++ b/src/com/redomar/game/menu/MenuInput.java @@ -8,6 +8,7 @@ public class MenuInput implements KeyListener { + private static final HelpMenu HELP_MENU = new HelpMenu(); private boolean ticket = false; private boolean help = false; @@ -35,14 +36,15 @@ private void toggleKey(int keyCode) { Menu.setSelectedStart(false); } - if(!ticket){ + if (!ticket) { if (keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_SPACE) { if (Menu.isSelectedStart()) { this.ticket = true; + new Game().start(); Menu.setRunning(false); Menu.getFrame().setVisible(false); Menu.getFrame().stopFrame(); - new Game().start(); + Menu.stop(); } if (Menu.isSelectedExit()) { @@ -50,18 +52,19 @@ private void toggleKey(int keyCode) { Menu.setRunning(false); Menu.getFrame().setVisible(false); Menu.getFrame().stopFrame(); + Menu.stop(); } } } if (keyCode == KeyEvent.VK_ESCAPE) { - System.exit(1); + HELP_MENU.helpMenuClose(); + help = false; + System.exit(0); } - if (keyCode == KeyEvent.VK_H){ - HelpMenu h = new HelpMenu(); - if (!help) - h.run(); + if (keyCode == KeyEvent.VK_H) { + if (!help) HELP_MENU.helpMenuLaunch(); help = true; } } diff --git a/src/com/redomar/game/script/Printing.java b/src/com/redomar/game/script/Printing.java index aba3de7..8b54977 100644 --- a/src/com/redomar/game/script/Printing.java +++ b/src/com/redomar/game/script/Printing.java @@ -8,13 +8,9 @@ public class Printing { private static int lineNumber = 0; + private final Time time = new Time(); private PrintTypes type; - private Time time = new Time(); private String message; - private String msgTime; - private String msgType; - private boolean errorMode = false; - private PrintToLog logFile; public Printing() { @@ -22,62 +18,53 @@ public Printing() { public void print(String message, PrintTypes type) { this.type = type; - setMessage(message); - readMessageType(type); + this.message = message; printOut(); } - private void printOut(){ - msgTime = "[" + time.getTime() + "]"; - msgType = "[" + type.toString() + "]"; + private void printOut() { + String msgTime = "[" + time.getTime() + "]"; + String msgType = "[" + type.toString() + "]"; - logFile = printToLogType(type); + PrintToLog logFile = printToLogType(type); if (lineNumber == 0) { String dashes = ""; String title = ("[" + time.getTimeDate() + "]"); char dash = '-'; - int number = title.length() / 3; + int number = Math.max((title.length() / 3), 10); char[] repeat = new char[number]; Arrays.fill(repeat, dash); dashes += new String(repeat); - logFile.log(dashes + title + dashes + "\n" + msgTime + msgType + this.getMessage()); + logFile.log(String.format("%s%s%s", dashes, title, dashes)); lineNumber++; - } else { - logFile.log(msgTime + msgType + this.getMessage()); } + logFile.log(String.format("%s%s\t%s", msgTime, msgType, message)); + String formattedStringForConsole = String.format("%s%s %s%n", msgType, msgTime, message); - if(errorMode) { - System.err.println(msgType + msgTime + message); - }else{ - System.out.println(msgType + msgTime + message); + if (type.equals(PrintTypes.ERROR)) { + System.err.printf(formattedStringForConsole); + } else { + System.out.printf(formattedStringForConsole); } } - private PrintToLog printToLogType(PrintTypes type){ - if (type == PrintTypes.TEST){ + private PrintToLog printToLogType(PrintTypes type) { + if (type == PrintTypes.TEST) { return new PrintToLog(".PrintType-TEST.txt"); } else { return new PrintToLog(".log.txt"); } } - public void removeLog(){ - new File(".log.txt").delete(); + public boolean removeLog() { + return new File(".log.txt").delete(); } public String getMessage() { return message; } - - public void setMessage(String message) { - this.message = message; - } - - private void readMessageType(PrintTypes type){ - this.errorMode = type == PrintTypes.ERROR; - } } diff --git a/test/com/redomar/game/script/PrintingTest.java b/test/com/redomar/game/script/PrintingTest.java index ab38469..4b89ce5 100644 --- a/test/com/redomar/game/script/PrintingTest.java +++ b/test/com/redomar/game/script/PrintingTest.java @@ -17,12 +17,12 @@ public class PrintingTest { private Printing printing; @Before - public void setUp() throws Exception { + public void setUp() { printing = new Printing(); } @Test - public void printToFileWorks() throws Exception { + public void printToFileWorks() { printing.print("TESTING STRING", PrintTypes.TEST); File file = new File(".PrintType-TEST.txt"); assertTrue(file.exists()); @@ -35,13 +35,13 @@ public void getMessageIsNull() { } @Test - public void getMessageIsNotNull() { - printing.setMessage("Not Null"); + public void messageShouldBeNullAfterPrinting() { + printing.print("Not Null", PrintTypes.TEST); assertNotNull(printing.getMessage()); } @After - public void cleanUp(){ + public void cleanUp() { printing = null; } From 62d26f02fa72c55f11441e5df5a0cf98a3c2a1e1 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Sun, 1 Jan 2023 23:19:29 +0000 Subject: [PATCH 02/12] #22 Refactored Player and Deprecated Multiplayer Code --- src/com/redomar/game/entities/Player.java | 144 +++++++----------- src/com/redomar/game/entities/PlayerMP.java | 13 +- src/com/redomar/game/net/GameClient.java | 35 ++--- src/com/redomar/game/net/GameServer.java | 46 +++--- src/com/redomar/game/net/packets/Packet.java | 51 ++++--- .../game/net/packets/Packet00Login.java | 10 +- .../game/net/packets/Packet01Disconnect.java | 7 +- .../game/net/packets/Packet02Move.java | 23 ++- 8 files changed, 141 insertions(+), 188 deletions(-) diff --git a/src/com/redomar/game/entities/Player.java b/src/com/redomar/game/entities/Player.java index 6a5d0b2..c52a083 100644 --- a/src/com/redomar/game/entities/Player.java +++ b/src/com/redomar/game/entities/Player.java @@ -15,84 +15,71 @@ public class Player extends Mob { - private static Name customeName = new Name(); - public static String guestPlayerName = customeName.setName("Player "); - private static double speed = 1; - private static int[] collisionBoders = {-2, 8, 0, 7}; - private InputHandler input; - private Swim swim; - private int colour, shirtCol, faceCol; + private static final int[] COLLISION_BORDERS = {-2, 8, 0, 7}; + private static final String guestPlayerName = new Name().setName("Player "); + private static final double speed = 1; + private final InputHandler inputHandler; + private final int shirtColour; + private final int faceColour; + private int colour; private int tickCount = 0; + private Swim swim; private String userName; private boolean[] swimType; - private int[] swimColour; - private int fireRate = 0; - - // Need to add a class for constants - private final int fontCharSize = 8; + private int fireRate; // "Cache" the division for the username length, no need for 60 divisions per second here. private int nameOffset = 0; - public Player(LevelHandler level, int x, int y, InputHandler input, - String userName, int shirtCol, int faceCol) { - super(level, "Player", x, y, speed, collisionBoders); - this.input = input; + public Player(LevelHandler level, int x, int y, InputHandler inputHandler, String userName, int shirtColour, int faceColour) { + super(level, "Player", x, y, speed, COLLISION_BORDERS); + this.inputHandler = inputHandler; this.userName = userName; - this.faceCol = faceCol; - this.shirtCol = shirtCol; - this.colour = Colours.get(-1, 111, shirtCol, faceCol); + this.faceColour = faceColour; + this.shirtColour = shirtColour; + this.colour = Colours.get(-1, 111, shirtColour, faceColour); fireRate = Small.FIRE_RATE; } - public static double getSpeed() { - return speed; - } - - public static void setSpeed(double speed) { - Player.speed = speed; - } - public void tick() { double xa = 0; double ya = 0; - if (input != null) { - if (input.getUP_KEY().isPressed() && input.isIgnoreInput() == false) { + if (inputHandler != null) { + if (inputHandler.getUP_KEY().isPressed() && !inputHandler.isIgnoreInput()) { ya -= speed; } - if (input.getDOWN_KEY().isPressed() && input.isIgnoreInput() == false) { + if (inputHandler.getDOWN_KEY().isPressed() && !inputHandler.isIgnoreInput()) { ya += speed; } - if (input.getLEFT_KEY().isPressed() && input.isIgnoreInput() == false) { + if (inputHandler.getLEFT_KEY().isPressed() && !inputHandler.isIgnoreInput()) { xa -= speed; } - if (input.getRIGHT_KEY().isPressed() && input.isIgnoreInput() == false) { + if (inputHandler.getRIGHT_KEY().isPressed() && !inputHandler.isIgnoreInput()) { xa += speed; } } - if(fireRate > 0) fireRate--; + if (fireRate > 0) fireRate--; - if (Game.getMouse().getButton() == 1 || Game.getMouse().getButton() == 3){ - if(fireRate <= 0){ - if(Game.getMouse().getButton()== 1){ + if (Game.getMouse().getButton() == 1 || Game.getMouse().getButton() == 3) { + if (fireRate <= 0) { + if (Game.getMouse().getButton() == 1) { fireRate = Small.FIRE_RATE; - }else if(Game.getMouse().getButton() == 3){ + } else if (Game.getMouse().getButton() == 3) { fireRate = Medium.FIRE_RATE; } - if(!swim.isActive(swimType)){ - double dx = Game.getMouse().getX() - 480/2; - double dy = Game.getMouse().getY() - 320/2; + if (!swim.isActive(swimType)) { + double dx = Game.getMouse().getX() - 480 / 2d; + double dy = Game.getMouse().getY() - 320 / 2d; double dir = Math.atan2(dy, dx); shoot(x, y, dir, Game.getMouse().getButton(), false); } } } - for (int i = 0; i < projectiles.size(); i++) { - Projectile p = projectiles.get(i); - if(p.isRemoved()){ - projectiles.remove(i); + for (Projectile p : projectiles) { + if (p.isRemoved()) { + p.remove(); Game.getLevel().removeProjectileEntities(p); } } @@ -100,13 +87,11 @@ public void tick() { if (xa != 0 || ya != 0) { move(xa, ya); isMoving = true; - Game.getGame(); - } else { isMoving = false; } - setSwim(new Swim(level, (int) getX(), (int) getY())); + swim = new Swim(level, (int) getX(), (int) getY()); swimType = swim.swimming(isSwimming, isMagma, isMuddy); isSwimming = swimType[0]; isMagma = swimType[1]; @@ -130,7 +115,7 @@ public void render(Screen screen) { if (movingDir == 1) { xTile += 2; - if (!isMoving || swim.isActive(swimType)){ + if (!isMoving || swim.isActive(swimType)) { yTile -= 2; } } else if (movingDir == 0 && !isMoving || movingDir == 0 && swim.isActive(swimType)) { @@ -138,7 +123,7 @@ public void render(Screen screen) { } else if (movingDir > 1) { xTile += 4 + ((numSteps >> walkingSpeed) & 1) * 2; flipTop = (movingDir - 1) % 2; - if(!isMoving){ + if (!isMoving) { xTile = 4; } } @@ -151,44 +136,36 @@ public void render(Screen screen) { Game.setChangeLevel(true); } - if(isSwimming || isMagma || isMuddy){ - swimColour = swim.waveCols(isSwimming, isMagma, isMuddy); + if (isSwimming || isMagma || isMuddy) { + int[] swimColour = swim.waveCols(isSwimming, isMagma, isMuddy); - int waterColour = 0; + int waterColour; yOffset += 4; - colour = Colours.get(-1, 111, -1, faceCol); + colour = Colours.get(-1, 111, -1, faceColour); if (tickCount % 60 < 15) { waterColour = Colours.get(-1, -1, swimColour[0], -1); - } else if (15 <= tickCount % 60 && tickCount % 60 < 30) { + } else if (tickCount % 60 < 30) { yOffset--; waterColour = Colours.get(-1, swimColour[1], swimColour[2], -1); - } else if (30 <= tickCount % 60 && tickCount % 60 < 45) { + } else if (tickCount % 60 < 45) { waterColour = Colours.get(-1, swimColour[2], -1, swimColour[1]); } else { yOffset--; waterColour = Colours.get(-1, -1, swimColour[1], swimColour[2]); } - screen.render(xOffset, yOffset + 3, 31 + 31 * 32, waterColour, - 0x00, 1); - screen.render(xOffset + 8, yOffset + 3, 31 + 31 * 32, waterColour, - 0x01, 1); + screen.render(xOffset, yOffset + 3, 31 + 31 * 32, waterColour, 0x00, 1); + screen.render(xOffset + 8, yOffset + 3, 31 + 31 * 32, waterColour, 0x01, 1); } - screen.render((xOffset + (modifier * flipTop)), yOffset, - (xTile + yTile * 32), colour, flipTop, scale); - screen.render((xOffset + modifier - (modifier * flipTop)), yOffset, - ((xTile + 1) + yTile * 32), colour, flipTop, scale); + screen.render((xOffset + (modifier * flipTop)), yOffset, (xTile + yTile * 32), colour, flipTop, scale); + screen.render((xOffset + modifier - (modifier * flipTop)), yOffset, ((xTile + 1) + yTile * 32), colour, flipTop, scale); if (!isSwimming && !isMagma && !isMuddy) { - screen.render((xOffset + (modifier * flipBottom)), - (yOffset + modifier), (xTile + (yTile + 1) * 32), colour, - flipBottom, scale); - screen.render((xOffset + modifier - (modifier * flipBottom)), - (yOffset + modifier), ((xTile + 1) + (yTile + 1) * 32), - colour, flipBottom, scale); - colour = Colours.get(-1, 111, shirtCol, faceCol); + screen.render((xOffset + (modifier * flipBottom)), (yOffset + modifier), (xTile + (yTile + 1) * 32), colour, flipBottom, scale); + screen.render((xOffset + modifier - (modifier * flipBottom)), (yOffset + modifier), ((xTile + 1) + (yTile + 1) * 32), colour, flipBottom, scale); + colour = Colours.get(-1, 111, shirtColour, faceColour); } if (userName != null) { @@ -198,11 +175,7 @@ public void render(Screen screen) { * -posmicanomaly */ - Font.render(userName, - screen, - (int)x - nameOffset, - yOffset - 10, - Colours.get(-1, -1, -1, 111), 1); + Font.render(userName, screen, (int) x - nameOffset, yOffset - 10, Colours.get(-1, -1, -1, 111), 1); } } @@ -219,6 +192,8 @@ public void setUsername(String name) { } public String getSanitisedUsername() { + // Need to add a class for constants + int fontCharSize = 8; if (this.getUsername() == null || this.userName.isEmpty()) { setUsername(guestPlayerName); @@ -227,20 +202,11 @@ public String getSanitisedUsername() { nameOffset = (userName.length() / 2) * fontCharSize - offsetUnit; return guestPlayerName; - } else - if(nameOffset == 0){ - int offsetUnit = ((userName.length() & 1) == 0 ? fontCharSize / 2 : 0); - nameOffset = (userName.length() / 2) * fontCharSize - offsetUnit; - } - return this.getUsername(); - } - - public Swim getSwim() { - return swim; - } - - public void setSwim(Swim swim) { - this.swim = swim; + } else if (nameOffset == 0) { + int offsetUnit = ((userName.length() & 1) == 0 ? fontCharSize / 2 : 0); + nameOffset = (userName.length() / 2) * fontCharSize - offsetUnit; + } + return this.getUsername(); } } diff --git a/src/com/redomar/game/entities/PlayerMP.java b/src/com/redomar/game/entities/PlayerMP.java index 4707161..adf8d21 100644 --- a/src/com/redomar/game/entities/PlayerMP.java +++ b/src/com/redomar/game/entities/PlayerMP.java @@ -5,22 +5,21 @@ import java.net.InetAddress; +@Deprecated public class PlayerMP extends Player { - public InetAddress ipAddess; + public InetAddress ipAddress; public int port; - public PlayerMP(LevelHandler level, int x, int y, InputHandler input, - String userName, InetAddress ipAddress, int port, int shirtCol, int faceCol) { + public PlayerMP(LevelHandler level, int x, int y, InputHandler input, String userName, InetAddress ipAddress, int port, int shirtCol, int faceCol) { super(level, x, y, input, userName, shirtCol, faceCol); - this.ipAddess = ipAddress; + this.ipAddress = ipAddress; this.port = port; } - public PlayerMP(LevelHandler level, int x, int y, String userName, - InetAddress ipAddress, int port, int shirtCol, int faceCol) { + public PlayerMP(LevelHandler level, int x, int y, String userName, InetAddress ipAddress, int port, int shirtCol, int faceCol) { super(level, x, y, null, userName, shirtCol, faceCol); - this.ipAddess = ipAddress; + this.ipAddress = ipAddress; this.port = port; } diff --git a/src/com/redomar/game/net/GameClient.java b/src/com/redomar/game/net/GameClient.java index 05614fd..eccec0e 100644 --- a/src/com/redomar/game/net/GameClient.java +++ b/src/com/redomar/game/net/GameClient.java @@ -13,21 +13,20 @@ import java.io.IOException; import java.net.*; +@Deprecated public class GameClient extends Thread { + private final Printing print = new Printing(); private InetAddress ipAddress; private DatagramSocket socket; private Game game; - private Printing print = new Printing(); public GameClient(Game game, String ipAddress) { this.setGame(game); try { this.socket = new DatagramSocket(); this.ipAddress = InetAddress.getByName(ipAddress); - } catch (SocketException e) { - e.printStackTrace(); - } catch (UnknownHostException e) { + } catch (SocketException | UnknownHostException e) { e.printStackTrace(); } } @@ -40,17 +39,17 @@ public void run() { socket.receive(packet); } catch (IOException e) { e.printStackTrace(); + break; } - this.parsePacket(packet.getData(), packet.getAddress(), - packet.getPort()); - // System.out.println("SERVER > "+new String(packet.getData())); + this.parsePacket(packet.getData(), packet.getAddress(), packet.getPort()); + System.out.println("SERVER > " + new String(packet.getData())); } } private void parsePacket(byte[] data, InetAddress address, int port) { String message = new String(data).trim(); PacketTypes type = Packet.lookupPacket(message.substring(0, 2)); - Packet packet = null; + Packet packet; switch (type) { default: case INVALID: @@ -61,11 +60,8 @@ private void parsePacket(byte[] data, InetAddress address, int port) { break; case DISCONNECT: packet = new Packet01Disconnect(data); - print.print("[" + address.getHostAddress() + ":" + port - + "] " + ((Packet01Disconnect) packet).getUsername() - + " has disconnected...", PrintTypes.NETWORK); - Game.getLevel().removeEntity( - ((Packet01Disconnect) packet).getUsername()); + print.print("[" + address.getHostAddress() + ":" + port + "] " + ((Packet01Disconnect) packet).getUsername() + " has disconnected...", PrintTypes.NETWORK); + Game.getLevel().removeEntity(((Packet01Disconnect) packet).getUsername()); break; case MOVE: packet = new Packet02Move(data); @@ -75,22 +71,17 @@ private void parsePacket(byte[] data, InetAddress address, int port) { } private void handleLogin(Packet00Login packet, InetAddress address, int port) { - print.print("[" + address.getHostAddress() + ":" + port + "] " - + packet.getUsername() + " has joined...", PrintTypes.NETWORK); - PlayerMP player = new PlayerMP(Game.getLevel(), packet.getX(), - packet.getY(), packet.getUsername(), address, port, Game.getShirtCol(), Game.getFaceCol()); + print.print("[" + address.getHostAddress() + ":" + port + "] " + packet.getUsername() + " has joined...", PrintTypes.NETWORK); + PlayerMP player = new PlayerMP(Game.getLevel(), packet.getX(), packet.getY(), packet.getUsername(), address, port, Game.getShirtCol(), Game.getFaceCol()); Game.getLevel().addEntity(player); } private void handleMove(Packet02Move packet) { - Game.getLevel().movePlayer(packet.getUsername(), packet.getX(), - packet.getY(), packet.getNumSteps(), packet.isMoving(), - packet.getMovingDir()); + Game.getLevel().movePlayer(packet.getUsername(), packet.getX(), packet.getY(), packet.getNumSteps(), packet.isMoving(), packet.getMovingDir()); } public void sendData(byte[] data) { - DatagramPacket packet = new DatagramPacket(data, data.length, - ipAddress, 1331); + DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 1331); try { socket.send(packet); } catch (IOException e) { diff --git a/src/com/redomar/game/net/GameServer.java b/src/com/redomar/game/net/GameServer.java index 9d27a3f..f8bb8e0 100644 --- a/src/com/redomar/game/net/GameServer.java +++ b/src/com/redomar/game/net/GameServer.java @@ -18,12 +18,13 @@ import java.util.ArrayList; import java.util.List; +@Deprecated public class GameServer extends Thread { + private final List connectedPlayers = new ArrayList<>(); + private final Printing print = new Printing(); private DatagramSocket socket; private Game game; - private List connectedPlayers = new ArrayList(); - private Printing print = new Printing(); public GameServer(Game game) { this.setGame(game); @@ -42,42 +43,36 @@ public void run() { socket.receive(packet); } catch (IOException e) { e.printStackTrace(); + break; } - this.parsePacket(packet.getData(), packet.getAddress(), - packet.getPort()); + this.parsePacket(packet.getData(), packet.getAddress(), packet.getPort()); - // String message = new String(packet.getData()); - // System.out.println("CLIENT ["+packet.getAddress().getHostAddress()+":"+packet.getPort()+"] "+message); - // if(message.trim().equalsIgnoreCase("ping")){ - // sendData("pong".getBytes(), packet.getAddress(), - // packet.getPort()); - // } + String message = new String(packet.getData()); + System.out.println("CLIENT [" + packet.getAddress().getHostAddress() + ":" + packet.getPort() + "] " + message); + if (message.trim().equalsIgnoreCase("ping")) { + sendData("pong".getBytes(), packet.getAddress(), packet.getPort()); + } } } private void parsePacket(byte[] data, InetAddress address, int port) { String message = new String(data).trim(); PacketTypes type = Packet.lookupPacket(message.substring(0, 2)); - Packet packet = null; + Packet packet; switch (type) { default: case INVALID: break; case LOGIN: packet = new Packet00Login(data); - print.print("[" + address.getHostAddress() + ":" + port - + "] " + ((Packet00Login) packet).getUsername() - + " has connected...", PrintTypes.SERVER); - PlayerMP player = new PlayerMP(Game.getLevel(), 10, 10, - ((Packet00Login) packet).getUsername(), address, port, Game.getShirtCol(), Game.getFaceCol()); + print.print("[" + address.getHostAddress() + ":" + port + "] " + ((Packet00Login) packet).getUsername() + " has connected...", PrintTypes.SERVER); + PlayerMP player = new PlayerMP(Game.getLevel(), 10, 10, ((Packet00Login) packet).getUsername(), address, port, Game.getShirtCol(), Game.getFaceCol()); this.addConnection(player, (Packet00Login) packet); break; case DISCONNECT: packet = new Packet01Disconnect(data); - print.print("[" + address.getHostAddress() + ":" + port - + "] " + ((Packet01Disconnect) packet).getUsername() - + " has disconnected...", PrintTypes.SERVER); + print.print("[" + address.getHostAddress() + ":" + port + "] " + ((Packet01Disconnect) packet).getUsername() + " has disconnected...", PrintTypes.SERVER); this.removeConnection((Packet01Disconnect) packet); break; case MOVE: @@ -103,8 +98,8 @@ public void addConnection(PlayerMP player, Packet00Login packet) { boolean alreadyConnected = false; for (PlayerMP p : this.connectedPlayers) { if (player.getUsername().equalsIgnoreCase(p.getUsername())) { - if (p.ipAddess == null) { - p.ipAddess = player.ipAddess; + if (p.ipAddress == null) { + p.ipAddress = player.ipAddress; } if (p.port == -1) { @@ -113,10 +108,10 @@ public void addConnection(PlayerMP player, Packet00Login packet) { alreadyConnected = true; } else { - sendData(packet.getData(), p.ipAddess, p.port); + sendData(packet.getData(), p.ipAddress, p.port); packet = new Packet00Login(p.getUsername(), (int) p.getX(), (int) p.getY()); - sendData(packet.getData(), player.ipAddess, player.port); + sendData(packet.getData(), player.ipAddress, player.port); } } if (!alreadyConnected) { @@ -151,8 +146,7 @@ public int getPlayerMPIndex(String username) { } public void sendData(byte[] data, InetAddress ipAddress, int port) { - DatagramPacket packet = new DatagramPacket(data, data.length, - ipAddress, port); + DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, port); try { this.socket.send(packet); } catch (IOException e) { @@ -162,7 +156,7 @@ public void sendData(byte[] data, InetAddress ipAddress, int port) { public void sendDataToAllClients(byte[] data) { for (PlayerMP p : connectedPlayers) { - sendData(data, p.ipAddess, p.port); + sendData(data, p.ipAddress, p.port); } } diff --git a/src/com/redomar/game/net/packets/Packet.java b/src/com/redomar/game/net/packets/Packet.java index 743784f..938c085 100644 --- a/src/com/redomar/game/net/packets/Packet.java +++ b/src/com/redomar/game/net/packets/Packet.java @@ -3,39 +3,15 @@ import com.redomar.game.net.GameClient; import com.redomar.game.net.GameServer; +@Deprecated public abstract class Packet { - public static enum PacketTypes { - INVALID(-1), LOGIN(00), DISCONNECT(01), MOVE(02); - - private int packetId; - - private PacketTypes(int packetId) { - this.packetId = packetId; - } - - public int getId() { - return packetId; - } - } - public byte packetId; public Packet(int packetId) { this.packetId = (byte) packetId; } - public abstract byte[] getData(); - - public abstract void writeData(GameClient client); - - public abstract void writeData(GameServer server); - - public String readData(byte[] data) { - String message = new String(data).trim(); - return message.substring(2); - } - public static PacketTypes lookupPacket(String packetId) { try { return lookupPacket(Integer.parseInt(packetId)); @@ -52,4 +28,29 @@ public static PacketTypes lookupPacket(int id) { } return PacketTypes.INVALID; } + + public abstract byte[] getData(); + + public abstract void writeData(GameClient client); + + public abstract void writeData(GameServer server); + + public String readData(byte[] data) { + String message = new String(data).trim(); + return message.substring(2); + } + + public enum PacketTypes { + INVALID(-1), LOGIN(0x00), DISCONNECT(0x01), MOVE(0x02); + + private final int packetId; + + PacketTypes(int packetId) { + this.packetId = packetId; + } + + public int getId() { + return packetId; + } + } } diff --git a/src/com/redomar/game/net/packets/Packet00Login.java b/src/com/redomar/game/net/packets/Packet00Login.java index 4e61dc4..6382b83 100644 --- a/src/com/redomar/game/net/packets/Packet00Login.java +++ b/src/com/redomar/game/net/packets/Packet00Login.java @@ -3,13 +3,15 @@ import com.redomar.game.net.GameClient; import com.redomar.game.net.GameServer; +@Deprecated public class Packet00Login extends Packet { - private String username; - private int x, y; + private final String username; + private final int x; + private final int y; public Packet00Login(byte[] data) { - super(00); + super(0x00); String[] dataArray = readData(data).split(","); this.username = dataArray[0]; this.x = Integer.parseInt(dataArray[1]); @@ -17,7 +19,7 @@ public Packet00Login(byte[] data) { } public Packet00Login(String username, int x, int y) { - super(00); + super(0x00); this.username = username; this.x = x; this.y = y; diff --git a/src/com/redomar/game/net/packets/Packet01Disconnect.java b/src/com/redomar/game/net/packets/Packet01Disconnect.java index d95eec5..4ac5e20 100644 --- a/src/com/redomar/game/net/packets/Packet01Disconnect.java +++ b/src/com/redomar/game/net/packets/Packet01Disconnect.java @@ -3,17 +3,18 @@ import com.redomar.game.net.GameClient; import com.redomar.game.net.GameServer; +@Deprecated public class Packet01Disconnect extends Packet { - private String username; + private final String username; public Packet01Disconnect(byte[] data) { - super(01); + super(0x01); this.username = readData(data); } public Packet01Disconnect(String username) { - super(01); + super(0x01); this.username = username; } diff --git a/src/com/redomar/game/net/packets/Packet02Move.java b/src/com/redomar/game/net/packets/Packet02Move.java index 8f1e47d..1336ee0 100644 --- a/src/com/redomar/game/net/packets/Packet02Move.java +++ b/src/com/redomar/game/net/packets/Packet02Move.java @@ -3,16 +3,18 @@ import com.redomar.game.net.GameClient; import com.redomar.game.net.GameServer; +@Deprecated public class Packet02Move extends Packet { - private String username; - private int x, y; - private int numSteps = 0; - private boolean isMoving; - private int movingDir = 1; + private final String username; + private final int x; + private final int y; + private final int numSteps; + private final boolean isMoving; + private final int movingDir; public Packet02Move(byte[] data) { - super(02); + super(0x02); String[] dataArray = readData(data).split(","); this.username = dataArray[0]; this.x = Integer.parseInt(dataArray[1]); @@ -22,9 +24,8 @@ public Packet02Move(byte[] data) { this.movingDir = Integer.parseInt(dataArray[5]); } - public Packet02Move(String username, int x, int y, int numSteps, - boolean isMoving, int movingDir) { - super(02); + public Packet02Move(String username, int x, int y, int numSteps, boolean isMoving, int movingDir) { + super(0x02); this.username = username; this.x = x; this.y = y; @@ -35,9 +36,7 @@ public Packet02Move(String username, int x, int y, int numSteps, @Override public byte[] getData() { - return ("02" + this.username + "," + this.x + "," + this.y + "," - + this.getNumSteps() + "," + (this.isMoving ? 1 : 0) + "," + this - .getMovingDir()).getBytes(); + return ("02" + this.username + "," + this.x + "," + this.y + "," + this.getNumSteps() + "," + (this.isMoving ? 1 : 0) + "," + this.getMovingDir()).getBytes(); } @Override From 49a8da8c1590d1386a410f249b6c17329b63f5e0 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Mon, 2 Jan 2023 22:18:42 +0000 Subject: [PATCH 03/12] #22 Start formatting Game class --- src/com/redomar/game/Game.java | 130 +++++++++++++++------------------ 1 file changed, 58 insertions(+), 72 deletions(-) diff --git a/src/com/redomar/game/Game.java b/src/com/redomar/game/Game.java index f47f56c..d7fca27 100644 --- a/src/com/redomar/game/Game.java +++ b/src/com/redomar/game/Game.java @@ -23,7 +23,7 @@ /* * This module forms the core architecture of the JavaGame. It coordinates the various - * audio and input handler components, generates the frame, renders the screen graphics, spawns + * audio and input handler components, generates the frame, renders the screen graphics, spawns * NPCs and customizes the player. Game is also responsible for changing the maps and levels, as well * as displaying various messages on the screen (e.g. fps) */ @@ -37,7 +37,7 @@ public class Game extends Canvas implements Runnable { private static final int SCALE = 3; private static final String NAME = "Game"; // The name of the JFrame panel private static Game game; - private static Time time = new Time(); // Represents the calender's time value, in hh:mm:ss + private static Time time = new Time(); // Represents the calendar's time value, in hh:mm:ss // The properties of the player, npc, and fps/tps private static int Jdata_Host; // The host of a multiplayer game (only available in earlier versions) @@ -62,30 +62,25 @@ public class Game extends Canvas implements Runnable { private static InputHandler input; // Accepts keyboard input and follows the appropriate actions private static MouseHandler mouse; // Tracks mouse movement and clicks, and follows the appropriate actions private static InputContext context; // Provides methods to control text input facilities - private int tickCount = 0; // Graphics - private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, - BufferedImage.TYPE_INT_RGB); - private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()) // Array of red, green and blue values for each pixel - .getData(); - private int[] colours = new int[6 * 6 * 6]; // Array of 216 unique colours (6 shades of red, 6 of green, and 6 of blue) - private BufferedImage image2 = new BufferedImage(WIDTH, HEIGHT - 30, - BufferedImage.TYPE_INT_RGB); + private final BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); + private final int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); // Array of red, green and blue values for each pixel + private final int[] colours = new int[6 * 6 * 6]; // Array of 216 unique colours (6 shades of red, 6 of green, and 6 of blue) + private final BufferedImage image2 = new BufferedImage(WIDTH, HEIGHT - 30, BufferedImage.TYPE_INT_RGB); + private final Font font = new Font(); // Font object capable of displaying 2 fonts: Arial and Segoe UI + private final Printing print = new Printing(); + private int tickCount = 0; private Screen screen; private WindowHandler window; - private LevelHandler level; // Loads and renders levels along with tiles, entities, projectiles and more. + private LevelHandler level; // Loads and renders levels along with tiles, entities, projectiles and more. //The entities of the game private Player player; - private Dummy dummy; // Dummy NPC follows the player around - private Vendor vendor; // Vendor NPC exhibits random movement and is only found on cutom_level - private Spruce spruce; // Tree -- Spruce - private Font font = new Font(); // Font object capable of displaying 2 fonts: Arial and Segoe UI + private Dummy dummy; // Dummy NPC follows the player around + private Vendor vendor; // Vendor NPC exhibits random movement and is only found on custom_level + private Spruce spruce; // Tree -- Spruce private String nowPlaying; - private boolean notActive = true; - private int trigger = 0; - private Printing print = new Printing(); /** * @author Redomar @@ -99,13 +94,13 @@ public Game() { setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE)); setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE)); - setFrame(new JFrame(NAME)); // Creates the frame with a defined name - getFrame().setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Exits the program when user closes the frame + setFrame(new JFrame(NAME)); // Creates the frame with a defined name + getFrame().setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Exits the program when user closes the frame getFrame().setLayout(new BorderLayout()); - getFrame().add(this, BorderLayout.CENTER); // Centers the canvas inside the JFrame - getFrame().pack(); // Sizes the frame so that all its contents are at or above their preferred sizes + getFrame().add(this, BorderLayout.CENTER); // Centers the canvas inside the JFrame + getFrame().pack(); // Sizes the frame so that all its contents are at or above their preferred sizes getFrame().setResizable(false); - getFrame().setLocationRelativeTo(null); // Centres the window on the screen + getFrame().setLocationRelativeTo(null); // Centres the window on the screen getFrame().setVisible(true); requestFocus(); @@ -114,22 +109,22 @@ public Game() { } /** - * This method will spawn a dummy NPC into the level only if they are allowed to be spawned in. + * This method will spawn a dummy NPC into the level only if they are allowed to be spawned in. * They will be spawned at position (100, 150) with a red shirt and caucasian face. */ public static void npcSpawn() { - if (isNpc() == true) { // If NPCs are allowed in the level + if (isNpc()) { // If NPCs are allowed in the level game.setDummy(new Dummy(game.level, "Dummy", 100, 150, 500, // Create a new dummy NPC on the current game level, with name 'Dummy' - 543)); // at position (100, 150), with a red shirt and caucasian ethnicity + 543)); // at position (100, 150), with a red shirt and caucasian ethnicity game.level.addEntity(Game.getDummy()); } } /** - * This method will remove a dummy NPC from the level only if they are not allowed to be in it. + * This method will remove a dummy NPC from the level only if they are not allowed to be in it. */ public static void npcKill() { - if (isNpc() == false) { // If NPCs are not allowed in the level + if (!isNpc()) { // If NPCs are not allowed in the level game.level.removeEntity(Game.getDummy()); } } @@ -196,9 +191,8 @@ public static int getMap() { /** * Sets the level to the map [.png] provided. Starts at x100 y100. - * @param Map_str * - * Also sets predefined character colours. + * @param Map_str Also sets predefined character colours. */ public void setMap(String Map_str) { setLevel(new LevelHandler(Map_str)); @@ -214,10 +208,9 @@ public void setMap(String Map_str) { if (!alternateCols[1]) { // If the last element (face colour) is set to False Game.setFaceCol(543); // The player will be caucasian } - setPlayer(new Player(level, 100, 100, input, - getJdata_UserName(), shirtCol, faceCol)); + setPlayer(new Player(level, 100, 100, input, getJdata_UserName(), shirtCol, faceCol)); level.addEntity(player); - spruce = new Spruce(level, 70,170, 2 ); + spruce = new Spruce(level, 70, 170, 2); level.addEntity(spruce); } @@ -344,9 +337,9 @@ public static void setClosing(boolean closing) { } /* - * This method initializes the game once it starts. It populates the colour array with actual colours (6 shades each of RGB). - * This method also builds the initial game level (custom_level), spawns a new vendor NPC, and begins accepting keyboard and mouse input/tracking. - */ + * This method initializes the game once it starts. It populates the colour array with actual colours (6 shades each of RGB). + * This method also builds the initial game level (custom_level), spawns a new vendor NPC, and begins accepting keyboard and mouse input/tracking. + */ public void init() { setGame(this); int index = 0; @@ -365,9 +358,9 @@ public void init() { input = new InputHandler(this); // Input begins to record key presses setMouse(new MouseHandler(this)); // Mouse tracking and clicking is now recorded setWindow(new WindowHandler(this)); - try{ + try { setMap("/levels/custom_level.png"); - } catch (Exception e){ + } catch (Exception e) { System.err.println(e); } setMap(1); // 1 corresponds to custom_level @@ -377,24 +370,24 @@ public void init() { } /** - * This method will start the game and allow the user to start playing - */ + * This method will start the game and allow the user to start playing + */ public synchronized void start() { Game.setRunning(true); // Game will run new Thread(this, "GAME").start(); // Thread is an instance of Runnable. Whenever it is started, it will run the run() method } /** - * This method will stop the game - */ + * This method will stop the game + */ public synchronized void stop() { Game.setRunning(false); // Game will not run } /** - * This method forms the game loop, determining how the game runs. It runs throughout the entire game, - * continuously updating the game state and rendering the game. - */ + * This method forms the game loop, determining how the game runs. It runs throughout the entire game, + * continuously updating the game state and rendering the game. + */ public void run() { long lastTime = System.nanoTime(); double nsPerTick = 1000000000D / 60D; // The number of nanoseconds in one tick (number of ticks limited to 60 per update) @@ -422,7 +415,8 @@ public void run() { try { Thread.sleep(2); // Delays the thread by 2 milliseconds - prevents the loop from using too much CPU - } catch (InterruptedException e) { // If the current thread is interrupted, the interrupted status is cleared + } catch ( + InterruptedException e) { // If the current thread is interrupted, the interrupted status is cleared e.printStackTrace(); } @@ -433,10 +427,7 @@ public void run() { if (System.currentTimeMillis() - lastTimer >= 1000) { // If elapsed time is greater than or equal to 1 second, update lastTimer += 1000; // Updates in another second - getFrame().setTitle( - "JavaGame - Version " - + WordUtils.capitalize(game_Version).substring( - 1, game_Version.length())); + getFrame().setTitle("JavaGame - Version " + WordUtils.capitalize(game_Version).substring(1, game_Version.length())); fps = frames; tps = ticks; frames = 0; // Reset the frames once per second @@ -447,16 +438,16 @@ public void run() { } /** - * This method updates the logic of the game. - */ + * This method updates the logic of the game. + */ public void tick() { setTickCount(getTickCount() + 1); level.tick(); } /** - * This method displays the current state of the game. - */ + * This method displays the current state of the game. + */ public void render() { BufferStrategy bs = getBufferStrategy(); if (bs == null) { @@ -490,12 +481,12 @@ public void render() { } } - if (isChangeLevel() == true && getTickCount() % 60 == 0) { + if (isChangeLevel() && getTickCount() % 60 == 0) { Game.setChangeLevel(true); setChangeLevel(false); } - if (changeLevel == true) { // If the player is teleporting to a different level + if (changeLevel) { // If the player is teleporting to a different level print.print("Teleported into new world", PrintTypes.GAME); if (getMap() == 1) { // If the player is currently on custom_level setMap("/levels/water_level.png"); @@ -524,19 +515,15 @@ public void render() { g.drawImage(image2, 0, getHeight() - 30, getWidth(), getHeight(), null); g.setColor(Color.WHITE); g.setFont(font.getSegoe()); - g.drawString( - "Welcome " - + WordUtils.capitalizeFully(player - .getSanitisedUsername()), 3, getHeight() - 17); + g.drawString("Welcome " + WordUtils.capitalizeFully(player.getSanitisedUsername()), 3, getHeight() - 17); g.setColor(Color.ORANGE); if (context.getLocale().getCountry().equals("BE") // If the player resides in Belgium or France (i.e. uses AZERTY keyboard) - || context.getLocale().getCountry().equals("FR")) { // Displays "Press A to quit" in orange at the bottom-middle portion of the screen - g.drawString("Press A to quit", (getWidth() / 2) - - ("Press A to quit".length() * 3), getHeight() - 17); + || context.getLocale().getCountry().equals("FR")) { // Displays "Press A to quit" in orange at the bottom-middle portion of the screen + g.drawString("Press A to quit", (getWidth() / 2) - ("Press A to quit".length() * 3), getHeight() - 17); } else { // If the player resides anywhere else (i.e. uses QWERTY keyboard) g.drawString("Press Q to quit", (getWidth() / 2) // Displays "Press Q to quit" in orange at the bottom-middle portion of the screen - - ("Press Q to quit".length() * 3), getHeight() - 17); + - ("Press Q to quit".length() * 3), getHeight() - 17); } g.setColor(Color.YELLOW); g.drawString(time.getTime(), (getWidth() - 58), (getHeight() - 3)); // Displays the current time in yellow in the bottom right corner of the screen (hh:mm:ss) @@ -549,9 +536,9 @@ public void render() { } /* - * This method displays information regarding various aspects/stats of the game, dependent upon - * whether it is running in developer mode, or if the application is closing. - */ + * This method displays information regarding various aspects/stats of the game, dependent upon + * whether it is running in developer mode, or if the application is closing. + */ private void status(Graphics g, boolean TerminalMode, boolean TerminalQuit) { if (TerminalMode) { // If running in developer mode g.setColor(Color.CYAN); @@ -561,11 +548,10 @@ private void status(Graphics g, boolean TerminalMode, boolean TerminalQuit) { steps += 1; } g.drawString("Foot Steps: " + steps, 0, 40); // Display the number of "Foot Steps" (in cyan, above the previous) - g.drawString( - "NPC: " + WordUtils.capitalize(String.valueOf(isNpc())), 0, // Displays whether the NPC is on the level (in cyan, above the previous) - 55); + g.drawString("NPC: " + WordUtils.capitalize(String.valueOf(isNpc())), 0, // Displays whether the NPC is on the level (in cyan, above the previous) + 55); g.drawString("Mouse: " + getMouse().getX() + "x |" // Displays the position of the cursor (in cyan, above the previous) - + getMouse().getY() + "y", 0, 70); + + getMouse().getY() + "y", 0, 70); if (getMouse().getButton() != -1) // If a mouse button is pressed g.drawString("Button: " + getMouse().getButton(), 0, 85); // Displays the mouse button that is pressed (in cyan, above the previous) g.setColor(Color.CYAN); @@ -579,7 +565,7 @@ private void status(Graphics g, boolean TerminalMode, boolean TerminalQuit) { g.fillRect(0, 0, getWidth(), getHeight()); // Make the screen fully black g.setColor(Color.RED); g.drawString("Shutting down the Game", (getWidth() / 2) - 70, // Display "Shutting down the Game" in red in the middle of the screen - (getHeight() / 2) - 8); + (getHeight() / 2) - 8); g.dispose(); // Free up memory for graphics } From 4245fc1c6d42cf0e8b605b09011ae1720abd82f7 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Tue, 3 Jan 2023 07:55:44 +0000 Subject: [PATCH 04/12] #22 Redesign Game class and Input Handler --- build.gradle | 1 + pom.xml | 6 + src/com/redomar/game/Game.java | 272 ++++++------------ src/com/redomar/game/InputHandler.java | 152 ++++------ src/com/redomar/game/UML.ucls | 2 +- src/com/redomar/game/audio/AudioHandler.java | 65 +++-- src/com/redomar/game/entities/Entity.java | 3 + src/com/redomar/game/entities/Player.java | 57 ++-- .../game/entities/projectiles/Small.java | 24 +- src/com/redomar/game/level/LevelHandler.java | 6 +- src/com/redomar/game/lib/HashGen.java | 27 +- src/com/redomar/game/lib/Name.java | 7 +- src/com/redomar/game/menu/Menu.java | 8 +- src/com/redomar/game/net/GameClient.java | 4 +- src/com/redomar/game/net/GameServer.java | 4 +- src/com/redomar/game/objects/Inventory.java | 2 - src/com/redomar/game/script/PrintTypes.java | 8 +- .../script/{Printing.java => Printer.java} | 39 ++- .../{PrintingTest.java => PrinterTest.java} | 16 +- 19 files changed, 306 insertions(+), 397 deletions(-) rename src/com/redomar/game/script/{Printing.java => Printer.java} (62%) rename test/com/redomar/game/script/{PrintingTest.java => PrinterTest.java} (68%) diff --git a/build.gradle b/build.gradle index 34cd597..2b7bbff 100644 --- a/build.gradle +++ b/build.gradle @@ -23,6 +23,7 @@ sourceSets{ dependencies{ implementation 'org.apache.commons:commons-text:+' implementation 'org.apache.commons:commons-lang3:3.+' + implementation 'org.jetbrains:annotations:23.0.0' testImplementation 'junit:junit:4.13' implementation files('res/jars/JSplashScreen.jar') } diff --git a/pom.xml b/pom.xml index e98648c..37a91d7 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,12 @@ 3.+ runtime + + org.jetbrains + annotations + 23.0.0 + runtime + junit junit diff --git a/src/com/redomar/game/Game.java b/src/com/redomar/game/Game.java index d7fca27..82a69eb 100644 --- a/src/com/redomar/game/Game.java +++ b/src/com/redomar/game/Game.java @@ -11,7 +11,7 @@ import com.redomar.game.lib.Font; import com.redomar.game.lib.Time; import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printing; +import com.redomar.game.script.Printer; import org.apache.commons.text.WordUtils; import javax.swing.*; @@ -35,33 +35,31 @@ public class Game extends Canvas implements Runnable { private static final int WIDTH = 160; private static final int HEIGHT = (WIDTH / 3 * 2); private static final int SCALE = 3; - private static final String NAME = "Game"; // The name of the JFrame panel + private static final String NAME = "Game"; // The name of the JFrame panel + private static final Time time = new Time(); // Represents the calendar's time value, in hh:mm:ss + private static final boolean[] alternateCols = new boolean[2]; // Boolean array describing shirt and face colour + private static Game game; - private static Time time = new Time(); // Represents the calendar's time value, in hh:mm:ss // The properties of the player, npc, and fps/tps - private static int Jdata_Host; // The host of a multiplayer game (only available in earlier versions) - private static String Jdata_UserName = ""; - private static String Jdata_IP = "127.0.0.1"; - private static boolean changeLevel = false; // Determines whether the player teleports to another level - private static boolean npc = false; // Non-player character (NPC) initialized to non-existing - private static int map = 0; // Map of the level, initialized to map default map - private static int shirtCol; // The colour of the character's shirt - private static int faceCol; // The colour (ethnicity) of the character (their face) - private static boolean[] alternateCols = new boolean[2]; // Boolean array describing shirt and face colour - private static int fps; // The frame rate (frames per second), frequency at which images are displayed on the canvas - private static int tps; // The ticks (ticks per second), unit measure of time for one iteration of the game logic loop. + private static boolean changeLevel = false; // Determines whether the player teleports to another level + private static boolean npc = false; // Non-player character (NPC) initialized to non-existing + private static int map = 0; // Map of the level, initialized to map default map + private static int shirtCol; // The colour of the character's shirt + private static int faceCol; // The colour (ethnicity) of the character (their face) + private static int fps; // The frame rate (frames per second), frequency at which images are displayed on the canvas + private static int tps; // The ticks (ticks per second), unit measure of time for one iteration of the game logic loop. private static int steps; - private static boolean devMode; // Determines whether the game is in developer mode - private static boolean closingMode; // Determines whether the game will exit + private static boolean devMode; // Determines whether the game is in developer mode + private static boolean closingMode; // Determines whether the game will exit // Audio, input, and mouse handler objects private static JFrame frame; private static AudioHandler backgroundMusic; - private static boolean running = false; // Determines whether the game is currently in process - private static InputHandler input; // Accepts keyboard input and follows the appropriate actions - private static MouseHandler mouse; // Tracks mouse movement and clicks, and follows the appropriate actions - private static InputContext context; // Provides methods to control text input facilities + private static boolean running = false; // Determines whether the game is currently in process + private static InputHandler input; // Accepts keyboard input and follows the appropriate actions + private static MouseHandler mouse; // Tracks mouse movement and clicks, and follows the appropriate actions + private static InputContext context; // Provides methods to control text input facilities // Graphics private final BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); @@ -69,22 +67,18 @@ public class Game extends Canvas implements Runnable { private final int[] colours = new int[6 * 6 * 6]; // Array of 216 unique colours (6 shades of red, 6 of green, and 6 of blue) private final BufferedImage image2 = new BufferedImage(WIDTH, HEIGHT - 30, BufferedImage.TYPE_INT_RGB); private final Font font = new Font(); // Font object capable of displaying 2 fonts: Arial and Segoe UI - private final Printing print = new Printing(); + private final Printer printer = new Printer(); private int tickCount = 0; private Screen screen; - private WindowHandler window; private LevelHandler level; // Loads and renders levels along with tiles, entities, projectiles and more. //The entities of the game private Player player; private Dummy dummy; // Dummy NPC follows the player around private Vendor vendor; // Vendor NPC exhibits random movement and is only found on custom_level - private Spruce spruce; // Tree -- Spruce - private String nowPlaying; /** * @author Redomar - * @version Alpha 1.8.4 */ public Game() { context = InputContext.getInstance(); @@ -113,9 +107,10 @@ public Game() { * They will be spawned at position (100, 150) with a red shirt and caucasian face. */ public static void npcSpawn() { - if (isNpc()) { // If NPCs are allowed in the level - game.setDummy(new Dummy(game.level, "Dummy", 100, 150, 500, // Create a new dummy NPC on the current game level, with name 'Dummy' - 543)); // at position (100, 150), with a red shirt and caucasian ethnicity + // If NPCs are allowed in the level + if (isNpc()) { + // Create a new dummy NPC to the current game level + game.setDummy(new Dummy(game.level, "Dummy", 100, 150, 500, 543)); game.level.addEntity(Game.getDummy()); } } @@ -153,13 +148,6 @@ public void setLevel(LevelHandler level) { this.level = level; } - public static Time getTime() { - return Game.time; - } - - public void setTime(Time time) { - Game.time = time; - } public static Game getGame() { return game; @@ -196,21 +184,22 @@ public static int getMap() { */ public void setMap(String Map_str) { setLevel(new LevelHandler(Map_str)); - if (alternateCols[0]) { // If the first element (shirt colour) is set to True - Game.setShirtCol(240); // The player's shirt colour will be green + if (alternateCols[0]) { // If the first element (shirt colour) is set to True + Game.setShirtCol(240); // The player's shirt colour will be green } - if (!alternateCols[0]) { // If the first element (shirt colour) is set to False - Game.setShirtCol(111); // The player's shirt colour will be black + if (!alternateCols[0]) { // If the first element (shirt colour) is set to False + Game.setShirtCol(111); // The player's shirt colour will be black } - if (alternateCols[1]) { // If the last element (face colour) is set to True - Game.setFaceCol(310); // The player will be African + if (alternateCols[1]) { // If the last element (face colour) is set to True + Game.setFaceCol(310); // The player will be African } - if (!alternateCols[1]) { // If the last element (face colour) is set to False - Game.setFaceCol(543); // The player will be caucasian + if (!alternateCols[1]) { // If the last element (face colour) is set to False + Game.setFaceCol(543); // The player will be caucasian } - setPlayer(new Player(level, 100, 100, input, getJdata_UserName(), shirtCol, faceCol)); + setPlayer(new Player(level, 100, 100, input, "", shirtCol, faceCol)); level.addEntity(player); - spruce = new Spruce(level, 70, 170, 2); + // Tree -- Spruce + Spruce spruce = new Spruce(level, 70, 170, 2); level.addEntity(spruce); } @@ -234,30 +223,6 @@ public void setDummy(Dummy dummy) { this.dummy = dummy; } - public static String getJdata_IP() { - return Jdata_IP; - } - - public static void setJdata_IP(String jdata_IP) { - Jdata_IP = jdata_IP; - } - - public static int getJdata_Host() { - return Jdata_Host; - } - - public static void setJdata_Host(int jdata_Host) { - Jdata_Host = jdata_Host; - } - - public static String getJdata_UserName() { - return Jdata_UserName; - } - - public static void setJdata_UserName(String jdata_UserName) { - Jdata_UserName = jdata_UserName; - } - public static String getGameVersion() { return game_Version; } @@ -278,14 +243,6 @@ public static void setFaceCol(int faceCol) { Game.faceCol = faceCol; } - public static boolean[] getAlternateCols() { - return alternateCols; - } - - public static void setAlternateCols(boolean[] alternateCols) { // Boolean array should have a size of only two elements - Game.alternateCols = alternateCols; - } - // Sets ethnicity/face colour for the player public static void setAlternateColsR(boolean alternateCols) { Game.alternateCols[1] = alternateCols; @@ -304,14 +261,6 @@ public static void setBackgroundMusic(AudioHandler backgroundMusic) { Game.backgroundMusic = backgroundMusic; } - public static InputHandler getInput() { - return input; - } - - public void setInput(InputHandler input) { - Game.input = input; - } - public static MouseHandler getMouse() { return mouse; } @@ -349,21 +298,21 @@ public void init() { int rr = (r * 255 / 5); // Split all 256 colours into 6 shades (0, 51, 102 ... 255) int gg = (g * 255 / 5); int bb = (b * 255 / 5); - colours[index++] = rr << 16 | gg << 8 | bb; // All colour values (RGB) are placed into one 32-bit integer, populating the colour array + colours[index++] = rr << 16 | gg << 8 | bb; // All colour values (RGB) are placed into one 32-bit integer, populating the colour array } } } screen = new Screen(WIDTH, HEIGHT, new SpriteSheet("/sprite_sheet.png")); - input = new InputHandler(this); // Input begins to record key presses - setMouse(new MouseHandler(this)); // Mouse tracking and clicking is now recorded - setWindow(new WindowHandler(this)); + input = new InputHandler(this); // Input begins to record key presses + setMouse(new MouseHandler(this)); // Mouse tracking and clicking is now recorded +// setWindow(new WindowHandler(this)); try { setMap("/levels/custom_level.png"); } catch (Exception e) { - System.err.println(e); + printer.print(e.toString(), PrintTypes.ERROR); } - setMap(1); // 1 corresponds to custom_level + setMap(1); // 1 corresponds to custom_level game.setVendor(new Vendor(level, "Vendor", 215, 215, 304, 543)); level.addEntity(getVendor()); @@ -373,15 +322,16 @@ public void init() { * This method will start the game and allow the user to start playing */ public synchronized void start() { - Game.setRunning(true); // Game will run - new Thread(this, "GAME").start(); // Thread is an instance of Runnable. Whenever it is started, it will run the run() method + Game.setRunning(true); // Game will run + new Thread(this, "GAME").start(); // Thread is an instance of Runnable. Whenever it is started, it will run the run() method } /** * This method will stop the game */ public synchronized void stop() { - Game.setRunning(false); // Game will not run + Game.getBackgroundMusic().close(); + Game.setRunning(false); // Game will not run } /** @@ -390,34 +340,27 @@ public synchronized void stop() { */ public void run() { long lastTime = System.nanoTime(); - double nsPerTick = 1000000000D / 60D; // The number of nanoseconds in one tick (number of ticks limited to 60 per update) + double nsPerTick = 1000000000D / 60D; // The number of nanoseconds in one tick (number of ticks limited to 60 per update) // 1 billion nanoseconds in one second int ticks = 0; int frames = 0; - long lastTimer = System.currentTimeMillis(); // Used for updating ticks and frames once every second + long lastTimer = System.currentTimeMillis(); // Used for updating ticks and frames once every second double delta = 0; - init(); // Initialize the game environment + init(); // Initialize the game environment while (Game.isRunning()) { - long now = System.nanoTime(); // Current time (now) compared to lastTime to calculate elapsed time - delta += (now - lastTime) / nsPerTick; // Elapsed time in seconds multiplied by 60 + long now = System.nanoTime(); // Current time (now) compared to lastTime to calculate elapsed time + delta += (now - lastTime) / nsPerTick; // Elapsed time in seconds multiplied by 60 lastTime = now; boolean shouldRender = false; - while (delta >= 1) { // Once 1/60 seconds or more have passed + while (delta >= 1) { // Once 1/60 seconds or more have passed ticks++; - tick(); // Tick updates - delta -= 1; // Delta becomes less than one again and the loop will close - shouldRender = true; // Limits the frames to 60 per second - } - - try { - Thread.sleep(2); // Delays the thread by 2 milliseconds - prevents the loop from using too much CPU - } catch ( - InterruptedException e) { // If the current thread is interrupted, the interrupted status is cleared - e.printStackTrace(); + tick(); // Tick updates + delta -= 1; // Delta becomes less than one again and the loop will close + shouldRender = true; // Limits the frames to 60 per second } if (shouldRender) { @@ -425,13 +368,13 @@ public void run() { render(); } - if (System.currentTimeMillis() - lastTimer >= 1000) { // If elapsed time is greater than or equal to 1 second, update - lastTimer += 1000; // Updates in another second + if (System.currentTimeMillis() - lastTimer >= 1000) { // If elapsed time is greater than or equal to 1 second, update + lastTimer += 1000; // Updates in another second getFrame().setTitle("JavaGame - Version " + WordUtils.capitalize(game_Version).substring(1, game_Version.length())); fps = frames; tps = ticks; - frames = 0; // Reset the frames once per second - ticks = 0; // Reset the ticks once per second + frames = 0; // Reset the frames once per second + ticks = 0; // Reset the ticks once per second } } @@ -451,32 +394,23 @@ public void tick() { public void render() { BufferStrategy bs = getBufferStrategy(); if (bs == null) { - createBufferStrategy(3); // Creates a new bs with triple buffering, which reduces tearing and cross-image pixelation + createBufferStrategy(3); return; } - // Centres the player in the middle of the screen + int xOffset = (int) getPlayer().getX() - (screen.getWidth() / 2); int yOffset = (int) getPlayer().getY() - (screen.getHeight() / 2); level.renderTiles(screen, xOffset, yOffset); - - /* - * for (int x = 0; x < level.width; x++) { int colour = Colours.get(-1, - * -1, -1, 000); if (x % 10 == 0 && x != 0) { colour = Colours.get(-1, - * -1, -1, 500); } Font.render((x % 10) + "", screen, 0 + (x * 8), 0, - * colour, 1); } - */ - level.renderEntities(screen); level.renderProjectileEntities(screen); - // Copies pixel data from the screen into the game for (int y = 0; y < screen.getHeight(); y++) { for (int x = 0; x < screen.getWidth(); x++) { int colourCode = screen.getPixels()[x + y * screen.getWidth()]; - if (colourCode < 255) { // If it is a valid colour code - pixels[x + y * WIDTH] = colours[colourCode]; // Sets the corresponding pixel from the screen to the game + if (colourCode < 255) { + pixels[x + y * WIDTH] = colours[colourCode]; } } } @@ -486,52 +420,56 @@ public void render() { setChangeLevel(false); } - if (changeLevel) { // If the player is teleporting to a different level - print.print("Teleported into new world", PrintTypes.GAME); - if (getMap() == 1) { // If the player is currently on custom_level + if (changeLevel) { + printer.print("Teleported into new world", PrintTypes.GAME); + if (getMap() == 1) { setMap("/levels/water_level.png"); - if (getDummy() != null) { // Gave nullPointerException(); upon - // entering new world. + if (getDummy() != null) { + level.removeEntity(getDummy()); setNpc(false); } - level.removeEntity(getVendor()); // When teleporting away from custom_level, remove vendor NPC (always found on custom_level) + level.removeEntity(getVendor()); setMap(2); - } else if (getMap() == 2) { // If the player is currently on water_level + } else if (getMap() == 2) { setMap("/levels/custom_level.png"); level.removeEntity(getDummy()); setNpc(false); - level.addEntity(getVendor()); // Add a vendor NPC - they are always found on custom_level + level.addEntity(getVendor()); setMap(1); } changeLevel = false; } Graphics g = bs.getDrawGraphics(); - g.drawRect(0, 0, getWidth(), getHeight()); // Creates a rectangle the same size as the screen + g.drawRect(0, 0, getWidth(), getHeight()); g.drawImage(image, 0, 0, getWidth(), getHeight() - 30, null); status(g, isDevMode(), isClosing()); - // Font.render("Hi", screen, 0, 0, Colours.get(-1, -1, -1, 555), 1); g.drawImage(image2, 0, getHeight() - 30, getWidth(), getHeight(), null); g.setColor(Color.WHITE); g.setFont(font.getSegoe()); - g.drawString("Welcome " + WordUtils.capitalizeFully(player.getSanitisedUsername()), 3, getHeight() - 17); + g.drawString("Welcome " + WordUtils.capitalize(player.getName()), 3, getHeight() - 17); g.setColor(Color.ORANGE); - if (context.getLocale().getCountry().equals("BE") // If the player resides in Belgium or France (i.e. uses AZERTY keyboard) - || context.getLocale().getCountry().equals("FR")) { // Displays "Press A to quit" in orange at the bottom-middle portion of the screen + if (context.getLocale().getCountry().equals("BE") || context.getLocale().getCountry().equals("FR")) { g.drawString("Press A to quit", (getWidth() / 2) - ("Press A to quit".length() * 3), getHeight() - 17); - } else { // If the player resides anywhere else (i.e. uses QWERTY keyboard) - g.drawString("Press Q to quit", (getWidth() / 2) // Displays "Press Q to quit" in orange at the bottom-middle portion of the screen - - ("Press Q to quit".length() * 3), getHeight() - 17); + } else { + g.drawString("Press Q to quit", (getWidth() / 2) - ("Press Q to quit".length() * 3), getHeight() - 17); } + g.setColor(Color.YELLOW); - g.drawString(time.getTime(), (getWidth() - 58), (getHeight() - 3)); // Displays the current time in yellow in the bottom right corner of the screen (hh:mm:ss) + g.drawString(time.getTime(), (getWidth() - 63), (getHeight() - 3)); + if (devMode) { + g.setColor(Color.CYAN); + g.drawString("Debug Mode Enabled", (getWidth() - 153), (getHeight() - 17)); + } g.setColor(Color.GREEN); - if (backgroundMusic.getActive()) { // If music is turned on - g.drawString("MUSIC is ON ", 3, getHeight() - 3); // Displays "MUSIC IS ON" in green in the bottom left corner of the screen. + + if (backgroundMusic.getActive()) { + g.drawString("MUSIC is ON ", 3, getHeight() - 3); } - g.dispose(); // Frees up memory and resources for graphics + + g.dispose(); bs.show(); } @@ -540,20 +478,17 @@ public void render() { * whether it is running in developer mode, or if the application is closing. */ private void status(Graphics g, boolean TerminalMode, boolean TerminalQuit) { - if (TerminalMode) { // If running in developer mode + if (TerminalMode) { g.setColor(Color.CYAN); - g.drawString("JavaGame Stats", 0, 10); // Display "JavaGame Stats" in cyan at the bottom left of the screen - g.drawString("FPS/TPS: " + fps + "/" + tps, 0, 25); // Display the FPS and TPS in cyan directly above "JavaGame Stats" + g.drawString("JavaGame Stats", 0, 10); + g.drawString("FPS/TPS: " + fps + "/" + tps, 0, 25); if ((player.getNumSteps() & 15) == 15) { steps += 1; } - g.drawString("Foot Steps: " + steps, 0, 40); // Display the number of "Foot Steps" (in cyan, above the previous) - g.drawString("NPC: " + WordUtils.capitalize(String.valueOf(isNpc())), 0, // Displays whether the NPC is on the level (in cyan, above the previous) - 55); - g.drawString("Mouse: " + getMouse().getX() + "x |" // Displays the position of the cursor (in cyan, above the previous) - + getMouse().getY() + "y", 0, 70); - if (getMouse().getButton() != -1) // If a mouse button is pressed - g.drawString("Button: " + getMouse().getButton(), 0, 85); // Displays the mouse button that is pressed (in cyan, above the previous) + g.drawString("Foot Steps: " + steps, 0, 40); + g.drawString("NPC: " + WordUtils.capitalize(String.valueOf(isNpc())), 0, 55); + g.drawString("Mouse: " + getMouse().getX() + "x |" + getMouse().getY() + "y", 0, 70); + if (getMouse().getButton() != -1) g.drawString("Button: " + getMouse().getButton(), 0, 85); g.setColor(Color.CYAN); g.fillRect(getMouse().getX() - 12, getMouse().getY() - 12, 24, 24); } @@ -562,27 +497,10 @@ private void status(Graphics g, boolean TerminalMode, boolean TerminalQuit) { return; } g.setColor(Color.BLACK); - g.fillRect(0, 0, getWidth(), getHeight()); // Make the screen fully black + g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(Color.RED); - g.drawString("Shutting down the Game", (getWidth() / 2) - 70, // Display "Shutting down the Game" in red in the middle of the screen - (getHeight() / 2) - 8); - g.dispose(); // Free up memory for graphics - } - - public WindowHandler getWindow() { - return window; - } - - public void setWindow(WindowHandler window) { - this.window = window; - } - - public String getNowPlaying() { - return nowPlaying; - } - - public void setNowPlaying(String nowPlaying) { - this.nowPlaying = nowPlaying; + g.drawString("Shutting down the Game", (getWidth() / 2) - 70, (getHeight() / 2) - 8); + g.dispose(); } public int getTickCount() { diff --git a/src/com/redomar/game/InputHandler.java b/src/com/redomar/game/InputHandler.java index 4d0676a..4f081bf 100644 --- a/src/com/redomar/game/InputHandler.java +++ b/src/com/redomar/game/InputHandler.java @@ -1,31 +1,29 @@ package com.redomar.game; import com.redomar.game.lib.SleepThread; -import com.redomar.game.script.PopUp; import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printing; +import com.redomar.game.script.Printer; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.im.InputContext; +import java.util.HashMap; +import java.util.Map; public class InputHandler implements KeyListener { - private final boolean isAzertyCountry; - private final Printing print = new Printing(); - private final PopUp popup = new PopUp(); + private final boolean frenchKeyboardLayout; + private final Printer inputPrinter = new Printer(PrintTypes.INPUT); private final Key UP_KEY = new Key(); private final Key DOWN_KEY = new Key(); private final Key LEFT_KEY = new Key(); private final Key RIGHT_KEY = new Key(); - private boolean ignoreInput = false; - private boolean toggleMusic = false; + private boolean musicPlaying = false; + public InputHandler(Game game) { InputContext context = InputContext.getInstance(); - // Important to know whether the keyboard is in Azerty or Qwerty. - // Azerty countries used QZSD instead of WASD keys. - isAzertyCountry = context.getLocale().getCountry().equals("BE") || context.getLocale().getCountry().equals("FR"); + frenchKeyboardLayout = context.getLocale().getCountry().equals("BE") || context.getLocale().getCountry().equals("FR"); game.addKeyListener(this); } @@ -34,61 +32,62 @@ public void keyPressed(KeyEvent e) { } public void keyReleased(KeyEvent e) { - toggleKey(e.getKeyCode(), false); - } - - public void keyTyped(KeyEvent e) { - - } - - private void toggleKey(int keyCode, boolean isPressed) { - if (!isIgnoreInput()) { - if (keyCode == KeyEvent.VK_Z && isAzertyCountry || keyCode == KeyEvent.VK_W && !isAzertyCountry || keyCode == KeyEvent.VK_UP) { - UP_KEY.toggle(isPressed); - } - - if (keyCode == KeyEvent.VK_Q && isAzertyCountry || keyCode == KeyEvent.VK_A && !isAzertyCountry || keyCode == KeyEvent.VK_LEFT) { - LEFT_KEY.toggle(isPressed); - } - - if (keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_DOWN) { - DOWN_KEY.toggle(isPressed); - } - - if (keyCode == KeyEvent.VK_D || keyCode == KeyEvent.VK_RIGHT) { - RIGHT_KEY.toggle(isPressed); + int keyCode = e.getKeyCode(); + toggleKey(keyCode, false); + if (keyCode == KeyEvent.VK_BACK_QUOTE) { + if (!Game.isClosing()) { + Game.setDevMode(!Game.isDevMode()); + new Thread(new SleepThread()); + inputPrinter.print(String.format("Debug Mode %s", Game.isDevMode() ? "Enabled" : "Disabled")); } } - if (isIgnoreInput()) { - UP_KEY.toggle(false); - DOWN_KEY.toggle(false); - LEFT_KEY.toggle(false); - RIGHT_KEY.toggle(false); - } if (keyCode == KeyEvent.VK_M) { - if (!toggleMusic) { + if (!musicPlaying) { Game.getBackgroundMusic().play(); - print.print("Playing Music", PrintTypes.MUSIC); - toggleMusic = true; + musicPlaying = true; + } else { + Game.getBackgroundMusic().stop(); + musicPlaying = false; + } + } + + if (keyCode == KeyEvent.VK_N) { + if (!Game.isNpc()) { + Game.setNpc(true); + Game.npcSpawn(); + inputPrinter.print("Dummy has been spawned", PrintTypes.GAME); } } + } - if (keyCode == KeyEvent.VK_COMMA) { - Game.getBackgroundMusic().stop(); - if (toggleMusic) print.print("Stopping Music", PrintTypes.MUSIC); - toggleMusic = false; + public void keyTyped(KeyEvent e) { + + } + + private void toggleKey(int keyCode, boolean isPressed) { + Map keyCodeActions = new HashMap<>(); + + keyCodeActions.put(KeyEvent.VK_S, () -> DOWN_KEY.toggle(isPressed)); + keyCodeActions.put(KeyEvent.VK_D, () -> RIGHT_KEY.toggle(isPressed)); + keyCodeActions.put(KeyEvent.VK_UP, () -> UP_KEY.toggle(isPressed)); + keyCodeActions.put(KeyEvent.VK_LEFT, () -> LEFT_KEY.toggle(isPressed)); + keyCodeActions.put(KeyEvent.VK_DOWN, () -> DOWN_KEY.toggle(isPressed)); + keyCodeActions.put(KeyEvent.VK_RIGHT, () -> RIGHT_KEY.toggle(isPressed)); + + if (frenchKeyboardLayout) { + keyCodeActions.put(KeyEvent.VK_Q, () -> LEFT_KEY.toggle(isPressed)); + keyCodeActions.put(KeyEvent.VK_Z, () -> UP_KEY.toggle(isPressed)); + keyCodeActions.put(KeyEvent.VK_A, this::quitGame); + } else { + keyCodeActions.put(KeyEvent.VK_A, () -> LEFT_KEY.toggle(isPressed)); + keyCodeActions.put(KeyEvent.VK_W, () -> UP_KEY.toggle(isPressed)); + keyCodeActions.put(KeyEvent.VK_Q, this::quitGame); } + if (keyCodeActions.containsKey(keyCode)) keyCodeActions.get(keyCode).run(); - if (keyCode == KeyEvent.VK_W && isAzertyCountry || keyCode == KeyEvent.VK_Z && !isAzertyCountry) { - // if (map == 0){ - // Game.getGame().setMap("/levels/water_level.png"); - // map++; - // } else{ - // Game.getGame().setMap("/levels/custom_level.png"); - // map--; - // } + if (keyCode == KeyEvent.VK_W && frenchKeyboardLayout || keyCode == KeyEvent.VK_Z && !frenchKeyboardLayout) { if (Game.getMap() == 2) { if (Game.isNpc()) { Game.setNpc(false); @@ -96,58 +95,31 @@ private void toggleKey(int keyCode, boolean isPressed) { Game.setChangeLevel(true); } } - if (keyCode == KeyEvent.VK_N) { - if (Game.getPlayer().isMoving()) { - setIgnoreInput(true); - int n = popup.Warn("Stop moving before spawning dummy AI"); - if (n == 0) { - setIgnoreInput(false); - } - return; - } - if (!Game.isNpc()) { - Game.setNpc(true); - Game.npcSpawn(); - print.print("Dummy has been spawned", PrintTypes.GAME); - } - } + if (keyCode == KeyEvent.VK_K) { if (Game.isNpc()) { Game.setNpc(false); Game.npcKill(); - print.print("Dummy has been removed", PrintTypes.GAME); + inputPrinter.print("Dummy has been removed", PrintTypes.GAME); } } - if (keyCode == KeyEvent.VK_A && isAzertyCountry || keyCode == KeyEvent.VK_Q && !isAzertyCountry) - this.quitGame(); - - if (keyCode == KeyEvent.VK_BACK_QUOTE) { - if (!Game.isClosing() && !Game.isDevMode()) { - Game.setDevMode(true); - new Thread(new SleepThread()); - } - } } private void quitGame() { Game.setClosing(true); - if (!print.removeLog()) System.err.println("Could not delete Log file"); + if (!inputPrinter.removeLog()) System.err.println("Could not delete Log file"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } - Game.getLevel().removeEntity(Game.getPlayer().getSanitisedUsername()); - Game.setRunning(false); + Game.getLevel().removeEntity(Game.getPlayer().getName()); + Game.getGame().stop(); Game.getFrame().dispose(); System.exit(0); } - public void untoggle(boolean toggle) { - this.ignoreInput = toggle; - } - public Key getUP_KEY() { return UP_KEY; } @@ -164,14 +136,6 @@ public Key getRIGHT_KEY() { return RIGHT_KEY; } - public boolean isIgnoreInput() { - return ignoreInput; - } - - private void setIgnoreInput(boolean ignoreInput) { - this.ignoreInput = ignoreInput; - } - public static class Key { private int numTimesPressed = 0; private boolean pressed = false; diff --git a/src/com/redomar/game/UML.ucls b/src/com/redomar/game/UML.ucls index 6c9da34..6e054bc 100644 --- a/src/com/redomar/game/UML.ucls +++ b/src/com/redomar/game/UML.ucls @@ -442,7 +442,7 @@ - range) remove(); + this.distance = Math.sqrt(Math.abs((xOrigin - x) * (xOrigin - x) + (yOrigin - y) * (yOrigin - y))); + if (this.distance > range) remove(); } public void render(Screen screen) { - screen.render((int)x,(int)y, 8 * 32, Colours.get(-1, 522, 540, 555), 0x00, 1); + screen.render((int) x, (int) y, 8 * 32, Colours.get(-1, 522, 540, 555), 0x00, 1); } } diff --git a/src/com/redomar/game/level/LevelHandler.java b/src/com/redomar/game/level/LevelHandler.java index 5b4d1c4..5dfbae8 100644 --- a/src/com/redomar/game/level/LevelHandler.java +++ b/src/com/redomar/game/level/LevelHandler.java @@ -8,7 +8,7 @@ import com.redomar.game.lib.utils.Vector2i; import com.redomar.game.scenes.Scene; import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printing; +import com.redomar.game.script.Printer; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; @@ -29,7 +29,7 @@ public class LevelHandler { private List entities_p; private String imagePath; private BufferedImage image; - private Printing print; + private Printer print; private Comparator nodeSorter; @@ -45,7 +45,7 @@ public LevelHandler(String imagePath) { this.generateLevel(); } - print = new Printing(); + print = new Printer(); entities = new ArrayList(); entities_p = new ArrayList(); nodeSorter = new Comparator() { diff --git a/src/com/redomar/game/lib/HashGen.java b/src/com/redomar/game/lib/HashGen.java index 3c36248..3044a40 100644 --- a/src/com/redomar/game/lib/HashGen.java +++ b/src/com/redomar/game/lib/HashGen.java @@ -11,18 +11,19 @@ public class HashGen { /** * Use for generating a hex Hash. Requires two parameters; + * * @param showPrefix to show 0x prefix. - * @param length Length of hash. + * @param length Length of hash. */ - public HashGen(boolean showPrefix, int length){ + public HashGen(boolean showPrefix, int length) { setPrefix(showPrefix); setHexLength(length); init(); } //Remove null char or prepend 0x - private void init(){ - if(prefix){ + private void init() { + if (prefix) { hexHash = "0x"; } else { hexHash = ""; @@ -31,29 +32,29 @@ private void init(){ /** * Retrieve hash + * * @return String containing hash */ - public String getHash(){ + public String getHash() { setHash(hexLength); return hexHash; } - private void setHash(int hexLength){ + private void setHash(int hexLength) { String hex; - for (int i = 0; i < hexLength; i++){ + for (int i = 0; i < hexLength; i++) { hex = Integer.toHexString(randNumGen()); hex = StringUtils.capitalize(hex); - hexHash = hexHash + hex; + hexHash = String.format("%s%s", hexHash, hex); } previousHash = hexHash; } - private int randNumGen(){ - int rand = (int)(Math.random() * 16); - return rand; + private int randNumGen() { + return (int) (Math.random() * 16); } //getters and setters @@ -66,8 +67,8 @@ public void setHexLength(int hexLength) { this.hexLength = hexLength; } - public String getPreviousHash(){ - if(previousHash == null) return null; + public String getPreviousHash() { + if (previousHash == null) return null; return previousHash; } } diff --git a/src/com/redomar/game/lib/Name.java b/src/com/redomar/game/lib/Name.java index a216932..7133819 100644 --- a/src/com/redomar/game/lib/Name.java +++ b/src/com/redomar/game/lib/Name.java @@ -2,19 +2,20 @@ import java.util.Random; +@Deprecated public class Name { - private Random rand = new Random(); private static int name_ID; public Name() { + Random rand = new Random(); setRand(rand); } + @Deprecated public String setName(String name) { - String finalName = name + name_ID; - return finalName; + return name + name_ID; } public static void setRand(Random rand) { diff --git a/src/com/redomar/game/menu/Menu.java b/src/com/redomar/game/menu/Menu.java index ec68f05..15b3283 100644 --- a/src/com/redomar/game/menu/Menu.java +++ b/src/com/redomar/game/menu/Menu.java @@ -5,7 +5,6 @@ import com.redomar.game.lib.Font; import com.redomar.game.lib.Mouse; import com.thehowtotutorial.splashscreen.JSplash; -import org.apache.commons.text.WordUtils; import javax.swing.*; import java.awt.*; @@ -45,12 +44,12 @@ public static void play() { splash.splashOn(); // Background tasks - Game.setBackgroundMusic(new AudioHandler("/music/Towards The End.wav")); + Game.setBackgroundMusic(new AudioHandler("/music/Towards The End.wav", true)); Game.getBackgroundMusic().setVolume(VOLUME_IN_DB); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); Game.setAlternateColsR(true); Game.setAlternateColsS(true); - splash.setProgress(100, "Connecting as " + Game.getJdata_UserName()); + splash.setProgress(100, "Starting Game..."); Thread.sleep(650); // Frame Init @@ -157,8 +156,7 @@ private void render() { g.fillRect(0, 0, WIDTH * 3, HEIGHT * 3); g.setColor(new Color(0xFFFF9900)); g.setFont(font.getArial()); - String name = (Game.getJdata_UserName().length() >= 1) ? WordUtils.capitalizeFully(Game.getJdata_UserName()) : "Player"; - g.drawString("Welcome to JavaGame " + name, 35, 30); + g.drawString("Welcome to JavaGame", 35, 30); g.drawLine(0, HEIGHT * 3, 0, 0); g.drawLine(0, 0, (WIDTH * 3), 0); g.drawLine((WIDTH * 3), 0, (WIDTH * 3), (HEIGHT * 3)); diff --git a/src/com/redomar/game/net/GameClient.java b/src/com/redomar/game/net/GameClient.java index eccec0e..62225bd 100644 --- a/src/com/redomar/game/net/GameClient.java +++ b/src/com/redomar/game/net/GameClient.java @@ -8,7 +8,7 @@ import com.redomar.game.net.packets.Packet01Disconnect; import com.redomar.game.net.packets.Packet02Move; import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printing; +import com.redomar.game.script.Printer; import java.io.IOException; import java.net.*; @@ -16,7 +16,7 @@ @Deprecated public class GameClient extends Thread { - private final Printing print = new Printing(); + private final Printer print = new Printer(); private InetAddress ipAddress; private DatagramSocket socket; private Game game; diff --git a/src/com/redomar/game/net/GameServer.java b/src/com/redomar/game/net/GameServer.java index f8bb8e0..5091bb4 100644 --- a/src/com/redomar/game/net/GameServer.java +++ b/src/com/redomar/game/net/GameServer.java @@ -8,7 +8,7 @@ import com.redomar.game.net.packets.Packet01Disconnect; import com.redomar.game.net.packets.Packet02Move; import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printing; +import com.redomar.game.script.Printer; import java.io.IOException; import java.net.DatagramPacket; @@ -22,7 +22,7 @@ public class GameServer extends Thread { private final List connectedPlayers = new ArrayList<>(); - private final Printing print = new Printing(); + private final Printer print = new Printer(); private DatagramSocket socket; private Game game; diff --git a/src/com/redomar/game/objects/Inventory.java b/src/com/redomar/game/objects/Inventory.java index ad181a5..de45baa 100644 --- a/src/com/redomar/game/objects/Inventory.java +++ b/src/com/redomar/game/objects/Inventory.java @@ -24,13 +24,11 @@ public static void activate() { + inside()); open = true; Game.getPlayer().setMoving(false); - Game.getInput().untoggle(true); inv_window.start(); } } else { if (closing) { Game.getPlayer().setMoving(true); - Game.getInput().untoggle(false); inv_window.stop(); inv_window.getFrame().setVisible(false); inv_window.getFrame().stopFrame(); diff --git a/src/com/redomar/game/script/PrintTypes.java b/src/com/redomar/game/script/PrintTypes.java index 0a366a5..e28753a 100644 --- a/src/com/redomar/game/script/PrintTypes.java +++ b/src/com/redomar/game/script/PrintTypes.java @@ -3,9 +3,11 @@ public enum PrintTypes { GAME, LEVEL, + ENTITY, + INPUT, MUSIC, - ERROR, - TEST, NETWORK, - SERVER + SERVER, + ERROR, + TEST } diff --git a/src/com/redomar/game/script/Printing.java b/src/com/redomar/game/script/Printer.java similarity index 62% rename from src/com/redomar/game/script/Printing.java rename to src/com/redomar/game/script/Printer.java index 8b54977..7333bc3 100644 --- a/src/com/redomar/game/script/Printing.java +++ b/src/com/redomar/game/script/Printer.java @@ -5,15 +5,20 @@ import java.io.File; import java.util.Arrays; -public class Printing { +public class Printer { private static int lineNumber = 0; private final Time time = new Time(); private PrintTypes type; private String message; + private boolean evalTypeAsException = false; - public Printing() { + public Printer() { + this.type = PrintTypes.GAME; + } + public Printer(PrintTypes type) { + this.type = type; } public void print(String message, PrintTypes type) { @@ -22,6 +27,11 @@ public void print(String message, PrintTypes type) { printOut(); } + public void print(String message) { + this.message = message; + printOut(); + } + private void printOut() { String msgTime = "[" + time.getTime() + "]"; String msgType = "[" + type.toString() + "]"; @@ -45,8 +55,9 @@ private void printOut() { String formattedStringForConsole = String.format("%s%s %s%n", msgType, msgTime, message); - if (type.equals(PrintTypes.ERROR)) { + if (type.equals(PrintTypes.ERROR) || evalTypeAsException) { System.err.printf(formattedStringForConsole); + evalTypeAsException = false; } else { System.out.printf(formattedStringForConsole); } @@ -67,4 +78,26 @@ public boolean removeLog() { public String getMessage() { return message; } + + /** + * Error that keeps the current {@link PrintTypes PrintType } instead of using {@link PrintTypes PrintTypes.ERROR} + * + * @return Printer + */ + public Printer cast() { + this.evalTypeAsException = true; + return this; + } + + /** + * Print exception as message, cast to keep {@link PrintTypes PrintType } + * + * @param exceptionMessage message to print + * @return Printer + */ + public Printer exception(String exceptionMessage) { + if (!this.evalTypeAsException) this.type = PrintTypes.ERROR; + print(exceptionMessage); + return this; + } } diff --git a/test/com/redomar/game/script/PrintingTest.java b/test/com/redomar/game/script/PrinterTest.java similarity index 68% rename from test/com/redomar/game/script/PrintingTest.java rename to test/com/redomar/game/script/PrinterTest.java index 4b89ce5..09a2deb 100644 --- a/test/com/redomar/game/script/PrintingTest.java +++ b/test/com/redomar/game/script/PrinterTest.java @@ -12,18 +12,18 @@ * Created by Mohamed on 28/08/2016. * This file tests the com.redomar.game.script.Printing class */ -public class PrintingTest { +public class PrinterTest { - private Printing printing; + private Printer printer; @Before public void setUp() { - printing = new Printing(); + printer = new Printer(); } @Test public void printToFileWorks() { - printing.print("TESTING STRING", PrintTypes.TEST); + printer.print("TESTING STRING", PrintTypes.TEST); File file = new File(".PrintType-TEST.txt"); assertTrue(file.exists()); assertTrue(file.delete()); @@ -31,18 +31,18 @@ public void printToFileWorks() { @Test public void getMessageIsNull() { - assertNull(printing.getMessage()); + assertNull(printer.getMessage()); } @Test public void messageShouldBeNullAfterPrinting() { - printing.print("Not Null", PrintTypes.TEST); - assertNotNull(printing.getMessage()); + printer.print("Not Null", PrintTypes.TEST); + assertNotNull(printer.getMessage()); } @After public void cleanUp() { - printing = null; + printer = null; } } \ No newline at end of file From cc0858ac66482bb174aacb9ac37cf8897e339ef5 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Wed, 4 Jan 2023 23:41:15 +0000 Subject: [PATCH 05/12] #22 Added Either Monad --- src/com/redomar/game/lib/Either.java | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/com/redomar/game/lib/Either.java diff --git a/src/com/redomar/game/lib/Either.java b/src/com/redomar/game/lib/Either.java new file mode 100644 index 0000000..de2c608 --- /dev/null +++ b/src/com/redomar/game/lib/Either.java @@ -0,0 +1,38 @@ +package com.redomar.game.lib; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public class Either { + private final Optional left; + private final Optional right; + + private Either(final Optional left, final Optional right) { + this.left = left; + this.right = right; + } + + @Contract("_ -> new") + static @NotNull Either left(final L value) { + return new Either<>(Optional.of(value), Optional.empty()); + } + + @Contract("_ -> new") + static @NotNull Either right(final R value) { + return new Either<>(Optional.empty(), Optional.of(value)); + } + + boolean isLeft() { + return left.isPresent(); + } + + L getLeft() { + return left.get(); + } + + R getRight() { + return right.get(); + } +} From 36deeba0bf489aae69d5a42e7683cd77b151276b Mon Sep 17 00:00:00 2001 From: Mohamed Date: Thu, 5 Jan 2023 06:46:52 +0000 Subject: [PATCH 06/12] #22 Sophisticated shuffle Fixed input issues Reworked fields in Entities, Mobs, etc. --- src/com/redomar/game/Game.java | 17 +- src/com/redomar/game/InputHandler.java | 166 --- src/com/redomar/game/UML.ucls | 1119 ----------------- src/com/redomar/game/audio/AudioHandler.java | 6 +- src/com/redomar/game/entities/Dummy.java | 104 +- src/com/redomar/game/entities/Entity.java | 23 +- src/com/redomar/game/entities/Mob.java | 244 ++-- src/com/redomar/game/entities/Player.java | 105 +- src/com/redomar/game/entities/PlayerMP.java | 2 +- src/com/redomar/game/entities/Vendor.java | 121 +- src/com/redomar/game/entities/efx/Swim.java | 59 +- .../redomar/game/entities/efx/WaterType.java | 5 + .../game/entities/projectiles/Projectile.java | 18 +- .../game/entities/projectiles/Small.java | 2 + src/com/redomar/game/entities/trees/Tree.java | 14 +- src/com/redomar/game/event/InputHandler.java | 174 +++ src/com/redomar/game/event/KeyHandler.java | 35 + .../redomar/game/{lib => event}/Mouse.java | 20 +- .../game/{ => event}/MouseHandler.java | 8 +- .../game/{ => event}/WindowHandler.java | 10 +- src/com/redomar/game/level/LevelHandler.java | 145 +-- src/com/redomar/game/lib/Either.java | 83 +- src/com/redomar/game/lib/Keys.java | 73 -- .../game/{script => log}/PrintToLog.java | 8 +- src/com/redomar/game/log/PrintTypes.java | 5 + .../redomar/game/{script => log}/Printer.java | 2 +- src/com/redomar/game/{ => menu}/HelpMenu.java | 2 +- src/com/redomar/game/menu/Menu.java | 2 +- src/com/redomar/game/menu/MenuInput.java | 1 - src/com/redomar/game/menu/PopUp.java | 22 + src/com/redomar/game/net/GameClient.java | 24 +- src/com/redomar/game/net/GameServer.java | 4 +- src/com/redomar/game/script/PopUp.java | 26 - src/com/redomar/game/script/PrintTypes.java | 13 - test/com/redomar/game/log/PopUpTest.java | 23 + .../game/{script => log}/PrintToLogTest.java | 5 +- .../game/{script => log}/PrinterTest.java | 2 +- test/com/redomar/game/script/PopUpTest.java | 22 - 38 files changed, 688 insertions(+), 2026 deletions(-) delete mode 100644 src/com/redomar/game/InputHandler.java delete mode 100644 src/com/redomar/game/UML.ucls create mode 100644 src/com/redomar/game/entities/efx/WaterType.java create mode 100644 src/com/redomar/game/event/InputHandler.java create mode 100644 src/com/redomar/game/event/KeyHandler.java rename src/com/redomar/game/{lib => event}/Mouse.java (81%) rename src/com/redomar/game/{ => event}/MouseHandler.java (89%) rename src/com/redomar/game/{ => event}/WindowHandler.java (86%) delete mode 100644 src/com/redomar/game/lib/Keys.java rename src/com/redomar/game/{script => log}/PrintToLog.java (82%) create mode 100644 src/com/redomar/game/log/PrintTypes.java rename src/com/redomar/game/{script => log}/Printer.java (98%) rename src/com/redomar/game/{ => menu}/HelpMenu.java (98%) create mode 100644 src/com/redomar/game/menu/PopUp.java delete mode 100644 src/com/redomar/game/script/PopUp.java delete mode 100644 src/com/redomar/game/script/PrintTypes.java create mode 100644 test/com/redomar/game/log/PopUpTest.java rename test/com/redomar/game/{script => log}/PrintToLogTest.java (86%) rename test/com/redomar/game/{script => log}/PrinterTest.java (96%) delete mode 100644 test/com/redomar/game/script/PopUpTest.java diff --git a/src/com/redomar/game/Game.java b/src/com/redomar/game/Game.java index 82a69eb..20b3994 100644 --- a/src/com/redomar/game/Game.java +++ b/src/com/redomar/game/Game.java @@ -5,13 +5,16 @@ import com.redomar.game.entities.Player; import com.redomar.game.entities.Vendor; import com.redomar.game.entities.trees.Spruce; +import com.redomar.game.event.InputHandler; +import com.redomar.game.event.MouseHandler; import com.redomar.game.gfx.Screen; import com.redomar.game.gfx.SpriteSheet; import com.redomar.game.level.LevelHandler; +import com.redomar.game.lib.Either; import com.redomar.game.lib.Font; import com.redomar.game.lib.Time; -import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printer; +import com.redomar.game.log.PrintTypes; +import com.redomar.game.log.Printer; import org.apache.commons.text.WordUtils; import javax.swing.*; @@ -68,10 +71,10 @@ public class Game extends Canvas implements Runnable { private final BufferedImage image2 = new BufferedImage(WIDTH, HEIGHT - 30, BufferedImage.TYPE_INT_RGB); private final Font font = new Font(); // Font object capable of displaying 2 fonts: Arial and Segoe UI private final Printer printer = new Printer(); + boolean musicPlaying = false; private int tickCount = 0; private Screen screen; private LevelHandler level; // Loads and renders levels along with tiles, entities, projectiles and more. - //The entities of the game private Player player; private Dummy dummy; // Dummy NPC follows the player around @@ -385,9 +388,17 @@ public void run() { */ public void tick() { setTickCount(getTickCount() + 1); + Either musicKeyAction = input.toggleActionWithCheckedRunnable(input.getM_KEY(), musicPlaying, () -> Game.getBackgroundMusic().play(), () -> Game.getBackgroundMusic().stop()); + musicKeyAction.either(exception -> { + printer.cast().print("Failed to play music", PrintTypes.MUSIC); + printer.exception(exception.toString()); + musicPlaying = false; + }, isPlaying -> musicPlaying = isPlaying); + level.tick(); } + /** * This method displays the current state of the game. */ diff --git a/src/com/redomar/game/InputHandler.java b/src/com/redomar/game/InputHandler.java deleted file mode 100644 index 4f081bf..0000000 --- a/src/com/redomar/game/InputHandler.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.redomar.game; - -import com.redomar.game.lib.SleepThread; -import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printer; - -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.im.InputContext; -import java.util.HashMap; -import java.util.Map; - -public class InputHandler implements KeyListener { - - private final boolean frenchKeyboardLayout; - private final Printer inputPrinter = new Printer(PrintTypes.INPUT); - private final Key UP_KEY = new Key(); - private final Key DOWN_KEY = new Key(); - private final Key LEFT_KEY = new Key(); - private final Key RIGHT_KEY = new Key(); - private boolean musicPlaying = false; - - - public InputHandler(Game game) { - InputContext context = InputContext.getInstance(); - frenchKeyboardLayout = context.getLocale().getCountry().equals("BE") || context.getLocale().getCountry().equals("FR"); - game.addKeyListener(this); - } - - public void keyPressed(KeyEvent e) { - toggleKey(e.getKeyCode(), true); - } - - public void keyReleased(KeyEvent e) { - int keyCode = e.getKeyCode(); - toggleKey(keyCode, false); - if (keyCode == KeyEvent.VK_BACK_QUOTE) { - if (!Game.isClosing()) { - Game.setDevMode(!Game.isDevMode()); - new Thread(new SleepThread()); - inputPrinter.print(String.format("Debug Mode %s", Game.isDevMode() ? "Enabled" : "Disabled")); - } - } - - if (keyCode == KeyEvent.VK_M) { - if (!musicPlaying) { - Game.getBackgroundMusic().play(); - musicPlaying = true; - } else { - Game.getBackgroundMusic().stop(); - musicPlaying = false; - } - } - - if (keyCode == KeyEvent.VK_N) { - if (!Game.isNpc()) { - Game.setNpc(true); - Game.npcSpawn(); - inputPrinter.print("Dummy has been spawned", PrintTypes.GAME); - } - } - } - - public void keyTyped(KeyEvent e) { - - } - - private void toggleKey(int keyCode, boolean isPressed) { - Map keyCodeActions = new HashMap<>(); - - keyCodeActions.put(KeyEvent.VK_S, () -> DOWN_KEY.toggle(isPressed)); - keyCodeActions.put(KeyEvent.VK_D, () -> RIGHT_KEY.toggle(isPressed)); - keyCodeActions.put(KeyEvent.VK_UP, () -> UP_KEY.toggle(isPressed)); - keyCodeActions.put(KeyEvent.VK_LEFT, () -> LEFT_KEY.toggle(isPressed)); - keyCodeActions.put(KeyEvent.VK_DOWN, () -> DOWN_KEY.toggle(isPressed)); - keyCodeActions.put(KeyEvent.VK_RIGHT, () -> RIGHT_KEY.toggle(isPressed)); - - if (frenchKeyboardLayout) { - keyCodeActions.put(KeyEvent.VK_Q, () -> LEFT_KEY.toggle(isPressed)); - keyCodeActions.put(KeyEvent.VK_Z, () -> UP_KEY.toggle(isPressed)); - keyCodeActions.put(KeyEvent.VK_A, this::quitGame); - } else { - keyCodeActions.put(KeyEvent.VK_A, () -> LEFT_KEY.toggle(isPressed)); - keyCodeActions.put(KeyEvent.VK_W, () -> UP_KEY.toggle(isPressed)); - keyCodeActions.put(KeyEvent.VK_Q, this::quitGame); - } - - if (keyCodeActions.containsKey(keyCode)) keyCodeActions.get(keyCode).run(); - - if (keyCode == KeyEvent.VK_W && frenchKeyboardLayout || keyCode == KeyEvent.VK_Z && !frenchKeyboardLayout) { - if (Game.getMap() == 2) { - if (Game.isNpc()) { - Game.setNpc(false); - } - Game.setChangeLevel(true); - } - } - - if (keyCode == KeyEvent.VK_K) { - if (Game.isNpc()) { - Game.setNpc(false); - Game.npcKill(); - inputPrinter.print("Dummy has been removed", PrintTypes.GAME); - } - } - - } - - private void quitGame() { - Game.setClosing(true); - if (!inputPrinter.removeLog()) System.err.println("Could not delete Log file"); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Game.getLevel().removeEntity(Game.getPlayer().getName()); - Game.getGame().stop(); - Game.getFrame().dispose(); - System.exit(0); - } - - public Key getUP_KEY() { - return UP_KEY; - } - - public Key getDOWN_KEY() { - return DOWN_KEY; - } - - public Key getLEFT_KEY() { - return LEFT_KEY; - } - - public Key getRIGHT_KEY() { - return RIGHT_KEY; - } - - public static class Key { - private int numTimesPressed = 0; - private boolean pressed = false; - - @Deprecated - public int getNumTimesPressed() { - return numTimesPressed; - } - - public boolean isPressed() { - return pressed; - } - - void toggle(boolean isPressed) { - pressed = isPressed; - if (isPressed) { - numTimesPressed++; - } - } - - @Deprecated - public void off() { - pressed = false; - numTimesPressed = 0; - } - } - -} diff --git a/src/com/redomar/game/UML.ucls b/src/com/redomar/game/UML.ucls deleted file mode 100644 index 6e054bc..0000000 --- a/src/com/redomar/game/UML.ucls +++ /dev/null @@ -1,1119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/com/redomar/game/audio/AudioHandler.java b/src/com/redomar/game/audio/AudioHandler.java index 96d7547..ae710bf 100644 --- a/src/com/redomar/game/audio/AudioHandler.java +++ b/src/com/redomar/game/audio/AudioHandler.java @@ -1,7 +1,7 @@ package com.redomar.game.audio; -import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printer; +import com.redomar.game.log.PrintTypes; +import com.redomar.game.log.Printer; import org.jetbrains.annotations.NotNull; import javax.sound.sampled.*; @@ -12,7 +12,7 @@ public class AudioHandler { - private final Printer musicPrinter = new Printer(PrintTypes.MUSIC); + public final Printer musicPrinter = new Printer(PrintTypes.MUSIC); private Clip clip; private boolean active = false; private boolean music = false; diff --git a/src/com/redomar/game/entities/Dummy.java b/src/com/redomar/game/entities/Dummy.java index 89cd7bf..9916101 100644 --- a/src/com/redomar/game/entities/Dummy.java +++ b/src/com/redomar/game/entities/Dummy.java @@ -2,40 +2,20 @@ import com.redomar.game.Game; import com.redomar.game.entities.efx.Swim; -import com.redomar.game.gfx.Colours; -import com.redomar.game.gfx.Screen; import com.redomar.game.level.LevelHandler; -import com.redomar.game.level.Node; - -import java.util.List; public class Dummy extends Mob { - private static double speed = 0.75; - private static int[] collisionBoders = {0, 7, 0, 7}; - private int colour, shirtCol, faceCol; // = Colours.get(-1, 111, 240, 310); - private int tickCount = 0; - private double xa = 0; - private double ya = 0; - private boolean[] swimType; - private int[] swimColour; - private List path = null; - private int time = 0; - private Swim swim; + private static final double SPEED = 0.75; + private static final int[] MOB_TILE = {8, 28}; + private static final int[] COLLISION_BORDERS = {0, 7, 0, 7}; - public Dummy(LevelHandler level, String name, int x, int y, int shirtCol, - int faceCol) { - super(level, name, x, y, speed, collisionBoders); - this.faceCol = faceCol; - this.shirtCol = shirtCol; - this.colour = Colours.get(-1, 111, shirtCol, faceCol); + public Dummy(LevelHandler level, String name, int x, int y, int shirtCol, int faceCol) { + super(level, name, x, y, MOB_TILE, SPEED, COLLISION_BORDERS, shirtCol, faceCol); } public void tick() { - - //List players = level.getPlayers(this, 8); - aStarMovementAI((int) getX(), (int) getY(), (int) Game.getPlayer().getX(), (int) Game - .getPlayer().getY(), xa, ya, speed, this, path, time); + aStarMovementAI((int) getX(), (int) getY(), (int) Game.getPlayer().getX(), (int) Game.getPlayer().getY(), SPEED, this); setSwim(new Swim(level, (int) getX(), (int) getY())); @@ -48,78 +28,6 @@ public void tick() { } - public void render(Screen screen) { - time++; - int xTile = 8; - int yTile = 28; - int walkingSpeed = 4; - int flipTop = (numSteps >> walkingSpeed) & 1; - int flipBottom = (numSteps >> walkingSpeed) & 1; - - if (movingDir == 1) { - xTile += 2; - if (!isMoving || swim.isActive(swimType)){ - yTile -= 2; - } - } else if (movingDir == 0 && !isMoving || movingDir == 0 && swim.isActive(swimType)) { - yTile -= 2; - } else if (movingDir > 1) { - xTile += 4 + ((numSteps >> walkingSpeed) & 1) * 2; - flipTop = (movingDir - 1) % 2; - if(!isMoving){ - xTile = 4; - } - } - - int modifier = 8 * scale; - int xOffset = (int) getX() - modifier / 2; - int yOffset = (int) getY() - modifier / 2 - 4; - - if (isSwimming || isMagma || isMuddy) { - swimColour = swim.waveCols(isSwimming, isMagma, isMuddy); - - int waterColour = 0; - yOffset += 4; - - colour = Colours.get(-1, 111, -1, faceCol); - - if (tickCount % 60 < 15) { - waterColour = Colours.get(-1, -1, swimColour[0], -1); - } else if (15 <= tickCount % 60 && tickCount % 60 < 30) { - yOffset--; - waterColour = Colours.get(-1, swimColour[1], swimColour[2], -1); - } else if (30 <= tickCount % 60 && tickCount % 60 < 45) { - waterColour = Colours.get(-1, swimColour[2], -1, swimColour[1]); - } else { - yOffset--; - waterColour = Colours.get(-1, -1, swimColour[1], swimColour[2]); - } - - screen.render(xOffset, yOffset + 3, 31 + 31 * 32, waterColour, - 0x00, 1); - screen.render(xOffset + 8, yOffset + 3, 31 + 31 * 32, waterColour, - 0x01, 1); - } - - screen.render((xOffset + (modifier * flipTop)), yOffset, - (xTile + yTile * 32), colour, flipTop, scale); - screen.render((xOffset + modifier - (modifier * flipTop)), yOffset, - ((xTile + 1) + yTile * 32), colour, flipTop, scale); - if (!isSwimming && !isMagma && !isMuddy) { - screen.render((xOffset + (modifier * flipBottom)), - (yOffset + modifier), (xTile + (yTile + 1) * 32), colour, - flipBottom, scale); - screen.render((xOffset + modifier - (modifier * flipBottom)), - (yOffset + modifier), ((xTile + 1) + (yTile + 1) * 32), - colour, flipBottom, scale); - colour = Colours.get(-1, 111, shirtCol, faceCol); - } - } - - public Swim getSwim() { - return swim; - } - public void setSwim(Swim swim) { this.swim = swim; } diff --git a/src/com/redomar/game/entities/Entity.java b/src/com/redomar/game/entities/Entity.java index a8fac57..7bb9a82 100644 --- a/src/com/redomar/game/entities/Entity.java +++ b/src/com/redomar/game/entities/Entity.java @@ -2,12 +2,13 @@ import com.redomar.game.gfx.Screen; import com.redomar.game.level.LevelHandler; -import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printer; +import com.redomar.game.log.PrintTypes; +import com.redomar.game.log.Printer; public abstract class Entity { protected double x, y; + protected int xTile, yTile; protected String name; protected LevelHandler level; protected Printer entityPrinter = new Printer(PrintTypes.ENTITY); @@ -22,6 +23,8 @@ public final void init(LevelHandler level) { public abstract void tick(); + public abstract void render(Screen screen, int xTile, int yTile); + public abstract void render(Screen screen); public double getX() { @@ -47,4 +50,20 @@ public String getName() { public void setName(String name) { this.name = name; } + + public int getXTile() { + return xTile; + } + + public void setXTile(int xTile) { + this.xTile = xTile; + } + + public int getYTile() { + return yTile; + } + + public void setYTile(int yTile) { + this.yTile = yTile; + } } diff --git a/src/com/redomar/game/entities/Mob.java b/src/com/redomar/game/entities/Mob.java index 01a2009..1c71e05 100644 --- a/src/com/redomar/game/entities/Mob.java +++ b/src/com/redomar/game/entities/Mob.java @@ -1,12 +1,18 @@ package com.redomar.game.entities; -import com.redomar.game.entities.projectiles.Medium; +import com.redomar.game.Game; +import com.redomar.game.entities.efx.Swim; +import com.redomar.game.entities.efx.WaterType; import com.redomar.game.entities.projectiles.Projectile; import com.redomar.game.entities.projectiles.Small; +import com.redomar.game.gfx.Colours; +import com.redomar.game.gfx.Screen; import com.redomar.game.level.LevelHandler; import com.redomar.game.level.Node; import com.redomar.game.level.tiles.Tile; +import com.redomar.game.lib.Font; import com.redomar.game.lib.utils.Vector2i; +import com.redomar.game.objects.Inventory; import java.util.ArrayList; import java.util.List; @@ -14,6 +20,8 @@ public abstract class Mob extends Entity { + protected final int shirtColour; + protected final int faceColour; protected Random random = new Random(); protected double speed; protected int numSteps = 0; @@ -24,24 +32,34 @@ public abstract class Mob extends Entity { protected boolean isMagma = false; protected boolean isMuddy = false; protected boolean changeLevels = false; - protected int ticker; + protected boolean showName = false; /** * [0] Contains the xMin
* [1] Contains the xMax
* [2] Contains the yMin
* [3] Contains the yMax */ - protected int[] collisionBoders = new int[4]; + protected int[] collisionBorders; - protected List projectiles = new ArrayList(); + protected List projectiles = new ArrayList<>(); + protected int colour; + protected int tickCount = 0; + protected Swim swim; + protected boolean[] swimType; - public Mob(LevelHandler level, String name, int x, int y, double speed, int[] collisionBoders) { + + public Mob(LevelHandler level, String name, int x, int y, int[] tile, double speed, int[] collisionBorders, int shirtColour, int faceColour) { super(level); this.name = name; this.setX(x); this.setY(y); + this.setXTile(tile[0]); + this.setYTile(tile[1]); this.speed = speed; - this.collisionBoders = collisionBoders; + this.collisionBorders = collisionBorders; + this.shirtColour = shirtColour; + this.faceColour = faceColour; + this.colour = Colours.get(-1, 111, shirtColour, faceColour); } public void move(double xa, double ya) { @@ -72,28 +90,28 @@ public void move(double xa, double ya) { movingDir = 3; } - while (xa != 0){ - if (Math.abs(xa) > 1){ - if (!hasCollided(abs(xa), ya)) { + while (xa != 0) { + if (Math.abs(xa) > 1) { + if (hasCollided(abs(xa), ya)) { this.x += abs(xa); } xa -= abs(xa); } else { - if (!hasCollided(abs(xa), ya)) { + if (hasCollided(abs(xa), ya)) { this.x += xa; } xa = 0; } } - while (ya != 0){ - if (Math.abs(ya) > 1){ - if (!hasCollided(xa, abs(ya))) { + while (ya != 0) { + if (Math.abs(ya) > 1) { + if (hasCollided(xa, abs(ya))) { this.y += abs(ya); } ya -= abs(ya); } else { - if (!hasCollided(xa, abs(ya))) { + if (hasCollided(xa, abs(ya))) { this.y += ya; } ya = 0; @@ -102,54 +120,35 @@ public void move(double xa, double ya) { } - public boolean hasCollided(double xa, double ya){ - int xMin = collisionBoders[0]; - int xMax = collisionBoders[1]; - int yMin = collisionBoders[2]; - int yMax = collisionBoders[3]; + public boolean hasCollided(double xa, double ya) { + int xMin = collisionBorders[0]; + int xMax = collisionBorders[1]; + int yMin = collisionBorders[2]; + int yMax = collisionBorders[3]; for (int x = xMin; x < xMax; x++) { if (isSolid((int) xa, (int) ya, x, yMin)) { - return true; + return false; } - } - - for (int x = xMin; x < xMax; x++) { if (isSolid((int) xa, (int) ya, x, yMax)) { - return true; + return false; } } for (int y = yMin; y < yMax; y++) { if (isSolid((int) xa, (int) ya, xMin, y)) { - return true; + return false; } - } - - for (int y = yMin; y < yMax; y++) { if (isSolid((int) xa, (int) ya, xMax, y)) { - return true; + return false; } } - return false; - } - - public boolean hasCollidedAlt(int xa, int ya){ - boolean solid = false; - for (int c = 0; c < 4; c++) { - double xt = ((x + xa) - c % 2 * 8) / 8; - double yt = ((y + ya) - c / 2 * 8) / 8; - int ix = (int) Math.ceil(xt); - int iy = (int) Math.ceil(yt); - if (c % 2 == 0) ix = (int) Math.floor(xt); - if (c / 2 == 0) iy = (int) Math.floor(yt); - if(level.getTile(ix, iy).isSolid()) solid = true; - } - return solid; + return true; } - private int abs(double i){ + @Deprecated + private int abs(double i) { if (i < 0) return -1; return 1; } @@ -160,46 +159,39 @@ protected boolean isSolid(int xa, int ya, int x, int y) { return false; } - Tile lastTile = level.getTile(((int) this.getX() + x) >> 3, - ((int) this.getY() + y) >> 3); - Tile newtTile = level.getTile(((int) this.getX() + x + xa) >> 3, ((int) this.getY() - + y + ya) >> 3); + Tile lastTile = level.getTile(((int) this.getX() + x) >> 3, ((int) this.getY() + y) >> 3); + Tile newtTile = level.getTile(((int) this.getX() + x + xa) >> 3, ((int) this.getY() + y + ya) >> 3); return !lastTile.equals(newtTile) && newtTile.isSolid(); } - protected void aStarMovementAI(int x, int y, int px, int py, double xa, - double ya, double speed, Mob mob, List path, int time) { - xa = 0; - ya = 0; + protected void aStarMovementAI(int x, int y, int px, int py, double speed, Mob mob) { + double xa = 0; + double ya = 0; Vector2i start = new Vector2i(x >> 3, y >> 3); Vector2i goal = new Vector2i(px >> 3, py >> 3); - path = level.findPath(start, goal); - if(path != null) { - if(path.size() > 0){ + List path = level.findPath(start, goal); + if (path != null) { + if (path.size() > 0) { Vector2i vector = path.get(path.size() - 1).tile; - if(x < vector.getX() << 3) xa =+ speed; - if(x > vector.getX() << 3) xa =- speed; - if(y < vector.getY() << 3) ya =+ speed; - if(y > vector.getY() << 3) ya =- speed; + if (x < vector.getX() << 3) xa = speed; + if (x > vector.getX() << 3) xa = -speed; + if (y < vector.getY() << 3) ya = speed; + if (y > vector.getY() << 3) ya = -speed; moveMob(xa, ya, mob); } } } - protected void followMovementAI(int x, int y, int px, int py, double xa, - double ya, double speed, Mob mob) { - ya = 0; - xa = 0; - if (px > x) - xa+=speed; - if (px < x) - xa-=speed; - if (py > y) - ya+=speed; - if (py < y) - ya-=speed; + @SuppressWarnings("unused") + protected void followMovementAI(int x, int y, int px, int py, double speed, Mob mob) { + double ya = 0; + double xa = 0; + if (px > x) xa += speed; + if (px < x) xa -= speed; + if (py > y) ya += speed; + if (py < y) ya -= speed; moveMob(xa, ya, mob); } @@ -212,11 +204,13 @@ protected double[] randomMovementAI(double x, double y, double xa, double ya, in ya = 0; } } - if(x <= 180){ + if (x <= 180) { xa = 1; + } + if (y <= 180) { ya = -1; } - double move[] = new double[2]; + double[] move = new double[2]; move[0] = xa; move[1] = ya; return move; @@ -231,16 +225,9 @@ protected void moveMob(double xa, double ya, Mob mob) { } } - protected void shoot(double x, double y, double dir, double buttonId, boolean secondry){ -// dir = dir * (180 /Math.PI); -// Printing print = new Printing(); -// print.print("Angle: "+ dir, PrintTypes.GAME); - if(buttonId == 1){ - Projectile p = new Small(level, (int) x,(int) y, dir); - projectiles.add(p); - level.addProjectileEntities(p); - } else if(buttonId == 3 && secondry == true){ - Projectile p = new Medium(level, (int) x,(int) y, dir); + protected void shoot(double x, double y, double dir, double buttonId) { + if (buttonId == 1) { + Projectile p = new Small(level, (int) x, (int) y, dir); projectiles.add(p); level.addProjectileEntities(p); } @@ -258,8 +245,8 @@ public void setNumSteps(int numSteps) { this.numSteps = numSteps; } - public boolean isMoving() { - return this.isMoving; + public void setSwim(Swim swim) { + this.swim = swim; } public void setMoving(boolean isMoving) { @@ -270,4 +257,89 @@ public void setMovingDir(int movingDir) { this.movingDir = movingDir; } + @Override + public void render(Screen screen) { + int xTile = getXTile(); + int yTile = getYTile(); + int modifier = 8 * scale; + int xOffset = (int) getX() - modifier / 2; + int yOffset = (int) getY() - modifier / 2 - 4; + int walkingSpeed = 4; + int flipTop = (numSteps >> walkingSpeed) & 1; + int flipBottom = (numSteps >> walkingSpeed) & 1; + + Inventory.activate(); + + if (movingDir == 1) { + xTile += 2; + if (!isMoving || swim.isActive(swimType)) { + yTile -= 2; + } + } else if (movingDir == 0 && !isMoving || movingDir == 0 && swim.isActive(swimType)) { + yTile -= 2; + } else if (movingDir > 1) { + xTile += 4 + ((numSteps >> walkingSpeed) & 1) * 2; + flipTop = (movingDir - 1) % 2; + if (!isMoving) { + xTile = 4; + } + } + + if (changeLevels) { + Game.setChangeLevel(true); + } + + WaterType type = isSwimming ? WaterType.SWIMMING : isMagma ? WaterType.MAGMA : isMuddy ? WaterType.SWAMP : null; + if (type != null) { + int[] swimColour = swim.waveCols(type); + + int waterColour; + yOffset += 4; + + colour = Colours.get(-1, 111, -1, faceColour); + + if (tickCount % 60 < 15) { + waterColour = Colours.get(-1, -1, swimColour[0], -1); + } else if (tickCount % 60 < 30) { + yOffset--; + waterColour = Colours.get(-1, swimColour[1], swimColour[2], -1); + } else if (tickCount % 60 < 45) { + waterColour = Colours.get(-1, swimColour[2], -1, swimColour[1]); + } else { + yOffset--; + waterColour = Colours.get(-1, -1, swimColour[1], swimColour[2]); + } + + screen.render(xOffset, yOffset + 3, 31 + 31 * 32, waterColour, 0x00, 1); + screen.render(xOffset + 8, yOffset + 3, 31 + 31 * 32, waterColour, 0x01, 1); + } + + screen.render((xOffset + (modifier * flipTop)), yOffset, (xTile + yTile * 32), colour, flipTop, scale); + screen.render((xOffset + modifier - (modifier * flipTop)), yOffset, ((xTile + 1) + yTile * 32), colour, flipTop, scale); + if (!isSwimming && !isMagma && !isMuddy) { + screen.render((xOffset + (modifier * flipBottom)), (yOffset + modifier), (xTile + (yTile + 1) * 32), colour, flipBottom, scale); + screen.render((xOffset + modifier - (modifier * flipBottom)), (yOffset + modifier), ((xTile + 1) + (yTile + 1) * 32), colour, flipBottom, scale); + colour = Colours.get(-1, 111, shirtColour, faceColour); + } + + if (name != null && showName) { + /* + * Improved name centering above player's sprite. + * Using player's own x value cast to int with an adjusted formula + * -posmicanomaly + */ + + int fontCharSize = 8; + int offsetUnit = ((name.length() & 1) == 0 ? fontCharSize / 2 : 0); + int nameOffset = (name.length() / 2) * fontCharSize - offsetUnit; + Font.render(name, screen, (int) x - nameOffset, yOffset - 10, Colours.get(-1, -1, -1, 111), 1); + + } + } + + public void render(Screen screen, int xTile, int yTile) { + setXTile(xTile); + setYTile(yTile); + render(screen); + } } diff --git a/src/com/redomar/game/entities/Player.java b/src/com/redomar/game/entities/Player.java index 27ded8e..0307749 100644 --- a/src/com/redomar/game/entities/Player.java +++ b/src/com/redomar/game/entities/Player.java @@ -1,42 +1,31 @@ package com.redomar.game.entities; import com.redomar.game.Game; -import com.redomar.game.InputHandler; import com.redomar.game.entities.efx.Swim; import com.redomar.game.entities.projectiles.Medium; import com.redomar.game.entities.projectiles.Projectile; import com.redomar.game.entities.projectiles.Small; -import com.redomar.game.gfx.Colours; -import com.redomar.game.gfx.Screen; +import com.redomar.game.event.InputHandler; import com.redomar.game.level.LevelHandler; -import com.redomar.game.lib.Font; import com.redomar.game.lib.HashGen; -import com.redomar.game.objects.Inventory; import java.util.Objects; public class Player extends Mob { private static final String PLAYER_ID = new HashGen(false, 3).getHash(); + private static final int[] PLAYER_TILE = {0, 28}; private static final int[] COLLISION_BORDERS = {-2, 8, 0, 7}; - private static final double speed = 1; + private static double speed = 1; private final InputHandler inputHandler; - private final int shirtColour; - private final int faceColour; - private int colour; - private int tickCount = 0; - private Swim swim; - private boolean[] swimType; private int fireRate; public Player(LevelHandler level, int x, int y, InputHandler inputHandler, String name, int shirtColour, int faceColour) { - super(level, "Player", x, y, speed, COLLISION_BORDERS); + super(level, "Player", x, y, PLAYER_TILE, speed, COLLISION_BORDERS, shirtColour, faceColour); this.inputHandler = inputHandler; this.name = !Objects.equals(name, "") ? name : String.format("Player %s", PLAYER_ID); - this.faceColour = faceColour; - this.shirtColour = shirtColour; - this.colour = Colours.get(-1, 111, shirtColour, faceColour); fireRate = Small.FIRE_RATE; + showName = true; } public void tick() { @@ -44,6 +33,9 @@ public void tick() { double ya = 0; if (inputHandler != null) { + + speed = inputHandler.getSHIFTED().isPressed() ? 2 : 1; + if (inputHandler.getUP_KEY().isPressed()) { ya -= speed; } @@ -71,7 +63,7 @@ public void tick() { double dx = Game.getMouse().getX() - 480 / 2d; double dy = Game.getMouse().getY() - 320 / 2d; double dir = Math.atan2(dy, dx); - shoot(x, y, dir, Game.getMouse().getButton(), false); + shoot(x, y, dir, Game.getMouse().getButton()); } } } @@ -103,85 +95,6 @@ public void tick() { tickCount++; } - public void render(Screen screen) { - int xTile = 0; - int yTile = 28; - int walkingSpeed = 4; - int flipTop = (numSteps >> walkingSpeed) & 1; - int flipBottom = (numSteps >> walkingSpeed) & 1; - - Inventory.activate(); - - if (movingDir == 1) { - xTile += 2; - if (!isMoving || swim.isActive(swimType)) { - yTile -= 2; - } - } else if (movingDir == 0 && !isMoving || movingDir == 0 && swim.isActive(swimType)) { - yTile -= 2; - } else if (movingDir > 1) { - xTile += 4 + ((numSteps >> walkingSpeed) & 1) * 2; - flipTop = (movingDir - 1) % 2; - if (!isMoving) { - xTile = 4; - } - } - - int modifier = 8 * scale; - int xOffset = (int) getX() - modifier / 2; - int yOffset = (int) getY() - modifier / 2 - 4; - - if (changeLevels) { - Game.setChangeLevel(true); - } - - if (isSwimming || isMagma || isMuddy) { - int[] swimColour = swim.waveCols(isSwimming, isMagma, isMuddy); - - int waterColour; - yOffset += 4; - - colour = Colours.get(-1, 111, -1, faceColour); - - if (tickCount % 60 < 15) { - waterColour = Colours.get(-1, -1, swimColour[0], -1); - } else if (tickCount % 60 < 30) { - yOffset--; - waterColour = Colours.get(-1, swimColour[1], swimColour[2], -1); - } else if (tickCount % 60 < 45) { - waterColour = Colours.get(-1, swimColour[2], -1, swimColour[1]); - } else { - yOffset--; - waterColour = Colours.get(-1, -1, swimColour[1], swimColour[2]); - } - - screen.render(xOffset, yOffset + 3, 31 + 31 * 32, waterColour, 0x00, 1); - screen.render(xOffset + 8, yOffset + 3, 31 + 31 * 32, waterColour, 0x01, 1); - } - - screen.render((xOffset + (modifier * flipTop)), yOffset, (xTile + yTile * 32), colour, flipTop, scale); - screen.render((xOffset + modifier - (modifier * flipTop)), yOffset, ((xTile + 1) + yTile * 32), colour, flipTop, scale); - if (!isSwimming && !isMagma && !isMuddy) { - screen.render((xOffset + (modifier * flipBottom)), (yOffset + modifier), (xTile + (yTile + 1) * 32), colour, flipBottom, scale); - screen.render((xOffset + modifier - (modifier * flipBottom)), (yOffset + modifier), ((xTile + 1) + (yTile + 1) * 32), colour, flipBottom, scale); - colour = Colours.get(-1, 111, shirtColour, faceColour); - } - - if (name != null) { - /* - * Improved name centering above player's sprite. - * Using player's own x value cast to int with an adjusted formula - * -posmicanomaly - */ - - int fontCharSize = 8; - int offsetUnit = ((name.length() & 1) == 0 ? fontCharSize / 2 : 0); - int nameOffset = (name.length() / 2) * fontCharSize - offsetUnit; - Font.render(name, screen, (int) x - nameOffset, yOffset - 10, Colours.get(-1, -1, -1, 111), 1); - - } - } - @Deprecated public String getUsername() { return this.name; diff --git a/src/com/redomar/game/entities/PlayerMP.java b/src/com/redomar/game/entities/PlayerMP.java index adf8d21..14d4cdd 100644 --- a/src/com/redomar/game/entities/PlayerMP.java +++ b/src/com/redomar/game/entities/PlayerMP.java @@ -1,6 +1,6 @@ package com.redomar.game.entities; -import com.redomar.game.InputHandler; +import com.redomar.game.event.InputHandler; import com.redomar.game.level.LevelHandler; import java.net.InetAddress; diff --git a/src/com/redomar/game/entities/Vendor.java b/src/com/redomar/game/entities/Vendor.java index 4e5be5c..e377ae6 100644 --- a/src/com/redomar/game/entities/Vendor.java +++ b/src/com/redomar/game/entities/Vendor.java @@ -1,41 +1,24 @@ package com.redomar.game.entities; import com.redomar.game.entities.efx.Swim; -import com.redomar.game.gfx.Colours; -import com.redomar.game.gfx.Screen; import com.redomar.game.level.LevelHandler; -import com.redomar.game.level.Node; - -import java.util.List; public class Vendor extends Mob { - private static double speed = 0.75; - private static int[] collisionBoders = {0, 7, 0, 7}; - private int colour, shirtCol, faceCol; // = Colours.get(-1, 111, 240, 310); - private int tickCount = 0; + private static final double SPEED = 0.75; + private static final int[] MOB_TILE = {0, 28}; + private static final int[] COLLISION_BORDERS = {0, 7, 0, 7}; private int tick = 0; private double xa = 0; private double ya = 0; - private double[] movement; - private boolean[] swimType; - private int[] swimColour; - private List path = null; - private int time = 0; - private Swim swim; - public Vendor(LevelHandler level, String name, int x, int y, int shirtCol, - int faceCol) { - super(level, name, x, y, speed, collisionBoders); - this.faceCol = faceCol; - this.shirtCol = shirtCol; - this.colour = Colours.get(-1, 111, shirtCol, faceCol); + public Vendor(LevelHandler level, String name, int x, int y, int shirtCol, int faceCol) { + super(level, name, x, y, MOB_TILE, SPEED, COLLISION_BORDERS, shirtCol, faceCol); } public void tick() { - tick++; - movement = randomMovementAI(x, y, xa, ya, tick); + double[] movement = randomMovementAI(x, y, xa, ya, tick); this.xa = movement[0]; this.ya = movement[1]; @@ -49,98 +32,6 @@ public void tick() { isMuddy = swimType[2]; tickCount++; - - } - - public void render(Screen screen) { - setTime(time + 1); - int xTile = 8; - int yTile = 28; - int walkingSpeed = 4; - int flipTop = (numSteps >> walkingSpeed) & 1; - int flipBottom = (numSteps >> walkingSpeed) & 1; - - if (movingDir == 1) { - xTile += 2; - if (!isMoving || swim.isActive(swimType)){ - yTile -= 2; - } - } else if (movingDir == 0 && !isMoving || movingDir == 0 && swim.isActive(swimType)) { - yTile -= 2; - } else if (movingDir > 1) { - xTile += 4 + ((numSteps >> walkingSpeed) & 1) * 2; - flipTop = (movingDir - 1) % 2; - if(!isMoving){ - xTile = 4; - } - } - - int modifier = 8 * scale; - int xOffset = (int) getX() - modifier / 2; - int yOffset = (int) getY() - modifier / 2 - 4; - - if (isSwimming || isMagma || isMuddy) { - swimColour = swim.waveCols(isSwimming, isMagma, isMuddy); - - int waterColour = 0; - yOffset += 4; - - colour = Colours.get(-1, 111, -1, faceCol); - - if (tickCount % 60 < 15) { - waterColour = Colours.get(-1, -1, swimColour[0], -1); - } else if (15 <= tickCount % 60 && tickCount % 60 < 30) { - yOffset--; - waterColour = Colours.get(-1, swimColour[1], swimColour[2], -1); - } else if (30 <= tickCount % 60 && tickCount % 60 < 45) { - waterColour = Colours.get(-1, swimColour[2], -1, swimColour[1]); - } else { - yOffset--; - waterColour = Colours.get(-1, -1, swimColour[1], swimColour[2]); - } - - screen.render(xOffset, yOffset + 3, 31 + 31 * 32, waterColour, - 0x00, 1); - screen.render(xOffset + 8, yOffset + 3, 31 + 31 * 32, waterColour, - 0x01, 1); - } - - screen.render((xOffset + (modifier * flipTop)), yOffset, - (xTile + yTile * 32), colour, flipTop, scale); - screen.render((xOffset + modifier - (modifier * flipTop)), yOffset, - ((xTile + 1) + yTile * 32), colour, flipTop, scale); - if (!isSwimming && !isMagma && !isMuddy) { - screen.render((xOffset + (modifier * flipBottom)), - (yOffset + modifier), (xTile + (yTile + 1) * 32), colour, - flipBottom, scale); - screen.render((xOffset + modifier - (modifier * flipBottom)), - (yOffset + modifier), ((xTile + 1) + (yTile + 1) * 32), - colour, flipBottom, scale); - colour = Colours.get(-1, 111, shirtCol, faceCol); - } - } - - public Swim getSwim() { - return swim; - } - - public void setSwim(Swim swim) { - this.swim = swim; - } - - public List getPath() { - return path; - } - - public void setPath(List path) { - this.path = path; } - public int getTime() { - return time; - } - - public void setTime(int time) { - this.time = time; - } } diff --git a/src/com/redomar/game/entities/efx/Swim.java b/src/com/redomar/game/entities/efx/Swim.java index b2b6399..354f173 100644 --- a/src/com/redomar/game/entities/efx/Swim.java +++ b/src/com/redomar/game/entities/efx/Swim.java @@ -2,12 +2,22 @@ import com.redomar.game.level.LevelHandler; +import java.util.HashMap; +import java.util.Map; + public class Swim { + private static final Map COLORS = new HashMap<>(); private static LevelHandler level; - private int x; - private int y; - private int[] swimCols = new int[3]; + + static { + COLORS.put(WaterType.SWIMMING, new int[]{255, 255, 115}); + COLORS.put(WaterType.MAGMA, new int[]{541, 521, 510}); + COLORS.put(WaterType.SWAMP, new int[]{422, 410, 321}); + } + + private final int x; + private final int y; public Swim(LevelHandler level, int x, int y) { Swim.level = level; @@ -15,24 +25,13 @@ public Swim(LevelHandler level, int x, int y) { this.y = y; } - public int[] waveCols(boolean isSwimming, boolean isMagma, boolean isMuddy){ + @Deprecated + public int[] waveCols(boolean isSwimming, boolean isMagma, boolean isMuddy) { + return COLORS.get(isSwimming ? WaterType.SWIMMING : isMagma ? WaterType.MAGMA : isMuddy ? WaterType.SWAMP : null); + } - if(isSwimming){ - swimCols[0] = 255; - swimCols[1] = 255; - swimCols[2] = 115; - } - if (isMagma) { - swimCols[0] = 541; - swimCols[1] = 521; - swimCols[2] = 510; - } - if (isMuddy) { - swimCols[0] = 422; - swimCols[1] = 410; - swimCols[2] = 321; - } - return swimCols; + public int[] waveCols(WaterType type) { + return COLORS.get(type); } public boolean water(boolean isSwimming) { @@ -71,19 +70,19 @@ public boolean mud(boolean isMuddy) { } public boolean[] swimming(boolean isSwimming, boolean isMagma, boolean isMuddy) { - boolean[] swimminhType; - swimminhType = new boolean[3]; - swimminhType[0] = water(isSwimming); - swimminhType[1] = magma(isMagma); - swimminhType[2] = mud(isMuddy); - return swimminhType; + boolean[] swimmingType; + swimmingType = new boolean[3]; + swimmingType[0] = water(isSwimming); + swimmingType[1] = magma(isMagma); + swimmingType[2] = mud(isMuddy); + return swimmingType; } - public boolean isActive(boolean[] swimmingType){ - if(swimmingType[0] == true){ + public boolean isActive(boolean[] swimmingType) { + if (swimmingType[0]) { return true; - }else if(swimmingType[1] == true){ + } else if (swimmingType[1]) { return true; - } else return swimmingType[2] == true; + } else return swimmingType[2]; } } diff --git a/src/com/redomar/game/entities/efx/WaterType.java b/src/com/redomar/game/entities/efx/WaterType.java new file mode 100644 index 0000000..5796eca --- /dev/null +++ b/src/com/redomar/game/entities/efx/WaterType.java @@ -0,0 +1,5 @@ +package com.redomar.game.entities.efx; + +public enum WaterType { + SWIMMING, MAGMA, SWAMP +} \ No newline at end of file diff --git a/src/com/redomar/game/entities/projectiles/Projectile.java b/src/com/redomar/game/entities/projectiles/Projectile.java index 9798d55..0633fe9 100644 --- a/src/com/redomar/game/entities/projectiles/Projectile.java +++ b/src/com/redomar/game/entities/projectiles/Projectile.java @@ -1,12 +1,13 @@ package com.redomar.game.entities.projectiles; import com.redomar.game.entities.Entity; +import com.redomar.game.gfx.Screen; import com.redomar.game.level.LevelHandler; import com.redomar.game.level.tiles.Tile; import java.util.Random; -public abstract class Projectile extends Entity{ +public abstract class Projectile extends Entity { protected final double xOrigin, yOrigin; protected double angle; @@ -27,7 +28,7 @@ public Projectile(LevelHandler level, int x, int y, double dir) { protected abstract void move(); - public boolean tileCollision(double xa, double ya, int nx, int ny){ + public boolean tileCollision(double xa, double ya, int nx, int ny) { int xMin = 0; int xMax = 7; int yMin = 0; @@ -60,21 +61,24 @@ public boolean tileCollision(double xa, double ya, int nx, int ny){ return false; } + @Override + public void render(Screen screen, int xTile, int yTile) { + + } + private boolean isSolid(int xa, int ya, int x, int y, int nx, int ny) { if (level == null) { return false; } - Tile lastTile = level.getTile((nx + x) >> 3, - (ny + y) >> 3); - Tile newtTile = level.getTile((nx + x + xa) >> 3, (ny - + y + ya) >> 3); + Tile lastTile = level.getTile((nx + x) >> 3, (ny + y) >> 3); + Tile newtTile = level.getTile((nx + x + xa) >> 3, (ny + y + ya) >> 3); return !lastTile.equals(newtTile) && newtTile.isSolid(); } - public void remove(){ + public void remove() { setRemoved(true); } diff --git a/src/com/redomar/game/entities/projectiles/Small.java b/src/com/redomar/game/entities/projectiles/Small.java index 1f95f1a..12d75bf 100644 --- a/src/com/redomar/game/entities/projectiles/Small.java +++ b/src/com/redomar/game/entities/projectiles/Small.java @@ -27,6 +27,8 @@ public Small(LevelHandler level, int x, int y, double dir) { smallSound.play(); } catch (NullPointerException e) { entityPrinter.cast().exception(e.toString()).exception("Unable to load Audio file " + smallShot.getName()); + } catch (Exception e) { + throw new RuntimeException(e); } } diff --git a/src/com/redomar/game/entities/trees/Tree.java b/src/com/redomar/game/entities/trees/Tree.java index 6297246..575c8f4 100644 --- a/src/com/redomar/game/entities/trees/Tree.java +++ b/src/com/redomar/game/entities/trees/Tree.java @@ -1,14 +1,14 @@ package com.redomar.game.entities.trees; import com.redomar.game.entities.Entity; +import com.redomar.game.gfx.Screen; import com.redomar.game.level.LevelHandler; public abstract class Tree extends Entity { - private final LevelHandler level; /** * Tree abstract class - * -- Used by Spruce Class + * -- Used by Spruce Class */ //Position variables @@ -17,15 +17,19 @@ public abstract class Tree extends Entity { /** * Constructor for tree entities + * * @param level LevelHandler in which tree spawns - * @param x X co-ordinate - * @param y Y co-ordinate + * @param x X co-ordinate + * @param y Y co-ordinate */ Tree(LevelHandler level, double x, double y) { super(level); - this.level = level; this.x = x; this.y = y; } + @Override + public void render(Screen screen, int xTile, int yTile) { + + } } diff --git a/src/com/redomar/game/event/InputHandler.java b/src/com/redomar/game/event/InputHandler.java new file mode 100644 index 0000000..e5a6f4e --- /dev/null +++ b/src/com/redomar/game/event/InputHandler.java @@ -0,0 +1,174 @@ +package com.redomar.game.event; + +import com.redomar.game.Game; +import com.redomar.game.lib.Either; +import com.redomar.game.lib.SleepThread; +import com.redomar.game.log.PrintTypes; +import com.redomar.game.log.Printer; + +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.im.InputContext; +import java.util.HashMap; +import java.util.Map; + +import static com.redomar.game.lib.Either.tryCatch; + +public class InputHandler implements KeyListener { + + private final boolean frenchKeyboardLayout; + private final Printer inputPrinter = new Printer(PrintTypes.INPUT); + private final KeyHandler UP_KEY = new KeyHandler(); + private final KeyHandler DOWN_KEY = new KeyHandler(); + private final KeyHandler LEFT_KEY = new KeyHandler(); + private final KeyHandler RIGHT_KEY = new KeyHandler(); + private final KeyHandler SHIFTED = new KeyHandler(); + private final KeyHandler M_KEY = new KeyHandler(); + + + public InputHandler(Game game) { + InputContext context = InputContext.getInstance(); + frenchKeyboardLayout = context.getLocale().getCountry().equals("BE") || context.getLocale().getCountry().equals("FR"); + game.addKeyListener(this); + } + + public void keyPressed(KeyEvent e) { + toggleKey(e.getKeyCode(), true); + } + + /** + * Toggles between two actions depending on the value of a boolean flag. + * + * @param key the key to be pressed to trigger the action + * @param isToggled the boolean flag that determines which action to activate + * @param actionA the function to execute the first action + * @param actionB the function to execute the second action + * @return an Either object with the result of the action on the right side and an Exception on the left side if an exception is thrown + */ + public Either toggleActionWithCheckedRunnable(KeyHandler key, boolean isToggled, Either.CheckedRunnable actionA, Either.CheckedRunnable actionB) { + boolean pressed = key.isPressed(); + if (pressed) { + if (!isToggled) { + Either result = tryCatch(actionA); + if (result.isLeft()) { + return result.map(__ -> false); + } + isToggled = true; + } else { + Either result = tryCatch(actionB); + if (result.isLeft()) { + return result.map(__ -> true); + } + isToggled = false; + } + key.reset(); + } + return Either.right(isToggled); + } + + public void keyReleased(KeyEvent e) { + int keyCode = e.getKeyCode(); + toggleKey(keyCode, false); + if (keyCode == KeyEvent.VK_BACK_QUOTE) { + if (!Game.isClosing()) { + Game.setDevMode(!Game.isDevMode()); + new Thread(new SleepThread()); + inputPrinter.print(String.format("Debug Mode %s", Game.isDevMode() ? "Enabled" : "Disabled")); + } + } + + if (keyCode == KeyEvent.VK_N) { + if (!Game.isNpc()) { + Game.setNpc(true); + Game.npcSpawn(); + inputPrinter.print("Dummy has been spawned", PrintTypes.GAME); + } + } + } + + public void keyTyped(KeyEvent e) { + + } + + private void toggleKey(int keyCode, boolean isPressed) { + Map keyCodeActions = new HashMap<>(); + + keyCodeActions.put(KeyEvent.VK_S, () -> DOWN_KEY.setPressed(isPressed)); + keyCodeActions.put(KeyEvent.VK_D, () -> RIGHT_KEY.setPressed(isPressed)); + keyCodeActions.put(KeyEvent.VK_UP, () -> UP_KEY.setPressed(isPressed)); + keyCodeActions.put(KeyEvent.VK_LEFT, () -> LEFT_KEY.setPressed(isPressed)); + keyCodeActions.put(KeyEvent.VK_DOWN, () -> DOWN_KEY.setPressed(isPressed)); + keyCodeActions.put(KeyEvent.VK_RIGHT, () -> RIGHT_KEY.setPressed(isPressed)); + keyCodeActions.put(KeyEvent.VK_SHIFT, () -> SHIFTED.setPressed(isPressed)); + keyCodeActions.put(KeyEvent.VK_M, () -> M_KEY.setPressedToggle(isPressed)); + + if (frenchKeyboardLayout) { + keyCodeActions.put(KeyEvent.VK_Q, () -> LEFT_KEY.setPressed(isPressed)); + keyCodeActions.put(KeyEvent.VK_Z, () -> UP_KEY.setPressed(isPressed)); + keyCodeActions.put(KeyEvent.VK_A, this::quitGame); + } else { + keyCodeActions.put(KeyEvent.VK_A, () -> LEFT_KEY.setPressed(isPressed)); + keyCodeActions.put(KeyEvent.VK_W, () -> UP_KEY.setPressed(isPressed)); + keyCodeActions.put(KeyEvent.VK_Q, this::quitGame); + } + + if (keyCodeActions.containsKey(keyCode)) keyCodeActions.get(keyCode).run(); + + if (keyCode == KeyEvent.VK_W && frenchKeyboardLayout || keyCode == KeyEvent.VK_Z && !frenchKeyboardLayout) { + if (Game.getMap() == 2) { + if (Game.isNpc()) { + Game.setNpc(false); + } + Game.setChangeLevel(true); + } + } + + if (keyCode == KeyEvent.VK_K) { + if (Game.isNpc()) { + Game.setNpc(false); + Game.npcKill(); + inputPrinter.print("Dummy has been removed", PrintTypes.GAME); + } + } + + } + + private void quitGame() { + Game.setClosing(true); + if (!inputPrinter.removeLog()) System.err.println("Could not delete Log file"); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Game.getLevel().removeEntity(Game.getPlayer().getName()); + Game.getGame().stop(); + Game.getFrame().dispose(); + System.exit(0); + } + + public KeyHandler getUP_KEY() { + return UP_KEY; + } + + public KeyHandler getDOWN_KEY() { + return DOWN_KEY; + } + + public KeyHandler getLEFT_KEY() { + return LEFT_KEY; + } + + public KeyHandler getRIGHT_KEY() { + return RIGHT_KEY; + } + + public KeyHandler getSHIFTED() { + return SHIFTED; + } + + public KeyHandler getM_KEY() { + return M_KEY; + } + +} diff --git a/src/com/redomar/game/event/KeyHandler.java b/src/com/redomar/game/event/KeyHandler.java new file mode 100644 index 0000000..56b0d06 --- /dev/null +++ b/src/com/redomar/game/event/KeyHandler.java @@ -0,0 +1,35 @@ +package com.redomar.game.event; + +@SuppressWarnings("unused") +public class KeyHandler { + private int numTimesPressed = 0; + private boolean pressed = false; + + @Deprecated + public int getNumTimesPressed() { + return numTimesPressed; + } + + public boolean isPressed() { + return pressed; + } + + void setPressed(boolean isPressed) { + pressed = isPressed; + if (isPressed) numTimesPressed++; + } + + void setPressedToggle(boolean isPressed) { + if (isPressed) return; + pressed = !pressed; + } + + public void on() { + pressed = true; + } + + public void reset() { + pressed = false; + numTimesPressed = 0; + } +} diff --git a/src/com/redomar/game/lib/Mouse.java b/src/com/redomar/game/event/Mouse.java similarity index 81% rename from src/com/redomar/game/lib/Mouse.java rename to src/com/redomar/game/event/Mouse.java index 6a334bd..f05807a 100644 --- a/src/com/redomar/game/lib/Mouse.java +++ b/src/com/redomar/game/event/Mouse.java @@ -1,12 +1,12 @@ -package com.redomar.game.lib; +package com.redomar.game.event; + +import com.redomar.game.Game; +import com.redomar.game.menu.Menu; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; -import com.redomar.game.Game; -import com.redomar.game.menu.Menu; - public class Mouse implements MouseListener, MouseMotionListener { public void mouseDragged(MouseEvent e) { @@ -16,17 +16,9 @@ public void mouseDragged(MouseEvent e) { public void mouseMoved(MouseEvent e) { if (e.getX() > 35 && e.getX() < 455) { // START is being selected - if (e.getY() > 38 && e.getY() < 150) { - Menu.setSelectedStart(true); - } else { - Menu.setSelectedStart(false); - } + Menu.setSelectedStart(e.getY() > 38 && e.getY() < 150); // EXIT is being selected - if (e.getY() > 170 && e.getY() < 280) { - Menu.setSelectedExit(true); - } else { - Menu.setSelectedExit(false); - } + Menu.setSelectedExit(e.getY() > 170 && e.getY() < 280); } else { Menu.setSelectedStart(false); Menu.setSelectedExit(false); diff --git a/src/com/redomar/game/MouseHandler.java b/src/com/redomar/game/event/MouseHandler.java similarity index 89% rename from src/com/redomar/game/MouseHandler.java rename to src/com/redomar/game/event/MouseHandler.java index 38e5e36..3cb3c2a 100644 --- a/src/com/redomar/game/MouseHandler.java +++ b/src/com/redomar/game/event/MouseHandler.java @@ -1,16 +1,18 @@ -package com.redomar.game; +package com.redomar.game.event; + +import com.redomar.game.Game; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; -public class MouseHandler implements MouseListener, MouseMotionListener{ +public class MouseHandler implements MouseListener, MouseMotionListener { private static int mouseX = -1; private static int mouseY = -1; private static int mouseB = -1; - public MouseHandler(Game game){ + public MouseHandler(Game game) { game.addMouseListener(this); game.addMouseMotionListener(this); } diff --git a/src/com/redomar/game/WindowHandler.java b/src/com/redomar/game/event/WindowHandler.java similarity index 86% rename from src/com/redomar/game/WindowHandler.java rename to src/com/redomar/game/event/WindowHandler.java index d04bf42..2180662 100644 --- a/src/com/redomar/game/WindowHandler.java +++ b/src/com/redomar/game/event/WindowHandler.java @@ -1,15 +1,15 @@ -package com.redomar.game; +package com.redomar.game.event; + +import com.redomar.game.Game; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; +@Deprecated +@SuppressWarnings("unused") public class WindowHandler implements WindowListener { - @SuppressWarnings("unused") - private final Game game; - public WindowHandler(Game game) { - this.game = game; Game.getFrame().addWindowListener(this); } diff --git a/src/com/redomar/game/level/LevelHandler.java b/src/com/redomar/game/level/LevelHandler.java index 5dfbae8..acf471a 100644 --- a/src/com/redomar/game/level/LevelHandler.java +++ b/src/com/redomar/game/level/LevelHandler.java @@ -2,36 +2,31 @@ import com.redomar.game.entities.Entity; import com.redomar.game.entities.Player; -import com.redomar.game.entities.PlayerMP; import com.redomar.game.gfx.Screen; import com.redomar.game.level.tiles.Tile; import com.redomar.game.lib.utils.Vector2i; +import com.redomar.game.log.PrintTypes; +import com.redomar.game.log.Printer; import com.redomar.game.scenes.Scene; -import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printer; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; +import java.util.*; import java.util.logging.Level; public class LevelHandler { + private final List entities; + private final List entities_p; + private final Printer print; + private final Comparator nodeSorter; private byte[] tiles; private int width; private int height; - private List entities; - private List entities_p; private String imagePath; private BufferedImage image; - private Printer print; - - private Comparator nodeSorter; public LevelHandler(String imagePath) { @@ -46,39 +41,29 @@ public LevelHandler(String imagePath) { } print = new Printer(); - entities = new ArrayList(); - entities_p = new ArrayList(); - nodeSorter = new Comparator() { - - public int compare(Node n0, Node n1) { - if(n1.fCost < n0.fCost) return +1; - if(n1.fCost > n0.fCost) return -1; - return 0; - } - - }; + entities = new ArrayList<>(); + entities_p = new ArrayList<>(); + nodeSorter = Comparator.comparingDouble(n0 -> n0.fCost); } private void loadLevelFromFile() { try { - this.image = ImageIO.read(LevelHandler.class.getResource(this.imagePath)); + this.image = ImageIO.read(Objects.requireNonNull(LevelHandler.class.getResource(this.imagePath))); this.setWidth(image.getWidth()); this.setHeight(image.getHeight()); tiles = new byte[getWidth() * getHeight()]; this.loadTiles(); - } catch (IOException e ){ + } catch (IOException e) { e.printStackTrace(); } } private void loadTiles() { - int[] tileColours = this.image.getRGB(0, 0, getWidth(), getHeight(), null, 0, - getWidth()); + int[] tileColours = this.image.getRGB(0, 0, getWidth(), getHeight(), null, 0, getWidth()); for (int y = 0; y < getHeight(); y++) { for (int x = 0; x < getWidth(); x++) { for (Tile t : Tile.getTiles()) - if (t != null - && t.getLevelColour() == tileColours[x + y * getWidth()]) { + if (t != null && t.getLevelColour() == tileColours[x + y * getWidth()]) { this.tiles[x + y * getWidth()] = t.getId(); break; } @@ -89,8 +74,7 @@ private void loadTiles() { @SuppressWarnings("unused") private void saveLevelToFile() { try { - ImageIO.write(image, "png", - new File(Level.class.getResource(this.imagePath).getFile())); + ImageIO.write(image, "png", new File(Objects.requireNonNull(Level.class.getResource(this.imagePath)).getFile())); } catch (IOException e) { e.printStackTrace(); } @@ -162,12 +146,12 @@ public void renderTiles(Screen screen, int xOffset, int yOffset) { public void renderEntities(Screen screen) { for (Entity e : entities) { - e.render(screen); + e.render(screen, e.getXTile(), e.getYTile()); } } - public void renderProjectileEntities(Screen screen){ - for (Entity e : getProjectileEntities()){ + public void renderProjectileEntities(Screen screen) { + for (Entity e : getProjectileEntities()) { e.render(screen); } } @@ -181,7 +165,7 @@ public Tile getTile(int x, int y) { public void addEntity(Entity entity) { this.entities.add(entity); - print.print("Added "+entity.getName()+" Entity", PrintTypes.LEVEL); + print.print("Added " + entity.getName() + " Entity", PrintTypes.LEVEL); try { Thread.sleep(100); } catch (InterruptedException e) { @@ -196,16 +180,17 @@ public void addProjectileEntities(Entity entity) { /** * Removes the entity that is passed through + * * @param entity Specifies which entity needs to be removed */ public void removeEntity(Entity entity) { - if(entity == null) return; - print.print("Removed "+entity.getName()+" Entity", PrintTypes.LEVEL); + if (entity == null) return; + print.print("Removed " + entity.getName() + " Entity", PrintTypes.LEVEL); this.entities.remove(entity); try { Thread.sleep(100); } catch (InterruptedException e) { - print.print("Interruption error: "+ e, PrintTypes.ERROR); + print.print("Interruption error: " + e, PrintTypes.ERROR); e.printStackTrace(); } } @@ -217,8 +202,7 @@ public void removeProjectileEntities(Entity entity) { public void removeEntity(String username) { int index = 0; for (Entity e : entities) { - if (e instanceof Player - && ((Player) e).getUsername().equalsIgnoreCase(username)) { + if (e instanceof Player && e.getName().equalsIgnoreCase(username)) { break; } index++; @@ -226,39 +210,17 @@ public void removeEntity(String username) { this.entities.remove(index); } - private int getPlayerMPIndex(String username) { - int index = 0; - for (Entity e : entities) { - if (e instanceof PlayerMP - && ((PlayerMP) e).getUsername().equalsIgnoreCase(username)) { - break; - } - index++; - } - return index; - } - - public void movePlayer(String username, int x, int y, int numSteps, - boolean isMoving, int movingDir) { - int index = getPlayerMPIndex(username); - PlayerMP player = (PlayerMP) this.entities.get(index); - player.setX(x); - player.setY(y); - player.setNumSteps(numSteps); - player.setMoving(isMoving); - player.setMovingDir(movingDir); - } - public List findPath(Vector2i start, Vector2i goal){ - List openList = new ArrayList(); - List closedList = new ArrayList(); + public List findPath(Vector2i start, Vector2i goal) { + List openList = new ArrayList<>(); + List closedList = new ArrayList<>(); Node current = new Node(start, null, 0, getDistance(start, goal)); openList.add(current); - while(openList.size() > 0){ - Collections.sort(openList, nodeSorter); + while (openList.size() > 0) { + openList.sort(nodeSorter); current = openList.get(0); - if(current.tile.equals(goal)){ - List path = new ArrayList(); + if (current.tile.equals(goal)) { + List path = new ArrayList<>(); while (current.parent != null) { path.add(current); current = current.parent; @@ -269,70 +231,61 @@ public List findPath(Vector2i start, Vector2i goal){ } openList.remove(current); closedList.add(current); - for(int i = 0; i < 9; i++){ - if(i == 4) continue; + for (int i = 0; i < 9; i++) { + if (i == 4) continue; int x = current.tile.getX(); int y = current.tile.getY(); int xi = (i % 3) - 1; int yi = (i / 3) - 1; - Tile at = getTile(x + xi,y + yi); - if(at == null) continue; - if(at.isSolid()) continue; + Tile at = getTile(x + xi, y + yi); + if (at == null) continue; + if (at.isSolid()) continue; Vector2i a = new Vector2i(x + xi, y + yi); double gCost = current.gCost + (getDistance(current.tile, a) == 1 ? 1 : 0.95); double hCost = getDistance(a, goal); Node node = new Node(a, current, gCost, hCost); - if(isVectorInList(closedList, a) && gCost >= node.gCost) continue; - if(!isVectorInList(openList, a) || gCost < node.gCost) openList.add(node); + if (isVectorInList(closedList, a) && gCost >= node.gCost) continue; + if (!isVectorInList(openList, a) || gCost < node.gCost) openList.add(node); } } closedList.clear(); return null; } - private boolean isVectorInList(List list, Vector2i vector){ - for(Node n : list){ - if(n.tile.equals(vector)) return true; + private boolean isVectorInList(List list, Vector2i vector) { + for (Node n : list) { + if (n.tile.equals(vector)) return true; } return false; } - private double getDistance(Vector2i tile, Vector2i goal){ + private double getDistance(Vector2i tile, Vector2i goal) { double dx = tile.getX() - goal.getX(); double dy = tile.getY() - goal.getY(); return Math.sqrt(dx * dx + dy * dy); } - public List getEntities(Entity e, int radius){ - List result = new ArrayList(); + @Deprecated + public List getEntities(Entity e, int radius) { + List result = new ArrayList<>(); int ex = (int) e.getX(); int ey = (int) e.getY(); - for (int i = 0; i < entities.size(); i++) { - Entity entity = entities.get(i); + for (Entity entity : entities) { int x = (int) entity.getX(); int y = (int) entity.getY(); int dx = Math.abs(x - ex); int dy = Math.abs(y - ey); - double distance = Math.sqrt((dx*2) + (dy*2)); - if(distance <= radius){ + double distance = Math.sqrt((dx * 2) + (dy * 2)); + if (distance <= radius) { result.add(entity); } } return result; } - public List getPlayers(Entity e, int radius){ - List entities = getEntities(e, radius); - List result = new ArrayList(); - for (int i = 0; i < entities.size(); i++) { - if (entities.get(i) instanceof Player) { - result.add((Player) entities.get(i)); - } - } - return result; - } + public int getWidth() { return width; diff --git a/src/com/redomar/game/lib/Either.java b/src/com/redomar/game/lib/Either.java index de2c608..edf658f 100644 --- a/src/com/redomar/game/lib/Either.java +++ b/src/com/redomar/game/lib/Either.java @@ -4,35 +4,104 @@ import org.jetbrains.annotations.NotNull; import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Function; +@SuppressWarnings({"OptionalUsedAsFieldOrParameterType", "OptionalGetWithoutIsPresent", "unused"}) public class Either { + private final Optional left; private final Optional right; - private Either(final Optional left, final Optional right) { + public Either(final Optional left, final Optional right) { this.left = left; this.right = right; } @Contract("_ -> new") - static @NotNull Either left(final L value) { + public static @NotNull Either left(final L value) { return new Either<>(Optional.of(value), Optional.empty()); } @Contract("_ -> new") - static @NotNull Either right(final R value) { - return new Either<>(Optional.empty(), Optional.of(value)); + public static @NotNull Either right(final R value) { + return new Either<>(Optional.empty(), Optional.ofNullable(value)); + } + + public static Either tryCatch(CheckedRunnable runnable) { + try { + runnable.run(); + return Either.right(null); + } catch (Exception e) { + return Either.left(e); + } + } + + public static Either tryCatch(CheckedFunction function) { + try { + return Either.right(function.apply()); + } catch (Exception e) { + return Either.left(e); + } } - boolean isLeft() { + public static Either tryCatch(CheckedSupplier supplier) { + try { + return Either.right(supplier.get()); + } catch (Exception e) { + return Either.left(e); + } + } + + public boolean isLeft() { return left.isPresent(); } - L getLeft() { + public L getLeft() { return left.get(); } - R getRight() { + public R getRight() { return right.get(); } + + public void either(Consumer leftConsumer, Consumer rightConsumer) { + if (isLeft()) { + leftConsumer.accept(getLeft()); + } else { + rightConsumer.accept(getRight()); + } + } + + public T either(Function leftFunction, Function rightFunction) { + if (isLeft()) { + return leftFunction.apply(getLeft()); + } else { + return rightFunction.apply(getRight()); + } + } + + public Either map(Function mapper) { + if (isLeft()) { + return Either.left(getLeft()); + } else { + return Either.right(mapper.apply(getRight())); + } + } + + @FunctionalInterface + public interface CheckedRunnable { + void run() throws Exception; + } + + @FunctionalInterface + public interface CheckedSupplier { + T get() throws Exception; + } + + @FunctionalInterface + public interface CheckedFunction { + T apply() throws Exception; + } + } diff --git a/src/com/redomar/game/lib/Keys.java b/src/com/redomar/game/lib/Keys.java deleted file mode 100644 index 3533e40..0000000 --- a/src/com/redomar/game/lib/Keys.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.redomar.game.lib; - -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; - -import com.redomar.game.Game; - -public class Keys implements KeyListener { - public Keys(Game game) { - game.addKeyListener(this); - } - - public class Key { - private int numTimesPressed = 0; - private boolean pressed = false; - - public int getNumTimesPressed() { - return numTimesPressed; - } - - public boolean isPressed() { - return pressed; - } - - public void toggle(boolean isPressed) { - pressed = isPressed; - if (isPressed) { - numTimesPressed++; - } - } - } - - private Key up = new Key(); - private Key down = new Key(); - - public void keyPressed(KeyEvent arg0) { - - } - - public void keyReleased(KeyEvent arg0) { - - } - - public void keyTyped(KeyEvent arg0) { - - } - - public void toggleKey(int keyCode, boolean isPressed) { - if (keyCode == KeyEvent.VK_W || keyCode == KeyEvent.VK_UP) { - up.toggle(isPressed); - } - if (keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_DOWN) { - getDown().toggle(isPressed); - } - } - - public Key getUp() { - return up; - } - - public void setUp(Key up) { - this.up = up; - } - - public Key getDown() { - return down; - } - - public void setDown(Key down) { - this.down = down; - } - -} diff --git a/src/com/redomar/game/script/PrintToLog.java b/src/com/redomar/game/log/PrintToLog.java similarity index 82% rename from src/com/redomar/game/script/PrintToLog.java rename to src/com/redomar/game/log/PrintToLog.java index 6927fdf..e3622e4 100644 --- a/src/com/redomar/game/script/PrintToLog.java +++ b/src/com/redomar/game/log/PrintToLog.java @@ -1,4 +1,4 @@ -package com.redomar.game.script; +package com.redomar.game.log; import java.io.File; import java.io.FileNotFoundException; @@ -8,7 +8,7 @@ public class PrintToLog { private static PrintWriter printer; - private File url; + private final File url; public PrintToLog(String url) { this.url = new File(url); @@ -25,11 +25,11 @@ private void initiate() { printer = new PrintWriter(new FileOutputStream(url, true)); } catch (FileNotFoundException e) { //throw new FileNotFoundException(); - System.err.println(e); + System.err.println(e.getMessage()); } } - public File getUrl(){ + public File getUrl() { return this.url; } } diff --git a/src/com/redomar/game/log/PrintTypes.java b/src/com/redomar/game/log/PrintTypes.java new file mode 100644 index 0000000..d0ea642 --- /dev/null +++ b/src/com/redomar/game/log/PrintTypes.java @@ -0,0 +1,5 @@ +package com.redomar.game.log; + +public enum PrintTypes { + GAME, LEVEL, ENTITY, INPUT, MUSIC, NETWORK, SERVER, ERROR, TEST +} diff --git a/src/com/redomar/game/script/Printer.java b/src/com/redomar/game/log/Printer.java similarity index 98% rename from src/com/redomar/game/script/Printer.java rename to src/com/redomar/game/log/Printer.java index 7333bc3..1ec777e 100644 --- a/src/com/redomar/game/script/Printer.java +++ b/src/com/redomar/game/log/Printer.java @@ -1,4 +1,4 @@ -package com.redomar.game.script; +package com.redomar.game.log; import com.redomar.game.lib.Time; diff --git a/src/com/redomar/game/HelpMenu.java b/src/com/redomar/game/menu/HelpMenu.java similarity index 98% rename from src/com/redomar/game/HelpMenu.java rename to src/com/redomar/game/menu/HelpMenu.java index 101e65a..0979621 100644 --- a/src/com/redomar/game/HelpMenu.java +++ b/src/com/redomar/game/menu/HelpMenu.java @@ -1,4 +1,4 @@ -package com.redomar.game; +package com.redomar.game.menu; import javax.imageio.ImageIO; import javax.swing.*; diff --git a/src/com/redomar/game/menu/Menu.java b/src/com/redomar/game/menu/Menu.java index 15b3283..7cd0a25 100644 --- a/src/com/redomar/game/menu/Menu.java +++ b/src/com/redomar/game/menu/Menu.java @@ -2,8 +2,8 @@ import com.redomar.game.Game; import com.redomar.game.audio.AudioHandler; +import com.redomar.game.event.Mouse; import com.redomar.game.lib.Font; -import com.redomar.game.lib.Mouse; import com.thehowtotutorial.splashscreen.JSplash; import javax.swing.*; diff --git a/src/com/redomar/game/menu/MenuInput.java b/src/com/redomar/game/menu/MenuInput.java index 599f15e..ea4f60b 100644 --- a/src/com/redomar/game/menu/MenuInput.java +++ b/src/com/redomar/game/menu/MenuInput.java @@ -1,7 +1,6 @@ package com.redomar.game.menu; import com.redomar.game.Game; -import com.redomar.game.HelpMenu; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; diff --git a/src/com/redomar/game/menu/PopUp.java b/src/com/redomar/game/menu/PopUp.java new file mode 100644 index 0000000..3f35171 --- /dev/null +++ b/src/com/redomar/game/menu/PopUp.java @@ -0,0 +1,22 @@ +package com.redomar.game.menu; + +import com.redomar.game.Game; + +import javax.swing.*; + +public class PopUp { + + public boolean active; + + public PopUp() { + active = true; + } + + public int Warn(String msg) { + Object[] options = {"Continue"}; + if (active) { + JFrame frame = Game.getFrame(); + return JOptionPane.showOptionDialog(frame, msg, "Notice", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]); + } else return 1; + } +} diff --git a/src/com/redomar/game/net/GameClient.java b/src/com/redomar/game/net/GameClient.java index 62225bd..6fb0f2f 100644 --- a/src/com/redomar/game/net/GameClient.java +++ b/src/com/redomar/game/net/GameClient.java @@ -7,8 +7,8 @@ import com.redomar.game.net.packets.Packet00Login; import com.redomar.game.net.packets.Packet01Disconnect; import com.redomar.game.net.packets.Packet02Move; -import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printer; +import com.redomar.game.log.PrintTypes; +import com.redomar.game.log.Printer; import java.io.IOException; import java.net.*; @@ -31,21 +31,6 @@ public GameClient(Game game, String ipAddress) { } } - public void run() { - while (true) { - byte[] data = new byte[1024]; - DatagramPacket packet = new DatagramPacket(data, data.length); - try { - socket.receive(packet); - } catch (IOException e) { - e.printStackTrace(); - break; - } - this.parsePacket(packet.getData(), packet.getAddress(), packet.getPort()); - System.out.println("SERVER > " + new String(packet.getData())); - } - } - private void parsePacket(byte[] data, InetAddress address, int port) { String message = new String(data).trim(); PacketTypes type = Packet.lookupPacket(message.substring(0, 2)); @@ -65,7 +50,6 @@ private void parsePacket(byte[] data, InetAddress address, int port) { break; case MOVE: packet = new Packet02Move(data); - this.handleMove((Packet02Move) packet); break; } } @@ -76,10 +60,6 @@ private void handleLogin(Packet00Login packet, InetAddress address, int port) { Game.getLevel().addEntity(player); } - private void handleMove(Packet02Move packet) { - Game.getLevel().movePlayer(packet.getUsername(), packet.getX(), packet.getY(), packet.getNumSteps(), packet.isMoving(), packet.getMovingDir()); - } - public void sendData(byte[] data) { DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 1331); try { diff --git a/src/com/redomar/game/net/GameServer.java b/src/com/redomar/game/net/GameServer.java index 5091bb4..bd96e00 100644 --- a/src/com/redomar/game/net/GameServer.java +++ b/src/com/redomar/game/net/GameServer.java @@ -2,13 +2,13 @@ import com.redomar.game.Game; import com.redomar.game.entities.PlayerMP; +import com.redomar.game.log.PrintTypes; +import com.redomar.game.log.Printer; import com.redomar.game.net.packets.Packet; import com.redomar.game.net.packets.Packet.PacketTypes; import com.redomar.game.net.packets.Packet00Login; import com.redomar.game.net.packets.Packet01Disconnect; import com.redomar.game.net.packets.Packet02Move; -import com.redomar.game.script.PrintTypes; -import com.redomar.game.script.Printer; import java.io.IOException; import java.net.DatagramPacket; diff --git a/src/com/redomar/game/script/PopUp.java b/src/com/redomar/game/script/PopUp.java deleted file mode 100644 index 2f69fa2..0000000 --- a/src/com/redomar/game/script/PopUp.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.redomar.game.script; - -import com.redomar.game.Game; - -import javax.swing.*; - -public class PopUp{ - - private JFrame frame; - public boolean active; - - public PopUp(){ - active = true; - } - - public int Warn(String msg){ - Object[] options = {"Continue"}; - if (active) { - frame = Game.getFrame(); - return JOptionPane.showOptionDialog(frame, msg, "Notice", JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, - null, options, options[0]); - } - else - return 1; - } -} diff --git a/src/com/redomar/game/script/PrintTypes.java b/src/com/redomar/game/script/PrintTypes.java deleted file mode 100644 index e28753a..0000000 --- a/src/com/redomar/game/script/PrintTypes.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.redomar.game.script; - -public enum PrintTypes { - GAME, - LEVEL, - ENTITY, - INPUT, - MUSIC, - NETWORK, - SERVER, - ERROR, - TEST -} diff --git a/test/com/redomar/game/log/PopUpTest.java b/test/com/redomar/game/log/PopUpTest.java new file mode 100644 index 0000000..3ccb68d --- /dev/null +++ b/test/com/redomar/game/log/PopUpTest.java @@ -0,0 +1,23 @@ +package com.redomar.game.log; + +import com.redomar.game.menu.PopUp; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PopUpTest { + private PopUp popUp; + + @Before + public void setUp() { + popUp = new PopUp(); + popUp.active = false; + } + + @Test + public void warnIntEfflux() { + assertEquals(1, popUp.Warn("TEST")); + } + +} diff --git a/test/com/redomar/game/script/PrintToLogTest.java b/test/com/redomar/game/log/PrintToLogTest.java similarity index 86% rename from test/com/redomar/game/script/PrintToLogTest.java rename to test/com/redomar/game/log/PrintToLogTest.java index ecc651e..f38dda5 100644 --- a/test/com/redomar/game/script/PrintToLogTest.java +++ b/test/com/redomar/game/log/PrintToLogTest.java @@ -1,13 +1,12 @@ -package com.redomar.game.script; +package com.redomar.game.log; import org.junit.Test; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** * Created by Mohamed on 23/08/2016. - * + *

* This file tests the com.redomar.game.script.PrintToLog class */ public class PrintToLogTest { diff --git a/test/com/redomar/game/script/PrinterTest.java b/test/com/redomar/game/log/PrinterTest.java similarity index 96% rename from test/com/redomar/game/script/PrinterTest.java rename to test/com/redomar/game/log/PrinterTest.java index 09a2deb..187f524 100644 --- a/test/com/redomar/game/script/PrinterTest.java +++ b/test/com/redomar/game/log/PrinterTest.java @@ -1,4 +1,4 @@ -package com.redomar.game.script; +package com.redomar.game.log; import org.junit.After; import org.junit.Before; diff --git a/test/com/redomar/game/script/PopUpTest.java b/test/com/redomar/game/script/PopUpTest.java deleted file mode 100644 index e4081ca..0000000 --- a/test/com/redomar/game/script/PopUpTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.redomar.game.script; - -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; - -public class PopUpTest { - private PopUp popUp; - - @Before - public void setUp() throws Exception { - popUp = new PopUp(); - popUp.active = false; - } - - @Test - public void warnIntEfflux() throws Exception { - assertEquals(1,popUp.Warn("TEST")); - } - -} From e9f9f67087718027a0db06f6ab8c6e0994de3232 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Fri, 6 Jan 2023 23:46:49 +0000 Subject: [PATCH 07/12] #22 Updated POM --- build.gradle | 8 ++++---- pom.xml | 6 +++--- src/com/redomar/game/entities/projectiles/Small.java | 4 +--- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 2b7bbff..d2ea902 100644 --- a/build.gradle +++ b/build.gradle @@ -21,10 +21,10 @@ sourceSets{ } dependencies{ - implementation 'org.apache.commons:commons-text:+' - implementation 'org.apache.commons:commons-lang3:3.+' + implementation 'org.apache.commons:commons-text:1.10.0' + implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'org.jetbrains:annotations:23.0.0' - testImplementation 'junit:junit:4.13' + testImplementation 'junit:junit:4.13.1' implementation files('res/jars/JSplashScreen.jar') } @@ -33,7 +33,7 @@ jar { manifest.attributes 'Main-Class' : 'com.redomar.game.Launcher' } -task createPom { +tasks.register('createPom') { pom { project { groupId 'com.redomar.game' diff --git a/pom.xml b/pom.xml index 37a91d7..308fce5 100644 --- a/pom.xml +++ b/pom.xml @@ -17,13 +17,13 @@ org.apache.commons commons-text - + + 1.10.0 runtime org.apache.commons commons-lang3 - 3.+ + 3.12.0 runtime @@ -35,7 +35,7 @@ junit junit - 4.13 + 4.13.1 test diff --git a/src/com/redomar/game/entities/projectiles/Small.java b/src/com/redomar/game/entities/projectiles/Small.java index 12d75bf..e1c8054 100644 --- a/src/com/redomar/game/entities/projectiles/Small.java +++ b/src/com/redomar/game/entities/projectiles/Small.java @@ -25,10 +25,8 @@ public Small(LevelHandler level, int x, int y, double dir) { AudioHandler smallSound = new AudioHandler(smallShot); smallSound.setVolume(-15); smallSound.play(); - } catch (NullPointerException e) { - entityPrinter.cast().exception(e.toString()).exception("Unable to load Audio file " + smallShot.getName()); } catch (Exception e) { - throw new RuntimeException(e); + entityPrinter.cast().exception(e.toString()).exception("Unable to load Audio file " + smallShot.getName()); } } From b2e9fdec82be6d5d2a9c503e5638c47da0faac42 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Sat, 7 Jan 2023 06:57:40 +0000 Subject: [PATCH 08/12] #22 Dropped Gradle for Maven --- .gitignore | 2 + build.gradle | 54 -------- gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 0 bytes gradle/wrapper/gradle-wrapper.properties | 5 - pom.xml | 123 ++++++++++++++++-- src/com/redomar/game/Game.java | 2 +- src/com/redomar/game/audio/AudioHandler.java | 23 +++- src/com/redomar/game/log/Printer.java | 11 ++ src/com/redomar/game/menu/Menu.java | 10 +- .../redomar/game/audio/AudioHandlerTest.java | 24 ++-- 10 files changed, 169 insertions(+), 85 deletions(-) delete mode 100644 build.gradle delete mode 100644 gradle/wrapper/gradle-wrapper.jar delete mode 100644 gradle/wrapper/gradle-wrapper.properties diff --git a/.gitignore b/.gitignore index 9ced6d8..25ad1df 100644 --- a/.gitignore +++ b/.gitignore @@ -190,3 +190,5 @@ out/ .log.txt /.gradle/ Package game.png +target/* +.PrintType-TEST.txt \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index d2ea902..0000000 --- a/build.gradle +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id 'com.adarshr.test-logger' version '2.0.0' - id "nebula.lint" version "16.0.2" -} - -repositories{ - mavenCentral() -} - -apply plugin: 'java' -apply plugin: 'maven' - -sourceSets{ - main{ - java.srcDirs = ['src'] - resources.srcDirs = ['res'] - } - test{ - java.srcDirs = ['test'] - } -} - -dependencies{ - implementation 'org.apache.commons:commons-text:1.10.0' - implementation 'org.apache.commons:commons-lang3:3.12.0' - implementation 'org.jetbrains:annotations:23.0.0' - testImplementation 'junit:junit:4.13.1' - implementation files('res/jars/JSplashScreen.jar') -} - -jar { - from configurations.compileClasspath.collect { zipTree it } - manifest.attributes 'Main-Class' : 'com.redomar.game.Launcher' -} - -tasks.register('createPom') { - pom { - project { - groupId 'com.redomar.game' - artifactId 'javagame' - version 'Alpha 1.8.5' - - inceptionYear '2013' - licenses { - license { - name 'GNU AFFERO GENERAL PUBLIC LICENSE 3.0' - url 'https://www.gnu.org/licenses/agpl-3.0.txt' - distribution 'repo' - } - } - - } - }.writeTo("pom.xml") -} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index cc4fdc293d0e50b0ad9b65c16e7ddd1db2f6025b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58702 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

@up^y4&I8N>~wvL%f(S2W%NN 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 D613UA diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 5028f28..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/pom.xml b/pom.xml index 308fce5..9b46a42 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,11 @@ - + 4.0.0 com.redomar.game javagame - Alpha 1.8.5 + Alpha 1.8.6 2013 @@ -13,30 +14,136 @@ repo + + + local-maven-repo + file://${project.basedir}/res/jars + + org.apache.commons commons-text 1.10.0 - runtime org.apache.commons commons-lang3 3.12.0 - runtime org.jetbrains annotations - 23.0.0 - runtime + 23.1.0 + + + com.thehowtotutorial.splashscreen + JSplashScreen + 1.0 junit junit - 4.13.1 + 4.13.2 test + + 8 + 8 + UTF-8 + UTF-8 + + + src + + + res + + + + test + + + + org.apache.maven.plugins + maven-resources-plugin + 2.6 + + false + + ${*} + @ + + UTF-8 + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.3.0 + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/lib + false + false + true + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + + true + lib/ + com.redomar.game.Launcher + + + + + + com.thehowtotutorial.splashscreen + JSplashScreen + 1.0 + + + + + org.apache.maven.plugins + maven-install-plugin + 2.4 + + + install-external-non-maven-jar-MWS-Client-into-local-maven-repo + clean + + default + com.thehowtotutorial.splashscreen + JSplashScreen + 1.0 + ${project.basedir}/res/jars/JSplashScreen.jar + jar + true + + + install-file + + + + + + diff --git a/src/com/redomar/game/Game.java b/src/com/redomar/game/Game.java index 20b3994..4cfd945 100644 --- a/src/com/redomar/game/Game.java +++ b/src/com/redomar/game/Game.java @@ -34,7 +34,7 @@ public class Game extends Canvas implements Runnable { // Setting the size and name of the frame/canvas private static final long serialVersionUID = 1L; - private static final String game_Version = "v1.8.5 Alpha"; + private static final String game_Version = "v1.8.6 Alpha"; private static final int WIDTH = 160; private static final int HEIGHT = (WIDTH / 3 * 2); private static final int SCALE = 3; diff --git a/src/com/redomar/game/audio/AudioHandler.java b/src/com/redomar/game/audio/AudioHandler.java index ae710bf..b3d8e2c 100644 --- a/src/com/redomar/game/audio/AudioHandler.java +++ b/src/com/redomar/game/audio/AudioHandler.java @@ -5,14 +5,15 @@ import org.jetbrains.annotations.NotNull; import javax.sound.sampled.*; +import java.io.BufferedInputStream; import java.io.File; -import java.util.Arrays; +import java.io.IOException; +import java.io.InputStream; import java.util.Objects; - public class AudioHandler { - public final Printer musicPrinter = new Printer(PrintTypes.MUSIC); + public static final Printer musicPrinter = new Printer(PrintTypes.MUSIC); private Clip clip; private boolean active = false; private boolean music = false; @@ -43,20 +44,32 @@ private void check(String path) { } } + /** + * Initialises an audio clip from the specified file path. + * + * @param path the file path of the audio clip + */ private void initiate(String path) { try { - AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(Objects.requireNonNull(AudioHandler.class.getResourceAsStream(path))); + InputStream inputStream = new BufferedInputStream(Objects.requireNonNull(AudioHandler.class.getResourceAsStream(path))); + AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(inputStream); + audioInputStream.mark(Integer.MAX_VALUE); AudioFormat baseFormat = audioInputStream.getFormat(); AudioFormat decodeFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16, baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false); AudioInputStream decodedAudioInputStream = AudioSystem.getAudioInputStream(decodeFormat, audioInputStream); clip = AudioSystem.getClip(); clip.open(decodedAudioInputStream); + } catch (IOException e) { + musicPrinter.cast().exception("Audio file not found " + path); + musicPrinter.cast().exception(e.getMessage()); + } catch (Exception e) { - System.err.println(Arrays.toString(e.getStackTrace())); musicPrinter.print("Audio Failed to initiate", PrintTypes.ERROR); + musicPrinter.cast().exception(e.getMessage()); } } + public void play() { try { if (clip == null) return; diff --git a/src/com/redomar/game/log/Printer.java b/src/com/redomar/game/log/Printer.java index 1ec777e..73d2c3b 100644 --- a/src/com/redomar/game/log/Printer.java +++ b/src/com/redomar/game/log/Printer.java @@ -12,6 +12,7 @@ public class Printer { private PrintTypes type; private String message; private boolean evalTypeAsException = false; + private boolean mute = false; public Printer() { this.type = PrintTypes.GAME; @@ -53,6 +54,7 @@ private void printOut() { } logFile.log(String.format("%s%s\t%s", msgTime, msgType, message)); + if (mute) return; String formattedStringForConsole = String.format("%s%s %s%n", msgType, msgTime, message); if (type.equals(PrintTypes.ERROR) || evalTypeAsException) { @@ -79,6 +81,15 @@ public String getMessage() { return message; } + public void mute() { + this.mute = true; + } + + @SuppressWarnings("unused") + public void unmute() { + this.mute = false; + } + /** * Error that keeps the current {@link PrintTypes PrintType } instead of using {@link PrintTypes PrintTypes.ERROR} * diff --git a/src/com/redomar/game/menu/Menu.java b/src/com/redomar/game/menu/Menu.java index 7cd0a25..c78044e 100644 --- a/src/com/redomar/game/menu/Menu.java +++ b/src/com/redomar/game/menu/Menu.java @@ -4,6 +4,7 @@ import com.redomar.game.audio.AudioHandler; import com.redomar.game.event.Mouse; import com.redomar.game.lib.Font; +import com.redomar.game.log.Printer; import com.thehowtotutorial.splashscreen.JSplash; import javax.swing.*; @@ -44,8 +45,13 @@ public static void play() { splash.splashOn(); // Background tasks - Game.setBackgroundMusic(new AudioHandler("/music/Towards The End.wav", true)); - Game.getBackgroundMusic().setVolume(VOLUME_IN_DB); + try { + Game.setBackgroundMusic(new AudioHandler("/music/Towards The End.wav", true)); + Game.getBackgroundMusic().setVolume(VOLUME_IN_DB); + } catch (Exception e) { + Printer printer = new Printer(); + printer.exception(e.getMessage()); + } UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); Game.setAlternateColsR(true); Game.setAlternateColsS(true); diff --git a/test/com/redomar/game/audio/AudioHandlerTest.java b/test/com/redomar/game/audio/AudioHandlerTest.java index 2177145..c17faa7 100644 --- a/test/com/redomar/game/audio/AudioHandlerTest.java +++ b/test/com/redomar/game/audio/AudioHandlerTest.java @@ -5,7 +5,7 @@ import java.io.File; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; /** * Created by Mohamed on 28/08/2016. @@ -13,27 +13,31 @@ */ public class AudioHandlerTest { + @Before + public void before() { + AudioHandler.musicPrinter.mute(); + } + @Test - public void bgMusicExists() throws Exception { + public void bgMusicExists() { File sfx = new File("res/music/Towards The End.mp3"); assertTrue(sfx.exists()); } @Test(expected = NullPointerException.class) - public void expectReturnExceptionFileEmptyDir(){ + public void expectReturnExceptionFileEmptyDir() { File empty = new File(""); - AudioHandler audio = new AudioHandler(empty); + new AudioHandler(empty); } @Test(expected = NullPointerException.class) - public void expectReturnExceptionFileEmptyPath(){ - AudioHandler audio = new AudioHandler(""); + public void expectReturnExceptionFileEmptyPath() { + new AudioHandler(""); } - @Test - public void tryInitiatingAndPlayingNonExistingFile(){ - AudioHandler audio = new AudioHandler("//"); - audio.play(); + @Test() + public void tryInitiatingAndPlayingNonExistingFile() { + new AudioHandler("//").play(); } } \ No newline at end of file From b257bc7782135d40b659e30009bd36508c262420 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Sat, 7 Jan 2023 07:05:51 +0000 Subject: [PATCH 09/12] #22 Dropped Gradle for Maven - Actions update --- .github/workflows/gradle.yml | 17 ----------------- .github/workflows/maven.yml | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 17 deletions(-) delete mode 100644 .github/workflows/gradle.yml create mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml deleted file mode 100644 index 0e12312..0000000 --- a/.github/workflows/gradle.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Java CI - -on: [push] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - name: Build with Gradle - run: ./gradlew build diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..2618579 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,23 @@ +name: Java CI with Maven + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml + + # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive + - name: Update dependency graph + uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 From a9603fc1692c089869bf9058d247515beda4a442 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Sat, 7 Jan 2023 07:26:42 +0000 Subject: [PATCH 10/12] #22 Dropped Gradle for Maven - Actions update fix jar --- .github/workflows/maven.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 2618579..fc9bfe5 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -15,9 +15,12 @@ jobs: java-version: '8' distribution: 'temurin' cache: maven - - name: Build with Maven + - name: Build with Maven - Install + run: mvn install:install-file -Dfile=home/runner/work/JavaGame/JavaGame/res/jars/JSplashScreen.jar -DgroupId=com.thehowtotutorial.splashscreen -DartifactId=JSplashScreen -Dversion=1.0 -Dpackaging=jar + - name: Build with Maven - From Pom run: mvn -B package --file pom.xml - # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive + + # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive - name: Update dependency graph uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 From a13a1096b8341f0b74d54a171d96358ec2707365 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Sat, 7 Jan 2023 07:28:06 +0000 Subject: [PATCH 11/12] #22 Dropped Gradle for Maven - Actions update add res --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index fc9bfe5..a0f370a 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -16,7 +16,7 @@ jobs: distribution: 'temurin' cache: maven - name: Build with Maven - Install - run: mvn install:install-file -Dfile=home/runner/work/JavaGame/JavaGame/res/jars/JSplashScreen.jar -DgroupId=com.thehowtotutorial.splashscreen -DartifactId=JSplashScreen -Dversion=1.0 -Dpackaging=jar + run: mvn install:install-file -Dfile=res/jars/JSplashScreen.jar -DgroupId=com.thehowtotutorial.splashscreen -DartifactId=JSplashScreen -Dversion=1.0 -Dpackaging=jar - name: Build with Maven - From Pom run: mvn -B package --file pom.xml From 4afb7251038dd567d82958da144cbbdb22b91c47 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Sat, 7 Jan 2023 08:50:25 +0000 Subject: [PATCH 12/12] #22 Code formatting --- src/com/redomar/game/Launcher.java | 6 +-- src/com/redomar/game/gfx/Colours.java | 3 +- src/com/redomar/game/gfx/Screen.java | 44 ++++++++----------- src/com/redomar/game/gfx/SpriteSheet.java | 16 +++---- src/com/redomar/game/level/LevelHandler.java | 1 - src/com/redomar/game/level/Node.java | 2 +- .../game/level/tiles/AnimatedTile.java | 22 ++++------ .../game/level/tiles/BasicSolidTile.java | 8 ++-- .../redomar/game/level/tiles/BasicTile.java | 8 ++-- src/com/redomar/game/lib/Font.java | 9 ++-- src/com/redomar/game/lib/SleepThread.java | 2 +- src/com/redomar/game/lib/utils/Vector2i.java | 18 +++----- src/com/redomar/game/objects/Inventory.java | 9 ++-- .../game/objects/InventoryHandler.java | 4 -- .../redomar/game/objects/InventoryWindow.java | 13 +++--- src/com/redomar/game/objects/Items.java | 5 +-- src/com/redomar/game/scenes/Scene.java | 8 ++-- 17 files changed, 71 insertions(+), 107 deletions(-) diff --git a/src/com/redomar/game/Launcher.java b/src/com/redomar/game/Launcher.java index 224ac35..784b9f9 100644 --- a/src/com/redomar/game/Launcher.java +++ b/src/com/redomar/game/Launcher.java @@ -2,10 +2,8 @@ import com.redomar.game.menu.Menu; -public class Launcher -{ - public static void main(String[] args) - { +public class Launcher { + public static void main(String[] args) { new Menu().start(); } } diff --git a/src/com/redomar/game/gfx/Colours.java b/src/com/redomar/game/gfx/Colours.java index 630ff16..c345423 100644 --- a/src/com/redomar/game/gfx/Colours.java +++ b/src/com/redomar/game/gfx/Colours.java @@ -3,8 +3,7 @@ public class Colours { public static int get(int colour1, int colour2, int colour3, int colour4) { - return (get(colour4) << 24) + (get(colour3) << 16) - + (get(colour2) << 8) + (get(colour1)); + return (get(colour4) << 24) + (get(colour3) << 16) + (get(colour2) << 8) + (get(colour1)); } private static int get(int colour) { diff --git a/src/com/redomar/game/gfx/Screen.java b/src/com/redomar/game/gfx/Screen.java index 50d7614..19a501b 100644 --- a/src/com/redomar/game/gfx/Screen.java +++ b/src/com/redomar/game/gfx/Screen.java @@ -7,22 +7,19 @@ public class Screen { private static final byte BIT_MIRROR_X = 0x01; private static final byte BIT_MIRROR_Y = 0x02; - + private final SpriteSheet sheet; private int[] pixels; - private int xOffset = 0; private int yOffset = 0; - private int width; private int height; - private SpriteSheet sheet; - /** * Constructs the draw area - * @param width width of the screen + * + * @param width width of the screen * @param height height of the screen - * @param sheet Sprite-sheet selector. Constructed Spritesheet needs to be here, + * @param sheet Sprite-sheet selector. Constructed sprite sheet needs to be here, * Sprite-sheet cp requires path only. */ public Screen(int width, int height, SpriteSheet sheet) { @@ -34,23 +31,24 @@ public Screen(int width, int height, SpriteSheet sheet) { setPixels(new int[width * height]); } + @SuppressWarnings("unused") public static int getMapWidthMask() { return MAP_WIDTH_MASK; } /** - * Rendering sprites from Spritesheet onto the game world. - * Render contstucter requires - * @param xPos X Postion of subject - * @param yPos Y Postion of subject - * @param tile tile location. e.g 7 * 32 + 1 is the oblong bullet on the 7th row 2nd colomn - * @param colour Using established colouring nomanclature. i.e. use com.redomar.game.gfx.Colours - * @param mirrorDir flip Direction: 0x01 flip verticle, 0x02 flip horizontal. - * @param scale Scale + * Rendering sprites from sprite sheet onto the game world. + * Render constructor requires + * + * @param xPos X Position of subject + * @param yPos Y Position of subject + * @param tile tile location. e.g 7 * 32 + 1 is the oblong bullet on the 7th row 2nd column + * @param colour Using established colouring nomenclature. i.e. use com.redomar.game.gfx.Colours + * @param mirrorDir flip Direction: 0x01 flip vertical, 0x02 flip horizontal. + * @param scale Scale */ - public void render(int xPos, int yPos, int tile, int colour, int mirrorDir, - int scale) { + public void render(int xPos, int yPos, int tile, int colour, int mirrorDir, int scale) { xPos -= xOffset; yPos -= yOffset; @@ -80,26 +78,22 @@ public void render(int xPos, int yPos, int tile, int colour, int mirrorDir, int xPixel = x + xPos + (x * scaleMap) - ((scaleMap << 3) / 2); - int col = (colour >> (sheet.pixels[xSheet + ySheet - * sheet.getWidth() + tileOffset] * 8)) & 255; + int col = (colour >> (sheet.pixels[xSheet + ySheet * sheet.getWidth() + tileOffset] * 8)) & 255; if (col < 255) { for (int yScale = 0; yScale < scale; yScale++) { - if (yPixel + yScale < 0 - | yPixel + yScale >= getHeight()) { + if (yPixel + yScale < 0 | yPixel + yScale >= getHeight()) { continue; } for (int xScale = 0; xScale < scale; xScale++) { - if (xPixel + xScale < 0 - | xPixel + xScale >= getWidth()) { + if (xPixel + xScale < 0 | xPixel + xScale >= getWidth()) { continue; } - getPixels()[(xPixel + xScale) + (yPixel + yScale) - * getWidth()] = col; + getPixels()[(xPixel + xScale) + (yPixel + yScale) * getWidth()] = col; } } diff --git a/src/com/redomar/game/gfx/SpriteSheet.java b/src/com/redomar/game/gfx/SpriteSheet.java index f6f34c9..6d0faa4 100644 --- a/src/com/redomar/game/gfx/SpriteSheet.java +++ b/src/com/redomar/game/gfx/SpriteSheet.java @@ -1,23 +1,21 @@ package com.redomar.game.gfx; +import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.IOException; - -import javax.imageio.ImageIO; +import java.util.Objects; public class SpriteSheet { + public int[] pixels; private String path; private int width; - private int height; - - public int[] pixels; public SpriteSheet(String path) { BufferedImage image = null; try { - image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path)); + image = ImageIO.read(Objects.requireNonNull(SpriteSheet.class.getResourceAsStream(path))); } catch (IOException e) { e.printStackTrace(); } @@ -28,7 +26,7 @@ public SpriteSheet(String path) { this.setPath(path); this.setWidth(image.getWidth()); - this.height = image.getHeight(); + int height = image.getHeight(); pixels = image.getRGB(0, 0, width, height, null, 0, width); @@ -36,11 +34,9 @@ public SpriteSheet(String path) { pixels[i] = (pixels[i] & 0xff) / 64; // removes alpha (transparency) } - for (int i = 0; i < 8; i++) { - // System.out.println(pixels[i]); - } } + @SuppressWarnings("unused") public String getPath() { return path; } diff --git a/src/com/redomar/game/level/LevelHandler.java b/src/com/redomar/game/level/LevelHandler.java index acf471a..f25e61d 100644 --- a/src/com/redomar/game/level/LevelHandler.java +++ b/src/com/redomar/game/level/LevelHandler.java @@ -286,7 +286,6 @@ public List getEntities(Entity e, int radius) { } - public int getWidth() { return width; } diff --git a/src/com/redomar/game/level/Node.java b/src/com/redomar/game/level/Node.java index 1f4dc3a..02ed733 100644 --- a/src/com/redomar/game/level/Node.java +++ b/src/com/redomar/game/level/Node.java @@ -8,7 +8,7 @@ public class Node { public Node parent; public double fCost, gCost, hCost; - public Node(Vector2i tile, Node parent, double gCost, double hCost){ + public Node(Vector2i tile, Node parent, double gCost, double hCost) { this.tile = tile; this.parent = parent; this.gCost = gCost; diff --git a/src/com/redomar/game/level/tiles/AnimatedTile.java b/src/com/redomar/game/level/tiles/AnimatedTile.java index fa839f3..db3a4dd 100644 --- a/src/com/redomar/game/level/tiles/AnimatedTile.java +++ b/src/com/redomar/game/level/tiles/AnimatedTile.java @@ -2,23 +2,20 @@ public class AnimatedTile extends BasicTile { - private int[][] animationTileCoords; + private final int[][] animationTileCoords; private int currentAnimationIndex; private long lastIterationTime; - private int animationSwitchDelay; + private final int animationSwitchDelay; /** - * - * @param id Unique ID for the Tile - * @param animationCoords A 2D array of all x,y-coordinates in Integers. - * @param tileColour Colours from the SpriteSheet. - * @param levelColour Colours to be displayed in the Game World. + * @param id Unique ID for the Tile + * @param animationCoords A 2D array of all x,y-coordinates in Integers. + * @param tileColour Colours from the SpriteSheet. + * @param levelColour Colours to be displayed in the Game World. * @param animationSwitchDelay Length of time to be delayed to the next frame from the 2D array. */ - public AnimatedTile(int id, int[][] animationCoords, int tileColour, - int levelColour, int animationSwitchDelay) { - super(id, animationCoords[0][0], animationCoords[0][1], tileColour, - levelColour); + public AnimatedTile(int id, int[][] animationCoords, int tileColour, int levelColour, int animationSwitchDelay) { + super(id, animationCoords[0][0], animationCoords[0][1], tileColour, levelColour); this.animationTileCoords = animationCoords; this.currentAnimationIndex = 0; this.lastIterationTime = System.currentTimeMillis(); @@ -28,8 +25,7 @@ public AnimatedTile(int id, int[][] animationCoords, int tileColour, public void tick() { if ((System.currentTimeMillis() - lastIterationTime) >= (animationSwitchDelay)) { lastIterationTime = System.currentTimeMillis(); - currentAnimationIndex = (currentAnimationIndex + 1) - % animationTileCoords.length; + currentAnimationIndex = (currentAnimationIndex + 1) % animationTileCoords.length; this.tileId = (animationTileCoords[currentAnimationIndex][0] + (animationTileCoords[currentAnimationIndex][1] * 32)); } } diff --git a/src/com/redomar/game/level/tiles/BasicSolidTile.java b/src/com/redomar/game/level/tiles/BasicSolidTile.java index a8545fa..220e154 100644 --- a/src/com/redomar/game/level/tiles/BasicSolidTile.java +++ b/src/com/redomar/game/level/tiles/BasicSolidTile.java @@ -5,10 +5,10 @@ public class BasicSolidTile extends BasicTile { /** * This is a solid tile, but does not emit any light. This tile does not have any animations. * - * @param id Unique ID for the Tile - * @param x Specifies the x-coordinate from the SpriteSheet, measured in 8 pixels. Must be 0 - 31 - * @param y Specifies the y-coordinate from the SpriteSheet, measured in 8 pixels. Must be 0 - 31 - * @param tileColour Colours from the SpriteSheet. + * @param id Unique ID for the Tile + * @param x Specifies the x-coordinate from the SpriteSheet, measured in 8 pixels. Must be 0 - 31 + * @param y Specifies the y-coordinate from the SpriteSheet, measured in 8 pixels. Must be 0 - 31 + * @param tileColour Colours from the SpriteSheet. * @param levelColour Colours to be displayed in the Game World. */ public BasicSolidTile(int id, int x, int y, int tileColour, int levelColour) { diff --git a/src/com/redomar/game/level/tiles/BasicTile.java b/src/com/redomar/game/level/tiles/BasicTile.java index c1bb1c4..99f9e44 100644 --- a/src/com/redomar/game/level/tiles/BasicTile.java +++ b/src/com/redomar/game/level/tiles/BasicTile.java @@ -11,10 +11,10 @@ public class BasicTile extends Tile { /** * This is a tile that does not emit light, nor is sold. This tile does not have any animations. * - * @param id Unique ID for the Tile - * @param x Specifies the x-coordinate from the SpriteSheet, measured in 8 pixels. Must be 0 - 31 - * @param y Specifies the y-coordinate from the SpriteSheet, measured in 8 pixels. Must be 0 - 31 - * @param tileColour Colours from the SpriteSheet. + * @param id Unique ID for the Tile + * @param x Specifies the x-coordinate from the SpriteSheet, measured in 8 pixels. Must be 0 - 31 + * @param y Specifies the y-coordinate from the SpriteSheet, measured in 8 pixels. Must be 0 - 31 + * @param tileColour Colours from the SpriteSheet. * @param levelColour Colours to be displayed in the Game World. */ public BasicTile(int id, int x, int y, int tileColour, int levelColour) { diff --git a/src/com/redomar/game/lib/Font.java b/src/com/redomar/game/lib/Font.java index cd659ba..b17de5d 100644 --- a/src/com/redomar/game/lib/Font.java +++ b/src/com/redomar/game/lib/Font.java @@ -6,23 +6,20 @@ public class Font { private static java.awt.Font arial; private static java.awt.Font segoe; - private static String chars = "" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ " - + "0123456789.,:;'\"!?$%()-=+/ "; + private static final String chars = "" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ " + "0123456789.,:;'\"!?$%()-=+/ "; public Font() { Font.setArial(new java.awt.Font("Arial", java.awt.Font.BOLD, 14)); Font.setSegoe(new java.awt.Font("Segoe UI", java.awt.Font.BOLD, 14)); } - public static void render(String msg, Screen screen, int x, int y, - int colour, int scale) { + public static void render(String msg, Screen screen, int x, int y, int colour, int scale) { msg = msg.toUpperCase(); for (int i = 0; i < msg.length(); i++) { int charIndex = chars.indexOf(msg.charAt(i)); if (charIndex >= 0) { - screen.render(x + (i * 8), y, charIndex + 30 * 32, colour, - 0x00, scale); + screen.render(x + (i * 8), y, charIndex + 30 * 32, colour, 0x00, scale); } } } diff --git a/src/com/redomar/game/lib/SleepThread.java b/src/com/redomar/game/lib/SleepThread.java index 7e807eb..7a9ada6 100644 --- a/src/com/redomar/game/lib/SleepThread.java +++ b/src/com/redomar/game/lib/SleepThread.java @@ -2,7 +2,7 @@ import com.redomar.game.Game; -public class SleepThread implements Runnable{ +public class SleepThread implements Runnable { public void run() { try { diff --git a/src/com/redomar/game/lib/utils/Vector2i.java b/src/com/redomar/game/lib/utils/Vector2i.java index 791e232..908301d 100644 --- a/src/com/redomar/game/lib/utils/Vector2i.java +++ b/src/com/redomar/game/lib/utils/Vector2i.java @@ -4,37 +4,31 @@ public class Vector2i { private int x, y; - public Vector2i(){ - set(0, 0); - } - public Vector2i(int x, int y){ + public Vector2i(int x, int y) { set(x, y); } - public Vector2i(Vector2i vector){ - set(vector.x, vector.y); - } - - public Vector2i add(Vector2i vector){ + public Vector2i add(Vector2i vector) { this.x += vector.x; this.y += vector.y; return this; } - public Vector2i subtract(Vector2i vector){ + @SuppressWarnings("unused") + public Vector2i subtract(Vector2i vector) { this.x -= vector.x; this.y -= vector.y; return this; } - public boolean equals(Object object){ + public boolean equals(Object object) { if (!(object instanceof Vector2i)) return false; Vector2i vector = (Vector2i) object; return vector.getX() == this.getX() && vector.getY() == this.getY(); } - public void set(int x, int y){ + public void set(int x, int y) { this.x = x; this.y = y; } diff --git a/src/com/redomar/game/objects/Inventory.java b/src/com/redomar/game/objects/Inventory.java index de45baa..96a24e1 100644 --- a/src/com/redomar/game/objects/Inventory.java +++ b/src/com/redomar/game/objects/Inventory.java @@ -10,7 +10,7 @@ public class Inventory { public static boolean closing; public static boolean reset; public static boolean enabled; - private static InventoryWindow inv_window = new InventoryWindow(); + private static final InventoryWindow inv_window = new InventoryWindow(); public static void activate() { x = (int) Game.getPlayer().getX(); @@ -20,8 +20,7 @@ public static void activate() { if (enabled) { if (!open) { if (!closing) { - System.out.println("Opened\nInside this Bag their is:" - + inside()); + System.out.println("Opened\nInside this Bag their is:" + inside()); open = true; Game.getPlayer().setMoving(false); inv_window.start(); @@ -40,7 +39,7 @@ public static void activate() { } } } else { - if (open == true || reset == true || closing == true) { + if (open || reset || closing) { reset = false; open = false; closing = false; @@ -51,7 +50,7 @@ public static void activate() { private static String inside() { String items = " "; for (Items item : Items.values()) { - items = items + item.toString() + ", "; + items = String.format("%s%s, ", items, item.toString()); } return items; } diff --git a/src/com/redomar/game/objects/InventoryHandler.java b/src/com/redomar/game/objects/InventoryHandler.java index 93b6128..e7b1cdd 100644 --- a/src/com/redomar/game/objects/InventoryHandler.java +++ b/src/com/redomar/game/objects/InventoryHandler.java @@ -7,11 +7,7 @@ public class InventoryHandler implements WindowListener { - @SuppressWarnings("unused") - private DedicatedJFrame frame; - public InventoryHandler(DedicatedJFrame frame) { - this.frame = frame; DedicatedJFrame.getFrameStatic().addWindowListener(this); } diff --git a/src/com/redomar/game/objects/InventoryWindow.java b/src/com/redomar/game/objects/InventoryWindow.java index 30afd00..94d7d45 100644 --- a/src/com/redomar/game/objects/InventoryWindow.java +++ b/src/com/redomar/game/objects/InventoryWindow.java @@ -5,7 +5,7 @@ import java.awt.*; import java.awt.image.BufferStrategy; -public class InventoryWindow implements Runnable{ +public class InventoryWindow implements Runnable { private static final int WIDTH = 160; private static final int HEIGHT = (WIDTH / 3 * 2); @@ -25,13 +25,13 @@ public static void setWindow(InventoryHandler inventoryHandler) { InventoryWindow.window = inventoryHandler; } - public synchronized void start(){ + public synchronized void start() { running = true; setFrame(new DedicatedJFrame(WIDTH, HEIGHT, SCALE, NAME)); new Thread(this, NAME).start(); } - public synchronized void stop(){ + public synchronized void stop() { running = false; } @@ -72,8 +72,7 @@ public void run() { if (System.currentTimeMillis() - lastTimer >= 1000) { lastTimer += 1000; - frame.getFrame().setTitle( - "Frames: " + frames + " Ticks: " + ticks); + frame.getFrame().setTitle("Frames: " + frames + " Ticks: " + ticks); frames = 0; ticks = 0; } @@ -82,14 +81,14 @@ public void run() { private void render() { BufferStrategy bs = frame.getBufferStrategy(); - if(bs == null){ + if (bs == null) { frame.createBufferStrategy(3); return; } Graphics g = bs.getDrawGraphics(); g.setColor(Color.BLACK); - g.fillRect(0, 0, WIDTH*SCALE+10, HEIGHT*SCALE+10); + g.fillRect(0, 0, WIDTH * SCALE + 10, HEIGHT * SCALE + 10); g.setColor(Color.WHITE); g.drawString(NAME, 50, 50); bs.show(); diff --git a/src/com/redomar/game/objects/Items.java b/src/com/redomar/game/objects/Items.java index 2bb4ffc..55f705a 100644 --- a/src/com/redomar/game/objects/Items.java +++ b/src/com/redomar/game/objects/Items.java @@ -1,8 +1,5 @@ package com.redomar.game.objects; public enum Items { - Stick, - Torch, - Sword, - Apple + Stick, Torch, Sword, Apple } diff --git a/src/com/redomar/game/scenes/Scene.java b/src/com/redomar/game/scenes/Scene.java index 0ca0f6d..2b869c6 100644 --- a/src/com/redomar/game/scenes/Scene.java +++ b/src/com/redomar/game/scenes/Scene.java @@ -6,17 +6,17 @@ public class Scene { private int xOffset, yOffset; - private Screen screen; - private LevelHandler level; + private final Screen screen; + private final LevelHandler level; - public Scene(int xOffset, int yOffset, Screen screen, LevelHandler level){ + public Scene(int xOffset, int yOffset, Screen screen, LevelHandler level) { this.xOffset = xOffset; this.yOffset = yOffset; this.screen = screen; this.level = level; } - public void playerScene(){ + public void playerScene() { if (xOffset < 0) { xOffset = 0; }