diff --git a/.gitignore b/.gitignore index a1c2a23..5c0636e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,11 @@ # Mobile Tools for Java (J2ME) .mtj.tmp/ +# Custom +out/ +profiles/ +unused/ + # Package Files # *.jar *.war @@ -21,3 +26,59 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +#*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet diff --git a/MetroidMapGuardian/.classpath b/MetroidMapGuardian/.classpath new file mode 100644 index 0000000..b5455e0 --- /dev/null +++ b/MetroidMapGuardian/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/MetroidMapGuardian/.project b/MetroidMapGuardian/.project new file mode 100644 index 0000000..f69c995 --- /dev/null +++ b/MetroidMapGuardian/.project @@ -0,0 +1,47 @@ + + + MetroidMapGuardian + A map viewer and powerup collector for the Metroid Prime Trilogy. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + full,incremental, + + + LaunchConfigHandle + <project>/builder.launch + + + + + + org.eclipse.jdt.core.javanature + + + + 1558289867571 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-bin + + + + 1558289867580 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-profiles + + + + diff --git a/MetroidMapGuardian/build.xml b/MetroidMapGuardian/build.xml new file mode 100644 index 0000000..c891593 --- /dev/null +++ b/MetroidMapGuardian/build.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/MetroidMapGuardian/builder.launch b/MetroidMapGuardian/builder.launch new file mode 100644 index 0000000..e74bc0c --- /dev/null +++ b/MetroidMapGuardian/builder.launch @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/MetroidMapGuardian/src/entity/Entity.java b/MetroidMapGuardian/src/entity/Entity.java new file mode 100644 index 0000000..54d68fc --- /dev/null +++ b/MetroidMapGuardian/src/entity/Entity.java @@ -0,0 +1,208 @@ +package entity; + +import java.awt.Graphics2D; + +import nbt.NBTTagCompound; + +import room.Room; +import game.GameInstance; +import game.Trilogy; +import geometry.Rectangle; +import geometry.Vector; + +/** + * A base class for all objects that are contained in, and interact with the map. + * + * @author Robert Jordan + * + * @see + * {@linkplain Map}, + * {@linkplain GameInstance} + */ +public abstract class Entity { + + // =================== Private Members ==================== + + /** + * The last known direction of the entity. This is used when + * the entities velocity is 0. + */ + private double lastDirection; + + // ==================== Public Members ==================== + + /** The game this entity is linked to. */ + public GameInstance instance; + public Trilogy trilogy; + /** The room that contains this entity. */ + public Room room; + /** + * A string that represents a way to access the entity without receiving + * information about it in advance. + */ + public String id; + /** + * The draw depth of the entity, entities with higher depths will draw + * before entities with lower depths. + */ + public int depth; + /** The position on the map of the entity. */ + public Vector position; + /** The speed of the entity in units per update. */ + public Vector velocity; + + public Rectangle bounds; + /** True if the entity has been destroyed. */ + public boolean destroyed; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + protected Entity() { + this.instance = null; + this.trilogy = null; + this.room = null; + + this.id = ""; + this.depth = 0; + + this.position = new Vector(); + this.velocity = new Vector(); + this.lastDirection = 0.0; + + } + /** + * Constructs an entity with the specified details. + * + * @param id - The key identifier of the entity. + * @param depth - The depth of the entity. + * @param position - The position of the entity. + * @param velocity - The velocity of the entity. + * @return Returns an entity with the specified details. + */ + protected Entity(String id, int depth, Vector position, Vector velocity) { + this.instance = null; + this.trilogy = null; + this.room = null; + + this.id = id; + this.depth = depth; + + this.position = new Vector(position); + this.velocity = new Vector(velocity); + this.lastDirection = 0.0; + + } + /** + * Constructs the entity from an NBT compound of values. This is mainly used + * To load entire maps from file in NBT format. + * + * @param nbt - The compound containing the tags related to the entity. + * @return Returns the entity constructed from tag data. + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ + protected Entity(NBTTagCompound nbt) { + instance = null; + trilogy = null; + room = null; + + id = nbt.getString("id", ""); + depth = nbt.getInteger("depth"); + + if (nbt.hasKey("speed") || nbt.hasKey("direction")) + velocity = new Vector(nbt.getDouble("speed"), nbt.getDouble("direction"), true); + else + velocity = new Vector(nbt.getDouble("hspeed"), nbt.getDouble("vspeed")); + position = new Vector(nbt.getDouble("x"), nbt.getDouble("y")); + lastDirection = nbt.getDouble("direction"); + + } + /** + * Initializes the entity by setting the game instance it is linked to. + * + * @param room - The room that contains the entity. + * @param instance - The game instance that contains the room. + */ + public void initialize(Room room, GameInstance instance, Trilogy trilogy) { + this.room = room; + this.trilogy = trilogy; + this.instance = instance; + } + + // ===================== NBT File IO ====================== + + /** + * Saves tag information about the entity to the NBT compound. + * + * @param nbt - The NBT compound to save tag information to. + * + * @see + * {@linkplain NBTTagCompound} + */ + public void saveEntity(NBTTagCompound nbt) { + nbt.setString( "id", id); + nbt.setInteger( "depth", depth); + nbt.setDouble( "x", position.x); + nbt.setDouble( "y", position.y); + nbt.setDouble( "hspeed", velocity.x); + nbt.setDouble( "vspeed", velocity.y); + nbt.setDouble( "lastDirection", lastDirection); + } + /** + * Saves the entity to an NBT compound tag. + * + * @return Returns the NBT compound containing the values on the entity. + * + * @see + * {@linkplain NBTTagCompound} + */ + public abstract NBTTagCompound saveEntity(); + /** + * Creates an entity based on the information given from an NBT compound. The + * entity must first be defined in EntityLoader in order to be loaded from a + * map file. + * + * @param nbt - The NBT compound containing tag information on the entity. + * @return Returns an entity constructed from the specified tag information. + * + * @see + * {@linkplain NBTTagCompound}, + * {@linkplain EntityLoader} + */ + public abstract Entity loadEntity(NBTTagCompound nbt); + + // ======================== Updating ======================== + + /** + * Called every step for the entity to perform actions and update. + */ + public void update() { + + // Update position + position.add(velocity); + + } + /** + * Called every step for the entity to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + } + /** + * Destroys the entity and marks it for removal. + */ + public void destroy() { + destroyed = true; + } + +} + diff --git a/MetroidMapGuardian/src/entity/EntityLoader.java b/MetroidMapGuardian/src/entity/EntityLoader.java new file mode 100644 index 0000000..b71d427 --- /dev/null +++ b/MetroidMapGuardian/src/entity/EntityLoader.java @@ -0,0 +1,51 @@ +package entity; + +import java.util.HashMap; + +import nbt.NBTTagCompound; + +public class EntityLoader { + + // ==================== Static Members ==================== + + /** The map that contains entities linked to class names. */ + private static HashMap entityMap = new HashMap(); + + // ==================== Static Methods ==================== + + /** + * Registers a class name with the specified entity so it can be linked + * during map construction. + * + * @param className - The class name for the entity. + * @param entity - The entity class to register. + */ + private static void register(String className, Entity entity) { + entityMap.put(className, entity); + } + /** + * Called at the beginning of the program to register and link all class + * names to entities. + */ + public static void registerEntities() { + + // Living + register("Marker", new Marker()); + } + /** + * Creates an entity based on the information given from an NBT compound. + * + * @param nbt - The NBT compound containing tag information on the entity. + * @return Returns the loaded entity. + */ + public static Entity loadEntity(NBTTagCompound nbt) { + + String className = nbt.getString("class", ""); + + if (entityMap.containsKey(className)) + return entityMap.get(className).loadEntity(nbt); + + return null; + } + +} diff --git a/MetroidMapGuardian/src/entity/Marker.java b/MetroidMapGuardian/src/entity/Marker.java new file mode 100644 index 0000000..2f18b4d --- /dev/null +++ b/MetroidMapGuardian/src/entity/Marker.java @@ -0,0 +1,311 @@ +package entity; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RadialGradientPaint; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; + +import javax.swing.JOptionPane; + +import room.Room; +import game.GameInstance; +import game.PowerUp; +import game.Profile; +import game.Trilogy; +import geometry.Rectangle; +import geometry.Vector; +import graphics.Draw; +import graphics.MarkerDetails; +import graphics.PopupMarkerDetails; +import graphics.ScalableImage; +import main.Keyboard; +import main.Mouse; +import nbt.NBTTagCompound; + +/** + * The marker used for checking off items completed on the map. Each marker + * stores and index and type of the power up, the power up information is + * then looked up based on that information. + * + * @author Robert Jordan + * @see + * {@linkplain PowerUp} + */ +public class Marker extends Entity { + + // ==================== Static Members ==================== + + /** The image to display when the marker has been checked off. */ + public static ScalableImage imageChecked = new ScalableImage("checked", "", + BufferedImage.TYPE_INT_ARGB, RenderingHints.VALUE_INTERPOLATION_BICUBIC, 1.0); + /** The image to display when the marker is unchecked and unchecked markers are visible. */ + public static ScalableImage imageUnchecked = new ScalableImage("unchecked", "", + BufferedImage.TYPE_INT_ARGB, RenderingHints.VALUE_INTERPOLATION_BICUBIC, 1.0); + + // ======================= Members ======================== + + /** The name of the marker type. */ + public int type; + /** The index of the marker. */ + public int index; + /** The secondary type of the marker. */ + public int linkedType; + /** The secondary index of the marker. */ + public int linkedIndex; + + /** True if the mouse is hovering over the marker. */ + public boolean hovering; + /** A debug feature used in the editor. */ + public boolean placing; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a marker. + * + * @return Returns the default marker. + */ + public Marker() { + super(); + this.type = 0; + this.index = 0; + this.linkedType = -1; + this.linkedIndex = 0; + + this.hovering = false; + this.placing = false; + } + /** + * Constructs a marker at the given coordinates. + * + * @param type - The name of the marker type. + * @param index - The index of the marker. + * @return Returns a marker at the given coordinates. + */ + public Marker(int type, int index) { + super(); + this.type = type; + this.index = index; + this.linkedType = -1; + this.linkedIndex = 0; + + this.hovering = false; + this.placing = false; + } + /** + * Constructs the entity from an NBT compound of values. This is mainly used + * To load entire maps from file in NBT format. + * + * @param nbt - The compound containing the tags related to the entity. + * @return Returns the entity constructed from tag data. + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ + public Marker(NBTTagCompound nbt) { + super(nbt); + this.type = nbt.getInteger("type", 0); + this.index = nbt.getInteger("index", 0); + this.linkedType = nbt.getInteger("linkedType", -1); + this.linkedIndex = nbt.getInteger("linkedIndex", 0); + + this.hovering = false; + this.placing = false; + + if (linkedType == type) { + linkedType = -1; + linkedIndex = 0; + } + } + /** + * Initializes the entity by setting the game instance it is linked to. + * + * @param room - The room that contains the entity. + * @param instance - The game instance that contains the room. + */ + public void initialize(Room room, GameInstance instance, Trilogy trilogy) { + super.initialize(room, instance, trilogy); + } + + // ===================== NBT File IO ====================== + + /** + * Saves tag information about the entity to the NBT compound. + * + * @param nbt - The NBT compound to save tag information to. + * + * @see + * {@linkplain NBTTagCompound} + */ + public void saveEntity(NBTTagCompound nbt) { + super.saveEntity(nbt); + + nbt.setInteger( "type", type); + nbt.setInteger( "index", index); + nbt.setInteger( "linkedType", linkedType); + nbt.setInteger( "linkedIndex", linkedIndex); + } + /** + * Saves the entity to an NBT compound tag. + * + * @return Returns the NBT compound containing the values on the entity. + * + * @see + * {@linkplain NBTTagCompound} + */ + public NBTTagCompound saveEntity() { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setString("class", "Marker"); + saveEntity(nbt); + return nbt; + } + /** + * Creates an entity based on the information given from an NBT compound. The + * entity must first be defined in EntityLoader in order to be loaded from a + * map file. + * + * @param nbt - The NBT compound containing tag information on the entity. + * @return Returns an entity constructed from the specified tag information. + * + * @see + * {@linkplain NBTTagCompound}, + * {@linkplain EntityLoader} + */ + public Marker loadEntity(NBTTagCompound nbt) { + return new Marker(nbt); + } + + // ======================== Updating ======================== + + /** + * Called every step for the entity to perform actions and update. + */ + public void update() { + + double radius = (double)imageChecked.getWidth() / 2.0; + Vector radiusVec = new Vector(radius, radius); + Rectangle rect = new Rectangle(position.minus(radiusVec), radiusVec.scaledBy(2.0)); + + if (rect.contains(room.view.getMousePoint()) && !room.isMouseOverGUI) { + // Create the marker display + if (!hovering) { + room.addGui(new MarkerDetails(this)); + } + hovering = true; + + if (Mouse.left.pressed() && !instance.editorMode) { + trilogy.checkPowerUp(type, index); + if (linkedType != -1) + trilogy.checkPowerUp(linkedType, linkedIndex); + new Profile(instance).saveProfile(); + } + else if (Mouse.right.pressed() && !instance.editorMode) { + room.addGui(new PopupMarkerDetails(this)); + } + } + else { + hovering = false; + } + + if (instance.editorMode) { + try { + if (placing) { + position = room.view.getMousePoint(); + if (Mouse.middle.released()) + placing = false; + } + else if (hovering) { + if (Mouse.left.pressed()) { + if (Keyboard.control.down() && !Keyboard.shift.down()) { + String num = JOptionPane.showInputDialog(null, "New Marker Index", Integer.toString(index + 1), JOptionPane.OK_CANCEL_OPTION); + index = Integer.parseInt(num) - 1; + Keyboard.reset(); + Mouse.reset(); + } + else if (Keyboard.control.down() && Keyboard.shift.down()) { + String num = JOptionPane.showInputDialog(null, "New Marker Linked Index", Integer.toString(linkedIndex + 1), JOptionPane.OK_CANCEL_OPTION); + linkedIndex = Integer.parseInt(num) - 1; + Keyboard.reset(); + Mouse.reset(); + } + else if (!Keyboard.control.down() && Keyboard.shift.down()) { + String num = JOptionPane.showInputDialog(null, "New Marker Linked Type", Integer.toString(linkedType), JOptionPane.OK_CANCEL_OPTION); + linkedType = Integer.parseInt(num); + Keyboard.reset(); + Mouse.reset(); + } + else { + trilogy.checkPowerUp(type, index); + if (linkedType != -1) + trilogy.checkPowerUp(linkedType, linkedIndex); + } + } + else if (Mouse.right.pressed()) { + destroy(); + } + } + } + catch (NumberFormatException e) { + + } + } + + super.update(); + } + /** + * Called every step for the entity to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + double radius = (double)imageChecked.getWidth() / 2.0 * imageChecked.getScale(); + Vector point = room.view.getViewPoint(position); + + Vector radiusVec = new Vector(radius, radius); + + // Draw check image + if (getPowerUp().collected) + Draw.drawImage(g, imageChecked.getScaledImage(), point.minus(radiusVec)); + else if(instance.showUncheckedMarkers) + Draw.drawImage(g, imageUnchecked.getScaledImage(), point.minus(radiusVec)); + + // Draw the bright circle to emphasize highlighting + if (hovering) { + g.setPaint(new RadialGradientPaint((float)point.x, (float)point.y, (float)radius, new float[]{0.0f, 1.0f}, + new Color[]{new Color(255, 255, 255, 200), new Color(255, 255, 255, 20)})); + + Draw.fillEllipse(g, point, radiusVec, true); + } + + // Draw a red circle to aid in placing + if (placing) { + g.setColor(new Color(255, 0, 0)); + Draw.drawEllipse(g, point, radiusVec, true); + } + + } + + // ==================== Marker Methods ==================== + + /** + * Called when the mouse is hovering over the marker. + */ + public PowerUp getPowerUp() { + return trilogy.getPowerUp(type, index); + } + /** + * Called when the mouse is hovering over the marker. + */ + public PowerUp getLinkedPowerUp() { + return trilogy.getPowerUp(linkedType, linkedIndex); + } + public boolean hasLinkedPowerUp() { + return linkedType != -1; + } + +} + + diff --git a/MetroidMapGuardian/src/entity/Surge.java b/MetroidMapGuardian/src/entity/Surge.java new file mode 100644 index 0000000..d64f4ea --- /dev/null +++ b/MetroidMapGuardian/src/entity/Surge.java @@ -0,0 +1,148 @@ +package entity; + +import game.GameInstance; +import game.Trilogy; +import geometry.Vector; +import graphics.Draw; + +import java.awt.Color; +import java.awt.Graphics2D; + +import room.Room; +import main.Main; +import nbt.NBTTagCompound; + +/** + * + * @author Robert Jordan + * + */ +public class Surge extends Entity { + + // ======================= Members ======================== + + /** The length of the surge. */ + public int length; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a marker. + * + * @return Returns the default marker. + */ + public Surge() { + super(); + this.length = 80; + this.velocity.y = 2; + } + /** + * Constructs a marker at the given coordinates. + * + * @param type - The name of the marker type. + * @param index - The index of the marker. + * @return Returns a marker at the given coordinates. + */ + public Surge(double x, double vspeed, int length) { + super(); + this.length = length; + this.velocity.y = vspeed; + if (vspeed < 0.0) + this.position = new Vector(x, Main.frame.getHeight()); + else + this.position = new Vector(x, -length); + } + /** + * Constructs the entity from an NBT compound of values. This is mainly used + * To load entire maps from file in NBT format. + * + * @param nbt - The compound containing the tags related to the entity. + * @return Returns the entity constructed from tag data. + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ + public Surge(NBTTagCompound nbt) { + super(nbt); + this.length = nbt.getInteger("length"); + } + /** + * Initializes the entity by setting the game instance it is linked to. + * + * @param room - The room that contains the entity. + * @param instance - The game instance that contains the room. + */ + public void initialize(Room room, GameInstance instance, Trilogy trilogy) { + super.initialize(room, instance, trilogy); + } + + // ===================== NBT File IO ====================== + + /** + * Saves tag information about the entity to the NBT compound. + * + * @param nbt - The NBT compound to save tag information to. + * + * @see + * {@linkplain NBTTagCompound} + */ + public void saveEntity(NBTTagCompound nbt) { + super.saveEntity(nbt); + + nbt.setInteger( "length", length); + } + /** + * Saves the entity to an NBT compound tag. + * + * @return Returns the NBT compound containing the values on the entity. + * + * @see + * {@linkplain NBTTagCompound} + */ + public NBTTagCompound saveEntity() { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setString("class", "Surge"); + saveEntity(nbt); + return nbt; + } + /** + * Creates an entity based on the information given from an NBT compound. The + * entity must first be defined in EntityLoader in order to be loaded from a + * map file. + * + * @param nbt - The NBT compound containing tag information on the entity. + * @return Returns an entity constructed from the specified tag information. + * + * @see + * {@linkplain NBTTagCompound}, + * {@linkplain EntityLoader} + */ + public Surge loadEntity(NBTTagCompound nbt) { + return new Surge(nbt); + } + + // ======================== Updating ======================== + + /** + * Called every step for the entity to perform actions and update. + */ + public void update() { + super.update(); + + if ((velocity.y < 0.0 && position.y < -length) || + (velocity.y > 0.0 && position.y > Main.frame.getContentPane().getHeight())) { + destroy(); + } + } + /** + * Called every step for the entity to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + g.setColor(new Color(50, 70, 100)); + Draw.drawLine(g, position, position.plus(0, length)); + } + +} diff --git a/MetroidMapGuardian/src/game/GameInstance.java b/MetroidMapGuardian/src/game/GameInstance.java new file mode 100644 index 0000000..87e0bd5 --- /dev/null +++ b/MetroidMapGuardian/src/game/GameInstance.java @@ -0,0 +1,304 @@ +package game; + +import geometry.Vector; +import graphics.Draw; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.event.KeyEvent; +import java.util.ArrayList; + +import javax.swing.JOptionPane; + +import entity.Marker; +import main.ImageLoader; +import main.Keyboard; +import main.Mouse; +import nbt.NBTElement; +import nbt.NBTTagCompound; +import nbt.NBTTagList; + +import room.Map; +import room.Menu; +import room.Room; + +/** + * The instance that stores all game information. + * + * @author Robert Jordan + * @see + * {@linkplain Profile}, + * {@linkplain Trilogy}, + * {@linkplain Map} + */ +public class GameInstance { + + // ======================= Members ======================== + + public static boolean PROGRAMMER_MODE = false; + + /** The list of trilogies. */ + public ArrayList trilogies; + /** The index of the current trilogy. */ + public int currentTrilogy; + /** The current trilogy. */ + public Trilogy trilogy; + /** The name of the current profile to save to. */ + public String profileName; + /** The current room that is running. */ + public Room room; + public Menu menu; + public boolean inMenu; + + /** Setting to show unchecked markers as red chozo symbols. */ + public boolean showUncheckedMarkers; + + // ===================== Debug Mode ======================= + + /** True if editor mode is enabled to place power ups. */ + public boolean editorMode; + /** The current power up to place in editor mode. */ + public int currentPowerUp; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + public GameInstance() { + + editorMode = false; + currentPowerUp = PowerUp.MISSILE_EXPANSION; + showUncheckedMarkers = false; + profileName = ""; + trilogies = new ArrayList(); + inMenu = true; + menu = new Menu(); + + NBTTagCompound nbt = NBTElement.loadNBTCompound("/resources/data/map.dat", true).getCompound("MetroidMapData"); + NBTTagList trilogyList = nbt.getList("trilogies"); + + for (NBTElement tag : trilogyList.getTags()) { + Trilogy t = new Trilogy((NBTTagCompound)tag); + trilogies.add(t); + } + + trilogy = trilogies.get(0); + } + /** + * Initializes game instance. + */ + public void initialize() { + + for (Trilogy t : trilogies) { + t.initialize(this); + } + changeTrilogy(1); + menu.initialize(this, null); + } + + // ======================== Updating ======================== + + /** + * Called every step for the game to perform actions and update. + */ + public void update() { + + if (Keyboard.getKey(KeyEvent.VK_S).pressed() && editorMode) { + NBTTagCompound root = new NBTTagCompound("root"); + NBTTagCompound nbt = new NBTTagCompound("MetroidMapData"); + NBTTagList trilogyList = new NBTTagList("trilogies", NBTElement.TAG_COMPOUND); + + for (Trilogy t : trilogies) { + NBTTagCompound trilogyTag = new NBTTagCompound(); + trilogyTag.setString("name", t.name); + trilogyTag.setString("rawName", t.rawName); + trilogyTag.setByte("game", (byte)t.game); + NBTTagList mapList = new NBTTagList("maps", NBTElement.TAG_COMPOUND); + + for (Map m : t.maps) { + NBTTagCompound mapTag = m.saveRoom(); + mapList.addCompound(mapTag); + } + + trilogyTag.setList("maps", mapList); + trilogyList.addCompound(trilogyTag); + } + nbt.setList("trilogies", trilogyList); + root.setCompound("MetroidMapData", nbt); + NBTElement.saveNBTCompound("map.dat", root); + System.out.println("Levels Saved in New Format."); + } + else if (Keyboard.getKey(KeyEvent.VK_L).pressed() && editorMode) { + NBTTagCompound nbt = NBTElement.loadNBTCompound("map.dat", false); + nbt = nbt.getCompound("MetroidMaps", null); + for (Trilogy t : trilogies) { + NBTTagCompound game = nbt.getCompound(t.rawName, null); + for (int i = 0; i < t.maps.size(); i++) { + NBTTagCompound map = game.getCompound(t.maps.get(i).rawName, null); + t.maps.set(i, t.maps.get(i).loadRoom(map)); + t.maps.get(i).initialize(this, t); + } + t.map = t.maps.get(t.currentMap); + } + System.out.println("Levels Loaded."); + } + + if (Keyboard.getKey(KeyEvent.VK_F4).pressed() && PROGRAMMER_MODE) + editorMode = !editorMode; + + + if (Keyboard.getKey(KeyEvent.VK_1).pressed()) + currentPowerUp = 0; + if (Keyboard.getKey(KeyEvent.VK_2).pressed()) + currentPowerUp = 1; + if (Keyboard.getKey(KeyEvent.VK_3).pressed()) + currentPowerUp = 2; + if (Keyboard.getKey(KeyEvent.VK_4).pressed()) + currentPowerUp = 3; + if (Keyboard.getKey(KeyEvent.VK_5).pressed()) + currentPowerUp = 4; + if (Keyboard.getKey(KeyEvent.VK_6).pressed()) + currentPowerUp = 5; + if (Keyboard.getKey(KeyEvent.VK_7).pressed()) + currentPowerUp = 6; + if (Keyboard.getKey(KeyEvent.VK_8).pressed()) + currentPowerUp = 7; + if (Keyboard.getKey(KeyEvent.VK_9).pressed()) + currentPowerUp = 8; + if (Keyboard.getKey(KeyEvent.VK_0).pressed()) + currentPowerUp = 9; + if (Keyboard.getKey(KeyEvent.VK_MINUS).pressed()) + currentPowerUp = 10; + + if (Keyboard.insert.pressed()) { + showUncheckedMarkers = !showUncheckedMarkers; + } + if (Keyboard.enter.pressed() && editorMode) { + ArrayList> collection = new ArrayList>(); + for(int i = 0; i < trilogy.powerUps.size(); i++) { + collection.add(new ArrayList()); + for (int j = 0; j < trilogy.powerUps.get(i).size(); j++) { + collection.get(i).add(0); + } + } + for (int i = 0; i < trilogy.maps.size(); i++) { + for (int j = 0; j < trilogy.maps.get(i).entities.size(); j++) { + if (trilogy.maps.get(i).entities.get(j) instanceof Marker) { + Marker marker = (Marker)trilogy.maps.get(i).entities.get(j); + collection.get(marker.type).set(marker.index, collection.get(marker.type).get(marker.index) + 1); + if (marker.hasLinkedPowerUp()) { + collection.get(marker.linkedType).set(marker.linkedIndex, collection.get(marker.linkedType).get(marker.linkedIndex) + 1); + } + } + } + } + int type = -1; + int index = 0; + for(int i = 0; i < collection.size(); i++) { + for (int j = 0; j < collection.get(i).size(); j++) { + if (collection.get(i).get(j) != 1) { + type = i; + index = j; + } + } + } + if (type != -1) { + boolean zero = (collection.get(type).get(index) == 0); + JOptionPane.showMessageDialog(null, "Number of power-ups for " + trilogy.getPowerUp(type, index).getTypeName() + + ": " + trilogy.getPowerUp(type, index).name + " is " + + (zero ? "less than" : "greater than") + " one.", "Power Up Collection Check", JOptionPane.ERROR_MESSAGE); + Keyboard.reset(); + Mouse.reset(); + + } + else { + JOptionPane.showMessageDialog(null, "All collectables are correct", "Power Up Collection Check", JOptionPane.PLAIN_MESSAGE); + Keyboard.reset(); + Mouse.reset(); + + } + } + + // Update the map + if (inMenu) + menu.update(); + else + trilogy.map.update(); + } + /** + * Called every step for the game to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); + g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + + // Draw the map + if (inMenu) + menu.draw(g); + else + trilogy.map.draw(g); + + if (editorMode) { + g.setFont(new Font("Eurostar Black", Font.PLAIN, 16)); + Stroke oldStroke = g.getStroke(); + g.setStroke(new BasicStroke(2.2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + //g.setColor(Color.WHITE); + g.setColor(Color.BLACK); + Draw.drawStringOutline(g, PowerUp.getPowerUpName(currentPowerUp), 24, 160, 0);//Draw.ALIGN_TOP); + g.setStroke(oldStroke); + + //g.setColor(new Color(33, 189, 222)); + g.setColor(Color.WHITE); + Draw.drawString(g, PowerUp.getPowerUpName(currentPowerUp), 24, 160, 0);//Draw.ALIGN_TOP); + oldStroke = g.getStroke(); + g.setStroke(new BasicStroke(0.3f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + //g.setColor(Color.WHITE); + g.setColor(Color.BLACK); + //Draw.drawStringOutline(g, PowerUp.getPowerUpName(currentPowerUp), 24, 160, 0);//Draw.ALIGN_TOP); + g.setStroke(oldStroke); + } + } + + public void changeTrilogy(int game) { + trilogy.map.image.unloadScaledImage(); + ImageLoader.unloadImage(trilogy.rawName + "/maps/" + trilogy.map.rawName, trilogy.rawName); + currentTrilogy = game - 1; + trilogy = trilogies.get(game - 1); + ImageLoader.loadImage(trilogy.rawName + "/maps/" + trilogy.map.rawName, trilogy.rawName); + } + + public void loadProfile(Profile profile) { + + profileName = profile.profileName; + currentTrilogy = profile.currentTrilogy; + trilogy = trilogies.get(currentTrilogy); + + for (int i = 0; i < trilogies.size(); i++) { + TrilogyInfo t = profile.trilogies.get(i); + trilogies.get(i).currentMap = t.currentMap; + trilogies.get(i).map = trilogies.get(i).maps.get(t.currentMap); + for (int j = 0; j < t.powerUpsCollected.size(); j++) { + for (int k = 0; k < t.powerUpsCollected.get(j).size(); k++) { + trilogies.get(i).powerUps.get(j).get(k).collected = t.powerUpsCollected.get(j).get(k); + } + } + for (int j = 0; j < t.mapPans.size(); j++) { + trilogies.get(i).maps.get(j).view.pan = new Vector(t.mapPans.get(j)); + trilogies.get(i).maps.get(j).view.zoom = t.mapZooms.get(j); + } + } + trilogy.changeMap(trilogy.currentMap); + } +} diff --git a/MetroidMapGuardian/src/game/PowerUp.java b/MetroidMapGuardian/src/game/PowerUp.java new file mode 100644 index 0000000..25baad8 --- /dev/null +++ b/MetroidMapGuardian/src/game/PowerUp.java @@ -0,0 +1,237 @@ +package game; + +import java.awt.Color; +import java.awt.Image; + +import main.ImageLoader; + +/** + * The class used to store data about each collectable in each game. PowerUps + * are referenced by Marker entities in maps. + * + * @author Robert Jordan + * @see + * {@linkplain Marker} + */ +public class PowerUp { + + // =================== Static Variables =================== + + /** The number of power up types. */ + public static final int NUM_TYPES = 11; + + public static final int SUIT_EXPANSION = 0; + public static final int MISSILE_EXPANSION = 1; + public static final int ENERGY_TANK = 2; + public static final int POWER_BOMB = 3; + + public static final int ARTIFACT = 4; + + public static final int BEAM_AMMO_EXPANSION = 5; + public static final int TEMPLE_KEY = 6; + public static final int SKY_TEMPLE_KEY = 7; + + public static final int SHIP_MISSILE_EXPANSION = 8; + public static final int ENERGY_CELL = 9; + public static final int RED_PHAZOID = 10; + + // ======================= Members ======================== + + /** The type of the power up. */ + public int type; + /** The name of the power up. */ + public String name; + /** The location of the power up. */ + public String location; + /** The description to acquire the power up. */ + public String description; + /** True if the power up has been checked off. */ + public boolean collected; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a power up as a suit expansion. + * + * @return Returns the default power up. + */ + public PowerUp() { + this.type = 0; + this.name = ""; + this.location = ""; + this.description = ""; + this.collected = false; + } + /** + * Constructs a power up of the given type. + * + * @param type - The type of power up. + * @return Returns the power up of the specified type. + */ + public PowerUp(int type) { + this.type = type; + this.name = ""; + this.location = ""; + this.description = ""; + this.collected = false; + } + + // ======================= Methods ======================== + + /** + * Gets the type name. + * + * @return Returns the name of the type. + */ + public String getTypeName() { + return getPowerUpName(type); + } + /** + * Gets the type color used for the marker on the mini map. + * + * @return Returns the mini map marker color. + */ + public Color getTypeColor() { + switch (type) { + /* Global Power Ups */ + case SUIT_EXPANSION: return new Color(255, 233, 0); + case MISSILE_EXPANSION: return new Color(255, 127, 39); + case ENERGY_TANK: return new Color(102, 232, 255); + case POWER_BOMB: return new Color(154, 58, 156); + + /* Metroid Prime 1 */ + case ARTIFACT: return new Color(188, 176, 95); + + /* Metroid Prime 2 */ + case BEAM_AMMO_EXPANSION: return new Color(157, 2, 251); + case TEMPLE_KEY: return new Color(243, 82, 82); + case SKY_TEMPLE_KEY: return new Color(96, 204, 201); + + /* Metroid Prime 3 */ + case SHIP_MISSILE_EXPANSION: return new Color(32, 220, 5); + case ENERGY_CELL: return new Color(36, 217, 208); + case RED_PHAZOID: return new Color(255, 74, 74); + } + return null; + } + + // ==================== Static Methods ==================== + + /** + * Tests whether the power up is in the specified game. + * + * @param type - The power up type. + * @param game - The game to check with. + * @return Returns true if the power up type is in the game. + */ + public static boolean isPowerUpInGame(int type, int game) { + switch (type) { + /* Global Power Ups */ + case SUIT_EXPANSION: return true; + case MISSILE_EXPANSION: return true; + case ENERGY_TANK: return true; + case POWER_BOMB: return (game == 1 || game == 2); + + /* Metroid Prime 1 */ + case ARTIFACT: return (game == 1); + + /* Metroid Prime 2 */ + case BEAM_AMMO_EXPANSION: return (game == 2); + case TEMPLE_KEY: return (game == 2); + case SKY_TEMPLE_KEY: return (game == 2); + + /* Metroid Prime 3 */ + case SHIP_MISSILE_EXPANSION: return (game == 3); + case ENERGY_CELL: return (game == 3); + case RED_PHAZOID: return (game == 3); + } + return false; + } + /** + * Gets the image icon for the power up type. + * + * @param type - The power up type. + * @return Returns the image of the power up type. + */ + public static Image getPowerUpIcon(int type) { + switch (type) { + /* Global Power Ups */ + case SUIT_EXPANSION: return ImageLoader.getImage("suit_expansion"); + case MISSILE_EXPANSION: return ImageLoader.getImage("missile_expansion"); + case ENERGY_TANK: return ImageLoader.getImage("energy_tank"); + case POWER_BOMB: return ImageLoader.getImage("power_bomb"); + + /* Metroid Prime 1 */ + case ARTIFACT: return ImageLoader.getImage("artifact"); + + /* Metroid Prime 2 */ + case BEAM_AMMO_EXPANSION: return ImageLoader.getImage("beam_ammo_expansion"); + case TEMPLE_KEY: return ImageLoader.getImage("dark_temple_key"); + case SKY_TEMPLE_KEY: return ImageLoader.getImage("sky_temple_key"); + + /* Metroid Prime 3 */ + case SHIP_MISSILE_EXPANSION: return ImageLoader.getImage("ship_missile_expansion"); + case ENERGY_CELL: return ImageLoader.getImage("energy_cell"); + case RED_PHAZOID: return ImageLoader.getImage("red_phazoid"); + } + return null; + } + /** + * Gets the raw name for the power up type. + * + * @param type - The power up type. + * @return Returns the raw name of the power up type. + */ + public static String getPowerUpRawName(int type) { + switch (type) { + /* Global Power Ups */ + case SUIT_EXPANSION: return "suit_expansions"; + case MISSILE_EXPANSION: return "missile_expansions"; + case ENERGY_TANK: return "energy_tanks"; + case POWER_BOMB: return "power_bombs"; + + /* Metroid Prime 1 */ + case ARTIFACT: return "artifacts"; + + /* Metroid Prime 2 */ + case BEAM_AMMO_EXPANSION: return "beam_ammo_expansions"; + case TEMPLE_KEY: return "dark_temple_keys"; + case SKY_TEMPLE_KEY: return "sky_temple_keys"; + + /* Metroid Prime 3 */ + case SHIP_MISSILE_EXPANSION: return "ship_missile_expansions"; + case ENERGY_CELL: return "energy_cells"; + case RED_PHAZOID: return "red_phazoids"; + } + return ""; + } + /** + * Gets the name for the power up type. + * + * @param type - The power up type. + * @return Returns the name of the power up type. + */ + public static String getPowerUpName(int type) { + switch (type) { + /* Global Power Ups */ + case SUIT_EXPANSION: return "Suit Expansion"; + case MISSILE_EXPANSION: return "Missile Expansion"; + case ENERGY_TANK: return "Energy Tank"; + case POWER_BOMB: return "Power Bomb"; + + /* Metroid Prime 1 */ + case ARTIFACT: return "Artifact"; + + /* Metroid Prime 2 */ + case BEAM_AMMO_EXPANSION: return "Beam Ammo Expansion"; + case TEMPLE_KEY: return "Dark Temple Key"; + case SKY_TEMPLE_KEY: return "Sky Temple Key"; + + /* Metroid Prime 3 */ + case SHIP_MISSILE_EXPANSION: return "Ship Missile Expansion"; + case ENERGY_CELL: return "Energy Cell"; + case RED_PHAZOID: return "Red Phaazoid"; + } + return ""; + } +} diff --git a/MetroidMapGuardian/src/game/Profile.java b/MetroidMapGuardian/src/game/Profile.java new file mode 100644 index 0000000..01545ad --- /dev/null +++ b/MetroidMapGuardian/src/game/Profile.java @@ -0,0 +1,216 @@ +package game; + +import geometry.Vector; + +import java.util.ArrayList; + +import nbt.NBTElement; +import nbt.NBTTagCompound; +import nbt.NBTTagList; + +import main.Game; + +/** + * + * @author Robert Jordan + * + */ +public class Profile { + + // ======================= Members ======================== + + public String profileName; + + public int currentTrilogy; + + public ArrayList trilogies; + + + // ===================== Constructors ===================== + + /** + * + */ + public Profile() { + this.profileName = ""; + this.currentTrilogy = 0; + this.trilogies = new ArrayList(); + this.trilogies.add(new TrilogyInfo(1)); + this.trilogies.add(new TrilogyInfo(2)); + this.trilogies.add(new TrilogyInfo(3)); + } + + public Profile(String name) { + this.profileName = name; + this.currentTrilogy = 0; + this.trilogies = new ArrayList(); + this.trilogies.add(new TrilogyInfo(1)); + this.trilogies.add(new TrilogyInfo(2)); + this.trilogies.add(new TrilogyInfo(3)); + } + public Profile(String name, NBTTagCompound nbt) { + nbt = nbt.getCompound("MetroidProfileData"); + + this.profileName = name; + this.currentTrilogy = nbt.getByte("currentTrilogy"); + this.trilogies = new ArrayList(); + for (NBTElement tag : nbt.getList("trilogies").getTags()) { + TrilogyInfo t = new TrilogyInfo((NBTTagCompound)tag); + this.trilogies.add(t); + } + } + public Profile(GameInstance instance) { + this.profileName = instance.profileName; + this.currentTrilogy = instance.currentTrilogy; + this.trilogies = new ArrayList(); + for (Trilogy t : instance.trilogies) { + this.trilogies.add(new TrilogyInfo(t)); + } + } + + // ======================= Methods ======================== + + public int getCompletionPercentage(int game) { + TrilogyInfo t = trilogies.get(game - 1); + + int total = 0; + int collected = 0; + + for (int i = 0; i < t.powerUpsCollected.size(); i++) { + for (int j = 0; j < t.powerUpsCollected.get(i).size(); j++) { + total++; + if (t.powerUpsCollected.get(i).get(j)) + collected ++; + } + } + return (int)((double)collected / total * 100); + } + + public void saveProfile() { + NBTTagCompound root = new NBTTagCompound("root"); + NBTTagCompound nbt = new NBTTagCompound("MetroidProfileData"); + + nbt.setByte("currentTrilogy", (byte)currentTrilogy); + NBTTagList list = new NBTTagList("trilogies"); + for (TrilogyInfo t : trilogies) { + NBTTagCompound tag = new NBTTagCompound(); + tag.setByte("game", (byte)t.game); + tag.setInteger("currentMap", t.currentMap); + + NBTTagList powerUps = new NBTTagList("powerUpsCollected"); + for (int i = 0; i < t.powerUpsCollected.size(); i++) { + NBTTagList powerUpTypes = new NBTTagList(); + for (int j = 0; j < t.powerUpsCollected.get(i).size(); j++) { + powerUpTypes.addBoolean(t.powerUpsCollected.get(i).get(j)); + } + powerUps.addList(powerUpTypes); + } + tag.setList("powerUpsCollected", powerUps); + + NBTTagList maps = new NBTTagList("maps"); + for (int i = 0; i < t.mapPans.size(); i++) { + NBTTagCompound map = new NBTTagCompound(); + map.setDouble("x", t.mapPans.get(i).x); + map.setDouble("y", t.mapPans.get(i).y); + map.setDouble("zoom", t.mapZooms.get(i)); + maps.addCompound(map); + } + tag.setList("maps", maps); + list.addCompound(tag); + } + nbt.setList("trilogies", list); + root.setCompound("MetroidProfileData", nbt); + + NBTElement.saveNBTCompound("profiles/" + profileName + ".dat", root); + } +} + +/** + * + * @author Robert Jordan + * + */ +class TrilogyInfo { + + // ======================= Members ======================== + + /** The collection of power up collected states. */ + public ArrayList> powerUpsCollected; + + public ArrayList mapPans; + + public ArrayList mapZooms; + + public int currentMap; + + public int game; + + + // ===================== Constructors ===================== + + /** + * + */ + public TrilogyInfo(int game) { + this.game = game; + this.currentMap = 0; + this.mapPans = new ArrayList(); + this.mapZooms = new ArrayList(); + this.powerUpsCollected = new ArrayList>(); + + Trilogy t = Game.instance.trilogies.get(game - 1); + for (int i = 0; i < t.powerUps.size(); i++) { + this.powerUpsCollected.add(new ArrayList()); + for (int j = 0; j < t.powerUps.get(i).size(); j++) { + this.powerUpsCollected.get(i).add(false); + } + } + for (int i = 0; i < t.maps.size(); i++) { + this.mapPans.add(new Vector()); + this.mapZooms.add(1.0); + } + } + + public TrilogyInfo(NBTTagCompound nbt) { + this.game = nbt.getByte("game"); + this.currentMap = nbt.getInteger("currentMap"); + this.mapPans = new ArrayList(); + this.mapZooms = new ArrayList(); + this.powerUpsCollected = new ArrayList>(); + + Trilogy t = Game.instance.trilogies.get(game - 1); + for (int i = 0; i < t.powerUps.size(); i++) { + NBTTagList list = nbt.getList("powerUpsCollected").getList(i, new NBTTagList()); + this.powerUpsCollected.add(new ArrayList()); + + for (int j = 0; j < t.powerUps.get(i).size(); j++) { + this.powerUpsCollected.get(i).add(list.getBoolean(j)); + } + } + for (int i = 0; i < t.maps.size(); i++) { + NBTTagCompound map = nbt.getList("maps").getCompound(i, new NBTTagCompound()); + this.mapPans.add(new Vector(map.getDouble("x"), map.getDouble("y"))); + this.mapZooms.add(map.getDouble("zoom", 1.0)); + } + } + + public TrilogyInfo(Trilogy t) { + this.game = t.game; + this.currentMap = t.currentMap; + this.mapPans = new ArrayList(); + this.mapZooms = new ArrayList(); + this.powerUpsCollected = new ArrayList>(); + + for (int i = 0; i < t.powerUps.size(); i++) { + this.powerUpsCollected.add(new ArrayList()); + + for (int j = 0; j < t.powerUps.get(i).size(); j++) { + this.powerUpsCollected.get(i).add(t.powerUps.get(i).get(j).collected); + } + } + for (int i = 0; i < t.maps.size(); i++) { + this.mapPans.add(new Vector(t.maps.get(i).view.pan)); + this.mapZooms.add(t.maps.get(i).view.zoom); + } + } +} diff --git a/MetroidMapGuardian/src/game/Trilogy.java b/MetroidMapGuardian/src/game/Trilogy.java new file mode 100644 index 0000000..129d30b --- /dev/null +++ b/MetroidMapGuardian/src/game/Trilogy.java @@ -0,0 +1,167 @@ +package game; + +import java.util.ArrayList; +import java.util.Scanner; + +import main.ImageLoader; +import nbt.NBTElement; +import nbt.NBTTagCompound; + +import room.Map; + +/** + * + * @author Robert Jordan + * + */ +public class Trilogy { + + // ================== Private Variables =================== + + + // =================== Public Variables =================== + + public static final int METROID_PRIME = 1; + public static final int METROID_PRIME_ECHOES = 2; + public static final int METROID_PRIME_CORRUPTION = 3; + + // ======================= Members ======================== + + /** The game instance that contains this trilogy. */ + public GameInstance instance; + /** The list of maps for this trilogy. */ + public ArrayList maps; + /** The index of the current map. */ + public int currentMap; + /** The current map. */ + public Map map; + + /** The collection of power up descriptions and settings. */ + public ArrayList> powerUps; + /** The index of the game. */ + public int game; + /** The name of the game. */ + public String name; + /** The raw name of the game. */ + public String rawName; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + public Trilogy(NBTTagCompound nbt) { + + this.name = nbt.getString("name"); + this.rawName = nbt.getString("rawName"); + this.game = nbt.getByte("game"); + this.maps = new ArrayList(); + this.currentMap = 0; + + this.powerUps = new ArrayList>(); + for (int i = 0; i < PowerUp.NUM_TYPES; i++) { + this.powerUps.add(new ArrayList()); + } + + // Load the power up data + for (int i = 0; i < PowerUp.NUM_TYPES; i++) { + if (PowerUp.isPowerUpInGame(i, game)) { + try (Scanner reader = new Scanner(Trilogy.class.getResourceAsStream("/resources/text/" + this.rawName + "/" + PowerUp.getPowerUpRawName(i) + ".txt"))) { + + while (reader.hasNextLine()) { + PowerUp powerUp = new PowerUp(i); + reader.nextLine(); + powerUp.name = reader.nextLine(); + powerUp.location = reader.nextLine(); + powerUp.description = reader.nextLine(); + + this.powerUps.get(i).add(powerUp); + } + } + } + } + + // Load the maps + for (NBTElement tag : nbt.getList("maps", null).getTags()) { + this.maps.add(new Map((NBTTagCompound)tag)); + } + + this.map = this.maps.get(0); + } + /** + * Initializes the entity by setting the game instance it is linked to. + * + * @param room - The room that contains the entity. + * @param instance - The game instance that contains the room. + */ + public void initialize(GameInstance instance) { + this.instance = instance; + + for (Map m : maps) { + m.initialize(instance, this); + } + } + + // ======================= Methods ======================== + + public void changeMap(int index) { + map.image.unloadScaledImage(); + ImageLoader.unloadImage(rawName + "/maps/" + map.rawName, rawName); + currentMap = index; + map = maps.get(index); + ImageLoader.loadImage(rawName + "/maps/" + map.rawName, rawName); + } + /** + * Gets the power up details from the list of power ups + * + * @param type - The type of power up. + * @param index - The index of the power up. + * @return Returns the power up of the given type or an empty power up if + * the index was out of range. + */ + public PowerUp getPowerUp(int type, int index) { + if (index >= 0 && index < powerUps.get(type).size()) { + return powerUps.get(type).get(index); + } + return new PowerUp(type); + } + /** + * Checks or unchecks the power up of the given type. + * + * @param type - The type of power up. + * @param index - The index of the power up. + */ + public void checkPowerUp(int type, int index) { + if (index >= 0 && index < powerUps.get(type).size()) { + powerUps.get(type).get(index).collected = !powerUps.get(type).get(index).collected; + } + } + + public static String getRawName(int game) { + switch (game) { + case METROID_PRIME: return "metroid_prime_1"; + case METROID_PRIME_ECHOES: return "metroid_prime_2"; + case METROID_PRIME_CORRUPTION: return "metroid_prime_3"; + } + return ""; + } + + public int getCompletionPercentage() { + + int total = 0; + int collected = 0; + + for (int i = 0; i < powerUps.size(); i++) { + for (int j = 0; j < powerUps.get(i).size(); j++) { + total++; + if (powerUps.get(i).get(j).collected) + collected ++; + } + } + return (int)((double)collected / total * 100); + } + +} + diff --git a/MetroidMapGuardian/src/geometry/Ellipse.java b/MetroidMapGuardian/src/geometry/Ellipse.java new file mode 100644 index 0000000..da4e45b --- /dev/null +++ b/MetroidMapGuardian/src/geometry/Ellipse.java @@ -0,0 +1,298 @@ +package geometry; + +/** + * A basic rectangular shape with a point and size. This class is used for + * bounding boxes of other shapes and works as a basic collision hit box. + * + * @author Robert Jordan + * + * @see + * {@linkplain Vector}, + * {@linkplain Shape} + */ +public class Ellipse { + + // ======================= Members ======================== + + /** The corner of the ellipse. */ + public Vector point; + /** The size of the ellipse from the point. */ + public Vector size; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an ellipse with a point and size + * of (0, 0). + * + * @return Returns the default ellipse with a point and size of (0, 0). + */ + public Ellipse() { + this.point = new Vector(); + this.size = new Vector(); + } + /** + * Constructs an ellipse with the specified dimensions. + * + * @param x - The x coordinate of the ellipse. + * @param y - The y coordinate of the ellipse. + * @param w - The width of the ellipse. + * @param h - The height of the ellipse. + * @return Returns an ellipse with the given dimensions. + */ + public Ellipse(double x, double y, double w, double h) { + this.point = new Vector(x, y); + this.size = new Vector(w, h); + } + /** + * Constructs an ellipse with the specified dimensions. + * + * @param point - The point of the ellipse. + * @param size - The size of the ellipse. + * @return Returns an ellipse with the given dimensions. + */ + public Ellipse(Vector point, Vector size) { + this.point = point; + this.size = size; + } + /** + * Constructs an ellipse with the same point and size as the given one. + * + * @param e - The ellipse to copy. + * @return Returns an ellipse that is identical to the given one. + */ + public Ellipse(Ellipse e) { + this.point = e.point; + this.size = e.size; + } + + // ==================== Shape Details ===================== + + /** + * Returns the minimum point of the shape. + * + * @return Returns the minimum point of the shape. + */ + public Vector min() { + return Vector.min(point, point.plus(size)); + } + /** + * Returns the maximum point of the shape. + * + * @return Returns the maximum point of the shape. + */ + public Vector max() { + return Vector.max(point, point.plus(size)); + } + /** + * Calculates and returns the center of the shape. + * + * @return The position of the center of the shape. + */ + public Vector getCenter() { + return point.plus(size.scaledBy(0.5)); + } + /** + * Calculates and returns the bounding box of the shape. + * + * @return Returns the rectangle of the bounding box of the shape. + */ + public Rectangle getBounds() { + return new Rectangle(min(), max().minus(min())); + } + + // ================== Shape Modification ================== + + /** + * Returns the shape translated by the specified distance. + * + * @param v - The Vector of the distance to translate. + * @return Returns a translated shape. + */ + public Ellipse getTranslation(Vector v) { + return new Ellipse(this).translate(v); + } + /** + * Translates the shape by the specified distance. + * + * @param v - The Vector of the distance to translate. + * @return Returns the shape after it has been translated. + */ + public Ellipse translate(Vector v) { + point.add(v); + return this; + } + /** + * Returns the scaled shape. + * + * @param scale - The change in scale of the shape + * @return Returns a scaled shape. + */ + public Ellipse getScaled(double scale) { + return new Ellipse(this).scale(scale); + } + /** + * Returns the shape scaled around the specified anchor. + * + * @param anchor - The anchor to scale the shape around. + * @param scale - The change in scale of the shape + * @return Returns a scaled shape. + */ + public Ellipse getScaled(Vector anchor, double scale) { + return new Ellipse(this).scale(anchor, scale); + } + /** + * Scales the shape by the specified size. + * + * @param scale - The new scale of the shape + * @return Returns the shape after it has been scaled. + */ + public Ellipse scale(double scale) { + point.scale(scale); + size.scale(scale); + return this; + } + /** + * Scales the shape by the specified size around the specified anchor. + * + * @param anchor - The anchor to scale the shape around. + * @param scale - The new scale of the shape + * @return Returns the shape after it has been scaled. + */ + public Ellipse scale(Vector anchor, double scale) { + point.sub(anchor); + point.scale(scale); + point.add(anchor); + size.scale(scale); + return this; + } + /** + * Returns the rotated shape. + * + * @param anchor - The anchor to rotate the shape around. + * @param theta - The changed rotation of the shape + * @return Returns a rotated shape. + */ + public Ellipse getRotation(Vector anchor, double theta) { + return null; + } + /** + * Rotates the shape by the specified angle around the anchor. + * + * @param anchor - The anchor to rotate the shape around. + * @param theta - The new rotation of the shape + * @return Returns the shape after it has been rotated. + */ + public Ellipse rotate(Vector anchor, double theta) { + return null; + } + + // ==================== Contains Shape ==================== + + /** + * Tests if the specified point is inside the boundary of the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is inside the boundary of the shape. + */ + public boolean contains(Vector v) { + return false; + } + /** + * Tests if the specified line is inside the boundary of the shape. + * + * @param l - The line. + * @return Returns true if the line is inside the boundary of the shape. + */ + public boolean contains(Line l) { + return false; + } + /** + * Tests if the specified rectangle is inside the boundary of the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle is inside the boundary of the shape. + */ + public boolean contains(Rectangle r) { + return false; + } + + // =================== Intersects Shape =================== + + /** + * Tests if the specified point is on the boundary of the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is on the boundary of the shape. + */ + public boolean intersects(Vector v) { + return false; + } + /** + * Tests if the specified line intersects the boundary of the shape. + * + * @param l - The line. + * @return Returns true if the line intersects the boundary of the shape. + */ + public boolean intersects(Line l) { + return false; + } + /** + * Tests if the specified rectangle intersects the boundary of the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle intersects the boundary of the shape. + */ + public boolean intersects(Rectangle r) { + return false; + } + + // ==================== Touching Shape ==================== + + /** + * Tests if the specified point is colliding with the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is colliding with the shape. + */ + public boolean colliding(Vector v) { + return false; + } + /** + * Tests if the specified line is colliding with the shape. + * + * @param l - The line. + * @return Returns true if the line is colliding with the shape. + */ + public boolean colliding(Line l) { + return false; + } + /** + * Tests if the specified rectangle is colliding with the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle is colliding with the shape. + */ + public boolean colliding(Rectangle r) { + return false; + } + + // ================ Java Awt Compatibility ================ + + /** + * Creates and returns the Java Awt Shape of the shape. + * This function is used for compatibility with java.awt.geom shapes. + * + * @return The Java Awt Shape of the shape. + * + * @see + * {@linkplain java.awt.Shape}, + * {@linkplain java.awt.Rectangle2D.Double} + */ + public java.awt.geom.Ellipse2D.Double getShape() { + return new java.awt.geom.Ellipse2D.Double(point.x, point.y, size.x, size.y); + } + +} + + diff --git a/MetroidMapGuardian/src/geometry/GMath.java b/MetroidMapGuardian/src/geometry/GMath.java new file mode 100644 index 0000000..895841a --- /dev/null +++ b/MetroidMapGuardian/src/geometry/GMath.java @@ -0,0 +1,234 @@ +package geometry; + +import java.util.Random; + +/** + * A class that encapsulates many improved versions of static functions from Math. + * These functions are made for use in game calculations. + * + * @author Robert Jordan + * @author David Jordan + * + * @see + * {@linkplain Vector} + */ +public class GMath { + + // ====================== Constants ======================= + + /** Euler's constant. */ + public static final double E = Math.E; + /** The constant variable used in radian and circle calculations. */ + public static final double PI = Math.PI; + /** The value of PI times 2. */ + public static final double TWO_PI = 2.0 * PI; + /** The inverse value of PI, or 1 divided by PI. */ + public static final double INV_PI = 1.0 / PI; + /** The value of PI divided by 2. */ + public static final double HALF_PI = PI / 2.0; + /** The value of PI divided by 4. */ + public static final double QUARTER_PI = PI / 4.0; + /** The value of PI times 3/2. */ + public static final double THREE_HALVES_PI = TWO_PI - HALF_PI; + /** The value of the square root of PI. */ + public static final double ROOT_PI = Math.sqrt(PI); + /** + * The epsilon value used in double floating precision calculations. + * Values are considered equal if they are in range of each other + * within this epsilon. + * @see + *{@linkplain #inRange(double a, double b, double epsilon)} + */ + public static final double EPSILON = 1.1920928955078125E-7; + + /** + * This variable is true if the angles should be in degrees. Otherwise + * angles will be in radians. + * @see + * {@linkplain #FULL_ANGLE}, + * {@linkplain #THREE_FOURTHS_ANGLE}, + * {@linkplain #HALF_ANGLE}, + * {@linkplain #QUARTER_ANGLE} + */ + public static final boolean USE_DEGREES = true; + + /** + * The full angle value based on the USE_DEGREES constant. + * @see + * {@linkplain #USE_DEGREES} + */ + public static final double FULL_ANGLE = (USE_DEGREES ? 360.0 : TWO_PI); + /** + * The three fourths angle value based on the USE_DEGREES constant. + * @see + * {@linkplain #USE_DEGREES} + */ + public static final double THREE_FOURTHS_ANGLE = (USE_DEGREES ? 270.0 : THREE_HALVES_PI); + /** + * The half angle value based on the USE_DEGREES constant. + * @see + * {@linkplain #USE_DEGREES} + */ + public static final double HALF_ANGLE = (USE_DEGREES ? 180.0 : PI); + /** + * The quarter angle value based on the USE_DEGREES constant. + * @see + * {@linkplain #USE_DEGREES} + */ + public static final double QUARTER_ANGLE = (USE_DEGREES ? 90.0 : HALF_PI); + + // ====================== Variables ======================= + + /** The class used to generate random values. */ + public static Random random = new Random(); + + // ======================= Doubles ======================== + + /** + * Finds the minimum from the list of values. + * + * @param args - The list of values. + * @return Returns the minimum value from the list. + */ + public static double min(double... args) { + double min = args[0]; + for (int i = 1; i < args.length; i++) { + if (args[i] < min) + min = args[i]; + } + return min; + } + /** + * Finds the maximum from the list of values. + * + * @param args - The list of values. + * @return Returns the maximum value from the list. + */ + public static double max(double... args) { + double max = args[0]; + for (int i = 1; i < args.length; i++) { + if (args[i] > max) + max = args[i]; + } + return max; + } + /** + * Tests whether the two values are within epsilon range of each other. + * + * @param a - The first value to compare with. + * @param b - The second value to compare with. + * @param epsilon - The max allowed range between a and b. + * @return Returns true if the two values are within epsilon range of + * each other. + */ + public static boolean inRange(double a, double b, double epsilon) { + return Math.abs(b - a) <= epsilon; + } + /** + * Returns the positive modulus of the value. + * + * @param x - The value to get the modulus of. + * @param mod - The modulus. + * @return Returns the positive modulus of the value. + */ + public static double absmod(double x, double mod) { + double val = x % mod; + if (val < 0) + return val + mod; + return val; + } + + // ======================= Vectors ======================== + + /** + * Finds the minimum x and y values from the given vectors. + * + * @param args - The list of vectors. + * @return Returns the minimum vector coordinates. + */ + public static Vector min(Vector... args) { + Vector min = new Vector(args[0]); + for (int i = 1; i < args.length; i++) { + if (args[i].x < min.x) + min.x = args[i].x; + if (args[i].y < min.y) + min.y = args[i].y; + } + return min; + } + /** + * Finds the maximum x and y values from the given vectors. + * + * @param args - The list of vectors. + * @return Returns the maximum vector coordinates. + */ + public static Vector max(Vector... args) { + Vector max = new Vector(args[0]); + for (int i = 1; i < args.length; i++) { + if (args[i].x > max.x) + max.x = args[i].x; + if (args[i].y > max.y) + max.y = args[i].y; + } + return max; + } + + public static Vector abs(Vector v) { + return new Vector(Math.abs(v.x), Math.abs(v.y)); + } + + // ===================== Trigonometry ===================== + + /** + * Returns the angle of the value in the range [0, 360). + * + * @param theta - The value to get the proper angle of. + * @return Returns the angle of the value in the range [0, 360). + */ + public static double absdir(double theta) { + return GMath.absmod(theta, FULL_ANGLE); + } + /** + * Returns the change in direction from the source to the destination. + * + * @param src - The current direction. + * @param dst - The direction to the destination. + * @return Returns the change in direction to the destination. + */ + public static double deltaDirection(double src, double dst) { + double dir = GMath.absdir(dst - src); + if (dir > HALF_ANGLE) + dir -= HALF_ANGLE; + return dir; + } + + /** + * Converts the given angle into degrees if USE_DEGREES is true. + * + * @param theta - The angle to convert. + * @return Returns the angle in degrees if USE_DEGREES is true, otherwise + * in radians. + */ + public static double convertRadians(double theta) { + if (USE_DEGREES) + return Math.toDegrees(theta); + else + return theta; + } + /** + * Converts the given angle into radians if USE_DEGREES is false. + * + * @param theta - The angle to convert. + * @return Returns the angle in radians if USE_DEGREES is false, otherwise + * in degrees. + */ + public static double convertDegrees(double theta) { + if (USE_DEGREES) + return theta; + else + return Math.toRadians(theta); + } + +} + + diff --git a/MetroidMapGuardian/src/geometry/Line.java b/MetroidMapGuardian/src/geometry/Line.java new file mode 100644 index 0000000..e5c6307 --- /dev/null +++ b/MetroidMapGuardian/src/geometry/Line.java @@ -0,0 +1,450 @@ +package geometry; + +/** + * A line segment that has two end points, This is the basic shape that + * constructs all polygons. + * + * @author Robert Jordan + * + * @see + * {@linkplain Vector}, + * {@linkplain Shape}, + * {@linkplain java.awt.geom.Line2D} + */ +public class Line { + + // ======================= Members ======================== + + /** The first end point of the line. */ + public Vector end1; + /** The second end point of the line. */ + public Vector end2; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a line with both points at (0, 0). + * + * @return Returns a line at (0, 0). + */ + public Line() { + this.end1 = new Vector(); + this.end2 = new Vector(); + } + /** + * Constructs a line with the two specified end points. + * + * @param end1 - The first end point. + * @param end2 - The second end point. + * @return Returns a line with the two end points. + */ + public Line(Vector end1, Vector end2) { + this.end1 = new Vector(end1); + this.end2 = new Vector(end2); + } + /** + * Constructs a line with the two specified end points. + * + * @param x1 - The x coordinate of the first end point. + * @param y1 - The y coordinate of the first end point. + * @param x2 - The x coordinate of the second end point. + * @param y2 - The y coordinate of the second end point. + * @return Returns a line with the two end points. + */ + public Line(double x1, double y1, double x2, double y2) { + this.end1 = new Vector(x1, y1); + this.end2 = new Vector(x2, y2); + } + /** + * Constructs a line with the same end points as the given line. + * + * @param l - The line to copy. + * @return Returns a line that is identical to the given line. + */ + public Line(Line l) { + this.end1 = new Vector(l.end1); + this.end2 = new Vector(l.end2); + } + + // ==================== Shape Details ===================== + + /** + * Returns the direction of the line from end point 1 to end point 2. + * + * @return Returns the direction of the line from end point 1 to end + * point 2. + */ + public double direction() { + return end2.minus(end1).direction(); + } + /** + * Returns the length of the line. + * + * @return Returns the length of the line. + */ + public double length() { + return end2.minus(end1).length(); + } + /** + * Returns the minimum coordinates of the two end points. + * + * @return Returns the minimum coordinates. + */ + public Vector min() { + return Vector.min(end1, end2); + } + /** + * Returns the maximum coordinates of the two end points. + * + * @return Returns the maximum coordinates. + */ + public Vector max() { + return Vector.max(end1, end2); + } + /** + * Returns the size from end point 1 to end point 2. + * + * @return Returns a the size of the line. + */ + public Vector size() { + return new Vector(end1, end2); + } + /** + * Tests whether the line is horizontal. + * + * @return Returns true if the line is horizontal. + */ + public boolean isHorizontal() { + return (end1.y == end2.y); + } + /** + * Tests whether the line is vertical. + * + * @return Returns true if the line is vertical. + */ + public boolean isVertical() { + return (end1.x == end2.x); + } + /** + * Creates a polygon with the same points as this line. + * + * @return Returns the polygon shape that represents this line. + */ + public Polygon getPolygon() { + return new Polygon(end1, end2); + } + /** + * Returns the vector of the line with end point 1 being the origin. + * + * @return TReturns the vector of the line. + */ + public Vector getVector() { + return new Vector(end1, end2); + } + /** + * Calculates and returns the center of the shape. + * + * @return The position of the center of the shape. + */ + public Vector getCenter() { + return new Vector(end1.plus(end2).scaledBy(0.5)); + } + /** + * Calculates and returns the bounding box of the shape. + * + * @return The rectangle of the bounding box of the shape. + */ + public Rectangle getBounds() { + return new Rectangle(min(), max().minus(min())); + } + + // ================== Shape Modification ================== + + /** + * Returns the shape translated by the specified distance. + * + * @param v - The Vector of the distance to translate. + * @return Returns a translated shape. + */ + public Line getTranslation(Vector v) { + return new Line(this).translate(v); + } + /** + * Translates the shape by the specified distance. + * + * @param v - The Vector of the distance to translate. + * @return Returns the shape after it has been translated. + */ + public Line translate(Vector v) { + end1.add(v); + end2.add(v); + return this; + } + /** + * Returns the scaled shape. + * + * @param scale - The change in scale of the shape + * @return Returns a scaled shape. + */ + public Line getScaled(double scale) { + return new Line(this).scale(scale); + } + /** + * Returns the shape scaled around the specified anchor. + * + * @param anchor - The anchor to scale the shape around. + * @param scale - The change in scale of the shape + * @return Returns a scaled shape. + */ + public Line getScaled(Vector anchor, double scale) { + return new Line(this).scale(anchor, scale); + } + /** + * Scales the shape by the specified size. + * + * @param scale - The new scale of the shape + * @return Returns the shape after it has been scaled. + */ + public Line scale(double scale) { + end1.scale(scale); + end2.scale(scale); + return this; + } + /** + * Scales the shape by the specified size around the specified anchor. + * + * @param anchor - The anchor to scale the shape around. + * @param scale - The new scale of the shape + * @return Returns the shape after it has been scaled. + */ + public Line scale(Vector anchor, double scale) { + end1.sub(anchor); + end2.sub(anchor); + end1.scale(scale); + end2.scale(scale); + end1.add(anchor); + end2.add(anchor); + return this; + } + /** + * Returns the rotated shape. + * + * @param anchor - The anchor to rotate the shape around. + * @param theta - The changed rotation of the shape + * @return Returns a rotated shape. + */ + public Line getRotation(Vector anchor, double theta) { + return new Line(this).rotate(anchor, theta); + } + /** + * Rotates the shape by the specified angle around the anchor. + * + * @param anchor - The anchor to rotate the shape around. + * @param theta - The new rotation of the shape + * @return Returns the shape after it has been rotated. + */ + public Line rotate(Vector anchor, double theta) { + end1.sub(anchor); + end2.sub(anchor); + end1.scale(end1.direction() + theta); + end2.scale(end2.direction() + theta); + end1.add(anchor); + end2.add(anchor); + return this; + } + + // =================== Shape Collision ==================== + + /** + * Finds the intersection point between this line and another. + * + * @param l - The line to intersect with + * @return Returns the point of intersection between the two lines, + * returns null if there is no intersection or the lines are parallel. + * + * @see + Wikipedia: Line-Line Intersection + */ + public Vector getIntersection(Line l) { + Vector pt = getIntersectionEndless(l); + + // Return null if the point is not within the end points of the lines. + if (pt == null) + return null; + if (!pt.greaterThanOrEqual(min()) || !pt.lessThanOrEqual(max())) + return null; + if (!pt.greaterThanOrEqual(l.min()) || !pt.lessThanOrEqual(l.max())) + return null; + + return pt; + } + /** + * Finds the intersection point between this line and another, + * assuming they extend on forever. + * + * @param l - The line to intersect with + * @return Returns the point of intersection between the two endless lines, + * returns null if the lines are parallel. + * + * @see + Wikipedia: Line-Line Intersection + */ + public Vector getIntersectionEndless(Line l) { + // Check if one or both of the lines are horizontal or parallel + // in order to speed up calculation. + if (isHorizontal()) { + // Lines are parallel + if (l.isHorizontal()) + return null; + if (l.isVertical()) + return new Vector(l.end1.x, end1.y); + + double xi = l.end1.x + l.size().x * ((end1.y - l.end1.y) / l.size().y); + return new Vector(xi, end1.y); + } + else if (isVertical()) { + // Lines are parallel + if (l.isVertical()) + return null; + if (l.isHorizontal()) + return new Vector(end1.x, l.end1.y); + + double yi = l.end1.y + l.size().y * ((end1.x - l.end1.x) / l.size().x); + return new Vector(end1.x, yi); + } + else if (l.isHorizontal() || l.isVertical()) + return l.getIntersectionEndless(this); + + double det = (size().x * l.size().y) - (size().y * l.size().x); + // Lines are parallel + if (det == 0.0) + return null; + + double d1 = ((end1.x * end2.y) - (end1.y * end2.x)); + double d2 = ((l.end1.x * l.end2.y) - (l.end1.y * l.end2.x)); + + double xi = -((d1 * l.size().x) - (d2 * size().x)) / det; + double yi = -((d1 * l.size().y) - (d2 * size().y)) / det; + + return new Vector(xi, yi); + } + /** + * Tests whether the two lines are parallel. + * + * @param l - The line to check the slope of. + * @return Returns true if the two lines are parallel. + */ + public boolean isParallel(Line l) { + return ((size().x * l.size().y) - (size().y * l.size().x) == 0.0); + } + + // ==================== Contains Shape ==================== + + /** + * Tests if the specified point is inside the boundary of the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is inside the boundary of the shape. + */ + public boolean contains(Vector v) { + return false; + } + /** + * Tests if the specified line is inside the boundary of the shape. + * + * @param l - The line. + * @return Returns true if the line is inside the boundary of the shape. + */ + public boolean contains(Line l) { + return false; + } + /** + * Tests if the specified rectangle is inside the boundary of the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle is inside the boundary of the shape. + */ + public boolean contains(Rectangle r) { + return false; + } + + // =================== Intersects Shape =================== + + /** + * Tests if the specified point is on the boundary of the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is on the boundary of the shape. + */ + public boolean intersects(Vector v) { + return false; + } + /** + * Tests if the specified line intersects the boundary of the shape. + * + * @param l - The line. + * @return Returns true if the line intersects the boundary of the shape. + */ + public boolean intersects(Line l) { + return false; + } + /** + * Tests if the specified rectangle intersects the boundary of the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle intersects the boundary of the shape. + */ + public boolean intersects(Rectangle r) { + return false; + } + + // ==================== Touching Shape ==================== + + /** + * Tests if the specified point is colliding with the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is colliding with the shape. + */ + public boolean colliding(Vector v) { + return false; + } + /** + * Tests if the specified line is colliding with the shape. + * + * @param l - The line. + * @return Returns true if the line is colliding with the shape. + */ + public boolean colliding(Line l) { + return false; + } + /** + * Tests if the specified rectangle is colliding with the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle is colliding with the shape. + */ + public boolean colliding(Rectangle r) { + return false; + } + + // ================ Java Awt Compatibility ================ + + /** + * Creates and returns the Java Awt Shape of the shape. + * This function is used for compatibility with java.awt.geom shapes. + * + * @return The Java Awt Shape of the shape. + * + * @see + * {@linkplain java.awt.Shape}, + * {@linkplain java.awt.Line2D.Double} + */ + public java.awt.geom.Line2D.Double getShape() { + return new java.awt.geom.Line2D.Double(end1.x, end1.y, end2.x, end2.y); + } + +} + + + diff --git a/MetroidMapGuardian/src/geometry/Polygon.java b/MetroidMapGuardian/src/geometry/Polygon.java new file mode 100644 index 0000000..a69b5a0 --- /dev/null +++ b/MetroidMapGuardian/src/geometry/Polygon.java @@ -0,0 +1,444 @@ +package geometry; + + +/** + * A shape that can contain a variable amount of sides. All basic shapes + * such as rectangles and lines can be converted into a polygon. + * + * @author Robert Jordan + * + * @see + * {@linkplain Vector}, + * {@linkplain Shape}, + * {@linkplain Line} + */ +public class Polygon { + + // ======================= Members ======================== + + /** The number of points in the polygon. */ + public int npoints; + /** An array containing the points of the polygon. */ + public Vector[] points; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a polygon with no points. + * + * @return Returns a polygon with no points + */ + public Polygon() { + this.npoints = 0; + this.points = new Vector[npoints]; + } + /** + * Constructs a polygon with the specified points. + * Input the coordinates in the format x1, y1, x2, y2... + * + * @param points - The x and y values for each point. + * @return Returns a polygon with no points + */ + public Polygon(double... points) { + this.npoints = points.length / 2; + this.points = new Vector[npoints]; + + for (int i = 0; i < npoints; i++) { + this.points[i] = new Vector(points[i * 2], points[i * 2 + 1]); + } + } + /** + * Constructs a polygon with the specified points. + * + * @param points - The vector values for each point. + * @return Returns a polygon with the given points. + */ + public Polygon(Vector... points) { + this.npoints = points.length; + this.points = new Vector[npoints]; + + for (int i = 0; i < npoints; i++) { + this.points[i] = new Vector(points[i]); + } + } + /** + * Constructs a polygon with the specified points. + * + * @param xpoints - The x coordinates of the points. + * @param ypoints - The y coordinates of the points. + * @param npoints - The number of points. + * @return Returns a polygon with the given points. + */ + public Polygon(double[] xpoints, double[] ypoints, int npoints) { + this.npoints = npoints; + this.points = new Vector[npoints]; + + for (int i = 0; i < npoints; i++) { + this.points[i] = new Vector(xpoints[i], ypoints[i]); + } + } + /** + * Constructs a polygon with the specified points. + * + * @param points - The vectors of the points. + * @param npoints - The number of points. + * @return Returns a polygon with the given points. + */ + public Polygon(Vector[] points, int npoints) { + this.npoints = npoints; + this.points = new Vector[npoints]; + + for (int i = 0; i < npoints; i++) { + this.points[i] = new Vector(points[i]); + } + } + /** + * Constructs a polygon with the same points as the given one. + * + * @param p - The polygon to copy. + * @return Returns a polygon that is identical to the given one. + */ + public Polygon(Polygon p) { + this.npoints = p.npoints; + this.points = new Vector[npoints]; + + for (int i = 0; i < npoints; i++) { + this.points[i] = new Vector(p.points[i]); + } + } + + // ================== Point Modification ================== + + /** + * Adds a point to the polygon at the specified location. + * + * @param x - The x coordinates of the point. + * @param y - The y coordinates of the point. + */ + public void addPoint(double x, double y) { + addPoint(new Vector(x, y), npoints); + } + /** + * Adds a point to the polygon at the specified location with the specified index. + * + * @param x - The x coordinates of the point. + * @param y - The y coordinates of the point. + * @param index - The index of the point. + */ + public void addPoint(double x, double y, int index) { + addPoint(new Vector(x, y), index); + } + /** + * Adds a point to the polygon at the specified location. + * + * @param v - The vector of the point. + */ + public void addPoint(Vector v) { + addPoint(v, npoints); + } + /** + * Adds a point to the polygon at the specified location with the specified index. + * + * @param v - The vector of the point. + * @param index - The index of the point. + */ + public void addPoint(Vector v, int index) { + npoints++; + Vector[] newPoints = new Vector[npoints]; + + for (int i = 0; i < npoints; i++) { + if (i == index) + newPoints[i] = new Vector(v); + else if (i > index) + newPoints[i] = points[i - 1]; + else + newPoints[i] = points[i]; + } + points = newPoints; + } + /** + * Removes the last point in the polygon. + */ + public void removePoint() { + removePoint(npoints - 1); + } + /** + * Removes the point at the specified index. + * + * @param index - The index of the point. + */ + public void removePoint(int index) { + npoints--; + Vector[] newPoints = new Vector[npoints]; + + for (int i = 0; i < npoints; i++) { + if (i >= index) + newPoints[i] = points[i + 1]; + else + newPoints[i] = points[i]; + } + points = newPoints; + } + + // ==================== Shape Details ===================== + + /** + * Gets the point at the specified index. + * + * @param index - The index of the point. + * @return Returns the point at the specified index. + */ + public Vector getPoint(int index) { + return new Vector(points[index]); + } + /** + * Calculates and returns the line of the point at index and the next point. + * + * @param index - The index of the first point. + * @return Returns the line with end points at point1 and point2. + */ + public Line getLine(int index) { + return new Line(points[index], points[(index + 1) % npoints]); + } + + /** + * Calculates and returns the center of the shape. + * + * @return Returns the position of the center of the shape. + */ + public Vector getCenter() { + Vector total = new Vector(); + for (int i = 0; i < npoints; i++) { + total.add(points[i]); + } + + return total.scaledBy(1.0 / (double)npoints); + } + /** + * Calculates and returns the bounding box of the shape. + * + * @return Returns the rectangle of the bounding box of the shape. + */ + public Rectangle getBounds() { + Vector min = new Vector(points[0]); + Vector max = new Vector(points[0]); + for (int i = 0; i < npoints; i++) { + min = Vector.min(min, points[i]); + max = Vector.max(max, points[i]); + } + + return new Rectangle(min, max.minus(min)); + } + + // ================== Shape Modification ================== + + /** + * Returns the shape translated by the specified distance. + * + * @param v - The Vector of the distance to translate. + * @return Returns a translated shape. + */ + public Polygon getTranslation(Vector v) { + return new Polygon(points, npoints).translate(v); + } + /** + * Translates the shape by the specified distance. + * + * @param v - The Vector of the distance to translate. + * @return Returns the shape after it has been translated. + */ + public Polygon translate(Vector v) { + for (int i = 0; i < npoints; i++) { + points[i].add(v); + } + return this; + } + /** + * Returns the scaled shape. + * + * @param scale - The change in scale of the shape + * @return Returns a scaled shape. + */ + public Polygon getScaled(double scale) { + return new Polygon(points, npoints).scale(scale); + } + /** + * Returns the shape scaled around the specified anchor. + * + * @param anchor - The anchor to scale the shape around. + * @param scale - The change in scale of the shape + * @return Returns a scaled shape. + */ + public Polygon getScaled(Vector anchor, double scale) { + return new Polygon(points, npoints).scale(anchor, scale); + } + /** + * Scales the shape by the specified size. + * + * @param scale - The new scale of the shape + * @return Returns the shape after it has been scaled. + */ + public Polygon scale(double scale) { + for (int i = 0; i < npoints; i++) { + points[i].scale(scale); + } + return this; + } + /** + * Scales the shape by the specified size around the specified anchor. + * + * @param anchor - The anchor to scale the shape around. + * @param scale - The new scale of the shape + * @return Returns the shape after it has been scaled. + */ + public Polygon scale(Vector anchor, double scale) { + for (int i = 0; i < npoints; i++) { + points[i].sub(anchor); + points[i].scale(scale); + points[i].add(anchor); + } + return this; + } + /** + * Returns the rotated shape. + * + * @param anchor - The anchor to rotate the shape around. + * @param theta - The changed rotation of the shape + * @return Returns a rotated shape. + */ + public Polygon getRotation(Vector anchor, double theta) { + return new Polygon(points, npoints).rotate(anchor, theta); + } + /** + * Rotates the shape by the specified angle around the anchor. + * + * @param anchor - The anchor to rotate the shape around. + * @param theta - The new rotation of the shape + * @return Returns the shape after it has been rotated. + */ + public Polygon rotate(Vector anchor, double theta) { + for (int i = 0; i < npoints; i++) { + points[i].sub(anchor); + points[i].setDirection(points[i].direction() + theta); + points[i].add(anchor); + } + return this; + } + + // ==================== Contains Shape ==================== + + /** + * Tests if the specified point is inside the boundary of the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is inside the boundary of the shape. + */ + public boolean contains(Vector v) { + return false; + } + /** + * Tests if the specified line is inside the boundary of the shape. + * + * @param l - The line. + * @return Returns true if the line is inside the boundary of the shape. + */ + public boolean contains(Line l) { + return false; + } + /** + * Tests if the specified rectangle is inside the boundary of the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle is inside the boundary of the shape. + */ + public boolean contains(Rectangle r) { + return false; + } + + // =================== Intersects Shape =================== + + /** + * Tests if the specified point is on the boundary of the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is on the boundary of the shape. + */ + public boolean intersects(Vector v) { + return false; + } + /** + * Tests if the specified line intersects the boundary of the shape. + * + * @param l - The line. + * @return Returns true if the line intersects the boundary of the shape. + */ + public boolean intersects(Line l) { + return false; + } + /** + * Tests if the specified rectangle intersects the boundary of the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle intersects the boundary of the shape. + */ + public boolean intersects(Rectangle r) { + return false; + } + + // ==================== Touching Shape ==================== + + /** + * Tests if the specified point is colliding with the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is colliding with the shape. + */ + public boolean colliding(Vector v) { + return false; + } + /** + * Tests if the specified line is colliding with the shape. + * + * @param l - The line. + * @return Returns true if the line is colliding with the shape. + */ + public boolean colliding(Line l) { + return false; + } + /** + * Tests if the specified rectangle is colliding with the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle is colliding with the shape. + */ + public boolean colliding(Rectangle r) { + return false; + } + + // ================ Java Awt Compatibility ================ + + /** + * Creates and returns the Java Awt Shape of the shape. + * This function is used for compatibility with java.awt.geom shapes. + * + * @return The Java Awt Shape of the shape. + * + * @see + * {@link java.awt.Shape} + */ + public java.awt.Shape getShape() { + java.awt.geom.Path2D.Double path = new java.awt.geom.Path2D.Double(java.awt.geom.Path2D.WIND_EVEN_ODD); + + path.moveTo(points[0].x, points[0].y); + for (int i = 1; i < npoints; i++) { + path.lineTo(points[i].x, points[i].y); + } + path.closePath(); + + return path; + } + +} + + + diff --git a/MetroidMapGuardian/src/geometry/Rectangle.java b/MetroidMapGuardian/src/geometry/Rectangle.java new file mode 100644 index 0000000..1dcff6b --- /dev/null +++ b/MetroidMapGuardian/src/geometry/Rectangle.java @@ -0,0 +1,346 @@ +package geometry; + +/** + * A basic rectangular shape with a point and size. This class is used for + * bounding boxes of other shapes and works as a basic collision hit box. + * + * @author Robert Jordan + * + * @see + * {@linkplain Vector}, + * {@linkplain Shape} + */ +public class Rectangle { + + // ======================= Members ======================== + + /** The corner of the rectangle. */ + public Vector point; + /** The size of the rectangle from the point. */ + public Vector size; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a rectangle + * with a point and size of (0, 0). + * + * @return Returns the default rectangle with a point and size of (0, 0). + */ + public Rectangle() { + this.point = new Vector(); + this.size = new Vector(); + } + /** + * Constructs a rectangle with the specified dimensions. + * + * @param x - The x coordinate of the rectangle. + * @param y - The y coordinate of the rectangle. + * @param w - The width of the rectangle. + * @param h - The height of the rectangle. + * @return Returns a rectangle with the given dimensions. + */ + public Rectangle(double x, double y, double w, double h) { + this.point = new Vector(x, y); + this.size = new Vector(w, h); + } + /** + * Constructs a rectangle with the specified dimensions. + * + * @param point - The point of the rectangle. + * @param size - The size of the rectangle. + * @return Returns a rectangle with the given dimensions. + */ + public Rectangle(Vector point, Vector size) { + this.point = new Vector(point); + this.size = new Vector(size); + } + /** + * Constructs a rectangle with the same point and size as the given one. + * + * @param r - The rectangle to copy. + * @return Returns a rectangle that is identical to the given one. + */ + public Rectangle(Rectangle r) { + this.point = new Vector(r.point); + this.size = new Vector(r.size); + } + + // ==================== Shape Details ===================== + + /** + * Returns one of the shape's points. + * + * @param index - The index of the point. This can be between 0 and 3. + * @return Returns the point of the specified index. + */ + public Vector getPoint(int index) { + switch (index) { + case 0: return new Vector(point.plus(0, 0)); + case 1: return new Vector(point.plus(size.x, 0)); + case 2: return new Vector(point.plus(size)); + case 3: return new Vector(point.plus(0, size.y)); + } + return null; + } + /** + * Returns one of the shape's lines. + * + * @param index - The index of the line. This can be between 0 and 3. + * @return Returns the line of the specified index. + */ + public Line getLine(int index) { + switch (index) { + case 0: return new Line(point.plus(0, 0), point.plus(size.x, 0)); + case 1: return new Line(point.plus(size.x, 0), point.plus(size)); + case 2: return new Line(point.plus(size), point.plus(0, size.y)); + case 3: return new Line(point.plus(0, size.y), point.plus(0, 0)); + } + return null; + } + /** + * Returns the minimum point of the shape. + * + * @return Returns the minimum point of the shape. + */ + public Vector min() { + return Vector.min(point, point.plus(size)); + } + /** + * Returns the maximum point of the shape. + * + * @return Returns the maximum point of the shape. + */ + public Vector max() { + return Vector.max(point, point.plus(size)); + } + /** + * Creates a polygon with the same points as this line. + * + * @return Returns the polygon shape that represents this line. + */ + public Polygon getPolygon() { + return new Polygon(getPoint(0), getPoint(1), getPoint(2), getPoint(3)); + } + /** + * Calculates and returns the center of the shape. + * + * @return The position of the center of the shape. + */ + public Vector getCenter() { + return point.plus(size.scaledBy(0.5)); + } + /** + * Calculates and returns the bounding box of the shape. + * + * @return Returns the rectangle of the bounding box of the shape. + */ + public Rectangle getBounds() { + return new Rectangle(min(), max().minus(min())); + } + + // ================== Shape Modification ================== + + /** + * Returns the shape translated by the specified distance. + * + * @param v - The Vector of the distance to translate. + * @return Returns a translated shape. + */ + public Rectangle getTranslation(Vector v) { + return new Rectangle(this).translate(v); + } + /** + * Translates the shape by the specified distance. + * + * @param v - The Vector of the distance to translate. + * @return Returns the shape after it has been translated. + */ + public Rectangle translate(Vector v) { + point.add(v); + return this; + } + /** + * Returns the scaled shape. + * + * @param scale - The change in scale of the shape + * @return Returns a scaled shape. + */ + public Rectangle getScaled(double scale) { + return new Rectangle(this).scale(scale); + } + /** + * Returns the shape scaled around the specified anchor. + * + * @param anchor - The anchor to scale the shape around. + * @param scale - The change in scale of the shape + * @return Returns a scaled shape. + */ + public Rectangle getScaled(Vector anchor, double scale) { + return new Rectangle(this).scale(anchor, scale); + } + /** + * Scales the shape by the specified size. + * + * @param scale - The new scale of the shape + * @return Returns the shape after it has been scaled. + */ + public Rectangle scale(double scale) { + point.scale(scale); + size.scale(scale); + return this; + } + /** + * Scales the shape by the specified size around the specified anchor. + * + * @param anchor - The anchor to scale the shape around. + * @param scale - The new scale of the shape + * @return Returns the shape after it has been scaled. + */ + public Rectangle scale(Vector anchor, double scale) { + point.sub(anchor); + point.scale(scale); + point.add(anchor); + size.scale(scale); + return this; + } + /** + * Returns the rotated shape. + * + * @param anchor - The anchor to rotate the shape around. + * @param theta - The changed rotation of the shape + * @return Returns a rotated shape. + */ + public Polygon getRotation(Vector anchor, double theta) { + return getPolygon().rotate(anchor, theta); + } + /** + * Rotates the shape by the specified angle around the anchor. + * + * @param anchor - The anchor to rotate the shape around. + * @param theta - The new rotation of the shape + * @return Returns the shape after it has been rotated. + */ + public Rectangle rotate(Vector anchor, double theta) { + return null; + } + + // ==================== Contains Shape ==================== + + /** + * Tests if the specified point is inside the boundary of the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is inside the boundary of the shape. + */ + public boolean contains(Vector v) { + return (v.greaterThanOrEqual(min()) && v.lessThanOrEqual(max())); + } + /** + * Tests if the specified line is inside the boundary of the shape. + * + * @param l - The line. + * @return Returns true if the line is inside the boundary of the shape. + */ + public boolean contains(Line l) { + return (l.min().greaterThanOrEqual(min()) && l.max().lessThanOrEqual(max())); + } + /** + * Tests if the specified rectangle is inside the boundary of the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle is inside the boundary of the shape. + */ + public boolean contains(Rectangle r) { + return (r.min().greaterThanOrEqual(min()) && r.max().lessThanOrEqual(max())); + } + + // =================== Intersects Shape =================== + + /** + * Tests if the specified point is on the boundary of the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is on the boundary of the shape. + */ + public boolean intersects(Vector v) { + if ((v.x == point.x || v.x == point.x + size.x) && + (v.y >= min().y && v.y <= max().y)) { + return true; + } + if ((v.y == point.y || v.y == point.y + size.y) && + (v.x >= min().x && v.x <= max().x)) { + return true; + } + return false; + } + /** + * Tests if the specified line intersects the boundary of the shape. + * + * @param l - The line. + * @return Returns true if the line intersects the boundary of the shape. + */ + public boolean intersects(Line l) { + for (int i = 0; i < 4; i++) { + if (l.intersects(getLine(i))) { + return true; + } + } + return false; + } + /** + * Tests if the specified rectangle intersects the boundary of the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle intersects the boundary of the shape. + */ + public boolean intersects(Rectangle r) { + return (r.min().greaterThanOrEqual(min()) || r.max().lessThanOrEqual(max())); + } + + // ==================== Touching Shape ==================== + + /** + * Tests if the specified point is colliding with the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is colliding with the shape. + */ + public boolean colliding(Vector v) { + return (v.greaterThanOrEqual(min()) && v.lessThanOrEqual(max())); + } + /** + * Tests if the specified line is colliding with the shape. + * + * @param l - The line. + * @return Returns true if the line is colliding with the shape. + */ + public boolean colliding(Line l) { + return (l.min().greaterThanOrEqual(min()) && l.max().lessThanOrEqual(max())); + } + /** + * Tests if the specified rectangle is colliding with the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle is colliding with the shape. + */ + public boolean colliding(Rectangle r) { + return (r.max().greaterThanOrEqual(min()) && r.min().lessThanOrEqual(max())); + } + + // ================ Java Awt Compatibility ================ + + /** + * Creates and returns the Java Awt Shape of the shape. + * This function is used for compatibility with java.awt.geom shapes. + * + * @return The Java Awt Shape of the shape. + * + * @see + * {@linkplain java.awt.Shape}, + * {@linkplain java.awt.Rectangle2D.Double} + */ + public java.awt.geom.Rectangle2D.Double getShape() { + return new java.awt.geom.Rectangle2D.Double(point.x, point.y, size.x, size.y); + } +} diff --git a/MetroidMapGuardian/src/geometry/Shape.java b/MetroidMapGuardian/src/geometry/Shape.java new file mode 100644 index 0000000..cd39138 --- /dev/null +++ b/MetroidMapGuardian/src/geometry/Shape.java @@ -0,0 +1,180 @@ +package geometry; + +/** + * The interface used to implement geometric figures that use + * advanced collision detection and response, as well as drawing. + * + * @author Robert Jordan + * + * @see + * {@linkplain Vector}, + * {@linkplain Line}, + * {@linkplain Rectangle}, + * {@linkplain java.awt.Shape} + */ +public interface Shape { + + // ==================== Shape Details ===================== + + /** + * Calculates and returns the center of the shape. + * + * @return Returns the position of the center of the shape. + */ + public Vector getCenter(); + /** + * Calculates and returns the bounding box of the shape. + * + * @return Returns the rectangle of the bounding box of the shape. + */ + public Rectangle getBounds(); + + // ================== Shape Modification ================== + + /** + * Returns the shape translated by the specified distance. + * + * @param v - The Vector of the distance to translate. + * @return Returns a translated shape. + */ + public Shape getTranslation(Vector v); + /** + * Translates the shape by the specified distance. + * + * @param v - The Vector of the distance to translate. + * @return Returns the shape after it has been translated. + */ + public Shape translate(Vector v); + /** + * Returns the scaled shape. + * + * @param scale - The change in scale of the shape + * @return Returns a scaled shape. + */ + public Shape getScaled(double scale); + /** + * Returns the shape scaled around the specified anchor. + * + * @param anchor - The anchor to scale the shape around. + * @param scale - The change in scale of the shape + * @return Returns a scaled shape. + */ + public Shape getScaled(Vector anchor, double scale); + /** + * Scales the shape by the specified size. + * + * @param scale - The new scale of the shape + * @return Returns the shape after it has been scaled. + */ + public Shape scale(double scale); + /** + * Scales the shape by the specified size around the specified anchor. + * + * @param anchor - The anchor to scale the shape around. + * @param scale - The new scale of the shape + * @return Returns the shape after it has been scaled. + */ + public Shape scale(Vector anchor, double scale); + /** + * Returns the rotated shape. + * + * @param anchor - The anchor to rotate the shape around. + * @param theta - The changed rotation of the shape + * @return Returns a rotated shape. + */ + public Shape getRotation(Vector anchor, double theta); + /** + * Rotates the shape by the specified angle around the anchor. + * + * @param anchor - The anchor to rotate the shape around. + * @param theta - The new rotation of the shape + * @return Returns the shape after it has been rotated. + */ + public Shape rotate(Vector anchor, double theta); + + // ==================== Contains Shape ==================== + + /** + * Tests if the specified point is inside the boundary of the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is inside the boundary of the shape. + */ + public boolean contains(Vector v); + /** + * Tests if the specified line is inside the boundary of the shape. + * + * @param l - The line. + * @return Returns true if the line is inside the boundary of the shape. + */ + public boolean contains(Line l); + /** + * Tests if the specified rectangle is inside the boundary of the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle is inside the boundary of the shape. + */ + public boolean contains(Rectangle r); + + // =================== Intersects Shape =================== + + /** + * Tests if the specified point is on the boundary of the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is on the boundary of the shape. + */ + public boolean intersects(Vector v); + /** + * Tests if the specified line intersects the boundary of the shape. + * + * @param l - The line. + * @return Returns true if the line intersects the boundary of the shape. + */ + public boolean intersects(Line l); + /** + * Tests if the specified rectangle intersects the boundary of the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle intersects the boundary of the shape. + */ + public boolean intersects(Rectangle r); + + // ==================== Touching Shape ==================== + + /** + * Tests if the specified point is colliding with the shape. + * + * @param v - The Vector of the point. + * @return Returns true if the point is colliding with the shape. + */ + public boolean colliding(Vector v); + /** + * Tests if the specified line is colliding with the shape. + * + * @param l - The line. + * @return Returns true if the line is colliding with the shape. + */ + public boolean colliding(Line l); + /** + * Tests if the specified rectangle is colliding with the shape. + * + * @param r - The rectangle. + * @return Returns true if the rectangle is colliding with the shape. + */ + public boolean colliding(Rectangle r); + + // ================ Java Awt Compatibility ================ + + /** + * Creates and returns the Java Awt Shape of the shape. + * This function is used for compatibility with java.awt.geom shapes. + * + * @return The Java Awt Shape of the shape. + * + * @see + * {@link java.awt.Shape} + */ + public java.awt.Shape getShape(); + +} diff --git a/MetroidMapGuardian/src/geometry/Vector.java b/MetroidMapGuardian/src/geometry/Vector.java new file mode 100644 index 0000000..090341a --- /dev/null +++ b/MetroidMapGuardian/src/geometry/Vector.java @@ -0,0 +1,546 @@ +package geometry; + +import java.text.DecimalFormat; + +/** + * A class that represents a 2D point with an x and y coordinate. + * Vectors are used in trigonometric functions and collision physics. + * This is the core point class used for all shapes. + * + * @author Robert Jordan + * @author David Jordan + * + * @see + * {@linkplain Shape}, + * {@linkplain GMath} + */ +public class Vector { + + // ====================== Constants ======================= + + /** The origin point of (0, 0). */ + public static final Vector ORIGIN = new Vector(0.0, 0.0); + + // ======================= Members ======================== + + /** The x coordinate of the vector. */ + public double x; + /** The y coordinate of the vector. */ + public double y; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a vector positioned at the origin. + * + * @return Returns a vector at the point (0, 0). + */ + public Vector() { + this.x = 0.0; + this.y = 0.0; + } + /** + * Constructs a vector positioned at the specified x and y coordinate. + * + * @param x - The x coordinate. + * @param y - The y coordinate. + * @return Returns a vector at the point (x, y). + */ + public Vector(double x, double y) { + this.x = x; + this.y = y; + } + /** + * Constructs a vector positioned at the specified polar coordinates. + * + * @param length - The length or x coordinate. + * @param theta - The angle or y coordinate. + * @param polar - Set to true to use polar coordinates, otherwise xy + * coordinates are used. + * @return Returns a vector with the length and angle or at the point (x, y). + */ + public Vector(double length, double theta, boolean polar) { + if (polar) { + this.x = length * Math.cos(theta); + this.y = length * Math.sin(theta); + } + else { + this.x = length; + this.y = theta; + } + } + /** + * Constructs a vector positioned at the specified vector position. + * + * @param v - The vector position. + * @return Returns a vector at the same point as the specified vector. + */ + public Vector(Vector v) { + this.x = v.x; + this.y = v.y; + } + /** + * Constructs a vector of the distance from v1 to v2. + * + * @param v1 - The first vector. + * @param v2 - The second vector. + * @return Returns a vector of the distance from v1 to v2. + */ + public Vector(Vector v1, Vector v2) { + this.x = v2.x - v1.x; + this.y = v2.y - v1.y; + } + + // ======================= General ======================== + + /** + * Returns the vector in the form of a string as (x, y). + * + * @return Returns a string representing the vector's x and y value. + */ + public String toString() { + return "(" + x + ", " + y + ")"; + } + /** + * Returns the vector in the form of a string with the specified format + * for the double values. + * + * @param format - The format to display the x and y values in. + * @return Returns a string representing the vector's x and y value + * with the specified format. + */ + public String toString(DecimalFormat format) { + return "(" + format.format(x) + ", " + format.format(y) + ")"; + } + /** + * Tests whether the vector is equal to the specified vector. + * Returns false if the specified vector is null. + * + * @param obj - The vector to compare. + * @return Returns true if the vectors have the same x and y values. + */ + public boolean equals(Object obj) { + if (obj == null) + return false; + + return (this.x == ((Vector)obj).x) && (this.y == ((Vector)obj).y); + } + /** + * Tests whether the vector is greater than the specified vector. + * Returns false if the specified vector is null. + * + * @param v - The vector to compare. + * @return Returns true if the vector's values are greater than + * the other vector's values. + */ + public boolean greaterThan(Vector v) { + if (v == null) + return false; + + return (this.x > v.x) && (this.y > v.y); + } + /** + * Tests whether the vector is greater than or equal to the specified vector. + * Returns false if the specified vector is null. + * + * @param v - The vector to compare. + * @return Returns true if the vector's values are greater than or equal + * to the other vector's values. + */ + public boolean greaterThanOrEqual(Vector v) { + if (v == null) + return false; + + return (this.x >= v.x) && (this.y >= v.y); + } + /** + * Tests whether the vector is less than the specified vector. + * Returns false if the specified vector is null. + * + * @param v - The vector to compare. + * @return Returns true if the vector's values are less than the other + * vector's values. + */ + public boolean lessThan(Vector v) { + if (v == null) + return false; + + return (this.x < v.x) && (this.y < v.y); + } + /** + * Tests whether the vector is less than or equal to the specified vector. + * Returns false if the specified vector is null. + * + * @param v - The vector to compare. + * @return Returns true if the vector's values are less than or equal to + * the other vector's values. + */ + public boolean lessThanOrEqual(Vector v) { + if (v == null) + return false; + + return (this.x <= v.x) && (this.y <= v.y); + } + + // ====================== Arithmetic ====================== + + /** + * Returns the vector plus the x and y distance. + * + * @param x - The x distance to add. + * @param y - The y distance to add. + * @return Returns a vector with the added distance. + */ + public Vector plus(double x, double y) { + return new Vector(this.x + x, this.y + y); + } + /** + * Returns the vector plus the vector distance. + * + * @param v - The vector of the distance to add. + * @return Returns a vector with the added distance. + */ + public Vector plus(Vector v) { + return new Vector(this.x + v.x, this.y + v.y); + } + /** + * Returns the vector minus the x and y distance. + * + * @param x - The x distance to subtract. + * @param y - The y distance to subtract. + * @return Returns a vector with the subtracted distance. + */ + public Vector minus(double x, double y) { + return new Vector(this.x - x, this.y - y); + } + /** + * Returns the vector minus the vector distance. + * + * @param v - The vector of the distance to subtract. + * @return Returns a vector with the subtracted distance. + */ + public Vector minus(Vector v) { + return new Vector(this.x - v.x, this.y - v.y); + } + /** + * Returns the vector multiplied by the scale. + * + * @param scale - The scale to multiply the vector by. + * @return Returns a vector with the values multiplied by the scale. + */ + public Vector scaledBy(double scale) { + return new Vector(this.x * scale, this.y * scale); + } + /** + * Returns the inverse of the vector. + * + * @return Returns a vector with the inverse values. + */ + public Vector inverse() { + return new Vector(-this.x, -this.y); + } + /** + * Returns the length of the vector from the origin. + * + * @return Returns the vector's length. + */ + public double length() { + return Math.sqrt((x * x) + (y * y)); + } + /** + * Returns the direction of the vector with an angle of zero being (1, 0). + * + * @return Returns the vector's direction. + */ + public double direction() { + if (x == 0.0 && y == 0.0) + return 0.0; + + return Math.atan2(y, x); + } + /** + * Returns the distance from this vector to the specified vector. + * + * @param v - The vector to get the distance to. + * @return Returns the distance to the specified vector. + */ + public double distanceTo(Vector v) { + return v.minus(this).length(); + } + /** + * Returns the angle between this vector and another. + * + * @param v - The vector to get the distance to. + * @return Returns the angle between the specified vector's direction. + */ + public double angleBetween(Vector v) { + return direction() - v.direction(); + } + /** + * Returns the dot product of this vector and another. + * + * @param v - The vector to multiply by. + * @return Returns the dot product of the two vectors. + */ + public double dot(Vector v) { + return (this.x * v.x) + (this.y * v.y); + } + /** + * Returns the scalar projection on this vector with an angle. + * + * @param theta - The angle used. + * @return Returns the scalar projection on this vector and an angle. + */ + public double scalarProjection(double theta) { + return (length() * Math.cos(direction() - theta)); + } + /** + * Returns the scalar projection on this vector with another. + * + * @param v - The vector whose angle is used. + * @return Returns the scalar projection on this vector with another's angle. + */ + public double scalarProjection(Vector v) { + return scalarProjection(v.direction()); + } + /** + * Returns the normalized vector. + * + * @return Returns the normalized vector. + */ + public Vector normalized() { + double len = length(); + if (len > 0) { + return new Vector(x / len, y / len); + } + return new Vector(); + } + /** + * Returns a vector with the same direction but a set length. + * + * @param length - The new length to use. + * @return Returns the vector with a new length. + */ + public Vector lengthVector(double length) { + return new Vector(this).setLength(length); + } + /** + * Returns a vector with the same length but a set direction. + * + * @param theta - The new angle to use. + * @return Returns the vector with a new direction. + */ + public Vector directionVector(double theta) { + return new Vector(this).setDirection(theta); + } + /** + * Returns the projection of this vector on the angle. + * + * @param theta - The angle used. + * @return Returns the vector's projection with the specified angle. + */ + public Vector projectionOn(double theta) { + return new Vector(scalarProjection(theta), theta, true); + } + /** + * Returns the projection of this vector on the specified vector. + * + * @param v - The vector whose angle is used. + * @return Returns the vector's projection with the specified vector's angle. + */ + public Vector projectionOn(Vector v) { + return v.lengthVector(scalarProjection(v)); + } + /** + * Returns the rejection of this vector on the specified angle. + * + * @param theta - The angle used. + * @return Returns the vector's rejection with the specified angle. + */ + public Vector rejectionOn(double theta) { + return new Vector(projectionOn(theta), this); + } + /** + * Returns the rejection of this vector on the specified vector. + * + * @param v - The vector whose angle is used. + * @return Returns the vector's rejection with the specified vector's angle. + */ + public Vector rejectionOn(Vector v) { + return new Vector(projectionOn(v), this); + } + + // ================= Modified Arithmetic ================== + + /** + * Adds the x and y distance to the vector. + * + * @param x - The x distance to add. + * @param y - The y distance to add. + * @return Returns the vector with the added distance. + */ + public Vector add(double x, double y) { + this.x += x; + this.y += y; + return this; + } + /** + * Adds the vector distance to the vector. + * + * @param v - The vector of the distance to add. + * @return Returns the vector with the added distance. + */ + public Vector add(Vector v) { + this.x += v.x; + this.y += v.y; + return this; + } + /** + * Subtracts the x and y distance from the vector. + * + * @param x - The x distance to subtract. + * @param y - The y distance to subtract. + * @return Returns the vector with the subtracted distance. + */ + public Vector sub(double x, double y) { + this.x -= x; + this.y -= y; + return this; + } + /** + * Subtracts the vector distance from the vector. + * + * @param v - The vector of the distance to subtract. + * @return Returns the vector with the subtracted distance. + */ + public Vector sub(Vector v) { + this.x -= v.x; + this.y -= v.y; + return this; + } + /** + * Multiplied the vector by the scale. + * + * @param scale - The scale to multiply the vector by. + * @return Returns a new scaled vector. + */ + public Vector scale(double scale) { + this.x *= scale; + this.y *= scale; + return this; + } + /** + * Negates the vector. + * + * @return Returns the new negated vector. + */ + public Vector negate() { + this.x = -x; + this.y = -y; + return this; + } + /** + * Sets the vector to (0, 0). + * + * @return Returns the new vector at the position (0, 0). + */ + public Vector zero() { + this.x = 0.0; + this.y = 0.0; + return this; + } + /** + * Normalizes the vector. + * + * @return Returns the new normalized vector. + */ + public Vector normalize() { + double len = length(); + if (len > 0) { + this.x /= len; + this.y /= len; + } + return this; + } + /** + * Sets the vector to the new position. + * + * @param x - The new x coordinate. + * @param y - The new y coordinate. + * @return Returns the new vector with the modified position. + */ + public Vector set(double x, double y) { + this.x = x; + this.y = y; + return this; + } + /** + * Sets the vector to the new position. + * + * @param v - The new vector value. + * @return Returns the new vector with the modified position. + */ + public Vector set(Vector v) { + this.x = v.x; + this.y = v.y; + return this; + } + /** + * Sets the vector to the new length and direction. + * + * @param length - The new length of the vector. + * @param theta - The new angle of the vector. + * @return Returns the new vector with the modified length and direction. + */ + public Vector setPolar(double length, double theta) { + this.x = length * Math.cos(theta); + this.y = length * Math.sin(theta); + return this; + } + /** + * Sets the vector to have the new length but same direction. + * + * @param length - The new length of the vector. + * @return Returns the new vector with the modified length. + */ + public Vector setLength(double length) { + double direction = direction(); + this.x = length * Math.cos(direction); + this.y = length * Math.sin(direction); + return this; + } + /** + * Sets the vector to have the new direction but same length. + * + * @param theta - The new angle of the vector. + * @return Returns the new vector with the modified direction. + */ + public Vector setDirection(double theta) { + double length = length(); + this.x = length * Math.cos(theta); + this.y = length * Math.sin(theta); + return this; + } + + + /** + * Returns the minimum x and y coordinate from the two vectors. + * + * @param v1 - The first vector. + * @param v2 - The second vector. + * @return Returns minimum vector coordinates. + */ + public static Vector min(Vector v1, Vector v2) { + return new Vector(Math.min(v1.x, v2.x), Math.min(v1.y, v2.y)); + } + /** + * Returns the maximum x and y coordinate from the two vectors. + * + * @param v1 - The first vector. + * @param v2 - The second vector. + * @return Returns maximum vector coordinates. + */ + public static Vector max(Vector v1, Vector v2) { + return new Vector(Math.max(v1.x, v2.x), Math.max(v1.y, v2.y)); + } +} \ No newline at end of file diff --git a/MetroidMapGuardian/src/graphics/Button.java b/MetroidMapGuardian/src/graphics/Button.java new file mode 100644 index 0000000..97a4fcb --- /dev/null +++ b/MetroidMapGuardian/src/graphics/Button.java @@ -0,0 +1,201 @@ +package graphics; + +import geometry.Rectangle; +import geometry.Vector; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.util.ArrayList; + +import main.Mouse; + +public class Button extends Gui { + + // ==================== Public Members ==================== + + public boolean visible; + + public Vector size; + + public String label; + + public boolean hover; + public boolean pressed; + + public Font font; + + public boolean dropDown; + + public ArrayList listItems; + + public int selectedIndex; + + public int hoverIndex; + + public boolean dropDownOpen; + + public Vector dropDownSize; + + public Font dropDownFont; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + public Button() { + super(); + + visible = true; + size = new Vector(); + label = ""; + hover = false; + pressed = false; + font = null; + dropDown = false; + listItems = new ArrayList(); + selectedIndex = -1; + dropDownOpen = false; + hoverIndex = -1; + dropDownFont = null; + dropDownSize = new Vector(); + } + /** + * Constructs an entity with the specified details. + * + * @param id - The key identifier of the entity. + * @param depth - The depth of the entity. + * @param position - The position of the entity. + * @param velocity - The velocity of the entity. + * @return Returns an entity with the specified details. + */ + public Button(String id, String label, Vector position, Vector size, Vector dropDownSize, Font font, Font dropDownFont, boolean dropDown) { + super(id, -5, position); + + visible = true; + this.size = new Vector(size); + this.label = label; + hover = false; + pressed = false; + this.font = font; + this.dropDown = dropDown; + listItems = new ArrayList(); + selectedIndex = -1; + dropDownOpen = false; + hoverIndex = -1; + this.dropDownSize = dropDownSize; + this.dropDownFont = dropDownFont; + } + + // ======================== Updating ======================== + + /** + * Called every step for the gui to perform actions and update. + */ + public void update() { + selectedIndex = -1; + hoverIndex = -1; + boolean guiJustOpened = false; + Rectangle buttonRect = new Rectangle(position, size); + Rectangle dropDownRect = new Rectangle(position.plus(0, size.y), dropDownSize); + + pressed = false; + + if (buttonRect.contains(Mouse.getVector())) { + room.isMouseOverGUI = true; + if (!hover) { + hover = true; + } + if (Mouse.left.pressed()) { + pressed = true; + if (dropDown) { + if (!dropDownOpen) { + guiJustOpened = true; + } + dropDownOpen = !dropDownOpen; + } + } + } + else { + hover = false; + } + + if (dropDownOpen) { + for (int i = 0; i < listItems.size(); i++) { + + if (dropDownRect.contains(Mouse.getVector())) { + room.isMouseOverGUI = true; + hoverIndex = i; + if (Mouse.left.pressed()) { + selectedIndex = i; + dropDownOpen = false; + } + } + + dropDownRect.translate(new Vector(0, dropDownRect.size.y)); + } + } + + if (Mouse.left.released()) { + pressed = false; + } + + if (!guiJustOpened && (Mouse.left.pressed() || Mouse.right.pressed())) { + dropDownOpen = false; + } + } + /** + * Called every step for the gui to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + if (hover) { + g.setPaint(new GradientPaint((float)position.x, (float)position.y, new Color(90, 160, 199, 210), + (float)position.x, (float)(position.y + size.y), new Color(46, 102, 133, 210))); + } + else { + g.setPaint(new GradientPaint((float)position.x, (float)position.y, new Color(46, 102, 133, 210), + (float)position.x, (float)(position.y + size.y), new Color(16, 36, 47, 210))); + } + Draw.fillRect(g, position, size); + g.setColor(new Color(76, 147, 179, 210)); + Draw.drawRect(g, position, size); + + g.setColor(new Color(33, 189, 222)); + g.setFont(font); + Draw.drawString(g, label, position.plus(size.scaledBy(0.5)), Draw.ALIGN_CENTER | Draw.ALIGN_MIDDLE); + + g.setFont(dropDownFont); + if (dropDownOpen) { + + g.setColor(new Color(16, 36, 47, 210)); + Draw.fillRect(g, position.plus(0, size.y), new Vector(dropDownSize.x, dropDownSize.y * listItems.size())); + g.fillRect((int)(position.x), + (int)(position.y + size.y), + (int)dropDownSize.x, + (int)(dropDownSize.y * listItems.size())); + + for (int i = 0; i < listItems.size(); i++) { + if (hoverIndex == i) { + g.setColor(new Color(46, 102, 133, 210)); + Draw.fillRect(g, position.plus(0, size.y + dropDownSize.y * i), dropDownSize); + g.fillRect((int)(position.x), + (int)(position.y + size.y + dropDownSize.y * i), + (int)dropDownSize.x, + (int)dropDownSize.y); + } + g.setColor(new Color(33, 189, 222)); + Draw.drawString(g, listItems.get(i), position.plus(24, size.y + dropDownSize.y * (i + 0.5)), Draw.ALIGN_LEFT | Draw.ALIGN_MIDDLE); + } + + g.setColor(new Color(76, 147, 179, 210)); + Draw.drawRect(g, position.plus(0, size.y), new Vector(dropDownSize.x, dropDownSize.y * listItems.size())); + } + } +} diff --git a/MetroidMapGuardian/src/graphics/Draw.java b/MetroidMapGuardian/src/graphics/Draw.java new file mode 100644 index 0000000..3ab4e3d --- /dev/null +++ b/MetroidMapGuardian/src/graphics/Draw.java @@ -0,0 +1,838 @@ +package graphics; + +import geometry.*; + +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.font.GlyphVector; +import java.awt.image.BufferedImage; + +/** + * A static class used to draw images, strings, and shapes. It simplifies the + * process by allowing the use of double precision coordinates. + * + * @author Robert Jordan + * @see + * {@linkplain Vector} + */ +public class Draw { + + // ================== Private Variables =================== + + /** The image kept for accessing the graphics object and using font metrics.*/ + private static Image graphicsSlave = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); + + // =================== Public Variables =================== + + /** The default font that comes with a graphics object. */ + public static Font DEFAULT_FONT = graphicsSlave.getGraphics().getFont(); + + /** The font will draw left aligned. */ + public static final int ALIGN_LEFT = 0x00; + /** The font will draw centered aligned. */ + public static final int ALIGN_CENTER = 0x01; + /** The font will draw right aligned. */ + public static final int ALIGN_RIGHT = 0x02; + + /** The font will draw at the base of its height. */ + public static final int ALIGN_BASE = 0x00; + /** The font will draw at the top of its height. */ + public static final int ALIGN_TOP = 0x10; + /** The font will draw at the middle of its height. */ + public static final int ALIGN_MIDDLE = 0x20; + /** The font will draw at the bottom of its height. */ + public static final int ALIGN_BOTTOM = 0x30; + + // ======================= Details ======================== + + /** + * Gets the font metrics for the given font. + * + * @param font - The font to get the metrics of. + * @return Returns the font metrics for the specified font. + */ + public static FontMetrics getFontMetrics(Font font) { + Graphics g = graphicsSlave.getGraphics(); + return g.getFontMetrics(font); + } + /** + * Gets the glyph vector for the specified font and text. + * + * @param text - the text to use. + * @param font - The font to use. + * @return Returns the glyph vector of the text with the specified font. + */ + public static GlyphVector getGlyphVector(String text, Font font) { + Graphics g = graphicsSlave.getGraphics(); + return font.createGlyphVector(g.getFontMetrics(font).getFontRenderContext(), text); + } + /** + * Calculates the size of the text with the specified font. + * + * @param text - The text to get the size of. + * @param font - The font to use for the text. + * @return Returns a vector of the size of the text. + */ + public static Vector getStringSize(String text, Font font) { + Graphics g = graphicsSlave.getGraphics(); + return new Vector(g.getFontMetrics(font).stringWidth(text), + g.getFontMetrics(font).getHeight()); + } + /** + * Calculates the size of the wrapped text with the specified font. + * + * @param text - The text to get the size of. + * @param font - The font to use for the text. + * @param width - The maximum width of the line. + * @param maxLines - The maximum number of lines, use -1 for infinite. + * @param separation - The space between each line. + * @return Returns a vector of the size of the text. + */ + public static Vector getStringWrapSize(String text, Font font, double width, int maxLines, double separation) { + Graphics g = graphicsSlave.getGraphics(); + String[] lines = getWrappedString(text, font, width, maxLines); + + return new Vector(width, ((lines.length - 1) * separation) + + (lines.length * g.getFontMetrics(font).getHeight())); + } + /** + * Calculates the wrapped text with the specified font. + * + * @param text - The text to return the wrapped form of. + * @param font - The font to use for the text. + * @param width - The maximum width of the line. + * @param maxLines - The maximum number of lines, use -1 for infinite. + * @return Returns an array of lines of the text or null if there were no lines. + */ + public static String[] getWrappedString(String text, Font font, double width, int maxLines) { + String[] lines = new String[0]; + + // The remaining text + String string = text; + + // Add lines until the string has been emptied + for (int i = 0; !string.isEmpty() && (i < maxLines || maxLines == -1); i++) { + // Extend the array + String[] newLines = new String[i + 1]; + for (int j = 0; j < i; j++) { + newLines[j] = lines[j]; + } + newLines[i] = ""; + lines = newLines; + + // The last space/dash where the line will break + int lastSpace = -1; + // The last space was a dash + boolean isDash = false; + + if ((getStringSize(string, font).x <= width) && (string.indexOf('\n') == -1)) { + lines[i] = string; + string = ""; + } + for (int j = 0; j < string.length(); j++) { + // Check for a space or dash + if (string.charAt(j) == ' ' || string.charAt(j) == '-') { + lastSpace = j; + isDash = (string.charAt(j) == '-'); + } + // If there is a line limit, try to fit "..." in if it is the last line: + String dotdot = ((i + 1 == maxLines) ? "..." : ""); + + if (string.charAt(j) == '\n') { + lines[i] = string.substring(0, j) + dotdot; + string = string.substring(j + 1, string.length()); + break; + } + else if (getStringSize(string.substring(0, j + 1) + dotdot, font).x > width) { + // If the string passes the line width + if (lastSpace == -1) { + // If there was no line break character... + lines[i] = string.substring(0, j) + dotdot; + string = string.substring(j, string.length()); + } + else { + // Include the line breaker if it was a dash + lines[i] = string.substring(0, lastSpace + (isDash ? 1 : 0)) + dotdot; + string = string.substring(lastSpace + 1, string.length()); + } + break; + } + else if (j + 1 == string.length()) { + // The last line still fits + lines[i] = string; + string = ""; + break; + } + } + } + return lines; + } + + // ====================== Clear Image ====================== + + /** + * Clears the entire image by filling it with the background color. + * + * @param g - The graphics object to draw to. + */ + public static void clear(Graphics2D g) { + java.awt.Rectangle rect = g.getDeviceConfiguration().getBounds(); + g.clearRect(rect.x, rect.y, rect.width, rect.height); + } + /** + * Clears a rectangular portion of the image by filling it with the background color. + * + * @param g - The graphics object to draw to. + * @param point - The point of the rectangle. + * @param size - The size of the rectangle. + */ + public static void clear(Graphics2D g, Vector point, Vector size) { + g.clearRect((int)point.x, (int)point.y, (int)size.x, (int)size.y); + } + + // ====================== Draw String ====================== + + /** + * Draws the specified text to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - THe text to use. + * @param x - The x coordinate to draw the text at. + * @param y - The y coordinate to draw the text at. + */ + public static void drawString(Graphics2D g, String text, double x, double y) { + drawString(g, text, new Vector(x, y), 0); + } + /** + * Draws the specified text to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - THe text to use. + * @param x - The x coordinate to draw the text at. + * @param y - The y coordinate to draw the text at. + * @param alignment - The alignment settings to use. + */ + public static void drawString(Graphics2D g, String text, double x, double y, int alignment) { + drawString(g, text, new Vector(x, y), alignment); + } + /** + * Draws the specified text to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - The text to use. + * @param point - The point to draw the text at. + */ + public static void drawString(Graphics2D g, String text, Vector point) { + drawString(g, text, point, 0); + } + /** + * Draws the specified text to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - The text to use. + * @param point - The point to draw the text at. + * @param alignment - The alignment settings to use. + */ + public static void drawString(Graphics2D g, String text, Vector point, int alignment) { + + point = new Vector(point); + + // Font width settings + if ((alignment & 0x03) == ALIGN_CENTER) { + point.x -= getStringSize(text, g.getFont()).x / 2; + } + else if ((alignment & 0x03) == ALIGN_RIGHT) { + point.x -= getStringSize(text, g.getFont()).x; + } + + // Font height settings + if ((alignment & 0x30) == ALIGN_TOP) { + point.y += getFontMetrics(g.getFont()).getAscent(); + } + else if ((alignment & 0x30) == ALIGN_MIDDLE) { + point.y += getFontMetrics(g.getFont()).getAscent(); + point.y -= getFontMetrics(g.getFont()).getHeight() / 2; + } + else if ((alignment & 0x30) == ALIGN_BOTTOM) { + point.y -= getFontMetrics(g.getFont()).getDescent(); + } + + g.drawString(text, (float)point.x, (float)point.y); + } + /** + * Draws the specified wrapped text to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - THe text to use. + * @param x - The x coordinate to draw the text at. + * @param y - The y coordinate to draw the text at. + * @param width - The maximum width of the line. + * @param maxLines - The maximum number of lines, use -1 for infinite. + * @param separation - The space between each line. + */ + public static void drawStringWrap(Graphics2D g, String text, double x, double y, double width, + int maxLines, double separation) { + drawStringWrap(g, text, new Vector(x, y), 0, width, maxLines, separation); + } + /** + * Draws the specified wrapped text to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - THe text to use. + * @param x - The x coordinate to draw the text at. + * @param y - The y coordinate to draw the text at. + * @param alignment - The alignment settings to use. + * @param width - The maximum width of the line. + * @param maxLines - The maximum number of lines, use -1 for infinite. + * @param separation - The space between each line. + */ + public static void drawStringWrap(Graphics2D g, String text, double x, double y, int alignment, + double width, int maxLines, double separation) { + drawStringWrap(g, text, new Vector(x, y), alignment, width, maxLines, separation); + } + /** + * Draws the specified wrapped text to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - The text to use. + * @param point - The point to draw the text at. + * @param width - The maximum width of the line. + * @param maxLines - The maximum number of lines, use -1 for infinite. + * @param separation - The space between each line. + */ + public static void drawStringWrap(Graphics2D g, String text, Vector point, + double width, int maxLines, double separation) { + drawStringWrap(g, text, point, 0, width, maxLines, separation); + } + /** + * Draws the specified wrapped text to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - The text to use. + * @param point - The point to draw the text at. + * @param alignment - The alignment settings to use. + * @param width - The maximum width of the line. + * @param maxLines - The maximum number of lines, use -1 for infinite. + * @param separation - The space between each line. + */ + public static void drawStringWrap(Graphics2D g, String text, Vector point, int alignment, + double width, int maxLines, double separation) { + + String[] lines = getWrappedString(text, g.getFont(), width, maxLines); + + for (int i = 0; i < lines.length; i++) { + drawString(g, lines[i], (float)point.x, (float)(point.y + i * (getStringSize("", g.getFont()).y + separation)), alignment); + } + } + + // ================== Draw String Outline ================== + + /** + * Draws the specified text outline to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - THe text to use. + * @param x - The x coordinate to draw the text at. + * @param y - The y coordinate to draw the text at. + */ + public static void drawStringOutline(Graphics2D g, String text, double x, double y) { + drawStringOutline(g, text, new Vector(x, y), 0); + } + /** + * Draws the specified text outline to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - THe text to use. + * @param x - The x coordinate to draw the text at. + * @param y - The y coordinate to draw the text at. + * @param alignment - The alignment settings to use. + */ + public static void drawStringOutline(Graphics2D g, String text, double x, double y, int alignment) { + drawStringOutline(g, text, new Vector(x, y), alignment); + } + /** + * Draws the specified text outline to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - The text to use. + * @param point - The point to draw the text at. + */ + public static void drawStringOutline(Graphics2D g, String text, Vector point) { + drawStringOutline(g, text, point, 0); + } + /** + * Draws the specified text outline to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - The text to use. + * @param point - The point to draw the text at. + * @param alignment - The alignment settings to use. + */ + public static void drawStringOutline(Graphics2D g, String text, Vector point, int alignment) { + + point = new Vector(point); + + // Font width settings + if ((alignment & 0x03) == ALIGN_CENTER) { + point.x -= getStringSize(text, g.getFont()).x / 2; + } + else if ((alignment & 0x03) == ALIGN_RIGHT) { + point.x -= getStringSize(text, g.getFont()).x; + } + + // Font height settings + if ((alignment & 0x30) == ALIGN_TOP) { + point.y += getFontMetrics(g.getFont()).getAscent(); + } + else if ((alignment & 0x30) == ALIGN_MIDDLE) { + point.y += getFontMetrics(g.getFont()).getAscent(); + point.y -= getFontMetrics(g.getFont()).getHeight() / 2; + } + else if ((alignment & 0x30) == ALIGN_BOTTOM) { + point.y -= getFontMetrics(g.getFont()).getDescent(); + } + + g.draw(getGlyphVector(text, g.getFont()).getOutline((float)point.x, (float)point.y)); + } + /** + * Draws the specified wrapped text outline to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - THe text to use. + * @param x - The x coordinate to draw the text at. + * @param y - The y coordinate to draw the text at. + * @param width - The maximum width of the line. + * @param maxLines - The maximum number of lines, use -1 for infinite. + * @param separation - The space between each line. + */ + public static void drawStringOutlineWrap(Graphics2D g, String text, double x, double y, double width, + int maxLines, double separation) { + drawStringOutlineWrap(g, text, new Vector(x, y), 0, width, maxLines, separation); + } + /** + * Draws the specified wrapped text outline to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - THe text to use. + * @param x - The x coordinate to draw the text at. + * @param y - The y coordinate to draw the text at. + * @param alignment - The alignment settings to use. + * @param width - The maximum width of the line. + * @param maxLines - The maximum number of lines, use -1 for infinite. + * @param separation - The space between each line. + */ + public static void drawStringOutlineWrap(Graphics2D g, String text, double x, double y, int alignment, + double width, int maxLines, double separation) { + drawStringOutlineWrap(g, text, new Vector(x, y), alignment, width, maxLines, separation); + } + /** + * Draws the specified wrapped text outline to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - The text to use. + * @param point - The point to draw the text at. + * @param width - The maximum width of the line. + * @param maxLines - The maximum number of lines, use -1 for infinite. + * @param separation - The space between each line. + */ + public static void drawStringOutlineWrap(Graphics2D g, String text, Vector point, + double width, int maxLines, double separation) { + drawStringOutlineWrap(g, text, point, 0, width, maxLines, separation); + } + /** + * Draws the specified wrapped text outline to the graphics object. + * + * @param g - The graphics object to draw to. + * @param text - The text to use. + * @param point - The point to draw the text at. + * @param alignment - The alignment settings to use. + * @param width - The maximum width of the line. + * @param maxLines - The maximum number of lines, use -1 for infinite. + * @param separation - The space between each line. + */ + public static void drawStringOutlineWrap(Graphics2D g, String text, Vector point, int alignment, + double width, int maxLines, double separation) { + + String[] lines = getWrappedString(text, g.getFont(), width, maxLines); + + for (int i = 0; i < lines.length; i++) { + drawStringOutline(g, lines[i], (float)point.x, (float)(point.y + i * (getStringSize("", g.getFont()).y + separation)), alignment); + } + } + + // ====================== Draw Image ======================= + + /** + * Draws the specified image to the graphics object. + * + * @param g - The graphics object to draw to. + * @param image - The image to use. + * @param x - The x coordinate to draw the image at. + * @param y - The y coordinate to draw the image at. + */ + public static void drawImage(Graphics2D g, Image image, double x, double y) { + drawImage(g, image, new Vector(x, y), 0); + } + /** + * Draws the specified image to the graphics object. + * + * @param g - The graphics object to draw to. + * @param image - The image to use. + * @param x - The x coordinate to draw the image at. + * @param y - The y coordinate to draw the image at. + * @param w - The scaled width of the image. + * @param h - The scaled height of the image. + */ + public static void drawImage(Graphics2D g, Image image, double x, double y, double w, double h) { + drawImage(g, image, new Vector(x, y), new Vector(w, h)); + } + /** + * Draws the specified image to the graphics object. + * + * @param g - The graphics object to draw to. + * @param image - The image to use. + * @param x - The x coordinate to draw the image at. + * @param y - The y coordinate to draw the image at. + * @param alignment - The alignment settings to use. + */ + public static void drawImage(Graphics2D g, Image image, double x, double y, int alignment) { + drawImage(g, image, new Vector(x, y), alignment); + } + /** + * Draws the specified image to the graphics object. + * + * @param g - The graphics object to draw to. + * @param image - The image to use. + * @param point - The point to draw the image at. + */ + public static void drawImage(Graphics2D g, Image image, Vector point) { + drawImage(g, image, point, 0); + } + /** + * Draws the specified image to the graphics object. + * + * @param g - The graphics object to draw to. + * @param image - The image to use. + * @param point - The point to draw the image at. + * @param size - The scaled size of the image. + */ + public static void drawImage(Graphics2D g, Image image, Vector point, Vector size) { + if (image != null) { + g.drawImage(image, (int)point.x, (int)point.y, (int)size.x, (int)size.y, null); + } + } + /** + * Draws the specified image to the graphics object. + * + * @param g - The graphics object to draw to. + * @param image - The image to use. + * @param point - The point to draw the image at. + * @param alignment - The alignment settings to use. + */ + public static void drawImage(Graphics2D g, Image image, Vector point, int alignment) { + point = new Vector(point); + + if (image != null) { + + // Image width settings + if ((alignment & 0x03) == ALIGN_CENTER) { + point.x -= (double)image.getWidth(null) / 2; + } + else if ((alignment & 0x03) == ALIGN_RIGHT) { + point.x -= (double)image.getWidth(null); + } + + // Image height settings + if ((alignment & 0x30) == ALIGN_MIDDLE) { + point.y -= (double)image.getHeight(null) / 2; + } + else if ((alignment & 0x30) == ALIGN_BOTTOM) { + point.y -= (double)image.getHeight(null); + } + + g.drawImage(image, (int)point.x, (int)point.y, null); + } + } + + // ====================== Draw Shape ====================== + + /** + * Draws the specified line to the graphics object. + * + * @param g - The graphics object to draw to. + * @param x1 - The x of the first end point. + * @param y1 - The y of the first end point. + * @param x2 - The x of the second end point. + * @param y2 - The y of the second end point. + */ + public static void drawLine(Graphics2D g, double x1, double y1, double x2, double y2) { + g.drawLine((int)x1, (int)y1, (int)x2, (int)y2); + } + /** + * Draws the specified line to the graphics object. + * + * @param g - The graphics object to draw to. + * @param end1 - The first end point. + * @param end2 - The second end point. + */ + public static void drawLine(Graphics2D g, Vector end1, Vector end2) { + g.drawLine((int)end1.x, (int)end1.y, (int)end2.x, (int)end2.y); + } + /** + * Draws the specified line to the graphics object. + * + * @param g - The graphics object to draw to. + * @param l - The line to draw. + */ + public static void drawLine(Graphics2D g, Line l) { + g.drawLine((int)l.end1.x, (int)l.end1.y, (int)l.end2.x, (int)l.end2.y); + } + /** + * Draws the specified rectangle to the graphics object. + * + * @param g - The graphics object to draw to. + * @param x - The x coordinate to draw the rectangle at. + * @param y - The y coordinate to draw the rectangle at. + * @param w - The width of the rectangle. + * @param h - The height of the rectangle. + */ + public static void drawRect(Graphics2D g, double x, double y, double w, double h) { + g.drawRect((int)x, (int)y, (int)w, (int)h); + } + /** + * Draws the specified rectangle to the graphics object. + * + * @param g - The graphics object to draw to. + * @param point - The point to draw the rectangle at. + * @param size - The size of the rectangle. + */ + public static void drawRect(Graphics2D g, Vector point, Vector size) { + g.drawRect((int)point.x, (int)point.y, (int)size.x, (int)size.y); + } + /** + * Draws the specified rectangle to the graphics object. + * + * @param g - The graphics object to draw to. + * @param r - The rectangle to draw. + */ + public static void drawRect(Graphics2D g, Rectangle r) { + g.drawRect((int)r.point.x, (int)r.point.y, (int)r.size.x, (int)r.size.y); + } + /** + * Draws the specified ellipse to the graphics object. + * + * @param g - The graphics object to draw to. + * @param x - The x coordinate to draw the ellipse at. + * @param y - The y coordinate to draw the ellipse at. + * @param w - The width of the ellipse. + * @param h - The height of the ellipse. + * @param origin - True if the x and y coordinates are the origin. + */ + public static void drawEllipse(Graphics2D g, double x, double y, double w, double h, boolean origin) { + if (origin) + g.drawOval((int)(x - w), (int)(y - h), (int)(w * 2), (int)(h * 2)); + else + g.drawOval((int)x, (int)y, (int)w, (int)h); + } + /** + * Draws the specified ellipse to the graphics object. + * + * @param g - The graphics object to draw to. + * @param point - The point to draw the ellipse at. + * @param size - The size of the ellipse. + * @param origin - True if the x and y coordinates are the origin. + */ + public static void drawEllipse(Graphics2D g, Vector point, Vector size, boolean origin) { + if (origin) + g.drawOval((int)(point.x - size.x), (int)(point.y - size.y), (int)(size.x * 2), (int)(size.y * 2)); + else + g.drawOval((int)point.x, (int)point.y, (int)size.x, (int)size.y); + } + /** + * Draws the specified ellipse to the graphics object. + * + * @param g - The graphics object to draw to. + * @param e - The ellipse to draw. + */ + public static void drawEllipse(Graphics2D g, Ellipse e) { + g.drawOval((int)e.point.x, (int)e.point.y, (int)e.size.x, (int)e.size.y); + } + /** + * Draws the specified polygon to the graphics object. + * + * @param g - The graphics object to draw to. + * @param points - The list of x and y coordinates to add to the polygon. + */ + public static void drawPolygon(Graphics2D g, double... points) { + int nPoints = (points.length + 1) / 2; + int[] xPoints = new int[nPoints]; + int[] yPoints = new int[nPoints]; + + for (int i = 0; i < nPoints; i += 2) { + xPoints[i / 2] = (int)points[i]; + yPoints[i / 2] = (int)points[i + 1]; + } + g.drawPolygon(xPoints, yPoints, nPoints); + } + /** + * Draws the specified polygon to the graphics object. + * + * @param g - The graphics object to draw to. + * @param points - The list of points to add to the polygon. + */ + public static void drawPolygon(Graphics2D g, Vector... points) { + int nPoints = points.length; + int[] xPoints = new int[nPoints]; + int[] yPoints = new int[nPoints]; + + for (int i = 0; i < nPoints; i++) { + xPoints[i] = (int)points[i].x; + yPoints[i] = (int)points[i].y; + } + g.drawPolygon(xPoints, yPoints, nPoints); + } + /** + * Draws the specified polygon to the graphics object. + * + * @param g - The graphics object to draw to. + * @param r - The rectangle to draw. + */ + public static void drawPolygon(Graphics2D g, Polygon p) { + int nPoints = p.npoints; + int[] xPoints = new int[nPoints]; + int[] yPoints = new int[nPoints]; + + for (int i = 0; i < nPoints; i++) { + xPoints[i] = (int)p.points[i].x; + yPoints[i] = (int)p.points[i].y; + } + g.drawPolygon(xPoints, yPoints, nPoints); + } + + // ====================== Draw Shape ====================== + + /** + * Draws the specified rectangle to the graphics object. + * + * @param g - The graphics object to draw to. + * @param x - The x coordinate to draw the rectangle at. + * @param y - The y coordinate to draw the rectangle at. + * @param w - The width of the rectangle. + * @param h - The height of the rectangle. + */ + public static void fillRect(Graphics2D g, double x, double y, double w, double h) { + g.fillRect((int)x, (int)y, (int)w, (int)h); + } + /** + * Draws the specified rectangle to the graphics object. + * + * @param g - The graphics object to draw to. + * @param point - The point to draw the rectangle at. + * @param size - The size of the rectangle. + */ + public static void fillRect(Graphics2D g, Vector point, Vector size) { + g.fillRect((int)point.x, (int)point.y, (int)size.x, (int)size.y); + } + /** + * Draws the specified rectangle to the graphics object. + * + * @param g - The graphics object to draw to. + * @param r - The rectangle to draw. + */ + public static void fillRect(Graphics2D g, Rectangle r) { + g.fillRect((int)r.point.x, (int)r.point.y, (int)r.size.x, (int)r.size.y); + } + /** + * Draws the specified ellipse to the graphics object. + * + * @param g - The graphics object to draw to. + * @param x - The x coordinate to draw the ellipse at. + * @param y - The y coordinate to draw the ellipse at. + * @param w - The width of the ellipse. + * @param h - The height of the ellipse. + * @param origin - True if the x and y coordinates are the origin. + */ + public static void fillEllipse(Graphics2D g, double x, double y, double w, double h, boolean origin) { + if (origin) + g.fillOval((int)(x - w), (int)(y - h), (int)(w * 2), (int)(h * 2)); + else + g.fillOval((int)x, (int)y, (int)w, (int)h); + } + /** + * Draws the specified ellipse to the graphics object. + * + * @param g - The graphics object to draw to. + * @param point - The point to draw the ellipse at. + * @param size - The size of the ellipse. + * @param origin - True if the x and y coordinates are the origin. + */ + public static void fillEllipse(Graphics2D g, Vector point, Vector size, boolean origin) { + if (origin) + g.fillOval((int)(point.x - size.x), (int)(point.y - size.y), (int)(size.x * 2), (int)(size.y * 2)); + else + g.fillOval((int)point.x, (int)point.y, (int)size.x, (int)size.y); + } + /** + * Draws the specified ellipse to the graphics object. + * + * @param g - The graphics object to draw to. + * @param e - The ellipse to draw. + */ + public static void fillEllipse(Graphics2D g, Ellipse e) { + g.fillOval((int)e.point.x, (int)e.point.y, (int)e.size.x, (int)e.size.y); + } + /** + * Draws the specified polygon to the graphics object. + * + * @param g - The graphics object to draw to. + * @param points - The list of x and y coordinates to add to the polygon. + */ + public static void fillPolygon(Graphics2D g, double... points) { + int nPoints = (points.length + 1) / 2; + int[] xPoints = new int[nPoints]; + int[] yPoints = new int[nPoints]; + + for (int i = 0; i < nPoints; i += 2) { + xPoints[i / 2] = (int)points[i]; + yPoints[i / 2] = (int)points[i + 1]; + } + g.fillPolygon(xPoints, yPoints, nPoints); + } + /** + * Draws the specified polygon to the graphics object. + * + * @param g - The graphics object to draw to. + * @param points - The list of points to add to the polygon. + */ + public static void fillPolygon(Graphics2D g, Vector... points) { + int nPoints = points.length; + int[] xPoints = new int[nPoints]; + int[] yPoints = new int[nPoints]; + + for (int i = 0; i < nPoints; i++) { + xPoints[i] = (int)points[i].x; + yPoints[i] = (int)points[i].y; + } + g.fillPolygon(xPoints, yPoints, nPoints); + } + /** + * Draws the specified polygon to the graphics object. + * + * @param g - The graphics object to draw to. + * @param r - The rectangle to draw. + */ + public static void fillPolygon(Graphics2D g, Polygon p) { + int nPoints = p.npoints; + int[] xPoints = new int[nPoints]; + int[] yPoints = new int[nPoints]; + + for (int i = 0; i < nPoints; i++) { + xPoints[i] = (int)p.points[i].x; + yPoints[i] = (int)p.points[i].y; + } + g.fillPolygon(xPoints, yPoints, nPoints); + } +} diff --git a/MetroidMapGuardian/src/graphics/Gui.java b/MetroidMapGuardian/src/graphics/Gui.java new file mode 100644 index 0000000..a3c57a4 --- /dev/null +++ b/MetroidMapGuardian/src/graphics/Gui.java @@ -0,0 +1,176 @@ +package graphics; + +import game.GameInstance; +import game.Trilogy; +import geometry.Rectangle; +import geometry.Vector; + +import java.awt.Graphics2D; +import room.Room; + +/** + * + * @author Jrob + * + */ +public abstract class Gui { + + // ==================== Public Members ==================== + + /** The game this entity is linked to. */ + public GameInstance instance; + public Trilogy trilogy; + /** The room that contains this entity. */ + public Room room; + /** + * A string that represents a way to access the entity without receiving + * information about it in advance. + */ + public String id; + /** + * The draw depth of the entity, entities with higher depths will draw + * before entities with lower depths. + */ + public int depth; + /** The position on the map of the entity. */ + public Vector position; + + public Rectangle bounds; + /** True if the entity has been destroyed. */ + public boolean destroyed; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + protected Gui() { + this.instance = null; + this.trilogy = null; + this.room = null; + + this.id = ""; + this.depth = 0; + + this.position = new Vector(); + + this.destroyed = false; + } + /** + * Constructs an entity with the specified details. + * + * @param id - The key identifier of the entity. + * @param depth - The depth of the entity. + * @param position - The position of the entity. + * @return Returns an entity with the specified details. + */ + protected Gui(String id, int depth, Vector position) { + this.instance = null; + this.trilogy = null; + this.room = null; + + this.id = id; + this.depth = depth; + + this.position = new Vector(position); + + this.destroyed = false; + } + /** + * Constructs the entity from an NBT compound of values. This is mainly used + * To load entire maps from file in NBT format. + * + * @param nbt - The compound containing the tags related to the entity. + * @return Returns the entity constructed from tag data. + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ + /*protected Gui(NBTTagCompound nbt) { + instance = null; + room = null; + id = nbt.getString("id", ""); + depth = nbt.getInteger("depth", 0); + position = new Vector(nbt.getDouble("x", 0.0), nbt.getDouble("y", 0.0)); + + destroyed = false; + }*/ + /** + * Initializes the entity by setting the game instance it is linked to. + * + * @param room - The room that contains the entity. + * @param instance - The game instance that contains the room. + */ + public void initialize(Room room, GameInstance instance, Trilogy trilogy) { + this.room = room; + this.trilogy = trilogy; + this.instance = instance; + } + + // ===================== NBT File IO ====================== + + /** + * Saves tag information about the entity to the NBT compound. + * + * @param nbt - The NBT compound to save tag information to. + * + * @see + * {@linkplain NBTTagCompound} + */ + /*public void saveGui(NBTTagCompound nbt) { + nbt.setString( "id", id); + nbt.setInteger( "depth", depth); + nbt.setDouble( "x", position.x); + nbt.setDouble( "y", position.y); + }*/ + /** + * Saves the entity to an NBT compound tag. + * + * @return Returns the NBT compound containing the values on the entity. + * + * @see + * {@linkplain NBTTagCompound} + */ + //public abstract NBTTagCompound saveGui(); + /** + * Creates an entity based on the information given from an NBT compound. The + * entity must first be defined in EntityLoader in order to be loaded from a + * map file. + * + * @param nbt - The NBT compound containing tag information on the entity. + * @return Returns an entity constructed from the specified tag information. + * + * @see + * {@linkplain NBTTagCompound}, + * {@linkplain EntityLoader} + */ + //public abstract Gui loadGui(NBTTagCompound nbt); + + // ======================== Updating ======================== + + /** + * Called every step for the entity to perform actions and update. + */ + public void update() { + + + } + /** + * Called every step for the entity to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + } + /** + * Destroys the entity and marks it for removal. + */ + public void destroy() { + destroyed = true; + } + +} diff --git a/MetroidMapGuardian/src/graphics/LinkedImage.java b/MetroidMapGuardian/src/graphics/LinkedImage.java new file mode 100644 index 0000000..e0f3222 --- /dev/null +++ b/MetroidMapGuardian/src/graphics/LinkedImage.java @@ -0,0 +1,95 @@ +package graphics; + +import geometry.Vector; + +import java.awt.Image; + +import main.ImageLoader; + +/** + * An image linked to a resource image. This way the image can exist even + * if the resource is not loaded. + * + * @author Robert Jordan + * @see + * {@linkplain ImageLoader}, + * {@linkplain ImageResource} + */ +public class LinkedImage { + + // ==================== Public Members ==================== + + /** The name of the image. */ + protected String resourceName; + /** The group of the image. */ + protected String resourceGroup; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a linked image with no name. + * + * @return Returns the default linked image. + */ + public LinkedImage() { + this.resourceName = ""; + this.resourceGroup = ""; + } + /** + * Constructs a linked image with the specified name. + * + * @param name - The name of the image. + * @return Returns a linked image with the specified name. + */ + public LinkedImage(String name, String group) { + this.resourceName = name; + this.resourceGroup = group; + } + + // ======================= Methods ======================== + + /** + * Gets the image with the given name. + * + * @return Returns the image or null if the image has not been loaded. + */ + public Image getImage() { + return ImageLoader.getImage(resourceName, resourceGroup); + } + /** + * Gets the width of the image. + * + * @return Returns the image's width. + */ + public int getWidth() { + Image image = ImageLoader.getImage(resourceName, resourceGroup); + if (image != null) + return image.getWidth(null); + + return 0; + } + /** + * Gets the height of the image. + * + * @return Returns the image's height. + */ + public int getHeight() { + Image image = ImageLoader.getImage(resourceName, resourceGroup); + if (image != null) + return image.getHeight(null); + + return 0; + } + /** + * Gets the height of the image. + * + * @return Returns the image's height. + */ + public Vector getSize() { + Image image = ImageLoader.getImage(resourceName, resourceGroup); + if (image != null) + return new Vector(image.getWidth(null), image.getHeight(null)); + + return new Vector(); + } +} diff --git a/MetroidMapGuardian/src/graphics/MarkerDetails.java b/MetroidMapGuardian/src/graphics/MarkerDetails.java new file mode 100644 index 0000000..a2cb2a1 --- /dev/null +++ b/MetroidMapGuardian/src/graphics/MarkerDetails.java @@ -0,0 +1,169 @@ +package graphics; + +import game.GameInstance; +import game.PowerUp; +import game.Trilogy; +import geometry.Rectangle; +import geometry.Vector; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.Image; + +import entity.Marker; +import main.ImageLoader; +import main.Keyboard; +import main.Mouse; +import room.Room; + +/** + * A gui that displays details about the marker's power up. When the mouse is + * no longer hovering over the marker, then the gui will be destroyed. + * + * @author Robert Jordan + * @see + * {@linkplain Marker} + */ +public class MarkerDetails extends Gui { + + // ==================== Public Members ==================== + + /** The marker this display is linked to. */ + public Marker marker; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a gui at (0, 0)). + * + * @return Returns the default gui. + */ + public MarkerDetails() { + super(); + this.marker = null; + } + /** + * Constructs an entity with the specified details. + * + * @param marker - The marker to link the gui to. + * @return Returns an gui with the specified details. + */ + public MarkerDetails(Marker marker) { + super("", -5, new Vector()); + this.marker = marker; + } + /** + * Initializes the entity by setting the game instance it is linked to. + * + * @param room - The room that contains the entity. + * @param instance - The game instance that contains the room. + */ + public void initialize(Room room, GameInstance instance, Trilogy trilogy) { + super.initialize(room, instance, trilogy); + } + + // ======================== Updating ======================== + + /** + * Called every step for the entity to perform actions and update. + */ + public void update() { + + // Destroy the display if the marker doesn't exist or the mouse is not + // hovering over it. + if (!marker.hovering || !room.entityExists(marker)) { + destroy(); + } + } + /** + * Called every step for the entity to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + Font font = new Font("Crystal clear", Font.PLAIN, 12); + + this.position = Mouse.getVector(); + + Vector size = new Vector(256, 0); + + double boxWidth = size.x - 8; + double drawWidth = boxWidth - 6 - 5; + double drawSeparation = 0; + int maxLines = 10; + + PowerUp powerUp = marker.getPowerUp(); + if (Keyboard.shift.down() && marker.hasLinkedPowerUp()) { + powerUp = marker.getLinkedPowerUp(); + } + + String title = powerUp.getTypeName() + ": " + powerUp.name; + String location = powerUp.location; + String description = powerUp.description; + + String num = Integer.toString(marker.index + 1); + while (num.length() < 3) { + num = "0" + num; + } + + Image image = ImageLoader.getImage(trilogy.rawName + "/" + PowerUp.getPowerUpRawName(marker.type) + "/" + num); + + + double titleHeight = Draw.getStringWrapSize(title, font, drawWidth, maxLines, drawSeparation).y; + double locationHeight = Draw.getStringWrapSize(location, font, drawWidth, maxLines, drawSeparation).y; + double descriptionHeight = Draw.getStringWrapSize(description, font, drawWidth, maxLines, drawSeparation).y; + double imageHeight = 0; + if (image != null) + imageHeight = image.getHeight(null); + + Rectangle titleRect = new Rectangle(new Vector(4, 4), + new Vector(boxWidth, titleHeight + 6)); + Rectangle locationRect = new Rectangle(titleRect.point.plus(0, titleRect.size.y + 4), + new Vector(boxWidth, locationHeight + 6)); + Rectangle descriptionRect = new Rectangle(locationRect.point.plus(0, locationRect.size.y + 4), + new Vector(boxWidth, descriptionHeight + 6)); + Rectangle imageRect = new Rectangle(descriptionRect.point.plus(0, descriptionRect.size.y + 4), + new Vector(boxWidth, imageHeight + 6)); + + if (image != null) + size.y = imageRect.point.y + imageRect.size.y + 4; + else + size.y = descriptionRect.point.y + descriptionRect.size.y + 4; + + Rectangle window = new Rectangle(position, size); + + titleRect.translate(position); + locationRect.translate(position); + descriptionRect.translate(position); + imageRect.translate(position); + + g.setPaint(new GradientPaint((float)position.x, (float)position.y, new Color(46, 102, 133, 210), + (float)position.x, (float)(position.y + size.y), new Color(16, 36, 47, 210))); + + Draw.fillRect(g, window); + g.setColor(new Color(16, 36, 47, 160)); + Draw.fillRect(g, titleRect); + Draw.fillRect(g, locationRect); + Draw.fillRect(g, descriptionRect); + if (image != null) + Draw.fillRect(g, imageRect); + g.setColor(new Color(76, 147, 179, 210)); + Draw.drawRect(g, window); + + g.setFont(font); + g.setColor(new Color(33, 189, 222)); + + //System.out.println(Draw.getStringSize("From here, turn around and look for", font)); + Draw.drawStringWrap(g, title, titleRect.point.plus(3, 3), Draw.ALIGN_TOP, drawWidth, maxLines, drawSeparation); + Draw.drawStringWrap(g, location, locationRect.point.plus(3, 3), Draw.ALIGN_TOP, drawWidth, maxLines, drawSeparation); + Draw.drawStringWrap(g, description, descriptionRect.point.plus(3, 3), Draw.ALIGN_TOP, drawWidth, maxLines, drawSeparation); + + //System.out.println(Draw.getStringSize("From here, turn around and look for", font)); + if (image != null) + Draw.drawImage(g, image, imageRect.point.plus(3 + drawWidth / 2 - image.getWidth(null) / 2, 3)); + } + +} diff --git a/MetroidMapGuardian/src/graphics/MiniMap.java b/MetroidMapGuardian/src/graphics/MiniMap.java new file mode 100644 index 0000000..2b486c9 --- /dev/null +++ b/MetroidMapGuardian/src/graphics/MiniMap.java @@ -0,0 +1,161 @@ +package graphics; + +import entity.Entity; +import entity.Marker; +import game.GameInstance; +import game.Trilogy; +import geometry.Rectangle; +import geometry.Vector; + +import java.awt.Color; +import java.awt.Graphics2D; + +import main.Main; +import main.Mouse; + +import room.Map; +import room.Room; + +public class MiniMap extends Gui { + + // ==================== Public Members ==================== + + //public static final double scale = 12.0; + public static final Vector maxSize = new Vector(192, 224); + + public boolean visible; + + public Vector size; + + public boolean pressed; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + public MiniMap() { + super(); + + visible = true; + size = new Vector(); + pressed = false; + } + /** + * Constructs an entity with the specified details. + * + * @param id - The key identifier of the entity. + * @param depth - The depth of the entity. + * @param position - The position of the entity. + * @param velocity - The velocity of the entity. + * @return Returns an entity with the specified details. + */ + protected MiniMap(String id, int depth, Vector position) { + super("minimap", -10, new Vector(0, 0)); + + visible = true; + size = new Vector(); + } + /** + * Initializes the entity by setting the game instance it is linked to. + * + * @param room - The room that contains the entity. + * @param instance - The game instance that contains the room. + */ + public void initialize(Room room, GameInstance instance, Trilogy trilogy) { + super.initialize(room, instance, trilogy); + } + + // ======================== Updating ======================== + + /** + * Called every step for the entity to perform actions and update. + */ + public void update() { + + LinkedImage image = ((Map)room).image; + double scale = 0.0; + + // Determine which axis has to be shrunk more to fit in the map size: + Vector scaleVec = new Vector((double)image.getWidth() / maxSize.x, (double)image.getHeight() / maxSize.y); + if (scaleVec.x >= scaleVec.y) + scale = scaleVec.x; + else + scale = scaleVec.y; + size = ((Map)room).image.getSize().scaledBy(1.0 / scale); + + position = new Vector(Main.frame.getContentPane().getWidth() - 24, Main.frame.getContentPane().getHeight() - 24 - 32).minus(size); + + Rectangle rect = new Rectangle(position, size); + + if (rect.contains(Mouse.getVector())) { + room.isMouseOverGUI = true; + if (Mouse.left.pressed()) { + pressed = true; + } + if (Mouse.left.down() && pressed) { + Vector mouseCenter = Mouse.getVector().minus(position).scaledBy(scale); + mouseCenter.sub(Main.frame.getContentPane().getWidth() / (2 * room.view.zoom), + Main.frame.getContentPane().getHeight() / (2 * room.view.zoom)); + room.view.pan = mouseCenter; + } + } + if (Mouse.left.released()) { + pressed = false; + } + } + /** + * Called every step for the entity to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + LinkedImage image = ((Map)room).image; + double scale = 0.0; + + // Determine which axis has to be shrunk more to fit in the map size: + Vector scaleVec = new Vector((double)image.getWidth() / maxSize.x, (double)image.getHeight() / maxSize.y); + if (scaleVec.x >= scaleVec.y) + scale = scaleVec.x; + else + scale = scaleVec.y; + size = ((Map)room).image.getSize().scaledBy(1.0 / scale); + + position = new Vector(Main.frame.getContentPane().getWidth() - 24, Main.frame.getContentPane().getHeight() - 24 - 32).minus(size); + + Vector windowSize = new Vector(Main.frame.getContentPane().getWidth(), Main.frame.getContentPane().getHeight()).scale(1.0 / room.view.zoom); + + g.setColor(new Color(16, 36, 47, 210)); + Draw.fillRect(g, position, size); + g.setColor(new Color(76, 147, 179, 210)); + Draw.drawRect(g, position, size); + + for (Entity e : room.entities) { + if (e instanceof Marker) { + Marker m = (Marker)e; + if (!m.getPowerUp().collected) { + Vector point = position.plus(m.position.scaledBy(1.0 / scale)).minus(2, 2); + g.setColor(m.getPowerUp().getTypeColor()); + Draw.fillRect(g, point, new Vector(4, 4)); + } + } + } + + Vector viewPoint = position.plus(room.view.pan.scaledBy(1.0 / scale)); + Vector viewSize = windowSize.scaledBy(1.0 / scale); + + java.awt.Rectangle clip = g.getClipBounds(); + g.setClip((int)position.x, (int)position.y, (int)size.x, (int)size.y); + + g.setColor(new Color(255, 255, 255)); + Draw.drawRect(g, viewPoint, viewSize); + + g.setClip(clip); + + + } + +} diff --git a/MetroidMapGuardian/src/graphics/Palette.java b/MetroidMapGuardian/src/graphics/Palette.java new file mode 100644 index 0000000..e82032d --- /dev/null +++ b/MetroidMapGuardian/src/graphics/Palette.java @@ -0,0 +1,57 @@ +package graphics; + +import geometry.Vector; + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.GradientPaint; +import java.io.IOException; +import java.io.InputStream; + +/** + * A static class to store variables for all the different types of + * colors used by the program. This stores: colors, fonts, gradients, + * textures, etc. + * @author Robert Jordan + * @see + * {@linkplain Draw} + */ +public class Palette { + + // ======================== Colors ======================== + + public static final Color colorFont1 = new Color(255, 255, 255); + + public static final Color colorPanelSolid = new Color(255, 255, 255); + public static final Color colorPanelOutline = new Color(255, 255, 255); + + public static final Color colorPanelGradient1 = new Color(255, 255, 255); + public static final Color colorPanelGradient2 = new Color(255, 255, 255); + + // ====================== Gradients ======================= + + + // ======================== Fonts ========================= + + public static Font fontEurostar = loadFont("resources/fonts/eurostar.ttf"); + + private static Font loadFont(String path) { + try { + InputStream stream = ClassLoader.getSystemResourceAsStream(path); + return Font.createFont(Font.TRUETYPE_FONT, stream); + } + catch (FontFormatException e) { + e.printStackTrace(); + } + catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + public static GradientPaint getGradient(GradientPaint gradient, Vector point1, Vector point2) { + return null; + } + +} diff --git a/MetroidMapGuardian/src/graphics/PopupAbout.java b/MetroidMapGuardian/src/graphics/PopupAbout.java new file mode 100644 index 0000000..e24f492 --- /dev/null +++ b/MetroidMapGuardian/src/graphics/PopupAbout.java @@ -0,0 +1,114 @@ +package graphics; + +import game.GameInstance; +import game.Trilogy; +import geometry.Vector; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Image; + +import main.ImageLoader; +import main.Main; +import main.Mouse; + +import room.Room; + +public class PopupAbout extends Gui { + + // ==================== Public Members ==================== + + public Vector size; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + public PopupAbout() { + super("popup", 100, new Vector()); + + size = new Vector(660, 350); + } + /** + * Initializes the entity by setting the game instance it is linked to. + * + * @param room - The room that contains the entity. + * @param instance - The game instance that contains the room. + */ + public void initialize(Room room, GameInstance instance, Trilogy trilogy) { + super.initialize(room, instance, trilogy); + } + + // ======================== Updating ======================== + + /** + * Called every step for the entity to perform actions and update. + */ + public void update() { + + room.isMouseOverGUI = true; + + if (Mouse.left.pressed() || Mouse.right.pressed() || Mouse.middle.pressed() || + Mouse.wheelUp() || Mouse.wheelDown()) { + destroy(); + } + + } + /** + * Called every step for the entity to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + position = new Vector((Main.frame.getContentPane().getWidth() - size.x) / 2, + (Main.frame.getContentPane().getHeight() - size.y) / 2); + + g.setColor(new Color(16, 36, 47, 210)); + Draw.fillRect(g, position, size); + g.setColor(new Color(76, 147, 179, 210)); + Draw.drawRect(g, position, size); + + g.setColor(new Color(12, 26, 36, 180)); + Draw.fillRect(g, position.plus(10, 10), new Vector(148, size.y - 20)); + + g.setFont(Palette.fontEurostar.deriveFont(Font.PLAIN, 22)); + g.setColor(new Color(33, 189, 222)); + Draw.drawStringWrap(g, + "Metroid Map Guardian\n" + + "Copyright (c) 2013 Robert Jordan\n" + + "\n" + + "\n" + + "Many thanks to Falcon Zero for permission to use his maps and " + + "guides for this program. Visit Metroid Recon (metroid.retropixel.net) " + + "for the full guides and item descriptions.\n" + + "\n" + + "Samus head icon by Nahlej on DeviantArt.\n" + + //"\n" + + "S emblem icon by newbreed on DeviantArt.", + position.plus(180, 20), Draw.ALIGN_TOP, 440, -1, 0); + + Image image = ImageLoader.getImage("s_emblem128"); + Draw.drawImage(g, image, position.plus(20, 40)); + + /*System.out.println("Many thanks to Falcon Zero for permission to use " + + "his maps and guides for this program. " + + "Visit Metroid Recon for the full guides and item descriptions.\n\n" + + "Samus head icon by Nahlej on DeviantArt.\n\n" + + "S emblem icon by newbreed on DeviantArt.");*/ + /*Draw.drawStringWrap(g, "Visit Metroid Recon for the full guides " + + "and item descriptions.", position.plus(30, 80), + Draw.ALIGN_TOP, 440, 10, 0); + + + Draw.drawStringWrap(g, "Samus head icon by Nahlej on DeviantArt.", position.plus(30, 190), + Draw.ALIGN_TOP, 440, 10, 0); + + Draw.drawStringWrap(g, "S emblem icon by newbreed on DeviantArt.", position.plus(30, 230), + Draw.ALIGN_TOP, 440, 10, 0);*/ + } + +} diff --git a/MetroidMapGuardian/src/graphics/PopupControls.java b/MetroidMapGuardian/src/graphics/PopupControls.java new file mode 100644 index 0000000..dce95bb --- /dev/null +++ b/MetroidMapGuardian/src/graphics/PopupControls.java @@ -0,0 +1,91 @@ +package graphics; + +import game.GameInstance; +import game.Trilogy; +import geometry.Vector; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; + +import main.Main; +import main.Mouse; + +import room.Room; + +public class PopupControls extends Gui { + + // ==================== Public Members ==================== + + public Vector size; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + public PopupControls() { + super("popup", 100, new Vector()); + + size = new Vector(640, 380); + } + /** + * Initializes the entity by setting the game instance it is linked to. + * + * @param room - The room that contains the entity. + * @param instance - The game instance that contains the room. + */ + public void initialize(Room room, GameInstance instance, Trilogy trilogy) { + super.initialize(room, instance, trilogy); + } + + // ======================== Updating ======================== + + /** + * Called every step for the entity to perform actions and update. + */ + public void update() { + + room.isMouseOverGUI = true; + + if (Mouse.left.pressed() || Mouse.right.pressed() || Mouse.middle.pressed() || + Mouse.wheelUp() || Mouse.wheelDown()) { + destroy(); + } + + } + /** + * Called every step for the entity to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + position = new Vector((Main.frame.getContentPane().getWidth() - size.x) / 2, + (Main.frame.getContentPane().getHeight() - size.y) / 2); + + g.setColor(new Color(16, 36, 47, 210)); + Draw.fillRect(g, position, size); + g.setColor(new Color(76, 147, 179, 210)); + Draw.drawRect(g, position, size); + + g.setFont(Palette.fontEurostar.deriveFont(Font.PLAIN, 22)); + g.setColor(new Color(33, 189, 222)); + Draw.drawStringWrap(g, + "Controls\n" + + "\n" + + "RMB on map - Move the view.\n" + + "LMB on minimap - Move the view.\n" + + "Mouse wheel - Zoom in and out.\n" + + "\n" + + "Insert - Toggle showing symbols for uncollected power-ups.\n" + + "\n" + + "RMB on power-up - Display full power-up details.\n" + + "\n" + + "F3 - Toggle debug mode.\n" + + "F11 - Toggle fullscreen mode.\n", + position.plus(26, 20), Draw.ALIGN_TOP, 600, -1, 0); + } + +} diff --git a/MetroidMapGuardian/src/graphics/PopupMarkerDetails.java b/MetroidMapGuardian/src/graphics/PopupMarkerDetails.java new file mode 100644 index 0000000..0cfb91e --- /dev/null +++ b/MetroidMapGuardian/src/graphics/PopupMarkerDetails.java @@ -0,0 +1,173 @@ +package graphics; + +import game.GameInstance; +import game.PowerUp; +import game.Trilogy; +import geometry.Rectangle; +import geometry.Vector; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.Image; + +import entity.Marker; +import main.ImageLoader; +import main.Keyboard; +import main.Main; +import main.Mouse; + +import room.Room; + +public class PopupMarkerDetails extends Gui { + + // ==================== Public Members ==================== + + /** The marker this display is linked to. */ + public Marker marker; + + public Vector size; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + public PopupMarkerDetails() { + super("popup", 100, new Vector()); + this.marker = null; + size = new Vector(660, 350); + } + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + public PopupMarkerDetails(Marker marker) { + super("popup", 100, new Vector()); + this.marker = marker; + size = new Vector(660, 350); + } + /** + * Initializes the entity by setting the game instance it is linked to. + * + * @param room - The room that contains the entity. + * @param instance - The game instance that contains the room. + */ + public void initialize(Room room, GameInstance instance, Trilogy trilogy) { + super.initialize(room, instance, trilogy); + } + + // ======================== Updating ======================== + + /** + * Called every step for the entity to perform actions and update. + */ + public void update() { + + room.isMouseOverGUI = true; + + if (Mouse.left.pressed() || Mouse.right.pressed() || Mouse.middle.pressed() || + Mouse.wheelUp() || Mouse.wheelDown()) { + destroy(); + } + + } + /** + * Called every step for the entity to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + Font font = new Font("Crystal clear", Font.PLAIN, 12); + + this.position = Mouse.getVector(); + + Vector size = new Vector(256 + 400 + 4, 0); + + double boxWidth1 = 256 - 8; + double drawWidth1 = boxWidth1 - 6 - 5; + double boxWidth2 = 400; + double drawWidth2 = boxWidth2 - 6 - 5; + double drawSeparation = 0; + int maxLines = 30; + + PowerUp powerUp = marker.getPowerUp(); + if (Keyboard.shift.down() && marker.hasLinkedPowerUp()) { + powerUp = marker.getLinkedPowerUp(); + } + + String title = powerUp.getTypeName() + ": " + powerUp.name; + String location = powerUp.location; + String description = powerUp.description; + + String num = Integer.toString(marker.index + 1); + while (num.length() < 3) { + num = "0" + num; + } + + Image image = ImageLoader.getImage(trilogy.rawName + "/" + PowerUp.getPowerUpRawName(marker.type) + "/" + num); + + double titleHeight = Draw.getStringWrapSize(title, font, drawWidth1, maxLines, drawSeparation).y; + double locationHeight = Draw.getStringWrapSize(location, font, drawWidth1, maxLines, drawSeparation).y; + double descriptionHeight = Draw.getStringWrapSize(description, font, drawWidth2, maxLines, drawSeparation).y; + double imageHeight = 0; + if (image != null) + imageHeight = image.getHeight(null); + + Rectangle titleRect = new Rectangle(new Vector(4, 4), + new Vector(boxWidth1, titleHeight + 6)); + Rectangle locationRect = new Rectangle(titleRect.point.plus(0, titleRect.size.y + 4), + new Vector(boxWidth1, locationHeight + 6)); + Rectangle imageRect = new Rectangle(locationRect.point.plus(0, locationRect.size.y + 4), + new Vector(boxWidth1, imageHeight + 6)); + + Rectangle descriptionRect = new Rectangle(new Vector(256, 4), + new Vector(boxWidth2, descriptionHeight + 6)); + + double height1 = (image != null ? (imageRect.point.y + imageRect.size.y) : + (locationRect.point.y + locationRect.size.y)) + 4; + + double height2 = descriptionRect.point.y + descriptionRect.size.y + 4; + + size.y = Math.max(height1, height2); + + position = new Vector((Main.frame.getContentPane().getWidth() - size.x) / 2, + (Main.frame.getContentPane().getHeight() - size.y) / 2); + + Rectangle window = new Rectangle(position, size); + + titleRect.translate(position); + locationRect.translate(position); + descriptionRect.translate(position); + imageRect.translate(position); + + g.setPaint(new GradientPaint((float)position.x, (float)position.y, new Color(46, 102, 133, 210), + (float)position.x, (float)(position.y + size.y), new Color(16, 36, 47, 210))); + + Draw.fillRect(g, window); + g.setColor(new Color(16, 36, 47, 160)); + Draw.fillRect(g, titleRect); + Draw.fillRect(g, locationRect); + Draw.fillRect(g, descriptionRect); + if (image != null) + Draw.fillRect(g, imageRect); + g.setColor(new Color(76, 147, 179, 210)); + Draw.drawRect(g, window); + + g.setFont(font); + g.setColor(new Color(33, 189, 222)); + + Draw.drawStringWrap(g, title, titleRect.point.plus(3, 3), Draw.ALIGN_TOP, drawWidth1, maxLines, drawSeparation); + Draw.drawStringWrap(g, location, locationRect.point.plus(3, 3), Draw.ALIGN_TOP, drawWidth1, maxLines, drawSeparation); + Draw.drawStringWrap(g, description, descriptionRect.point.plus(3, 3), Draw.ALIGN_TOP, drawWidth2, maxLines, drawSeparation); + + if (image != null) + Draw.drawImage(g, image, imageRect.point.plus(3 + drawWidth1 / 2 - image.getWidth(null) / 2, 3)); + } + +} diff --git a/MetroidMapGuardian/src/graphics/ProfileList.java b/MetroidMapGuardian/src/graphics/ProfileList.java new file mode 100644 index 0000000..46eaff0 --- /dev/null +++ b/MetroidMapGuardian/src/graphics/ProfileList.java @@ -0,0 +1,296 @@ +package graphics; + +import game.Profile; +import geometry.Rectangle; +import geometry.Vector; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.util.ArrayList; + +import main.Main; +import main.Mouse; + +/** + * + * @author Robert Jordan + * + */ +public class ProfileList extends Gui { + + // ==================== Public Members ==================== + + public ArrayList profiles; + public int hoverIndex; + public int selectedIndex; + + public double scrollPosition; + + public double scrollSpeed; + public double scrollScale; + public boolean scrollingUp; + + + public boolean scrollDragging; + public double scrollGrip; + public boolean scrollHover; + + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + public ProfileList() { + super(); + + profiles = new ArrayList(); + scrollPosition = 0.0; + + selectedIndex = -1; + hoverIndex = -1; + this.scrollSpeed = 0.0; + this.scrollingUp = false; + this.scrollScale = 0.0; + scrollDragging = false; + scrollGrip = 0.0; + scrollHover = false; + } + + // ======================== Updating ======================== + + /** + * Called every step for the gui to perform actions and update. + */ + public void update() { + selectedIndex = -1; + hoverIndex = -1; + + Vector size = new Vector(Main.frame.getContentPane().getWidth() - 96 - 24, Main.frame.getContentPane().getHeight() - 200); + position = new Vector(48, 104); + Vector itemSize = new Vector(size.x, 80); + double scrollBarHeight = Math.max(6, size.y / (profiles.size() * itemSize.y) * (size.y - 4)); + double scrollBarPos = (size.y - 4 - scrollBarHeight) / (profiles.size() * itemSize.y - size.y) * scrollPosition; + + Rectangle scrollRect = new Rectangle(position.plus(size.x + 3, scrollBarPos + 3), new Vector(20, scrollBarHeight)); + if (scrollRect.contains(Mouse.getVector())) { + scrollHover = true; + if (Mouse.left.pressed()) { + scrollDragging = true; + scrollGrip = Mouse.getVector().y - scrollRect.point.y; + } + } + else { + scrollHover = false; + } + if (scrollDragging) { + if (Mouse.left.released()) { + scrollDragging = false; + } + else { + scrollBarPos = Mouse.getVector().y - scrollGrip - (position.y + 3); + if (scrollBarPos < 0.0) { + scrollBarPos = 0.0; + } + else if (scrollBarPos > size.y - 4 - scrollBarHeight) { + scrollBarPos = size.y - 4 - scrollBarHeight; + } + scrollPosition = (profiles.size() * itemSize.y - size.y) / (size.y - 4 - scrollBarHeight) * scrollBarPos; + } + } + + for (int i = 0; i < profiles.size() && !scrollDragging; i++) { + Rectangle itemRect = new Rectangle(position.plus(0, i * itemSize.y - scrollPosition), itemSize); + + if (itemRect.point.y + itemRect.size.y >= position.y && + itemRect.point.y <= position.y + size.y) { + + if (itemRect.point.y < position.y) { + Vector newSize = itemRect.size.minus(position).plus(itemRect.point); + itemRect.point = new Vector(position); + itemRect.size = new Vector(newSize); + } + if (itemRect.point.y + itemRect.size.y > position.y + size.y) { + itemRect.size.y += (position.y + size.y) - (itemRect.point.y + itemRect.size.y); + } + + if (itemRect.contains(Mouse.getVector())) { + hoverIndex = i; + if (Mouse.left.pressed()) { + selectedIndex = i; + } + } + } + } + + double scaleMultiplier = 1.2; + double scaleAddition = 0.2; + double speedMultiplier = 4.0; + double speedDeduction = 0.3; + double maxScale = 10.0; + double minScroll = 0.0; + double maxScroll = profiles.size() * itemSize.y - size.y; + + if (Mouse.wheelUp()) { + if (!scrollingUp || scrollSpeed == 0.0) { + scrollScale = 1.0; + scrollSpeed = speedMultiplier; + scrollingUp = true; + } + else { + scrollScale *= scaleMultiplier + scaleAddition; + scrollScale = Math.min(scrollScale, maxScale); + scrollSpeed = speedMultiplier * scrollScale; + } + } + if (Mouse.wheelDown()) { + if (scrollingUp || scrollSpeed == 0.0) { + scrollScale = 1.0; + scrollSpeed = speedMultiplier; + scrollingUp = false; + } + else { + scrollScale *= scaleMultiplier + scaleAddition; + scrollScale = Math.min(scrollScale, maxScale); + scrollSpeed = speedMultiplier * scrollScale; + } + } + + if (scrollSpeed != 0.0) { + scrollSpeed -= speedDeduction * scrollScale; + if (scrollSpeed <= 0.0) { + scrollSpeed = 0.0; + } + else { + if (scrollingUp) { + scrollPosition -= scrollSpeed; + if (scrollPosition <= minScroll) { + scrollPosition = minScroll; + scrollSpeed = 0.0; + } + } + else { + scrollPosition += scrollSpeed; + if (scrollPosition >= maxScroll) { + scrollPosition = maxScroll; + scrollSpeed = 0.0; + } + } + } + } + if (scrollPosition <= minScroll) { + scrollPosition = minScroll; + } + else if (scrollPosition >= maxScroll) { + scrollPosition = maxScroll; + } + } + /** + * Called every step for the gui to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + // Draw the title: + g.setPaint(new GradientPaint(64.0f, 0.0f, new Color(24, 50, 67, 255), + Main.frame.getContentPane().getWidth(), 0.0f, new Color(0, 0, 0, 0))); + Draw.fillRect(g, 0, 24, Main.frame.getContentPane().getWidth(), 104 - 40); + + g.setFont(new Font("Eurostar Black Extended", Font.PLAIN, 52)); + g.setColor(new Color(172, 180, 190)); + Draw.drawString(g, "PROFILE SELECT", 24, 24, Draw.ALIGN_TOP); + + Vector size = new Vector(Main.frame.getContentPane().getWidth() - 96 - 24, Main.frame.getContentPane().getHeight() - 200); + position = new Vector(48, 104); + Vector itemSize = new Vector(size.x, 80); + double scrollBarHeight = Math.min(size.y - 4, Math.max(6, size.y / (profiles.size() * itemSize.y) * (size.y - 4))); + double scrollBarPos = (size.y - 4 - scrollBarHeight) / (profiles.size() * itemSize.y - size.y) * scrollPosition; + + // If the scroll bar is not needed, make it fill the allowed height + if (size.y >= profiles.size() * itemSize.y) { + scrollBarHeight = size.y - 4; + } + + // Draw the list background + g.setColor(new Color(16, 36, 47, 210)); + Draw.fillRect(g, position, size); + Draw.fillRect(g, position.plus(size.x, 0), new Vector(24, size.y)); + + // Draw each profile entry: + for (int i = 0; i < profiles.size(); i++) { + Rectangle itemRect = new Rectangle(position.plus(0, i * itemSize.y - scrollPosition), itemSize); + + // Only draw the profile if it is within the visible portion of the list: + if (itemRect.point.y + itemRect.size.y >= position.y && + itemRect.point.y <= position.y + size.y) { + + java.awt.Rectangle oldClip = g.getClipBounds(); + + Rectangle clipBounds = new Rectangle(itemRect); + + // Set the clip bounds so the rectangle and text do not draw out of bounds + if (itemRect.point.y < position.y) { + clipBounds.point.y = position.y; + clipBounds.size.y += itemRect.point.y - position.y; + } + if (itemRect.point.y + itemRect.size.y > position.y + size.y) { + clipBounds.size.y += (position.y + size.y) - (itemRect.point.y + itemRect.size.y); + } + g.setClip((int)clipBounds.point.x, (int)clipBounds.point.y, (int)clipBounds.size.x, (int)clipBounds.size.y + 1); + + // Highlight the entry if the mouse is hovering over it. + if (hoverIndex == i) { + g.setColor(new Color(46, 102, 133, 210)); + Draw.fillRect(g, itemRect); + } + + int percentX1 = 68; + int percentX2 = 20; + + // Draw the profile name and completion status: + g.setColor(new Color(33, 189, 222)); + //g.setFont(new Font("Eurostar", Font.PLAIN, 28)); + g.setFont(Palette.fontEurostar.deriveFont(Font.PLAIN, 28)); + Draw.drawString(g, profiles.get(i).profileName, itemRect.point.plus(10, 6), Draw.ALIGN_TOP); + //g.setFont(new Font("Eurostar", Font.PLAIN, 18)); + g.setFont(Palette.fontEurostar.deriveFont(Font.PLAIN, 18)); + Draw.drawString(g, "Metroid Prime 1: ", itemRect.point.plus(6, 6).plus(itemRect.size.x - percentX1, 0), Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + Draw.drawString(g, profiles.get(i).getCompletionPercentage(1) + "%", + itemRect.point.plus(6, 6).plus(itemRect.size.x - percentX2, 0), Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + Draw.drawString(g, "Metroid Prime 2: ", itemRect.point.plus(6, 6 + 24).plus(itemRect.size.x - percentX1, 0), Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + Draw.drawString(g, profiles.get(i).getCompletionPercentage(2) + "%", + itemRect.point.plus(6, 6 + 24).plus(itemRect.size.x - percentX2, 0), Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + Draw.drawString(g, "Metroid Prime 3: ", itemRect.point.plus(6, 6 + 48).plus(itemRect.size.x - percentX1, 0), Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + Draw.drawString(g, profiles.get(i).getCompletionPercentage(3) + "%", + itemRect.point.plus(6, 6 + 48).plus(itemRect.size.x - percentX2, 0), Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + /*Draw.drawString(g, "Metroid Prime 2: ", itemRect.point.plus(6, 6 + 24).plus(itemRect.size.x - 192, 0), Draw.ALIGN_TOP); + Draw.drawString(g, "Metroid Prime 3: ", itemRect.point.plus(6, 6 + 48).plus(itemRect.size.x - 192, 0), Draw.ALIGN_TOP);*/ + g.setColor(new Color(76, 147, 179, 210)); + Draw.drawRect(g, itemRect); + + g.setClip(oldClip); + } + } + + if (profiles.isEmpty()) { + g.setColor(new Color(33, 189, 222)); + g.setFont(new Font("Eurostar", Font.PLAIN, 32)); + Draw.drawString(g, "There are no profiles", position.plus(size.scaledBy(0.5)), Draw.ALIGN_CENTER | Draw.ALIGN_TOP); + } + + // Draw the list frames: + g.setColor(new Color(46, 102, 133, 210)); + Draw.drawRect(g, position, size); + Draw.drawRect(g, position.plus(size.x, 0), new Vector(24, size.y)); + + // Draw the scroll bar: + if (scrollHover || scrollDragging) + g.setColor(new Color(62, 130, 170, 210)); + Draw.fillRect(g, position.plus(size.x + 3, 3 + scrollBarPos), new Vector(20, scrollBarHeight).minus(1, 1)); + } +} diff --git a/MetroidMapGuardian/src/graphics/ScalableImage.java b/MetroidMapGuardian/src/graphics/ScalableImage.java new file mode 100644 index 0000000..f3e1b4c --- /dev/null +++ b/MetroidMapGuardian/src/graphics/ScalableImage.java @@ -0,0 +1,263 @@ +package graphics; + +import geometry.Vector; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; + +import main.ImageLoader; + + +/** + * A linked image that can be scaled with ease. The last scaled image is + * stored in the class. + * + * @author Robert Jordan + * @see + * {@linkplain LinkedImage} + */ +public class ScalableImage extends LinkedImage { + + // ======================= Members ======================== + + /** The new scaled image. */ + private BufferedImage scaledImage; + /** The currently used scale. */ + public double scale; + /** True if the scaled image is being used. */ + public boolean isScaled; + /** The color type used by the buffered image. */ + private int colorType; + /** The interpolation used to render the object. */ + private Object interpolation; + /** The maximum size of the scaled image. */ + private double maxScale; + + public boolean scaleInThread; + + private boolean threadFinished = true; + + public boolean finishedScaling = true; + + private boolean shouldUnload = false; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a basic scalable image. + * + * @return Returns the default scalable image. + */ + public ScalableImage() { + super(); + this.scaledImage = null; + this.scale = 1.0; + this.isScaled = false; + this.colorType = BufferedImage.TYPE_INT_ARGB; + this.interpolation = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; + this.maxScale = 1.0; + this.scaleInThread = false; + } + /** + * Constructs a scalable image using the given image. + * + * @param name - The name of the image to use. + * @return Returns a scalable image. + */ + public ScalableImage(String name, String group) { + super(name, group); + this.scaledImage = null; + this.scale = 1.0; + this.isScaled = false; + this.colorType = BufferedImage.TYPE_INT_ARGB; + this.interpolation = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; + this.maxScale = 0.0; + this.scaleInThread = false; + } + /** + * Constructs a scalable image with the given image and color type. + * + * @param name - The name of the image to use. + * @param colorType - The buffered image color type of the scaled image. + * @param interpolation - The interpolation rendering hint. + * @return Returns a scalable image with the given color type. + */ + public ScalableImage(String name, String group, int colorType, Object interpolation) { + super(name, group); + this.scaledImage = null; + this.scale = 1.0; + this.isScaled = false; + this.colorType = colorType; + this.interpolation = interpolation; + this.maxScale = 0.0; + this.scaleInThread = false; + } + /** + * Constructs a scalable image with the given image and color type. + * + * @param name - The name of the image to use. + * @param colorType - The buffered image color type of the scaled image. + * @param interpolation - The interpolation rendering hint. + * @param maxScale - The max size of the image to continuously use. + * @return Returns a scalable image with the given color type. + */ + public ScalableImage(String name, String group, int colorType, Object interpolation, double maxScale) { + super(name, group); + this.scaledImage = null; + this.scale = 1.0; + this.isScaled = false; + this.colorType = colorType; + this.interpolation = interpolation; + this.maxScale = maxScale; + this.scaleInThread = false; + } + + // ==================== Image Details ===================== + + public void unloadScaledImage() { + if (scaleInThread && !threadFinished) { + shouldUnload = true; + } + else { + if (scaledImage != null) + scaledImage.flush(); + scaledImage = null; + scale = 1.0; + isScaled = false; + } + } + /** + * Gets the scaled image. + * + * @return Returns the scaled image. + */ + public Image getScaledImage() { + return (isScaled ? scaledImage : ImageLoader.getImage(resourceName, resourceGroup)); + } + /** + * Tests whether the scaled image is being used. + * + * @return Returns true if the image is using the scaled version. + */ + public boolean isScaled() { + return isScaled; + } + /** + * Returns the scale being used. + * + * @return Returns the current scale or 1.0 if there is no scale + */ + public double getScale() { + return (isScaled ? scale : 1.0); + } + /** + * Scales the image to the requested size + * + * @param scale - The new scale of the image. + */ + public void setScale(final double scale) { + if (!scaleInThread || threadFinished) + { + if (scale == 1.0) { + isScaled = false; + } + else if (this.scale != scale) { + if (scaleInThread) { + finishedScaling = false; + threadFinished = false; + final ScalableImage scalableImage = this; + new Thread() { + public void run() { + scalableImage.isScaled = true; + scalableImage.scale = scale; + Image image = getImage(); + + // Get the new image size + Vector newSize = new Vector(image.getWidth(null), image.getHeight(null)); + if (scalableImage.maxScale == 0.0) + newSize.scale(scale).add(1, 1); + else + newSize.scale(scalableImage.maxScale).add(1, 1); + + + // Create the scaled image if needed + if (scalableImage.scaledImage == null || scalableImage.maxScale == 0.0) { + if (scalableImage.scaledImage != null) + scalableImage.scaledImage.flush(); + scalableImage.scaledImage = new BufferedImage((int)newSize.x, (int)newSize.y, scalableImage.colorType); + } + + Graphics2D g = (Graphics2D)scalableImage.scaledImage.getGraphics(); + + // Clear the scaled image + if (scalableImage.colorType == BufferedImage.TYPE_INT_ARGB) + g.setBackground(new Color(0, 0, 0, 0)); + else + g.setBackground(new Color(0, 0, 0)); + + Draw.clear(g, new Vector(), new Vector(image.getWidth(null), image.getHeight(null))); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, scalableImage.interpolation); + + g.scale(scale, scale); + g.drawImage(image, 0, 0, null); + g.dispose(); + + scalableImage.threadFinished = true; + scalableImage.finishedScaling = true; + if (scalableImage.shouldUnload) { + if (scalableImage.scaledImage != null) + scalableImage.scaledImage.flush(); + scalableImage.scaledImage = null; + scalableImage.scale = 1.0; + scalableImage.isScaled = false; + } + } + }.start(); + } + else { + isScaled = true; + this.scale = scale; + Image image = getImage(); + + // Get the new image size + Vector newSize = new Vector(image.getWidth(null), image.getHeight(null)); + if (maxScale == 0.0) + newSize.scale(scale).add(1, 1); + else + newSize.scale(maxScale).add(1, 1); + + + // Create the scaled image if needed + if (scaledImage == null || maxScale == 0.0) { + if (scaledImage != null) + scaledImage.flush(); + scaledImage = new BufferedImage((int)newSize.x, (int)newSize.y, colorType); + } + + Graphics2D g = (Graphics2D)scaledImage.getGraphics(); + + // Clear the scaled image + if (colorType == BufferedImage.TYPE_INT_ARGB) + g.setBackground(new Color(0, 0, 0, 0)); + else + g.setBackground(new Color(0, 0, 0)); + + Draw.clear(g, new Vector(), new Vector(image.getWidth(null), image.getHeight(null))); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolation); + + g.scale(scale, scale); + g.drawImage(image, 0, 0, null); + g.dispose(); + } + } + else { + isScaled = true; + } + } + } + +} + diff --git a/MetroidMapGuardian/src/graphics/StatusBar.java b/MetroidMapGuardian/src/graphics/StatusBar.java new file mode 100644 index 0000000..efb98ce --- /dev/null +++ b/MetroidMapGuardian/src/graphics/StatusBar.java @@ -0,0 +1,132 @@ +package graphics; + +import game.GameInstance; +import game.PowerUp; +import game.Trilogy; +import geometry.Rectangle; +import geometry.Vector; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.Image; + +import main.Main; +import main.Mouse; +import room.Room; + +/** + * + * @author Robert Jordan + * + */ +public class StatusBar extends Gui { + + // ==================== Public Members ==================== + + + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a gui at (0, 0). + * + * @return Returns the default gui. + */ + public StatusBar() { + super(); + } + /** + * Initializes the entity by setting the game instance it is linked to. + * + * @param room - The room that contains the entity. + * @param instance - The game instance that contains the room. + */ + public void initialize(Room room, GameInstance instance, Trilogy trilogy) { + super.initialize(room, instance, trilogy); + } + + // ======================== Updating ======================== + + /** + * Called every step for the entity to perform actions and update. + */ + public void update() { + + Vector size = new Vector(Main.frame.getContentPane().getWidth() + 64, 64 + 64); + position = new Vector(0, Main.frame.getContentPane().getHeight() - 40); + + Rectangle rect = new Rectangle(position, size); + + if (rect.contains(Mouse.getVector())) { + room.isMouseOverGUI = true; + } + } + /** + * Called every step for the entity to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + Vector size = new Vector(Main.frame.getContentPane().getWidth() + 64, 64 + 64); + position = new Vector(0, Main.frame.getContentPane().getHeight() - 40); + + g.setPaint(new GradientPaint((float)position.x, (float)position.y, new Color(46, 102, 133, 210), + (float)position.x, (float)(position.y + 40), new Color(16, 36, 47, 210))); + + g.fillRect((int)position.x, (int)position.y, (int)size.x, (int)size.y); + Draw.fillRect(g, position, size); + g.setColor(new Color(76, 147, 179, 210)); + Draw.drawLine(g, position, position.plus(size.x, 0)); + + double offset = 16; + + Font font = new Font("Crystal clear", Font.PLAIN, 18); + g.setFont(font); + g.setColor(new Color(33, 189, 222)); + + for (int i = 0; i < PowerUp.NUM_TYPES; i++) { + + if (PowerUp.isPowerUpInGame(i, trilogy.game)) { + + int numCollected = 0; + int numTotal = trilogy.powerUps.get(i).size(); + + for (PowerUp p : trilogy.powerUps.get(i)) { + if (p.collected) + numCollected++; + } + + Image image = PowerUp.getPowerUpIcon(i); + if (image != null) { + Draw.drawImage(g, image, position.plus(offset, -4)); + offset += image.getWidth(null); + offset += 6; + } + + Draw.drawString(g, numCollected + "/" + numTotal, position.plus(offset, 9), Draw.ALIGN_TOP); + + offset += Draw.getStringSize(numCollected + "/" + numTotal, font).x; + //offset += Draw.getStringSize("000/000", font).x; + + offset += 12; + } + } + + font = new Font("Crystal clear", Font.PLAIN, 18); + font = Palette.fontEurostar.deriveFont(Font.PLAIN, 20); + g.setFont(font); + + Draw.drawString(g, "Completion:", + position.plus(Main.frame.getContentPane().getWidth() - 72, 8), + Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + + Draw.drawString(g, trilogy.getCompletionPercentage() + "%", + //Draw.drawString(g, "100%", + position.plus(Main.frame.getContentPane().getWidth() - 16, 8), + Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + } + +} diff --git a/MetroidMapGuardian/src/graphics/TextBox.java b/MetroidMapGuardian/src/graphics/TextBox.java new file mode 100644 index 0000000..093967e --- /dev/null +++ b/MetroidMapGuardian/src/graphics/TextBox.java @@ -0,0 +1,159 @@ +package graphics; + +import geometry.Rectangle; +import geometry.Vector; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; + +import main.Keyboard; +import main.Mouse; + +/** + * + * @author Robert Jordan + * + */ +public class TextBox extends Gui { + + // ==================== Public Members ==================== + + public boolean typing; + + public String text; + + public Vector size; + + public Font font; + + public int maxLength; + + public long cursorTimer; + public boolean cursorShow; + + public boolean editable; + + public boolean justStartedTyping = false; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an entity at (0, 0). + * + * @return Returns the default entity. + */ + public TextBox() { + super(); + typing = false; + text = ""; + size = new Vector(); + maxLength = -1; + font = null; + cursorTimer = System.currentTimeMillis(); + cursorShow = true; + editable = true; + } + /** + * Constructs an entity with the specified details. + * + * @param id - The key identifier of the entity. + * @param depth - The depth of the entity. + * @param position - The position of the entity. + * @param velocity - The velocity of the entity. + * @return Returns an entity with the specified details. + */ + public TextBox(String id, String text, Vector position, Vector size, Font font, boolean editable, int maxLength) { + super(id, -5, position); + + this.text = text; + this.size = new Vector(size); + this.font = font; + this.editable = editable; + this.typing = false; + this.maxLength = maxLength; + this.cursorTimer = System.currentTimeMillis(); + this.cursorShow = true; + } + + // ======================== Updating ======================== + + /** + * Called every step for the gui to perform actions and update. + */ + public void update() { + + if (!editable) { + typing = false; + } + + + if (System.currentTimeMillis() - cursorTimer > 600) { + cursorTimer = System.currentTimeMillis(); + cursorShow = !cursorShow; + } + + if (editable) { + Rectangle rect = new Rectangle(position, size); + if (rect.contains(Mouse.getVector())) { + if (Mouse.left.pressed() && !typing) { + typing = true; + cursorTimer = System.currentTimeMillis(); + cursorShow = true; + } + } + else { + if (Mouse.left.pressed() && typing && !justStartedTyping) { + typing = false; + } + } + if (typing) { + if (Keyboard.keyWasTyped()) { + char typedChar = Keyboard.getTypedChar(); + if (Keyboard.enter.pressed()) { + typing = false; + } + else if (typedChar == (char)8) { + if (!text.isEmpty()) { + cursorTimer = System.currentTimeMillis(); + cursorShow = true; + text = text.substring(0, text.length() - 1); + } + } + else if (text.length() < maxLength) { + text += typedChar; + cursorTimer = System.currentTimeMillis(); + cursorShow = true; + } + } + } + } + + justStartedTyping = false; + } + /** + * Called every step for the gui to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + g.setColor(new Color(16, 36, 47, 170)); + Draw.fillRect(g, position, size); + g.setColor(new Color(46, 102, 133, 210)); + Draw.drawRect(g, position, size); + + java.awt.Rectangle oldClip = g.getClipBounds(); + + g.setClip((int)position.x, (int)position.y, (int)size.x, (int)size.y); + + g.setColor(new Color(33, 189, 222)); + g.setFont(font); + Draw.drawString(g, text + (cursorShow && typing ? "_" : ""), position.plus(12, size.y / 2), Draw.ALIGN_MIDDLE); + + g.setClip(oldClip); + + + } + +} diff --git a/MetroidMapGuardian/src/main/Game.java b/MetroidMapGuardian/src/main/Game.java new file mode 100644 index 0000000..6204e63 --- /dev/null +++ b/MetroidMapGuardian/src/main/Game.java @@ -0,0 +1,126 @@ +package main; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.event.KeyEvent; +import java.text.DecimalFormat; + +import javax.swing.JComponent; + +import entity.EntityLoader; + +import game.GameInstance; +import graphics.Draw; + +/** + * The static class that runs the base of the game. + * + * @author David Jordan + */ +public class Game extends JComponent { + + private static final long serialVersionUID = 1L; + public static Point viewSize = new Point(900, 700); + public static GameInstance instance; + public static boolean debugMode = false; + + + /** Setup the canvas and install listeners. **/ + public Game() { + this.setFocusable(true); + EntityLoader.registerEntities(); + + // Install Mouse, Load images, and initialize the game: + Mouse mouse = new Mouse(); + addMouseListener(mouse); + addMouseWheelListener(mouse); + + initializeGame(); + } + + /** Initialize any game objects. **/ + public void initializeGame() { + // INITIALIZE OBJECTS: + ResourceLoader.loadResources(); + instance = new GameInstance(); + instance.initialize(); + + } + + + /** Update the game objects. **/ + public void update() { + // UPDATE EVENTS HERE: + + instance.update(); + + + if (Keyboard.getKey(KeyEvent.VK_F3).pressed()) + debugMode = !debugMode; + if (Keyboard.getKey(KeyEvent.VK_F11).pressed()) + Main.setFullScreenMode(!Main.getFullScreenMode()); + + repaint(); + } + + /** Draw on the canvas. **/ + public void render(Graphics2D g) { + + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + // DRAW EVENTS HERE: + instance.draw(g); + + // Draw debig information: + if (debugMode) { + g.setColor(Color.WHITE); + g.setFont(new Font("Eurostar", Font.PLAIN, 16)); + DecimalFormat df = new DecimalFormat("#,##0.0##"); + DecimalFormat lf = new DecimalFormat("#,##0"); + + double fps = Main.fps; + long maxMemory = Runtime.getRuntime().maxMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + long freeMemory = Runtime.getRuntime().freeMemory(); + double usedMemory = (double)(Runtime.getRuntime().totalMemory() - + Runtime.getRuntime().freeMemory()) / (double)Runtime.getRuntime().maxMemory(); + + double x = 112; + double y = 8; + double spacing = 20; + + Draw.drawString(g, "FPS: ", x, y, Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + Draw.drawString(g, df.format(fps), x, y, Draw.ALIGN_TOP); + y += spacing; + Draw.drawString(g, "Max Memory: ", x, y, Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + Draw.drawString(g, lf.format(maxMemory), x, y, Draw.ALIGN_TOP); + y += spacing; + Draw.drawString(g, "Total Memory: ", x, y, Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + Draw.drawString(g, lf.format(totalMemory), x, y, Draw.ALIGN_TOP); + y += spacing; + Draw.drawString(g, "Free Memory: ", x, y, Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + Draw.drawString(g, lf.format(freeMemory), x, y, Draw.ALIGN_TOP); + //Draw.drawString(g, df.format(freeMemory), x, y, Draw.ALIGN_TOP); + y += spacing; + Draw.drawString(g, "Memory Used: ", x, y, Draw.ALIGN_RIGHT | Draw.ALIGN_TOP); + Draw.drawString(g, df.format(usedMemory), x, y, Draw.ALIGN_TOP); + } + } + + @Override + /** Handle rendering and draw the raw canvas image to the window. **/ + protected void paintComponent(Graphics g) { + + super.paintComponent(g); + + Graphics2D g2 = (Graphics2D)g; + g2.setBackground(Color.BLACK); + g2.clearRect(g.getClipBounds().x, g.getClipBounds().y, + g.getClipBounds().width, g.getClipBounds().height); + render(g2); + } +} diff --git a/MetroidMapGuardian/src/main/ImageLoader.java b/MetroidMapGuardian/src/main/ImageLoader.java new file mode 100644 index 0000000..ad5488d --- /dev/null +++ b/MetroidMapGuardian/src/main/ImageLoader.java @@ -0,0 +1,301 @@ +package main; + +import java.awt.Image; +import java.util.ArrayList; +import java.util.HashMap; + +/** + * A static class that handles loading and storing images from the 'images' folder. + * + * @author Robert Jordan + * @author David Jordan + */ +public class ImageLoader { + + // ================== Private Variables =================== + + /** The number of images loaded. This is used for console output. */ + private static int imagesLoaded = 0; + /** The map containing all the loaded images. */ + private static HashMap> imageMap = new HashMap>(); + + // =================== Program Loading ==================== + + /** + * Preload any images that need to be stored before the program is initialized. + */ + static void preloadImages() { + // PRELOAD ALL IMAGES HERE: + // example: loadImage("image1", "imagetest1.png"); + + // Output console information: + imagesLoaded = 0; + System.out.println("Loading Images:"); + + // Load the application icons: + loadImage("icon16", "icon16.png", true, true); + loadImage("icon24", "icon24.png", true, true); + loadImage("icon32", "icon32.png", true, true); + loadImage("icon48", "icon48.png", true, true); + loadImage("icon64", "icon64.png", true, true); + loadImage("icon96", "icon96.png", true, true); + loadImage("icon128", "icon128.png", true, true); + + loadImage("s_emblem64", "s_emblem64.png", true, true); + loadImage("s_emblem128", "s_emblem128.png", true, true); + + // Load the splash screen: + //loadImage("splash", "splash.jpg", true, true); + //loadImage("header_texture", "header_texture.png", true, true); + + // Output console information: + System.out.println(""); + System.out.println("Loaded " + String.valueOf(imagesLoaded) + " images"); + System.out.println("--------------------------------"); + } + /** + * Load the rest of the images for the program. + */ + static void loadImages() { + // PRELOAD ALL IMAGES HERE: + // example: loadImage("image1", "imagetest1.png"); + + // Output console information: + imagesLoaded = 0; + System.out.println("Loading Images:"); + + // Checked Image Icons: + loadImage("checked", "checked.png", true, true); + loadImage("unchecked", "unchecked.png", true, true); + + // Power Up Icons: + loadImage("suit_expansion", "suit_expansion.png", true, true); + loadImage("missile_expansion", "missile_expansion.png", true, true); + loadImage("energy_tank", "energy_tank.png", true, true); + loadImage("power_bomb", "power_bomb.png", true, true); + loadImage("artifact", "artifact.png", true, true); + loadImage("beam_ammo_expansion", "beam_ammo_expansion.png", true, true); + loadImage("dark_temple_key", "dark_temple_key.png", true, true); + loadImage("sky_temple_key", "sky_temple_key.png", true, true); + loadImage("ship_missile_expansion", "ship_missile_expansion.png", true, true); + loadImage("energy_cell", "energy_cell.png", true, true); + loadImage("red_phazoid", "red_phazoid.png", true, true); + loadImage("boss", "boss.png", true, true); + + + // Load all basic Metroid Prime images: + loadAllImages("metroid_prime_1/", "metroid_prime_1/", "maps/", true, true); + loadAllImages("metroid_prime_2/", "metroid_prime_2/", "maps/", true, true); + loadAllImages("metroid_prime_3/", "metroid_prime_3/", "maps/", true, true); + + // Load all Metroid Prime maps into a map group: + loadAllImages("metroid_prime_1/maps/", "metroid_prime_1", "metroid_prime_1/maps/", "", true, false); + loadAllImages("metroid_prime_2/maps/", "metroid_prime_2", "metroid_prime_2/maps/", "", true, false); + loadAllImages("metroid_prime_3/maps/", "metroid_prime_3", "metroid_prime_3/maps/", "", true, false); + + // Output console information: + System.out.println(""); + System.out.println("Loaded " + String.valueOf(imagesLoaded) + " images"); + System.out.println("--------------------------------"); + } + + // =================== Loading Methods ==================== + + /** + * Finds the image with the given name. + * + * @param name - The name of the image to look for. + * @return Returns the image resource or null if the image is not loaded. + */ + public static Image getImage(String name) { + return getImage(name, ""); + } + /** + * Finds the image with the given name. + * + * @param name - The name of the image to look for. + * @param group - The resource group of the image. + * @return Returns the image resource or null if the image is not loaded. + */ + public static Image getImage(String name, String group) { + if (imageMap.containsKey(group)) { + if (imageMap.get(group).containsKey(name)) { + return imageMap.get(group).get(name).getResource(); + } + } + return null; + } + /** + * Tests whether the image with the specified name has been loaded. + * + * @param name - The name of the image to look for. + * @return Returns true if the image has been loaded. + */ + public static boolean isImageLoaded(String name) { + return isImageLoaded(name, ""); + } + /** + * Tests whether the image with the specified name has been loaded. + * + * @param name - The name of the image to look for. + * @param group - The resource group of the image. + * @return Returns true if the image has been loaded. + */ + public static boolean isImageLoaded(String name, String group) { + if (imageMap.containsKey(group)) { + if (imageMap.get(group).containsKey(name)) { + return imageMap.get(group).get(name).isLoaded(); + } + } + return false; + } + /** + * Loads the image with the specified name. + * + * @param name - The name of the image to load. + */ + public static void loadImage(String name) { + loadImage(name, ""); + } + /** + * Loads the image with the specified name. + * + * @param name - The name of the image to load. + * @param group - The resource group of the image. + */ + public static void loadImage(String name, String group) { + if (imageMap.containsKey(group)) { + if (imageMap.get(group).containsKey(name)) { + imageMap.get(group).get(name).load(); + } + } + } + /** + * Loads all the image in specified group. + * + * @param group - The resource group to load. + */ + public static void loadGroup(String group) { + if (imageMap.containsKey(group)) { + for (ImageResource resource : imageMap.get(group).values()) { + resource.load(); + } + } + } + /** + * Unloads the image with the specified name. + * + * @param name - The name of the image to unload. + */ + public static void unloadImage(String name) { + unloadImage(name, ""); + } + /** + * Unloads the image with the specified name. + * + * @param name - The name of the image to unload. + * @param group - The resource group of the image. + */ + public static void unloadImage(String name, String group) { + if (imageMap.containsKey(group)) { + if (imageMap.get(group).containsKey(name)) { + imageMap.get(group).get(name).unload(); + } + } + } + /** + * Unloads all the image in specified group. + * + * @param group - The resource group to unload. + */ + public static void unloadGroup(String group) { + if (imageMap.containsKey(group)) { + for (ImageResource resource : imageMap.get(group).values()) { + resource.unload(); + } + } + } + + // =================== Private Methods ==================== + + /** + * Load an image and stores it under a given name in the hash map. + * + * @param name - The name to store the image with. + * @param path - The path to the image. + * @param isResource - True if the image should be loaded as a resource. + * @param load - True if the image should be loaded now. + */ + private static void loadImage(String name, String path, boolean isResource, boolean load) { + loadImage(name, "", path, isResource, load); + } + /** + * Load an image and stores it under a given name in the hash map. + * + * @param name - The name to store the image with. + * @param group - The group to store the image with. + * @param path - The path to the image. + * @param isResource - True if the image should be loaded as a resource. + * @param load - True if the image should be loaded now. + */ + private static void loadImage(String name, String group, String path, boolean isResource, boolean load) { + ImageResource resource = new ImageResource(path, isResource); + if (load) + resource.load(); + + // Add the image to the hash map: + // Create a new hash map group if one doesn't exist + if (!imageMap.containsKey(group)) { + imageMap.put(group, new HashMap()); + } + imageMap.get(group).put(name, resource); + + // Output the loaded image path to the console + System.out.println("- " + path); + imagesLoaded++; + } + /** + * Load all the images with a given path and stores them under a given + * name in the hash map. + * + * @param name - The name to store the images with. + * @param path - The path to the images. + * @param excludePath - The continued path to exclude from the search. + * @param isResource - True if the image should be loaded as a resource. + * @param load - True if the image should be loaded now. + */ + private static void loadAllImages(String name, String path, String excludePath, boolean isResource, boolean load) { + loadAllImages(name, "", path, excludePath, isResource, load); + } + /** + * Load all the images with a given path and stores them under a given + * name in the hash map. + * + * @param name - The name to store the images with. + * @param group - The group to store the images with. + * @param path - The path to the images. + * @param excludePath - The continued path to exclude from the search. + * @param isResource - True if the image should be loaded as a resource. + * @param load - True if the image should be loaded now. + */ + private static void loadAllImages(String name, String group, String path, String excludePath, boolean isResource, boolean load) { + + String imagePath = "resources/images/" + path; + ArrayList images = new ArrayList(); + + // Load all png's and jpg's: + images.addAll(ResourceLoader.getResources("resources/images/" + path, excludePath, ".jpg", true)); + images.addAll(ResourceLoader.getResources("resources/images/" + path, excludePath, ".png", true)); + + // For each image resource found, load the image: + for (String fullPath : images) { + // Get the index of the start of the path + int index = fullPath.lastIndexOf("resources/images/" + path); + + String finalPath = fullPath.substring(index + imagePath.length(), fullPath.length()); + String finalName = name + finalPath.substring(0, finalPath.length() - 4); + + loadImage(finalName, group, path + finalPath, isResource, load); + } + } +} diff --git a/MetroidMapGuardian/src/main/ImageResource.java b/MetroidMapGuardian/src/main/ImageResource.java new file mode 100644 index 0000000..a0ec6e6 --- /dev/null +++ b/MetroidMapGuardian/src/main/ImageResource.java @@ -0,0 +1,96 @@ +package main; + +import java.awt.Image; +import java.net.MalformedURLException; +import java.net.URL; + +import javax.swing.ImageIcon; + +/** + * A basic image resource that can be stored and loaded or unloaded in + * order to manage memory. Each resource needs to have a name, path, and + * boolean of whether it's loaded as a resource, or file. + * @author Robert Jordan + * @see + * {@linkplain Resource} + */ +public class ImageResource extends Resource { + + // ======================= Members ======================== + + /** The image data of the resource. */ + protected Image image; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an unloaded image. + * + * @return Returns the default image. + */ + public ImageResource() { + super(); + this.image = null; + } + /** + * Constructs an image with the given name, path, and resource state. + * + * @param path - The path to the image. + * @param isResource - True if the image should be loaded as a + * resource instead of as a file. + * @return Returns an unloaded image with the given file details. + */ + public ImageResource(String path, boolean isResource) { + super(path, isResource); + this.image = null; + } + + // ======================= Methods ======================== + + /** + * Tests whether the image has been loaded. + * + * @return Returns true if the image is currently loaded. + */ + public boolean isLoaded() { + return image != null; + } + /** + * Loads the image from file. + */ + public void load() { + try { + // Load the image only if it is not loaded + if (image == null) { + if (isResource) { + // Load the image as a resource + image = new ImageIcon(ImageResource.class.getResource("/resources/images/" + resourcePath)).getImage(); + } + else { + // Load the image as a file + image = new ImageIcon(new URL(resourcePath)).getImage(); + } + } + } + catch (MalformedURLException e) { + e.printStackTrace(); + } + } + /** + * Unloads the image and removes all attached data to save memory. + */ + public void unload() { + if (image != null) + image.flush(); + image = null; + } + /** + * Gets the image with the given name. + * + * @return Returns the image or null if it's not loaded. + */ + public Image getResource() { + return image; + } + +} diff --git a/MetroidMapGuardian/src/main/Keyboard.java b/MetroidMapGuardian/src/main/Keyboard.java new file mode 100644 index 0000000..0cdd775 --- /dev/null +++ b/MetroidMapGuardian/src/main/Keyboard.java @@ -0,0 +1,164 @@ +package main; + +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + + +/** + * A static key listener class that handles + * key states with custom key bindings. + * + * @author David + */ +public class Keyboard implements KeyListener { + + // CUSTOM KEY BINDINGS: + public static Key up = new Key(KeyEvent.VK_W, KeyEvent.VK_UP); + public static Key down = new Key(KeyEvent.VK_S, KeyEvent.VK_DOWN); + public static Key left = new Key(KeyEvent.VK_A, KeyEvent.VK_LEFT); + public static Key right = new Key(KeyEvent.VK_D, KeyEvent.VK_RIGHT); + + public static Key reload = new Key(KeyEvent.VK_R); + + public static Key space = new Key(KeyEvent.VK_SPACE); + public static Key enter = new Key(KeyEvent.VK_ENTER); + public static Key control = new Key(KeyEvent.VK_CONTROL); + public static Key shift = new Key(KeyEvent.VK_SHIFT); + public static Key alt = new Key(KeyEvent.VK_ALT); + public static Key tab = new Key(KeyEvent.VK_TAB); + public static Key pageUp = new Key(KeyEvent.VK_PAGE_UP); + public static Key pageDown = new Key(KeyEvent.VK_PAGE_DOWN); + public static Key insert = new Key(KeyEvent.VK_INSERT); + + public static Key escape = new Key(KeyEvent.VK_ESCAPE); + public static Key f12 = new Key(KeyEvent.VK_F12); + + + /** Sub-class that represents a key that can have multiple bindings **/ + public static class Key { + private int[] keyCodes; + + /** Initialize a key with any amount of key code bindings. **/ + public Key(int... keyCodes) { + this.keyCodes = new int[keyCodes.length]; + for (int i = 0; i < keyCodes.length; i++) + this.keyCodes[i] = keyCodes[i]; + } + + /** Check if the key is down. **/ + public boolean down() { + for (int k : keyCodes) { + if (Keyboard.keyDown[k]) + return true; + } + return false; + } + + /** Check if the key was pressed. **/ + public boolean pressed() { + boolean down = false; + boolean downPrev = false; + for (int k : keyCodes) { + down = down || Keyboard.keyDown[k]; + downPrev = downPrev || Keyboard.keyDownPrev[k]; + } + return (down && !downPrev); + } + + /** Check if the key was released. **/ + public boolean released() { + boolean down = false; + boolean downPrev = false; + for (int k : keyCodes) { + down = down || Keyboard.keyDown[k]; + downPrev = downPrev || Keyboard.keyDownPrev[k]; + } + return (!down && downPrev); + } + + /** Check if the key was typed. **/ + public boolean typed() { + for (int k : keyCodes) { + if (keyTyped[k]) + return true; + } + return false; + } + } + + + /** Initialize all key code states. **/ + public Keyboard() { + for (int i = 0; i < KEYCODE_SIZE; i++) { + rawKeyDown[i] = false; + keyDown[i] = false; + keyDownPrev[i] = false; + } + } + + @Override + public void keyPressed(KeyEvent e) { + if (!rawKeyDown[e.getKeyCode()]) { + rawKeyDown[e.getKeyCode()] = true; + //System.out.println(KeyEvent.getKeyText(e.getKeyCode()) + " pressed"); + } + } + + @Override + public void keyReleased(KeyEvent e) { + if (rawKeyDown[e.getKeyCode()]) { + rawKeyDown[e.getKeyCode()] = false; + //System.out.println(KeyEvent.getKeyText(e.getKeyCode()) + " released"); + } + } + + @Override + public void keyTyped(KeyEvent e) { + rawKeyTyped[e.getKeyCode()] = true; + rawCharTyped = e.getKeyChar(); + } + + /** Update all key states. **/ + public static void update() { + charTyped = rawCharTyped; + rawCharTyped = '\0'; + for (int i = 0; i < KEYCODE_SIZE; i++) { + //java.awt.Toolkit.getDefaultToolkit().getLockingKeyState(arg0); + + keyDownPrev[i] = keyDown[i]; + keyDown[i] = rawKeyDown[i]; + keyTypedPrev[i] = keyTyped[i]; + keyTyped[i] = rawKeyTyped[i]; + rawKeyTyped[i] = false; + } + } + + public static Key getKey(int... keyCodes) { + return new Key(keyCodes); + } + + public static void reset() { + for (int i = 0; i < KEYCODE_SIZE; i++) { + rawKeyDown[i] = false; + rawKeyTyped[i] = false; + } + } + + public static boolean keyWasTyped() { + return charTyped != '\0'; + } + + public static char getTypedChar() { + return charTyped; + } + + private static final int KEYCODE_SIZE = 0x108; + private static boolean[] rawKeyDown = new boolean[KEYCODE_SIZE]; + private static boolean[] keyDown = new boolean[KEYCODE_SIZE]; + private static boolean[] keyDownPrev = new boolean[KEYCODE_SIZE]; + private static boolean[] rawKeyTyped = new boolean[KEYCODE_SIZE]; + private static boolean[] keyTyped = new boolean[KEYCODE_SIZE]; + private static boolean[] keyTypedPrev = new boolean[KEYCODE_SIZE]; + private static char rawCharTyped = '\0'; + private static char charTyped = '\0'; +} diff --git a/MetroidMapGuardian/src/main/Main.java b/MetroidMapGuardian/src/main/Main.java new file mode 100644 index 0000000..704b9f4 --- /dev/null +++ b/MetroidMapGuardian/src/main/Main.java @@ -0,0 +1,344 @@ +package main; + +import game.Profile; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.SplashScreen; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.util.ArrayList; + +import javax.swing.JFrame; + +/** + * This class sets up a windows and starts a thread to update and render + * the Game class. + * + * @author Robert Jordan + * @author David Jordan + * + * @see + * {@linkplain Game} + */ +public class Main implements Runnable { + + // =================== Private Variables ================== + + /** The size of the frames array. */ + private static final int MAX_TIMES = 8; + /** The array of times for each frame used to get the average. */ + private static long[] frameTimes = new long[MAX_TIMES]; + /** The current frame in the array of frames. */ + private static int frameCurrent = 0; + + // ==================== Public Constants ================== + + /** + * The name of the game. Classes can reference this when needed. This is + * useful in case the name has to be changed. + */ + public static final String GAME_NAME = "Metroid Map Guardian"; + /** + * The default desired update rate of the game in frames-per-second. + * This is used to maintain conversion rates for system time to step + * time. + * + * @see + * {@linkplain time.Time} + */ + public static final int FPS = 60; + /** + * The conversion rate for how long a step lasts. This value is represented + * in milliseconds per frame. See FPS for more details. + * + * @see + * {@linkplain #FPS}, + * {@linkplain time.Time} + */ + public static final int STEP_TIME = 1000 / FPS; + + // ==================== Public Variables ================== + + /** The variable that states whether the game loop should terminate. */ + public static boolean running; + /** The frame component that the game is drawn to. */ + public static JFrame frame; + /** The game class running the game. */ + public static Game game; + + /** The desired update rate of the game for frames-per-second. */ + public static int fpsDesired; + /** The current update rate of the game in frames-per-second. */ + public static double fps; + + private static boolean fullScreenEnabled = false; + + private static GraphicsDevice graphicsDevice; + + // ====================== Entry Point ===================== + + /** + * The entry point for the program. Everything is run from this function. + * + * @param args - The arguments to execute the program with. + */ + public static void main(String [] args) { + System.setProperty("sun.java2d.d3d", "false"); + new Main(); + } + /** + * Constructs the main class that will run the program. After the class + * has been created a new thread will begin executing it's run function. + */ + public Main() { + //GraphicsEnvironment.getLocalGraphicsEnvironment(). + + ResourceLoader.preloadResources(); + + final SplashScreen splash = SplashScreen.getSplashScreen(); + /*if (splash != null) { + Graphics2D g = splash.createGraphics(); + java.awt.Rectangle bounds = splash.getBounds(); + Draw.drawImage(g, ImageLoader.getImage("splash"), new Vector(bounds.width, bounds.height).scale(0.5)); + g.drawImage(ImageLoader.getImage("splash"), 0, 0, null); + g.drawImage(ImageLoader.getImage("splash"), bounds.x, bounds.y, null); + Draw.drawImage(g, ImageLoader.getImage("splash"), new Vector(bounds.x, bounds.y)); + /*int fontSize = 55; + int x = 260; + int y = 60; + int offset = (int)(fontSize * 0.24); + int spacing = 80; + int color1 = 255; + int color2 = 90; + Color gradient1 = new Color(color1, color1, color1); + Color gradient2 = new Color(color2, color2, color2); + + + BufferedImage texture = new BufferedImage(ImageLoader.getImage("header_texture").getWidth(null), + ImageLoader.getImage("header_texture").getHeight(null), + BufferedImage.TYPE_INT_ARGB); + Draw.drawImage((Graphics2D)texture.getGraphics(), ImageLoader.getImage("header_texture"), new Vector(0, 0)); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g.setFont(new Font("Eurostar Black Extended", Font.PLAIN, fontSize)); + int fontHeight = (int)Draw.getStringSize("Metroid", g.getFont()).y - offset * 2; + //g.setStroke(new BasicStroke(2.0f)); + //g.setPaint(new TexturePaint(texture, new java.awt.geom.Rectangle2D.Double(x, y, x, y + (fontSize + spacing) * 2))); + g.setPaint(new GradientPaint(x, y + offset, gradient1, x, y + offset + fontHeight, gradient2)); + Draw.drawString(g, "Metroid", new Vector(x, y), Draw.ALIGN_TOP); + //Draw.drawLine(g, x, y + offset, x, y + offset + fontHeight); + y += spacing; + g.setPaint(new GradientPaint(x, y + offset, gradient1, x, y + offset + fontHeight, gradient2)); + Draw.drawString(g, "Map", new Vector(x, y), Draw.ALIGN_TOP); + //Draw.drawLine(g, x, y + offset, x, y + offset + fontHeight); + y += spacing; + g.setPaint(new GradientPaint(x, y + offset, gradient1, x, y + offset + fontHeight, gradient2)); + Draw.drawString(g, "Guardian", new Vector(x, y), Draw.ALIGN_TOP); + //Draw.drawLine(g, x, y + offset, x, y + offset + fontHeight); + //splash.update(); + + try { + BufferedImage image = new BufferedImage(ImageLoader.getImage("splash").getWidth(null), + ImageLoader.getImage("splash").getHeight(null), + BufferedImage.TYPE_INT_ARGB); + y = 60; + g = (Graphics2D)image.getGraphics(); + Draw.drawImage(g, ImageLoader.getImage("splash"), 0, 0); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g.setFont(new Font("Eurostar Black Extended", Font.PLAIN, fontSize)); + fontHeight = (int)Draw.getStringSize("Metroid", g.getFont()).y - offset * 2; + //g.setStroke(new BasicStroke(2.0f)); + //g.setPaint(new TexturePaint(texture, new java.awt.geom.Rectangle2D.Double(x, y, x, y + (fontSize + spacing) * 2))); + g.setPaint(new GradientPaint(x, y + offset, gradient1, x, y + offset + fontHeight, gradient2)); + Draw.drawString(g, "Metroid", new Vector(x, y), Draw.ALIGN_TOP); + //Draw.drawLine(g, x, y + offset, x, y + offset + fontHeight); + y += spacing; + g.setPaint(new GradientPaint(x, y + offset, gradient1, x, y + offset + fontHeight, gradient2)); + Draw.drawString(g, "Map", new Vector(x, y), Draw.ALIGN_TOP); + //Draw.drawLine(g, x, y + offset, x, y + offset + fontHeight); + y += spacing; + g.setPaint(new GradientPaint(x, y + offset, gradient1, x, y + offset + fontHeight, gradient2)); + Draw.drawString(g, "Guardian", new Vector(x, y), Draw.ALIGN_TOP); + //Draw.drawLine(g, x, y + offset, x, y + offset + fontHeight); + ImageIO.write(image, "png", new File("mySplash.png")); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + else { + System.out.println("Cannot load Splash Screen!"); + return; + }*/ + + frame = new JFrame(GAME_NAME); + frame.setLayout(new BorderLayout()); + game = new Game(); + + graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); + + fpsDesired = FPS; + fps = 0.0; + + // Add the game to the frame's content pane: + Container c = frame.getContentPane(); + c.setLayout(new BorderLayout()); + c.add(game); + frame.addKeyListener(new Keyboard()); + + frame.addWindowListener(new WindowListener() { + public void windowClosing(WindowEvent e) { + + if (Game.instance != null) { + if (!Game.instance.inMenu) { + new Profile(Game.instance).saveProfile(); + } + } + + } + + public void windowActivated(WindowEvent arg0) {} + + public void windowClosed(WindowEvent arg0) {} + + public void windowDeactivated(WindowEvent arg0) {} + + public void windowDeiconified(WindowEvent arg0) {} + + public void windowIconified(WindowEvent arg0) {} + + public void windowOpened(WindowEvent arg0) {} + }); + + // Set Icon + ArrayList icons = new ArrayList(); + icons.add(ImageLoader.getImage("icon16")); + icons.add(ImageLoader.getImage("icon24")); + icons.add(ImageLoader.getImage("icon32")); + icons.add(ImageLoader.getImage("icon48")); + icons.add(ImageLoader.getImage("icon64")); + icons.add(ImageLoader.getImage("icon96")); + icons.add(ImageLoader.getImage("icon128")); + frame.setIconImages(icons); + + // Configure the frame settings: + frame.setPreferredSize(new Dimension(Game.viewSize.x + 18, Game.viewSize.y + 40)); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.pack(); + frame.setResizable(true); + + if (splash != null) { + splash.close(); + } + + frame.setVisible(true); + + // Move the frame to the center of the screen: + Dimension screenSize = frame.getToolkit().getScreenSize(); + frame.setLocation((screenSize.width / 2) - (frame.getWidth() / 2), (screenSize.height / 2) - (frame.getHeight() / 2)); + + // Start the thread and request focus for the frame: + new Thread(this).start(); + frame.requestFocusInWindow(); + } + + // ======================= Execution ====================== + + /** + * Ends the main game loop by preventing the run loop to continue after + * the current step. + */ + public static void stop() { + running = false; + if (Game.instance != null) { + if (!Game.instance.inMenu) { + new Profile(Game.instance).saveProfile(); + } + } + } + /** + * The main loop for running the game. This will update and draw the game + * every step. The function will sleep until it is time for the next step. + * The sleep time is based off how long it took to run the step and the + * frames per second constant. + */ + public void run() { + long time = System.currentTimeMillis(); + running = true; + + while (running) { + // Update the mouse and keyboard inputs, then update and repaint the game: + frame.requestFocusInWindow(); + Keyboard.update(); + Mouse.update(); + game.update(); + game.repaint(); + + updateFPS(); + + // End the game if the user presses Escape: + //if (Keyboard.escape.pressed()) + // Main.stop(); + + // Wait until the next frame: + try { + time += 1000 / fpsDesired; + Thread.sleep(Math.max(0, time - System.currentTimeMillis())); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + } + + // End the game: + System.exit(0); + } + /** + * Changes the full screen mode. + * + * @param fullScreen - Whether to enable or disable fullScreen mode. + */ + public static void setFullScreenMode(boolean fullScreen) { + if (fullScreenEnabled && !fullScreen) { + frame.dispose(); + frame.setUndecorated(false); + frame.setVisible(true); + frame.setResizable(true); + graphicsDevice.setFullScreenWindow(null); + } + else if (!fullScreenEnabled && fullScreen) { + frame.dispose(); + frame.setUndecorated(true); + frame.setVisible(true); + frame.setResizable(false); + graphicsDevice.setFullScreenWindow(frame); + } + fullScreenEnabled = fullScreen; + } + public static boolean getFullScreenMode() { + return fullScreenEnabled; + } + /** + * Updates the frames-per-second variable to give an average, more readable + * value. + */ + private static void updateFPS() { + // Get current steps per second + frameTimes[frameCurrent] = System.currentTimeMillis(); + int frameLast = frameCurrent + 1; + if (frameLast >= MAX_TIMES) { + frameLast = 0; + } + // Steps per second = 1000 / (steps[current] - steps[current - maxSteps + 1]) * (maxSteps - 1); + fps = 1000.0 / (double)(frameTimes[frameCurrent] - frameTimes[frameLast]) * (double)(MAX_TIMES - 1); + + frameCurrent = frameLast; + } + +} + + diff --git a/MetroidMapGuardian/src/main/Mouse.java b/MetroidMapGuardian/src/main/Mouse.java new file mode 100644 index 0000000..a7b41fd --- /dev/null +++ b/MetroidMapGuardian/src/main/Mouse.java @@ -0,0 +1,206 @@ +package main; + +import geometry.Vector; + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; + + +/** + * A static mouse listener class that handles + * mouse buttons and wheel movement. + * + * @author David + */ +public class Mouse extends MouseAdapter implements MouseWheelListener { + public static Button left = new Button(MouseEvent.BUTTON1); + public static Button middle = new Button(MouseEvent.BUTTON2); + public static Button right = new Button(MouseEvent.BUTTON3); + private static Button[] buttons = {left, middle, right}; + private static Point position = new Point(); + private static Point positionLast = new Point(); + private static boolean mouseInWindow = false; + private static int rawWheelMovement = 0; + private static int wheelMovement = 0; + + + public static void reset() { + for (int i = 0; i < 3; i++) { + buttons[i].rawDown = false; + buttons[i].rawClicked = false; + } + } + + + /** Sub-class that represents a mouse button. **/ + public static class Button { + protected int buttonIndex; + protected boolean rawDown; + protected boolean down; + protected boolean downPrev; + protected boolean rawClicked; + protected boolean clicked; + + public Button(int buttonIndex) { + this.buttonIndex = buttonIndex; + this.rawDown = false; + this.down = false; + this.downPrev = false; + this.rawClicked = false; + this.clicked = false; + } + + /** Check if the mouse button is down. **/ + public boolean down() { + return down; + } + + /** Check if the mouse button was pressed. **/ + public boolean pressed() { + return (down && !downPrev); + } + + /** Check if the mouse button was released. **/ + public boolean released() { + return (!down && downPrev); + } + + /** Check if the mouse button was clicked (pressed & released without movement). **/ + public boolean clicked() { + return clicked; + } + } + + + /** Get the x component of the mouse position. **/ + public static int x() { + return position.x; + } + + /** Get the y component of the mouse position. **/ + public static int y() { + return position.y; + } + + /** Get the previous x component of the mouse position. **/ + public static int xPrevious() { + return positionLast.x; + } + + /** Get the previous y component of the mouse position. **/ + public static int yPrevious() { + return positionLast.y; + } + + /** Get the mouse position as a Point. **/ + public static Point position() { + return new Point(position); + } + + /** Get the mouse position as a Vector. **/ + public static Vector getVector() { + return new Vector(position.x, position.y); + } + + + /** Get the previous mouse position as a Vector. **/ + public static Vector getVectorPrevious() { + return new Vector(positionLast.x, positionLast.y); + } + + /** Get the previous mouse position as a Point. **/ + public static Point positionLast() { + return new Point(positionLast); + } + + /** Check if the mouse wheel is moved up. **/ + public static boolean wheelUp() { + return (wheelMovement < 0); + } + + /** Check if the mouse wheel is moved down. **/ + public static boolean wheelDown() { + return (wheelMovement > 0); + } + + /** Check if the mouse is inside the window. **/ + public static boolean inWindow() { + return mouseInWindow; + } + + /** Check if the mouse position is in a rectangular area. **/ + public static boolean inArea(int x1, int y1, int x2, int y2) { + return (x() >= x1 && y() >= y1 && x() < x2 && y() < y2); + } + + /** Check if the mouse position is in a rectangular area defnined by two points. **/ + public static boolean inArea(Point p1, Point p2) { + return (x() >= p1.x && y() >= p1.y && x() < p2.x && y() < p2.y); + } + + /** Check if the mouse position is in a rectangular area. **/ + public static boolean inArea(Rectangle r) { + return (x() >= r.x && y() >= r.y && x() < r.x + r.width && y() < r.y + r.height); + } + + @Override + public void mousePressed(MouseEvent e) { + for (Button b : buttons) { + if (b.buttonIndex == e.getButton()) { + b.rawDown = true; + break; + } + } + } + + @Override + public void mouseReleased(MouseEvent e) { + for (Button b : buttons) { + if (b.buttonIndex == e.getButton()) { + b.rawDown = false; + break; + } + } + } + + @Override + public void mouseClicked(MouseEvent e) { + for (Button b : buttons) { + if (b.buttonIndex == e.getButton()) { + b.rawClicked = true; + break; + } + } + } + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + rawWheelMovement = e.getWheelRotation(); + } + + /** Update button states, wheel movement, and mouse coordinates. **/ + public static void update() { + // Update the button states: + for (Button b : buttons) { + b.downPrev = b.down; + b.down = b.rawDown; + b.clicked = b.rawClicked; + } + + // Update the scroll wheel movement: + wheelMovement = rawWheelMovement; + rawWheelMovement = 0; + + // Update the mouse coordinates: + positionLast.setLocation(position); + Point msPosition = Main.game.getMousePosition(); + mouseInWindow = (msPosition != null); + if (mouseInWindow) { + position.setLocation(msPosition); + } + } +} diff --git a/MetroidMapGuardian/src/main/Resource.java b/MetroidMapGuardian/src/main/Resource.java new file mode 100644 index 0000000..75098b8 --- /dev/null +++ b/MetroidMapGuardian/src/main/Resource.java @@ -0,0 +1,68 @@ +package main; + +/** + * A basic resource that can be stored and loaded or unloaded in order to + * manage memory. Each resource needs to have a name, path, and boolean of + * whether it's loaded as a resource, or file. + * @author Robert Jordan + * @see + * {@linkplain ImageResource} + */ +public abstract class Resource { + + // ======================= Members ======================== + + /** The path of the resource. */ + protected String resourcePath; + /** True if the resource should be loaded as a resource. */ + protected boolean isResource; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an unloaded resource. + * + * @return Returns the default resource. + */ + protected Resource() { + this.resourcePath = ""; + this.isResource = true; + } + /** + * Constructs a resource with the given name, path, and resource state. + * + * @param name - The name of the resource. + * @param path - The path to the resource. + * @param isResource - True if the resource should be loaded as a + * resource instead of as a file. + * @return Returns an unloaded resource with the given file details. + */ + protected Resource(String path, boolean isResource) { + this.resourcePath = path; + this.isResource = isResource; + } + + // ======================= Methods ======================== + + /** + * Tests whether the resource has been loaded. + * + * @return Returns true if the resource is currently loaded. + */ + public abstract boolean isLoaded(); + /** + * Loads the resource from file. + */ + public abstract void load(); + /** + * Unloads the resource and removes all attached data to save memory. + */ + public abstract void unload(); + /** + * Gets the resource with the given name. + * + * @return Returns the resource object or null if it's not loaded. + */ + public abstract Object getResource(); + +} diff --git a/MetroidMapGuardian/src/main/ResourceLoader.java b/MetroidMapGuardian/src/main/ResourceLoader.java new file mode 100644 index 0000000..2017d15 --- /dev/null +++ b/MetroidMapGuardian/src/main/ResourceLoader.java @@ -0,0 +1,273 @@ +package main; + +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.GraphicsEnvironment; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; + +/** + * A static class to simplify loading resources and make the call to load + * all program resources at once. + * + * @author Robert Jordan + * @see + * {@linkplain ImageLoader}, + * {@linkplain Resource}, + * {@linkplain ImageResource} + */ +public class ResourceLoader { + + // =================== Program Loading ==================== + + /** + * Preload any resources that need to be stored before the program is initialized. + */ + static void preloadResources() { + System.out.println(""); + System.out.println("============= Preloading Resources ============="); + + preloadFonts(); + + ImageLoader.preloadImages(); + } + /** + * Load the rest of the resources for the program. + */ + static void loadResources() { + System.out.println(""); + System.out.println("============== Loading Resources ==============="); + + + ImageLoader.loadImages(); + + //SoundLoader.loadSounds(); + //RoomLoader.loadRooms(); + } + /** + * Preload all fonts in the fonts folder. + */ + static void preloadFonts() { + + System.out.println("Loading Fonts:"); + + // Get all font paths + ArrayList paths = new ArrayList(); + paths.addAll(getResources("resources/fonts/", "", ".ttf", true)); + + // Register all loaded fonts + for( int i = 0; i < paths.size(); i++ ) { + try { + InputStream stream = ClassLoader.getSystemResourceAsStream(paths.get(i)); + Font font = Font.createFont(Font.TRUETYPE_FONT, stream); + GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font); + System.out.println("- " + font.getFontName()); + } + catch (FontFormatException e) { + e.printStackTrace(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + System.out.println(""); + System.out.println("Loaded " + String.valueOf(paths.size()) + " fonts"); + System.out.println("--------------------------------"); + } + + // =================== Loading Methods ==================== + + /** + * Find the paths to all resources with a given path. + * + * @param path - The base path of the resource. + * @param excludePath - The continued path to exclude from the list. + * @param extension - The extension of the resource, this can be empty. + * @param isResource - True if the file is a resource. + * @return Returns a collection of strings with the paths of the matching + * resources. + */ + public static Collection getResources(String path, String excludePath, String extension, boolean isResource) { + + ArrayList paths = new ArrayList(); + + // Get the path of the jar file + String classPath = System.getProperty((isResource ? "java.class.path" : "user.dir"), "."); + + // Set directory separator due to changes in OS: + // Replace '/' with '\\' for Windows OS + paths.addAll(getResources(classPath.replace('/', '\\'), path.replace('/', '\\'), excludePath.replace('/', '\\'), extension)); + // Replace '\\' with '/' for Mac OS + paths.addAll(getResources(classPath.replace('\\', '/'), path.replace('\\', '/'), excludePath.replace('\\', '/'), extension)); + + // Replace all '\\'s with '/' in the paths for consistency + for (int i = 0; i < paths.size(); i++) { + paths.set(i, paths.get(i).replace('\\', '/')); + } + + return paths; + } + + // =================== Private Methods ==================== + + /** + * Finds the paths of all the resources with the class path and extension. + * + * @param classPath - The path of the jar file. + * @param path - The main path of the resource. + * @param excludePath - The continued path to exclude from the list. + * @param extension - The extension of the resource, this can be empty. + * @return Returns a collection of strings with the paths of the matching + * resources. + */ + private static Collection getResources(String classPath, String path, String excludePath, String extension) { + + ArrayList paths = new ArrayList(); + File file = new File(classPath); + + if (file.isDirectory()) { + // Add files from directory if the class path is not a jar file + paths.addAll(getResourcesFromDirectory(file, classPath, path, excludePath, extension)); + } + else { + // Add files from a jar if the class path is not a directory + paths.addAll(getResourcesFromJarFile(file, classPath, path, excludePath, extension)); + } + return paths; + } + /** + * Finds the paths of all the resources within a jar file. + * + * @param file - The jar file to look through. + * @param classPath - The path of the jar file. + * @param path - The main path of the resource. + * @param excludePath - The continued path to exclude from the list. + * @param extension - The extension of the resource, this can be empty. + * @return Returns a collection of strings with the paths of the matching + * resources. + */ + private static Collection getResourcesFromJarFile(File file, String classPath, String path, String excludePath, String extension) { + + ArrayList paths = new ArrayList(); + + try { + // Open the jar file + ZipFile zipFile = new ZipFile(file); + + // Get the contents of the jar file + Enumeration zipEntries = zipFile.entries(); + + // For each entry in the jar file, check for a matching path: + while (zipEntries.hasMoreElements()) { + ZipEntry zipEntry = zipEntries.nextElement(); + String fileName = zipEntry.getName(); + // Make sure the path ends with the appropriate extension and is not a directory + if (!fileName.endsWith("\\") && !fileName.endsWith("/") && fileName.endsWith(extension)) { + + // Compare paths: + if (fileName.startsWith(path) && + (!fileName.startsWith(path + excludePath) || + excludePath.isEmpty())) { + // Try loading without the class path + paths.add(fileName); + } + else if (fileName.startsWith(classPath + "\\" + path) && + (!fileName.startsWith(classPath + "\\" + path + excludePath) || + excludePath.isEmpty())) { + // Try loading with the class path with Windows OS separators + fileName = fileName.substring((classPath + "\\").length()); + paths.add(fileName); + } + else if (fileName.startsWith(classPath + "/" + path) && + (!fileName.startsWith(classPath + "/" + path + excludePath) || + excludePath.isEmpty())) { + // Try loading with the class path with Mac OS separators + fileName = fileName.substring((classPath + "/").length()); + paths.add(fileName); + } + } + } + + // Close the jar file + zipFile.close(); + } + catch (ZipException e) { + e.printStackTrace(); + } + catch (IOException e) { + e.printStackTrace(); + } + + return paths; + } + /** + * Finds the paths of all the resources within a jar file. + * + * @param file - The directory file to look through. + * @param classPath - The path of the jar file. + * @param path - The main path of the resource. + * @param excludePath - The continued path to exclude from the list. + * @param extension - The extension of the resource, this can be empty. + * @return Returns a collection of strings with the paths of the matching + * resources. + */ + private static Collection getResourcesFromDirectory(File directory, String classPath, String path, String excludePath, String extension) { + + ArrayList paths = new ArrayList(); + + // Get the contents of the directory + File[] fileList = directory.listFiles(); + + // Get for each file in the directory, check for a matching path: + for (File file : fileList) { + if (file.isDirectory()) { + // The file is a directory + // Load contents from the child directory + paths.addAll(getResourcesFromDirectory(file, classPath, path, excludePath, extension)); + } + else { + // The file is not a directory + try { + String fileName = file.getCanonicalPath(); + // Make sure the path ends with the appropriate extension and is not a directory + if (!fileName.endsWith("\\") && !fileName.endsWith("/") && fileName.endsWith(extension)) { + + // Compare paths: + if (fileName.startsWith(path) && + (!fileName.startsWith(path + excludePath) || + excludePath.isEmpty())) { + // Try loading without the class path + paths.add(fileName); + } + else if (fileName.startsWith(classPath + "\\" + path) && + (!fileName.startsWith(classPath + "\\" + path + excludePath) || + excludePath.isEmpty())) { + // Try loading with the class path with Windows OS separators + fileName = fileName.substring((classPath + "\\").length()); + paths.add(fileName); + } + else if (fileName.startsWith(classPath + "/" + path) && + (!fileName.startsWith(classPath + "/" + path + excludePath) || + excludePath.isEmpty())) { + // Try loading with the class path with Mac OS separators + fileName = fileName.substring((classPath + "/").length()); + paths.add(fileName); + } + } + } + catch (IOException e) { + e.printStackTrace(); + } + } + } + + return paths; + } +} diff --git a/MetroidMapGuardian/src/main/Sound.java b/MetroidMapGuardian/src/main/Sound.java new file mode 100644 index 0000000..8738862 --- /dev/null +++ b/MetroidMapGuardian/src/main/Sound.java @@ -0,0 +1,179 @@ +package main; +import java.util.ArrayList; +import javax.sound.sampled.*; + + +public class Sound { + + public static final int SOUND_GROUPS = 2; + + public static final int groupRoom = 1; + public static final int groupMenu = 2; + + + // Sound Management + public static ArrayList sounds = new ArrayList(); + public static boolean muted = false; + public static float volume = 0.0f; + + // Sound Data + public ArrayList clips = new ArrayList(); + public int currentSound = 0; + public float volumeOffset = 0.0f; + public int group = 0; + + // Constructor + public Sound(Clip clip, int group) { + this.clips.add(clip); + this.group = group; + } + + public Sound(int group) { + this.group = group; + } + public Sound() { + + } + + /* + * Local Sound Functions + */ + + public void play() { + if( !muted ) { + clips.get(currentSound).stop(); + clips.get(currentSound).setFramePosition(0); + clips.get(currentSound).start(); + currentSound += 1; + if( currentSound >= clips.size() ) { + currentSound = 0; + } + } + } + + public void stop() { + for( int i = 0; i < clips.size(); i++ ) { + clips.get(i).stop(); + clips.get(i).setFramePosition(0); + + } + } + + public void pause() { + for( int i = 0; i < clips.size(); i++ ) { + if( clips.get(i).getMicrosecondPosition() > 0 && clips.get(i).isActive() ) { + clips.get(i).stop(); + } + } + } + + public void resume() { + for( int i = 0; i < clips.size(); i++ ) { + if( clips.get(i).getMicrosecondPosition() > 0 && !clips.get(i).isActive() ) { + clips.get(i).start(); + } + } + } + + public void setVolume(float volume) { + volumeOffset = Math.max(-80.0f, Math.min(6.0f, volume)); + for( int i = 0; i < clips.size(); i++ ) { + FloatControl ctrl = (FloatControl)clips.get(i).getControl(FloatControl.Type.MASTER_GAIN); + ctrl.setValue(Math.max(-80.0f, Math.min(6.0f, Sound.volume + volumeOffset))); + } + } + + public boolean isPlaying() { + for( int i = 0; i < clips.size(); i++ ) { + if( clips.get(i).isActive() ) { + return true; + } + } + return false; + } + + public boolean isPaused() { + for( int i = 0; i < clips.size(); i++ ) { + if( clips.get(i).getMicrosecondPosition() > 0 && !clips.get(i).isActive() ) { + return true; + } + } + return false; + } + + public int channels() { + return clips.size(); + } + + public void add(Clip clip) { + clips.add(clip); + } + + public void remove() { + clips.remove(clips.size() - 1); + if( currentSound >= clips.size() ) { + currentSound = 0; + } + } + + /* + * Static Sound Functions + */ + + public static void mute(boolean mute) { + muted = mute; + for( int i = 0; i < sounds.size(); i++ ) { + sounds.get(i).setVolume(muted ? -80.0f : volume); + } + } + + public static void stopAll() { + for( int i = 0; i < sounds.size(); i++ ) { + sounds.get(i).stop(); + } + } + + public static void stopAll(int group) { + for( int i = 0; i < sounds.size(); i++ ) { + if( sounds.get(i).group == group || group == 0 ) { + sounds.get(i).stop(); + } + } + } + + public static void pauseAll() { + for( int i = 0; i < sounds.size(); i++ ) { + sounds.get(i).pause(); + } + } + + public static void pauseAll(int group) { + for( int i = 0; i < sounds.size(); i++ ) { + if( sounds.get(i).group == group || group == 0 ) { + sounds.get(i).pause(); + } + } + } + + public static void resumeAll() { + for( int i = 0; i < sounds.size(); i++ ) { + sounds.get(i).resume(); + } + } + + public static void resumeAll(int group) { + for( int i = 0; i < sounds.size(); i++ ) { + if( sounds.get(i).group == group || group == 0 ) { + sounds.get(i).resume(); + } + } + } + + public static void setVolumeAll(float volume) { + Sound.volume = Math.max(-80.0f, Math.min(6.0f, volume)); + + for( int i = 0; i < sounds.size(); i++ ) { + sounds.get(i).setVolume(sounds.get(i).volumeOffset); + } + } +} diff --git a/MetroidMapGuardian/src/main/SoundLoader.java b/MetroidMapGuardian/src/main/SoundLoader.java new file mode 100644 index 0000000..4c99e66 --- /dev/null +++ b/MetroidMapGuardian/src/main/SoundLoader.java @@ -0,0 +1,97 @@ +package main; + + +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; + +import javax.sound.sampled.*; + + +public class SoundLoader { + + private static HashMap soundMap = new HashMap(); + + private static int soundsLoaded = 0; + + // Songs + + + + public static void loadSounds() { + + System.out.println("Loading Music:"); + + soundsLoaded = 0; + + // Load Songs + + + System.out.println(""); + System.out.println("Loaded " + String.valueOf(soundsLoaded) + " songs"); + System.out.println("--------------------------------"); + System.out.println("Loading Sounds:"); + + soundsLoaded = 0; + + // Load Sounds + loadSound("activation", "activation.wav", 4, 0.0f, 0); + loadSound("focus_change", "focus_change.wav", 4, 0.0f, 0); + loadSound("marker_activation", "activation_change_fail.wav", 4, 0.0f, 0); + loadSound("marker_focus_change", "focus_change_fail.wav", 4, 0.0f, 0); + + System.out.println(""); + System.out.println("Loaded " + String.valueOf(soundsLoaded) + " sounds"); + System.out.println("--------------------------------"); + + Sound.setVolumeAll(0.0f); + } + + public static Sound getSound(String name) { + return soundMap.get(name); + } + + public static Clip loadClip(String path) { + try { + URL url = SoundLoader.class.getResource(path); + + AudioInputStream audioIn = AudioSystem.getAudioInputStream(url); + + Clip clip = AudioSystem.getClip(); + clip.open(audioIn); + //new JS_MP3ConversionProvider(); + //new JS_MP3FileReader(); + //new JavaDecoder(); + return clip; + } + catch (UnsupportedAudioFileException e) { + e.printStackTrace(); + } + catch (IOException e) { + e.printStackTrace(); + } + catch (LineUnavailableException e) { + e.printStackTrace(); + } + return null; + } + + public static void loadSound(String name, String path, int channels, float volumeOffset, int group) { + + System.out.println("- " + path); + + soundsLoaded += 1; + Sound sound = new Sound(group); + for( int i = 0; i < channels; i++ ) { + Clip clip = loadClip("/resources/sounds/" + path); + if( clip != null ) + sound.add(clip); + else + return; + } + sound.setVolume(volumeOffset); + Sound.sounds.add(sound); + soundMap.put(name, sound); + } + +} diff --git a/MetroidMapGuardian/src/nbt/NBTElement.java b/MetroidMapGuardian/src/nbt/NBTElement.java new file mode 100644 index 0000000..61924e4 --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTElement.java @@ -0,0 +1,317 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * The Named-Binary-Tag format is a file format created by Markus Persson. + * It works by storing elements in the form of tags. Each tag starts with a + * tag type which is a byte long, then the tag will contain a name. There + * are currently 12 different types of tags, the most important being + * {@linkplain NBTTagCompound}, as it is used to store all other tags. + * + *

+ * + * This is the base element in the Named-Binary-Tag format. + * All elements contain a value of the type specified by their tag. + * + *

+ * + * To write and read a tag use {@linkplain saveNBTCompound} and + * {@linkplain loadNBTCompound} respectively. The NBT standard requires the + * contents to be saved with a compound within a root compound, however the + * root compound is not required to function. + * + *

+ * + * @author Markus Persson + * + * @see Markus Persson's Twitter, + * Minepedia: NBT Format + * @see + * {@linkplain NBTTagCompound} + */ +public abstract class NBTElement { + + // ====================== Constants ======================= + + /** A tag used to end lists and compounds. */ + public static final byte TAG_END = 0; + /** A tag with a byte value, it can also be used as a boolean. */ + public static final byte TAG_BYTE = 1; + /** A tag with a short value. */ + public static final byte TAG_SHORT = 2; + /** A tag with a integer value. */ + public static final byte TAG_INT = 3; + /** A tag with a long value. */ + public static final byte TAG_LONG = 4; + /** A tag with a float value. */ + public static final byte TAG_FLOAT = 5; + /** A tag with a double value. */ + public static final byte TAG_DOUBLE = 6; + /** A tag with a byte array value. */ + public static final byte TAG_BYTE_ARRAY = 7; + /** A tag with a string value. */ + public static final byte TAG_STRING = 8; + /** A tag with a list of tag value. */ + public static final byte TAG_LIST = 9; + /** A tag that contains more elements of tags. */ + public static final byte TAG_COMPOUND = 10; + /** A tag with a integer array value. */ + public static final byte TAG_INT_ARRAY = 11; + + // ======================= Members ======================== + + /** The key identifier of the element. */ + protected String key; + + // ===================== Constructors ===================== + + /** + * Creates the base of an element with the given key. + * + * @param key - The key identifier of the element. + * @return Returns the base of the element with the given key. + */ + protected NBTElement(String key) { + this.key = ((key == null) ? "" : key); + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + // Format: + // TAG_Compound - MyCompound: + // TAG_String - MyString: "Hello World!" + + String spacing = ""; + for (int i = 0; i < level; i++) + spacing += " "; + + String tagName = NBTElement.getTagName(getType()); + + if (getType() != NBTElement.TAG_END) { + if (!key.isEmpty()) + tagName += " - " + key; + + tagName += ": "; + } + + return spacing + tagName; + } + + // =================== Abstract Methods =================== + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + abstract void writeTagContents(DataOutput out) throws IOException; + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + abstract void readTagContents(DataInput in) throws IOException; + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public abstract byte getType(); + + // =================== Key Information ==================== + + /** + * Sets the key identifier of the tag to the specified string. + * + * @param key - The new key identifier. + * @return Returns the element after the key has been set. + */ + public NBTElement setKey(String key) { + // If the string is null set key to an empty string. + this.key = ((key == null) ? "" : key); + return this; + } + /** + * Returns the key identifier of the tag. + * + * @return Returns the key identifier. + */ + public String getKey() { + return key; + } + + // ======================= File IO ======================== + + /** + * Writes the given tag to the output stream. + * + * @param tag - The tag to write. + * @param out - The output stream to write to. + * @throws IOException + */ + public static void writeTag(NBTElement tag, DataOutput out) throws IOException { + // Write the tag type + out.writeByte(tag.getType()); + // Write the contents and key if the tag is not TAG_End + if (tag.getType() == NBTElement.TAG_END) { + return; + } + else { + // Write the key identifier + out.writeUTF(tag.getKey()); + // Write the tag contents + tag.writeTagContents(out); + return; + } + } + /** + * Reads and returns the next tag in the input stream. + * + * @param in - The input stream to read from + * @return Returns the new tag after it has been read. + * @throws IOException + */ + public static NBTElement readTag(DataInput in) throws IOException { + // Read the tag type + byte type = in.readByte(); + // Read the contents and key if the tag is not TAG_End + if (type == NBTElement.TAG_END) { + return new NBTTagEnd(); + } + else { + // Read the key identifier + String key = in.readUTF(); + // Create and read the tag contents + NBTElement tag = NBTElement.createTagOfType(type, key); + tag.readTagContents(in); + return tag; + } + } + + // =================== Static Functions =================== + + /** + * Returns a tag of the given type with the given key. + * + * @param type - The type of tag to create. + * @param key - The key identifier to assign to the tag + * @return Returns a tag of the given tag type with the given key. + */ + public static NBTElement createTagOfType(byte type, String key) { + switch (type) { + case NBTElement.TAG_END: return new NBTTagEnd(); + case NBTElement.TAG_BYTE: return new NBTTagByte(key); + case NBTElement.TAG_SHORT: return new NBTTagShort(key); + case NBTElement.TAG_INT: return new NBTTagInt(key); + case NBTElement.TAG_LONG: return new NBTTagLong(key); + case NBTElement.TAG_FLOAT: return new NBTTagFloat(key); + case NBTElement.TAG_DOUBLE: return new NBTTagDouble(key); + case NBTElement.TAG_BYTE_ARRAY: return new NBTTagByteArray(key); + case NBTElement.TAG_STRING: return new NBTTagString(key); + case NBTElement.TAG_LIST: return new NBTTagList(key); + case NBTElement.TAG_COMPOUND: return new NBTTagCompound(key); + case NBTElement.TAG_INT_ARRAY: return new NBTTagIntArray(key); + } + return null; + } + /** + * Returns the name of the specified tag type. + * + * @param type - The type of tag to get the name of. + * @return Returns the name of the given tag type. + */ + public static String getTagName(byte type) { + switch (type) { + case NBTElement.TAG_END: return "TAG_End"; + case NBTElement.TAG_BYTE: return "TAG_Byte"; + case NBTElement.TAG_SHORT: return "TAG_Short"; + case NBTElement.TAG_INT: return "TAG_Int"; + case NBTElement.TAG_LONG: return "TAG_Long"; + case NBTElement.TAG_FLOAT: return "TAG_Float"; + case NBTElement.TAG_DOUBLE: return "TAG_Double"; + case NBTElement.TAG_BYTE_ARRAY: return "TAG_Byte_Array"; + case NBTElement.TAG_STRING: return "TAG_String"; + case NBTElement.TAG_LIST: return "TAG_List"; + case NBTElement.TAG_COMPOUND: return "TAG_Compound"; + case NBTElement.TAG_INT_ARRAY: return "TAG_Int_Array"; + } + return "UNKNOWN"; + } + /** + * Loads and returns an NBT compound that contains the main tag in the file. + * + * @param path - The path of the file to load from. + * @param isResource - True if the file should be loaded as a resource. + * @return Returns the NBT compound that contains the main tag in the file. + */ + public static NBTTagCompound loadNBTCompound(String path, boolean isResource) { + try { + InputStream stream = null; + + if (isResource) + stream = NBTElement.class.getResourceAsStream(path); + else + stream = new FileInputStream(path); + + DataInputStream in = new DataInputStream(stream); + + // Read the tag which needs to be a TAG_Compound. + NBTElement tag = NBTElement.readTag(in); + + return (NBTTagCompound)tag; + } + catch (FileNotFoundException e) { + e.printStackTrace(); + } + catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + /** + * Saves the given NBT tag to the file. + * + * @param path - The path of the file to save as. + * @param nbt - The NBT tag to save to file. + */ + public static void saveNBTCompound(String path, NBTTagCompound nbt) { + try { + OutputStream stream = new FileOutputStream(path); + DataOutputStream out = new DataOutputStream(stream); + + // Write the tag which needs to be a TAG_Compound. + NBTElement.writeTag(nbt, out); + } + catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/MetroidMapGuardian/src/nbt/NBTTagByte.java b/MetroidMapGuardian/src/nbt/NBTTagByte.java new file mode 100644 index 0000000..8f2cd9d --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagByte.java @@ -0,0 +1,104 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * A basic NBT element with a byte value. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ +public class NBTTagByte extends NBTElement { + + // ======================= Members ======================== + + /** The byte value of the element. */ + public byte byteValue; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a byte with a value of 0 and + * an empty key. + * + * @return Returns a byte of the value 0 with an empty key. + */ + public NBTTagByte() { + super(""); + this.byteValue = 0; + } + /** + * Constructs a byte of the value 0 with the given key. + * + * @param key - The key identifier of the tag. + * @return Returns a byte of the value 0 with the given key. + */ + public NBTTagByte(String key) { + super(key); + this.byteValue = 0; + } + /** + * Constructs a byte with the given value and key. + * + * @param key - The key identifier of the tag. + * @param byteValue - The value of the tag. + * @return Returns a byte with the given value and key. + */ + public NBTTagByte(String key, byte byteValue) { + super(key); + this.byteValue = byteValue; + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + return super.toString(level) + String.valueOf(byteValue) + "\n"; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + out.writeByte(byteValue); + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + byteValue = in.readByte(); + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_BYTE; + } +} + diff --git a/MetroidMapGuardian/src/nbt/NBTTagByteArray.java b/MetroidMapGuardian/src/nbt/NBTTagByteArray.java new file mode 100644 index 0000000..caf2b2f --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagByteArray.java @@ -0,0 +1,123 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * A basic NBT element with a byte array. This can be used to store files. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ +public class NBTTagByteArray extends NBTElement { + + // ======================= Members ======================== + + /** The byte array of the element. */ + public byte[] byteArray; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a byte array with 0 bytes and an + * empty key. + * + * @return Returns a byte array with 0 bytes and an empty key. + */ + public NBTTagByteArray() { + super(""); + this.byteArray = new byte[0]; + } + /** + * Constructs a byte array with 0 bytes and the given key. + * + * @param key - The key identifier of the tag. + * @return Returns a byte array with 0 bytes and the given key. + */ + public NBTTagByteArray(String key) { + super(key); + this.byteArray = new byte[0]; + } + /** + * Constructs a byte array with the given value and key. + * + * @param key - The key identifier of the tag. + * @param byteArray - The value of the tag. + * @return Returns a byte array with the given value and key. + */ + public NBTTagByteArray(String key, byte[] byteArray) { + super(key); + this.byteArray = byteArray; + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + String tagName = super.toString(level) + "\n"; + level += 1; + for (byte byteValue : byteArray) { + tagName += new NBTTagByte("", byteValue).toString(level); + } + + return tagName; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + out.writeInt(byteArray.length); + out.write(byteArray); + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + int arraySize = in.readInt(); + byteArray = new byte[arraySize]; + in.readFully(byteArray); + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_BYTE_ARRAY; + } + + // ==================== Array Methods ===================== + + /** + * Returns the number of bytes in the array. + * + * @return Returns the number of bytes in the array. + */ + public int arraySize() { + return byteArray.length; + } +} diff --git a/MetroidMapGuardian/src/nbt/NBTTagCompound.java b/MetroidMapGuardian/src/nbt/NBTTagCompound.java new file mode 100644 index 0000000..2ffc7cf --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagCompound.java @@ -0,0 +1,730 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * An NBT element that contains a collection of NBT elements. This is the + * main class to read NBT files from. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement} + */ +public class NBTTagCompound extends NBTElement { + + // ======================= Members ======================== + + /** + * The map that contains all the elements in this compound. A linked hash map + * is used for this so the order of the elements is kept, thus outputting to the + * console will give an organized list. + */ + private LinkedHashMap tagMap; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an empty compound with an empty key. + * + * @return Returns an empty compound with an empty key. + */ + public NBTTagCompound() { + super(""); + this.tagMap = new LinkedHashMap(); + } + /** + * Constructs an empty compound with the given key. + * + * @param key - The key identifier. + * @return Returns an empty compound with the given key. + */ + public NBTTagCompound(String key) { + super(key); + this.tagMap = new LinkedHashMap(); + } + /** + * Constructs a compound with the given tags and key. + * + * @param key - The key identifier. + * @param tagMap - The map of tags to add to the compound. + * @return Returns a compound with the given tags and key. + */ + public NBTTagCompound(String key, Map tagMap) { + super(key); + this.tagMap = new LinkedHashMap(); + this.tagMap.putAll(tagMap); + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + String tagName = super.toString(level) + "\n"; + level += 1; + for (NBTElement tag : tagMap.values()) { + tagName += tag.toString(level); + } + tagName += new NBTTagEnd().toString(level); + + return tagName; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + + // Write the tags + for (NBTElement tag : tagMap.values()) { + NBTElement.writeTag(tag, out); + } + + // End the list with TAG_End + out.writeByte(0); + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + + // Read the tags until TAG_End is reached + NBTElement tag = null; + tagMap.clear(); + do { + // Read and add the tag to the map + tag = NBTElement.readTag(in); + if (tag.getType() != NBTElement.TAG_END) + tagMap.put(tag.getKey(), tag); + } + while(tag.getType() != NBTElement.TAG_END); + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_COMPOUND; + } + + // =================== Compound Methods =================== + + /** + * Returns the collection of tags contained in this compound. + * + * @return Returns the collection of tags contained in this compound. + */ + public Collection getTags() { + return tagMap.values(); + } + /** + * Returns the map of tags contained in this compound. + * + * @return Returns the map of tags contained in this compound. + */ + public Map getTagMap() { + return tagMap; + } + /** + * Returns the number of elements in the list. + * + * @return Returns the number of elements in the list. + */ + public int tagCount() { + return tagMap.size(); + } + /** + * Clears all the tags in the compound. + */ + public void clearTags() { + tagMap.clear(); + } + /** + * Tests whether an element with the given key exists. + * + * @param key - The key identifier to test for. + * @return Returns true if there is an element with the given key. + */ + public boolean hasKey(String key) { + return (getTag(key, null) != null); + } + /** + * Tests whether an element with the given key and type exists. + * + * @param key - The key identifier to test for. + * @param type - The type that the element must match + * @return Returns true if there is an element with the given key and + * the specified type. + */ + public boolean hasKey(String key, byte type) { + NBTElement tag = getTag(key, null); + if (tag != null) + return (tag.getType() == type); + + return false; + } + + // =================== Mutator Methods ==================== + + /** + * Sets the tag of the given key identifier to the given value. This will overwrite + * the current tag with this key in the compound. To access compound elements + * within this compound use a '/' to separate values. + * + * @param key - The key identifier of the tag. + * @param tag - The tag to set the element to. + */ + public void setTag(String key, NBTElement tag) { + // Check if the key is accessing another compound + if (key.indexOf("/") == -1) { + // Add the tag to the map + tagMap.put(key, tag.setKey(key)); + } + else { + String prefix = key.substring(0, key.indexOf("/")); + String postfix = key.substring(key.indexOf("/") + 1); + + // Create a compound tag if one does not exist + if (!hasKey(prefix, NBTElement.TAG_COMPOUND)) + tagMap.put(prefix, new NBTTagCompound(prefix)); + + // Recurse until the tag is set + ((NBTTagCompound)tagMap.get(prefix)).setTag(postfix, tag); + } + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param booleanValue - The value to set the tag to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setBoolean(String key, boolean booleanValue) { + setTag(key, new NBTTagByte(key, (byte)(booleanValue ? 1 : 0))); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param byteValue - The value to set the tag to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setByte(String key, byte byteValue) { + setTag(key, new NBTTagByte(key, byteValue)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param shortValue - The value to set the tag to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setShort(String key, short shortValue) { + setTag(key, new NBTTagShort(key, shortValue)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param intValue - The value to set the tag to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setInteger(String key, int intValue) { + setTag(key, new NBTTagInt(key, intValue)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param longValue - The value to set the tag to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setLong(String key, long longValue) { + setTag(key, new NBTTagLong(key, longValue)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param floatValue - The value to set the tag to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setFloat(String key, float floatValue) { + setTag(key, new NBTTagFloat(key, floatValue)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param doubleValue - The value to set the tag to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setDouble(String key, double doubleValue) { + setTag(key, new NBTTagDouble(key, doubleValue)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param stringValue - The value to set the tag to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setString(String key, String stringValue) { + setTag(key, new NBTTagString(key, stringValue)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param byteArray - The value to set the tag to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setByteArray(String key, byte[] byteArray) { + setTag(key, new NBTTagByteArray(key, byteArray)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param intArray - The value to set the tag to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setIntegerArray(String key, int[] intArray) { + setTag(key, new NBTTagIntArray(key, intArray)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param tagList - The list of tags to set the element to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setList(String key, Collection tagList) { + setTag(key, new NBTTagList(key, tagList)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param tag - The tag to set the element to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setList(String key, NBTTagList tag) { + setTag(key, tag.setKey(key)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param tagMap - The map of tags to set the element to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setCompound(String key, Map tagMap) { + setTag(key, new NBTTagCompound(key, tagMap)); + } + /** + * Sets the tag with the given key to the given value. See setTag for more details. + * + * @param key - The key identifier of the tag. + * @param tag - The tag to set the element to. + * + * @see + * {@linkplain #setTag(String, NBTElement)} + */ + public void setCompound(String key, NBTTagCompound tag) { + setTag(key, tag.setKey(key)); + } + + // =================== Accessor Methods =================== + + /** + * Finds and returns the tag with the given key identifier. To access + * compound elements within this compound use a '/' to separate values. + * Returns the default tag if the key does not exist. + * + * @param key - The key of the tag to search for. + * @param defTag - The default tag to return if the key does not exist. + * This can be set to null. + * @return Returns the tag with the given key identifier, or defTag if + * the tag doesn't exist. + */ + public NBTElement getTag(String key, NBTElement defTag) { + // Check if the key is accessing another compound + if (key.indexOf("/") == -1) { + // Get the tag + NBTElement tag = tagMap.get(key); + // Return defTag if the tag does not exist + return ((tag != null) ? tag : defTag); + } + else { + String prefix = key.substring(0, key.indexOf("/")); + String postfix = key.substring(key.indexOf("/") + 1); + + // Recurse until the tag is retreived + return ((NBTTagCompound)tagMap.get(prefix)).getTag(postfix, defTag); + } + } + /** + * Finds and returns the tag with the given key identifier. To access + * compound elements within this compound use a '/' to separate values. + * Returns the null if the key does not exist. + * + * @param key - The key of the tag to search for. + * @return Returns the tag with the given key identifier, or null if + * the tag doesn't exist. + */ + public NBTElement getTag(String key) { + return getTag(key, null); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public boolean getBoolean(String key, boolean defValue) { + return ((NBTTagByte)getTag(key, new NBTTagByte(key, (byte)(defValue ? 1 : 0)))).byteValue != 0; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public boolean getBoolean(String key) { + return getBoolean(key, false); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public byte getByte(String key, byte defValue) { + return ((NBTTagByte)getTag(key, new NBTTagByte(key, defValue))).byteValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public byte getByte(String key) { + return getByte(key, (byte)0); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public short getShort(String key, short defValue) { + return ((NBTTagShort)getTag(key, new NBTTagShort(key, defValue))).shortValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public short getShort(String key) { + return getShort(key, (short)0); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public int getInteger(String key, int defValue) { + return ((NBTTagInt)getTag(key, new NBTTagInt(key, defValue))).intValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public int getInteger(String key) { + return getInteger(key, 0); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public long getLong(String key, long defValue) { + return ((NBTTagLong)getTag(key, new NBTTagLong(key, defValue))).longValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public long getLong(String key) { + return getLong(key, 0L); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public float getFloat(String key, float defValue) { + return ((NBTTagFloat)getTag(key, new NBTTagFloat(key, defValue))).floatValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public float getFloat(String key) { + return getFloat(key, 0.0f); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public double getDouble(String key, double defValue) { + return ((NBTTagDouble)getTag(key, new NBTTagDouble(key, defValue))).doubleValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public double getDouble(String key) { + return getDouble(key, 0.0); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public String getString(String key, String defValue) { + return ((NBTTagString)getTag(key, new NBTTagString(key, defValue))).stringValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public String getString(String key) { + return getString(key, null); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public byte[] getByteArray(String key, byte[] defValue) { + return ((NBTTagByteArray)getTag(key, new NBTTagByteArray(key, defValue))).byteArray; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public byte[] getByteArray(String key) { + return getByteArray(key, null); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public int[] getIntegerArray(String key, int[] defValue) { + return ((NBTTagIntArray)getTag(key, new NBTTagIntArray(key, defValue))).intArray; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public int[] getIntegerArray(String key) { + return getIntegerArray(key, null); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public NBTTagList getList(String key, NBTTagList defValue) { + return ((NBTTagList)getTag(key, defValue)); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public NBTTagList getList(String key) { + return getList(key, null); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(String, NBTElement)} + */ + public NBTTagCompound getCompound(String key, NBTTagCompound defValue) { + return ((NBTTagCompound)getTag(key, defValue)); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param key - The key of the tag to search for. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(String)} + */ + public NBTTagCompound getCompound(String key) { + return getCompound(key, null); + } +} diff --git a/MetroidMapGuardian/src/nbt/NBTTagDouble.java b/MetroidMapGuardian/src/nbt/NBTTagDouble.java new file mode 100644 index 0000000..02b7c3d --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagDouble.java @@ -0,0 +1,103 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * A basic NBT element with a double value. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ +public class NBTTagDouble extends NBTElement { + + // ======================= Members ======================== + + /** The double value of the element. */ + public double doubleValue; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a double with a value of 0 and + * an empty key. + * + * @return Returns a double of the value 0 with an empty key. + */ + public NBTTagDouble() { + super(""); + this.doubleValue = 0.0; + } + /** + * Constructs a double of the value 0 with the given key. + * + * @param key - The key identifier of the tag. + * @return Returns a double of the value 0 with the given key. + */ + public NBTTagDouble(String key) { + super(key); + this.doubleValue = 0.0; + } + /** + * Constructs a double with the given value and key. + * + * @param key - The key identifier of the tag. + * @param doubleValue - The value of the tag. + * @return Returns a double with the given value and key. + */ + public NBTTagDouble(String key, double doubleValue) { + super(key); + this.doubleValue = doubleValue; + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + return super.toString(level) + String.valueOf(doubleValue) + "\n"; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + out.writeDouble(doubleValue); + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + doubleValue = in.readDouble(); + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_DOUBLE; + } +} diff --git a/MetroidMapGuardian/src/nbt/NBTTagEnd.java b/MetroidMapGuardian/src/nbt/NBTTagEnd.java new file mode 100644 index 0000000..b345e4b --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagEnd.java @@ -0,0 +1,75 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * The end tag used to close NBT compounds. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ +public class NBTTagEnd extends NBTElement { + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an end tag + * + * @return Returns an end tag. + */ + public NBTTagEnd() { + super(""); + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + return super.toString(level) + "\n"; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_END; + } +} diff --git a/MetroidMapGuardian/src/nbt/NBTTagFloat.java b/MetroidMapGuardian/src/nbt/NBTTagFloat.java new file mode 100644 index 0000000..b6e8b2c --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagFloat.java @@ -0,0 +1,103 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * A basic NBT element with a float value. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ +public class NBTTagFloat extends NBTElement { + + // ======================= Members ======================== + + /** The float value of the element. */ + public float floatValue; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a float with a value of 0 and + * an empty key. + * + * @return Returns a float of the value 0 with an empty key. + */ + public NBTTagFloat() { + super(""); + this.floatValue = 0.0f; + } + /** + * Constructs a float of the value 0 with the given key. + * + * @param key - The key identifier of the tag. + * @return Returns a float of the value 0 with the given key. + */ + public NBTTagFloat(String key) { + super(key); + this.floatValue = 0.0f; + } + /** + * Constructs a float with the given value and key. + * + * @param key - The key identifier of the tag. + * @param floatValue - The value of the tag. + * @return Returns a float with the given value and key. + */ + public NBTTagFloat(String key, float floatValue) { + super(key); + this.floatValue = floatValue; + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + return super.toString(level) + String.valueOf(floatValue) + "\n"; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + out.writeFloat(floatValue); + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + floatValue = in.readFloat(); + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_FLOAT; + } +} diff --git a/MetroidMapGuardian/src/nbt/NBTTagInt.java b/MetroidMapGuardian/src/nbt/NBTTagInt.java new file mode 100644 index 0000000..5815795 --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagInt.java @@ -0,0 +1,103 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * A basic NBT element with a integer value. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ +public class NBTTagInt extends NBTElement { + + // ======================= Members ======================== + + /** The integer value of the element. */ + public int intValue; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an integer with a value of 0 and + * an empty key. + * + * @return Returns an integer of the value 0 with an empty key. + */ + public NBTTagInt() { + super(""); + this.intValue = 0; + } + /** + * Constructs an integer of the value 0 with the given key. + * + * @param key - The key identifier of the tag. + * @return Returns an integer of the value 0 with the given key. + */ + public NBTTagInt(String key) { + super(key); + this.intValue = 0; + } + /** + * Constructs an integer with the given value and key. + * + * @param key - The key identifier of the tag. + * @param intValue - The value of the tag. + * @return Returns an integer with the given value and key. + */ + public NBTTagInt(String key, int intValue) { + super(key); + this.intValue = intValue; + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + return super.toString(level) + String.valueOf(intValue) + "\n"; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + out.writeInt(intValue); + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + intValue = in.readInt(); + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_INT; + } +} diff --git a/MetroidMapGuardian/src/nbt/NBTTagIntArray.java b/MetroidMapGuardian/src/nbt/NBTTagIntArray.java new file mode 100644 index 0000000..30afed4 --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagIntArray.java @@ -0,0 +1,127 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * A basic NBT element with a integer array. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ +public class NBTTagIntArray extends NBTElement { + + // ======================= Members ======================== + + /** The integer array of the element. */ + public int[] intArray; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a integer array with 0 integers and an + * empty key. + * + * @return Returns a integer array with 0 integers and an empty key. + */ + public NBTTagIntArray() { + super(""); + this.intArray = new int[0]; + } + /** + * Constructs a integer array with 0 integers and the given key. + * + * @param key - The key identifier of the tag. + * @return Returns a integer array with 0 integers and the given key. + */ + public NBTTagIntArray(String key) { + super(key); + this.intArray = new int[0]; + } + /** + * Constructs a integer array with the given value and key. + * + * @param key - The key identifier of the tag. + * @param intArray - The value of the tag. + * @return Returns a integer array with the given value and key. + */ + public NBTTagIntArray(String key, int[] intArray) { + super(key); + this.intArray = intArray; + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + String tagName = super.toString(level) + "\n"; + level += 1; + for (int intValue : intArray) { + tagName += new NBTTagInt("", intValue).toString(level); + } + + return tagName; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + out.writeInt(intArray.length); + for (int i = 0; i < intArray.length; i++) { + out.writeInt(intArray[i]); + } + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + int arraySize = in.readInt(); + intArray = new int[arraySize]; + for (int i = 0; i < arraySize; i++) { + intArray[i] = in.readInt(); + } + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_INT_ARRAY; + } + + // ==================== Array Methods ===================== + + /** + * Returns the number of integers in the array. + * + * @return Returns the number of integers in the array. + */ + public int arraySize() { + return intArray.length; + } +} diff --git a/MetroidMapGuardian/src/nbt/NBTTagList.java b/MetroidMapGuardian/src/nbt/NBTTagList.java new file mode 100644 index 0000000..f90111b --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagList.java @@ -0,0 +1,801 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +/** + * A basic NBT element with a byte value. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ +public class NBTTagList extends NBTElement { + + // ======================= Members ======================== + + /** The type of tags in the list. */ + private byte tagType; + /** The list of elements. */ + private ArrayList tagList; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an empty list with a byte type and + * an empty key. + * + * @return Returns an empty list with a byte type and with an empty key. + */ + public NBTTagList() { + super(""); + this.tagType = 0; + this.tagList = new ArrayList(); + } + /** + * Constructs an empty list with a byte type and the given key. + * + * @param key - The key identifier of the tag. + * @return Returns an empty list with a byte type and the given key. + */ + public NBTTagList(String key) { + super(key); + this.tagType = 0; + this.tagList = new ArrayList(); + } + /** + * Constructs an empty list of the given type and key. + * + * @param key - The key identifier of the tag. + * @param tagType - The type of the tag in the list. + * @return Returns an empty list with the given type and key. + */ + public NBTTagList(String key, byte tagType) { + super(key); + this.tagType = tagType; + this.tagList = new ArrayList(); + } + /** + * Constructs an empty list of the given type and key. + * + * @param key - The key identifier of the tag. + * @param tagType - The type of the tag in the list. + * @return Returns an empty list with the given type and key. + */ + public NBTTagList(String key, Collection tagList) { + super(key); + this.tagList = new ArrayList(); + this.tagList.addAll(tagList); + if (this.tagList.size() > 0) + this.tagType = this.tagList.get(0).getType(); + else + this.tagType = NBTElement.TAG_BYTE; + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + String tagName = super.toString(level) + "\n"; + level += 1; + for (NBTElement tag : tagList) { + tagName += tag.toString(level); + } + + return tagName; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + // Correct the tag type + if (tagList.size() > 0) + tagType = tagList.get(0).getType(); + + // Write the header + out.writeByte(tagType); + out.writeInt(tagList.size()); + + // Write the list + for (NBTElement tag : tagList) { + tag.writeTagContents(out); + } + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + // Read the header + tagType = in.readByte(); + int tagCount = in.readInt(); + + // Read the list + tagList.clear(); + for (int i = 0; i < tagCount; i++) { + NBTElement tag = NBTElement.createTagOfType(tagType, ""); + tag.readTagContents(in); + tagList.add(tag); + } + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_LIST; + } + + // ===================== List Methods ===================== + + /** + * Returns the collection of tags contained in this list. + * + * @return Returns the collection of tags contained in this list. + */ + public Collection getTags() { + return tagList; + } + /** + * Returns the number of elements in the list. + * + * @return Returns the number of elements in the list. + */ + public int tagCount() { + return tagList.size(); + } + /** + * Clears all the tags in the list. + */ + public void clearTags() { + tagList.clear(); + } + + // =================== Mutator Methods ==================== + + /** + * Sets the type of tags this list contains, this is mainly used for when + * it is not certain if the list will have any elements. + * + * @param tagType - The new type of tag this list contains. + * @return Returns this element after the list type has been set. + */ + public NBTTagList setTagType(byte tagType) { + this.tagType = tagType; + return this; + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param tag - The tag to set the element to. + */ + public void setTag(int index, NBTElement tag) { + // Set the tag type + tagType = tag.getType(); + + // Add the tag to the list at the given index + tagList.set(index, tag.setKey("")); + } + /** + * Adds the tag at the end of the list. + * + * @param tag - The tag to set the element to. + */ + public void addTag(NBTElement tag) { + // Set the tag type + tagType = tag.getType(); + + // Add the tag to the list + tagList.add(tag.setKey("")); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param booleanValue - The value to set the tag to. + */ + public void setBoolean(int index, boolean booleanValue) { + setTag(index, new NBTTagByte("", (byte)(booleanValue ? 1 : 0))); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param booleanValue - The value to set the tag to. + */ + public void addBoolean(boolean booleanValue) { + addTag(new NBTTagByte("", (byte)(booleanValue ? 1 : 0))); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param byteValue - The value to set the tag to. + */ + public void setByte(int index, byte byteValue) { + setTag(index, new NBTTagByte("", byteValue)); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param booleanValue - The value to set the tag to. + */ + public void addByte(byte byteValue) { + addTag(new NBTTagByte("", byteValue)); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param shortValue - The value to set the tag to. + */ + public void setShort(int index, short shortValue) { + setTag(index, new NBTTagShort("", shortValue)); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param shortValue - The value to set the tag to. + */ + public void addShort(short shortValue) { + addTag(new NBTTagShort("", shortValue)); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param intValue - The value to set the tag to. + */ + public void setInteger(int index, int intValue) { + setTag(index, new NBTTagInt("", intValue)); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param intValue - The value to set the tag to. + */ + public void addInteger(int intValue) { + addTag(new NBTTagInt("", intValue)); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param longValue - The value to set the tag to. + */ + public void setLong(int index, long longValue) { + setTag(index, new NBTTagLong("", longValue)); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param longValue - The value to set the tag to. + */ + public void addLong(long longValue) { + addTag(new NBTTagLong("", longValue)); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param floatValue - The value to set the tag to. + */ + public void setFloat(int index, float floatValue) { + setTag(index, new NBTTagFloat("", floatValue)); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param floatValue - The value to set the tag to. + */ + public void addFloat(float floatValue) { + addTag(new NBTTagFloat("", floatValue)); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param doubleValue - The value to set the tag to. + */ + public void setDouble(int index, double doubleValue) { + setTag(index, new NBTTagDouble("", doubleValue)); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param doubleValue - The value to set the tag to. + */ + public void addDouble(double doubleValue) { + addTag(new NBTTagDouble("", doubleValue)); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param stringValue - The value to set the tag to. + */ + public void setString(int index, String stringValue) { + setTag(index, new NBTTagString("", stringValue)); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param stringValue - The value to set the tag to. + */ + public void addString(String stringValue) { + addTag(new NBTTagString("", stringValue)); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param byteArray - The value to set the tag to. + */ + public void setByteArray(int index, byte[] byteArray) { + setTag(index, new NBTTagByteArray("", byteArray)); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param byteArray - The value to set the tag to. + */ + public void addByteArray(byte[] byteArray) { + addTag(new NBTTagByteArray("", byteArray)); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param intArray - The value to set the tag to. + */ + public void setIntegerArray(int index, int[] intArray) { + setTag(index, new NBTTagIntArray("", intArray)); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param intArray - The value to set the tag to. + */ + public void addIntegerArray(int[] intArray) { + addTag(new NBTTagIntArray("", intArray)); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param tagList - The list of tags to set the element to. + */ + public void setList(int index, Collection tagList) { + setTag(index, new NBTTagList("", tagList)); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param tagList - The list of tags to set the element to. + */ + public void addList(Collection tagList) { + addTag(new NBTTagList("", tagList)); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param tag - The tag to set the element to. + */ + public void setList(int index, NBTTagList tag) { + setTag(index, tag); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param tag - The tag to set the element to. + */ + public void addList(NBTTagList tag) { + addTag(tag); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param tagMap - The map of tags to set the element to. + */ + public void setCompound(int index, Map tagMap) { + setTag(index, new NBTTagCompound("", tagMap)); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param tagMap - The map of tags to set the element to. + */ + public void addCompound(Map tagMap) { + addTag(new NBTTagCompound("", tagMap)); + } + /** + * Sets the tag at the given index to the given value. + * + * @param index - The index of the tag. + * @param tag - The tag to set the element to. + */ + public void setCompound(int index, NBTTagCompound tag) { + setTag(index, tag); + } + /** + * Adds the tag at the end of the list with the given value. + * + * @param tag - The tag to set the element to. + */ + public void addCompound(NBTTagCompound tag) { + addTag(tag); + } + + // =================== Accessor Methods =================== + + /** + * Returns the type of tags this list contains. + * + * @return Returns the type of tags this list contains. + */ + public byte getTagType() { + if (tagList.size() > 0) { + return tagList.get(0).getType(); + } + else { + return tagType; + } + } + /** + * Finds and returns the tag at the given index. Returns the default + * tag if the key does not exist. + * + * @param index - The index of the tag. + * @param defTag - The default tag to return if the index does not exist. + * @return Returns the tag at the given index, or defTag if the tag doesn't + * exist. + */ + public NBTElement getTag(int index, NBTElement defTag) { + + // Make sure the index is valid + if (index >= 0 && index < tagList.size()) + return tagList.get(index); + + // Return defTag if the tag does not exist + return defTag; + } + /** + * Finds and returns the tag at the given index. Returns null if the key + * does not exist. + * + * @param index - The index of the tag. + * @return Returns the tag at the given index, or null if the tag doesn't + * exist. + */ + public NBTElement getTag(int index) { + return getTag(index, null); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public boolean getBoolean(int index, boolean defValue) { + return ((NBTTagByte)getTag(index, new NBTTagByte("", (byte)(defValue ? 1 : 0)))).byteValue != 0; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public boolean getBoolean(int index) { + return getBoolean(index, false); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public byte getByte(int index, byte defValue) { + return ((NBTTagByte)getTag(index, new NBTTagByte("", defValue))).byteValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public byte getByte(int index) { + return getByte(index, (byte)0); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public short getShort(int index, short defValue) { + return ((NBTTagShort)getTag(index, new NBTTagShort("", defValue))).shortValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public short getShort(int index) { + return getShort(index, (short)0); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public int getInteger(int index, int defValue) { + return ((NBTTagInt)getTag(index, new NBTTagInt("", defValue))).intValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public int getInteger(int index) { + return getInteger(index, 0); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public long getLong(int index, long defValue) { + return ((NBTTagLong)getTag(index, new NBTTagLong("", defValue))).longValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public long getLong(int index) { + return getLong(index, 0L); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public float getFloat(int index, float defValue) { + return ((NBTTagFloat)getTag(index, new NBTTagFloat("", defValue))).floatValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public float getFloat(int index) { + return getFloat(index, 0.0f); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public double getDouble(int index, double defValue) { + return ((NBTTagDouble)getTag(index, new NBTTagDouble("", defValue))).doubleValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public double getDouble(int index) { + return getDouble(index, 0.0); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public String getString(int index, String defValue) { + return ((NBTTagString)getTag(index, new NBTTagString("", defValue))).stringValue; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public String getString(int index) { + return getString(index, null); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public byte[] getByteArray(int index, byte[] defValue) { + return ((NBTTagByteArray)getTag(index, new NBTTagByteArray("", defValue))).byteArray; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public byte[] getByteArray(int index) { + return getByteArray(index, null); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public int[] getIntegerArray(int index, int[] defValue) { + return ((NBTTagIntArray)getTag(index, new NBTTagIntArray("", defValue))).intArray; + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public int[] getIntegerArray(int index) { + return getIntegerArray(index, null); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public NBTTagList getList(int index, NBTTagList defValue) { + return ((NBTTagList)getTag(index, defValue)); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public NBTTagList getList(int index) { + return getList(index, null); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @param defValue - The default value to return if the tag does not exist. + * @return Returns the value of the key or the default value. + * + * @see + * {@linkplain #getTag(int, NBTElement)} + */ + public NBTTagCompound getCompound(int index, NBTTagCompound defValue) { + return ((NBTTagCompound)getTag(index, defValue)); + } + /** + * Returns the value of the given key. See getTag for more details. + * + * @param index - The index of the tag. + * @return Returns the value of the key. + * + * @see + * {@linkplain #getTag(int)} + */ + public NBTTagCompound getCompound(int index) { + return getCompound(index, null); + } +} diff --git a/MetroidMapGuardian/src/nbt/NBTTagLong.java b/MetroidMapGuardian/src/nbt/NBTTagLong.java new file mode 100644 index 0000000..d062032 --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagLong.java @@ -0,0 +1,103 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * A basic NBT element with a long value. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ +public class NBTTagLong extends NBTElement { + + // ======================= Members ======================== + + /** The long value of the element. */ + public long longValue; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a long with a value of 0 and + * an empty key. + * + * @return Returns a long of the value 0 with an empty key. + */ + public NBTTagLong() { + super(""); + this.longValue = 0; + } + /** + * Constructs a long of the value 0 with the given key. + * + * @param key - The key identifier of the tag. + * @return Returns a long of the value 0 with the given key. + */ + public NBTTagLong(String key) { + super(key); + this.longValue = 0; + } + /** + * Constructs a long with the given value and key. + * + * @param key - The key identifier of the tag. + * @param longValue - The value of the tag. + * @return Returns a long with the given value and key. + */ + public NBTTagLong(String key, long longValue) { + super(key); + this.longValue = longValue; + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + return super.toString(level) + String.valueOf(longValue) + "\n"; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + out.writeLong(longValue); + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + longValue = in.readLong(); + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_LONG; + } +} diff --git a/MetroidMapGuardian/src/nbt/NBTTagShort.java b/MetroidMapGuardian/src/nbt/NBTTagShort.java new file mode 100644 index 0000000..436b992 --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagShort.java @@ -0,0 +1,103 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * A basic NBT element with a short value. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ +public class NBTTagShort extends NBTElement { + + // ======================= Members ======================== + + /** The short value of the element. */ + public short shortValue; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a short with a value of 0 and + * an empty key. + * + * @return Returns a short of the value 0 with an empty key. + */ + public NBTTagShort() { + super(""); + this.shortValue = 0; + } + /** + * Constructs a short of the value 0 with the given key. + * + * @param key - The key identifier of the tag. + * @return Returns a short of the value 0 with the given key. + */ + public NBTTagShort(String key) { + super(key); + this.shortValue = 0; + } + /** + * Constructs a short with the given value and key. + * + * @param key - The key identifier of the tag. + * @param shortValue - The value of the tag. + * @return Returns a short with the given value and key. + */ + public NBTTagShort(String key, short shortValue) { + super(key); + this.shortValue = shortValue; + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + return super.toString(level) + String.valueOf(shortValue) + "\n"; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + out.writeShort(shortValue); + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + shortValue = in.readShort(); + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_SHORT; + } +} diff --git a/MetroidMapGuardian/src/nbt/NBTTagString.java b/MetroidMapGuardian/src/nbt/NBTTagString.java new file mode 100644 index 0000000..cf9d9fa --- /dev/null +++ b/MetroidMapGuardian/src/nbt/NBTTagString.java @@ -0,0 +1,102 @@ +package nbt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * A basic NBT element with a string value. + * + * @author Markus Persson + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ +public class NBTTagString extends NBTElement { + + // ======================= Members ======================== + + /** The string value of the element. */ + public String stringValue; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs an empty string and an empty key. + * + * @return Returns an empty string with an empty key. + */ + public NBTTagString() { + super(""); + this.stringValue = ""; + } + /** + * Constructs an empty string with the given key. + * + * @param key - The key identifier of the tag. + * @return Returns an empty string with the given key. + */ + public NBTTagString(String key) { + super(key); + this.stringValue = ""; + } + /** + * Constructs a string with the given value and key. + * + * @param key - The key identifier of the tag. + * @param stringValue - The value of the tag. + * @return Returns a string with the given value and key. + */ + public NBTTagString(String key, String stringValue) { + super(key); + this.stringValue = stringValue; + } + + // ================= Implemented Methods ================== + + /** + * Returns the string representation of the tag. + * + * @return Returns the string representation of the tag. + */ + public String toString() { + return toString(0); + } + /** + * Returns the string representation of the tag with level spacing. + * + * @param level - The compound level of the tag. + * @return Returns the string representation of the tag with level spacing. + */ + public String toString(int level) { + return super.toString(level) + "\"" + stringValue + "\"" + "\n"; + } + + /** + * Writes the contents of the tag to the output stream. + * + * @param out - The output stream to write the contents to. + * @throws IOException + */ + void writeTagContents(DataOutput out) throws IOException { + out.writeUTF(stringValue); + } + /** + * Reads the contents of the tag from the input stream. + * + * @param in - The input stream to read the contents from. + * @throws IOException + */ + void readTagContents(DataInput in) throws IOException { + stringValue = in.readUTF(); + } + /** + * Returns the type of the tag. + * + * @return Returns the type of the tag. + */ + public byte getType() { + return NBTElement.TAG_STRING; + } +} diff --git a/MetroidMapGuardian/src/resources/data/map.dat b/MetroidMapGuardian/src/resources/data/map.dat new file mode 100644 index 0000000..b12cd42 Binary files /dev/null and b/MetroidMapGuardian/src/resources/data/map.dat differ diff --git a/MetroidMapGuardian/src/resources/fonts/crystal_clear.ttf b/MetroidMapGuardian/src/resources/fonts/crystal_clear.ttf new file mode 100644 index 0000000..a9d5d7f Binary files /dev/null and b/MetroidMapGuardian/src/resources/fonts/crystal_clear.ttf differ diff --git a/MetroidMapGuardian/src/resources/fonts/eurostar.ttf b/MetroidMapGuardian/src/resources/fonts/eurostar.ttf new file mode 100644 index 0000000..ba18cc1 Binary files /dev/null and b/MetroidMapGuardian/src/resources/fonts/eurostar.ttf differ diff --git a/MetroidMapGuardian/src/resources/fonts/eurostar_black.ttf b/MetroidMapGuardian/src/resources/fonts/eurostar_black.ttf new file mode 100644 index 0000000..8cf7d7b Binary files /dev/null and b/MetroidMapGuardian/src/resources/fonts/eurostar_black.ttf differ diff --git a/MetroidMapGuardian/src/resources/fonts/eurostar_black_extended.ttf b/MetroidMapGuardian/src/resources/fonts/eurostar_black_extended.ttf new file mode 100644 index 0000000..4965075 Binary files /dev/null and b/MetroidMapGuardian/src/resources/fonts/eurostar_black_extended.ttf differ diff --git a/MetroidMapGuardian/src/resources/fonts/eurostar_regular_extended.ttf b/MetroidMapGuardian/src/resources/fonts/eurostar_regular_extended.ttf new file mode 100644 index 0000000..f74f9ba Binary files /dev/null and b/MetroidMapGuardian/src/resources/fonts/eurostar_regular_extended.ttf differ diff --git a/MetroidMapGuardian/src/resources/fonts/zero_threes.ttf b/MetroidMapGuardian/src/resources/fonts/zero_threes.ttf new file mode 100644 index 0000000..9d2beb8 Binary files /dev/null and b/MetroidMapGuardian/src/resources/fonts/zero_threes.ttf differ diff --git a/MetroidMapGuardian/src/resources/images/artifact.png b/MetroidMapGuardian/src/resources/images/artifact.png new file mode 100644 index 0000000..5386bd4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/artifact.png differ diff --git a/MetroidMapGuardian/src/resources/images/beam_ammo_expansion.png b/MetroidMapGuardian/src/resources/images/beam_ammo_expansion.png new file mode 100644 index 0000000..6b34f37 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/beam_ammo_expansion.png differ diff --git a/MetroidMapGuardian/src/resources/images/boss.png b/MetroidMapGuardian/src/resources/images/boss.png new file mode 100644 index 0000000..cc95dca Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/boss.png differ diff --git a/MetroidMapGuardian/src/resources/images/checked.png b/MetroidMapGuardian/src/resources/images/checked.png new file mode 100644 index 0000000..741096d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/checked.png differ diff --git a/MetroidMapGuardian/src/resources/images/dark_temple_key.png b/MetroidMapGuardian/src/resources/images/dark_temple_key.png new file mode 100644 index 0000000..11cbd68 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/dark_temple_key.png differ diff --git a/MetroidMapGuardian/src/resources/images/energy_cell.png b/MetroidMapGuardian/src/resources/images/energy_cell.png new file mode 100644 index 0000000..085be0d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/energy_cell.png differ diff --git a/MetroidMapGuardian/src/resources/images/energy_tank.png b/MetroidMapGuardian/src/resources/images/energy_tank.png new file mode 100644 index 0000000..8897583 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/energy_tank.png differ diff --git a/MetroidMapGuardian/src/resources/images/icon.ico b/MetroidMapGuardian/src/resources/images/icon.ico new file mode 100644 index 0000000..5f5f9b9 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/icon.ico differ diff --git a/MetroidMapGuardian/src/resources/images/icon128.png b/MetroidMapGuardian/src/resources/images/icon128.png new file mode 100644 index 0000000..284d9a5 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/icon128.png differ diff --git a/MetroidMapGuardian/src/resources/images/icon16.png b/MetroidMapGuardian/src/resources/images/icon16.png new file mode 100644 index 0000000..6cc7e83 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/icon16.png differ diff --git a/MetroidMapGuardian/src/resources/images/icon24.png b/MetroidMapGuardian/src/resources/images/icon24.png new file mode 100644 index 0000000..19f9357 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/icon24.png differ diff --git a/MetroidMapGuardian/src/resources/images/icon32.png b/MetroidMapGuardian/src/resources/images/icon32.png new file mode 100644 index 0000000..c62eb08 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/icon32.png differ diff --git a/MetroidMapGuardian/src/resources/images/icon48.png b/MetroidMapGuardian/src/resources/images/icon48.png new file mode 100644 index 0000000..bc6741f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/icon48.png differ diff --git a/MetroidMapGuardian/src/resources/images/icon64.png b/MetroidMapGuardian/src/resources/images/icon64.png new file mode 100644 index 0000000..967b087 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/icon64.png differ diff --git a/MetroidMapGuardian/src/resources/images/icon96.png b/MetroidMapGuardian/src/resources/images/icon96.png new file mode 100644 index 0000000..a4d7541 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/icon96.png differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/001.jpg new file mode 100644 index 0000000..e66f1d4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/002.jpg new file mode 100644 index 0000000..b2f0f7c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/003.jpg new file mode 100644 index 0000000..74bb2d3 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/004.jpg new file mode 100644 index 0000000..12339d8 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/005.jpg new file mode 100644 index 0000000..63c7818 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/006.jpg new file mode 100644 index 0000000..99285a7 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/007.jpg new file mode 100644 index 0000000..6fc74d1 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/008.jpg new file mode 100644 index 0000000..365d59f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/009.jpg new file mode 100644 index 0000000..5f0271a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/010.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/010.jpg new file mode 100644 index 0000000..bf565d7 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/010.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/011.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/011.jpg new file mode 100644 index 0000000..06811d9 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/011.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/012.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/012.jpg new file mode 100644 index 0000000..a21e1e1 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/artifacts/012.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/001.jpg new file mode 100644 index 0000000..a634095 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/002.jpg new file mode 100644 index 0000000..fd72a17 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/003.jpg new file mode 100644 index 0000000..e53ec75 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/004.jpg new file mode 100644 index 0000000..1ec1489 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/005.jpg new file mode 100644 index 0000000..f2ec7bd Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/006.jpg new file mode 100644 index 0000000..610548b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/007.jpg new file mode 100644 index 0000000..76978a0 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/008.jpg new file mode 100644 index 0000000..a287d52 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/009.jpg new file mode 100644 index 0000000..ff6a0f9 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/010.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/010.jpg new file mode 100644 index 0000000..62bde2c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/010.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/011.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/011.jpg new file mode 100644 index 0000000..1f050f4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/011.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/012.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/012.jpg new file mode 100644 index 0000000..13ae5ab Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/012.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/013.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/013.jpg new file mode 100644 index 0000000..f1d32d3 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/013.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/014.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/014.jpg new file mode 100644 index 0000000..abf5428 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/energy_tanks/014.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/chozo_ruins.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/chozo_ruins.jpg new file mode 100644 index 0000000..5cdb1f6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/chozo_ruins.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/impact_crater.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/impact_crater.jpg new file mode 100644 index 0000000..9a12f93 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/impact_crater.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/magmoor_caverns.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/magmoor_caverns.jpg new file mode 100644 index 0000000..df008aa Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/magmoor_caverns.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/phazon_mines.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/phazon_mines.jpg new file mode 100644 index 0000000..bbaadbe Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/phazon_mines.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/phendrana_drifts.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/phendrana_drifts.jpg new file mode 100644 index 0000000..3ca9bae Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/phendrana_drifts.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/pirate_frigate.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/pirate_frigate.jpg new file mode 100644 index 0000000..7275be7 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/pirate_frigate.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/tallon_overworld.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/tallon_overworld.jpg new file mode 100644 index 0000000..2b0e487 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/maps/tallon_overworld.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/001.jpg new file mode 100644 index 0000000..3a4d103 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/002.jpg new file mode 100644 index 0000000..db6cdbb Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/003.jpg new file mode 100644 index 0000000..9275640 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/004.jpg new file mode 100644 index 0000000..89c8d3d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/005.jpg new file mode 100644 index 0000000..66cbd52 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/006.jpg new file mode 100644 index 0000000..b02b0a8 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/007.jpg new file mode 100644 index 0000000..b33f1ff Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/008.jpg new file mode 100644 index 0000000..ddc0f1e Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/009.jpg new file mode 100644 index 0000000..716084e Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/010.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/010.jpg new file mode 100644 index 0000000..1df1e24 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/010.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/011.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/011.jpg new file mode 100644 index 0000000..43b1753 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/011.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/012.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/012.jpg new file mode 100644 index 0000000..57ddf11 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/012.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/013.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/013.jpg new file mode 100644 index 0000000..7eeeed3 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/013.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/014.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/014.jpg new file mode 100644 index 0000000..8881a1f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/014.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/015.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/015.jpg new file mode 100644 index 0000000..12d1316 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/015.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/016.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/016.jpg new file mode 100644 index 0000000..aa8266f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/016.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/017.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/017.jpg new file mode 100644 index 0000000..6997417 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/017.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/018.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/018.jpg new file mode 100644 index 0000000..90f896b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/018.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/019.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/019.jpg new file mode 100644 index 0000000..cd1277f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/019.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/020.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/020.jpg new file mode 100644 index 0000000..b2f5435 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/020.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/021.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/021.jpg new file mode 100644 index 0000000..2925f2a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/021.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/022.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/022.jpg new file mode 100644 index 0000000..b40c9b2 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/022.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/023.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/023.jpg new file mode 100644 index 0000000..cc0f9c6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/023.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/024.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/024.jpg new file mode 100644 index 0000000..796547b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/024.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/025.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/025.jpg new file mode 100644 index 0000000..3b6be05 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/025.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/026.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/026.jpg new file mode 100644 index 0000000..3217797 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/026.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/027.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/027.jpg new file mode 100644 index 0000000..e308524 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/027.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/028.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/028.jpg new file mode 100644 index 0000000..8c273bb Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/028.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/029.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/029.jpg new file mode 100644 index 0000000..2d61750 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/029.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/030.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/030.jpg new file mode 100644 index 0000000..9455e0b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/030.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/031.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/031.jpg new file mode 100644 index 0000000..94a5bba Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/031.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/032.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/032.jpg new file mode 100644 index 0000000..968faa1 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/032.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/033.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/033.jpg new file mode 100644 index 0000000..f0a0c2d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/033.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/034.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/034.jpg new file mode 100644 index 0000000..bf9a612 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/034.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/035.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/035.jpg new file mode 100644 index 0000000..e48a9b5 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/035.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/036.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/036.jpg new file mode 100644 index 0000000..418f091 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/036.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/037.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/037.jpg new file mode 100644 index 0000000..33e97f0 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/037.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/038.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/038.jpg new file mode 100644 index 0000000..9279ad2 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/038.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/039.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/039.jpg new file mode 100644 index 0000000..288e778 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/039.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/040.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/040.jpg new file mode 100644 index 0000000..02f8850 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/040.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/041.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/041.jpg new file mode 100644 index 0000000..96bf746 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/041.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/042.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/042.jpg new file mode 100644 index 0000000..8b72714 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/042.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/043.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/043.jpg new file mode 100644 index 0000000..519e4c0 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/043.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/044.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/044.jpg new file mode 100644 index 0000000..ea9a078 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/044.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/045.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/045.jpg new file mode 100644 index 0000000..c9d905d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/045.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/046.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/046.jpg new file mode 100644 index 0000000..294888c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/046.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/047.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/047.jpg new file mode 100644 index 0000000..e7d9a28 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/047.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/048.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/048.jpg new file mode 100644 index 0000000..4d8cd16 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/048.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/049.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/049.jpg new file mode 100644 index 0000000..fe08a20 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/049.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/050.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/050.jpg new file mode 100644 index 0000000..f0cf9db Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/missile_expansions/050.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/001.jpg new file mode 100644 index 0000000..4d4049e Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/002.jpg new file mode 100644 index 0000000..361ec4a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/003.jpg new file mode 100644 index 0000000..882958f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/004.jpg new file mode 100644 index 0000000..6ecbf2d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/005.jpg new file mode 100644 index 0000000..f6cbaa6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/power_bombs/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/001.jpg new file mode 100644 index 0000000..1df1e24 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/002.jpg new file mode 100644 index 0000000..2d26bfb Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/003.jpg new file mode 100644 index 0000000..b86367d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/004.jpg new file mode 100644 index 0000000..adc98c6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/005.jpg new file mode 100644 index 0000000..6f80f3b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/006.jpg new file mode 100644 index 0000000..a55c121 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/007.jpg new file mode 100644 index 0000000..5359c62 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/008.jpg new file mode 100644 index 0000000..6e370da Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/009.jpg new file mode 100644 index 0000000..1923d47 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/010.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/010.jpg new file mode 100644 index 0000000..1358a0b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/010.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/011.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/011.jpg new file mode 100644 index 0000000..c869d82 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/011.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/012.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/012.jpg new file mode 100644 index 0000000..268bee2 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/012.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/013.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/013.jpg new file mode 100644 index 0000000..c6b7f8c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/013.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/014.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/014.jpg new file mode 100644 index 0000000..f6cbaa6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/014.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/015.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/015.jpg new file mode 100644 index 0000000..6ec4de8 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/015.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/016.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/016.jpg new file mode 100644 index 0000000..0b6099a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/016.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/017.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/017.jpg new file mode 100644 index 0000000..b4b9b7a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/017.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/018.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/018.jpg new file mode 100644 index 0000000..aa2ce96 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/018.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/019.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/019.jpg new file mode 100644 index 0000000..4ae3b9d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/019.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/020.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/020.jpg new file mode 100644 index 0000000..f7d7263 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/020.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/021.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/021.jpg new file mode 100644 index 0000000..09c136f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_1/suit_expansions/021.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/001.jpg new file mode 100644 index 0000000..7dd17dc Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/002.jpg new file mode 100644 index 0000000..ca506f2 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/003.jpg new file mode 100644 index 0000000..5b6a886 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/004.jpg new file mode 100644 index 0000000..4cf0964 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/beam_ammo_expansions/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/001.jpg new file mode 100644 index 0000000..ca05d75 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/002.jpg new file mode 100644 index 0000000..3b8e445 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/003.jpg new file mode 100644 index 0000000..0c259a6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/004.jpg new file mode 100644 index 0000000..f24f4bb Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/005.jpg new file mode 100644 index 0000000..d400cbb Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/006.jpg new file mode 100644 index 0000000..050bd8c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/007.jpg new file mode 100644 index 0000000..2d8dc7f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/008.jpg new file mode 100644 index 0000000..eee3687 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/009.jpg new file mode 100644 index 0000000..c5f9ee7 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/dark_temple_keys/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/001.jpg new file mode 100644 index 0000000..41819f9 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/002.jpg new file mode 100644 index 0000000..2af1f55 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/003.jpg new file mode 100644 index 0000000..c12cfe7 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/004.jpg new file mode 100644 index 0000000..e1784c2 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/005.jpg new file mode 100644 index 0000000..1e1a8d9 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/006.jpg new file mode 100644 index 0000000..d76fd29 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/007.jpg new file mode 100644 index 0000000..21c0ad3 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/008.jpg new file mode 100644 index 0000000..801698c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/009.jpg new file mode 100644 index 0000000..7bb9019 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/010.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/010.jpg new file mode 100644 index 0000000..8509df2 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/010.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/011.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/011.jpg new file mode 100644 index 0000000..6f978c8 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/011.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/012.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/012.jpg new file mode 100644 index 0000000..a66a94c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/012.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/013.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/013.jpg new file mode 100644 index 0000000..2d76713 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/013.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/014.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/014.jpg new file mode 100644 index 0000000..5849a76 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/energy_tanks/014.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_agon_wastes.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_agon_wastes.jpg new file mode 100644 index 0000000..ad1344a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_agon_wastes.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_ing_hive.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_ing_hive.jpg new file mode 100644 index 0000000..b39dee0 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_ing_hive.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_temple_grounds.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_temple_grounds.jpg new file mode 100644 index 0000000..d6cd6e8 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_temple_grounds.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_torvus_bog.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_torvus_bog.jpg new file mode 100644 index 0000000..c4dc54d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/dark_torvus_bog.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/great_temple.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/great_temple.jpg new file mode 100644 index 0000000..677c310 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/great_temple.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_agon_wastes.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_agon_wastes.jpg new file mode 100644 index 0000000..37eec35 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_agon_wastes.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_sanctuary_fortress.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_sanctuary_fortress.jpg new file mode 100644 index 0000000..3025ae6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_sanctuary_fortress.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_temple_grounds.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_temple_grounds.jpg new file mode 100644 index 0000000..1d659c6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_temple_grounds.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_torvus_bog.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_torvus_bog.jpg new file mode 100644 index 0000000..b2489f5 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/maps/light_torvus_bog.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/001.jpg new file mode 100644 index 0000000..a3a2b06 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/002.jpg new file mode 100644 index 0000000..df08b63 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/003.jpg new file mode 100644 index 0000000..21acaac Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/004.jpg new file mode 100644 index 0000000..6fd8c2d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/005.jpg new file mode 100644 index 0000000..ec4674a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/006.jpg new file mode 100644 index 0000000..f961c48 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/007.jpg new file mode 100644 index 0000000..191d3db Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/008.jpg new file mode 100644 index 0000000..d0ca603 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/009.jpg new file mode 100644 index 0000000..a243e9c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/010.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/010.jpg new file mode 100644 index 0000000..844af75 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/010.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/011.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/011.jpg new file mode 100644 index 0000000..80666f0 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/011.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/012.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/012.jpg new file mode 100644 index 0000000..b73cc18 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/012.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/013.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/013.jpg new file mode 100644 index 0000000..3b49edf Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/013.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/014.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/014.jpg new file mode 100644 index 0000000..b248291 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/014.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/015.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/015.jpg new file mode 100644 index 0000000..0bb8ff5 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/015.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/016.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/016.jpg new file mode 100644 index 0000000..2c190e8 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/016.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/017.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/017.jpg new file mode 100644 index 0000000..9833e85 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/017.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/018.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/018.jpg new file mode 100644 index 0000000..7b34f1d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/018.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/019.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/019.jpg new file mode 100644 index 0000000..9e76aef Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/019.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/020.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/020.jpg new file mode 100644 index 0000000..90924f9 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/020.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/021.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/021.jpg new file mode 100644 index 0000000..5a48c8c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/021.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/022.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/022.jpg new file mode 100644 index 0000000..93704ac Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/022.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/023.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/023.jpg new file mode 100644 index 0000000..8a4cfd0 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/023.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/024.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/024.jpg new file mode 100644 index 0000000..ac69b6f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/024.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/025.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/025.jpg new file mode 100644 index 0000000..d185ae8 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/025.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/026.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/026.jpg new file mode 100644 index 0000000..f34a8d4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/026.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/027.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/027.jpg new file mode 100644 index 0000000..dc1dff3 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/027.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/028.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/028.jpg new file mode 100644 index 0000000..0cfc067 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/028.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/029.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/029.jpg new file mode 100644 index 0000000..7f723a7 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/029.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/030.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/030.jpg new file mode 100644 index 0000000..a953eb4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/030.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/031.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/031.jpg new file mode 100644 index 0000000..1c83055 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/031.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/032.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/032.jpg new file mode 100644 index 0000000..d450624 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/032.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/033.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/033.jpg new file mode 100644 index 0000000..b0daf52 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/033.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/034.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/034.jpg new file mode 100644 index 0000000..4757469 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/034.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/035.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/035.jpg new file mode 100644 index 0000000..3383d9d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/035.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/036.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/036.jpg new file mode 100644 index 0000000..60dea63 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/036.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/037.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/037.jpg new file mode 100644 index 0000000..daa143f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/037.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/038.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/038.jpg new file mode 100644 index 0000000..f976e4a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/038.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/039.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/039.jpg new file mode 100644 index 0000000..3794206 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/039.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/040.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/040.jpg new file mode 100644 index 0000000..f0db50c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/040.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/041.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/041.jpg new file mode 100644 index 0000000..f5df295 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/041.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/042.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/042.jpg new file mode 100644 index 0000000..ff0dc38 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/042.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/043.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/043.jpg new file mode 100644 index 0000000..0d49567 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/043.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/044.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/044.jpg new file mode 100644 index 0000000..e4a9525 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/044.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/045.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/045.jpg new file mode 100644 index 0000000..b0c5972 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/045.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/046.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/046.jpg new file mode 100644 index 0000000..fc61838 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/046.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/047.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/047.jpg new file mode 100644 index 0000000..b6879ce Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/047.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/048.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/048.jpg new file mode 100644 index 0000000..20a88e5 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/048.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/049.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/049.jpg new file mode 100644 index 0000000..d559aec Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/049.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/050.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/050.jpg new file mode 100644 index 0000000..5c0c5d7 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/missile_expansions/050.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/001.jpg new file mode 100644 index 0000000..9b09e53 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/002.jpg new file mode 100644 index 0000000..964f21e Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/003.jpg new file mode 100644 index 0000000..f997543 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/004.jpg new file mode 100644 index 0000000..bbc7a80 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/005.jpg new file mode 100644 index 0000000..8c13479 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/006.jpg new file mode 100644 index 0000000..97980e0 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/007.jpg new file mode 100644 index 0000000..9622235 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/008.jpg new file mode 100644 index 0000000..9626aa4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/009.jpg new file mode 100644 index 0000000..6a428c1 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/power_bombs/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/001.jpg new file mode 100644 index 0000000..9cd0e9d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/002.jpg new file mode 100644 index 0000000..272ebda Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/003.jpg new file mode 100644 index 0000000..9956b08 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/004.jpg new file mode 100644 index 0000000..2a16148 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/005.jpg new file mode 100644 index 0000000..8a20be9 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/006.jpg new file mode 100644 index 0000000..f39729b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/007.jpg new file mode 100644 index 0000000..560b620 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/008.jpg new file mode 100644 index 0000000..e3c13db Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/009.jpg new file mode 100644 index 0000000..1a271fc Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/sky_temple_keys/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/001.jpg new file mode 100644 index 0000000..a3a2b06 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/002.jpg new file mode 100644 index 0000000..4c1999d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/003.jpg new file mode 100644 index 0000000..f0b0053 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/004.jpg new file mode 100644 index 0000000..7a3b865 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/005.jpg new file mode 100644 index 0000000..a8ba8b0 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/006.jpg new file mode 100644 index 0000000..bc68f8c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/007.jpg new file mode 100644 index 0000000..7c57caa Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/008.jpg new file mode 100644 index 0000000..4cdfc20 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/009.jpg new file mode 100644 index 0000000..025970d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/010.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/010.jpg new file mode 100644 index 0000000..7d61c3b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/010.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/011.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/011.jpg new file mode 100644 index 0000000..d252400 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/011.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/012.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/012.jpg new file mode 100644 index 0000000..81548ce Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/012.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/013.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/013.jpg new file mode 100644 index 0000000..955ea9a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/013.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/014.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/014.jpg new file mode 100644 index 0000000..9b09e53 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/014.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/015.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/015.jpg new file mode 100644 index 0000000..92be1e4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/015.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/016.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/016.jpg new file mode 100644 index 0000000..9c21431 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/016.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/017.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/017.jpg new file mode 100644 index 0000000..3693dfb Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/017.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/018.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/018.jpg new file mode 100644 index 0000000..d345662 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/018.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/019.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/019.jpg new file mode 100644 index 0000000..27a852c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/019.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/020.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/020.jpg new file mode 100644 index 0000000..7fb8bc4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/020.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/021.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/021.jpg new file mode 100644 index 0000000..5510b77 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_2/suit_expansions/021.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/001.jpg new file mode 100644 index 0000000..ca812d2 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/002.jpg new file mode 100644 index 0000000..8735557 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/003.jpg new file mode 100644 index 0000000..c63ca14 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/004.jpg new file mode 100644 index 0000000..4c3b1a7 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/005.jpg new file mode 100644 index 0000000..43fb2a1 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/006.jpg new file mode 100644 index 0000000..796bc34 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/007.jpg new file mode 100644 index 0000000..4426c50 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/008.jpg new file mode 100644 index 0000000..a9f89c8 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/009.jpg new file mode 100644 index 0000000..626b066 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_cells/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/001.jpg new file mode 100644 index 0000000..3a1c3e7 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/002.jpg new file mode 100644 index 0000000..a78f044 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/003.jpg new file mode 100644 index 0000000..52e62b6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/004.jpg new file mode 100644 index 0000000..d639b48 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/005.jpg new file mode 100644 index 0000000..daa7e34 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/006.jpg new file mode 100644 index 0000000..4d99e8f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/007.jpg new file mode 100644 index 0000000..16f28c3 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/008.jpg new file mode 100644 index 0000000..6b055bf Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/009.jpg new file mode 100644 index 0000000..a777482 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/010.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/010.jpg new file mode 100644 index 0000000..5e9b9ab Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/010.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/011.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/011.jpg new file mode 100644 index 0000000..d0fd587 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/011.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/012.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/012.jpg new file mode 100644 index 0000000..9250226 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/012.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/013.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/013.jpg new file mode 100644 index 0000000..f4333ae Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/013.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/014.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/014.jpg new file mode 100644 index 0000000..cb7595b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/energy_tanks/014.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/bryyo.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/bryyo.jpg new file mode 100644 index 0000000..ab03097 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/bryyo.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/elysia.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/elysia.jpg new file mode 100644 index 0000000..27c0d9a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/elysia.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/gfs_olympus.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/gfs_olympus.jpg new file mode 100644 index 0000000..dfbcd9f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/gfs_olympus.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/gfs_valhalla.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/gfs_valhalla.jpg new file mode 100644 index 0000000..e89f4b5 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/gfs_valhalla.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/norion.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/norion.jpg new file mode 100644 index 0000000..5c4c666 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/norion.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/phaaze.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/phaaze.jpg new file mode 100644 index 0000000..ddd2ec1 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/phaaze.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/pirate_homeworld.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/pirate_homeworld.jpg new file mode 100644 index 0000000..1458613 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/maps/pirate_homeworld.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/001.jpg new file mode 100644 index 0000000..927ccf5 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/002.jpg new file mode 100644 index 0000000..c348db3 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/003.jpg new file mode 100644 index 0000000..c9506cc Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/004.jpg new file mode 100644 index 0000000..1175390 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/005.jpg new file mode 100644 index 0000000..e729fc8 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/006.jpg new file mode 100644 index 0000000..b105815 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/007.jpg new file mode 100644 index 0000000..5866c3d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/008.jpg new file mode 100644 index 0000000..2330e9a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/009.jpg new file mode 100644 index 0000000..21b8574 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/010.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/010.jpg new file mode 100644 index 0000000..759def4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/010.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/011.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/011.jpg new file mode 100644 index 0000000..a0ea5c6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/011.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/012.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/012.jpg new file mode 100644 index 0000000..2e1b91c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/012.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/013.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/013.jpg new file mode 100644 index 0000000..6fd451f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/013.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/014.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/014.jpg new file mode 100644 index 0000000..bac276c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/014.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/015.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/015.jpg new file mode 100644 index 0000000..c8de5ed Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/015.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/016.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/016.jpg new file mode 100644 index 0000000..7fea9d5 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/016.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/017.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/017.jpg new file mode 100644 index 0000000..7260e2b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/017.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/018.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/018.jpg new file mode 100644 index 0000000..cc28c48 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/018.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/019.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/019.jpg new file mode 100644 index 0000000..766251d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/019.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/020.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/020.jpg new file mode 100644 index 0000000..5579383 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/020.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/021.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/021.jpg new file mode 100644 index 0000000..f48b34f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/021.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/022.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/022.jpg new file mode 100644 index 0000000..fabc4cd Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/022.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/023.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/023.jpg new file mode 100644 index 0000000..5c3832b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/023.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/024.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/024.jpg new file mode 100644 index 0000000..f756b33 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/024.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/025.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/025.jpg new file mode 100644 index 0000000..e2c8070 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/025.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/026.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/026.jpg new file mode 100644 index 0000000..8d4e35b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/026.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/027.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/027.jpg new file mode 100644 index 0000000..02529c5 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/027.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/028.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/028.jpg new file mode 100644 index 0000000..20a82ff Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/028.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/029.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/029.jpg new file mode 100644 index 0000000..23f3690 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/029.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/030.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/030.jpg new file mode 100644 index 0000000..92818ed Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/030.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/031.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/031.jpg new file mode 100644 index 0000000..0558280 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/031.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/032.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/032.jpg new file mode 100644 index 0000000..7254654 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/032.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/033.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/033.jpg new file mode 100644 index 0000000..a38688a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/033.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/034.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/034.jpg new file mode 100644 index 0000000..20b96c2 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/034.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/035.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/035.jpg new file mode 100644 index 0000000..f33ffaf Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/035.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/036.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/036.jpg new file mode 100644 index 0000000..f79a755 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/036.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/037.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/037.jpg new file mode 100644 index 0000000..918a494 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/037.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/038.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/038.jpg new file mode 100644 index 0000000..3d560c4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/038.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/039.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/039.jpg new file mode 100644 index 0000000..2107b60 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/039.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/040.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/040.jpg new file mode 100644 index 0000000..5161386 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/040.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/041.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/041.jpg new file mode 100644 index 0000000..d5a287d Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/041.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/042.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/042.jpg new file mode 100644 index 0000000..7eb3459 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/042.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/043.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/043.jpg new file mode 100644 index 0000000..8757a60 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/043.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/044.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/044.jpg new file mode 100644 index 0000000..86224f4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/044.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/045.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/045.jpg new file mode 100644 index 0000000..46c006b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/045.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/046.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/046.jpg new file mode 100644 index 0000000..c026fe5 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/046.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/047.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/047.jpg new file mode 100644 index 0000000..5becb8b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/047.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/048.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/048.jpg new file mode 100644 index 0000000..e31f3a0 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/048.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/049.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/049.jpg new file mode 100644 index 0000000..16b503c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/049.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/050.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/050.jpg new file mode 100644 index 0000000..0020aa2 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/050.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/051.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/051.jpg new file mode 100644 index 0000000..8f63a8f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/missile_expansions/051.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/001.jpg new file mode 100644 index 0000000..b5f98a4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/002.jpg new file mode 100644 index 0000000..b269971 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/003.jpg new file mode 100644 index 0000000..ea5609a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/004.jpg new file mode 100644 index 0000000..4fb05d1 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/005.jpg new file mode 100644 index 0000000..374089b Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/006.jpg new file mode 100644 index 0000000..74016c6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/007.jpg new file mode 100644 index 0000000..a221ac2 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/008.jpg new file mode 100644 index 0000000..61fa40a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/009.jpg new file mode 100644 index 0000000..56bb259 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/ship_missile_expansions/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/001.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/001.jpg new file mode 100644 index 0000000..927ccf5 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/001.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/002.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/002.jpg new file mode 100644 index 0000000..79697cb Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/002.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/003.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/003.jpg new file mode 100644 index 0000000..cfc446c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/003.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/004.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/004.jpg new file mode 100644 index 0000000..8464e8f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/004.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/005.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/005.jpg new file mode 100644 index 0000000..0f729b7 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/005.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/006.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/006.jpg new file mode 100644 index 0000000..b5f98a4 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/006.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/007.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/007.jpg new file mode 100644 index 0000000..0703254 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/007.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/008.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/008.jpg new file mode 100644 index 0000000..eb7eb58 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/008.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/009.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/009.jpg new file mode 100644 index 0000000..30e3fd6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/009.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/010.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/010.jpg new file mode 100644 index 0000000..18371d6 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/010.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/011.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/011.jpg new file mode 100644 index 0000000..60ea815 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/011.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/012.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/012.jpg new file mode 100644 index 0000000..5177e36 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/012.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/013.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/013.jpg new file mode 100644 index 0000000..ee4a66a Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/013.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/014.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/014.jpg new file mode 100644 index 0000000..0f2dffe Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/014.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/015.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/015.jpg new file mode 100644 index 0000000..3be89ee Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/015.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/016.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/016.jpg new file mode 100644 index 0000000..e34f101 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/016.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/017.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/017.jpg new file mode 100644 index 0000000..d1e98f9 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/017.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/018.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/018.jpg new file mode 100644 index 0000000..c3a3568 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/018.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/019.jpg b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/019.jpg new file mode 100644 index 0000000..a076456 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/metroid_prime_3/suit_expansions/019.jpg differ diff --git a/MetroidMapGuardian/src/resources/images/missile_expansion.png b/MetroidMapGuardian/src/resources/images/missile_expansion.png new file mode 100644 index 0000000..d2525bd Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/missile_expansion.png differ diff --git a/MetroidMapGuardian/src/resources/images/power_bomb.png b/MetroidMapGuardian/src/resources/images/power_bomb.png new file mode 100644 index 0000000..5aa4bbb Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/power_bomb.png differ diff --git a/MetroidMapGuardian/src/resources/images/red_phazoid.png b/MetroidMapGuardian/src/resources/images/red_phazoid.png new file mode 100644 index 0000000..c24ae4c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/red_phazoid.png differ diff --git a/MetroidMapGuardian/src/resources/images/s_emblem128.png b/MetroidMapGuardian/src/resources/images/s_emblem128.png new file mode 100644 index 0000000..3725ee3 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/s_emblem128.png differ diff --git a/MetroidMapGuardian/src/resources/images/s_emblem64.png b/MetroidMapGuardian/src/resources/images/s_emblem64.png new file mode 100644 index 0000000..6ebc269 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/s_emblem64.png differ diff --git a/MetroidMapGuardian/src/resources/images/ship_missile_expansion.png b/MetroidMapGuardian/src/resources/images/ship_missile_expansion.png new file mode 100644 index 0000000..781856f Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/ship_missile_expansion.png differ diff --git a/MetroidMapGuardian/src/resources/images/sky_temple_key.png b/MetroidMapGuardian/src/resources/images/sky_temple_key.png new file mode 100644 index 0000000..47ef85c Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/sky_temple_key.png differ diff --git a/MetroidMapGuardian/src/resources/images/splash.png b/MetroidMapGuardian/src/resources/images/splash.png new file mode 100644 index 0000000..72cdf00 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/splash.png differ diff --git a/MetroidMapGuardian/src/resources/images/suit_expansion.png b/MetroidMapGuardian/src/resources/images/suit_expansion.png new file mode 100644 index 0000000..a44c981 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/suit_expansion.png differ diff --git a/MetroidMapGuardian/src/resources/images/unchecked.png b/MetroidMapGuardian/src/resources/images/unchecked.png new file mode 100644 index 0000000..a559d18 Binary files /dev/null and b/MetroidMapGuardian/src/resources/images/unchecked.png differ diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_1/artifacts.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_1/artifacts.txt new file mode 100644 index 0000000..59f76ee --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_1/artifacts.txt @@ -0,0 +1,48 @@ +001 +Truth +Artifact Temple +The first artifact. You'll find this one in plain view resting at the center of all the totem statues. +002 +Chozo +Life Grove +This artifact can be found in the same room as the X-Ray Visor. Out in the main open area of the room, you'll have to face three Chozo Ghosts before leaving. Once they're finished, go over to the large pool and jump in. Bomb the small circular metal cover plate to raise up a pillar. At the base of the pillar's a Spinner, use it to wind a metal platform around to raise up a structure. Within the structure a small alcove containing the artifact will reveal itself. +003 +Lifegiver +Tower Chamber +You'll find this artifact beyond the Tower of Light (the room where you found the Wavebuster), but you need the Gravity Suit to move freely underwater. Hidden underwater at the base of the tower is a tunnel leading on, head through and up through the door in the roof to find this artifact hidden in a tiny room. +004 +Wild +Sunchamber +Back in the giant room where you faced Flaahgra (you'll need to access it via the Sun Tower room, as vines are blocking the other entrance), three Chozo Ghosts will be waiting to challenge you. Send all three to the afterlife (the X-Ray Visor really helps) and the artifact will appear above Flaahgra's remains. +005 +World +Elder Chamber +In the Hall of the Elders you'll need the Plasma Beam to access the third lock mechanism. Once it's active, the Chozo Statue will grid forward, revealing a hidden door below it. Go down below to find this artifact waiting in a small room. +006 +Nature +Lava Lake +In this large lava-filled cavern you should spot a large rocky pillar in the center of one of the two lakes. Blast it with missiles or a Super Missile to blow it open and reveal the artifact hidden inside. Use the Space Jump Boots to reach it. +007 +Strength +Warrior Shrine +Access this room via the Monitor Station. Here's how to reach that door high up along the cavern wall. Get up to the top of the large structure in the Monitor Station with help from the Space Jump Boots, then use the Spinner to raise up a metal bridge. Jump over to the rocky ledge on the far side then simply stroll around to the door. Once inside, the large Chozo Statue and artifact will be waiting for you atop a throne ahead. +008 +Elder +Control Tower +This artifact is waiting for you at the highest point of Tallon IV you'll be exploring. Clear all the Flying Pirates in the area first, then go over to the tower above the door leading down to the East Tower. Inside you'll find a stack of crates, blow them open to find an ice-covered window hidden behind. Use the Plasma Beam to melt the ice, then fire a missile through the window aimed at the base of the tall tower visible just beyond. The tower will collapse, taking out part of the wall section in the main area of the region. Go through the ruined wall to find this artifact waiting at the base of the tower. +009 +Sun +Chozo Ice Temple +On the way to the room containing the Wave Beam, you'll find a giant winged Chozo Statue in the Chozo Ice Temple. Melt the ice pouring out of the statue's mouth with the Plasma Beam, then jump onto the statue's hands and activate the Morph Ball to reveal an opening at the base of the bowl. Roll through to find this artifact inside. +010 +Spirit +Storage Cave +The room concealing this artifact lives all the way over in the isolated Phendrana's Edge area. At the very top of this circular region near the entrance leading to a hidden Power Bomb, use the X-Ray Visor to reveal a door hidden behind a rock wall. Blow down the wall with a Power Bomb and head through to find the artifact inside. +011 +Warrior +Elite Research +Use a Power Bomb in this room to blow open the large capsule containing the huge Phazon Elite. I know it's a bad idea releasing the ugly beast, but you'll need to defeat it to find this artifact. Use maximum firepower against it and you shouldn't have much trouble, but if you need more help check the bosses guide. Defeat the beast to earn this artifact. +012 +Newborn +Phazon Mining Tunnel +Deep down in the bowels of the Mines you'll find yourself in a circular shaft filled with narrow tunnels. At the bottom is a tunnel leading on covered with deadly Phazon, so you'll need the Phazon Suit to get through alive. Hidden at the very bottom of the winding tunnels is this final artifact. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_1/energy_tanks.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_1/energy_tanks.txt new file mode 100644 index 0000000..d1ebcce --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_1/energy_tanks.txt @@ -0,0 +1,56 @@ + +001 +Cargo Freight Lift To Deck Gamma +Within the ruins of the Space Pirate Frigate, once you reach this now-underwater elevator shaft you'll spot this Energy Tank concealed within the wrecked elevator. Blast open the metal door with a missile to reach the Energy Tank. + +002 +Hydro Access Tunnel +Again within the ruined frigate, in this room you'll need to time your bombs so that each blast will propel Samus further up in the underwater environment. Practice the technique a few times, then use bombs to reach the Energy Tank hidden way up the shaft halfway through the region. + +003 +Main Plaza +You'll be able to reach this Energy Tank when accessing this area via the Vault. + +004 +Transport Access North +You'll get this straight after finding your first missile. Head through the door behind the remains of the Hive Mecha to find this Energy Tank waiting there. + +005 +Furnace +Go through the small opening next to the Spider Ball track to eventually reach a large enclosed canister in the Furnace. The Energy Tank's waiting inside in clear view. + +006 +Hall of the Elders +You'll need the Ice Beam to activate the second of the three locks in this room. With the second lock active, the Chozo Statue will send you down to a small room containing the Energy Tank. + +007 +Training Chamber +Once you've dealt with the Chozo Ghosts in this room, use the Boost Ball to boost up to the Morph Ball Slot high up on the wall (the other slot opens up an entrance leading out of this room). Once active the slot will call down an elevator near the exit of the room, quickly head over to it then follow the Spider Ball track above to find the Energy Tank concealed within in a small room. + +008 +Transport Tunnel A +In this narrow tunnel-filled room leading to a Phendrana elevator, from the entrance you'll need to successfully perform three double-bomb jumps to reach the Energy Tank high up in the tunnel network. It'll take some practice, refer to the hints section for more info on double-bomb jumping. + +009 +Magmoor Workstation +In this room you'll need to charge three electrical conduits to power up the large lava pump (use the Thermal Visor to see them - one's alongside each of the three sealed doors). Once active, go down below the grate to reach the lava-cooled rooms to activate further consoles. Once you reach the third room you'll find this Energy Tank there. + +010 +Ruined Courtyard +Activate two Morph Ball Slots and a Spinner device to raise the water level in this area, then head over to the small opening in the far wall not normally reachable when the water's at its lowest level. Use the Morph Ball to reach a hidden room below containing this Energy Tank. + +011 +Research Lab Aether +This Energy Tank's hidden within a glass container on the ground floor. Break the container open with a single missile to reach it. + +012 +Transport Access +You'll easily spot this Energy Tank concealed within a tunnel blocked with ice. Use the Plasma Beam to break through the ice to reach it. + +013 +Ventilation Shaft +Use a Power Bomb to break through a grate near one of the large fans (you'll have to be quick to avoid the poison gas) then activate the console behind the fan to turn it on. The Puffers and gas will be blown into the opposite fan, destroying it and revealing this Energy Tank hiding beyond. + +014 +Processing Center Access +Once you've conquered the Omega Pirate, head through the red door above on the platforms to find this Energy Tank waiting in the next chamber. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_1/maps.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_1/maps.txt new file mode 100644 index 0000000..28abb81 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_1/maps.txt @@ -0,0 +1,27 @@ +001 +pirate_frigate +Pirate Frigate + +002 +tallon_overworld +Tallon Overworld + +003 +chozo_ruins +Chozo Ruins + +004 +magmoor_caverns +Magmoor Caverns + +005 +phendrana_drifts +Phendrana Drifts + +006 +phazon_mines +Phazon Mines + +007 +impact_crater +Impact Crater diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_1/missile_expansions.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_1/missile_expansions.txt new file mode 100644 index 0000000..f779ec4 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_1/missile_expansions.txt @@ -0,0 +1,200 @@ +Tallon Overworld +001 +Landing Site +You'll need the Morph Ball to reach this one. Check under a small alcove filled with Tangle Weeds right behind Samus' ship for this missile. + +002 +Transport Tunnel B +This one's easy, just check under the rocky bridge and you'll find the missile hidden in the dust and dirt. + +003 +Overgrown Cavern +You'll spot this one hidden among a swarm of Venom Weed in the cavern. Reach this area by taking the elevator down from the Chozo Ruins near the Reflecting Pool room (specifically the Tallon Overworld East elevator). + +004 +Frigate Crash Site +This one's hidden up high in a small underwater cave near the large tangled tree roots. You'll need the Gravity Suit to reach it successfully. + +005 +Biohazard Containment +Use the Scan Visor down below in the underwater region of this room to find a Cordite door along the wall. Use a Super Missile to break the door open, revealing this missile waiting inside. + +006 +Arbor Chamber +Use the Grapple Beam in the giant Root Cave room to reach the upper part of the chamber. Once above use the X-Ray Visor to reveal invisible platforms, then simply use them to climb up to the red door above. Head inside to find this missile. + +007 +Root Cave +On the way up to the Arbor Chamber room (the Grapple Beam's required), use the X-Ray Visor to reveal a hidden alcove in the wall concealed by vines. Jump inside to find this missile. + +008 +Great Tree Chamber +In the upper area of the Great Tree Hall, there's an invisible platform suspended in mid-air leading up to a door. Use the X-Ray Visor to see it, or watch for an area in the air where the rain drops are falling on the platform. Use it to reach the door on the far wall, then head inside to find this missile. + +009 +Life Grove Tunnel +Accessed via the Great Tree Hall, once inside use the Morph Ball to reach an underground "O" shaped tunnel. Use the Boost Ball to reach the top of the "O", then bomb the middle of the ground to fall through and find this hidden missile. +Chozo Ruins +010 +Hive Totem +This will be your first missile - the Missile Launcher. Check the walkthrough for more details and while you're at it check the bosses guide for tips on defeating the Hive Mecha. + +011 +Main Plaza +This missile's hidden in a small alcove above the large half-pipe. Use the Boost Ball to reach it easily. + +012 +Main Plaza +Accessed from the Training Chamber room, use the Grapple Beam to reach this missile on the opposite side as you enter the region. + +013 +Main Plaza +On the large tree here you'll spot a huge knot which can be scanned. Blast it open with a Super Missile to reveal the hidden missile inside. + +014 +Ruined Nursery +This missile's waiting beyond narrow tunnels carved in the walls of this room. Use the Morph Ball and bombs to blow apart the metal blocks to open up a path leading to the missile. + +015 +Ruined Gallery +On the right wall of this room (as you enter) you'll spot two small openings. Use the Morph Ball to enter the narrow tunnel to find this missile hiding inside. + +016 +Ruined Gallery +Use a single missile to break through a weakened wall across the shallow Blastcap-infested pond (below the door) to reveal this missile. + +017 +Ruined Shrine +Use the Boost Ball to reach a small opening high up on the left wall (facing the alcove where the Morph Ball was), head inside to find the missile in a small chamber. + +018 +Ruined Shrine +On the right wall of this room (when facing the small alcove where the Morph Ball was), use a bomb to break through into a small tunnel leading to this missile. + +019 +Vault +In this large room you'll need to lay a bomb in each of the three locks on the large metal gate to open up the cage surrounding this missile. Use a double-bomb jump (check the hints section for more info) to reach the highest lock. + +020 +Ruined Fountain +In this room you should spot a Spider Ball track running across the roof and walls. Use the fountain to propel Samus up to the track while in Morph Ball mode, then follow it to the missile hidden within the wall. + +021 +Gathering Hall +At the very top of this room you'll need the Space Jump Boots to reach the top of the roof where all the Shriekbats are hanging. Blow open the metal grate above with a bomb to reach the concealed missile. You'll also be able to use the double-bomb jump trick to get up there, but it's tricky. + +022 +Watery Hall Access +Use a missile at the foot of the stairs in this room to break through the crumbling wall to find this missile. + +023 +Watery Hall +Once you've defeated Flaahgra, use the Gravity Suit to find an underwater tunnel in this room. Go through to find a hidden room containing this missile. + +024 +Burn Dome +Once you've whacked the Incinerator Drone, use a bomb to break through the small sandstone wall to find this missile hidden in a small chamber beyond. + +025 +Furnace +Use a Power Bomb at one side of this room below the Spider Ball tracks to reveal a half-pipe hidden below. Use the Boost Ball to reach the Spider track above, then carefully make your way up to the highest point of the room where the missile waits. Use regular bombs on the Plated Parasites to avoid being knocked off. + +026 +Dynamo +In this room, blast open the grating on the wall opposite the door to reach the missile concealed in a small alcove. + +027 +Dynamo +Climb up the Spider Ball track (watch out for the Plazmite) to reach this missile hiding above in a tiny alcove. + +028 +Crossway +Blow open the small Cordite casing covering a console beyond the half-pipe in this room. Scan the console, then use the Boost Ball to reach both Morph Ball Slots via the half-pipe and Spider Ball tracks. Once both slots are active, drop down and ride up the automatic elevator to reach this missile. + +029 +Training Chamber Access +Near the door of this room you'll spot a large tree covering most of the wall behind it. Activate Morph Ball mode and roll through the tree, revealing a concealed tunnel leading to this missile. +Magmoor Caverns +030 +Storage Cavern +In the Triclops Pit, use the Morph Ball to reach the area under the floor grating where all the Triclops are wandering around. Maneuver around them to reach a small opening on the far side of the room (the opposite side from the lava), then head through the door you'll find to locate this missile. + +031 +Triclops Pit +This time you'll need the Space Jump Boots and X-Ray Visor. In the Triclops Pit, use the X-Ray Visor to locate several invisible platforms hanging in mid air. Jump across them to reach a large blank rocky pillar. Shoot open the pillar with a missile to reveal this missile hiding inside. + +032 +Fiery Shores +All you'll need here is the Morph Ball and bomb to reach this one. In one corner of the lava lake you'll spot a series of raised catwalks, with the missile waiting at the end of one. Get up to the catwalk with bombs then carefully roll along them to reach the missile. +Phendrana Drifts +033 +Phendrana Shorelines +You'll find this missile hidden in a corner of the Phendrana Shorelines, encased in ice within a pillar. Use the Plasma Beam to break through the ice to reach it. + +034 +Phendrana Shorelines +Up on the ledge where the temple structure resides, use the Scan Visor to reveal a weakened statue cover. Blow it open with a Super Missile and scan the console underneath to open up a Spider Ball track on the tower to the left. Use the Spider Ball to reach the missile at the top of the small tower. + +035 +Ice Ruins East +Up in one of the corners of this area among the ruined buildings you should spot a hidden Spider Ball track. Follow the track to find this missile hiding in a narrow tunnel above. + +036 +Ice Ruins East +Just around the corner from the entrance of this region you should find a small cave with an ice sheet blocking the entrance (follow the humming sound to find it). Blast open the ice with the Plasma Beam to find the missile waiting inside. + +037 +Research Lab Hydra +Up on the top floor of this research lab you'll find a large cylindrical container which once scanned reveals fractures present in its casing. Break it open with a Super Missile to find this missile hiding inside. + +038 +Research Lab Aether +Around halfway up this lab you should spot the missile tucked away beyond a series of narrow catwalks. Use the Morph Ball and carefully roll along the catwalks to reach the missile. + +039 +Frost Cave +In this large cave you'll need the Grapple Beam to reach the highest point of the cavern (it's hidden within a stalactite). Once at the top shoot out the highest stalactite in the room, which once dislodged will plummet down and break open the ice lake below. Jump down into the water to reach this submerged missile. + +040 +Gravity Chamber +You'll need the Grapple Beam and Plasma Beam for this one. Up above the area where you find the Gravity Suit you'll spot a giant ice stalactite in the roof above. Blast it with the Plasma Beam to reveal a Grapple Point hidden within. Use the Grapple Beam to reach the missile up in the small alcove. + +041 +Quarantine Monitor +You'll need the Grapple Beam for this one. In the Quarantine Cave where you fought Thardus, use the Spider Ball to reach the door leading off to the elevator beyond. From here, use the Grapple Points leading over to an entrance on the far side of the room. Head through to find this missile waiting inside. +Phazon Mines +042 +Main Quarry +In the giant Main Quarry area, clear off all the Pirates in the area, then head up to the top of the large structure where the crane is. Use the Thermal Visor to find an electrical conduit and charge it with the Wave Beam. Scan the console inside the command room to activate the crane. The crane swings around and breaks open a wall, revealing the missile, so head up there via the Spider Ball tracks along the crane to reach it. + +043 +Security Access A +You'll need to break open a weakened metal wall with a Power Bomb to find this missile. Use your Scan Visor to find the damaged wall section. + +044 +Elite Research +At the top of this room, use the Spinner to aim the industrial laser at the final wall it faces while rotating in a clockwise direction. Activate the beam to blast open the wall and reveal this missile. + +045 +Elite Control Access +Not far from the door of this corridor you'll spot a crate up on a ledge above. Shoot the crate and it'll blow out a wall section behind, revealing this missile (and taking down two Pirates hidden in ceiling sections further along). + +046 +Phazon Processing Center +In this massive chamber you should spot a platform with a few crates resting up against the far wall (the wall opposite the one with the red door at the bottom). Head over there, then if you use the X-Ray Visor you'll spot this missile hidden behind a wall section. Rip it open with a Power Bomb to find this missile. + +047 +Metroid Quarantine A +This missile's waiting high up at the top of the dark cavernous part of this room. Once you reach the Spider Ball tracks leading up to the door at the far side, scan around to find a weakened rock wall. Use a Power Bomb on this wall and the next one to reach a Spider Ball track leading to the other side of the room over the Phazon pool below. Go across, then use the X-Ray Visor to see the invisible platform. Ride it up to reach this missile. + +048 +Fungal Hall Access +At the very bottom of this room the missile is hiding below a large fungal mushroom. Although you'll need the Phazon Suit to avoid taking serious damage from walking all over the Phazon coating the floor. + +049 +Fungal Hall B +Near the door leading out of this room, use a bomb on the ground in front of the small cliff below to reveal this missile hiding beneath (use the Thermal or X-Ray Visor to see it in the dark). + +050 +Metroid Quarantine B +Rip open one of the cylindrical containers just past the large force field in this room with a Super Missile to reveal this final missile. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_1/power_bombs.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_1/power_bombs.txt new file mode 100644 index 0000000..ac32932 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_1/power_bombs.txt @@ -0,0 +1,20 @@ + +001 +Magma Pool +You'll need the Grapple Beam and a Power Bomb to find this one. In this lava-filled cavern, use the Grapple Beam to reach the far side then simply use a Power Bomb to break down the wall, revealing this Power Bomb Expansion inside. + +002 +Warrior Shrine +Accessed from the Monitor Station, in the Warrior Shrine you'll find a metal grate covering a small opening right in front of a large Chozo Statue (the statue holds an Artifact). Use a Power Bomb to break open the cover then drop below to find this Power Bomb in a small rocky chamber. + +003 +Ice Ruins West +From the entrance of this room, to the left is a large block-shaped building with a pair of Crystallites wandering around on top. Make your way to the top of the building then use the Plasma Beam to break open the ice block there, uncovering this Power Bomb. + +004 +Security Cave +At the very top of Phendrana's Edge is a small opening leading to the room containing this Power Bomb. Use the Grapple Beam on the Glider flying around to reach the opening. + +005 +Central Dynamo +This is the first Power Bomb you'll find. After crushing the cloaked Sentry Drone, refer to the walkthrough for more details on reaching this explosive beauty. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_1/suit_expansions.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_1/suit_expansions.txt new file mode 100644 index 0000000..2215088 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_1/suit_expansions.txt @@ -0,0 +1,84 @@ +001 +Missile Launcher +Chozo Ruins (Hive Totem) +You'll need to conquer the Hive Mecha in the ruins before winning this prize. Take a look at the bosses guide for tips on defeating this bug-summoning boss. Walk on forward once it shuts down to secure your first missile. +002 +Morph Ball +Chozo Ruins (Ruined Shrine) +In the Ruined Shrine, you'll spot the Morph Ball waiting in a small alcove on the far side, but once in close proximity a barrier rises up to bar your path. You'll then have to fight off a multitude of Beetles lunging up out of the ground everywhere. Don't relax once they're all fried as another surprise awaits. A Plated Beetle promptly jumps out of the ground to challenge Samus to a good old fashioned duel. Show the bug who's boss by firing away at its red tail, once it's finished you'll have clear access to the Morph Ball. +003 +Charge Beam +Chozo Ruins (Watery Hall) +In the Watery Hall, you'll need to scan four symbols on the walls of the region to open up a gate concealing the Charge Beam's alcove. Look for one just to the left of the door as you enter the area, another hidden under a group of Blastcaps around the corner, and the remaining two near the gate itself. Once you've scanned all four scan the symbol on the gate to open it, then simply jump through and head on forward to receive your prize. +004 +Morph Ball Bomb +Chozo Ruins (Burn Dome) +You'll need to beat the Incinerator Drone and its Ram War Wasp cronies before receiving the Morph Ball Bomb. Refer to the bosses guide for tips on defeating this scorching drone. +005 +Varia Suit +Chozo Ruins (Sunchamber) +Before claiming the awesome Varia Suit, you'll need to defeat the huge insect-plant Flaahgra. Refer to the bosses guide to learn all about its weaknesses. Once the bug's cooked you'll spot the rotating Samus logo straight ahead. +006 +Boost Ball +Phendrana Drifts (Phendrana Canyon) +In the Phendrana Canyon region you'll find a long frozen curving canyon with floating platforms leading up to the entrance of a tall tower on the far side. Make your way up to the control panel at the head of the canyon and scan it to align all the platforms. Jump across them up to the tower to find the Boost Ball waiting snugly inside. +007 +Space Jump Boots +Tallon Overworld (Alcove) +You'll need the Boost Ball before finding this upgrade. In the Tallon Canyon region, you'll find a half-pipe area where two Beetles launch out of the ground. Use the Boost Ball to reach the platform high up above. Go around to find a pathway eventually leading back to the Landing Site. Go straight ahead and over the gap in the ledge (don't fall down) to find a door. Head through to find the boots. +008 +Wave Beam +Phendrana Drifts (Chapel of the Elders) +You'll need the Space Jump Boots to reach this area. Check the walkthrough if you have any trouble making your way through the rooms leading here. Once in the large chapel you'll have to fight four Baby Sheegoths and then a fully-grown Sheegoth before claiming the Wave Beam. The juniors are pretty easy, but you might want to check the bosses guide for tips on defeating the adult Sheegoth. +009 +Super Missile +Phendrana Drifts (Observatory) +You'll find the Super Missile atop the upper holographic projector node in the Observatory. First you'll need to activate the hologram by scanning a few control panels and using the four Spinners, once the holographic star map appears jump up the platforms around the room to reach the missile combo upgrade. +010 +Thermal Visor +Phendrana Drifts (Research Core) +You'll find the first visor upgrade deep within the Space Pirate research facilities in Phendrana. Work your way through the complex and you'll eventually find the Research Core, a tall multi-leveled room. Fight off the Flying Pirates and gun turrets positioned around the room, then scan three critical panels to open up the force field below protecting the Thermal Visor. +011 +Spider Ball +Phendrana Drifts (Quarantine Cave) +You'll need to defeat the rock monster Thardus before receiving the Spider Ball. Check the bosses guide for tips to turn Thardus back into a bunch of inanimate rocks. +012 +Ice Beam +Chozo Ruins (Antechamber) +Once you've secured the Wave Beam and Spider Ball, head over to the Furnace. Go up the Spider Ball track (it's next to the hole leading to an Energy Tank) to reach the main area of the room, from here you'll be able to explore a whole new area of the ruins. Eventually you'll reach a room with a large pool and several Stone Toads (refer to the walkthrough for more details). Destroy the grate at the bottom of the pool to drain it, then use the Boost Ball to reach the upper part of the room (watch out for the greedy Stone Toads). Go through the door on the left side of the room (the left side when you first entered the room) to find the Ice Beam waiting inside. +013 +Gravity Suit +Phendrana Drifts (Gravity Chamber) +The trek to the Gravity Suit is a long one, so I'll be brief here (check the walkthrough for more details). You'll need the Spider Ball and Ice Beam to find it. In Phendrana, go past the Quarantine Cave where you fought Thardus and head past the elevator leading down to Magmoor. You'll now enter a completely new area of Phendrana to explore, tucked away behind the Pirate's research labs. In this mini-maze make your way across to the Gravity Chamber (if you've got the hint system on it'll show you where it is). Once inside, work through the underwater areas filled with Aqua Reapers and Jelzaps, in the second underwater cavern you'll find the Gravity Suit in the form of the rotating Samus logo on the far side. +014 +Power Bomb +Phazon Mines (Central Dynamo) +In the Central Dynamo room of the mines (on the middle level), you'll spot a large electrical structure in the center of the room above an electrified floor grating. Jump down to the structure to meet a nasty surprise, a cloaked Sentry Drone is hovering around. You'll need to destroy the drone before reaching the first Power Bomb, try to avoid its attacks while firing madly at it. You won't be able to lock-on so just keep firing with the Power Beam (or use the Wavebuster) and you'll take it down in no time. Once it blows you'll be able to drop down a hole in the ground using the Morph Ball. Down below is an intricate maze with coursing electricity acting as wall barriers - so don't touch any of them. You'll need to maneuver throughout the maze to reach the center where the Power Bomb waits. Blow the water balls with bombs to destroy some of the electric walls along the way, eventually you'll clear a path to the center. +015 +Grapple Beam +Phazon Mines (Storage Depot B) +Remember the Ore Processing room you went through earlier (the one with the rotating Spider Ball track pillar in the center)? Well, you'll probably have noticed a door at the top blocked off by a pile of rubble, simply go up there and blow the rubble away with a Power Bomb. Head inside to find the Grapple Beam waiting - easy. +016 +X-Ray Visor +Tallon Overworld (Life Grove) +Once you've found your first Power Bomb in the mines you'll be able to find this final visor upgrade. Beyond the wreck of the Space Pirate Frigate you'll reach the large circular Great Tree Hall. From here, make your way up to the very top of the region using the intricate Spider Ball tracks to reach the door at the very top. Head through to find a small cave with a large rock blocking a small hole. Use a Power Bomb to blow the rock apart, then head on in. You'll need to use the Boost Ball to get through a narrow O-shaped tunnel (there's a missile hidden in here too) to reach the Life Grove. Once inside jump down below to find the X-Ray Visor. +017 +Wavebuster +Chozo Ruins (Tower of Light) +Naturally you'll need the Wave Beam (and the Super Missile and Spider Ball) to reach this upgrade. From the Main Plaza room, go through the missile-locked door to eventually reach the room where you found the Morph Ball. Use the Boost Ball to reach the Spider Ball track on the roof then go over to the purple door and head through. Eventually you'll reach the Tower of Light, the Wavebuster's right at the top. Jump up to the platform above, then use Super Missiles to break the cracked blocks on each wall (or three Missiles on each block to save ammo - thanks Peter!). There's four blocks per level. With the support blocks destroyed, the tower's entire wall structure will crash down, ascend the tower before the Plated Puffers appear, then keep blasting the cracked blocks (be careful not to hit the Oculus crawling over the blocks) to eventually reach the top. +018 +Ice Spreader +Magmoor Caverns (Shore Tunnel) +In the Shore Tunnel you'll find yourself in a somewhat nondescript metal tunnel within a lava-filled cavern. Look closely (or use the scan visor to reveal it) and you'll notice fractures throughout the center part of the tunnel. Use a Power Bomb to blow open the tunnel (just like old times in Maridia), drop down below to find the Ice Spreader underneath the tunnel. +019 +Plasma Beam +Magmoor Caverns (Plasma Processing) +You'll need the Ice Beam, Power Bombs, Grapple Beam and Spider Ball to reach this. In the Geothermal Core room, use the Grapple Beam to jump up to one of the three large pillars. Use the Spinner slots and Spider Ball tracks to reach the highest platform of the three pillars and activate the Morph Ball slot hidden there. The pillars will rise up and push the roof up higher, revealing an intricate series of Spider Ball tracks all around the walls. Make your way across the tracks (don't fall) and watch out for the Plated Parasites. Once you reach the door, lay a Power Bomb while still attached to the Spider Ball track to destroy the rubble in front of the door. Go inside to find the Plasma Beam. +020 +Flamethrower +Phazon Mines (Storage Depot A) +Once again you'll need a Power Bomb to find this one. In the Mine Security Station (the room filled with Space Pirates jumping down out of the roof), not far from the entrance you'll find a red door blocked off by a red force field. On the next level above this door (near the purple door in the roof) is a wall blocking a computer console. Blow apart the wall with a Power Bomb and scan the console to power down the force field. Head through the red door below to find the Flamethrower in the adjacent room. +021 +Phazon Suit +Phazon Mines (Elite Quarters) +Defeat the hideous Omega Pirate in the mines to win the Phazon Suit and Phazon Beam. Refer to the bosses guide for really handy hints on defeating the Pirate's Phazon king. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_2/beam_ammo_expansions.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_2/beam_ammo_expansions.txt new file mode 100644 index 0000000..71b0faf --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_2/beam_ammo_expansions.txt @@ -0,0 +1,16 @@ + +001 +Profane Path +You'll require the Echo Visor and Annihilator Beam to reach this one. Use the portal at the Sacred Path to travel to Dark Aether, and deal with the two Dark Pirate Commandos greeting you there. Walk over to the giant mutated Ingworm structure, that sealed door at its base guards the item. Switch on the Echo Visor and pull out the Annihilator Beam. Shoot the door to hear the correct sequence of tones needed to open the door. Look around for the three tone emitters, then shoot each one in the correct order to match the door's tone and unlock it. Step inside the open alcove to claim your prize. + +002 +Central Mining Station +Upon retrieving the Light Beam and returning to Aether, enter the Central Mining Station via the upper corridor of the Command Center Access room to be able to reach the two Vigilance Class Turrets. Jump in one and use it to destroy all the power generator devices scattered around the area. Once they're clear, climb up to the large red force shield directly across from the turrets and crawl through a narrow tunnel hidden beside the shield to find this item inside. + +003 +Cache A +With the Seeker Launcher in hand, head to the Poisoned Bog by way of the black door in the Venomous Pond. Once there, destroy the purple blast shield on the door on the southern side of the area to find this item waiting patiently inside the chamber beyond. + +004 +Watch Station +You'll require the Spider Ball to locate this one. In the Watch Station, travel up to the top of the floating platform in the center of the region to find a Kinetic Orb Cannon there. Use it to launch yourself over to the northern wall, grabbing onto a Spider Ball track as you reach it. Follow the network of tracks along the walls (take care around the moving circular sections, lay a bomb as you pass between the two red markers to time your jump correctly). Eventually you'll reach a large vertical section of track, with two paths deviating from it, one directly below (leading to a Bomb Slot), and another off the bottom-left corner. Drop off the bottom-left corner and grab hold of the track below. Follow this network along, again taking care on the circular moving sections. Eventually you'll reach a translucent tunnel high up at the top of the room. Look for a tunnel going into the northern wall, whatever you do don't go down the right-hand tunnel as it leads straight back down to the ground below. Follow the tunnel inside the wall to find this item waiting in a tiny chamber. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_2/dark_temple_keys.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_2/dark_temple_keys.txt new file mode 100644 index 0000000..a1c6ae6 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_2/dark_temple_keys.txt @@ -0,0 +1,36 @@ +001 +Dark Agon Key 1 +Trial Tunnel +When you first visit the Dark Agon Temple, take the left path from the entrance to find a door at a dead-end. Inside a tiny chamber beyond you'll find this key. +002 +Dark Agon Key 2 +Doomed Entry +You'll discover this key up high in the Doomed Entry room after accessing Dark Aether via the Command Center. Climb up around the room and Space Jump across to the rock ledge where it rests to retrieve it easily. +003 +Dark Agon Key 3 +Battleground +Once you've obtained the Light Beam, head through the western exit of the Doomed Entry and follow the corridor beyond to locate the Battleground area where this key awaits. Defeat the pack of Warrior Ing awaiting inside to secure your prize. +004 +Dark Torvus Key 1 +Dark Torvus Arena +You'll need to destroy the Boost Guardian (also in this room) and reclaim the Boost Ball before reaching this key. Once you have the Boost Ball, boost yourself up the half-pipe this key resides atop, you should then easily be able to pop into the small alcove containing the key. +005 +Dark Torvus Key 2 +Undertemple Access +Once you've secured the Gravity Boost and defeated the Alpha Blogg, travel back up to the Hydrodynamo Shaft and power up the Dark Portal there. This key will be waiting directly in front of you in Dark Aether. +006 +Dark Torvus Key 3 +Venomous Pond +With the Grapple Beam recovered, head to the Venomous Pond to see this Dark Temple Key lying atop a ledge only accessible via a Grapple Point suspended nearby. Work your way up to the ledge across from the key, then use the Grapple Beam to reach it easily. +007 +Ing Hive Key 1 +Culling Chamber +You'll need the Spider Ball to reach this. Just inside the main corridor from the portal terminal you'll see this Dark Temple Key resting inside a wall section surrounded by a strain of Phazon and a number of Spider Ball tracks. Head further down the corridor to find an accessible Spider Ball track. Climb up around the tracks to reach the tunnel within the wall where the key resides, and lay a bomb to break through the crates keeping it sealed in. +008 +Ing Hive Key 2 +Hive Gyro Chamber +The Echo Visor and Spider Ball will enable you to reach this. Transit to Dark Aether at the Dynamo Works and proceed through the white door near the portal. Open up the sealed door in the following chamber by using the Echo Visor to see the sonic emitters locking it down, then move onwards to the Hive Gyro Chamber. Inside the gyro chamber itself you'll discover this Dark Temple Key resting atop a huge sphere covered in Spider Ball tracks. Climb aboard and look for a small vertical track, from there boost yourself up to the horizontal circular track surrounding the key. Simply line yourself up with the key and boost off the track to slam right into it. +009 +Ing Hive Key 3 +Aerial Training Site +Once you've secured the Screw Attack ability, travel to the Main Research room on Aether. Use the portal there to travel to Dark Aether, then exit the Staging Area by way of the only exit up on the western wall. Use the Screw Attack in the following shaft to jump up the Wall Jump Surfaces, then exit the shaft at the apex to find this Dark Temple Key waiting directly in front of you beyond the door. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_2/energy_tanks.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_2/energy_tanks.txt new file mode 100644 index 0000000..e9ec492 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_2/energy_tanks.txt @@ -0,0 +1,56 @@ + +001 +Storage Cavern B +Within the Temple Assembly Site area you'll find a red blast shield sealing a door. Once you've recovered the Missile Launcher blow open the door with a single shot to reveal this Energy Tank hiding in the room beyond. + +002 +Windchamber Gateway +You'll need the Light Beam, Super Missile and the Grapple Beam to reach this one. From the Path of Eyes area, use the Light Beam to move the pillar covering the green blast shielded-door at the northern side of this area before opening the door with a Super Missile. Go inside to find a huge cliff and a massive chasm before you. Use the nearby Kinetic Orb Cannon to fly to the other side, then turn left and use the Grapple Beam to reach this item waiting on a platform overlooking the cliff side. + +003 +Fortress Transport Access +The Light Suit will grant you access to this item. Look for a giant yellow light beam spanning the floor and ceiling of a chamber within the Fortress Transport Access corridor. Step into the beam to be teleported above to a smaller hidden chamber where this Energy Tank awaits. + +004 +Mining Station Access +Upon recovering your Morph Ball bomb ability, destroy the block covering a Kinetic Orb Cannon in this room and use it to reach this Energy Tank hidden above. + +005 +Bioenergy Production +The Energy Tank within this large chamber lies atop a ledge on the southern side. You'll need to rearrange the three large storage racks to create a working staircase to reach the ledge. Energize the storage racks via the console on the eastern side of the room, then use the terminals on the western side to tweak each storage rack's configuration. Climb up to claim your prize. + +006 +Mine Shaft +With the Dark Beam in your arsenal, head to the Agon Temple. On the western side of the temple lies a black door, enter to find the Mine Shaft. At the top of this twisting network of tunnels you'll find the Energy Tank (you'll in fact see it as you enter the main network). You'll need to work your way through the uppermost tunnels to eventually wind around the shaft and reach this item, just watch out for Pillbugs and use the double bomb-jump to reach heights you normally can't with a single bomb. + +007 +Mining Plaza +You'll need the Echo Visor and Screw Attack to recover this. See the large triple-lens structure beside the statue of Amorbis in the Mining Plaza? Switch on the Echo Visor to see three separate sonic emitters sending signals into each lens. Shoot each emitter to line up all three lens pieces. Doing so will open the wall panel above the western door of the region, revealing this item inside an alcove there. Screw Attack from atop the bluff to reach it (might take a few tries). + +008 +Temple Access +Enter the Temple Access room via the upper door (outside in the Great Bridge area), then look for a damaged cover plate along the tight corridor. Blow it open with a bomb and fall through below to grab this Energy Tank. + +009 +Cache B +When you visit the Dark Torvus Temple, roll through the narrow red tunnel on the western end of the room (behind the elevator). Blow the green blast shield off the door beyond with a Super Missile and enter the next chamber to locate this Energy Tank waiting patiently inside. + +010 +Torvus Plaza +With both the Boost Ball and Spider Ball in hand, head to this room where a huge half-pipe resides. Boost yourself up the pipe and latch onto the Spider Ball track high above. Work your way along the network of tracks (watch out for a rogue Sporb) until you reach a Kinetic Orb Cannon. Let it throw you across the room, right onto a ledge where this Energy Tank awaits. + +011 +Meditation Vista +The Screw Attack will enable you to find this one. Travel to the Meditation Vista beside the Torvus Grove and look out across the cliff edge where the portal terminal lies. See that platform hovering about in the air? Aim at it, wait for it to begin travelling left then Screw Attack across to land squarely on top. Stay on the platform and allow it to take you over to the now-visible Energy Tank. + +012 +Transit Tunnel East +You'll need the Gravity Boost to reach this one (special thanks to Joe for clarifying this!). Visit Transit Tunnel East in the bowels of Dark Torvus to find it filled with transparent tubes. On the far left side you'll discover a Bomb Slot - energize it to see a number of jet streams appear in the vertical tubes on the right. Travel over to the second tube with a vertical current, then bomb-jump yourself up the stream. The current will carry you higher than normal, lay a second bomb near the apex of your ascent to propel yourself higher as you fall back towards the bomb. Reach the Bomb Slot at the top of this tube and energize it to temporarily send the water stream upwards over in the vertical tube on the left. Quickly travel over to it and bomb-jump yourself to the top where this Energy Tank lies in wait. + +013 +Reactor Core +This Energy Tank resides above the western door at the top of the reactor shaft, but you'll need the Spider Ball to reach it. Clear the area of Rezbit and look for a Kinetic Orb Cannon at the base of the shaft near the reactor. Jump in and hold R (or Z in the Metroid Prime Trilogy version), watch as the cannon launches you up onto a large sphere covered in Spider Ball tracks. Climb to the top of the shaft, watching out for arcing electricity. Once at the top, look for a red node attached to a smaller sphere. Position Samus over it and boost away from it, in the correct position you'll land directly onto another suspended sphere. Look for another red node attached to this one and boost away from it - keep this up to eventually reach a Spider Ball track on the wall. Do it quickly as electricity tends to arc across the spheres. Follow the network of Spider Ball tracks to ultimately reach this item. + +014 +Watch Station Access +Enter this room via the Watch Station end to find this Energy Tank waiting patiently inside an alcove. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_2/maps.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_2/maps.txt new file mode 100644 index 0000000..2d5c4d1 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_2/maps.txt @@ -0,0 +1,35 @@ +001 +great_temple +Great Temple + +002 +light_temple_grounds +Temple Grounds + +003 +dark_temple_grounds +Sky Temple Grounds + +004 +light_agon_wastes +Light Agon Wastes + +005 +dark_agon_wastes +Dark Agon Wastes + +006 +light_torvus_bog +Light Torvus Bog + +007 +dark_torvus_bog +Dark Torvus Bog + +008 +light_sanctuary_fortress +Sanctuary Fortress + +009 +dark_ing_hive +Ing Hive diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_2/missile_expansions.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_2/missile_expansions.txt new file mode 100644 index 0000000..9aab84c --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_2/missile_expansions.txt @@ -0,0 +1,200 @@ + +001 +Temple Grounds (GFMC Compound) +You'll find the Missile Launcher packed inside the oversized yellow-marked ordinance crate on the port side of the GF trooper's ship. Blow it open with a blast from the Charge Beam to reveal your prize. + +002 +Transport to Agon Wastes +You'll find this missile hidden behind a Splinter web near the Agon elevator. Blow it open to uncover your prize. + +003 +Hive Chamber A +After returning the planetary energy to the Agon Temple, return to the Temple Grounds and fall through the shaft you originally descended at the very beginning of the game. Down in Hive Chamber A you'll encounter a Dark Missile Trooper, defeat it to claim your prize. + +004 +Hive Chamber B +Right past the area where the first Dark Portal you encountered existed in Hive Chamber B, you'll find a sealed tunnel beside the one you take to bypass the jammed cargo lift pod. Use a Morph Ball Bomb to crack open the cover plate. Roll inside to find this missile tucked away inside. + +005 +Plain of Dark Worship +Energize the purple crystal on the column in the corner of the Temple Assembly Site (in the Temple Grounds) to reveal a Dark Portal. Use it to travel to Dark Aether, you'll then find this missile within an Ingworm tower structure over on the western side of the area. + +006 +Temple Assembly Site +Once you've picked up the Space Jump Boots, climb atop the cliff side on the western end of the Assembly Site, then follow it around and roll through the narrow tunnel at the end to locate this missile. + +007 +Communication Area +With the Space Jump Boots in hand, jump atop the jagged cliff near the entrance of the Communication Area (coming from the Temple Assembly Site). Drop a Morph Ball Bomb atop the stasis chamber in the ground to blow open the cover, revealing this missile inside. + +008 +GFMC Compound +This missile waits atop the rear of the GFS Tyr. You can try to Space Jump atop the craft via a crate near the damaged opening on the side of the ship, but it may not be easy. Otherwise use the Screw Attack from one of the cliff edges across from the nose of the craft to climb aboard easily. + +009 +War Ritual Grounds +Look for a sealed door at the base of the large mutated Ingworm structure here. Switch on the Dark Visor and stand back, looking for five red pods surrounding the door. Use the Seeker Launcher to hit all at once, opening the door to your prize ahead. + +010 +Phazon Grounds +You'll require either the Dark Visor or the Screw Attack to reach this safely. Travel to Dark Aether by way of the portal at the Sacred Path area and make your way to the Phazon Grounds. Clear the area of the Dark Tallon Metroid colony and look out over the cliff to the tall structure ahead. Your prize is waiting there - either switch on the Dark Visor and carefully cross the chasm via the moving platforms (thanks Brian!), or simply Screw Attack over the chasm to reach it. + +011 +Transport B Access +In this Lightflyer-inhabited corridor you'll see a number of large grooves along the walls of the middle section of the corridor. Use the Morph Ball and bomb-jump your way through the tunnels lining the walls, eventually they'll lead you straight to this missile. + +012 +Transport A Access +Inside this corridor lies a hidden Save Station. Beside the Save Station is a rock wall containing elements of Talloric Alloy. Lay a bomb beside it to destroy the wall, then proceed down the winding path under the Save Station to find this missile there. + +013 +Sand Cache +Once you've visited the Agon Temple and been granted access to amber holograms, scan the translator gate in Mining Station A to open up access to the room where this missile hides. + +014 +Portal Access +On one side of the tall structure in this room you'll find the remains of a Luminoth warrior. This missile rests directly behind it, sneak around the Kinetic Orb Cannon nearby using the Morph Ball to reach it. + +015 +Transport Center +Once you've raised the trans-dimensional gate in Dark Agon in the Portal Site room, return to the light world and head through to the Transport Center. Inside you'll find this missile beyond a half-pipe, encased within a metal cage. Energize the Bomb Slot nearby to raise the gate to claim your prize. + +016 +Command Center +On your first visit to the Space Pirate's Command Center you'll be under the floor in Morph Ball mode and witness several Pirate Troopers head through a portal to Dark Aether. Follow the narrow tunnels over to the right side of the room to discover this missile waiting there. + +017 +Storage B +Once you've picked up the Dark Beam, return to the Biostorage Station and deal with two pesky Metroids inside. Open up the black door up in the corner of the room to discover this missile hidden beyond. + +018 +Ing Cache 4 +You'll need the Dark Beam to find this. In the Duelling Range there's a black door on the far western side. Open it up to find a small canyon ending with a dead-end. You'll find this missile hiding in a small alcove directly below the door you entered via. + +019 +Crossroads +With the Boost Ball in your possession, use the half-pipe in the Transport Center to reach an inactive Dark Portal high above. Energize it and step through to find this missile directly in front of you once in Dark Aether. + +020 +Ventilation Area A +Travel to the right side of the main tunnel conduit to see a Pillbug rolling around tunnels up in the ceiling. Defeat the creature and use double bomb-jumps to climb up through the tunnels, eventually locating this item waiting at the top. + +021 +Main Reactor +You'll require the Boost Ball and Spider Ball to reach this. In the corner of the Main Reactor lies a Spider Ball track leading up to the ceiling. Climb up to see a piston over on the right raising and lowering itself above a vat of Phazon. Time your boost over to it to latch onto the Spider Ball track wrapped around the top section. Spin around it and look for the next piston, wait for the tracks to line up again before boosting across. Keep this up to reach a small alcove in the opposite corner of the room where this item waits inside a stasis chamber. Lay a bomb beside it to gain access. + +022 +Sand Processing +You'll need the Boost Ball to secure this one. Look for a large half-pipe partially filled with sand in this room. Destroy the two turrets guarding the area, then boost yourself up to a small tunnel above the half-pipe. Roll through the tunnel to access the enclosed control station overlooking the half-pipe. Scan the terminal beside the Bomb Slot to power it up, then jump inside and energize it to drain the sand from the half-pipe outside, revealing this missile waiting inside an alcove. + +023 +Storage C +The Boost Ball and Spider Ball will enable you to reach this one. Inside the Bioenergy Productions room, activate the lone terminal beneath the ledge where a green door resides to raise the three large storage rack units in the center of the room. Then, make your way over to the north-western corner of the room up where the three control stations to move the storage racks live. A Spider Ball track is hidden in the corner, climb up and make your way along the network of tracks to find yourself up on the ceiling out in the open chamber. Boost across the small structures until you reach the one in the center, looking for a Spider Ball track visible ahead travelling east. Boost over to it, then boost yourself across to the Spider Ball track running around the top of the middle storage rack. Go around to the other side of it and finally boost yourself across to the green door. Blow the blast shield off with a Super Missile to locate this missile in a hidden chamber beyond. + +024 +Storage A +You'll require a Power Bomb to locate this one. In the Mining Station B area, there's a large cracked section of the rock wall on the southern side. Destroy the wall with a Power Bomb to uncover a white door beyond. Go inside to find a cosy grove where this missile waits. + +025 +Mining Station A +You'll require a Power Bomb and the Spider Ball to reach this. Look for a weakened wall section at the base of this region, then blow it open with a Power Bomb. Jump in the exposed Kinetic Orb Cannon to be launched high up to a network of Spider Ball tracks above. Follow them along to reach this missile. + +026 +Junction Site +The Spider Ball's necessary to reach this one. In the center of this tunnel you'll find the missile tucked inside an alcove below you. Climb up the Spider Ball track above and energize the Bomb Slot to rotate the entire circular structure, clearing the way to the missile. + +027 +Warrior's Walk +You'll need the Super Missile Charge Combo to find this one. At the eastern end of the Judgement Pit (or western end of the Battleground) you'll find a green door. Blow the blast shield off the door with a Super Missile and enter the corridor beyond. At the eastern end of the corridor you'll see a vein of Phazon running below a group of floor coverings. Just at the foot of the door under the floor lies this missile, use your Scan Visor to find a weakened section and blow through it with a bomb. Jump in and make a run for the missile across the Phazon, making a hasty escape afterwards to avoid taking too much damage. + +028 +Forgotten Bridge +This missile rests atop a ledge in front of a door, but to reach it you'll need to rotate the large bridge first. Travel to Dark Aether via the nearby portal and energize the Bomb Slot nearby to rotate the bridge. Return to Aether and cross the bridge to claim your prize. + +029 +Hydrodynamo Station +At the base of this shaft lies a door sealed by three security locks. This missile lies atop a platform directly in front of a purple door. Descend to the near-base of the shaft, then scan the first lock directly below the purple door's platform to cause a smaller platform to extend from it. Make your way back up there and simply jump across to claim this missile. + +030 +Underground Tunnel +Enter this room via the Torvus Temple, then drop off the platform you're standing on. Activate the Morph Ball and roll underneath it, tucked away in a corner lies this missile. + +031 +Plaza Access +Once you've recovered the Boost Ball, reach this room by way of the Torvus Grove. Once inside the first section of the tunnel, energize both Bomb Slots to rotate two devices needed to make it through the tunnel. The second device will grant you access to a visible tunnel opening directly above it. Roll through there to find yourself in a narrow half-pipe tunnel. Charge up the Boost Ball and build momentum; this missile is hiding up on the right side of the tunnel. + +032 +Portal Chamber +Look for the Portal Chamber room adjacent the Venomous Pond in Dark Torvus Bog. Travel to the eastern side of it and jump atop the platforms to reach the roof. From there, roll through a narrow opening you find to reach the inactive Light Portal in the main chamber. Power it up and return to Aether to find this missile waiting in the chamber right in front of you. + +033 +Undertransit One +One the left-hand side of this transit tunnel this missile hides among the pipes. The missile is right next to the left-most part of the safe zone, so experiment with bomb jumps to find the hidden opening in the tunnels to reach it. + +034 +Abandoned Worksite +You'll need the Grapple Beam to reach this one. On the southern section of this room you'll see the missile lying atop a tall ledge. Simply use the Grapple Beam on the Grapple Point above to swing over and reach it easily. + +035 +Path of Roots +Once again you'll need the Grapple Beam to secure this. Enter the Path of Roots room by way of the Great Bridge. Use the Grapple Point ahead to swing over to the top of a small cage where this missile awaits. + +036 +Torvus Lagoon +You'll require the Gravity Boost to secure this item. In the Torvus Lagoon, deal with the two annoying Grenchlers before attempting your search. Travel underwater and look for a tall underwater wall directly below the body of the Luminoth warrior (there's a cluster of Venom Weed at the base). Use the Gravity Boost to reach a small alcove at the top of the wall where this missile waits. + +037 +Gathering Hall +The Spider Ball and two Power Bombs are needed for this. Descend into the water in this chamber and destroy the cracked glass below with a Power Bomb. Destroy the drain cover at the base of the half-pipe with a second Power Bomb to drain the water in the chamber. Then use the exposed half-pipe to reach the Spider Ball tracks up in the ceiling, and traverse to both sides of the room from there, energizing each Bomb Slot on either side of the chamber. Doing so will lower the containment shield guarding this missile, you're then clear to jump atop a newly-extended platform to reach this item. + +038 +Training Chamber +You'll require the Spider Ball to recover this one. Look for a Spider Ball track underwater, to the left of the tall Luminoth statue. Follow the tracks around to reach the Bomb Slot below the statue's head, then energize it to cause the statue to move forward. Right behind the statue, where it once stood awaits this item. + +039 +Torvus Grove +Take a close look at the trio of roots holding up the giant tree growing here. Upon closer inspection (and use of the Scan Visor) two are revealed to have been weakened thanks to Phazon exposure, so finish them off with a Power Bomb (or two). Look closely for two rods on the ground protruding from each tree root - lay a Power Bomb between them to destroy both roots with a single blast (thanks Brian!). With both roots destroyed the entire tree will slam into the rock wall, blowing open a hidden alcove to reveal this missile inside. + +040 +Transit Tunnel South +The Annihilator Beam will grant you access to this missile. Travel down to the bowels of Torvus and head for one of either the Gathering Hall or Catacombs chambers. Exit the chamber via the gray door (thanks to the Annihilator Beam) to reach this transit tunnel. Deep inside you'll find a network of tunnels running throughout the rock walls. See those vents shooting jets of water up and down? You'll need to travel through this area, activating Bomb Slots to reverse the direction of the jets and bomb-jump your way up the streams of water. After energizing three Bomb Slots you'll be clear to reach this missile at the top of the tunnel network. + +041 +Undertemple +With the Screw Attack in your hands, travel back to the Undertemple at the very depths of Dark Aether (the chamber where you fought the Power Bomb Guardian). Dispatch the two Hunter Ing snooping around there, then look for a shaft at the northern end of the chamber. See the Wall Jump Surfaces running up the walls? They're not just there to reach the Light Portal above. Screw Attack up the walls to the very top where you'll discover this missile waiting in an alcove. + +042 +Hazing Cliff +Use the portal station in the Hall of Combat Mastery to transit to Dark Aether. From there, exit the portal chamber, turn right, and go through the door nearby. Inside you'll find a large chamber with most of the floor and one wall non-existent. Deal with the Dark Tallon Metroid greeting you from below, then make your way to the opposite end of the chamber. Fry the two Dark Diligence Drones guarding a small passage to then find this missile tucked away inside. + +043 +Dynamo Works +Upon eliminating the Spider Guardian and recovering the Spider Ball, follow the tracks up to the highest point of the tunnel network. From here you'll spot a small opening in the ceiling leading to another tunnel. Bomb-jump up there and follow the path to discover this missile lying in front of a chute leading back to the main section of the Dynamo Works. + +044 +Hall of Combat Mastery +You'll need the Spider Ball for this one. Running up one of the inner walls of the Hall of Combat Mastery area is a Spider Ball track. Travel up it and enter the large network of narrow tunnels lining the walls of the entire area. Work your way through the numerous obstacles to eventually reach this missile. + +045 +Main Research +The Spider Ball can help you reach this. In the Main Research area, you'll discover a tall blue translucent wall on one side covered with a number of Spider Ball tracks and a number of moving machinery components. Climb up the wall and take care around the dangerous pieces of machinery. Eventually the tracks will lead straight to this missile. + +046 +Central Area Transport West +This missile resides inside a network of tunnels running up the side of the shaft in this room. Travel to the top of the shaft and drop into the large pit once at the top. Down below you'll find three tunnels leading below. Take the left tunnel at the top, then take a right, right again, and finally a left to land right on top of the missile. If you take the wrong tunnel check where you should have dropped through, then make your way to the top of the shaft again via the Kinetic Orb Cannons. + +047 +Aerial Training Site +With the Screw Attack secured, use it to jump up the Wall Jump Surfaces near the inactive Light Portal in this area to grab this missile from an overhead alcove. + +048 +Temple Access +The Dark Visor, Seeker Launcher and Echo Visor are needed to retrieve this item. Firstly, make sure that the Kinetic Orb Cannon is active. If it isn't, leap down to the cannon and switch on the Dark Visor. Face the wall containing the door leading to the Sanctuary Temple, and look up. There's four glowing red pods above the door - fire the Seeker Launcher at them to activate the cannon (special thanks to Joe for clarifying this!). Use the cannon to return to the the entrance of the room. The Kinetic Orb Cannon's target can be seen directly above. Switch on the Echo Visor to see a sonic emitter beaming a signal at it. Shoot the emitter to cause the target to move forward slightly, then quickly jump down to the Kinetic Orb Cannon. Hop in to be launched into the target where you'll drop to a narrow tunnel. Fall below to land underneath the floor, then roll forward to find this item waiting for you near the cannon. Use the Spinner right next to it to open up a section of the floor to escape. + +049 +Sentinel's Path +The Echo Visor and Annihilator Beam will grant you access to this item. Check your map of the fortress, on the upper floor you'll see a corridor connecting the Sanctuary Temple to the Watch Station. Enter the corridor from either end and make your way to the center. Take out the two Mekenobites hanging about via the Seeker Launcher, then take a look at the sealed door halfway through the corridor. Three small terminals lie in front of it, switch on the Echo Visor to see a number of icons appear - one on each terminal and four on the door itself. Target the orange icon on the door and shoot it once with the Annihilator to hear four distinct tones of the lock sequence. You'll then need to shoot the correct terminals to produce the same notes in the same order presented to unlock the door. Once you do, pick up your prize in the small alcove beyond. + +050 +Sanctuary Map Station +The Light Suit is key to finding this missile. Travel to the Map Station via the Reactor Core to see a giant yellow light beam down the ramp ahead. Simply step into the beam with the Light Suit equipped to be teleported up to a hidden chamber where this item lives. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_2/power_bombs.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_2/power_bombs.txt new file mode 100644 index 0000000..069591b --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_2/power_bombs.txt @@ -0,0 +1,36 @@ + +001 +Dark Torvus Bog (Undertemple) +Once you've recovered the Spider Ball, you'll be able to locate this power-up. Dive to the very depths of the Torvus Bog, way down to the Main Hydrochamber where you faced the Alpha Blogg. Reach the Dark Portal on the northern side of the chamber via the Spider Ball track, then transit to Dark Aether. Drop off the ledge you appear on and enter the main chamber to confront the Power Bomb Guardian. Defeating this monster rewards you with your first Power Bomb, check the bosses guide for tips to send it away. + +002 +Dynamo Chamber +You'll need two Power Bombs to recover this one. Inside the Dynamo Chamber lies two main tunnels running through the area, with one above the other. The lower tunnel is blocked by two Mk VII security gates, destroy one with a Power Bomb to access the lower tunnel, then look for a weakened wall section inside and destroy it with another Power Bomb, revealing this item inside. + +003 +Sandcanyon +You'll need a Power Bomb and the Screw Attack to reach this. Out in the center of the massive Sandcanyon lies a tall statue. Screw Attack over to the platform below the statue, then lay a Power Bomb to dislodge the statue into the abyss, revealing this Power Bomb where it once stood. + +004 +Feeding Pit +The Light Suit will allow you to reach this item without incurring serious health loss. Travel to the Feeding Pit area and dive into the murky lake inhabited by the two tall pillars. Search around for a hidden underwater alcove, this item is sitting neatly inside. + +005 +Putrid Alcove +Two Power Bombs will score you this item. See a yellow door in the Dark Forgotten Bridge and Poisoned Bog areas? Blow through one with a Power Bomb to locate a small pond connecting the two regions. Dwelling in the putrid pond is a Phlogus, shoot it when its maw opens to flip it around and step aboard. Switch on the Scan Visor and sweep around, looking for a scannable section in the surrounding rock walls. The cracked wall is composed of Denzium, so light up another Power Bomb beside it to reveal this item inside a tiny alcove. + +006 +Great Bridge +Another Power Bomb will enable you to secure this one. Running behind the upper northern and eastern walls of this area lies a narrow hidden tunnel where this Power Bomb awaits. Blow open one of the Denzium blocks covering either end of the tunnel and roll through to snag it. + +007 +Transit Station +Look for a weakened glass shield protecting an inactive Dark Portal in this chamber. Use a Power Bomb to breach the shield and gain access to the portal. Travel to Dark Aether, defeat the Dark Ingsmasher there, then follow a sequence of portals jumping back and forth between dimensions until you reach a hidden alcove where this item awaits. + +008 +Sanctuary Entrance +The Spider Ball and a Power Bomb are required for this item. At the Sanctuary Entrance, there's an elevator to the left of the main entrance leading inside the fortress. But it's blocked by a cracked window, and only a Power Bomb can break through. Take out the window and ride the lift up. Scan the control terminal to activate a nearby Kinetic Orb Cannon. Use it to reach an overlooking platform and climb up to the Vigilance Class Turret atop it. Jump in and aim at the top of the southern cliff wall. Send a few shots into it to uncover the Power Bomb. Spin around to face the fortress entrance, then send a few shots into the cracked section of the wall to uncover a ledge. Finally, aim down at the right-hand corner of the fortress and send a shot or two into the jagged formation of rocks there. With all three obstacles clear, return to the ground and head over to where the jagged rock formation once stood. Look for a small alcove where a number of Spider Ball tracks line the walls, use them and follow the tracks to reach the ledge above which you uncovered. Finally, jump in the Kinetic Orb Cannon up there to launch yourself over to the alcove in the cliff opposite where this item awaits. + +009 +Main Gyro Chamber +With the Echo Visor and Annihilator Beam in hand, travel to the very bottom of this chamber to locate a sealed door at the rear of the gyro chamber. Switch on the Echo Visor and take out the Annihilator Beam. Shoot the door to hear the required sequence of tones needed to unlock it. Memorise the sequence then reproduce it via the three tone emitters nearby. Unlocking the door will reveal a Kinetic Orb Cannon beyond, jump in to be launched up into the giant purple sphere above, destroying it and revealing this Power Bomb inside. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_2/sky_temple_keys.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_2/sky_temple_keys.txt new file mode 100644 index 0000000..cd76203 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_2/sky_temple_keys.txt @@ -0,0 +1,36 @@ +001 +Sky Temple Key 1 +Battleground +Travel to the Battleground, entering the room via the upper eastern corridor from the Doomed Entry room. From the ledge overlooking the sand pit below, deal with the two Warrior Ing below and look across to the opposite side of the room. Switch on the Dark Visor to spot the Flying Ing Cache way over on a ledge opposite. You'll also spy four now-visible floating platforms. Traverse across the platforms carefully to reach the ledge where the Flying Ing Cache hides, then blow it open to retrieve this key. +002 +Sky Temple Key 2 +Dark Oasis +You'll need a Power Bomb and the Light Suit to safely retrieve this key. Inside the Dark Oasis you'll discover a large section of the cave is blocked by a large cracked rock wall. Dismantle the rock wall with a Power Bomb to discover a large underground murky lake beyond. The air above the lake is rife with Ingstorm particles but with the Light Suit on they can't do squat to you. Wipe out the Inglets covering the walls then dive into the murky water. Switch on the Dark Visor and search for the Flying Ing Cache (underwater) hiding in a corner. Take it out to retrieve this key. +003 +Sky Temple Key 3 +Poisoned Bog +Travel to the Poisoned Bog and deal with the lone Hunter Ing standing guard. Take a dip in the murky lake and switch on the Dark Visor (just make certain you've got the Light Suit). Search for the Flying Ing Cache hidden down a dead-end and take it apart to score this key. +004 +Sky Temple Key 4 +Dungeon +Travel to the Catacombs in Torvus and transit to Dark Aether via the Dark Portal there. Once in the Dungeon, play with the two Dark Grenchler and take a dip in the murky water below the inactive Light Portal. Step forward and turn right in this small underwater maze to spot a Light Beacon within a wall ahead above a small round object. Scan the object for your Logbook, this Watchdrone will only move when exposed to bright light. So go ahead and shoot at the Light Beacon to cause the little fella to hobble out of the reach of the safe zone. Roll through the opening and look for another Watchdrone around the corner. Pass this one to locate a dead-end, switch on the Dark Visor to locate the Flying Ing Cache easily. +005 +Sky Temple Key 5 +Hive Entrance +Travel to Dark Aether via the portal terminal at the Hall of Combat Mastery, then make your way across to the Hive Reactor (the Dark Aether version of the Reactor Core room). From there, blow open the yellow door on the south wall and follow the path through to the Hive Entrance. Wipe out the Dark Preed floating above the massive chasm ahead of you, then Screw Attack across the gap to the giant yellow light beam on the far side. Step in to teleport up to a higher ledge, then face the fortress entrance and Screw Attack back there. Switch on the Dark Visor to spot the Flying Ing Cache hiding up on this alcove, blow it open to recover this key. +006 +Sky Temple Key 6 +Hive Dynamo Works +Head back to the section of the Dynamo Works where you faced the Spider Guardian (by way of the Sanctuary Temple). Once there, follow the network of tunnels right through to the end. In the small chamber where you claimed the Spider Ball a yellow blast shielded-door exists. Blow the shield off with a Power Bomb and step inside the next chamber to locate an inactive Dark Portal. Energize it and step inside. Once in Dark Aether, go outside to the Hive Dynamo Works to find yourself looking across a chasm to a platform across the room. Climb up the Spider Ball track nearby and boost yourself across the two floating sentry pods to clear the gap. Boost to the second Spider Ball track running along the northern wall to reach the platform, then search for the Flying Ing Cache there to retrieve this key. +007 +Sky Temple Key 7 +Ing Reliquary +You'll need the Light Suit to locate this one. Travel to Dark Aether via the portal at the Sacred Path area. Follow the path along past the Phazon Grounds to locate the Reliquary Grounds - inside the lone door up on the cliff here is the Ing Reliquary. Go inside, search for the Flying Ing Cache with the Dark Visor on and bust it open to claim this key. +008 +Sky Temple Key 8 +Defiled Shrine +Use the portal at the Hall of Eyes in the Temple Grounds, then make your way across to the Defiled Shrine (the Dark Aether version of the Landing Site). Defeat the four Warrior Ing greeting you there and switch on the Dark Visor. Look for the Flying Ing Cache hiding up in the south-western corner of the room. Blow it open to reveal this key. +009 +Sky Temple Key 9 +Accursed Lake +Use the portal at the Temple Assembly Site to travel to Dark Aether. Once there, exit the room via the door blocked with a purple blast shield (blow it off first) then proceed through the tunnel beyond to locate the Accursed Lake. Deal with the two Hunter Ing emerging from the poisoned waters, then switch on the Dark Visor and look for the Flying Ing Cache hiding on the far side of the lake. Blow it open to claim this key. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_2/suit_expansions.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_2/suit_expansions.txt new file mode 100644 index 0000000..bd3a424 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_2/suit_expansions.txt @@ -0,0 +1,84 @@ +001 +Missile Launcher +Temple Grounds (GFMC Compound) +You'll find the Missile Launcher packed inside the oversized yellow-marked ordinance crate on the port side of the GF trooper's ship. Blow it open with a blast from the Charge Beam to reveal your prize. +002 +Morph Ball Bomb +Agon Wastes (Agon Temple) +The Bomb Guardian possesses your Morph Ball Bomb. Destroy its oily hide to recover this trusty ability. Refer back to the bosses guide for tips to beat this guardian easily. +003 +Space Jump Boots +Dark Agon Wastes (Judgement Pit) +The vile Jump Guardian inhabiting the Dark Agon Wastes has stolen your Space Jump Boots ability. You'll need to crush this monster in its homeland to recover it. Refer to the bosses guide for tips to survive this heated battle. +004 +Dark Beam +Agon Wastes (Storage D) +You'll be clear to find the Dark Beam once you've claimed the first Dark Temple Key in Dark Agon. Right before finding it you'll have your first confrontation with Dark Samus, for precise directions refer back to the walkthrough as you'll be exploring a fair deal of the Space Pirate's facility in Agon before finding this weapon. +005 +Light Beam +Dark Agon Wastes (Ing Cache 1) +With the Dark Beam in your possession you'll be able to enter the Dark Agon Wastes via the portal in the Command Center. Once inside, follow the rooms from there until you reach the Feeding Pit. Raise the two columns inside by firing Dark Beam shots at the Light Crystals attached to each, then climb up to the black door above. Inside you'll find the Light Beam waiting patiently. +006 +Dark Suit +Dark Agon Wastes (Dark Agon Temple) +You'll need to conquer the enormous Amorbis in the Dark Agon Temple before claiming this prize. Refer back to the walkthrough for directions on where to find all three Dark Temple Keys and the bosses guide for tips to cook Amorbis' hide. +007 +Super Missile +Torvus Bog (Torvus Temple) +The Super Missile is locked away in the Torvus Temple. Upon reaching the temple, deal with the numerous Space Pirate foes you encounter, upon which the force field covering this item will disappear, granting you access to your prize. +008 +Boost Ball +Dark Torvus Bog (Dark Torvus Arena) +Take the northern exit from the Torvus Temple and follow the path to the Torvus Grove. Beyond here lies the Meditation Vista and an inactive portal. Scan the terminal to charge up the portal and step inside. Once in Dark Aether, follow the path till you reach the Dark Torvus Arena (make certain to save your game along the way). Defeat the Boost Guardian you discover there to reclaim this ability. +009 +Seeker Launcher +Temple Grounds (Hall of Honored Dead) +Once you've recovered the Boost Ball from Dark Torvus and have the Super Missile Charge Combo in your arsenal, return to the Temple Grounds. At the Meeting Grounds area, boost yourself up the half-pipe there and roll through the small opening in a nearby cave atop the half-pipe. Boost across the breakable floor sections in the Service Access room and follow the tunnels till you bypass a purple door and enter the Hall of Honored Dead chamber. The Seeker Launcher resides inside a containment unit at the center of this massive chamber. You'll need to use the four Spinners placed at the foot of each giant Luminoth statue. Each Spinner controls one or two rotating locks in the floor around the unit, you'll need to get them all glowing to unlock the unit. Experiment with the locks until you align them all, once you do a large lens assembly will rise from the floor and focus light rays onto the containment unit, shattering it. Now you can claim your prize. +010 +Gravity Boost +Torvus Bog (Hydrochamber Storage) +Once you've secured the Seeker Launcher, head down to the depths of the Torvus Bog. In the Hydrodynamo Station you'll need to scan three terminals to unlock a door at the very base of the shaft. Unlock the first terminal near the bottom of the shaft, then blow off the purple blast shield on a door you can now access. Travel to the Training Chamber beyond and take both paths leading out of this room individually to reach rooms that will ultimately lead back to the Hydrodynamo Station, granting you access to the other two terminals. With all three locks disengaged, travel through the door at the base of the shaft. Keep descending beyond till you reach the Main Hydrochamber. Search for a door on its southern side, then head inside to find this item waiting for you in the deepest region of the planet. +011 +Grapple Beam +Dark Torvus Bog (Sacrificial Chamber) +You'll need to conquer the nasty Grapple Guardian to recover this. Once you've picked up the Gravity Boost, head to the Catacombs chamber in the Torvus Bog and open up access to the inactive Dark Portal there by way of an underwater Bomb Slot. Once in Dark Aether, make your way around to the Undertemple Shaft (you'll pass through the lower section of the Sacrificial Chamber along the way), then from there you can access the main upper section of the Sacrificial Chamber where the Grapple Guardian awaits. Refer to the bosses guide for tips to finish the beast off. +012 +Dark Visor +Dark Torvus Bog (Dark Torvus Temple) +To secure this new visor you'll need to conquer the Chykka Guardian in the Dark Torvus Temple. Refer to the walkthrough and bosses guide for tips to locate the three Dark Torvus Temple Keys and hints to send the massive dragonfly on its way. +013 +Spider Ball +Sanctuary Fortress (Dynamo Works) +Recovering the Spider Ball requires you to locate and defeat the immensely annoying Spider Guardian in the Sanctuary Fortress. Refer to the walkthrough for precise directions, and check out the bosses guide for tips to eliminate this creature with hopefully a less-than painful experience. +014 +Power Bomb +Dark Torvus Bog (Undertemple) +Once you've recovered the Spider Ball, you'll be able to locate this power-up. Dive to the very depths of the Torvus Bog, way down to the Main Hydrochamber where you faced the Alpha Blogg. Reach the Dark Portal on the northern side of the chamber via the Spider Ball track, then transit to Dark Aether. Drop off the ledge you appear on and enter the main chamber to confront the Power Bomb Guardian. Defeating this monster rewards you with your first Power Bomb, check the bosses guide for tips to send it away. +015 +Darkburst +Agon Wastes (Mining Station B) +To recover this item you'll need the Boost Ball and Seeker Launcher. Mining Station B lies beyond the Mine Shaft (beside the Agon Temple). Use the Seeker Launcher to breach the purple blast shielded-door in the Mine Shaft and move through to locate the Darkburst's home. You'll need to play with the mining drill, transit to Dark Aether, then find your way back here to reach the Darkbusrt, refer to the walkthrough for precise directions. +016 +Sunburst +Temple Grounds (Grand Windchamber) +You'll need the Boost Ball, Power Bombs, Seeker Launcher and Grapple Beam to secure this item. Head to the Path of Eyes region in the Temple Grounds and proceed through the green blast shielded-door on the northern side of the area. Proceed through the Windchamber Gateway and blow off the yellow blast shield covering the next door with a Power Bomb. Inside is the huge Grand Windchamber - the Sunburst is waiting atop the large structure in the center of the area. But to reach it, you'll need to first travel to Dark Aether via the nearby portal. Once there, see the Spinners positioned around the central structure? Use each one to rotate one of the half-circle rings attached to the central structure. Firstly, rotate all the rings and line them up so they all glow yellow. Travel around to the front of them, lock onto all four pods attached to each ring with the Seeker Launcher and open up to activate the system. Doing so will raise two metal arms outward from the structure. Rotate all the rings again to the opposite side so they all glow blue. Travel around to the front of them again and use the Seeker Launcher to activate the system. Two more arms will raise out around the structure before all the control rings promptly fall off into the chasm below. Return to Aether and use the Grapple Points on the extended arms to reach the lone platform where a Kinetic Orb Cannon resides, then simply jump in the cannon to be launched atop the structure where the Sunburst awaits. +017 +Echo Visor +Sanctuary Fortress (Aerie) +You'll need the Spider Ball and Power Bombs to reach this. Return to the Main Gyro Chamber and travel up to the door leading to the Sanctuary Temple. Destroy the fallen canisters above the Bomb Slot at the observation window, then energize it to bring up three coloured power conduits on the window. Rotate the corresponding nodes to line up with the correct conduits to cause a second Bomb Slot to rise from the floor. Energize this one to shut down the rotating inner gyro wheel, revealing a Spider Ball track running along it. Go down inside the gyro chamber and climb up along the inner gyro ring. Boost yourself into the cracked glass window to gain access to the yellow door on the northern side of the room. Blow the blast shield off the door with a Power Bomb and enter the room beyond to witness Dark Samus take out three Dark Pirate Troopers. Follow the beast around and exit the room via the next door to reach the base of a huge elevator shaft. You'll now need to take down Dark Samus before recovering this - refer back to the bosses guide for tips. With the area clear, step out through the wall section Dark Samus destroyed and walk along the balcony you find to locate an inactive Dark Portal. Power it up and transit to Dark Aether. Once there, walk around the balcony and climb up the Spider Ball track at the end to access the main chamber. See the Spinner across the other side of the room? Use it to rotate the Spider Ball track assembly in the center of the chamber. Then, climb up the tracks and boost yourself up to a ledge above. Jump across to the inactive Light Portal and travel back to Aether. Finally, jump across to the ledge ahead where your prize awaits. +018 +Screw Attack +Sanctuary Fortress (Vault) +You'll pick up the Screw Attack after securing the Echo Visor. It's a fairly long trip to the Vault for this item, so refer to the walkthrough for complete directions and details on what to do once you're there to secure this lovely new toy. +019 +Annihilator Beam +Ing Hive (Hive Temple) +You'll need to locate all three Hive Temple Keys (and a number of items) before unlocking the Hive Temple. Refer to the walkthrough for details and directions, then refer to the bosses guide for tips to defeat the guardian of the temple, Quadraxis, to claim this deadly beam weapon. +020 +Light Suit +Great Temple (Main Energy Controller) +Simply restore the planetary energy to all three temples of Aether and visit U-Mos to be granted the ultimate protection available to Samus. Easy. +021 +Sonic Boom +Dark Agon Wastes (Ing Cache 2) +The Annihilator Beam and Screw Attack will allow you to track this final item down. Head to the Phazon Site at the Dark Agon Wastes to find the area inhabited by three Dark Tallon Metroids. Deal with all three customers and look up to see a gray door way up on an out-of-reach ledge. Climb atop the middle of the three floating platforms, then simply Screw Attack across to the ledge to reach it neatly. Open the door with the Annihilator to find the Sonic Boom awaiting you in the following chamber. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_3/energy_cells.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_3/energy_cells.txt new file mode 100644 index 0000000..4c9c82d --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_3/energy_cells.txt @@ -0,0 +1,36 @@ + +001 +GFS Valhalla - Docking Bay 5 +Upon landing aboard the GFS Valhalla, wander over to the wrecked Stiletto fighter on the right deck to discover this loose Energy Tank resting in front of the craft's lifeless engines. + +002 +Bryyo - Hangar Bay +On your first visit to the Hangar Bay you'll be ambushed by a number of Warp Hounds and Reptilicus Hunters. Clear all hostiles in the area to restore access to the lift in the corner, then ride it up to a damaged platform. Look for two sealed vents on the wall; bomb them open and enter the correct one to find yourself whisked up to a small alcove above where this Energy Cell station awaits. + +003 +Norion - Generator B +Once you've picked up the Plasma Beam you'll be clear to locate this Energy Cell, but you should probably wait till after finding the Nova Beam to make your job easier. Head to the Cargo Hub area and repair the damaged circuit panel beside the sealed door. Proceed through and beyond to ultimately find yourself at Generator B - home to a nasty Metroid Hatcher. If you bring along the X-Ray Visor and Nova Beam it'll be a complete pushover, otherwise you'll be in for a long fight (refer to the bosses guide if you need tips). With the creature gone and all the icky Phazon deposits expelled you'll be clear to enter the tunnel network lining the chamber. Move through the tunnels to eventually find yourself at this Energy Cell's station. + +004 +Bryyo - Hidden Court +This Energy Cell requires a hefty trek to uncover. Firstly, you'll need the Ship Grapple to uncover it. Work your way towards picking up Ship Missile BR.03 and Energy Tank BR.04. This will ultimately lead you to the Machineworks Bridge. Upon extending half the bridge connecting the chasm and picking up the Energy Tank, return to your ship and fly to the Thorn Jungle Airdock. Head for the North Jungle Court and search there for a huge portable generator capable of being lifted. Summon your ship to raise the generator and store it away for safekeeping. Climb up to the generator's alcove and look for a small opening revealed underneath its former resting place. Roll through and proceed ahead to find yourself down the opposite end of the Machineworks Bridge. Use the Spinner device to extend this half of the bridge, finally bridging the gap. Cross over and head for the Hidden Court from here. Once there, look up at the huge Fuel Gel pump and switch on the Command Visor. Command your ship to set the portable generator down atop the pump system - watch as the generator instantly energizes the system. The small Energy Cell station inside the pump will swivel around, giving you clear access to your prize. + +005 +SkyTown - Xenoresearch B +Upon receiving the Ship Grapple upgrade head back towards the Chozo Observatory and continue exploring Eastern SkyTown. Eventually you'll discover a pod structure filled with the husks of Space Pirate foes. Explore deeper into the Xenoresearch areas past all the Phazon Metroids contained there to finally locate this Energy Cell station beside a containment pod housing the Seeker Missile upgrade. Tear the cover off the Energy Cell station by way of the Grapple Lasso to gain access. + +006 +Pirate Homeworld - Command Courtyard +On your first trip through the Command Courtyard you'll need to avoid contact with the acid rain. Make your way to the far corner where the ventilation fans reside and climb up the Grab Ledge there. Roll through the tunnel network; eventually you'll emerge directly above the ventilation fans to where this Energy Cell station awaits. + +007 +Pirate Homeworld - Metroid Processing +During your travels through the Pirate Research region you'll discover a chamber inhabited by a number of docile Phazon Metroids in containment chambers. Look for a control terminal beside a sealed wall - use the X-Ray Visor to unlock the door successfully and reveal a lift. Ride the lift down below where you'll discover this Energy Cell station along with a damaged circuit panel. + +008 +SkyTown - Ballista Storage +Return to the Ballista Storage (where you picked up the Boost Ball) with the Grapple Voltage in your inventory. See the pair of ventilation fans flanking a central object on one side of the chamber? Overload both fans with energy via the Grapple Voltage to reveal this Energy Cell station between them. + +009 +Pirate Homeworld - Phazon Quarry +Right after securing the Nova Beam upgrade, head back to the Phazon Quarry region via the Drill Shaft 2 area. Once there you'll find this Energy Cell station down the other end of the balcony overlooking the quarry. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_3/energy_tanks.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_3/energy_tanks.txt new file mode 100644 index 0000000..06f5883 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_3/energy_tanks.txt @@ -0,0 +1,56 @@ + +001 +Ventilation Shaft +Of all the items in the game you certainly can't miss this Energy Tank. Early on in the game during the Pirate attack on the Olympus you'll discover this item snugly tucked inside a tunnel in the Ventilation Shaft. Lay a bomb to break through the glass container to access your prize. + +002 +Substation East +As you enter Substation East from the Cargo Hub you'll spot this Energy Tank sitting just inside the tunnel running along the wall around the exposed floor. Simply activate the Morph Ball and jump inside to retrieve it. + +003 +Reliquary II +From the giant Gateway chamber, release both locks on either side of the region to unlock the large ornate door on the west side. Travel through and clear the obstruction inside the narrow tunnels lining the walls of the chamber. Roll through and head right to discover a door beyond guarded by a few Hoppers. Enter the chamber to find this Energy Tank waiting inside. + +004 +Vault +Right after landing at the Thorn Jungle Airdock you'll be greeted by two Armored Pirate Troopers in the Overgrown Ruins area. Deal with them both and look for a section of the wall on the right covered in crystallized Fuel Gel. Send a Missile into the wall to reveal a hidden door beyond, then step through to discover this Energy Tank inside. + +005 +Ruined Shrine +Travel to the base of the Ruined Shrine beyond the Hidden Court to discover the aging remains of a statue's arm. Scan the arm to learn that age has considerably weakened the structure. Lay a Morph Ball Bomb beside it to reveal this Energy Tank hidden within. + +006 +Machineworks Bridge +Right after securing Ship Missile BR.03 at the Colossus Vista, head through the now-revealed door to locate the Machineworks Bridge. Use the nearest Spinner device to rotate a bridge over the bottomless pit. Cross the bridge to the center and look up - see the Energy Tank floating above? Wait for a pair of Wall Jump surfaces to move towards you, then quickly scale them with the Screw Attack to reach the Energy Tank before the walls move away. + +007 +Bryyo Ice - Tower +Once you've found the Spider Ball upgrade, return to Bryyo Ice and the massive Hall of Remembrance where you discovered the Screw Attack. Fly over the region and enter the Tower shaft beyond. Scale up the network of Spider Ball tracks lining the walls to eventually locate this Energy Tank high up at the very top. + +008 +Steambot Barracks +Defeat the Steamlord and its Steambot cronies at the Steambot Barracks to receive this Energy Tank. Refer to the bosses guide for tips to shut the rampant droids down. + +009 +Arrival Station +Upon receiving the Boost Ball upgrade, return to the Arrival Station area and leap up to the Grab Ledge above the open balcony. You'll discover a Kinetic Orb Cannon above - use the Boost Ball to restore power, then hop in to launch yourself over to the floating satellite. This Energy Tank awaits aboard the age-old construct. + +010 +Xenoresearch A Lift +You'll spot this Energy Tank inside a containment pod on your way through the Phazon Metroid-infested Xenoresearch area. The pod's shield will deactivate once you've picked up the Seeker Missile, so as you backtrack through here simply launch a Missile at the pod to gain access to your prize. + +011 +Zipline Station Charlie +Soon after locating the Spider Ball upgrade you'll find yourself crossing back over Zipline Station Charlie via a network of Spider Ball tracks thanks to the inoperable Zipline Cable. Keep your eyes open for this Energy Tank around halfway along the network, concealed within a circular track. + +012 +Pirate Research - Scrapworks +As you travel through the Scrapworks area, keep an eye out for this Energy Tank resting at the very top of the region. Use a double bomb-jump to reach it easily. + +013 +Pirate Research - Metroid Creche +Defeat the Metroid Hatcher located here (refer to the bosses guide if you need help), and launch Samus up to the network of tunnels in the ceiling by way of the Spinner where the Metroid Hatcher emerged. As you enter the first tunnel, roll along and look for a Spider Ball track up in the ceiling. Follow it along and hop down into another short tunnel where this Energy Tank awaits. + +014 +Munitions Locker +Ride up the Auxiliary Lift and move onward to the Port Observation Deck. Just inside on the right you'll find a sealed door; restore power by inserting an Energy Cell into the adjacent terminal. With the door accessible, enter the Junction A area beyond and head through the eastern door to locate this Energy Tank waiting in a small chamber. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_3/maps.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_3/maps.txt new file mode 100644 index 0000000..6658973 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_3/maps.txt @@ -0,0 +1,27 @@ +001 +gfs_olympus +G.F.S. Olympus + +002 +norion +Norion + +003 +bryyo +Bryyo + +004 +elysia +Elysia + +005 +gfs_valhalla +G.F.S. Valhalla + +006 +pirate_homeworld +Pirate Homeworld + +007 +phaaze +Phaaze diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_3/missile_expansions.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_3/missile_expansions.txt new file mode 100644 index 0000000..c4e1f5f --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_3/missile_expansions.txt @@ -0,0 +1,204 @@ + +001 +GFS Olympus (Munitions Storage) +The Missile Launcher awaits aboard the Olympus in the Munitions Storage chamber. Scale the vast Repair Bay A chamber and the enter the small chamber to find it waiting inside. + +002 +Cargo Hub +As you first enter the Cargo Hub you'll see a number of unfortunate fallen GF Marines scattered around the chamber. Take out the rounds of ambushing Aeromines and return to the entrance. See the small chute in the wall nearby? Use the Grapple Lasso to rip off a panel beside the chute and activate the terminal to slide it open. Roll through and make your way through the network of narrow tunnels to eventually discover this Missile hiding inside (although watch out for the Jolly Roger drone). + +003 +Docking Hub Alpha +You'll need either the Grapple Swing or Screw Attack to reach this. Touch down at Docking Hub Alpha and look for a hidden alcove behind your ship. You'll spot this Missile directly across a short chasm, simply use the Grapple Swing or the Screw Attack to reach it. + +004 +Substation West +Upon scoring the Plasma Beam from Ghor at SkyTown, return to the Cargo Hub and repair the damaged circuit panel present. Enter the following chamber and use the Morph Ball to enter the narrow tunnel lining the curved wall. This Missile awaits at the far end, but watch out for the pistons constantly extending and retracting; you don't want to find yourself pushed off onto the heated coils below. Take care while rolling through the tunnel and stay put up against pistons that aren't glowing. Time your movement to reach the Missile. + +005 +Maintenance Station +You'll need the Ice Missile upgrade to find this. Return to the Maintenance Station room and look for a white blast-shielded door. Simply knock the shield off with an Ice Missile and enter the chamber beyond to locate this Missile Expansion inside. + +006 +Cargo Dock A +The Spider Ball will grant you access to this Missile. Head for the Cargo Dock A area and look for a Spider Ball track hidden along a wall in the south-west corner. Simply follow the track to eventually find it leading straight to this Missile high above. + +007 +Grand Court Path +From the entrance of the Grand Court Path chamber, climb up the narrow tunnel and look for a large Fuel Gel statue resting inside an alcove on the right. Destroy it with a Missile and climb up. Leap over the gap to another alcove on the opposite wall and follow the path around. Jump across the opening where a large block of ice resides below to easily reach this Missile's alcove ahead. + +008 +Hillside Vista +On your first visit to the Hillside Vista, blow open a rock near the entrance and roll through inside the narrow network of tunnels. Gather enough Snatchers to send Samus on a skyward trip and quickly hug the left side of the area to fly up a tunnel where this Missile awaits. + +009 +Crash Site +After activating the map station aboard the downed GF frigate, go outside and head back inside the service duct you originally used to enter the ship. Climb up the network of tunnels while watching out for all the active circuitry - eventually you'll pop back outside atop one of the ship's wings. This Missile awaits right at the tip of the wing. + +010 +Bryyo Fire - Main Lift +Enter the narrow tunnel network inside the Main Lift and gather enough Snatchers to float Samus skyward. Hold left as you ascend and quickly drop a bomb just as you reach the highest platform near the Korba. Roll through the tunnel you'll find ahead to discover this Missile snugly at the end. + +011 +Bryyo Fire - Gel Hall +An easy find, simply wait for the Golem head in this chamber to rotate and face the thick yellow cable. Send a Charge Beam blast at the head to ignite the Fuel Gel and burn through the cable. With the cable torn apart a platform will promptly fall from the ceiling bearing your prize. + +012 +Bryyo Fire - Gel Hall +Once you've picked up the Ice Missile upgrade, return to this chamber and stand atop the platform where you discovered the previous Missile. See the tunnel leading around the corner out of sight? Use Ice Missiles to create handy stepping stones in the Fuel Gel; around the corner you'll discover this Missile waiting. + +013 +Bryyo Fire - Gel Refinery Site +From the Gel Hall chamber, see the white blast-shielded door on the far side of the Fuel Gel pool? Use Ice Missiles to create stepping stones and another to breach the shield. Enter the following chamber and use the Grapple Swing to pass over the deadly chasm below (shoot the red switches on each Grapple Point to extend them - and don't look down). Beyond you'll find yourself back outside at the Gel Refinery Site. Look for weakened support pipes around the corner, use the Grapple Lasso to rip it off and discover this Missile right behind it. + +014 +Reliquary III +You'll need the Ice Missile upgrade to find this. Return to the Grand Court and use the Grapple Points above to reach a white blast-shielded door hiding in an alcove. Blow it off with an Ice Missile and enter the chamber beyond to locate this Missile Expansion among two of the only Geemers you'll see in the game. + +015 +Jungle Generator +As you enter the Jungle Generator chamber you can't miss the Bryyo Lore mural directly ahead. This Missile shares the alcove right in front of it. + +016 +Generator Hall North +Upon dismantling both anti-aircraft turrets and on your way back to the Jungle Generator you'll pass through the Generator Hall North region. This Missile rests inside a sealed-off alcove along a wall, simply use the pump terminal nearby to rotate the lock open to retrieve it. + +017 +Bryyo Fire - Imperial Hall +You'll require the Plasma Beam to reach this Missile. Head to the Gel Refinery Site and melt all the ice adorning the far wall. See all the narrow tunnels etched into the wall? Use the Morph Ball and enter the network, dropping bombs on the small exhaust ports to launch yourself along the vertical sections. Move around the network, watching out for flame exhaust vents as you go. Eventually you'll find yourself dropped off at a completely frozen door. Melt the ice and head inside. Swing around the Refinery Access to find yourself back in the Imperial Hall. Move ahead to find two moveable panels along the wall. Rip them down with the Grapple Lasso and use both to reach the alcove ahead where this Missile waits patiently. + +018 +Gateway +With the Plasma Beam secured in your inventory, head for the Gateway chamber. Climb up to the once-sealed door and enter the narrow tunnels along the wall in the chamber inside. Roll right and exit the tunnel. See the frozen Reptilicus ahead on the far wall? Melt it with the Plasma Beam to reveal a narrow tunnel. Roll through to find this Missile waiting on the right. + +019 +Falls of Fire +The Screw Attack will help you reach this. Head for the Falls of Fire and use the Golem to reach the bottom of the huge shaft. Once at the base you should spot a short series of Wall Jump surfaces leading skyward. Use the Screw Attack and climb up the shaft to find this Missile waiting above. + +020 +Fuel Gel Pool +You'll need the Ice Missile upgrade, Plasma Beam and Ship Grapple to reach this. Head for the Hidden Court and climb up to the orange door on the north side (you may need the Screw Attack to climb up successfully). Proceed through and work your way around the following region to locate the Fuel Gel Pool. Use the Ship Grapple to remove the gigantic Golem head from the pool and freeze the Fuel Gel spouts to climb up to the alcove where this Missile awaits. + +021 +Fuel Gel Pool +The Hazard Shield will help you safely reach this Missile. Back in the Fuel Gel Pool, once you've removed the Golem head by way of the Ship Grapple, dive into the oily mess and look for a hidden cave underneath the spout on the far side. Inside awaits this Missile Expansion. + +022 +Hidden Court +Travel to the Hidden Court and climb up to the orange door on the north side by way of the Screw Attack or after opening up the gate on the south side and revealing a Grapple Point. Leap across to the half-pipe and launch yourself up to the right side to find this Missile hiding in an alcove there. + +023 +Hall of the Golems +You'll need the Grapple Voltage and Spider Ball to find this. Head for the Hangar Bay and exit the region via the orange door. Move through to ultimately find yourself at the Hall of the Golems. Look for the Golem on the right and use the Grapple Voltage to power the seal covering its Bomb Slot. Energize the Golem with a Morph Ball Bomb and watch as it powers a huge network of Spider Ball tracks leading around the chamber and up to this Missile Expansion. Use the Spider Ball and make your way across the tracks, watching out for electrical activity along the way. Use the Boost Ball and double bomb-jumps to clear the final sections of track to reach this Missile. + +024 +Burrow +Once again in the Hall of the Golems, use an Ice Missile to break the cover off the middle Golem's Bomb Slot. Energize the Golem and watch as it freezes the entire Fuel Gel falls. Climb up the frozen structure and exit the chamber ahead (watch out for the pathetically annoying Fargul Hatcher). Enter the narrow opening you find to locate a narrow network of tunnels filled with crystallized Fuel Gel. Move to the bottom and use Morph Ball Bombs to break through the formations, then head for the left side where this Missile awaits. Use a double bomb-jump to reach its alcove. + +025 +Ancient Courtyard +With the Boost Ball in your inventory, head for the Ancient Courtyard. Once there, look up at where the massive Maldium-laced gate once resided. See the Missile Expansion up there? Use the Boost Ball in the half-pipe where the gate once stood to reach it easily. + +026 +Bryyo Fire - Temple of Bryyo +The Hazard Shield is most certainly needed to retrieve this Missile Expansion, along with the X-Ray Visor and Nova Beam. Head to the Temple of Bryyo and clear any hostiles from the area. Look for a Phazite shield covering a portion of the wall on the far side and use the X-Ray Visor in tandem with the Nova Beam to strike the four switches hidden on the other side. A floor section nearby will slide open, activate the Morph Ball and dive into the Fuel Gel. Follow the terrain around to eventually locate this Missile wading in the oil in a corner. + +027 +Transit Hub +On your first trip to the Transit Hub area you'll spot this Missile Expansion in clear sight within a narrow tunnel. Use the Morph Ball and double-bomb jump to reach it easily. + +028 +Barracks Access +Step inside the Barracks Access and look for the Steamlord ahead looming down at you. Walk towards the laser fields sweeping across the area ahead and activate the Morph Ball. Drop down and look behind you to spot this Missile sitting not far away. + +029 +Skybridge Hera +This sneaky customer resides inside a small pillar at the Skybridge Hera region. Listen for the humming sound near the entrance beside the Junction area, you'll find it hidden inside a small opening on the side of the pillar. Use the Morph Ball to reach inside. + +030 +Main Docking Bay +Right after defeating Ghor and scoring the Plasma Beam, climb back up to the observation window overlooking the landing pad. Ghor's reckless rampaging has caused a huge pillar to crash through the window. Melt the damaged metal debris covering the pillar with the Plasma Beam to find this Missile Expansion hidden inside. + +031 +Eastern SkyTown - Gearworks +After receiving the Ship Grapple upgrade, head back to the Gearworks area. As you arrive you'll witness a Space Pirate ATC arrive and do a number on the huge gear system nearby. Destroy the craft then use the Screw Attack to snag the floating Missile Expansion where the gears once were. + +032 +Eastern SkyTown - Botanica +Upon reactivating the holoprojector in the Chozo Observatory, climb up to the orange door above and head through. Move through the leafy Botanica area and turn around as you reach the highest point of the region. Use the Screw Attack to backtrack across the elevated alcoves; you'll find this Missile Expansion waiting in an alcove directly above the entrance of the area. + +033 +Eastern SkyTown - Concourse +Remember finding an elevator in the Concourse area which you couldn't activate? Eventually after finding the Seeker Missile you'll find yourself above the elevator where its locking system lives. From here, turn around and look for a narrow opening in the wall. Roll through to discover this Missile Expansion waiting beyond. + +034 +Construction Bay +The Screw Attack is needed to reach this. Head for the Construction Bay area and climb up to the entrance leading inside to the Ballista Storage. Look out over to the huge floating structure possessing all the Grapple Points on its underside. See the small alcove atop it where a Databot hovers? Use the Screw Attack to reach it; this Missile Expansion awaits there. + +035 +Powerworks +Right after picking up the Spider Ball you'll exit the area by way of a network of Spider Ball tracks at the base of the giant pod structure. Work your way across till you reach a platform where a Spider Ball track leads skyward up a shaft. Turn around and look for another track leading off around the corner - follow it to locate this Missile. + +036 +Steambot Barracks +Return to the Steambot Barracks after you've picked up the Spider Ball upgrade. Roll through the narrow tunnels up at the top of the chamber to eventually find a set of Spider Ball tracks leading up to this Missile Expansion. + +037 +Eastern SkyTown - Concourse Ventilation +Travel to the outside section of this chamber adjacent to the Chozo Observatory and use the Spider Ball to ascend the tracks running up a wall. You'll discover this Missile waiting atop a platform at the very top. + +038 +Pirate Command - Command Courtyard +On your first trip to the Command Courtyard you'll need to power down the ventilation fans in the corner of the chamber to proceed. As you roll through the narrow tunnels leading around to the Energy Cell station you'll spot this Missile Expansion hiding in an alcove. Roll around to the opposite side of the area and follow the left path upon reaching a junction to eventually find your way to the Missile. + +039 +Pirate Command - Command Station +Your first trip to the Command Station will be through a set of narrow tunnels under the floor. Follow the right path at the blue-tinted lift to locate this Missile Expansion hiding below a force field. + +040 +Pirate Command - Security Air Lock +After securing the X-Ray Visor upgrade you'll eventually find yourself inside the Security Air Lock. This time you're on the right side of the gate, simply stroll forward to pick up this Missile Expansion waiting inside the gate. + +041 +Pirate Research - Scrapvault +This Missile awaits high above in the Scrapvault region. Look high above the head of the giant deceased specimen to see the Missile Expansion atop a platform. Climb up there and use the Grab Ledge to reach it easily. + +042 +Pirate Research - Metroid Processing +Extract the Energy Cell in this region powering the Metroid's force fields. Deal with all the Phazon Metroids once they break out, then look for this Missile Expansion resting inside one of their alcoves. + +043 +Pirate Research - Creche Transit +Enter the Creche Transit area by way of the Metroid Processing chamber and look for a small cracked covering in the corner. Blow it open with a Morph Ball Bomb and roll through the narrow tunnel beyond. Use the Boost Ball to rotate the circular junction out under the acid rain to give yourself a clear path to this Missile ahead. + +044 +Pirate Research - Craneyard +Head for the Craneyard after receiving the Spider Ball upgrade and follow the Spider Ball tracks there. Once you've found yourself at the base of the tall structure possessing two rotating wall sections, use the Spinners at the base to line up a path over to the top-right corner of the structure. Climb up to find this Missile Expansion waiting at the end of a short red chute. + +045 +Pirate Mines - Phazon Quarry +On your initial trip to the Mining Site you'll be assaulted by a number of Assault Pirate Troopers and Commando Pirates in the Phazon Quarry. Clear them all out, then summon the huge mining drill via the terminal hidden in a corner. Instruct the drill to mine the wall on the right side to reveal this Missile Expansion hiding within it (I wonder how it got there?). + +046 +Pirate Mines - Phazon Mine Entry +Upon securing the Nova Beam, exit the Main Cavern via the green door and look for a large Phazite wall covering in the following chamber. Switch on the X-Ray Visor and fire at each lock pod to release the Phazite wall - revealing this Missile Expansion inside a small room beyond (along with a pesky Phazon Metroid). + +047 +Pirate Command - Lift Hub +You'll need the Grapple Voltage to find this one. Return to base of the Lift Hub and look for a purple terminal beside a sealed elevator shaft door. Energize the terminal via the Grapple Voltage to crank the door open. Inside you'll spot this Missile beyond a rickety lift container. Step inside the lift to dislodge it slightly, then jump out and shoot the cable atop to break it free. Leap across the gap to reach this Missile. + +048 +Pirate Command - Flux Control +With the Spider Ball upgrade secured, return to the Flux Control area and travel down to the base of the area. Once there pull the tunnel covering over the left tunnel and roll through the right to find yourself inside the shaft of the giant energy turbine. Climb up the Spider Ball track to find this Missile Expansion not far up the shaft. + +049 +MedLab Alpha +From the wrecked Repair Bay, head up through to the Security Access corridor. Travel west to eventually locate a chamber with a pile of wreckage on the far wall. Use the Grapple Lasso to clear off all the debris, then enter a narrow opening in the corner and roll through to discover this Missile Expansion hidden under the floor (although watch out for Phazon Hoppers). + +050 +Auxiliary Lift +Upon re-establishing power to the elevator in the Auxiliary Lift, look for a narrow opening on the east wall at the top of the shaft. Go inside and travel left at the base of the narrow tunnel to discover this Missile Expansion snugly tucked away. + +051 +Weapons Cache +Use two Energy Cells in the Stairwell area to raise the damaged ramp, granting you access to the floor above. Climb up and enter the Weapons Cache to find this Missile Expansion waiting inside. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_3/red_phazoids.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_3/red_phazoids.txt new file mode 100644 index 0000000..2503714 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_3/red_phazoids.txt @@ -0,0 +1,40 @@ + +001 +Jousting Field +Destroy the Leviathan on Bryyo to reveal this Phaazoid. + +002 +Gel Processing Site +Destroy the Leviathan on Bryyo to reveal this Phaazoid. + +003 +Grand Court +Reveal the Red Phaazoid by activating the unit on the downed Mogenar's head (use the X-Ray Visor). Once the Mogenar rises and reveals a Phazon pool, the Red Phaazoid will emerge. + +004 +Hoverplat Docking Site +Destroy the Leviathan on Elysia to reveal this Phaazoid. + +005 +Construction Bay +Destroy the Leviathan on Elysia to reveal this Phaazoid. + +006 +Concourse Ventilation +Destroy the Leviathan on Elysia to reveal this Phaazoid. + +007 +Transit Station 0204 +Destroy the Leviathan on the Pirate Homeworld to reveal this Phaazoid. + +008 +Phazon Harvesting +Destroy the Leviathan on the Pirate Homeworld to reveal this Phaazoid. + +009 +Proving Grounds +Destroy the Leviathan on the Pirate Homeworld to reveal this Phaazoid. + +010 +Metroid Creche +Destroy the Leviathan on the Pirate Homeworld to reveal this Phaazoid. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_3/ship_missile_expansions.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_3/ship_missile_expansions.txt new file mode 100644 index 0000000..a8b3dc0 --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_3/ship_missile_expansions.txt @@ -0,0 +1,36 @@ + +001 +Bryyo (Hangar Bay) +Upon securing the Ice Missile upgrade, head to the downed GF frigate and make your way through the Falls of Fire by freezing the Fuel Gel spouts along the chasm. Explore the regions beyond, move through the Hidden Court area and up the Ruined Shrine to ultimately find yourself at the Hangar Bay. At first glance the area seems completely deserted, but step towards the lift in the corner of the chamber or the Missile upgrade terminal to see otherwise. Repel the Reptilicus Hunter invasion to secure the area and bring the systems back online. First things first, you'll need to open up the hangar bay door to allow your ship to enter. Even though your ship isn't present, raise the upgrade station by way of the terminal beside the landing pad. Ride up the lift in the corner to the top of the damaged platform, then leap across atop the raised upgrade station. Make your way over to the command station by way of the Grab Ledge (and extend a platform with the Grapple Lasso). Once inside, activate the terminal to open up the hangar doors. Then simply scale back down to ground level, lower the upgrade station, summon your ship then hit the switch again to receive the Ship Missile upgrade. + +002 +Auxiliary Dynamo +On your way through the Auxiliary Dynamo (during your attack on the second Leviathan shield generator) you'll spot a narrow tunnel network wrapping around the bend. Travel around the corner to discover a tall piston stuck in place, blocking the tunnel. Use the Grapple Lasso to pull it down, then backtrack and enter the tunnel using the Morph Ball. Follow the tunnel along, zip up the piston and roll onward to discover this Ship Missile waiting ahead. + +003 +Bryyo Ice - Hall of Remembrance +Right after claiming the Screw Attack at the Hall of Remembrance, use it to leap across to the far side of the canyon. Enter the Tower shaft and scale up the Wall Jump surfaces. Back outside in the Hall of Remembrance, send a Missile into the open palm of the gigantic Chozo statue to rotate it flat. Use the Screw Attack and cross the chasm to land on the hand before it rotates back. Look over at the giant Golem statue - you'll spot this Ship Missile sitting atop the head in clear view. + +004 +Colossus Vista +This Ship Missile will have you journeying across Bryyo to access. Firstly, you'll need the Ship Grapple to start the sequence. Head to the Hidden Court region and climb up to the orange door on the north side (you may need the Screw Attack to help). Go inside and cross through the following area to discover the Fuel Gel Pool. See the giant Golem head resting idly in the oil? Summon your ship to lift it out of the pool. Leave this area and head back towards the Hangar Bay. Once there, exit via the orange door and move through to the Hall of the Golems chamber. Use the Plasma Beam to reveal the Bomb Slot on the left-most Golem and power it up. The Golem will promptly spew flames and burn away a sealed door nearby, head through when it powers down. Inside you'll discover a grand sight: the colossal body of a Golem overlooking a cage where your prize awaits. Notice the Golem's body is headless? Simply command your ship to set the Golem head down on the body and watch as it pulverises the cage with one of its arms, leaving you clear to pick up this Ship Missile Expansion. + +005 +Security Station +The Plasma Beam will grant you access to this Ship Missile. Travel to the Security Station and look up above the orange door - see the item waiting at the mouth of a narrow tunnel? Move around to the other side of the area to find a group of damaged metal debris blocking an open tunnel near the massive gears. Use the Plasma Beam to melt them, then simply enter the tunnel with the Morph Ball and roll on through to eventually reach the Ship Missile. + +006 +Hoverplat Docking Site +The Spider Ball is needed to reach this Ship Missile. Travel to the Hoverplat Docking Site and use the Screw Attack to reach the central cluster of floating pods. See the winding Spider Ball tracks in the air? Make your way up there to find this Ship Missile hidden down one end of the network. + +007 +Pirate Research - Scrapworks +On your first trip through the Scrapworks you may spot this Ship Missile near a lone Spider Ball track. You can't reach it without the Spider Ball, so return here once you've picked it up at SkyTown. With the Spider Ball in hand, use the half-pipe below to boost yourself up to the Spider Ball track and carefully use the small blocks below the Ship Missile to leap up to your prize. + +008 +Pirate Research - Processing Access +You'll need the Screw Attack, X-Ray Visor and Nova Beam to locate this item. Head to the Processing Access beyond the Scrapvault and travel halfway down the corridor. See the two small Phazite panels on either side of the hallway? Use the Nova Beam and X-Ray Visor to activate the switches hidden behind each. Watch as a series of Wall Jump surfaces emerge above, use them to reach this Ship Missile Expansion's alcove higher up. Once there, use a few Missiles to penetrate the energy field surrounding this item. + +009 +MedLab Alpha +You'll need the Seeker Missile and two spare Energy Cells to locate this item. Head to the Auxiliary Lift and ride it topside. Move through to the Port Observation Deck and travel down to the to the far end (watch out for hostiles). Dismantle the blast shield you find with the Seeker Missile and proceed through to discover the Xenoresearch Lab. Make your way down to the main chamber below to discover this Ship Missile hidden under the floor in a narrow tunnel. Slot two Energy Cells into the disabled power station to open up access to the Ship Missile... except watch as it's sneakily whisked away through an open hatch. Quickly follow it through a network of tunnels to finally catch up to it down in MedLab Alpha. \ No newline at end of file diff --git a/MetroidMapGuardian/src/resources/text/metroid_prime_3/suit_expansions.txt b/MetroidMapGuardian/src/resources/text/metroid_prime_3/suit_expansions.txt new file mode 100644 index 0000000..b38d22c --- /dev/null +++ b/MetroidMapGuardian/src/resources/text/metroid_prime_3/suit_expansions.txt @@ -0,0 +1,76 @@ +001 +Missile Launcher +GFS Olympus (Munitions Storage) +The Missile Launcher awaits aboard the Olympus in the Munitions Storage chamber. Scale the vast Repair Bay A chamber and the enter the small chamber to find it waiting inside. +002 +Grapple Lasso +Norion (Docking Hub Alpha) +You can't miss the Grapple Lasso - find it inside a small chamber right after landing on Norion. Open the door by shooting the red lock switch. +003 +Phazon Enhancement Device (PED) Suit +GFS Olympus (MedLab Delta) +You'll receive the PED Suit automatically after Samus awakens from her month-long sleep following the Pirate attack on Norion. This gift from the Federation will remain with her throughout the rest of the game, so be sure to accustom yourself with the ins and outs of Hypermode. +004 +Grapple Swing +Bryyo (Reliquary I) +From the giant Gateway chamber, open the sealed door by releasing both locks and make your way through to the Grand Court. Conquer the pair of Reptilicus Hunters ambushing you there and move through to the Hillside Vista. Make your way to the opposite cliffside via the tunnels along the wall (use the Snatchers to traverse the tunnels, but watch out for the Korba). Use the Grapple Lasso and a Missile to dismantle the statue covering the door you find, then simply step inside the chamber to discover your prize waiting inside. +005 +Ice Missile +Bryyo (Bryyo Fire - Temple of Bryyo) +You'll need to conquer Rundas in the Temple of Bryyo to secure this upgrade. Refer to the bosses guide for tips to win this upgrade. +006 +Ship Missile +Bryyo (Hangar Bay) +Upon securing the Ice Missile upgrade, head to the downed GF frigate and make your way through the Falls of Fire by freezing the Fuel Gel spouts along the chasm. Explore the regions beyond, move through the Hidden Court area and up the Ruined Shrine to ultimately find yourself at the Hangar Bay. At first glance the area seems completely deserted, but step towards the lift in the corner of the chamber or the Missile upgrade terminal to see otherwise. Repel the Reptilicus Hunter invasion to secure the area and bring the systems back online. First things first, you'll need to open up the hangar bay door to allow your ship to enter. Even though your ship isn't present, raise the upgrade station by way of the terminal beside the landing pad. Ride up the lift in the corner to the top of the damaged platform, then leap across atop the raised upgrade station. Make your way over to the command station by way of the Grab Ledge (and extend a platform with the Grapple Lasso). Once inside, activate the terminal to open up the hangar doors. Then simply scale back down to ground level, lower the upgrade station, summon your ship then hit the switch again to receive the Ship Missile upgrade. +007 +Hyper Ball +Bryyo Seed (Bryyo Leviathan Core) +Defeat the monstrous Mogenar in the heart of the Bryyo Seed to receive this upgrade. Refer to the bosses guide for tips to survive the heated battle in one piece. +008 +Boost Ball +SkyTown (Ballista Storage) +You'll need to face and defeat the frenetic Defense Drone in the Ballista Storage chamber to score this upgrade. Upon discovering Ghor's powered-down armour suit on the Spire Pod, head right and continue in that direction to eventually locate the Ballista Storage area (and the Boost Ball before it's promptly snatched away from you). Refer to the bosses guide for tips to shut the drone down to score your prize. +009 +Plasma Beam +SkyTown (Main Docking Bay) +You must stop Ghor's rampant behaviour to score the Plasma Beam. Upon watching the short skirmish between Ghor and Samus below Aurora Unit 217's chamber, quickly return to your gunship at the Main Docking Bay to find the weirdo doing a number on your ride. Step outside to face him in a final showdown. Refer to the bosses guide to learn a few tips to bring the hunter to an unfortunate end. +010 +Screw Attack +Bryyo (Bryyo Ice - Hall of Remembrance) +Thankfully this time you'll discover the Screw Attack early in the game. Upon defeating Ghor and scoring the Plasma Beam, you'll eventually discover a tall shaft lined with Wall Jump surfaces leading to the SkyTown East tram. With no way of scaling the shaft, Aurora Unit 217 will suggest backtracking to Bryyo in search of new items. So let's do just that. Return to Bryyo and land at the Fiery Airdock. Head for the Main Lift chamber and use the Snatchers deep inside the narrow tunnels to reach the second floor. Once there, you may remember spotting a tunnel fashioned in the shape of a lizard's open mouth filled with frozen ice. Use your Plasma Beam to clear the obstructions and roll through to find a hidden room beyond. Step inside to discover a large round chamber inhabited by a huge frozen battering ram in the ceiling and a lone inactive stone Golem. First melt the ice around the battering ram before using a Morph Ball Bomb to activate the Golem. The Golem will promptly slam the object into a huge gong, summoning a Spinner device. Use the Spinner to rotate the chamber's walls to reveal a cracked wall. Activate the Golem again and watch as it uses the battering ram to crash through the weakened wall. Step into the newly revealed chamber and enter the teleporter to find yourself in a truly alien environment to the rest of Bryyo. Explore around to eventually find the Screw Attack waiting in the grand Hall of Remembrance. +011 +Ship Grapple +SkyTown (Eastern SkyTown - SkyTown Federation Landing Site) +Upon arriving at SkyTown East, explore the area and pass through the Chozo Observatory and over Skybridge Athene to eventually locate the SkyTown Federation Landing Site. Aurora Unit 217 will summon a Bomb Slot, activate it to lower the shutters blocking the landing pad. See the small terminal overlooking the landing pad? Summon your ship and simply activate the terminal to receive the Ship Grapple upgrade. +012 +Seeker Missile +SkyTown (Eastern SkyTown - Xenoresearch B) +Soon after upgrading your ship and receiving the Ship Grapple you'll find yourself inside a chamber filled with the husks of Space Pirate foes. You know what that means. Continue to explore the area to discover corridors lined with dozens of Phazon Metroid specimens, all itching to get their pincers on you. Eventually you'll discover the power source of this area, an Energy Cell locked inside a station beside a containment pod containing the Seeker Missile. Use the Grapple Lasso to tear off the cover on the Energy Cell, then extract it to power down the containment pod's force field. Simply fire a Missile at the pod to breach the glass and gain access to your prize. +013 +Hyper Missile +Elysia Seed (Elysian Leviathan Core) +Defeat Helios in the core of the Elysian Leviathan Seed to receive the Hyper Missile (and a dose of corruptive Phazon). Refer to the bosses guide for tips to shut the rogue droid and its Swarmbot cronies down. +014 +X-Ray Visor +Pirate Homeworld (Pirate Command - Command Vault) +Travel to the Command Courtyard and disable the ventilation fans by extracting the Energy Cell directly above the fans. Roll through the ventilation tunnels to discover the Command Station - carry on through here to discover the Command Vault area where the X-Ray Visor awaits. Look up - see the five orange pods above? Simply use the Seeker Missile to strike all pods at once, revealing the X-Ray Visor as your prize. +015 +Grapple Voltage +Pirate Homeworld (Pirate Research - Proving Grounds) +Defeat Gandrayda in battle to receive this Grapple Beam addition. First pick up the map of the Pirate Homeworld at the Lift Hub to reveal the Pirate Research area. Fly your ship there and explore the region to ultimately discover Gandrayda disguised as a Federation Marine. Refer to the bosses guide for tips to survive the showdown with Dark Samus' final puppet. +016 +Spider Ball +SkyTown (Powerworks) +Upon securing the Grapple Voltage you'll be clear to locate the Spider Ball. Return to Elysia and set down at Landing Bay A. Travel to the Junction area and head south. Beyond you'll discover an elaborate gate system blocking access to a Zipline Cable. Simply attach the Grapple Lasso to the gate and deliver enough energy into the device to release the lock and move the gate out of your path. With your path clear, ride the Zipline Cable along till it malfunctions and drops you off on a platform halfway along. Look towards the structure beyond the drop and Screw Attack across to make the distance. Head inside and roll down into the main chamber of the Powerworks. Here you'll discover a tall pillar in the centre below a set of rotating gears in the ceiling. Look closely, see the fallen cog on the ground? Stand atop the raised platform nearby and look down at the cog. Deploy the Grapple Lasso and pull back to launch the cog into the air. Quickly lock on as it spins and fire a Missile to snugly send it back into place among the other gears. With the system operational again the pillar will open wide, revealing the Spider Ball within the grasp of an elaborate Chozo statue. +017 +Hazard Shield +Pirate Homeworld (Pirate Research - Craneyard) +You'll need the Spider Ball to successfully find your way to the Hazard Shield. Head to the Pirate Research region of the Pirate Homeworld and back to the Craneyard area. Look for a tall Spider Ball track running up a wall and follow it along. You'll eventually find yourself inside a snug compartment below the giant central structure outside in the deluge of acid rain. Use the two Spinners present to rotate the pair of rotating sections of the structure to line up a clean passage up to the top (be sure to grab the Missile Expansion hiding up over on the right of the structure). See the tunnel up on the left side leading away from the structure? Line up the rotating tunnels to create a clear path up there, then climb up and move through to find yourself inside a small command alcove overlooking the Craneyard. Simply activate the lone terminal there to summon the Hazard Shield to your position. +018 +Nova Beam +Pirate Homeworld (Pirate Mines - Main Cavern) +You've got a long journey ahead to the Nova Beam. Head to the Mining Site of the Pirate Homeworld and explore the region to ultimately find yourself at the Main Cavern. See the Nova Beam inside the Phazon mining chamber? You'll first need to find your way inside. Walk around the enclosure and activate the terminal on the far side to power up a nearby elevator. Ride the elevator down and enter the chamber to face a Pirate welcoming committee. See those access hatches surrounding the chamber? A trio of Pirates will attack in waves, usually comprised of Assault Pirate Troopers and Commando Pirates. They won't stop coming, so you'll need to focus on the task at hand. Normally the massive Phazon mining equipment will spend its time drilling the ore below the chamber, but watch out when a massive beam erupts in the center to draw up loose Phazon minerals. As it does so all your foes will scramble to grab hold of something before being sucked up into the beam. Quickly target one and fill them with enough firepower to break them loose and straight up into the beam. With the beam disrupted four odd glowing objects appear below the Nova Beam's pod. Quickly target one and shoot it before they retract. Hold out till the beam begins sucking everything towards itself again and send another hapless Pirate straight into it (use Hypermode to avoid taking too much damage in the crossfire). Shoot down another of the red objects and repeat the sequence till all four objects blow. With all targets down the Nova Beam will plummet to ground level; leaving you clear to claim your prize. +019 +Hyper Grapple +Pirate Seed (Pirate Homeworld Leviathan Core) +Send Omega Ridley to oblivion deep inside the Pirate Homeworld Seed to receive your final suit upgrade. Refer to the bosses guide for tips to score victory against yet another form of Ridley. \ No newline at end of file diff --git a/MetroidMapGuardian/src/room/Map.java b/MetroidMapGuardian/src/room/Map.java new file mode 100644 index 0000000..3e97414 --- /dev/null +++ b/MetroidMapGuardian/src/room/Map.java @@ -0,0 +1,405 @@ +package room; + +import entity.Marker; +import game.GameInstance; +import game.Profile; +import game.Trilogy; +import geometry.Vector; +import graphics.Button; +import graphics.Draw; +import graphics.MiniMap; +import graphics.PopupAbout; +import graphics.PopupControls; +import graphics.ScalableImage; +import graphics.StatusBar; + +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; + +import main.ImageLoader; +import main.Mouse; +import nbt.*; + +/** + * + * @author Robert Jordan + * + */ +public class Map extends Room { + + // ======================= Members ======================== + + public boolean scaleInThread = true; + + /** The name of the map. */ + public String name; + /** The raw name of the map. */ + public String rawName; + + /** The background image of the map. */ + public ScalableImage image; + + public int game; + + public double zoomSpeed; + + public boolean zoomingIn; + + public double zoomScale; + + public Vector mouseFocus; + + public static final boolean SMOOTH_ZOOM = true; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a basic entity. + * + * @return Returns the default entity. + */ + public Map() { + super(); + + this.name = ""; + this.rawName = ""; + this.game = 1; + this.image = null; + this.zoomSpeed = 0.0; + this.zoomingIn = false; + this.zoomScale = 0.0; + this.mouseFocus = new Vector(); + } + /** + * The default constructor, constructs a basic entity. + * + * @return Returns the default entity. + */ + public Map(String name, String rawName, int game) { + super(); + + this.name = name; + this.rawName = rawName; + this.game = game; + this.image = new ScalableImage(Trilogy.getRawName(game) + "/maps/" + rawName, Trilogy.getRawName(game), + BufferedImage.TYPE_INT_RGB, RenderingHints.VALUE_INTERPOLATION_BICUBIC, 1.0); + this.image.scaleInThread = scaleInThread; + this.zoomSpeed = 0.0; + this.zoomingIn = false; + this.zoomScale = 0.0; + this.mouseFocus = new Vector(); + } + /** + * Constructs the map from an NBT compound of values. This is mainly used + * To load entire maps from file in NBT format. + * + * @param nbt - The compound containing the tags related to the map. + * @return Returns the map constructed from tag data. + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ + public Map(String name, String rawName, int game, NBTTagCompound nbt) { + super(nbt); + + this.name = name; + this.rawName = rawName; + this.game = game; + this.image = new ScalableImage(Trilogy.getRawName(game) + "/maps/" + rawName, Trilogy.getRawName(game), + BufferedImage.TYPE_INT_RGB, RenderingHints.VALUE_INTERPOLATION_BICUBIC, 1.0); + this.image.scaleInThread = scaleInThread; + this.zoomSpeed = 0.0; + this.zoomingIn = false; + this.zoomScale = 0.0; + this.mouseFocus = new Vector(); + } + /** + * Constructs the map from an NBT compound of values. This is mainly used + * To load entire maps from file in NBT format. + * + * @param nbt - The compound containing the tags related to the map. + * @return Returns the map constructed from tag data. + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ + public Map(NBTTagCompound nbt) { + super(nbt); + + this.name = nbt.getString("name", ""); + this.rawName = nbt.getString("rawName", ""); + this.game = nbt.getByte("game", (byte)1); + this.image = new ScalableImage(Trilogy.getRawName(game) + "/maps/" + rawName, Trilogy.getRawName(game), + BufferedImage.TYPE_INT_RGB, RenderingHints.VALUE_INTERPOLATION_BICUBIC, 1.0); + this.image.scaleInThread = scaleInThread; + this.zoomSpeed = 0.0; + this.zoomingIn = false; + this.zoomScale = 0.0; + this.mouseFocus = new Vector(); + } + /** + * Initializes the room by setting the game instance it is linked to. + * + * @param instance - The game instance that contains the room. + */ + public void initialize(GameInstance instance, Trilogy trilogy) { + super.initialize(instance, trilogy); + + Vector buttonSize = new Vector(168, 56); + double dropHeight = 28; + Font font = new Font("Crystal clear", Font.PLAIN, 22); + Font dropFont = new Font("Crystal clear", Font.PLAIN, 18); + + addGui(new MiniMap()); + addGui(new StatusBar()); + Button button = new Button("trilogy", "Trilogy", new Vector(32 + buttonSize.x * 0, 32), buttonSize, new Vector(370, dropHeight), font, dropFont, true); + for (int i = 0; i < instance.trilogies.size(); i++) { + button.listItems.add(instance.trilogies.get(i).name); + } + addGui(button); + button = new Button("maps", "Map", new Vector(32 + buttonSize.x * 1, 32), buttonSize, new Vector(320, dropHeight), font, dropFont, true); + for (int i = 0; i < trilogy.maps.size(); i++) { + button.listItems.add(trilogy.maps.get(i).name); + } + addGui(button); + button = new Button("reset", "Reset View", new Vector(32 + buttonSize.x * 2, 32), buttonSize, new Vector(), font, null, false); + addGui(button); + button = new Button("help", "Help", new Vector(32 + buttonSize.x * 3, 32), buttonSize, new Vector(220, dropHeight), font, dropFont, true); + button.listItems.add("Controls"); + button.listItems.add("About"); + addGui(button); + button = new Button("quit", "Main Menu", new Vector(32 + buttonSize.x * 4, 32), buttonSize, new Vector(), font, null, false); + addGui(button); + } + + // ===================== NBT File IO ====================== + + /** + * Saves tag information about the room to the NBT compound. + * + * @param nbt - The NBT compound to save tag information to. + * + * @see + * {@linkplain NBTTagCompound} + */ + protected void saveRoom(NBTTagCompound nbt) { + super.saveRoom(nbt); + + nbt.setString("name", name); + nbt.setString("rawName", rawName); + nbt.setByte("game", (byte)game); + } + /** + * Saves the room to an NBT compound tag. + * + * @return Returns the NBT compound containing the values on the room. + * + * @see + * {@linkplain NBTTagCompound} + */ + public NBTTagCompound saveRoom() { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setString("class", "Map"); + saveRoom(nbt); + return nbt; + } + /** + * Creates a room based on the information given from an NBT compound. The + * room must first be defined in RoomLoader in order to be loaded from an + * nbt file. + * + * @param nbt - The NBT compound containing tag information on the room. + * @return Returns a room constructed from the specified tag information. + * + * @see + * {@linkplain NBTTagCompound}, + * {@linkplain RoomLoader} + */ + public Map loadRoom(NBTTagCompound nbt) { + return new Map(nbt); + } + + // ======================= Updating ======================= + + /** + * Called every step for the map to perform actions and update. + */ + public void update() { + + // Update the view + updateMousePanControls(); + updateZoomControls(); + + // Update the room + super.update(); + + if (Mouse.middle.pressed() && instance.editorMode) { + Marker marker = new Marker(instance.currentPowerUp, 0); + marker.placing = true; + addEntity(marker); + } + + if (((Button)getGui("trilogy")).selectedIndex != -1) { + instance.changeTrilogy(((Button)getGui("trilogy")).selectedIndex + 1); + } + if (((Button)getGui("maps")).selectedIndex != -1) { + trilogy.changeMap(((Button)getGui("maps")).selectedIndex); + } + if (((Button)getGui("reset")).pressed) { + view.zoom = 1.0; + view.pan.zero(); + } + if (((Button)getGui("help")).selectedIndex != -1) { + if (((Button)getGui("help")).selectedIndex == 0) { + addGui(new PopupControls()); + } + else if (((Button)getGui("help")).selectedIndex == 1) { + addGui(new PopupAbout()); + } + } + if (((Button)getGui("help")).pressed) { + + /*long timer = System.currentTimeMillis(); + new Profile(instance).saveProfile(); + System.out.println("Save took " + (System.currentTimeMillis() - timer) + " milliseconds.");*/ + } + else if (((Button)getGui("quit")).pressed) { + new Profile(instance).saveProfile(); + instance.menu = new Menu(); + instance.menu.initialize(instance, trilogy); + instance.inMenu = true; + image.unloadScaledImage(); + ImageLoader.unloadImage(trilogy.rawName + "/maps/" + rawName, trilogy.rawName); + } + } + /** + * Called every step for the map to draw to the screen. + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + //g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + + Marker.imageChecked.setScale(view.zoom); + Marker.imageUnchecked.setScale(view.zoom); + + // Draw map image + Vector point = view.getViewPoint(new Vector(0, 0)); + if (zoomSpeed != 0.0 || (view.zoom != 1.0 && instance.editorMode)) { + Draw.drawImage(g, image.getImage(), point, image.getSize().scaledBy(view.zoom)); + } + else if (view.zoom != 1.0 && !instance.editorMode) { + image.setScale(view.zoom); + if (image.finishedScaling) { + Draw.drawImage(g, image.getScaledImage(), point); + } + else { + Draw.drawImage(g, image.getImage(), point, image.getSize().scaledBy(view.zoom)); + } + } + else { + Draw.drawImage(g, image.getImage(), point); + //g.drawImage(image.getImage(), (int)point.x, (int)point.y, null); + } + + // Draw the room + super.draw(g); + } + + // ======================= Panning ======================== + + /** + * Pans the view when the right mouse button is down. + */ + public void updateMousePanControls() { + // Pan the view: + if (Mouse.right.down()) { + view.pan.add(Mouse.getVectorPrevious().minus(Mouse.getVector()).scale(1.0 / view.zoom)); + } + } + /** + * Zooms the view with the mouse wheel. + */ + public void updateZoomControls() { + Vector ms = Mouse.getVector(); + + final double scaleMultiplier = 1.2; + final double speedMultiplier = 0.32; + + // Zoom in and out: + if (Mouse.wheelUp() && view.zoom < View.ZOOM_MAX) { + if (SMOOTH_ZOOM) { + mouseFocus = new Vector(ms); + if (!zoomingIn || zoomSpeed == 0.0) { + zoomScale = 1.0; + zoomSpeed = speedMultiplier; + zoomingIn = true; + } + else { + zoomScale *= scaleMultiplier; + zoomSpeed = speedMultiplier * zoomScale; + } + } + else { + double newZoom = view.zoom * View.ZOOM_AMOUNT; + if (newZoom + 0.01 > View.ZOOM_MAX) + newZoom = View.ZOOM_MAX; + + view.zoomFocus(ms, newZoom); + } + } + if (Mouse.wheelDown() && view.zoom > View.ZOOM_MIN + 0.00001) { + if (SMOOTH_ZOOM) { + mouseFocus = new Vector(ms); + if (zoomingIn || zoomSpeed == 0.0) { + zoomScale = 1.0; + zoomSpeed = speedMultiplier; + zoomingIn = false; + } + else { + zoomScale *= scaleMultiplier; + zoomSpeed = speedMultiplier * zoomScale; + } + } + else { + double newZoom = view.zoom / View.ZOOM_AMOUNT; + if (newZoom - 0.04 < View.ZOOM_MIN) + newZoom = View.ZOOM_MIN; + + view.zoomFocus(ms, newZoom); + } + } + if (SMOOTH_ZOOM) { + if (zoomSpeed != 0.0) { + zoomSpeed -= 0.02 * zoomScale; + if (zoomSpeed <= 0.0) { + zoomSpeed = 0.0; + } + else { + double newZoom = 1.0; + if (zoomingIn) { + newZoom = view.zoom * (0.1 * zoomSpeed + 1.0); + if (newZoom + 0.002 > View.ZOOM_MAX) { + newZoom = View.ZOOM_MAX; + zoomSpeed = 0.0; + } + } + else { + newZoom = view.zoom / (0.1 * zoomSpeed + 1.0); + if (newZoom - 0.005 < View.ZOOM_MIN) { + newZoom = View.ZOOM_MIN; + zoomSpeed = 0.0; + } + } + view.zoomFocus(mouseFocus, newZoom); + } + } + } + } + +} + diff --git a/MetroidMapGuardian/src/room/Menu.java b/MetroidMapGuardian/src/room/Menu.java new file mode 100644 index 0000000..1bd487c --- /dev/null +++ b/MetroidMapGuardian/src/room/Menu.java @@ -0,0 +1,235 @@ +package room; + +import java.awt.Font; +import java.awt.Graphics2D; +import java.io.File; +import java.util.ArrayList; + +import nbt.NBTElement; +import nbt.NBTTagCompound; + +import main.Main; +import main.ResourceLoader; +import entity.Surge; + +import game.GameInstance; +import game.Profile; +import game.Trilogy; +import geometry.GMath; +import geometry.Vector; +import graphics.Button; +import graphics.Palette; +import graphics.ProfileList; +import graphics.TextBox; + +/** + * + * @author Robert Jordan + * + */ +public class Menu extends Room { + + // ======================= Members ======================== + + /** The list of profiles to choose from. */ + public ArrayList profiles; + + public int mode; + + public int selectedProfile; + + public ProfileList profileList; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a basic entity. + * + * @return Returns the default entity. + */ + public Menu() { + profiles = new ArrayList(); + mode = 0; + selectedProfile = -1; + profileList = null; + } + /** + * Initializes the room by setting the game instance it is linked to. + * + * @param instance - The game instance that contains the room. + */ + public void initialize(GameInstance instance, Trilogy trilogy) { + super.initialize(instance, trilogy); + + File directory = new File("profiles"); + if (!directory.exists()) { + directory.mkdir(); + } + + profileList = new ProfileList(); + ArrayList profilePaths = new ArrayList(); + profilePaths.addAll(ResourceLoader.getResources("profiles/", "", ".dat", false)); + for (int i = 0; i < profilePaths.size(); i++) { + String path = profilePaths.get(i); + int endIndex = path.lastIndexOf("profiles/") + ("profiles/").length(); + NBTTagCompound nbt = NBTElement.loadNBTCompound(path, false); + Profile profile = new Profile(path.substring(endIndex, path.length() - 4), nbt); + profiles.add(profile); + } + profileList.profiles = profiles; + + addGui(profileList); + + Vector buttonSize = new Vector(174, 56); + //Font font = new Font("Crystal clear", Font.PLAIN, 22); + //Font font = new Font("Eurostar", Font.PLAIN, 29); + Font font = Palette.fontEurostar.deriveFont(Font.PLAIN, 29); + + Button button = new Button("new", "New Profile", new Vector(48, 16), buttonSize, new Vector(), font, null, false); + addGui(button); + button = new Button("delete", "Delete Profile", new Vector(48 + buttonSize.x + 16, 16), buttonSize, new Vector(), font, null, false); + addGui(button); + + TextBox textBox = new TextBox("textBox", "Select a profile", new Vector(48 + buttonSize.x * 2 + 32, 16), buttonSize.plus(256, 0), font, false, 20); + addGui(textBox); + + font = Palette.fontEurostar.deriveFont(Font.PLAIN, 22); + button = new Button("quit", "Quit", new Vector(10, 10), new Vector(80, 40), new Vector(), font, null, false); + addGui(button); + + } + + // ======================= Updating ======================= + + /** + * Called every step for the map to perform actions and update. + */ + public void update() { + + getGui("new").position.y = Main.frame.getContentPane().getHeight() - 56 - 24; + getGui("delete").position.y = Main.frame.getContentPane().getHeight() - 56 - 24; + getGui("quit").position.x = Main.frame.getContentPane().getWidth() - 80 - 10; + getGui("textBox").position.y = Main.frame.getContentPane().getHeight() - 56 - 24; + ((TextBox)getGui("textBox")).size.x = Main.frame.getContentPane().getWidth() - 48 - getGui("textBox").position.x; + + super.update(); + + //if (GMath.random.nextInt(6) == 0) { + if (GMath.random.nextDouble() * 6.0 * 900.0 / Main.frame.getContentPane().getWidth() <= 1.0) { + double vspeed = 1.5 + GMath.random.nextDouble(); + if (GMath.random.nextBoolean()) + vspeed *= -1; + double x = GMath.random.nextDouble() * Main.frame.getContentPane().getWidth(); + int length = 60 + GMath.random.nextInt(60); + addEntity(new Surge(x, vspeed, length)); + } + + if (((Button)getGui("new")).pressed) { + if (mode == 0) { // New Profile + setMode(1); + } + else if (mode == 1) { // Create New Profile + char[] invalidCharacters = {'<', '>', ':', '"', '/', '\\', '|', '?', '*'}; + String name = ((TextBox)getGui("textBox")).text; + boolean validName = true; + for (Profile p : profiles) { + if (p.profileName.equals(name)) { + validName = false; + break; + } + } + for (char c : invalidCharacters) { + if (name.indexOf(c) != -1) { + validName = false; + break; + } + } + if (validName && !name.isEmpty()) { + Profile newProfile = new Profile(name); + newProfile.saveProfile(); + profiles.add(newProfile); + setMode(0); + } + } + else if (mode == 2) { // New Profile + setMode(1); + } + else if (mode == 3) { // Yes Delete Profile + File file = new File("profiles/" + profiles.get(selectedProfile).profileName + ".dat"); + file.delete(); + profiles.remove(selectedProfile); + setMode(0); + } + } + else if (((Button)getGui("delete")).pressed) { + if (mode == 0) { // Delete Profile + setMode(2); + } + else if (mode == 1) { // Cancel New Profile + setMode(0); + } + else if (mode == 2) { // Cancel Delete Profile + setMode(0); + } + else if (mode == 3) { // No Delete Profile + setMode(0); + } + } + else if (((Button)getGui("quit")).pressed) { + Main.stop(); + } + + if (profileList.selectedIndex != -1) { + if (mode == 0) { // Load Profile + instance.inMenu = false; + instance.menu = null; + instance.loadProfile(profiles.get(profileList.selectedIndex)); + } + else if (mode == 2) { // Delete Profile + selectedProfile = profileList.selectedIndex; + setMode(3); + } + } + } + /** + * Called every step for the map to draw to the screen. + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + + // Draw the room + super.draw(g); + } + + + public void setMode(int mode) { + this.mode = mode; + if (mode == 0) { + ((Button)getGui("new")).label = "New Profile"; + ((Button)getGui("delete")).label = "Delete Profile"; + ((TextBox)getGui("textBox")).text = "Select a profile"; + ((TextBox)getGui("textBox")).editable = false; + } + else if (mode == 1) { + ((Button)getGui("new")).label = "Create"; + ((Button)getGui("delete")).label = "Cancel"; + ((TextBox)getGui("textBox")).text = "Enter profile name"; + ((TextBox)getGui("textBox")).editable = true; + ((TextBox)getGui("textBox")).typing = true; + ((TextBox)getGui("textBox")).justStartedTyping = true; + } + else if (mode == 2) { + ((Button)getGui("new")).label = "New Profile"; + ((Button)getGui("delete")).label = "Cancel"; + ((TextBox)getGui("textBox")).text = "Delete a profile"; + ((TextBox)getGui("textBox")).editable = false; + } + else if (mode == 3) { + ((Button)getGui("new")).label = "Yes"; + ((Button)getGui("delete")).label = "No"; + ((TextBox)getGui("textBox")).text = "Delete this profile?"; + ((TextBox)getGui("textBox")).editable = false; + } + } +} diff --git a/MetroidMapGuardian/src/room/Room.java b/MetroidMapGuardian/src/room/Room.java new file mode 100644 index 0000000..ec5ba0f --- /dev/null +++ b/MetroidMapGuardian/src/room/Room.java @@ -0,0 +1,333 @@ +package room; + +import java.awt.Graphics2D; +import java.util.ArrayList; + +import nbt.NBTElement; +import nbt.NBTTagCompound; +import nbt.NBTTagList; +import entity.Entity; +import entity.EntityLoader; + +import game.GameInstance; +import game.Trilogy; +import graphics.Gui; + +/** + * + * @author Robert Jordan + * + */ +public class Room { + + // ====================== Constants ======================= + + /** The max amount of entities allowed to be contained within the room. */ + public static final int MAX_ENTITIES = 10000; + /** The max amount of guis allowed to be contained within the room. */ + public static final int MAX_GUIS = 1000; + + // ======================= Members ======================== + + /** The name identifier of the room. */ + public String id; + /** The instance that contains the room. */ + public Trilogy trilogy; + /** The instance that contains the room. */ + public GameInstance instance; + + /** The list of entities contained in the room. */ + public ArrayList entities; + /** The list of GUIs contained in the room. */ + public ArrayList guis; + /** The view pan and zoom in the room. */ + public View view; + /** Used to determine if the entity can interact with the mouse. */ + public boolean isMouseOverGUI; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a basic room. + * + * @return Returns the default room. + */ + public Room() { + id = ""; + trilogy = null; + instance = null; + entities = new ArrayList(); + guis = new ArrayList(); + view = new View(); + + isMouseOverGUI = false; + } + /** + * Constructs the room from an NBT compound of values. This is mainly used + * to load entire rooms from file in NBT format. + * + * @param nbt - The compound containing the tags related to the room. + * @return Returns the room constructed from tag data. + * + * @see + * {@linkplain NBTElement}, + * {@linkplain NBTTagCompound} + */ + public Room(NBTTagCompound nbt) { + id = nbt.getString("id", ""); + trilogy = null; + instance = null; + entities = new ArrayList(); + guis = new ArrayList(); + view = new View(); + + isMouseOverGUI = false; + + for (NBTElement tag : nbt.getList("entities").getTags()) { + entities.add(EntityLoader.loadEntity((NBTTagCompound)tag)); + } + } + /** + * Initializes the room by setting the game instance it is linked to. + * + * @param instance - The game instance that contains the room. + */ + public void initialize(GameInstance instance, Trilogy trilogy) { + this.trilogy = trilogy; + this.instance = instance; + + for (Entity e : entities) { + e.initialize(this, instance, trilogy); + } + + for (Gui g : guis) { + g.initialize(this, instance, trilogy); + } + } + + // ===================== NBT File IO ====================== + + /** + * Saves tag information about the room to the NBT compound. + * + * @param nbt - The NBT compound to save tag information to. + * + * @see + * {@linkplain NBTTagCompound} + */ + protected void saveRoom(NBTTagCompound nbt) { + nbt.setString("id", id); + NBTTagList entityTags = new NBTTagList("entities", NBTElement.TAG_COMPOUND); + for (Entity e : entities) { + entityTags.addCompound(e.saveEntity()); + } + nbt.setList("entities", entityTags); + } + /** + * Saves the room to an NBT compound tag. + * + * @return Returns the NBT compound containing the values on the room. + * + * @see + * {@linkplain NBTTagCompound} + */ + public NBTTagCompound saveRoom() { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setString("class", "Room"); + saveRoom(nbt); + return nbt; + } + /** + * Creates a room based on the information given from an NBT compound. The + * room must first be defined in RoomLoader in order to be loaded from an + * nbt file. + * + * @param nbt - The NBT compound containing tag information on the room. + * @return Returns a room constructed from the specified tag information. + * + * @see + * {@linkplain NBTTagCompound}, + * {@linkplain RoomLoader} + */ + public Room loadRoom(NBTTagCompound nbt) { + return new Room(nbt); + } + + // ======================= Updating ======================= + + /** + * Called every step for the room to perform actions and update. + */ + public void update() { + + // This is considered false until a GUI changes it. + isMouseOverGUI = false; + + // Update the GUIs + for (Gui g : guis) { + if (!g.destroyed) { + g.update(); + } + } + // Remove any GUIs that have been destroyed + for (int i = 0; i < guis.size(); i++) { + if (guis.get(i).destroyed) { + guis.remove(i); + i--; + } + } + + // Update the entities + for (Entity e : entities) { + if (!e.destroyed) { + e.update(); + } + } + // Remove any entities that have been destroyed + for (int i = 0; i < entities.size(); i++) { + if (entities.get(i).destroyed) { + entities.remove(i); + i--; + } + } + + } + /** + * Called every step for the room to draw to the screen. + * + * @param g - The graphics object to draw to. + */ + public void draw(Graphics2D g) { + + // Draw the entities + for (Entity e : entities) { + e.draw(g); + } + + // Draw the GUIs + for (Gui gu : guis) { + gu.draw(g); + } + } + + // ======================= Entities ======================= + + /** + * Adds the entity to the room and sets its game instance and room variable. + * + * @param e - The entity to add to the room. + */ + public void addEntity(Entity e) { + if (entities.size() < MAX_ENTITIES) { + entities.add(e); + e.initialize(this, instance, trilogy); + } + } + /** + * Finds the entity with the given id. + * + * @param id - The key identifier used to locate the entity. + * @return Returns the entity with the given id. + */ + public Entity getEntity(String id) { + for (Entity e : entities) { + if (e.id == id) { + return e; + } + } + return null; + } + /** + * Returns true if the entity with the given id exists. + * + * @param id - The key identifier used to locate the entity. + * @return Returns true if the entity with the given id exists. + */ + public boolean entityExists(String id) { + for (Entity e : entities) { + if (e.id == id) { + return true; + } + } + return false; + } + /** + * Returns true if the entity exists in the room. + * + * @param e - The entity to check for existence. + * @return Returns true if the entity exists in the room. + */ + public boolean entityExists(Entity e) { + return entities.contains(e); + } + /** + * Returns the number of entities in the room. + * + * @return Returns the number of entities in the room. + */ + public int numEntities() { + return entities.size(); + } + + // ========================= Guis ========================= + + /** + * Adds the GUI to the room and sets its game instance and room variable. + * + * @param e - The GUI to add to the room. + */ + public void addGui(Gui g) { + if (guis.size() < MAX_GUIS) { + guis.add(g); + g.initialize(this, instance, trilogy); + } + } + /** + * Finds the GUI with the given id. + * + * @param id - The key identifier used to locate the GUI. + * @return Returns the GUI with the given id or null if the id does not exist. + */ + public Gui getGui(String id) { + for (Gui g : guis) { + if (g.id == id) { + return g; + } + } + return null; + } + /** + * Returns true if the GUI with the given id exists. + * + * @param id - The key identifier used to locate the GUI. + * @return Returns true if the GUI with the given id exists. + */ + public boolean guiExists(String id) { + for (Gui g : guis) { + if (g.id == id) { + return true; + } + } + return false; + } + /** + * Returns true if the GUI exists in the room. + * + * @param e - The GUI to check for existence. + * @return Returns true if the GUI exists in the room. + */ + public boolean guiExists(Gui g) { + return guis.contains(g); + } + /** + * Returns the number of GUIs in the room. + * + * @return Returns the number of GUIs in the room. + */ + public int numGuis() { + return guis.size(); + } + +} + + diff --git a/MetroidMapGuardian/src/room/View.java b/MetroidMapGuardian/src/room/View.java new file mode 100644 index 0000000..2bdd176 --- /dev/null +++ b/MetroidMapGuardian/src/room/View.java @@ -0,0 +1,103 @@ +package room; + +import main.Mouse; + +import geometry.Vector; + +/** + * + * @author Robert Jordan + * + */ +public class View { + + public static final double ZOOM_AMOUNT = 1.1; + public static final double ZOOM_MIN = 0.2; + public static final double ZOOM_MAX = 1.0; + + public boolean changing = false; + + + // ======================= Members ======================== + + /** The view position in the room. */ + public Vector pan; + /** The view zoom in the room. */ + public double zoom; + + // ===================== Constructors ===================== + + /** + * The default constructor, constructs a view control at (0, 0) with no zoom. + * + * @return Returns the default view control. + */ + public View() { + this.pan = new Vector(); + this.zoom = 1.0; + } + /** + * Constructs a view control at the given position with the given zoom. + * + * @return Returns a view control with the given position with the given zoom. + */ + public View(Vector pan, double zoom) { + this.pan = new Vector(pan); + this.zoom = zoom; + } + + // ===================== View Methods ===================== + + /** + * Zooms in while focusing on the given coordinate. + * + * @param focusPoint - The point to zoom in to. + * @param zoom - The new zoom. + */ + public void zoomFocus(Vector focusPoint, double zoom) { + //Vector focus = focusPoint.scaledBy(1.0 / this.zoom).plus(pan); + //Vector focus = focusPoint.scaledBy(1.0 * zoom).plus(pan); + //this.zoom = zoom; + //this.pan = focus.minus(focusPoint.scaledBy(1.0 / this.zoom)); + //this.pan = focus.minus(focusPoint.scaledBy(1.0 * zoom)); + + Vector focus = focusPoint.scaledBy(1.0 / this.zoom); + //System.out.println(focus.minus(focus.scaledBy(this.zoom / zoom)) + " " + this.zoom / zoom + " " + getMousePoint()); + //changing = true; + this.pan = pan.plus(focus.minus(focus.scaledBy(this.zoom / zoom))); + this.zoom = zoom; + //changing = false; + //System.out.println(focus.minus(focus.scaledBy(this.zoom / zoom)) + " " + this.zoom / zoom + " " + getMousePoint() + " " + zoom); + } + + // ===================== Coordinates ====================== + + /** + * Converts the view point to game point coordinates. + * + * @param viewPoint - The view point. + * @return Returns the game point from the view point. + */ + public Vector getGamePoint(Vector viewPoint) { + return viewPoint.scaledBy(1.0 / zoom).plus(pan); + } + /** + * Converts the game point to view point coordinates. + * + * @param gamePoint - The game point. + * @return Returns the view point from the game point. + */ + public Vector getViewPoint(Vector gamePoint) { + return gamePoint.minus(pan).scaledBy(1.0 * zoom); + } + /** + * Converts the mouse position to game point coordinates. + * + * @return Returns the game point from the mouse position. + */ + public Vector getMousePoint() { + return getGamePoint(Mouse.getVector()); + } + +} + diff --git a/MetroidMapGuardian/src/testing/TestingMain.java b/MetroidMapGuardian/src/testing/TestingMain.java new file mode 100644 index 0000000..a8293fe --- /dev/null +++ b/MetroidMapGuardian/src/testing/TestingMain.java @@ -0,0 +1,77 @@ +package testing; + +import java.awt.Color; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; + +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; + +public class TestingMain { + + /** + * @param args + */ + public static void main(String[] args) { + + try { + Color maskColor = new Color(254, 222, 1); + Image transformImage = new ImageIcon("transformImage.png").getImage(); + Image maskImage = new ImageIcon("maskImage.png").getImage(); + + int width = transformImage.getWidth(null); + int height = transformImage.getHeight(null); + + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + BufferedImage mask = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + + image.getGraphics().drawImage(transformImage, 0, 0, null); + mask.getGraphics().drawImage(maskImage, 0, 0, null); + + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + if (mask.getRGB(x, y) == maskColor.getRGB()) { + int rgb = image.getRGB(x, y); + + short alpha = (short)(((rgb & 0xFF000000) >> 24) & 0x00FF); + short red = (short)((rgb & 0xFF0000) >> 16); + short green = (short)((rgb & 0xFF00) >> 8); + short blue = (short)((rgb & 0xFF)); + + short average = (short)((red + green + blue) / 3); + + alpha = average; + red = 255; + green = 255; + blue = 255; + + int pixelColor = 0; + pixelColor += (alpha & 0xFF) << 24; + pixelColor += (red & 0xFF) << 16; + pixelColor += (green & 0xFF) << 8; + pixelColor += (blue & 0xFF); + + image.setRGB(x, y, pixelColor); + } + } + } + + + File file = new File("fixedImage.png"); + ImageIO.write(image, "png", file); + + } + catch (MalformedURLException e) { + e.printStackTrace(); + } + catch (IOException e) { + e.printStackTrace(); + } + + + } + +} diff --git a/MetroidMapGuardian/src/testing/package-info.java b/MetroidMapGuardian/src/testing/package-info.java new file mode 100644 index 0000000..4fdc730 --- /dev/null +++ b/MetroidMapGuardian/src/testing/package-info.java @@ -0,0 +1,8 @@ +/** + * + */ +/** + * @author Jrob + * + */ +package testing; \ No newline at end of file