diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 310e0f2..13a8247 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -1,5 +1,6 @@ + - + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 3137788..6831dc3 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ group 'cl.cromer.azaraka' version '1.0.0' sourceCompatibility = 1.8 +targetCompatibility = 1.8 mainClassName = "cl.cromer.azaraka.Main" @@ -37,7 +38,9 @@ dependencies { jar { manifest { attributes "Main-Class": "$mainClassName", - 'Class-Path': configurations.default.files.collect { "$it.name" }.join(' ') + 'Class-Path': configurations.default.files.collect { "$it.name" }.join(' '), + "Implementation-Title": "Gradle", + "Implementation-Version": "$gradle.gradleVersion" } // This adds the libs into the jar diff --git a/src/main/java/cl/cromer/azaraka/Celda.java b/src/main/java/cl/cromer/azaraka/Celda.java index ec4ed66..e4d704f 100644 --- a/src/main/java/cl/cromer/azaraka/Celda.java +++ b/src/main/java/cl/cromer/azaraka/Celda.java @@ -21,6 +21,8 @@ import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.Map; /** * This class is a cell that will contain a game element such as a player, enemy, prize, etc @@ -43,17 +45,21 @@ public class Celda extends JComponent implements Constantes { */ private final int y; /** - * The textures to show in this cell + * A map containing the textures used in the cell, LinkedHashMap is used to maintain the order of images */ - private final ArrayList textures = new ArrayList<>(); - /** - * The texture numbers - */ - private final ArrayList textureNumbers = new ArrayList<>(); + private final LinkedHashMap textures = new LinkedHashMap<>(); /** * The object in the cell */ private Object object = null; + /** + * An object that doesn't collide and is drawn on top of the other sprites + */ + private Object objectOnTop = null; + /** + * An object that doesn't collide and is drawn below the other sprites + */ + private Object objectOnBottom = null; /** * Initialize the cell with its coordinates @@ -88,6 +94,51 @@ public class Celda extends JComponent implements Constantes { this.object = object; } + /** + * Get the top object + * + * @return Returns the top object + */ + public Object getObjectOnTop() { + return objectOnTop; + } + + /** + * Set a top object + * + * @param object The top object + */ + public void setObjectOnTop(Object object) { + this.objectOnTop = object; + } + + /** + * Get a bottom object + * + * @return Returns the bottom object + */ + public Object getObjectOnBottom() { + return objectOnBottom; + } + + /** + * Set a bottom object + * + * @param object The object + */ + public void setObjectOnBottom(Object object) { + this.objectOnBottom = object; + } + + /** + * Check if cell contains an object + * + * @return Returns true if it contains an object or false otherwise + */ + public boolean containsObject() { + return (object != null || objectOnTop != null || objectOnBottom != null); + } + /** * Get the x coordinate of the cell * @@ -113,25 +164,27 @@ public class Celda extends JComponent implements Constantes { * @param textureNumber The texture's number */ public void addTexture(BufferedImage texture, int textureNumber) { - textures.add(texture); - textureNumbers.add(textureNumber); + textures.put(textureNumber, texture); } /** - * Remove the texture that is on the top of the stack + * Remove the texture from the map */ - public void removeTopTexture() { - textures.remove(textures.size() - 1); - textureNumbers.remove(textureNumbers.size() - 1); + public void removeTexture(int texture) { + textures.remove(texture); } /** - * Get the numbers of the textures + * Get an array list of the texture numbers used * - * @return Returns an array list containing the texture numbers + * @return Returns an array list of texture numbers */ public ArrayList getTextureNumbers() { - return textureNumbers; + ArrayList arrayList = new ArrayList<>(); + for (Map.Entry entry : textures.entrySet()) { + arrayList.add(entry.getKey()); + } + return arrayList; } /** @@ -151,18 +204,27 @@ public class Celda extends JComponent implements Constantes { */ @Override public void update(Graphics g) { - // Don't replace with foreach because it can cause a race condition - //noinspection ForLoopReplaceableByForEach - for (int i = 0; i < textures.size(); i++) { - BufferedImage texture = textures.get(i); + // Draw the textures in the cell + for (Map.Entry entry : textures.entrySet()) { + BufferedImage texture = entry.getValue(); if (texture != null) { g.drawImage(texture, xPixels, yPixels, null); } } + // Draw the bottom sprite + if (objectOnBottom != null) { + objectOnBottom.drawAnimation(g, xPixels, yPixels); + } + // Draw a sprite in the cell if needed if (object != null) { object.drawAnimation(g, xPixels, yPixels); } + + // Draw the top sprite + if (objectOnTop != null) { + objectOnTop.drawAnimation(g, xPixels, yPixels); + } } } \ No newline at end of file diff --git a/src/main/java/cl/cromer/azaraka/Constantes.java b/src/main/java/cl/cromer/azaraka/Constantes.java index 46e5eeb..64c4443 100644 --- a/src/main/java/cl/cromer/azaraka/Constantes.java +++ b/src/main/java/cl/cromer/azaraka/Constantes.java @@ -203,7 +203,7 @@ public interface Constantes { /** * The global log level is used if the individual log levels are not */ - GLOBAL(Level.WARNING), + GLOBAL(Level.SEVERE), /** * The main log level */ @@ -256,6 +256,10 @@ public interface Constantes { * The json log level */ JSON(Level.INFO), + /** + * The gem log level + */ + GEM(Level.INFO), /** * The portal log level */ diff --git a/src/main/java/cl/cromer/azaraka/Escenario.java b/src/main/java/cl/cromer/azaraka/Escenario.java index 1d86847..0ff8e0d 100644 --- a/src/main/java/cl/cromer/azaraka/Escenario.java +++ b/src/main/java/cl/cromer/azaraka/Escenario.java @@ -190,14 +190,14 @@ public class Escenario extends JComponent implements Constantes { } random = randomCoordinates(); - celdas[random[0]][random[1]].setObject(new Portal(this, celdas[random[0]][random[1]])); - objectArrayList.add(celdas[random[0]][random[1]].getObject()); + celdas[random[0]][random[1]].setObjectOnBottom(new Portal(this, celdas[random[0]][random[1]])); + objectArrayList.add(celdas[random[0]][random[1]].getObjectOnBottom()); // Generate enough keys for the chests that will exist for (int i = 0; i < CHESTS; i++) { random = randomCoordinates(); - celdas[random[0]][random[1]].setObject(new Key(this, celdas[random[0]][random[1]])); - objectArrayList.add(celdas[random[0]][random[1]].getObject()); + celdas[random[0]][random[1]].setObjectOnBottom(new Key(this, celdas[random[0]][random[1]])); + objectArrayList.add(celdas[random[0]][random[1]].getObjectOnBottom()); } // Chests need to be last to make sure they are openable @@ -206,14 +206,14 @@ public class Escenario extends JComponent implements Constantes { int random_y = random(0, VERTICAL_CELLS - 1); // Don't put a chest if it can't be opened while (random_y + 1 == VERTICAL_CELLS || - celdas[random_x][random_y].getObject() != null || - celdas[random_x][random_y + 1].getObject() != null || - celdas[random_x][random_y - 1].getObject() != null) { + celdas[random_x][random_y].containsObject() || + celdas[random_x][random_y + 1].containsObject() || + celdas[random_x][random_y - 1].containsObject()) { random_x = random(0, HORIZONTAL_CELLS - 1); random_y = random(0, VERTICAL_CELLS - 1); } - celdas[random_x][random_y].setObject(new Chest(this, celdas[random_x][random_y])); - objectArrayList.add(celdas[random_x][random_y].getObject()); + celdas[random_x][random_y].setObjectOnBottom(new Chest(this, celdas[random_x][random_y])); + objectArrayList.add(celdas[random_x][random_y].getObjectOnBottom()); } return objectArrayList; @@ -228,7 +228,7 @@ public class Escenario extends JComponent implements Constantes { int[] random = new int[2]; random[0] = random(0, HORIZONTAL_CELLS - 1); random[1] = random(0, VERTICAL_CELLS - 1); - while (celdas[random[0]][random[1]].getObject() != null) { + while (celdas[random[0]][random[1]].containsObject()) { random[0] = random(0, HORIZONTAL_CELLS - 1); random[1] = random(0, VERTICAL_CELLS - 1); } @@ -486,16 +486,18 @@ public class Escenario extends JComponent implements Constantes { */ public void setDoorClosed(boolean doorClosed) { if (doorClosed && !isDoorClosed()) { + celdas[2][0].setObject(new Obstacle(this, celdas[2][0])); try { celdas[2][0].addTexture(textureSheet.getTexture(193), 193); } catch (SheetException e) { - e.printStackTrace(); + logger.warning(e.getMessage()); } this.doorClosed = true; } else if (!doorClosed && isDoorClosed()) { - celdas[2][0].removeTopTexture(); + celdas[2][0].removeTexture(193); + celdas[2][0].setObject(null); this.doorClosed = false; } } diff --git a/src/main/java/cl/cromer/azaraka/Lienzo.java b/src/main/java/cl/cromer/azaraka/Lienzo.java index 768a284..2d6a7d4 100644 --- a/src/main/java/cl/cromer/azaraka/Lienzo.java +++ b/src/main/java/cl/cromer/azaraka/Lienzo.java @@ -139,15 +139,24 @@ public class Lienzo extends Canvas implements Constantes { Enemy.Direction enemyDirection = Enemy.Direction.DOWN; + // Create the gems and later place them in 2 of the chests + ArrayList gems = new ArrayList<>(); + Gem lifeGem = new Gem(escenario, new Celda(0, 0, 0, 0)); + lifeGem.setType(Gem.Type.LIFE); + Gem deathGem = new Gem(escenario, new Celda(0, 0, 0, 0)); + deathGem.setType(Gem.Type.DEATH); + gems.add(lifeGem); + gems.add(deathGem); + ArrayList objectList = escenario.generateRandomObjects(); for (Object object : objectList) { - object.getCelda().setObject(object); if (object instanceof Player) { + object.getCelda().setObject(object); player = (Player) object; threads.put(object, new Thread(object)); } else if (object instanceof Enemy) { - ((Enemy) object).setDirection(enemyDirection); + object.getCelda().setObject(object); if (enemyDirection == Enemy.Direction.UP) { enemyDirection = Enemy.Direction.DOWN; } @@ -160,18 +169,30 @@ public class Lienzo extends Canvas implements Constantes { else { enemyDirection = Enemy.Direction.UP; } + ((Enemy) object).setDirection(enemyDirection); enemies.add((Enemy) object); threads.put(object, new Thread(object)); } else if (object instanceof Chest) { + object.getCelda().setObject(object); + if (gems.size() > 0) { + Gem gem = gems.get(0); + // Place the gem in the cell above the chest, but don't add it to object2 until we are ready to draw it + gem.setCelda(escenario.getCeldas()[object.getCelda().getX()][object.getCelda().getY() - 1]); + threads.put(gem, new Thread(gem)); + ((Chest) object).setGem(gem); + gems.remove(gem); + } chests.add((Chest) object); threads.put(object, new Thread(object)); } else if (object instanceof Key) { + object.getCelda().setObjectOnBottom(object); keys.add((Key) object); threads.put(object, new Thread(object)); } else if (object instanceof Portal) { + object.getCelda().setObjectOnBottom(object); portal = (Portal) object; threads.put(object, new Thread(object)); } @@ -227,6 +248,12 @@ public class Lienzo extends Canvas implements Constantes { } } + ArrayList gems = player.getInventoryGems(); + for (Gem gem : gems) { + gem.drawAnimation(graphicBuffer, xKey, 8); + xKey = xKey + 27; + } + if (player != null) { int health = player.getHealth(); if (health == 0) { diff --git a/src/main/java/cl/cromer/azaraka/json/Json.java b/src/main/java/cl/cromer/azaraka/json/Json.java index dbb71bd..3c3cec8 100644 --- a/src/main/java/cl/cromer/azaraka/json/Json.java +++ b/src/main/java/cl/cromer/azaraka/json/Json.java @@ -79,7 +79,7 @@ public class Json implements Constantes { Gson gson = gsonBuilder.create(); String json = gson.toJson(cells); - File file = new File("res/scene.json"); + File file = new File("src/main/resources/scene.json"); try { FileOutputStream fileOutputStream = new FileOutputStream(file); fileOutputStream.write(json.getBytes()); diff --git a/src/main/java/cl/cromer/azaraka/object/Chest.java b/src/main/java/cl/cromer/azaraka/object/Chest.java index bee500b..50c121b 100644 --- a/src/main/java/cl/cromer/azaraka/object/Chest.java +++ b/src/main/java/cl/cromer/azaraka/object/Chest.java @@ -37,6 +37,14 @@ public class Chest extends Object implements Constantes { * The open chest sound */ private Sound sound; + /** + * The gem contained in the chest + */ + private Gem gem = null; + /** + * The number of loops before the gem should move to inventory + */ + private int gemLoops = 3; /** * Initialize the chest @@ -118,6 +126,24 @@ public class Chest extends Object implements Constantes { } } + /** + * Get the gem from the chest + * + * @return The gem in the chest + */ + public Gem getGem() { + return gem; + } + + /** + * Put a gem in the chest + * + * @param gem The gem + */ + public void setGem(Gem gem) { + this.gem = gem; + } + /** * Play the chest opening sound */ @@ -160,7 +186,21 @@ public class Chest extends Object implements Constantes { getLogger().info(e.getMessage()); } synchronized (this) { - if (state == State.OPENING) { + if (state == State.OPENED) { + if (gemLoops > 0) { + gemLoops--; + } + else if (gemLoops == 0) { + gem.getCelda().setObjectOnTop(null); + gem.setYScale(24); + gem.setXScale(24); + gem.setUseOffset(false); + getEscenario().getCanvas().getPlayer().addInventory(gem); + getEscenario().getCanvas().getPortal().setState(Portal.State.ACTIVE); + gemLoops--; + } + } + else if (state == State.OPENING) { animate(); getEscenario().getCanvas().repaint(); } diff --git a/src/main/java/cl/cromer/azaraka/object/Enemy.java b/src/main/java/cl/cromer/azaraka/object/Enemy.java index c8ec09e..a71f7a5 100644 --- a/src/main/java/cl/cromer/azaraka/object/Enemy.java +++ b/src/main/java/cl/cromer/azaraka/object/Enemy.java @@ -101,6 +101,18 @@ public class Enemy extends Object implements Constantes { */ public void setDirection(Direction direction) { this.direction = direction; + if (direction == Direction.UP) { + getAnimation().setCurrentDirection(Animation.Direction.UP); + } + else if (direction == Direction.DOWN) { + getAnimation().setCurrentDirection(Animation.Direction.DOWN); + } + else if (direction == Direction.LEFT) { + getAnimation().setCurrentDirection(Animation.Direction.LEFT); + } + else if (direction == Direction.RIGHT) { + getAnimation().setCurrentDirection(Animation.Direction.RIGHT); + } } /** diff --git a/src/main/java/cl/cromer/azaraka/object/Gem.java b/src/main/java/cl/cromer/azaraka/object/Gem.java index 8c8d876..185f38f 100644 --- a/src/main/java/cl/cromer/azaraka/object/Gem.java +++ b/src/main/java/cl/cromer/azaraka/object/Gem.java @@ -17,15 +17,29 @@ package cl.cromer.azaraka.object; import cl.cromer.azaraka.Celda; import cl.cromer.azaraka.Escenario; +import cl.cromer.azaraka.sprite.Animation; +import cl.cromer.azaraka.sprite.AnimationException; /** * This class contains the gem */ public class Gem extends Object { + /** + * The type of gem + */ + private Type type = null; /** * The current state of the gem */ private State state = State.TAINTED; + /** + * + */ + private Animation taintedAnimation; + /** + * The animation to use when the gem is purified + */ + private Animation purifiedAnimation; /** * Initialize the gem object @@ -35,12 +49,135 @@ public class Gem extends Object { */ public Gem(Escenario escenario, Celda celda) { super(escenario, celda); + setLogger(getLogger(this.getClass(), LogLevel.GEM)); + loadGemAnimation(null); + setAnimation(taintedAnimation); + } + + /** + * Load the gem animations + */ + private void loadGemAnimation(Type type) { + if (type == null) { + taintedAnimation = new Animation(); + for (int i = 0; i <= 6; i++) { + String string = i + ".png"; + taintedAnimation.addImage(Animation.Direction.NONE, "/img/gem/gray/" + string); + } + taintedAnimation.setYOffset(32); + } + else { + switch (type) { + case LIFE: + purifiedAnimation = new Animation(); + for (int i = 0; i <= 6; i++) { + String string = i + ".png"; + purifiedAnimation.addImage(Animation.Direction.NONE, "/img/gem/blue/" + string); + } + break; + case DEATH: + purifiedAnimation = new Animation(); + for (int i = 0; i <= 6; i++) { + String string = i + ".png"; + purifiedAnimation.addImage(Animation.Direction.NONE, "/img/gem/red/" + string); + } + break; + } + } + } + + /** + * Set the gem type + * + * @param type The type of gem + */ + public void setType(Type type) { + this.type = type; + loadGemAnimation(type); + } + + /** + * Get the current state of the gem + * + * @return Returns the state of the gem + */ + public State getState() { + return state; + } + + /** + * Set the state of the gem + * + * @param state The new state + */ + public void setState(State state) { + this.state = state; + switch (state) { + case PURIFIED: + try { + purifiedAnimation.setCurrentFrame(0); + } + catch (AnimationException e) { + getLogger().warning(e.getMessage()); + } + setAnimation(purifiedAnimation); + break; + case TAINTED: + try { + taintedAnimation.setCurrentFrame(0); + } + catch (AnimationException e) { + getLogger().warning(e.getMessage()); + } + setAnimation(taintedAnimation); + break; + } + } + + /** + * This method animates the gem + */ + private void animate() { + try { + getAnimation().getNextFrame(); + } + catch (AnimationException e) { + getLogger().warning(e.getMessage()); + } + } + + /** + * This method is run when the thread starts + */ + @Override + public void run() { + super.run(); + while (getActive()) { + try { + Thread.sleep(60); + } + catch (InterruptedException e) { + getLogger().info(e.getMessage()); + } + synchronized (this) { + animate(); + getEscenario().getCanvas().repaint(); + } + } + } + + /** + * The type of gem + */ + public enum Type { + LIFE, + DEATH } /** * The possible states of the gem */ - private enum State { + public enum State { /** * The gem is tainted */ diff --git a/src/main/java/cl/cromer/azaraka/object/Key.java b/src/main/java/cl/cromer/azaraka/object/Key.java index 475600d..1df10fc 100644 --- a/src/main/java/cl/cromer/azaraka/object/Key.java +++ b/src/main/java/cl/cromer/azaraka/object/Key.java @@ -118,7 +118,7 @@ public class Key extends Object implements Constantes { */ public void getKey() { // Remove the key from the cell - getCelda().setObject(null); + getCelda().setObjectOnBottom(null); setState(State.HELD); } diff --git a/src/main/java/cl/cromer/azaraka/object/Object.java b/src/main/java/cl/cromer/azaraka/object/Object.java index 4a1c2c2..2161cef 100644 --- a/src/main/java/cl/cromer/azaraka/object/Object.java +++ b/src/main/java/cl/cromer/azaraka/object/Object.java @@ -16,6 +16,7 @@ package cl.cromer.azaraka.object; import cl.cromer.azaraka.Celda; +import cl.cromer.azaraka.Constantes; import cl.cromer.azaraka.Escenario; import cl.cromer.azaraka.sprite.Animation; import cl.cromer.azaraka.sprite.AnimationException; @@ -23,12 +24,13 @@ import cl.cromer.azaraka.sprite.Sheet; import cl.cromer.azaraka.sprite.SheetException; import java.awt.*; +import java.awt.image.BufferedImage; import java.util.logging.Logger; /** * All game objects extend this class */ -public class Object implements Runnable { +public class Object implements Runnable, Constantes { /** * The scene the object is in */ @@ -61,6 +63,14 @@ public class Object implements Runnable { * Whether or not the run loop of the object is active */ private boolean active; + /** + * x scale + */ + private int xScale = 0; + /** + * y scale + */ + private int yScale = 0; /** * Initialize the object @@ -111,6 +121,24 @@ public class Object implements Runnable { this.y = y; } + /** + * Scale the image to x pixels + * + * @param x The amount of pixels to scale + */ + public void setXScale(int x) { + this.xScale = x; + } + + /** + * Scale the image to y pixels + * + * @param y The amount of pixels to scale + */ + public void setYScale(int y) { + this.yScale = y; + } + /** * Get the scene the object is in * @@ -134,7 +162,7 @@ public class Object implements Runnable { * * @param celda The cell */ - protected void setCelda(Celda celda) { + public void setCelda(Celda celda) { this.celda = celda; } @@ -208,11 +236,45 @@ public class Object implements Runnable { public void drawAnimation(Graphics graphics, int x, int y) { try { if (animation != null && animation.getFrame() != null) { + BufferedImage frame = animation.getFrame(); + if (frame == null) { + // No animation, so don't draw anything + return; + } + + int xOffset = animation.getXOffset(); + int yOffset = animation.getYOffset(); + + // Check if scale is needed + if (xScale != 0 || yScale != 0) { + if (xScale == 0) { + xScale = frame.getWidth(); + } + else if (yScale == 0) { + yScale = frame.getHeight(); + } + frame = Animation.scaleImage(frame, xScale, yScale); + + if (frame.getWidth() == CELL_PIXELS) { + xOffset = 0; + } + else { + xOffset = (CELL_PIXELS - frame.getWidth()) / 2; + } + + if (frame.getHeight() == CELL_PIXELS) { + yOffset = 0; + } + else { + yOffset = (CELL_PIXELS - frame.getHeight()) / 2; + } + } + if (useOffset) { - graphics.drawImage(animation.getFrame(), x + animation.getXOffset(), y + animation.getYOffset(), null); + graphics.drawImage(frame, x + xOffset, y + yOffset, null); } else { - graphics.drawImage(animation.getFrame(), x, y, null); + graphics.drawImage(frame, x, y, null); } } } diff --git a/src/main/java/cl/cromer/azaraka/object/Player.java b/src/main/java/cl/cromer/azaraka/object/Player.java index 2439d7b..08c443c 100644 --- a/src/main/java/cl/cromer/azaraka/object/Player.java +++ b/src/main/java/cl/cromer/azaraka/object/Player.java @@ -67,7 +67,17 @@ public class Player extends Object implements Constantes { */ public void keyPressed(KeyEvent event) { if (!getEscenario().isDoorClosed()) { - getEscenario().setDoorClosed(true); + ArrayList gems = getInventoryGems(); + if (gems.size() < 2) { + getEscenario().setDoorClosed(true); + } + else { + for (Gem gem : gems) { + if (gem.getState() == Gem.State.TAINTED) { + getEscenario().setDoorClosed(true); + } + } + } } switch (event.getKeyCode()) { case KeyEvent.VK_UP: @@ -95,10 +105,14 @@ public class Player extends Object implements Constantes { int x = getX(); int y = getY(); getLogger().info("Up key pressed"); - if (y > 0) { + if (x == 2 && y == 0) { + getEscenario().getCanvas().win(); + } + else if (y > 0) { Object type = getEscenario().getCeldas()[x][y - 1].getObject(); - if (type == null || type instanceof Key) { - if (type != null) { + if (type == null) { + Object typeBottom = getEscenario().getCeldas()[x][y - 1].getObjectOnBottom(); + if (typeBottom instanceof Key) { for (Key key : getEscenario().getCanvas().getKeys()) { if (key.checkPosition(x, y - 1)) { // Get the key @@ -107,6 +121,9 @@ public class Player extends Object implements Constantes { } } } + else if (typeBottom instanceof Portal) { + getEscenario().getCanvas().getPortal().purifyGems(); + } getCelda().setObject(null); setCelda(getEscenario().getCeldas()[x][y - 1]); @@ -123,9 +140,6 @@ public class Player extends Object implements Constantes { setY(getY() - 1); } - else if (type instanceof Portal && getEscenario().getCanvas().getPortal().getState() == Portal.State.ACTIVE) { - getEscenario().getCanvas().win(); - } else { if (changeDirection(Animation.Direction.UP)) { try { @@ -156,10 +170,11 @@ public class Player extends Object implements Constantes { int x = getX(); int y = getY(); getLogger().info("Down key pressed"); - Object type = getEscenario().getCeldas()[x][y + 1].getObject(); if (y < (VERTICAL_CELLS - 1)) { - if (type == null || type instanceof Key) { - if (type != null) { + Object type = getEscenario().getCeldas()[x][y + 1].getObject(); + if (type == null) { + Object typeBottom = getEscenario().getCeldas()[x][y + 1].getObjectOnBottom(); + if (typeBottom instanceof Key) { for (Key key : getEscenario().getCanvas().getKeys()) { if (key.checkPosition(x, y + 1)) { // Get the key @@ -168,6 +183,9 @@ public class Player extends Object implements Constantes { } } } + else if (typeBottom instanceof Portal) { + getEscenario().getCanvas().getPortal().purifyGems(); + } getCelda().setObject(null); setCelda(getEscenario().getCeldas()[x][y + 1]); @@ -184,9 +202,6 @@ public class Player extends Object implements Constantes { setY(getY() + 1); } - else if (type instanceof Portal && getEscenario().getCanvas().getPortal().getState() == Portal.State.ACTIVE) { - getEscenario().getCanvas().win(); - } else { if (changeDirection(Animation.Direction.DOWN)) { try { @@ -219,8 +234,9 @@ public class Player extends Object implements Constantes { getLogger().info("Left key pressed"); if (x > 0) { Object type = getEscenario().getCeldas()[x - 1][y].getObject(); - if (type == null || type instanceof Key) { - if (type != null) { + if (type == null) { + Object typeBottom = getEscenario().getCeldas()[x - 1][y].getObjectOnBottom(); + if (typeBottom instanceof Key) { for (Key key : getEscenario().getCanvas().getKeys()) { if (key.checkPosition(x - 1, y)) { // Get the key @@ -229,6 +245,9 @@ public class Player extends Object implements Constantes { } } } + else if (typeBottom instanceof Portal) { + getEscenario().getCanvas().getPortal().purifyGems(); + } getCelda().setObject(null); setCelda(getEscenario().getCeldas()[x - 1][y]); @@ -245,9 +264,6 @@ public class Player extends Object implements Constantes { setX(getX() - 1); } - else if (type instanceof Portal && getEscenario().getCanvas().getPortal().getState() == Portal.State.ACTIVE) { - getEscenario().getCanvas().win(); - } else { if (changeDirection(Animation.Direction.LEFT)) { try { @@ -278,10 +294,11 @@ public class Player extends Object implements Constantes { int x = getX(); int y = getY(); getLogger().info("Right key pressed"); - Object type = getEscenario().getCeldas()[x + 1][y].getObject(); if (x < (HORIZONTAL_CELLS - 1)) { - if (type == null || type instanceof Key) { - if (type != null) { + Object type = getEscenario().getCeldas()[x + 1][y].getObject(); + if (type == null) { + Object typeBottom = getEscenario().getCeldas()[x + 1][y].getObjectOnBottom(); + if (typeBottom instanceof Key) { for (Key key : getEscenario().getCanvas().getKeys()) { if (key.checkPosition(x + 1, y)) { // Get the key @@ -290,6 +307,9 @@ public class Player extends Object implements Constantes { } } } + else if (typeBottom instanceof Portal) { + getEscenario().getCanvas().getPortal().purifyGems(); + } getCelda().setObject(null); setCelda(getEscenario().getCeldas()[x + 1][y]); @@ -306,9 +326,6 @@ public class Player extends Object implements Constantes { setX(getX() + 1); } - else if (type instanceof Portal && getEscenario().getCanvas().getPortal().getState() == Portal.State.ACTIVE) { - getEscenario().getCanvas().win(); - } else { if (changeDirection(Animation.Direction.RIGHT)) { try { @@ -377,22 +394,16 @@ public class Player extends Object implements Constantes { gainHealth(2); - int openedChests = 0; for (Chest chest : getEscenario().getCanvas().getChests()) { if (chest.checkPosition(x, y - 1)) { if (chest.getState() == Chest.State.CLOSED) { chest.setState(Chest.State.OPENING); + Gem gem = chest.getGem(); + gem.getCelda().setObjectOnTop(gem); useKey(); + break; } } - if (chest.getState() == Chest.State.OPENED || chest.getState() == Chest.State.OPENING) { - openedChests++; - } - } - - // All chests are opened, activate portal - if (openedChests == getEscenario().getCanvas().getChests().size()) { - getEscenario().getCanvas().getPortal().setState(Portal.State.ACTIVE); } } } @@ -436,6 +447,30 @@ public class Player extends Object implements Constantes { return health; } + /** + * Add an object to player inventory + * + * @param object The object to add + */ + public void addInventory(Object object) { + carrying.add(object); + } + + /** + * Get the gems the player has + * + * @return Returns an array of the gems the player is carrying + */ + public ArrayList getInventoryGems() { + ArrayList gems = new ArrayList<>(); + for (Object object : carrying) { + if (object instanceof Gem) { + gems.add((Gem) object); + } + } + return gems; + } + /** * Lose a variable amount of health * diff --git a/src/main/java/cl/cromer/azaraka/object/Portal.java b/src/main/java/cl/cromer/azaraka/object/Portal.java index 52dab4c..1ea4f54 100644 --- a/src/main/java/cl/cromer/azaraka/object/Portal.java +++ b/src/main/java/cl/cromer/azaraka/object/Portal.java @@ -21,6 +21,8 @@ import cl.cromer.azaraka.Escenario; import cl.cromer.azaraka.sprite.Animation; import cl.cromer.azaraka.sprite.AnimationException; +import java.util.ArrayList; + /** * This class handles the portal functionality */ @@ -47,15 +49,15 @@ public class Portal extends Object implements Constantes { public Portal(Escenario escenario, Celda celda) { super(escenario, celda); setLogger(getLogger(this.getClass(), LogLevel.PORTAL)); - loadPortalAnimation(); + loadPortalAnimations(); } /** * Load the portal animation */ - private void loadPortalAnimation() { + private void loadPortalAnimations() { activeAnimation = new Animation(); - for (int i = 0; i < 120; i++) { + for (int i = 0; i <= 119; i++) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(i); while (stringBuilder.length() < 3) { @@ -66,7 +68,7 @@ public class Portal extends Object implements Constantes { } inactiveAnimation = new Animation(); - for (int i = 0; i < 120; i++) { + for (int i = 0; i <= 119; i++) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(i); while (stringBuilder.length() < 3) { @@ -79,6 +81,22 @@ public class Portal extends Object implements Constantes { setAnimation(inactiveAnimation); } + /** + * Purify the gems the player is carrying + */ + public void purifyGems() { + if (state == State.ACTIVE) { + ArrayList gems = getEscenario().getCanvas().getPlayer().getInventoryGems(); + for (Gem gem : gems) { + gem.setState(Gem.State.PURIFIED); + } + setState(State.INACTIVE); + if (gems.size() == 2) { + getEscenario().setDoorClosed(false); + } + } + } + /** * This method animates the portal */ diff --git a/src/main/resources/img/gem/blue/0.png b/src/main/resources/img/gem/blue/0.png new file mode 100755 index 0000000..9eb4f12 Binary files /dev/null and b/src/main/resources/img/gem/blue/0.png differ diff --git a/src/main/resources/img/gem/blue/1.png b/src/main/resources/img/gem/blue/1.png new file mode 100755 index 0000000..f3bb1d5 Binary files /dev/null and b/src/main/resources/img/gem/blue/1.png differ diff --git a/src/main/resources/img/gem/blue/2.png b/src/main/resources/img/gem/blue/2.png new file mode 100755 index 0000000..8a60572 Binary files /dev/null and b/src/main/resources/img/gem/blue/2.png differ diff --git a/src/main/resources/img/gem/blue/3.png b/src/main/resources/img/gem/blue/3.png new file mode 100755 index 0000000..a37cafe Binary files /dev/null and b/src/main/resources/img/gem/blue/3.png differ diff --git a/src/main/resources/img/gem/blue/4.png b/src/main/resources/img/gem/blue/4.png new file mode 100755 index 0000000..4d6ffd7 Binary files /dev/null and b/src/main/resources/img/gem/blue/4.png differ diff --git a/src/main/resources/img/gem/blue/5.png b/src/main/resources/img/gem/blue/5.png new file mode 100755 index 0000000..a1f21ec Binary files /dev/null and b/src/main/resources/img/gem/blue/5.png differ diff --git a/src/main/resources/img/gem/blue/6.png b/src/main/resources/img/gem/blue/6.png new file mode 100755 index 0000000..39b5197 Binary files /dev/null and b/src/main/resources/img/gem/blue/6.png differ diff --git a/src/main/resources/img/gem/gray/0.png b/src/main/resources/img/gem/gray/0.png new file mode 100755 index 0000000..aba587e Binary files /dev/null and b/src/main/resources/img/gem/gray/0.png differ diff --git a/src/main/resources/img/gem/gray/1.png b/src/main/resources/img/gem/gray/1.png new file mode 100755 index 0000000..97419b5 Binary files /dev/null and b/src/main/resources/img/gem/gray/1.png differ diff --git a/src/main/resources/img/gem/gray/2.png b/src/main/resources/img/gem/gray/2.png new file mode 100755 index 0000000..fa9c2f4 Binary files /dev/null and b/src/main/resources/img/gem/gray/2.png differ diff --git a/src/main/resources/img/gem/gray/3.png b/src/main/resources/img/gem/gray/3.png new file mode 100755 index 0000000..14df0c8 Binary files /dev/null and b/src/main/resources/img/gem/gray/3.png differ diff --git a/src/main/resources/img/gem/gray/4.png b/src/main/resources/img/gem/gray/4.png new file mode 100755 index 0000000..83fecf6 Binary files /dev/null and b/src/main/resources/img/gem/gray/4.png differ diff --git a/src/main/resources/img/gem/gray/5.png b/src/main/resources/img/gem/gray/5.png new file mode 100755 index 0000000..22d2528 Binary files /dev/null and b/src/main/resources/img/gem/gray/5.png differ diff --git a/src/main/resources/img/gem/gray/6.png b/src/main/resources/img/gem/gray/6.png new file mode 100755 index 0000000..d1507f9 Binary files /dev/null and b/src/main/resources/img/gem/gray/6.png differ diff --git a/src/main/resources/img/gem/red/0.png b/src/main/resources/img/gem/red/0.png new file mode 100755 index 0000000..d7a2a66 Binary files /dev/null and b/src/main/resources/img/gem/red/0.png differ diff --git a/src/main/resources/img/gem/red/1.png b/src/main/resources/img/gem/red/1.png new file mode 100755 index 0000000..3751179 Binary files /dev/null and b/src/main/resources/img/gem/red/1.png differ diff --git a/src/main/resources/img/gem/red/2.png b/src/main/resources/img/gem/red/2.png new file mode 100755 index 0000000..35a5ee3 Binary files /dev/null and b/src/main/resources/img/gem/red/2.png differ diff --git a/src/main/resources/img/gem/red/3.png b/src/main/resources/img/gem/red/3.png new file mode 100755 index 0000000..145dd12 Binary files /dev/null and b/src/main/resources/img/gem/red/3.png differ diff --git a/src/main/resources/img/gem/red/4.png b/src/main/resources/img/gem/red/4.png new file mode 100755 index 0000000..6d522be Binary files /dev/null and b/src/main/resources/img/gem/red/4.png differ diff --git a/src/main/resources/img/gem/red/5.png b/src/main/resources/img/gem/red/5.png new file mode 100755 index 0000000..bebd5a8 Binary files /dev/null and b/src/main/resources/img/gem/red/5.png differ diff --git a/src/main/resources/img/gem/red/6.png b/src/main/resources/img/gem/red/6.png new file mode 100755 index 0000000..c6526ad Binary files /dev/null and b/src/main/resources/img/gem/red/6.png differ