Skip to main content
Code Review

Return to Question

Bumped by Community user
Tweeted twitter.com/StackCodeReview/status/739977431726055424
added more context to title
Link
Dan95363
  • 143
  • 2
  • 6

Any ways to make my Compacting code more efficient?for World's Hardest Game remake

Post Reopened by Mathieu Guindon
Added source code
Source Link
Dan95363
  • 143
  • 2
  • 6

Game.java

package net.thedanpage.worldshardestgame;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import kuusisto.tinysound.Music;
import kuusisto.tinysound.Sound;
import kuusisto.tinysound.TinySound;
public class Game extends JPanel implements ActionListener {
 
 /** An instance of the game. */
 private static Game game;
 
 /** The timer used for the game's clock. */
 private Timer t = new Timer(5, this);
 
 /** Used for logging information during the game. */
 public final static Logger logger = Logger.getLogger(Game.class.getName());
 
 static String logFilePath = System.getProperty("user.home")
 + "/worldshardestgame/logs/" + new SimpleDateFormat("YY-MM-dd").format(new Date()) + ".log";
 private static final long serialVersionUID = 1L;
 
 /** The frame that the panel goes in. */
 static JFrame frame = new JFrame();
 
 /** The enum instance used for switching the state of the game. */
 static final int INTRO = 0, MAIN_MENU = 1, LEVEL_TITLE = 2, LEVEL = 3;
 
 /** The integer used for the game state. */
 static int gameState = INTRO;
 
 /** Used for when the instructions should be shown. */
 private boolean showIntro = false;
 
 
 /** This is the level that the player is on. */
 static int levelNum = 0;
 
 /** A player class, used to get information about the player. */
 private Player player = new Player();
 
 /** The data of the current level. This should be given data in initLevel(). */
 static GameLevel level = new GameLevel();
 
 /** Controls whether the game has sound or not. */
 static boolean muted = false;
 
 /** Images for indicating volume. */
 private final Image VOLUME_BLACK = new ImageIcon(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/volume_black.png")).getImage();
 private final Image VOLUME_BLACK_MUTE = new ImageIcon(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/volume_black_mute.png")).getImage();
 private final Image VOLUME_WHITE = new ImageIcon(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/volume_white.png")).getImage();
 private final Image VOLUME_WHITE_MUTE = new ImageIcon(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/volume_white_mute.png")).getImage();
 
 /** Background music. */
 static Thread bgMusic = new Thread() {
 public void run() {
 TinySound.init();
 Music bgmusic = TinySound.loadMusic(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/music.ogg"));
 bgmusic.play(true);
 }
 };
 
 Thread endIntro = new Thread() {
 public void run() {
 try {
 Thread.sleep(1500);
 } catch (InterruptedException e) {
 TextFileWriter.appendToFile(logFilePath, e.getMessage());
 }
 gameState = MAIN_MENU;
 easyLog(logger, Level.INFO, "Game state set to MAIN_MENU");
 }
 };
 
 static boolean doLogging = false;
 
 private static int totalLevels = 0;
 
 
 //Intro objects
 
 /** True if the intro text should move down. */
 private boolean fadeOutIntro = false;
 
 /** The opacity of the intro text. */
 private int introTextOpacity = 0;
 
 /** A whoosh sound. */
 Sound drone = TinySound.loadSound(ClassLoader.getSystemResource("net/thedanpage/worldshardestgame/resources/drone.ogg"));
 
 /** A bell sound. */
 Sound bell = TinySound.loadSound(ClassLoader.getSystemResource("net/thedanpage/worldshardestgame/resources/bell.wav"));
 
 
 
 
 
 public void paintComponent(final Graphics g) {
 super.paintComponent(g);
 
 update(g);
 render(g);
 
 //Start the timer
 t.start();
 
 Toolkit.getDefaultToolkit().sync();
 }
 
 
 
 
 
 /** Update the game.
 * 
 * @param g
 * */
 public void update(Graphics g) {
 
 if (gameState == INTRO) {
 
 if (introTextOpacity == 0 && !fadeOutIntro) {
 drone.play();
 }
 
 if (introTextOpacity < 255 && !fadeOutIntro) {
 introTextOpacity += 255/10;
 if (introTextOpacity > 255) introTextOpacity = 255;
 }
 
 if (introTextOpacity == 225) {
 new Thread() {
 public void run() {
 try {
 Thread.sleep(3500);
 } catch (InterruptedException e) {
 TextFileWriter.appendToFile(logFilePath, e.getMessage());
 }
 fadeOutIntro = true;
 bgMusic.start();
 }
 }.start();
 }
 
 if (fadeOutIntro) {
 if (introTextOpacity > 0) {
 introTextOpacity -= 255/20;
 if (introTextOpacity < 0) introTextOpacity = 0;
 }
 }
 
 if (fadeOutIntro && introTextOpacity == 0 && !endIntro.isAlive()) {
 endIntro.start();
 }
 
 
 
 
 
 } else if (gameState == MAIN_MENU) {
 
 if (showIntro) {
 
 if (Input.enter.isPressed) {
 showIntro = false;
 gameState = LEVEL_TITLE;
 easyLog(logger, Level.INFO, "Game state set to LEVEL_TITLE");
 
 player.reset();
 
 levelNum = 1;
 level.init(player, levelNum);
 
 //Wait 1.75 seconds then start the level.
 new Thread() {
 public void run() {
 try { Thread.sleep(1750); } catch (InterruptedException e) { TextFileWriter.appendToFile(logFilePath, e.getMessage()); }
 gameState = LEVEL;
 easyLog(logger, Level.INFO, "Game state set to LEVEL");
 }
 }.start();
 }
 } else {
 
 //Click to start the first level
 if (Input.mousePressed && Input.mouseCoords.x > 304 && Input.mouseCoords.y < 323
 && Input.mouseCoords.x < 515 && Input.mouseCoords.y > 192) {
 showIntro = true;
 bell.play();
 } 
 }
 
 } else if (gameState == LEVEL) {
 
 if (Input.mouseOnWindow && Input.mouseCoords.x <= 65 && Input.mouseCoords.y <= 22
 && Input.mousePressed) {
 gameState = MAIN_MENU;
 easyLog(logger, Level.INFO, "Game state set to MAIN_MENU");
 }
 }
 }
 
 
 
 
 
 /** Draw the game's graphics.
 * 
 * @param g
 */
 private void render(Graphics g) {
 Graphics2D g2 = (Graphics2D) g;
 
 if (gameState == INTRO) {
 
 //Background
 g2.setPaint(new GradientPaint(0, 0, new Color(213, 213, 255), 0, 600, Color.WHITE));
 g2.fillRect(0, 0, 800, 600);
 
 g2.setFont(new Font("Tahoma", Font.BOLD, 50));
 g2.setColor(new Color(0, 0, 0, introTextOpacity));
 drawCenteredString("Made by Dan95363", 400, 250, g2);
 
 } else if (gameState == MAIN_MENU) {
 
 if (showIntro) {
 //Instructions
 g2.setFont(new Font("Tahoma", Font.BOLD, 20));
 g2.setColor(Color.BLACK);
 drawString("You are the red square. Avoid the blue circles and collect the\n" +
 "yellow circles. Once you have collected all of the yellow\n" +
 "circles, move to the green beacon to complete the level.\n" +
 "Some levels consist of more than one beacon; the\n" +
 "intermediary beacons act as checkpoints. You must complete\n" +
 "all 30 levels in order to submit your score. Your score is a\n" +
 "reflection of how many times you have died; the less, the better.", 30, 40, g2);
 
 g2.setColor(Color.BLUE);
 drawCenteredString("Press enter to continue", 400, 350, g2);
 } else {
 //Background
 g2.setPaint(new GradientPaint(0, 0, new Color(213, 213, 255), 0, 600, Color.WHITE));
 g2.fillRect(0, 0, 800, 600);
 
 //Draw and outline the title
 g2.setPaint(Color.BLACK);
 g2.setFont(new Font("SansSerif", Font.BOLD, 32));
 g2.drawString("The world's...", 40, 60);
 g2.setPaint(new Color(66, 117, 192));
 g2.setFont(new Font("SansSerif", Font.BOLD, 80));
 g2.drawString("HARDEST GAME", 40, 145);
 g2.setPaint(Color.BLACK);
 drawTextOutline("HARDEST GAME", 40, 145, 5, g2);
 
 g2.setFont(new Font("SansSerif", Font.BOLD, 60));
 
 //Gradient of "play game" text depending on the mouse location
 if (Input.mouseCoords.x > 284 && Input.mouseCoords.y < 343
 && Input.mouseCoords.x < 515 && Input.mouseCoords.y > 192) {
 g2.setPaint(new GradientPaint(0, 175, new Color(220, 220, 220), 0, 255, new Color(190, 60, 60)));
 } else {
 g2.setPaint(new GradientPaint(0, 175, Color.WHITE, 0, 255, Color.RED));
 }
 
 //Draw and outline the "play game" text
 drawCenteredString("PLAY", 400, 255, g2);
 drawCenteredString("GAME", 400, 320, g2);
 g2.setColor(Color.BLACK);
 drawTextOutline("PLAY", 315, 255, 3, g2);
 drawTextOutline("GAME", 302, 320, 3, g2);
 }
 
 } else if (gameState == LEVEL) {
 
 if (levelNum != 0) {
 level.drawTiles(g);
 
 level.drawCoins(g);
 
 level.drawDots(g);
 level.updateDots();
 
 player.draw(g);
 player.update(level);
 
 g.setColor(Color.BLACK);
 g.fillRect(0, 0, 800, 22);
 
 g.setColor(Color.WHITE);
 g.setFont(new Font("Tahoma", Font.BOLD, 18));
 drawRightJustifiedString("Deaths: " + player.getDeaths(), 750, 17, g);
 drawCenteredString(levelNum + "/" + totalLevels, 400, 17, g);
 
 if (Input.mouseOnWindow && Input.mouseCoords.x <= 65 && Input.mouseCoords.y <= 22) {
 g.setColor(Color.LIGHT_GRAY);
 }
 g.drawString("MENU", 0, 17);
 
 if (muted) {
 g.drawImage(VOLUME_WHITE_MUTE, 760, -12, null);
 } else {
 g.drawImage(VOLUME_WHITE, 760, -12, null);
 }
 }
 
 } else if (gameState == LEVEL_TITLE) {
 //Background
 g2.setPaint(new GradientPaint(0, 0, new Color(213, 213, 255), 0, 600, Color.WHITE));
 g2.fillRect(0, 0, 800, 600);
 
 //Draw the title text
 g2.setFont(new Font("Tahoma", Font.BOLD, 48));
 g.setColor(Color.BLACK);
 int textY = 200;
 for (String s : level.getTitle().split("\n")) {
 drawCenteredString(s, 400, textY += g.getFontMetrics().getHeight(), g);
 }
 }
 
 if (gameState != LEVEL) {
 if (muted) {
 g.drawImage(VOLUME_BLACK_MUTE, 760, -12, null);
 } else {
 g.drawImage(VOLUME_BLACK, 760, -12, null);
 }
 }
 
 g.dispose();
 }
 
 
 
 
 
 public void actionPerformed(ActionEvent arg0) {
 repaint();
 }
 
 
 
 
 
 /** Draw a string centered on its x axis.
 * 
 * @param text
 * the text to be drawn
 * @param x
 * the x coordinate of the text
 * @param y
 * the y coordinate of the text
 * @param g
 * the graphics the text will be drawn with
 */
 private void drawCenteredString(String s, int w, int h, Graphics g) {
 FontMetrics fm = g.getFontMetrics();
 int x = (w*2 - fm.stringWidth(s)) / 2;
 g.drawString(s, x, h);
 }
 
 
 
 
 
 /** Draw a string centered on its x axis.
 * 
 * @param text
 * the text to be drawn
 * @param x
 * the x coordinate of the text
 * @param y
 * the y coordinate of the text
 * @param g2
 * the 2D graphics the text will be drawn with
 */
 private void drawCenteredString(String s, int w, int h, Graphics2D g2) {
 FontMetrics fm = g2.getFontMetrics();
 int x = (w*2 - fm.stringWidth(s)) / 2;
 g2.drawString(s, x, h);
 }
 
 
 
 
 
 /** Draw a right-justified string.
 * 
 * @param text
 * the text to be drawn
 * @param x
 * the x coordinate of the text
 * @param y
 * the y coordinate of the text
 * @param g2
 * the 2D graphics the text will be drawn with
 */
 private void drawRightJustifiedString(String s, int w, int h, Graphics g) {
 FontMetrics fm = g.getFontMetrics();
 int x = (w - fm.stringWidth(s));
 g.drawString(s, x, h);
 }
 
 
 
 
 
 /** Draw the outline of a string of text.
 * 
 * @param text
 * the text to be drawn
 * @param x
 * the x coordinate of the text
 * @param y
 * the y coordinate of the text
 * @param thickness
 * the thickness of the outline
 * @param g2
 * the 2D graphics the text will be drawn with
 */
 private void drawTextOutline(String text, int x, int y, int thickness, Graphics2D g2) {
 TextLayout tl = new TextLayout(text, g2.getFont(), new FontRenderContext(null,false,false));
 AffineTransform textAt = new AffineTransform();
 textAt.translate(x, y);
 g2.setStroke(new BasicStroke(thickness));
 g2.draw(tl.getOutline(textAt));
 g2.setStroke(new BasicStroke());
 }
 
 
 
 
 
 /** Draw a string, with the use of \n implemented.
 * 
 * @param text
 * the text to be drawn
 * @param x
 * the x coordinate of the text
 * @param y
 * the y coordinate of the text
 * @param g
 * the graphics the text will be drawn with
 */
 private void drawString(String text, int x, int y, Graphics g) {
 for (String line : text.split("\n"))
 g.drawString(line, x, y += g.getFontMetrics().getHeight());
 }
 
 
 
 
 
 /**
 * Convert an exception to a String with full stack trace
 * 
 * @param ex
 * the exception
 * @return A string with the full stacktrace error text
 */
 public static String getStringFromStackTrace(Throwable ex) {
 if (ex == null) {
 return "";
 }
 StringWriter str = new StringWriter();
 PrintWriter writer = new PrintWriter(str);
 try {
 ex.printStackTrace(writer);
 return str.getBuffer().toString();
 } finally {
 try {
 str.close();
 writer.close();
 } catch (IOException e) {
 // ignore
 }
 }
 }
 
 
 
 
 
 /**
 * Easily log a string of text, and write it to the log file
 * 
 * @param logger
 * The logger for the string to be logged with
 * @param level
 * The level of the logger
 * @param s
 * The string of text to be logged
 */
 static void easyLog(Logger logger, Level level, String s) {
 if (doLogging) {
 logger.setLevel(level);
 
 if (level == Level.CONFIG) logger.config(s);
 else if (level == Level.FINE) logger.fine(s);
 else if (level == Level.FINER) logger.finer(s);
 else if (level == Level.FINEST) logger.finest(s);
 else if (level == Level.INFO) logger.info(s);
 else if (level == Level.SEVERE) logger.severe(s);
 else if (level == Level.WARNING) logger.warning(s);
 
 else {
 logger.setLevel(Level.WARNING);
 logger.warning("Logging error");
 }
 
 TextFileWriter.appendToFile(logFilePath, new SimpleDateFormat(
 "MMM dd, YYYY h:mm:ss a").format(new Date())
 + " net.thedanpage.worldshardestgame easyLog\n" + level + ": " + s);
 }
 }
 
 
 
 
 
 public static void main(String[] args) {
 
 int option = JOptionPane.showConfirmDialog(
 new Dialog(frame, true),
 "Would you like to enable logging to " + System.getProperty("user.home") + "/worldshardestgame/logs?",
 "Setup",
 JOptionPane.YES_NO_OPTION);
 if (option == JOptionPane.YES_OPTION) Game.doLogging = true;
 else Game.doLogging = false;
 
 if (Game.doLogging) {
 
 //Create directory for logs if it does not exist
 if (!new File(System.getProperty("user.home") + "/worldshardestgame/logs").isDirectory()) {
 new File(System.getProperty("user.home") + "/worldshardestgame/logs").mkdirs();
 }
 
 if (new File(Game.logFilePath + ".zip").exists()) {
 LogZipper.unzip(
 System.getProperty("user.home") + "/worldshardestgame/logs", Game.logFilePath + ".zip");
 new File(Game.logFilePath + ".zip").delete();
 }
 
 try {
 if (new File(Game.logFilePath).exists() && new BufferedReader(new FileReader(Game.logFilePath)).readLine() != null) {
 TextFileWriter.appendToFile(Game.logFilePath, "\n");
 }
 } catch (IOException e) {
 Game.easyLog(Game.logger, Level.WARNING, Game.getStringFromStackTrace(e));
 }
 }
 
 try {
 while (new File(ClassLoader
 .getSystemResource("net/thedanpage/worldshardestgame/resources/maps/level_" + (totalLevels+1) + ".txt").toURI())
 .exists()) {
 totalLevels++;
 }
 } catch (Exception e) {
 System.out.println("Total levels: " + totalLevels);
 }
 
 Game.easyLog(Game.logger, Level.INFO, "Starting The World's Hardest Game");
 
 TinySound.init();
 Game.easyLog(Game.logger, Level.INFO, "TinySound initialized");
 
 if (Game.muted) TinySound.setGlobalVolume(0);
 
 Input.init();
 Game.easyLog(Game.logger, Level.INFO, "Input initialized");
 
 frame.setTitle("World's Hardest Game");
 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 frame.setSize(new Dimension(800, 622));
 frame.setResizable(false);
 frame.setLocationRelativeTo(null);
 
 game = new Game();
 frame.add(game);
 
 frame.setIconImage(new ImageIcon(ClassLoader.getSystemResource("net/thedanpage/worldshardestgame/resources/favicon.png")).getImage());
 frame.setVisible(true);
 }
 
}

GameLevel.java

package net.thedanpage.worldshardestgame;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.logging.Level;
public class GameLevel {
 
 @Override
 public String toString() {
 return "GameLevel [spawnPoint=" + spawnPoint + ", id=" + id
 + ", levelTitle=" + levelTitle + ", tileMap=" + tileMap
 + ", dots=" + dots + ", coins=" + coins + ", levelArea="
 + levelArea + "]";
 }
 /** Spawn point of the level. */
 private Point spawnPoint;
 
 /** The ID of the level. The first level has an ID of 1. */
 private int id;
 
 /** The message that is displayed before the level. */
 private String levelTitle;
 
 /** A list of all of the level's tiles. */
 private ArrayList<Tile> tileMap;
 
 /** A list of all of the level's dots. */
 public ArrayList<Dot> dots;
 
 /** A list of all of the level's coins. **/
 public ArrayList<Coin> coins;
 
 /** The area of the level, not including background tiles. */
 Area levelArea;
 
 public GameLevel() {
 this.levelArea = new Area();
 this.tileMap = new ArrayList<Tile>();
 this.dots = new ArrayList<Dot>();
 this.spawnPoint = new Point(20, 20);
 this.id = -1;
 this.levelTitle = "\"Intimidating message\nhere\"";
 }
 
 public GameLevel(Point spawn, int id) {
 this.levelArea = new Area();
 this.tileMap = new ArrayList<Tile>();
 this.dots = new ArrayList<Dot>();
 this.spawnPoint = spawn;
 this.id = id;
 this.levelTitle = "\"Intimidating message\nhere\"";
 }
 
 /**
 * @return spawnPoint
 */
 public Point getSpawnPoint() {
 return this.spawnPoint;
 }
 
 /**
 * @return id
 */
 public int getID() {
 return this.id;
 }
 
 /**
 * @return tileMap
 */
 public ArrayList<Tile> getTileMap() {
 return this.tileMap;
 }
 
 /**
 * @return levelTitle
 */
 public String getTitle() {
 return this.levelTitle;
 }
 
 
 
 /** Draw the tiles based on a text file in the maps package. 
 * 
 * 
 * */
 public void drawTiles(Graphics g) {
 
 Graphics2D g2 = (Graphics2D) g;
 
 try {
 /*for (Tile t : this.tileMap) {
 //Background
 if (t.getType() == 0) {
 g.setColor(new Color(180, 181, 254));
 g.fillRect(t.getX(), t.getY(), 40, 40);
 }
 }*/
 
 g.setColor(new Color(180, 181, 254));
 g.fillRect(0, 22, 800, 622);
 
 //Border around level
 g2.setColor(Color.BLACK);
 g2.fill(this.levelArea);
 
 for (Tile t : this.tileMap) {
 
 t.draw(this, g);
 
 }
 } catch (Exception e) {
 System.out.println("File not found.");
 TextFileWriter.appendToFile(Game.logFilePath, Game.getStringFromStackTrace(e));
 }
 }
 
 
 
 public void drawDots(Graphics g) {
 for (Dot dot : this.dots) dot.draw(g);
 }
 
 
 
 public void updateDots() {
 if (this.dots != null)
 for (Dot dot : this.dots) dot.update();
 }
 
 
 
 public void drawCoins(Graphics g) {
 if (this.coins != null)
 for (Coin coin : this.coins) coin.draw(g);
 }
 
 
 
 public boolean allCoinsCollected() {
 if (this.coins != null) {
 for (Coin coin : this.coins) {
 if (!coin.collected) return false;
 }
 }
 return true;
 }
 
 
 
 /**
 * Load the current level data from
 * net.thedanpage.worldshardestgame.resources.maps
 */
 public void init(Player player, int levelNum) {
 
 if (ClassLoader.getSystemResource("net/thedanpage/worldshardestgame/resources/maps/level_" + levelNum + ".txt") != null)
 Game.easyLog(Game.logger, Level.INFO, "The file for level " + levelNum + " has been found");
 else Game.easyLog(Game.logger, Level.SEVERE, "The file for level " + levelNum + " could not be found");
 
 Game.easyLog(Game.logger, Level.INFO, "Level " + Game.levelNum + " is being initialized");
 
 //Clears the tile data
 this.tileMap = new ArrayList<Tile>();
 
 //Clears the dot data
 this.dots = new ArrayList<Dot>();
 
 //Clears the coin data
 this.coins = new ArrayList<Coin>();
 
 //Clears the level area data
 this.levelArea = new Area();
 
 //Resets the level title
 this.levelTitle = "\"Intimidating message\nhere\"";
 
 try {
 this.spawnPoint = new Point(
 Integer.parseInt(PropLoader
 .loadProperty("spawn_point",
 "net/thedanpage/worldshardestgame/resources/maps/level_" + levelNum + ".properties")
 .split(",")[0]) * 40 + 20,
 Integer.parseInt(PropLoader
 .loadProperty("spawn_point",
 "net/thedanpage/worldshardestgame/resources/maps/level_" + levelNum + ".properties")
 .split(",")[1]) * 40 + 20);
 
 this.id = Integer.parseInt(PropLoader.loadProperty("level_id",
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".properties"));
 
 this.levelTitle = PropLoader.loadProperty("level_title", 
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".properties").toString();
 
 String coinData = null;
 
 //Retrieves the coin data
 if (PropLoader.loadProperty("coins", 
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".properties") != "null") {
 coinData = PropLoader.loadProperty("coins", 
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".properties");
 }
 
 if (coinData != null) {
 coinData = coinData.replaceAll("\\Z", "");
 
 if (coinData.contains("-")) {
 
 String[] coins = coinData.split("-");
 for (String s : coins) this.coins.add(new Coin((int) (Double.parseDouble(s.split(",")[0]) * 40),
 (int) (Double.parseDouble(s.split(",")[1]) * 40)));
 
 } else this.coins.add(new Coin((int) (Double.parseDouble(coinData.split(",")[0]) * 40),
 (int) (Double.parseDouble(coinData.split(",")[1]) * 40)));
 }
 Game.easyLog(Game.logger, Level.INFO, "All coins have been added");
 
 //Retrieves the tile data
 InputStreamReader isr = new InputStreamReader(ClassLoader
 .getSystemResource(
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".txt").openStream());
 String content = "";
 Scanner scanner = new Scanner(isr);
 content = scanner.useDelimiter("\\Z").next();
 scanner.close();
 
 Game.easyLog(Game.logger, Level.INFO, "Level data:\n\n" + content);
 
 content = content.replaceAll("\n", "");
 for (int i = 0; i < content.length(); i++) {
 if (i > 299)
 break;
 else
 this.tileMap.add(new Tile((i % 20) * 40, (i / 20) * 40,
 Character.getNumericValue(content.charAt(i))));
 }
 this.levelArea = new Area();
 for (Tile t : this.tileMap) {
 if (t.getType() != 0) {
 this.levelArea.add(new Area(
 new Rectangle(t.getX() - 3, t.getY() - 3 + 22, 46, 46)));
 }
 }
 } catch (Exception e) {
 Game.easyLog(Game.logger, Level.SEVERE, "Map unable to be loaded:\n" + Game.getStringFromStackTrace(e));
 }
 //Retrieves the dot data
 try {
 InputStreamReader isr = new InputStreamReader(ClassLoader
 .getSystemResource(
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".txt").openStream());
 Scanner scanner = new Scanner(isr);
 String content = scanner.useDelimiter("\\Z").next();
 String[] lines = content.split("\n");
 scanner.close();
 for (int i=19; lines[i] != null; i++) {
 String line = lines[i];
 String[] dotData = line.replaceAll(" ", "").split("-");
 this.dots.add(new Dot(
 Integer.parseInt(dotData[0]),
 Integer.parseInt(dotData[1]),
 new Point(Integer.parseInt(dotData[2].split(",")[0]),
 Integer.parseInt(dotData[2].split(",")[1])),
 new Point(Integer.parseInt(dotData[3].split(",")[0]),
 Integer.parseInt(dotData[3].split(",")[1])),
 Double.parseDouble(dotData[4]),
 Boolean.parseBoolean(dotData[5]),
 Boolean.parseBoolean(dotData[6])
 ));
 }
 Game.easyLog(Game.logger, Level.INFO, "All dots have been added");
 } catch (Exception e) {
 if (e.getClass().getName() != "java.lang.ArrayIndexOutOfBoundsException")
 Game.easyLog(Game.logger, Level.SEVERE, "Dots unable to be loaded:\n" + Game.getStringFromStackTrace(e));
 }
 if (this.tileMap.size() == 300) Game.easyLog(Game.logger, Level.INFO, "All tiles have been added");
 else Game.easyLog(Game.logger, Level.WARNING, "Not all tiles were added");
 
 player.respawn(this);
 }
}

Player.java

package net.thedanpage.worldshardestgame;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;
import java.util.logging.Level;
import kuusisto.tinysound.Sound;
import kuusisto.tinysound.TinySound;
public class Player {
 
 /** The X coordinate of the player. */
 private int x;
 /** The Y coordinate of the player. */
 private int y;
 /**
 * The X coordinate of the player, snapped to the grid of 40x40 tiles.
 * snapX = x/40
 */
 private int snapX;
 /**
 * The Y coordinate of the player, snapped to the grid of 40x40 tiles.
 * snapY = y/40
 */
 private int snapY;
 /** True if the player is colliding with a tile above them. */
 private boolean collidingUp;
 /** True if the player is colliding with a tile below them. */
 private boolean collidingDown;
 /** True if the player is colliding with a tile to their left. */
 private boolean collidingLeft;
 /** True if the player is colliding with a tile to their right. */
 private boolean collidingRight;
 
 /** The smack sound. */
 Sound smack;
 
 /** The number of times the player has died. */
 private int deaths;
 
 /** True if the player has been hit and is not allowed to move. */
 private boolean dead;
 
 /** The opacity of the player. */
 private double opacity;
 
 public Player() {
 this.x = 400;
 this.y = 300;
 this.snapX = x/40;
 this.snapY = y/40;
 this.collidingUp = false;
 this.collidingDown = false;
 this.collidingLeft = false;
 this.collidingRight = false;
 this.deaths = 0;
 this.dead = false;
 this.opacity = 255;
 }
 
 
 
 
 
 public Player(int x, int y) {
 this.x = x;
 this.y = y;
 this.snapX = x/40;
 this.snapY = y/40;
 this.collidingUp = false;
 this.collidingDown = false;
 this.collidingLeft = false;
 this.collidingRight = false;
 this.deaths = 0;
 this.dead = false;
 this.opacity = 255;
 }
 
 
 
 
 
 public void draw(Graphics g) {
 g.setColor(new Color(0, 0, 0, (int) opacity));
 g.fillRect(x - 15, y - 15 + 22, 31, 31);
 g.setColor(new Color(255, 0, 0, (int) opacity));
 g.fillRect(x-12, y-12 + 22,
 25, 25);
 }
 
 
 
 
 
 Tile getRelativeTile(GameLevel level, int x1, int y1, int xOff, int yOff) {
 for (Tile t : level.getTileMap()) {
 if (x1/40 + xOff == t.getSnapX() && y1/40 + yOff == t.getSnapY()) {
 return t;
 }
 }
 return null;
 }
 
 
 
 
 
 Tile getTile(GameLevel level) {
 for (Tile t : level.getTileMap()) {
 if (this.x/40 == t.getSnapX() && this.y/40 == t.getSnapY()) {
 return t;
 }
 }
 return null;
 }
 
 
 
 
 
 boolean doesIntersect(Rectangle a, Rectangle b) {
 return (a.x + a.width < b.x || a.x > b.x + b.width
 || a.y + a.height < b.y || a.y > b.y + b.height);
 }
 
 
 
 
 
 public Rectangle getBounds() {
 return new Rectangle(this.x - 15, this.y - 15, 31, 31);
 }
 
 
 
 
 
 void checkCollisionUp(GameLevel level) {
 if (getRelativeTile(level, this.x - 14, this.y + 24, 0, -1) != null &&
 getRelativeTile(level, this.x - 14, this.y + 24, 0, -1).getType() == 0 ||
 getRelativeTile(level, this.x + 15, this.y + 24, 0, -1) != null &&
 getRelativeTile(level, this.x + 15, this.y + 24, 0, -1).getType() == 0) {
 this.collidingUp = true;
 return;
 }
 this.collidingUp = false;
 }
 
 
 
 
 
 void checkCollisionDown(GameLevel level) {
 if (getRelativeTile(level, this.x - 14, this.y - 24, 0, 1) != null &&
 getRelativeTile(level, this.x - 14, this.y - 24, 0, 1).getType() == 0 ||
 getRelativeTile(level, this.x + 15, this.y - 24, 0, 1) != null &&
 getRelativeTile(level, this.x + 15, this.y - 24, 0, 1).getType() == 0) {
 this.collidingDown = true;
 return;
 }
 this.collidingDown = false;
 }
 
 
 
 
 
 void checkCollisionLeft(GameLevel level) {
 if (getRelativeTile(level, this.x + 24, this.y - 15, -1, 0) != null &&
 getRelativeTile(level, this.x + 24, this.y - 15, -1, 0).getType() == 0 ||
 getRelativeTile(level, this.x + 24, this.y + 14, -1, 0) != null &&
 getRelativeTile(level, this.x + 24, this.y + 14, -1, 0).getType() == 0) {
 this.collidingLeft = true;
 return;
 }
 this.collidingLeft = false;
 }
 
 
 
 
 
 void checkCollisionRight(GameLevel level) {
 if (getRelativeTile(level, this.x - 24, this.y - 15, 1, 0) != null &&
 getRelativeTile(level, this.x - 24, this.y - 15, 1, 0).getType() == 0 ||
 getRelativeTile(level, this.x - 24, this.y + 15, 1, 0) != null &&
 getRelativeTile(level, this.x - 24, this.y + 15, 1, 0).getType() == 0) {
 this.collidingRight = true;
 return;
 }
 this.collidingRight = false;
 }
 
 
 
 
 
 void respawn(GameLevel level) {
 this.x = level.getSpawnPoint().x;
 this.y = level.getSpawnPoint().y;
 if (level.coins != null) {
 for (Coin coin : level.coins) coin.collected = false;
 }
 }
 
 
 
 
 
 boolean collidesWith(Shape other) {
 return this.getBounds().getBounds2D().intersects(other.getBounds2D());
 }
 
 
 
 
 
 public void update(GameLevel level) {
 this.snapX = this.x / 40;
 this.snapY = this.y / 40;
 
 if (level.coins != null) {
 for (Coin coin : level.coins) {
 if (this.collidesWith(coin.getBounds()) && !coin.collected) {
 coin.collected = true;
 
 //Coin sound
 TinySound.init();
 TinySound.loadSound(Player.class.getClassLoader()
 .getResource("net/thedanpage/worldshardestgame/resources/ding.wav")).play();
 }
 }
 }
 
 if (level.getTileMap() != new ArrayList<Tile>()) {
 
 if (level.allCoinsCollected()) {
 
 for (Tile t : level.getTileMap()) {
 
 if (t.getType() == 3 && this.collidesWith(t.getBounds())) {
 
 Game.levelNum ++;
 level.init(this, Game.levelNum);
 Game.gameState = Game.LEVEL_TITLE;
 Game.easyLog(Game.logger, Level.INFO, "Game state set to LEVEL_TITLE");
 
 //Wait 1.75 seconds then start the level.
 new Thread() {
 public void run() {
 try {
 Thread.sleep(1750);
 } catch (InterruptedException e) {
 Game.easyLog(Game.logger, Level.SEVERE, Game.getStringFromStackTrace(e));
 }
 Game.gameState = Game.LEVEL;
 Game.easyLog(Game.logger, Level.INFO, "Game state set to LEVEL");
 }
 }.start();
 }
 }
 }
 }
 
 checkCollisionUp(level);
 checkCollisionDown(level);
 checkCollisionLeft(level);
 checkCollisionRight(level);
 
 if (this.dead) {
 this.opacity -= 255/75;
 
 if (this.opacity < 0) this.opacity = 0;
 
 if (this.opacity == 0) {
 this.dead = false;
 this.opacity = 255;
 this.respawn(level);
 }
 } else {
 if (Input.up.isPressed && !this.collidingUp) this.y --;
 if (Input.down.isPressed && !this.collidingDown) this.y ++;
 if (Input.left.isPressed && !this.collidingLeft) this.x --;
 if (Input.right.isPressed && !this.collidingRight) this.x ++;
 }
 
 if (this.x > 800) this.x = 0;
 if (this.x < 0) this.x = 800;
 if (this.y > 600) this.y = 0;
 if (this.y < 0) this.y = 600;
 
 if (!this.dead) {
 for (Dot dot : level.dots) {
 if (this.collidesWith(dot.getBounds())) {
 this.deaths ++;
 this.dead = true;
 
 if (!Game.muted) {
 //Play the smack sound
 TinySound.init();
 TinySound.loadSound(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/smack.wav")).play();
 }
 }
 }
 }
 }
 
 
 
 
 
 public int getX() {
 return this.x;
 }
 
 
 
 public int getY() {
 return this.y;
 }
 
 
 
 public int getSnapX() {
 return this.snapX;
 }
 
 
 
 public int getSnapY() {
 return this.snapY;
 }
 
 
 
 public int getWidth() {
 return (int) this.getBounds().getWidth();
 }
 
 
 
 public int getHeight() {
 return (int) this.getBounds().getHeight();
 }
 
 
 
 public boolean isCollidingLeft() {
 return this.collidingLeft;
 }
 
 
 
 public boolean isCollidingRight() {
 return this.collidingRight;
 }
 
 
 
 public boolean isCollidingUp() {
 return this.collidingUp;
 }
 
 
 
 public boolean isCollidingDown() {
 return this.collidingDown;
 }
 
 
 
 public int getDeaths() {
 return this.deaths;
 }
 
 
 
 public boolean isDead() {
 return this.dead;
 }
 
 
 
 public void setDead(boolean dead) {
 this.dead = dead;
 }
 
 
 
 public double getOpacity() {
 return this.opacity;
 }
 
 
 
 public void reset() {
 this.x = 400;
 this.y = 300;
 this.snapX = x/40;
 this.snapY = y/40;
 this.collidingUp = false;
 this.collidingDown = false;
 this.collidingLeft = false;
 this.collidingRight = false;
 this.deaths = 0;
 this.dead = false;
 this.opacity = 255;
 }
 @Override
 public String toString() {
 return "Player [x=" + x + ", y=" + y + ", snapX=" + snapX + ", snapY="
 + snapY + ", collidingUp=" + collidingUp + ", collidingDown="
 + collidingDown + ", collidingLeft=" + collidingLeft
 + ", collidingRight=" + collidingRight + ", deaths=" + deaths
 + ", dead=" + dead + "]";
 }
}

TextFileWriter.java

package net.thedanpage.worldshardestgame;
// JavaFileAppendFileWriterExample.java
// Created by <a href="http://alvinalexander.com" title="http://alvinalexander.com">http://alvinalexander.com</a>
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class TextFileWriter {
 static BufferedWriter bw = null;
 public static void appendToFile(String filepath, String s) {
 try {
 // APPEND MODE SET HERE
 bw = new BufferedWriter(new FileWriter(filepath, true));
 bw.write(s);
 bw.newLine();
 bw.flush();
 } catch (IOException e) {
 System.out.println(e);
 } finally { // always close the file
 if (bw != null)
 try {
 bw.close();
 } catch (IOException ioe2) {
 // just ignore it
 }
 } // end try/catch/finally
 }
} // end class

LogZipper.java

package net.thedanpage.worldshardestgame;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
public class LogZipper {
 public static void zipLog() {
 byte[] buffer = new byte[1024];
 try {
 FileOutputStream fos = new FileOutputStream(
 Game.logFilePath + ".zip");
 ZipOutputStream zos = new ZipOutputStream(fos);
 ZipEntry ze = new ZipEntry(Game.logFilePath.replace(
 System.getProperty("user.home")
 + "/worldshardestgame/logs/", ""));
 zos.putNextEntry(ze);
 FileInputStream in = new FileInputStream(Game.logFilePath);
 int len;
 while ((len = in.read(buffer)) > 0) {
 zos.write(buffer, 0, len);
 }
 in.close();
 zos.closeEntry();
 // remember close it
 zos.close();
 
 if (new File(Game.logFilePath).exists()) new File(Game.logFilePath).delete();
 } catch (IOException ex) {
 ex.printStackTrace();
 }
 }
 
 public static void unzipLog() {
 try {
 ZipFile zipFile = new ZipFile(Game.logFilePath + ".zip");
 Enumeration<?> enu = zipFile.entries();
 while (enu.hasMoreElements()) {
 ZipEntry zipEntry = (ZipEntry) enu.nextElement();
 
 String name = zipEntry.getName();
 
 File file = new File(name);
 if (name.endsWith("/")) {
 file.mkdirs();
 continue;
 }
 
 File parent = file.getParentFile();
 if (parent != null) {
 parent.mkdirs();
 }
 
 InputStream is = zipFile.getInputStream(zipEntry);
 FileOutputStream fos = new FileOutputStream(file);
 byte[] bytes = new byte[1024];
 int length;
 while ((length = is.read(bytes)) >= 0) {
 fos.write(bytes, 0, length);
 }
 is.close();
 fos.close();
 
 }
 zipFile.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 
 public static void unzip(String destinationFolder, String zipFile) {
 File directory = new File(destinationFolder);
 
 // if the output directory doesn't exist, create it
 if(!directory.exists()) 
 directory.mkdirs();
 // buffer for read and write data to file
 byte[] buffer = new byte[2048];
 
 try {
 FileInputStream fInput = new FileInputStream(zipFile);
 ZipInputStream zipInput = new ZipInputStream(fInput);
 
 ZipEntry entry = zipInput.getNextEntry();
 
 while(entry != null){
 String entryName = entry.getName();
 File file = new File(destinationFolder + File.separator + entryName);
 
 System.out.println("Unzipping file " + entryName + " to " + file.getAbsolutePath());
 
 // create the directories of the zip directory
 if(entry.isDirectory()) {
 File newDir = new File(file.getAbsolutePath());
 if(!newDir.exists()) {
 boolean success = newDir.mkdirs();
 if(success == false) {
 System.out.println("Problem creating Folder");
 }
 }
 }
 else {
 FileOutputStream fOutput = new FileOutputStream(file);
 int count = 0;
 while ((count = zipInput.read(buffer)) > 0) {
 // write 'count' bytes to the file output stream
 fOutput.write(buffer, 0, count);
 }
 fOutput.close();
 }
 // close ZipEntry and take the next one
 zipInput.closeEntry();
 entry = zipInput.getNextEntry();
 }
 
 // close the last ZipEntry
 zipInput.closeEntry();
 
 zipInput.close();
 fInput.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
}

Game.java

package net.thedanpage.worldshardestgame;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import kuusisto.tinysound.Music;
import kuusisto.tinysound.Sound;
import kuusisto.tinysound.TinySound;
public class Game extends JPanel implements ActionListener {
 
 /** An instance of the game. */
 private static Game game;
 
 /** The timer used for the game's clock. */
 private Timer t = new Timer(5, this);
 
 /** Used for logging information during the game. */
 public final static Logger logger = Logger.getLogger(Game.class.getName());
 
 static String logFilePath = System.getProperty("user.home")
 + "/worldshardestgame/logs/" + new SimpleDateFormat("YY-MM-dd").format(new Date()) + ".log";
 private static final long serialVersionUID = 1L;
 
 /** The frame that the panel goes in. */
 static JFrame frame = new JFrame();
 
 /** The enum instance used for switching the state of the game. */
 static final int INTRO = 0, MAIN_MENU = 1, LEVEL_TITLE = 2, LEVEL = 3;
 
 /** The integer used for the game state. */
 static int gameState = INTRO;
 
 /** Used for when the instructions should be shown. */
 private boolean showIntro = false;
 
 
 /** This is the level that the player is on. */
 static int levelNum = 0;
 
 /** A player class, used to get information about the player. */
 private Player player = new Player();
 
 /** The data of the current level. This should be given data in initLevel(). */
 static GameLevel level = new GameLevel();
 
 /** Controls whether the game has sound or not. */
 static boolean muted = false;
 
 /** Images for indicating volume. */
 private final Image VOLUME_BLACK = new ImageIcon(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/volume_black.png")).getImage();
 private final Image VOLUME_BLACK_MUTE = new ImageIcon(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/volume_black_mute.png")).getImage();
 private final Image VOLUME_WHITE = new ImageIcon(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/volume_white.png")).getImage();
 private final Image VOLUME_WHITE_MUTE = new ImageIcon(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/volume_white_mute.png")).getImage();
 
 /** Background music. */
 static Thread bgMusic = new Thread() {
 public void run() {
 TinySound.init();
 Music bgmusic = TinySound.loadMusic(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/music.ogg"));
 bgmusic.play(true);
 }
 };
 
 Thread endIntro = new Thread() {
 public void run() {
 try {
 Thread.sleep(1500);
 } catch (InterruptedException e) {
 TextFileWriter.appendToFile(logFilePath, e.getMessage());
 }
 gameState = MAIN_MENU;
 easyLog(logger, Level.INFO, "Game state set to MAIN_MENU");
 }
 };
 
 static boolean doLogging = false;
 
 private static int totalLevels = 0;
 
 
 //Intro objects
 
 /** True if the intro text should move down. */
 private boolean fadeOutIntro = false;
 
 /** The opacity of the intro text. */
 private int introTextOpacity = 0;
 
 /** A whoosh sound. */
 Sound drone = TinySound.loadSound(ClassLoader.getSystemResource("net/thedanpage/worldshardestgame/resources/drone.ogg"));
 
 /** A bell sound. */
 Sound bell = TinySound.loadSound(ClassLoader.getSystemResource("net/thedanpage/worldshardestgame/resources/bell.wav"));
 
 
 
 
 
 public void paintComponent(final Graphics g) {
 super.paintComponent(g);
 
 update(g);
 render(g);
 
 //Start the timer
 t.start();
 
 Toolkit.getDefaultToolkit().sync();
 }
 
 
 
 
 
 /** Update the game.
 * 
 * @param g
 * */
 public void update(Graphics g) {
 
 if (gameState == INTRO) {
 
 if (introTextOpacity == 0 && !fadeOutIntro) {
 drone.play();
 }
 
 if (introTextOpacity < 255 && !fadeOutIntro) {
 introTextOpacity += 255/10;
 if (introTextOpacity > 255) introTextOpacity = 255;
 }
 
 if (introTextOpacity == 225) {
 new Thread() {
 public void run() {
 try {
 Thread.sleep(3500);
 } catch (InterruptedException e) {
 TextFileWriter.appendToFile(logFilePath, e.getMessage());
 }
 fadeOutIntro = true;
 bgMusic.start();
 }
 }.start();
 }
 
 if (fadeOutIntro) {
 if (introTextOpacity > 0) {
 introTextOpacity -= 255/20;
 if (introTextOpacity < 0) introTextOpacity = 0;
 }
 }
 
 if (fadeOutIntro && introTextOpacity == 0 && !endIntro.isAlive()) {
 endIntro.start();
 }
 
 
 
 
 
 } else if (gameState == MAIN_MENU) {
 
 if (showIntro) {
 
 if (Input.enter.isPressed) {
 showIntro = false;
 gameState = LEVEL_TITLE;
 easyLog(logger, Level.INFO, "Game state set to LEVEL_TITLE");
 
 player.reset();
 
 levelNum = 1;
 level.init(player, levelNum);
 
 //Wait 1.75 seconds then start the level.
 new Thread() {
 public void run() {
 try { Thread.sleep(1750); } catch (InterruptedException e) { TextFileWriter.appendToFile(logFilePath, e.getMessage()); }
 gameState = LEVEL;
 easyLog(logger, Level.INFO, "Game state set to LEVEL");
 }
 }.start();
 }
 } else {
 
 //Click to start the first level
 if (Input.mousePressed && Input.mouseCoords.x > 304 && Input.mouseCoords.y < 323
 && Input.mouseCoords.x < 515 && Input.mouseCoords.y > 192) {
 showIntro = true;
 bell.play();
 } 
 }
 
 } else if (gameState == LEVEL) {
 
 if (Input.mouseOnWindow && Input.mouseCoords.x <= 65 && Input.mouseCoords.y <= 22
 && Input.mousePressed) {
 gameState = MAIN_MENU;
 easyLog(logger, Level.INFO, "Game state set to MAIN_MENU");
 }
 }
 }
 
 
 
 
 
 /** Draw the game's graphics.
 * 
 * @param g
 */
 private void render(Graphics g) {
 Graphics2D g2 = (Graphics2D) g;
 
 if (gameState == INTRO) {
 
 //Background
 g2.setPaint(new GradientPaint(0, 0, new Color(213, 213, 255), 0, 600, Color.WHITE));
 g2.fillRect(0, 0, 800, 600);
 
 g2.setFont(new Font("Tahoma", Font.BOLD, 50));
 g2.setColor(new Color(0, 0, 0, introTextOpacity));
 drawCenteredString("Made by Dan95363", 400, 250, g2);
 
 } else if (gameState == MAIN_MENU) {
 
 if (showIntro) {
 //Instructions
 g2.setFont(new Font("Tahoma", Font.BOLD, 20));
 g2.setColor(Color.BLACK);
 drawString("You are the red square. Avoid the blue circles and collect the\n" +
 "yellow circles. Once you have collected all of the yellow\n" +
 "circles, move to the green beacon to complete the level.\n" +
 "Some levels consist of more than one beacon; the\n" +
 "intermediary beacons act as checkpoints. You must complete\n" +
 "all 30 levels in order to submit your score. Your score is a\n" +
 "reflection of how many times you have died; the less, the better.", 30, 40, g2);
 
 g2.setColor(Color.BLUE);
 drawCenteredString("Press enter to continue", 400, 350, g2);
 } else {
 //Background
 g2.setPaint(new GradientPaint(0, 0, new Color(213, 213, 255), 0, 600, Color.WHITE));
 g2.fillRect(0, 0, 800, 600);
 
 //Draw and outline the title
 g2.setPaint(Color.BLACK);
 g2.setFont(new Font("SansSerif", Font.BOLD, 32));
 g2.drawString("The world's...", 40, 60);
 g2.setPaint(new Color(66, 117, 192));
 g2.setFont(new Font("SansSerif", Font.BOLD, 80));
 g2.drawString("HARDEST GAME", 40, 145);
 g2.setPaint(Color.BLACK);
 drawTextOutline("HARDEST GAME", 40, 145, 5, g2);
 
 g2.setFont(new Font("SansSerif", Font.BOLD, 60));
 
 //Gradient of "play game" text depending on the mouse location
 if (Input.mouseCoords.x > 284 && Input.mouseCoords.y < 343
 && Input.mouseCoords.x < 515 && Input.mouseCoords.y > 192) {
 g2.setPaint(new GradientPaint(0, 175, new Color(220, 220, 220), 0, 255, new Color(190, 60, 60)));
 } else {
 g2.setPaint(new GradientPaint(0, 175, Color.WHITE, 0, 255, Color.RED));
 }
 
 //Draw and outline the "play game" text
 drawCenteredString("PLAY", 400, 255, g2);
 drawCenteredString("GAME", 400, 320, g2);
 g2.setColor(Color.BLACK);
 drawTextOutline("PLAY", 315, 255, 3, g2);
 drawTextOutline("GAME", 302, 320, 3, g2);
 }
 
 } else if (gameState == LEVEL) {
 
 if (levelNum != 0) {
 level.drawTiles(g);
 
 level.drawCoins(g);
 
 level.drawDots(g);
 level.updateDots();
 
 player.draw(g);
 player.update(level);
 
 g.setColor(Color.BLACK);
 g.fillRect(0, 0, 800, 22);
 
 g.setColor(Color.WHITE);
 g.setFont(new Font("Tahoma", Font.BOLD, 18));
 drawRightJustifiedString("Deaths: " + player.getDeaths(), 750, 17, g);
 drawCenteredString(levelNum + "/" + totalLevels, 400, 17, g);
 
 if (Input.mouseOnWindow && Input.mouseCoords.x <= 65 && Input.mouseCoords.y <= 22) {
 g.setColor(Color.LIGHT_GRAY);
 }
 g.drawString("MENU", 0, 17);
 
 if (muted) {
 g.drawImage(VOLUME_WHITE_MUTE, 760, -12, null);
 } else {
 g.drawImage(VOLUME_WHITE, 760, -12, null);
 }
 }
 
 } else if (gameState == LEVEL_TITLE) {
 //Background
 g2.setPaint(new GradientPaint(0, 0, new Color(213, 213, 255), 0, 600, Color.WHITE));
 g2.fillRect(0, 0, 800, 600);
 
 //Draw the title text
 g2.setFont(new Font("Tahoma", Font.BOLD, 48));
 g.setColor(Color.BLACK);
 int textY = 200;
 for (String s : level.getTitle().split("\n")) {
 drawCenteredString(s, 400, textY += g.getFontMetrics().getHeight(), g);
 }
 }
 
 if (gameState != LEVEL) {
 if (muted) {
 g.drawImage(VOLUME_BLACK_MUTE, 760, -12, null);
 } else {
 g.drawImage(VOLUME_BLACK, 760, -12, null);
 }
 }
 
 g.dispose();
 }
 
 
 
 
 
 public void actionPerformed(ActionEvent arg0) {
 repaint();
 }
 
 
 
 
 
 /** Draw a string centered on its x axis.
 * 
 * @param text
 * the text to be drawn
 * @param x
 * the x coordinate of the text
 * @param y
 * the y coordinate of the text
 * @param g
 * the graphics the text will be drawn with
 */
 private void drawCenteredString(String s, int w, int h, Graphics g) {
 FontMetrics fm = g.getFontMetrics();
 int x = (w*2 - fm.stringWidth(s)) / 2;
 g.drawString(s, x, h);
 }
 
 
 
 
 
 /** Draw a string centered on its x axis.
 * 
 * @param text
 * the text to be drawn
 * @param x
 * the x coordinate of the text
 * @param y
 * the y coordinate of the text
 * @param g2
 * the 2D graphics the text will be drawn with
 */
 private void drawCenteredString(String s, int w, int h, Graphics2D g2) {
 FontMetrics fm = g2.getFontMetrics();
 int x = (w*2 - fm.stringWidth(s)) / 2;
 g2.drawString(s, x, h);
 }
 
 
 
 
 
 /** Draw a right-justified string.
 * 
 * @param text
 * the text to be drawn
 * @param x
 * the x coordinate of the text
 * @param y
 * the y coordinate of the text
 * @param g2
 * the 2D graphics the text will be drawn with
 */
 private void drawRightJustifiedString(String s, int w, int h, Graphics g) {
 FontMetrics fm = g.getFontMetrics();
 int x = (w - fm.stringWidth(s));
 g.drawString(s, x, h);
 }
 
 
 
 
 
 /** Draw the outline of a string of text.
 * 
 * @param text
 * the text to be drawn
 * @param x
 * the x coordinate of the text
 * @param y
 * the y coordinate of the text
 * @param thickness
 * the thickness of the outline
 * @param g2
 * the 2D graphics the text will be drawn with
 */
 private void drawTextOutline(String text, int x, int y, int thickness, Graphics2D g2) {
 TextLayout tl = new TextLayout(text, g2.getFont(), new FontRenderContext(null,false,false));
 AffineTransform textAt = new AffineTransform();
 textAt.translate(x, y);
 g2.setStroke(new BasicStroke(thickness));
 g2.draw(tl.getOutline(textAt));
 g2.setStroke(new BasicStroke());
 }
 
 
 
 
 
 /** Draw a string, with the use of \n implemented.
 * 
 * @param text
 * the text to be drawn
 * @param x
 * the x coordinate of the text
 * @param y
 * the y coordinate of the text
 * @param g
 * the graphics the text will be drawn with
 */
 private void drawString(String text, int x, int y, Graphics g) {
 for (String line : text.split("\n"))
 g.drawString(line, x, y += g.getFontMetrics().getHeight());
 }
 
 
 
 
 
 /**
 * Convert an exception to a String with full stack trace
 * 
 * @param ex
 * the exception
 * @return A string with the full stacktrace error text
 */
 public static String getStringFromStackTrace(Throwable ex) {
 if (ex == null) {
 return "";
 }
 StringWriter str = new StringWriter();
 PrintWriter writer = new PrintWriter(str);
 try {
 ex.printStackTrace(writer);
 return str.getBuffer().toString();
 } finally {
 try {
 str.close();
 writer.close();
 } catch (IOException e) {
 // ignore
 }
 }
 }
 
 
 
 
 
 /**
 * Easily log a string of text, and write it to the log file
 * 
 * @param logger
 * The logger for the string to be logged with
 * @param level
 * The level of the logger
 * @param s
 * The string of text to be logged
 */
 static void easyLog(Logger logger, Level level, String s) {
 if (doLogging) {
 logger.setLevel(level);
 
 if (level == Level.CONFIG) logger.config(s);
 else if (level == Level.FINE) logger.fine(s);
 else if (level == Level.FINER) logger.finer(s);
 else if (level == Level.FINEST) logger.finest(s);
 else if (level == Level.INFO) logger.info(s);
 else if (level == Level.SEVERE) logger.severe(s);
 else if (level == Level.WARNING) logger.warning(s);
 
 else {
 logger.setLevel(Level.WARNING);
 logger.warning("Logging error");
 }
 
 TextFileWriter.appendToFile(logFilePath, new SimpleDateFormat(
 "MMM dd, YYYY h:mm:ss a").format(new Date())
 + " net.thedanpage.worldshardestgame easyLog\n" + level + ": " + s);
 }
 }
 
 
 
 
 
 public static void main(String[] args) {
 
 int option = JOptionPane.showConfirmDialog(
 new Dialog(frame, true),
 "Would you like to enable logging to " + System.getProperty("user.home") + "/worldshardestgame/logs?",
 "Setup",
 JOptionPane.YES_NO_OPTION);
 if (option == JOptionPane.YES_OPTION) Game.doLogging = true;
 else Game.doLogging = false;
 
 if (Game.doLogging) {
 
 //Create directory for logs if it does not exist
 if (!new File(System.getProperty("user.home") + "/worldshardestgame/logs").isDirectory()) {
 new File(System.getProperty("user.home") + "/worldshardestgame/logs").mkdirs();
 }
 
 if (new File(Game.logFilePath + ".zip").exists()) {
 LogZipper.unzip(
 System.getProperty("user.home") + "/worldshardestgame/logs", Game.logFilePath + ".zip");
 new File(Game.logFilePath + ".zip").delete();
 }
 
 try {
 if (new File(Game.logFilePath).exists() && new BufferedReader(new FileReader(Game.logFilePath)).readLine() != null) {
 TextFileWriter.appendToFile(Game.logFilePath, "\n");
 }
 } catch (IOException e) {
 Game.easyLog(Game.logger, Level.WARNING, Game.getStringFromStackTrace(e));
 }
 }
 
 try {
 while (new File(ClassLoader
 .getSystemResource("net/thedanpage/worldshardestgame/resources/maps/level_" + (totalLevels+1) + ".txt").toURI())
 .exists()) {
 totalLevels++;
 }
 } catch (Exception e) {
 System.out.println("Total levels: " + totalLevels);
 }
 
 Game.easyLog(Game.logger, Level.INFO, "Starting The World's Hardest Game");
 
 TinySound.init();
 Game.easyLog(Game.logger, Level.INFO, "TinySound initialized");
 
 if (Game.muted) TinySound.setGlobalVolume(0);
 
 Input.init();
 Game.easyLog(Game.logger, Level.INFO, "Input initialized");
 
 frame.setTitle("World's Hardest Game");
 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 frame.setSize(new Dimension(800, 622));
 frame.setResizable(false);
 frame.setLocationRelativeTo(null);
 
 game = new Game();
 frame.add(game);
 
 frame.setIconImage(new ImageIcon(ClassLoader.getSystemResource("net/thedanpage/worldshardestgame/resources/favicon.png")).getImage());
 frame.setVisible(true);
 }
 
}

GameLevel.java

package net.thedanpage.worldshardestgame;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.logging.Level;
public class GameLevel {
 
 @Override
 public String toString() {
 return "GameLevel [spawnPoint=" + spawnPoint + ", id=" + id
 + ", levelTitle=" + levelTitle + ", tileMap=" + tileMap
 + ", dots=" + dots + ", coins=" + coins + ", levelArea="
 + levelArea + "]";
 }
 /** Spawn point of the level. */
 private Point spawnPoint;
 
 /** The ID of the level. The first level has an ID of 1. */
 private int id;
 
 /** The message that is displayed before the level. */
 private String levelTitle;
 
 /** A list of all of the level's tiles. */
 private ArrayList<Tile> tileMap;
 
 /** A list of all of the level's dots. */
 public ArrayList<Dot> dots;
 
 /** A list of all of the level's coins. **/
 public ArrayList<Coin> coins;
 
 /** The area of the level, not including background tiles. */
 Area levelArea;
 
 public GameLevel() {
 this.levelArea = new Area();
 this.tileMap = new ArrayList<Tile>();
 this.dots = new ArrayList<Dot>();
 this.spawnPoint = new Point(20, 20);
 this.id = -1;
 this.levelTitle = "\"Intimidating message\nhere\"";
 }
 
 public GameLevel(Point spawn, int id) {
 this.levelArea = new Area();
 this.tileMap = new ArrayList<Tile>();
 this.dots = new ArrayList<Dot>();
 this.spawnPoint = spawn;
 this.id = id;
 this.levelTitle = "\"Intimidating message\nhere\"";
 }
 
 /**
 * @return spawnPoint
 */
 public Point getSpawnPoint() {
 return this.spawnPoint;
 }
 
 /**
 * @return id
 */
 public int getID() {
 return this.id;
 }
 
 /**
 * @return tileMap
 */
 public ArrayList<Tile> getTileMap() {
 return this.tileMap;
 }
 
 /**
 * @return levelTitle
 */
 public String getTitle() {
 return this.levelTitle;
 }
 
 
 
 /** Draw the tiles based on a text file in the maps package. 
 * 
 * 
 * */
 public void drawTiles(Graphics g) {
 
 Graphics2D g2 = (Graphics2D) g;
 
 try {
 /*for (Tile t : this.tileMap) {
 //Background
 if (t.getType() == 0) {
 g.setColor(new Color(180, 181, 254));
 g.fillRect(t.getX(), t.getY(), 40, 40);
 }
 }*/
 
 g.setColor(new Color(180, 181, 254));
 g.fillRect(0, 22, 800, 622);
 
 //Border around level
 g2.setColor(Color.BLACK);
 g2.fill(this.levelArea);
 
 for (Tile t : this.tileMap) {
 
 t.draw(this, g);
 
 }
 } catch (Exception e) {
 System.out.println("File not found.");
 TextFileWriter.appendToFile(Game.logFilePath, Game.getStringFromStackTrace(e));
 }
 }
 
 
 
 public void drawDots(Graphics g) {
 for (Dot dot : this.dots) dot.draw(g);
 }
 
 
 
 public void updateDots() {
 if (this.dots != null)
 for (Dot dot : this.dots) dot.update();
 }
 
 
 
 public void drawCoins(Graphics g) {
 if (this.coins != null)
 for (Coin coin : this.coins) coin.draw(g);
 }
 
 
 
 public boolean allCoinsCollected() {
 if (this.coins != null) {
 for (Coin coin : this.coins) {
 if (!coin.collected) return false;
 }
 }
 return true;
 }
 
 
 
 /**
 * Load the current level data from
 * net.thedanpage.worldshardestgame.resources.maps
 */
 public void init(Player player, int levelNum) {
 
 if (ClassLoader.getSystemResource("net/thedanpage/worldshardestgame/resources/maps/level_" + levelNum + ".txt") != null)
 Game.easyLog(Game.logger, Level.INFO, "The file for level " + levelNum + " has been found");
 else Game.easyLog(Game.logger, Level.SEVERE, "The file for level " + levelNum + " could not be found");
 
 Game.easyLog(Game.logger, Level.INFO, "Level " + Game.levelNum + " is being initialized");
 
 //Clears the tile data
 this.tileMap = new ArrayList<Tile>();
 
 //Clears the dot data
 this.dots = new ArrayList<Dot>();
 
 //Clears the coin data
 this.coins = new ArrayList<Coin>();
 
 //Clears the level area data
 this.levelArea = new Area();
 
 //Resets the level title
 this.levelTitle = "\"Intimidating message\nhere\"";
 
 try {
 this.spawnPoint = new Point(
 Integer.parseInt(PropLoader
 .loadProperty("spawn_point",
 "net/thedanpage/worldshardestgame/resources/maps/level_" + levelNum + ".properties")
 .split(",")[0]) * 40 + 20,
 Integer.parseInt(PropLoader
 .loadProperty("spawn_point",
 "net/thedanpage/worldshardestgame/resources/maps/level_" + levelNum + ".properties")
 .split(",")[1]) * 40 + 20);
 
 this.id = Integer.parseInt(PropLoader.loadProperty("level_id",
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".properties"));
 
 this.levelTitle = PropLoader.loadProperty("level_title", 
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".properties").toString();
 
 String coinData = null;
 
 //Retrieves the coin data
 if (PropLoader.loadProperty("coins", 
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".properties") != "null") {
 coinData = PropLoader.loadProperty("coins", 
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".properties");
 }
 
 if (coinData != null) {
 coinData = coinData.replaceAll("\\Z", "");
 
 if (coinData.contains("-")) {
 
 String[] coins = coinData.split("-");
 for (String s : coins) this.coins.add(new Coin((int) (Double.parseDouble(s.split(",")[0]) * 40),
 (int) (Double.parseDouble(s.split(",")[1]) * 40)));
 
 } else this.coins.add(new Coin((int) (Double.parseDouble(coinData.split(",")[0]) * 40),
 (int) (Double.parseDouble(coinData.split(",")[1]) * 40)));
 }
 Game.easyLog(Game.logger, Level.INFO, "All coins have been added");
 
 //Retrieves the tile data
 InputStreamReader isr = new InputStreamReader(ClassLoader
 .getSystemResource(
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".txt").openStream());
 String content = "";
 Scanner scanner = new Scanner(isr);
 content = scanner.useDelimiter("\\Z").next();
 scanner.close();
 
 Game.easyLog(Game.logger, Level.INFO, "Level data:\n\n" + content);
 
 content = content.replaceAll("\n", "");
 for (int i = 0; i < content.length(); i++) {
 if (i > 299)
 break;
 else
 this.tileMap.add(new Tile((i % 20) * 40, (i / 20) * 40,
 Character.getNumericValue(content.charAt(i))));
 }
 this.levelArea = new Area();
 for (Tile t : this.tileMap) {
 if (t.getType() != 0) {
 this.levelArea.add(new Area(
 new Rectangle(t.getX() - 3, t.getY() - 3 + 22, 46, 46)));
 }
 }
 } catch (Exception e) {
 Game.easyLog(Game.logger, Level.SEVERE, "Map unable to be loaded:\n" + Game.getStringFromStackTrace(e));
 }
 //Retrieves the dot data
 try {
 InputStreamReader isr = new InputStreamReader(ClassLoader
 .getSystemResource(
 "net/thedanpage/worldshardestgame/resources/maps/level_"
 + levelNum + ".txt").openStream());
 Scanner scanner = new Scanner(isr);
 String content = scanner.useDelimiter("\\Z").next();
 String[] lines = content.split("\n");
 scanner.close();
 for (int i=19; lines[i] != null; i++) {
 String line = lines[i];
 String[] dotData = line.replaceAll(" ", "").split("-");
 this.dots.add(new Dot(
 Integer.parseInt(dotData[0]),
 Integer.parseInt(dotData[1]),
 new Point(Integer.parseInt(dotData[2].split(",")[0]),
 Integer.parseInt(dotData[2].split(",")[1])),
 new Point(Integer.parseInt(dotData[3].split(",")[0]),
 Integer.parseInt(dotData[3].split(",")[1])),
 Double.parseDouble(dotData[4]),
 Boolean.parseBoolean(dotData[5]),
 Boolean.parseBoolean(dotData[6])
 ));
 }
 Game.easyLog(Game.logger, Level.INFO, "All dots have been added");
 } catch (Exception e) {
 if (e.getClass().getName() != "java.lang.ArrayIndexOutOfBoundsException")
 Game.easyLog(Game.logger, Level.SEVERE, "Dots unable to be loaded:\n" + Game.getStringFromStackTrace(e));
 }
 if (this.tileMap.size() == 300) Game.easyLog(Game.logger, Level.INFO, "All tiles have been added");
 else Game.easyLog(Game.logger, Level.WARNING, "Not all tiles were added");
 
 player.respawn(this);
 }
}

Player.java

package net.thedanpage.worldshardestgame;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;
import java.util.logging.Level;
import kuusisto.tinysound.Sound;
import kuusisto.tinysound.TinySound;
public class Player {
 
 /** The X coordinate of the player. */
 private int x;
 /** The Y coordinate of the player. */
 private int y;
 /**
 * The X coordinate of the player, snapped to the grid of 40x40 tiles.
 * snapX = x/40
 */
 private int snapX;
 /**
 * The Y coordinate of the player, snapped to the grid of 40x40 tiles.
 * snapY = y/40
 */
 private int snapY;
 /** True if the player is colliding with a tile above them. */
 private boolean collidingUp;
 /** True if the player is colliding with a tile below them. */
 private boolean collidingDown;
 /** True if the player is colliding with a tile to their left. */
 private boolean collidingLeft;
 /** True if the player is colliding with a tile to their right. */
 private boolean collidingRight;
 
 /** The smack sound. */
 Sound smack;
 
 /** The number of times the player has died. */
 private int deaths;
 
 /** True if the player has been hit and is not allowed to move. */
 private boolean dead;
 
 /** The opacity of the player. */
 private double opacity;
 
 public Player() {
 this.x = 400;
 this.y = 300;
 this.snapX = x/40;
 this.snapY = y/40;
 this.collidingUp = false;
 this.collidingDown = false;
 this.collidingLeft = false;
 this.collidingRight = false;
 this.deaths = 0;
 this.dead = false;
 this.opacity = 255;
 }
 
 
 
 
 
 public Player(int x, int y) {
 this.x = x;
 this.y = y;
 this.snapX = x/40;
 this.snapY = y/40;
 this.collidingUp = false;
 this.collidingDown = false;
 this.collidingLeft = false;
 this.collidingRight = false;
 this.deaths = 0;
 this.dead = false;
 this.opacity = 255;
 }
 
 
 
 
 
 public void draw(Graphics g) {
 g.setColor(new Color(0, 0, 0, (int) opacity));
 g.fillRect(x - 15, y - 15 + 22, 31, 31);
 g.setColor(new Color(255, 0, 0, (int) opacity));
 g.fillRect(x-12, y-12 + 22,
 25, 25);
 }
 
 
 
 
 
 Tile getRelativeTile(GameLevel level, int x1, int y1, int xOff, int yOff) {
 for (Tile t : level.getTileMap()) {
 if (x1/40 + xOff == t.getSnapX() && y1/40 + yOff == t.getSnapY()) {
 return t;
 }
 }
 return null;
 }
 
 
 
 
 
 Tile getTile(GameLevel level) {
 for (Tile t : level.getTileMap()) {
 if (this.x/40 == t.getSnapX() && this.y/40 == t.getSnapY()) {
 return t;
 }
 }
 return null;
 }
 
 
 
 
 
 boolean doesIntersect(Rectangle a, Rectangle b) {
 return (a.x + a.width < b.x || a.x > b.x + b.width
 || a.y + a.height < b.y || a.y > b.y + b.height);
 }
 
 
 
 
 
 public Rectangle getBounds() {
 return new Rectangle(this.x - 15, this.y - 15, 31, 31);
 }
 
 
 
 
 
 void checkCollisionUp(GameLevel level) {
 if (getRelativeTile(level, this.x - 14, this.y + 24, 0, -1) != null &&
 getRelativeTile(level, this.x - 14, this.y + 24, 0, -1).getType() == 0 ||
 getRelativeTile(level, this.x + 15, this.y + 24, 0, -1) != null &&
 getRelativeTile(level, this.x + 15, this.y + 24, 0, -1).getType() == 0) {
 this.collidingUp = true;
 return;
 }
 this.collidingUp = false;
 }
 
 
 
 
 
 void checkCollisionDown(GameLevel level) {
 if (getRelativeTile(level, this.x - 14, this.y - 24, 0, 1) != null &&
 getRelativeTile(level, this.x - 14, this.y - 24, 0, 1).getType() == 0 ||
 getRelativeTile(level, this.x + 15, this.y - 24, 0, 1) != null &&
 getRelativeTile(level, this.x + 15, this.y - 24, 0, 1).getType() == 0) {
 this.collidingDown = true;
 return;
 }
 this.collidingDown = false;
 }
 
 
 
 
 
 void checkCollisionLeft(GameLevel level) {
 if (getRelativeTile(level, this.x + 24, this.y - 15, -1, 0) != null &&
 getRelativeTile(level, this.x + 24, this.y - 15, -1, 0).getType() == 0 ||
 getRelativeTile(level, this.x + 24, this.y + 14, -1, 0) != null &&
 getRelativeTile(level, this.x + 24, this.y + 14, -1, 0).getType() == 0) {
 this.collidingLeft = true;
 return;
 }
 this.collidingLeft = false;
 }
 
 
 
 
 
 void checkCollisionRight(GameLevel level) {
 if (getRelativeTile(level, this.x - 24, this.y - 15, 1, 0) != null &&
 getRelativeTile(level, this.x - 24, this.y - 15, 1, 0).getType() == 0 ||
 getRelativeTile(level, this.x - 24, this.y + 15, 1, 0) != null &&
 getRelativeTile(level, this.x - 24, this.y + 15, 1, 0).getType() == 0) {
 this.collidingRight = true;
 return;
 }
 this.collidingRight = false;
 }
 
 
 
 
 
 void respawn(GameLevel level) {
 this.x = level.getSpawnPoint().x;
 this.y = level.getSpawnPoint().y;
 if (level.coins != null) {
 for (Coin coin : level.coins) coin.collected = false;
 }
 }
 
 
 
 
 
 boolean collidesWith(Shape other) {
 return this.getBounds().getBounds2D().intersects(other.getBounds2D());
 }
 
 
 
 
 
 public void update(GameLevel level) {
 this.snapX = this.x / 40;
 this.snapY = this.y / 40;
 
 if (level.coins != null) {
 for (Coin coin : level.coins) {
 if (this.collidesWith(coin.getBounds()) && !coin.collected) {
 coin.collected = true;
 
 //Coin sound
 TinySound.init();
 TinySound.loadSound(Player.class.getClassLoader()
 .getResource("net/thedanpage/worldshardestgame/resources/ding.wav")).play();
 }
 }
 }
 
 if (level.getTileMap() != new ArrayList<Tile>()) {
 
 if (level.allCoinsCollected()) {
 
 for (Tile t : level.getTileMap()) {
 
 if (t.getType() == 3 && this.collidesWith(t.getBounds())) {
 
 Game.levelNum ++;
 level.init(this, Game.levelNum);
 Game.gameState = Game.LEVEL_TITLE;
 Game.easyLog(Game.logger, Level.INFO, "Game state set to LEVEL_TITLE");
 
 //Wait 1.75 seconds then start the level.
 new Thread() {
 public void run() {
 try {
 Thread.sleep(1750);
 } catch (InterruptedException e) {
 Game.easyLog(Game.logger, Level.SEVERE, Game.getStringFromStackTrace(e));
 }
 Game.gameState = Game.LEVEL;
 Game.easyLog(Game.logger, Level.INFO, "Game state set to LEVEL");
 }
 }.start();
 }
 }
 }
 }
 
 checkCollisionUp(level);
 checkCollisionDown(level);
 checkCollisionLeft(level);
 checkCollisionRight(level);
 
 if (this.dead) {
 this.opacity -= 255/75;
 
 if (this.opacity < 0) this.opacity = 0;
 
 if (this.opacity == 0) {
 this.dead = false;
 this.opacity = 255;
 this.respawn(level);
 }
 } else {
 if (Input.up.isPressed && !this.collidingUp) this.y --;
 if (Input.down.isPressed && !this.collidingDown) this.y ++;
 if (Input.left.isPressed && !this.collidingLeft) this.x --;
 if (Input.right.isPressed && !this.collidingRight) this.x ++;
 }
 
 if (this.x > 800) this.x = 0;
 if (this.x < 0) this.x = 800;
 if (this.y > 600) this.y = 0;
 if (this.y < 0) this.y = 600;
 
 if (!this.dead) {
 for (Dot dot : level.dots) {
 if (this.collidesWith(dot.getBounds())) {
 this.deaths ++;
 this.dead = true;
 
 if (!Game.muted) {
 //Play the smack sound
 TinySound.init();
 TinySound.loadSound(ClassLoader.getSystemResource(
 "net/thedanpage/worldshardestgame/resources/smack.wav")).play();
 }
 }
 }
 }
 }
 
 
 
 
 
 public int getX() {
 return this.x;
 }
 
 
 
 public int getY() {
 return this.y;
 }
 
 
 
 public int getSnapX() {
 return this.snapX;
 }
 
 
 
 public int getSnapY() {
 return this.snapY;
 }
 
 
 
 public int getWidth() {
 return (int) this.getBounds().getWidth();
 }
 
 
 
 public int getHeight() {
 return (int) this.getBounds().getHeight();
 }
 
 
 
 public boolean isCollidingLeft() {
 return this.collidingLeft;
 }
 
 
 
 public boolean isCollidingRight() {
 return this.collidingRight;
 }
 
 
 
 public boolean isCollidingUp() {
 return this.collidingUp;
 }
 
 
 
 public boolean isCollidingDown() {
 return this.collidingDown;
 }
 
 
 
 public int getDeaths() {
 return this.deaths;
 }
 
 
 
 public boolean isDead() {
 return this.dead;
 }
 
 
 
 public void setDead(boolean dead) {
 this.dead = dead;
 }
 
 
 
 public double getOpacity() {
 return this.opacity;
 }
 
 
 
 public void reset() {
 this.x = 400;
 this.y = 300;
 this.snapX = x/40;
 this.snapY = y/40;
 this.collidingUp = false;
 this.collidingDown = false;
 this.collidingLeft = false;
 this.collidingRight = false;
 this.deaths = 0;
 this.dead = false;
 this.opacity = 255;
 }
 @Override
 public String toString() {
 return "Player [x=" + x + ", y=" + y + ", snapX=" + snapX + ", snapY="
 + snapY + ", collidingUp=" + collidingUp + ", collidingDown="
 + collidingDown + ", collidingLeft=" + collidingLeft
 + ", collidingRight=" + collidingRight + ", deaths=" + deaths
 + ", dead=" + dead + "]";
 }
}

TextFileWriter.java

package net.thedanpage.worldshardestgame;
// JavaFileAppendFileWriterExample.java
// Created by <a href="http://alvinalexander.com" title="http://alvinalexander.com">http://alvinalexander.com</a>
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class TextFileWriter {
 static BufferedWriter bw = null;
 public static void appendToFile(String filepath, String s) {
 try {
 // APPEND MODE SET HERE
 bw = new BufferedWriter(new FileWriter(filepath, true));
 bw.write(s);
 bw.newLine();
 bw.flush();
 } catch (IOException e) {
 System.out.println(e);
 } finally { // always close the file
 if (bw != null)
 try {
 bw.close();
 } catch (IOException ioe2) {
 // just ignore it
 }
 } // end try/catch/finally
 }
} // end class

LogZipper.java

package net.thedanpage.worldshardestgame;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
public class LogZipper {
 public static void zipLog() {
 byte[] buffer = new byte[1024];
 try {
 FileOutputStream fos = new FileOutputStream(
 Game.logFilePath + ".zip");
 ZipOutputStream zos = new ZipOutputStream(fos);
 ZipEntry ze = new ZipEntry(Game.logFilePath.replace(
 System.getProperty("user.home")
 + "/worldshardestgame/logs/", ""));
 zos.putNextEntry(ze);
 FileInputStream in = new FileInputStream(Game.logFilePath);
 int len;
 while ((len = in.read(buffer)) > 0) {
 zos.write(buffer, 0, len);
 }
 in.close();
 zos.closeEntry();
 // remember close it
 zos.close();
 
 if (new File(Game.logFilePath).exists()) new File(Game.logFilePath).delete();
 } catch (IOException ex) {
 ex.printStackTrace();
 }
 }
 
 public static void unzipLog() {
 try {
 ZipFile zipFile = new ZipFile(Game.logFilePath + ".zip");
 Enumeration<?> enu = zipFile.entries();
 while (enu.hasMoreElements()) {
 ZipEntry zipEntry = (ZipEntry) enu.nextElement();
 
 String name = zipEntry.getName();
 
 File file = new File(name);
 if (name.endsWith("/")) {
 file.mkdirs();
 continue;
 }
 
 File parent = file.getParentFile();
 if (parent != null) {
 parent.mkdirs();
 }
 
 InputStream is = zipFile.getInputStream(zipEntry);
 FileOutputStream fos = new FileOutputStream(file);
 byte[] bytes = new byte[1024];
 int length;
 while ((length = is.read(bytes)) >= 0) {
 fos.write(bytes, 0, length);
 }
 is.close();
 fos.close();
 
 }
 zipFile.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 
 public static void unzip(String destinationFolder, String zipFile) {
 File directory = new File(destinationFolder);
 
 // if the output directory doesn't exist, create it
 if(!directory.exists()) 
 directory.mkdirs();
 // buffer for read and write data to file
 byte[] buffer = new byte[2048];
 
 try {
 FileInputStream fInput = new FileInputStream(zipFile);
 ZipInputStream zipInput = new ZipInputStream(fInput);
 
 ZipEntry entry = zipInput.getNextEntry();
 
 while(entry != null){
 String entryName = entry.getName();
 File file = new File(destinationFolder + File.separator + entryName);
 
 System.out.println("Unzipping file " + entryName + " to " + file.getAbsolutePath());
 
 // create the directories of the zip directory
 if(entry.isDirectory()) {
 File newDir = new File(file.getAbsolutePath());
 if(!newDir.exists()) {
 boolean success = newDir.mkdirs();
 if(success == false) {
 System.out.println("Problem creating Folder");
 }
 }
 }
 else {
 FileOutputStream fOutput = new FileOutputStream(file);
 int count = 0;
 while ((count = zipInput.read(buffer)) > 0) {
 // write 'count' bytes to the file output stream
 fOutput.write(buffer, 0, count);
 }
 fOutput.close();
 }
 // close ZipEntry and take the next one
 zipInput.closeEntry();
 entry = zipInput.getNextEntry();
 }
 
 // close the last ZipEntry
 zipInput.closeEntry();
 
 zipInput.close();
 fInput.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
}
Post Closed as "Not suitable for this site" by Community Bot, Mathieu Guindon
added 3 characters in body
Source Link
Dan95363
  • 143
  • 2
  • 6

I was wondering if someone could quickly skim over this for me really quickly and tell me if there's anything I could improve code-wise. What I have right now seems pretty big and clustered, and I'm almost positive that there's a way it can be compressed and made more efficient, and maybe even faster. I'm also hopeful for a way to remove the threads in my code if possible. Thanks for the help :P

By the way, this game is an attempted remake of The World's Hardest Game by Snubby Land and Armor Games, and it can be played here: http://armorgames.com/play/1043/the-worlds-hardest-game

I was wondering if someone could quickly skim over this for me really quickly and tell me if there's anything I could improve code-wise. What I have right now seems pretty big and clustered, and I'm almost positive that there's a way it can be compressed and made more efficient, and maybe even faster. I'm also hopeful for a way to remove the threads in my code if possible. Thanks for the help :P

By the way, this game an attempted remake of The World's Hardest Game by Snubby Land and Armor Games, and it can be played here: http://armorgames.com/play/1043/the-worlds-hardest-game

I was wondering if someone could quickly skim over this for me really quickly and tell me if there's anything I could improve code-wise. What I have right now seems pretty big and clustered, and I'm almost positive that there's a way it can be compressed and made more efficient, and maybe even faster. I'm also hopeful for a way to remove the threads in my code if possible. Thanks for the help :P

By the way, this game is an attempted remake of The World's Hardest Game by Snubby Land and Armor Games, and it can be played here: http://armorgames.com/play/1043/the-worlds-hardest-game

Source Link
Dan95363
  • 143
  • 2
  • 6
Loading
lang-java

AltStyle によって変換されたページ (->オリジナル) /