Add gems and new end game spot
Signed-off-by: Chris Cromer <chris@cromer.cl>
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<option name="OPTION_SCOPE" value="private" />
|
||||
<option name="OPEN_IN_BROWSER" value="false" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="1.8 Oracle" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="false" project-jdk-name="11 OpenJDK" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
@ -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
|
||||
|
@ -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<BufferedImage> textures = new ArrayList<>();
|
||||
/**
|
||||
* The texture numbers
|
||||
*/
|
||||
private final ArrayList<Integer> textureNumbers = new ArrayList<>();
|
||||
private final LinkedHashMap<Integer, BufferedImage> 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<Integer> getTextureNumbers() {
|
||||
return textureNumbers;
|
||||
ArrayList<Integer> arrayList = new ArrayList<>();
|
||||
for (Map.Entry<Integer, BufferedImage> 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<Integer, BufferedImage> 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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<Gem> 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<Object> 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<Gem> 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) {
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
if (useOffset) {
|
||||
graphics.drawImage(animation.getFrame(), x + animation.getXOffset(), y + animation.getYOffset(), 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 {
|
||||
graphics.drawImage(animation.getFrame(), x, y, null);
|
||||
xOffset = (CELL_PIXELS - frame.getWidth()) / 2;
|
||||
}
|
||||
|
||||
if (frame.getHeight() == CELL_PIXELS) {
|
||||
yOffset = 0;
|
||||
}
|
||||
else {
|
||||
yOffset = (CELL_PIXELS - frame.getHeight()) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (useOffset) {
|
||||
graphics.drawImage(frame, x + xOffset, y + yOffset, null);
|
||||
}
|
||||
else {
|
||||
graphics.drawImage(frame, x, y, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,8 +67,18 @@ public class Player extends Object implements Constantes {
|
||||
*/
|
||||
public void keyPressed(KeyEvent event) {
|
||||
if (!getEscenario().isDoorClosed()) {
|
||||
ArrayList<Gem> 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:
|
||||
moveUp();
|
||||
@ -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<Gem> getInventoryGems() {
|
||||
ArrayList<Gem> gems = new ArrayList<>();
|
||||
for (Object object : carrying) {
|
||||
if (object instanceof Gem) {
|
||||
gems.add((Gem) object);
|
||||
}
|
||||
}
|
||||
return gems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lose a variable amount of health
|
||||
*
|
||||
|
@ -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<Gem> 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
|
||||
*/
|
||||
|
BIN
src/main/resources/img/gem/blue/0.png
Executable file
After Width: | Height: | Size: 464 B |
BIN
src/main/resources/img/gem/blue/1.png
Executable file
After Width: | Height: | Size: 447 B |
BIN
src/main/resources/img/gem/blue/2.png
Executable file
After Width: | Height: | Size: 451 B |
BIN
src/main/resources/img/gem/blue/3.png
Executable file
After Width: | Height: | Size: 408 B |
BIN
src/main/resources/img/gem/blue/4.png
Executable file
After Width: | Height: | Size: 439 B |
BIN
src/main/resources/img/gem/blue/5.png
Executable file
After Width: | Height: | Size: 458 B |
BIN
src/main/resources/img/gem/blue/6.png
Executable file
After Width: | Height: | Size: 449 B |
BIN
src/main/resources/img/gem/gray/0.png
Executable file
After Width: | Height: | Size: 463 B |
BIN
src/main/resources/img/gem/gray/1.png
Executable file
After Width: | Height: | Size: 446 B |
BIN
src/main/resources/img/gem/gray/2.png
Executable file
After Width: | Height: | Size: 452 B |
BIN
src/main/resources/img/gem/gray/3.png
Executable file
After Width: | Height: | Size: 415 B |
BIN
src/main/resources/img/gem/gray/4.png
Executable file
After Width: | Height: | Size: 441 B |
BIN
src/main/resources/img/gem/gray/5.png
Executable file
After Width: | Height: | Size: 462 B |
BIN
src/main/resources/img/gem/gray/6.png
Executable file
After Width: | Height: | Size: 450 B |
BIN
src/main/resources/img/gem/red/0.png
Executable file
After Width: | Height: | Size: 465 B |
BIN
src/main/resources/img/gem/red/1.png
Executable file
After Width: | Height: | Size: 445 B |
BIN
src/main/resources/img/gem/red/2.png
Executable file
After Width: | Height: | Size: 451 B |
BIN
src/main/resources/img/gem/red/3.png
Executable file
After Width: | Height: | Size: 406 B |
BIN
src/main/resources/img/gem/red/4.png
Executable file
After Width: | Height: | Size: 439 B |
BIN
src/main/resources/img/gem/red/5.png
Executable file
After Width: | Height: | Size: 456 B |
BIN
src/main/resources/img/gem/red/6.png
Executable file
After Width: | Height: | Size: 447 B |