Change over to gradle build system
Signed-off-by: Chris Cromer <chris@cromer.cl>
168
src/main/java/cl/cromer/azaraka/Celda.java
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka;
|
||||
|
||||
import cl.cromer.azaraka.object.Object;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This class is a cell that will contain a game element such as a player, enemy, prize, etc
|
||||
*/
|
||||
public class Celda extends JComponent implements Constantes {
|
||||
/**
|
||||
* The x graphical coordinate of the cell
|
||||
*/
|
||||
private final int xPixels;
|
||||
/**
|
||||
* The y graphical coordinate of the cell
|
||||
*/
|
||||
private final int yPixels;
|
||||
/**
|
||||
* The x coordinate of the cell
|
||||
*/
|
||||
private final int x;
|
||||
/**
|
||||
* The y coordinate of the cell
|
||||
*/
|
||||
private final int y;
|
||||
/**
|
||||
* The textures to show in this cell
|
||||
*/
|
||||
private final ArrayList<BufferedImage> textures = new ArrayList<>();
|
||||
/**
|
||||
* The texture numbers
|
||||
*/
|
||||
private final ArrayList<Integer> textureNumbers = new ArrayList<>();
|
||||
/**
|
||||
* The object in the cell
|
||||
*/
|
||||
private Object object = null;
|
||||
|
||||
/**
|
||||
* Initialize the cell with its coordinates
|
||||
*
|
||||
* @param xPixels The x graphical coordinate
|
||||
* @param yPixels The y graphical coordinate
|
||||
* @param x The x coordinate of the cell
|
||||
* @param y The y coordinate of the cell
|
||||
*/
|
||||
public Celda(int xPixels, int yPixels, int x, int y) {
|
||||
this.xPixels = xPixels;
|
||||
this.yPixels = yPixels;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object that is in the cell
|
||||
*
|
||||
* @return Returns the object
|
||||
*/
|
||||
public Object getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an object in the cell
|
||||
*
|
||||
* @param object The new object
|
||||
*/
|
||||
public void setObject(Object object) {
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the x coordinate of the cell
|
||||
*
|
||||
* @return Returns the x coordinate
|
||||
*/
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the y coordinate for the cell
|
||||
*
|
||||
* @return Returns the y coordinate
|
||||
*/
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a texture to the texture list
|
||||
*
|
||||
* @param texture The new texture
|
||||
* @param textureNumber The texture's number
|
||||
*/
|
||||
public void addTexture(BufferedImage texture, int textureNumber) {
|
||||
textures.add(texture);
|
||||
textureNumbers.add(textureNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the texture that is on the top of the stack
|
||||
*/
|
||||
public void removeTopTexture() {
|
||||
textures.remove(textures.size() - 1);
|
||||
textureNumbers.remove(textureNumbers.size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the numbers of the textures
|
||||
*
|
||||
* @return Returns an array list containing the texture numbers
|
||||
*/
|
||||
public ArrayList<Integer> getTextureNumbers() {
|
||||
return textureNumbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the paintComponent method of JComponent to paint the cell based on type
|
||||
*
|
||||
* @param g The graphics object to paint
|
||||
*/
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
update(g);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the update method of JComponent to do double buffering
|
||||
*
|
||||
* @param g The graphics object to paint
|
||||
*/
|
||||
@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);
|
||||
if (texture != null) {
|
||||
g.drawImage(texture, xPixels, yPixels, null);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a sprite in the cell if needed
|
||||
if (object != null) {
|
||||
object.drawAnimation(g, xPixels, yPixels);
|
||||
}
|
||||
}
|
||||
}
|
287
src/main/java/cl/cromer/azaraka/Constantes.java
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka;
|
||||
|
||||
import cl.cromer.azaraka.logging.HtmlFormatter;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Random;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Constants used in the game
|
||||
*/
|
||||
public interface Constantes {
|
||||
/**
|
||||
* The name of the game
|
||||
*/
|
||||
String TITLE = "La Aventura de Azaraka";
|
||||
/**
|
||||
* Use a global log if true or individual logs if false
|
||||
*/
|
||||
boolean GLOBAL_LOG = true;
|
||||
/**
|
||||
* Append to the logs if true or make a new log if false
|
||||
*/
|
||||
boolean APPEND_LOGS = false;
|
||||
/**
|
||||
* The size in pixels of the cells
|
||||
*/
|
||||
int CELL_PIXELS = 64;
|
||||
/**
|
||||
* The number of cells to draw horizontally
|
||||
*/
|
||||
int HORIZONTAL_CELLS = 18;
|
||||
/**
|
||||
* The number of cells to draw vertically
|
||||
*/
|
||||
int VERTICAL_CELLS = 10;
|
||||
/**
|
||||
* The amount of margin before drawing the cells
|
||||
*/
|
||||
int TOP_MARGIN = 40;
|
||||
/**
|
||||
* The amount of margin to the left and right of cells
|
||||
*/
|
||||
int LEFT_MARGIN = 40;
|
||||
/**
|
||||
* The amount of chests to draw
|
||||
*/
|
||||
int CHESTS = 2;
|
||||
/**
|
||||
* The amount of enemies to draw
|
||||
*/
|
||||
int ENEMIES = 3;
|
||||
/**
|
||||
* The font size to use
|
||||
*/
|
||||
int FONT_SIZE = 12;
|
||||
/**
|
||||
* The minimum speed of the enemies
|
||||
*/
|
||||
int MINIMUM_SPEED = 100;
|
||||
/**
|
||||
* The maximum speed of the enemies
|
||||
*/
|
||||
int MAXIMUM_SPEED = 500;
|
||||
/**
|
||||
* The default speed of the enemies
|
||||
*/
|
||||
int DEFAULT_SPEED = 100;
|
||||
/**
|
||||
* The minimum volume
|
||||
*/
|
||||
int MINIMUM_VOLUME = 0;
|
||||
/**
|
||||
* The maximum volume
|
||||
*/
|
||||
int MAXIMUM_VOLUME = 100;
|
||||
/**
|
||||
* The default volume
|
||||
*/
|
||||
int DEFAULT_VOLUME = 100;
|
||||
/**
|
||||
* Generates the scene manually instead of from the JSON file if true
|
||||
*/
|
||||
boolean GENERATE_SCENE = false;
|
||||
/**
|
||||
* Exports the scene to a JSON file if true
|
||||
*/
|
||||
boolean EXPORT_SCENE = false;
|
||||
/**
|
||||
* Use pretty JSON if true
|
||||
*/
|
||||
boolean PRETTY_JSON = true;
|
||||
/**
|
||||
* The normal font to use
|
||||
*/
|
||||
Font FONT = new Font("monospaced", Font.PLAIN, FONT_SIZE);
|
||||
|
||||
/**
|
||||
* Get a logger object to use for debugging
|
||||
*
|
||||
* @param logClass The class that is in need of a logger
|
||||
* @param logLevel What log level to use
|
||||
* @return Returns the logger
|
||||
*/
|
||||
default Logger getLogger(Class logClass, LogLevel logLevel) {
|
||||
String className = logClass.getName();
|
||||
Logger logger;
|
||||
if (GLOBAL_LOG) {
|
||||
logger = Logger.getGlobal();
|
||||
}
|
||||
else {
|
||||
logger = Logger.getLogger(className);
|
||||
}
|
||||
if (logger.getHandlers().length == 0) {
|
||||
initializeLogger(logClass);
|
||||
}
|
||||
if (GLOBAL_LOG) {
|
||||
logger.setLevel(LogLevel.GLOBAL.getLevel());
|
||||
}
|
||||
else {
|
||||
logger.setLevel(logLevel.getLevel());
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random number between given min and max
|
||||
*
|
||||
* @param min Minimum number in range
|
||||
* @param max Maximum number in range
|
||||
* @return Returns a random number
|
||||
*/
|
||||
default int random(int min, int max) {
|
||||
Random random = new Random();
|
||||
return random.nextInt((max - min) + 1) + min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the logger and assign a html handler
|
||||
*
|
||||
* @param logClass The class to be initialized
|
||||
*/
|
||||
default void initializeLogger(Class logClass) {
|
||||
String className = logClass.getName();
|
||||
Logger logger;
|
||||
if (GLOBAL_LOG) {
|
||||
logger = Logger.getGlobal();
|
||||
}
|
||||
else {
|
||||
logger = Logger.getLogger(className);
|
||||
}
|
||||
FileHandler fileHandler = null;
|
||||
File directory = new File("log");
|
||||
if (!directory.exists()) {
|
||||
if (!directory.mkdir()) {
|
||||
System.out.println("Could not make directory \"log\"");
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (GLOBAL_LOG) {
|
||||
fileHandler = new FileHandler("log/log.html", APPEND_LOGS);
|
||||
}
|
||||
else {
|
||||
fileHandler = new FileHandler("log/" + className + ".html", APPEND_LOGS);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (fileHandler != null) {
|
||||
logger.addHandler(fileHandler);
|
||||
}
|
||||
Formatter formatter = new HtmlFormatter();
|
||||
if (fileHandler != null) {
|
||||
fileHandler.setFormatter(formatter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This enum contains all the levels used for logging
|
||||
*/
|
||||
enum LogLevel {
|
||||
/**
|
||||
* The global log level is used if the individual log levels are not
|
||||
*/
|
||||
GLOBAL(Level.WARNING),
|
||||
/**
|
||||
* The main log level
|
||||
*/
|
||||
MAIN(Level.INFO),
|
||||
/**
|
||||
* The ventana principal log level
|
||||
*/
|
||||
VENTANA_PRINCIPAL(Level.INFO),
|
||||
/**
|
||||
* The lienzo log level
|
||||
*/
|
||||
LIENZO(Level.INFO),
|
||||
/**
|
||||
* The escenario log level
|
||||
*/
|
||||
ESCENARIO(Level.INFO),
|
||||
/**
|
||||
* The player log level
|
||||
*/
|
||||
PLAYER(Level.WARNING),
|
||||
/**
|
||||
* The enemy log level
|
||||
*/
|
||||
ENEMY(Level.WARNING),
|
||||
/**
|
||||
* The chest log level
|
||||
*/
|
||||
CHEST(Level.INFO),
|
||||
/**
|
||||
* The config log level
|
||||
*/
|
||||
CONFIG(Level.INFO),
|
||||
/**
|
||||
* The sound log level
|
||||
*/
|
||||
SOUND(Level.INFO),
|
||||
/**
|
||||
* The animation log level
|
||||
*/
|
||||
ANIMATION(Level.INFO),
|
||||
/**
|
||||
* The sheet log level
|
||||
*/
|
||||
SHEET(Level.INFO),
|
||||
/**
|
||||
* The key log level
|
||||
*/
|
||||
KEY(Level.INFO),
|
||||
/**
|
||||
* The json log level
|
||||
*/
|
||||
JSON(Level.INFO),
|
||||
/**
|
||||
* The portal log level
|
||||
*/
|
||||
PORTAL(Level.INFO);
|
||||
|
||||
/**
|
||||
* The level of log for the enum
|
||||
*/
|
||||
private final Level level;
|
||||
|
||||
/**
|
||||
* Initialize the log level enum
|
||||
*
|
||||
* @param level The level for each element
|
||||
*/
|
||||
LogLevel(Level level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the level for the specific part
|
||||
*
|
||||
* @return Returns the level
|
||||
*/
|
||||
protected Level getLevel() {
|
||||
return this.level;
|
||||
}
|
||||
}
|
||||
}
|
511
src/main/java/cl/cromer/azaraka/Escenario.java
Normal file
@@ -0,0 +1,511 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka;
|
||||
|
||||
import cl.cromer.azaraka.json.Cell;
|
||||
import cl.cromer.azaraka.json.Json;
|
||||
import cl.cromer.azaraka.object.Object;
|
||||
import cl.cromer.azaraka.object.*;
|
||||
import cl.cromer.azaraka.sprite.Sheet;
|
||||
import cl.cromer.azaraka.sprite.SheetException;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* The scene used for the game
|
||||
*/
|
||||
public class Escenario extends JComponent implements Constantes {
|
||||
/**
|
||||
* The width of the scene
|
||||
*/
|
||||
protected final int width = CELL_PIXELS * HORIZONTAL_CELLS;
|
||||
/**
|
||||
* The height of the scene
|
||||
*/
|
||||
protected final int height = CELL_PIXELS * VERTICAL_CELLS;
|
||||
/**
|
||||
* The canvas
|
||||
*/
|
||||
private final Lienzo canvas;
|
||||
/**
|
||||
* The cells of the game
|
||||
*/
|
||||
private final Celda[][] celdas;
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private final Logger logger;
|
||||
/**
|
||||
* A collection of tiles that can be used in the scene
|
||||
*/
|
||||
private Sheet textureSheet;
|
||||
/**
|
||||
* Whether or not the door is closed yet
|
||||
*/
|
||||
private boolean doorClosed = false;
|
||||
|
||||
/**
|
||||
* Initialize the scene
|
||||
*
|
||||
* @param canvas The canvas that this scene is in
|
||||
*/
|
||||
public Escenario(Lienzo canvas) {
|
||||
logger = getLogger(this.getClass(), LogLevel.ESCENARIO);
|
||||
this.canvas = canvas;
|
||||
loadTextures();
|
||||
|
||||
celdas = new Celda[HORIZONTAL_CELLS][VERTICAL_CELLS];
|
||||
|
||||
if (GENERATE_SCENE) {
|
||||
generateScene();
|
||||
}
|
||||
else {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
InputStream inputStream = getClass().getResourceAsStream("/scene.json");
|
||||
try {
|
||||
String line;
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
stringBuilder.append(line);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
loadScene(stringBuilder.toString());
|
||||
}
|
||||
|
||||
if (EXPORT_SCENE) {
|
||||
Json json = new Json();
|
||||
json.exportScene(celdas);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the scene from a JSON file
|
||||
*
|
||||
* @param json The JSON string to load
|
||||
*/
|
||||
private void loadScene(String json) {
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
Gson gson = gsonBuilder.create();
|
||||
Cell[][] cells = gson.fromJson(json, Cell[][].class);
|
||||
|
||||
for (int x = 0; x < cells.length; x++) {
|
||||
for (int y = 0; y < cells[x].length; y++) {
|
||||
celdas[x][y] = new Celda((x * CELL_PIXELS) + LEFT_MARGIN, (y * CELL_PIXELS) + TOP_MARGIN, x, y);
|
||||
|
||||
if (cells[x][y].type.equals(Player.class.getName())) {
|
||||
celdas[x][y].setObject(new Player(null, celdas[x][y]));
|
||||
}
|
||||
else if (cells[x][y].type.equals(Enemy.class.getName())) {
|
||||
celdas[x][y].setObject(new Enemy(null, celdas[x][y], null));
|
||||
}
|
||||
else if (cells[x][y].type.equals(Chest.class.getName())) {
|
||||
celdas[x][y].setObject(new Chest(null, celdas[x][y]));
|
||||
}
|
||||
else if (cells[x][y].type.equals(Gem.class.getName())) {
|
||||
celdas[x][y].setObject(new Gem(null, celdas[x][y]));
|
||||
}
|
||||
else if (cells[x][y].type.equals(Key.class.getName())) {
|
||||
celdas[x][y].setObject(new Key(null, celdas[x][y]));
|
||||
}
|
||||
else if (cells[x][y].type.equals(Obstacle.class.getName())) {
|
||||
celdas[x][y].setObject(new Obstacle(null, celdas[x][y]));
|
||||
}
|
||||
else if (cells[x][y].type.equals(Portal.class.getName())) {
|
||||
celdas[x][y].setObject(new Portal(null, celdas[x][y]));
|
||||
}
|
||||
|
||||
for (int k = 0; k < cells[x][y].textures.size(); k++) {
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(cells[x][y].textures.get(k)), cells[x][y].textures.get(k));
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate random objects in the scene
|
||||
*
|
||||
* @return Returns a list of objects that where generated
|
||||
*/
|
||||
public ArrayList<Object> generateRandomObjects() {
|
||||
final int cells = (HORIZONTAL_CELLS * VERTICAL_CELLS);
|
||||
final int obstacles = (int) Math.floor((double) cells * 0.05);
|
||||
|
||||
int[] random;
|
||||
ArrayList<Object> objectArrayList = new ArrayList<>();
|
||||
|
||||
// The player has a fixed position
|
||||
celdas[2][1].setObject(new Player(this, celdas[2][1]));
|
||||
objectArrayList.add(celdas[2][1].getObject());
|
||||
|
||||
final Lock lock = new ReentrantLock(true);
|
||||
|
||||
for (int i = 0; i < obstacles; i++) {
|
||||
random = randomCoordinates();
|
||||
celdas[random[0]][random[1]].setObject(new Obstacle(this, celdas[random[0]][random[1]]));
|
||||
try {
|
||||
celdas[random[0]][random[1]].addTexture(textureSheet.getTexture(30), 30);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < ENEMIES; i++) {
|
||||
random = randomCoordinates();
|
||||
celdas[random[0]][random[1]].setObject(new Enemy(this, celdas[random[0]][random[1]], lock));
|
||||
objectArrayList.add(celdas[random[0]][random[1]].getObject());
|
||||
}
|
||||
|
||||
random = randomCoordinates();
|
||||
celdas[random[0]][random[1]].setObject(new Portal(this, celdas[random[0]][random[1]]));
|
||||
objectArrayList.add(celdas[random[0]][random[1]].getObject());
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
// Chests need to be last to make sure they are openable
|
||||
for (int i = 0; i < CHESTS; i++) {
|
||||
int random_x = random(0, HORIZONTAL_CELLS - 1);
|
||||
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) {
|
||||
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());
|
||||
}
|
||||
|
||||
return objectArrayList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get random x and y coordinates
|
||||
*
|
||||
* @return Returns an array with the coordinates
|
||||
*/
|
||||
private int[] randomCoordinates() {
|
||||
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) {
|
||||
random[0] = random(0, HORIZONTAL_CELLS - 1);
|
||||
random[1] = random(0, VERTICAL_CELLS - 1);
|
||||
}
|
||||
return random;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the scene manually without the JSON file
|
||||
*/
|
||||
private void generateScene() {
|
||||
for (int x = 0; x < HORIZONTAL_CELLS; x++) {
|
||||
for (int y = 0; y < VERTICAL_CELLS; y++) {
|
||||
logger.info("Generate cell x: " + x + " y: " + y + " manually");
|
||||
celdas[x][y] = new Celda((x * CELL_PIXELS) + LEFT_MARGIN, (y * CELL_PIXELS) + TOP_MARGIN, x, y);
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(0), 0);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
|
||||
if (x == 0 && y == 0) {
|
||||
// Top left corner
|
||||
celdas[x][y].setObject(new Obstacle(this, celdas[x][y]));
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(33), 33);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else if (x == HORIZONTAL_CELLS - 1 && y == 0) {
|
||||
// Top right corner
|
||||
celdas[x][y].setObject(new Obstacle(this, celdas[x][y]));
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(37), 37);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else if (x == 0 && y == VERTICAL_CELLS - 1) {
|
||||
// Bottom left corner
|
||||
celdas[x][y].setObject(new Obstacle(this, celdas[x][y]));
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(97), 97);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else if (x == HORIZONTAL_CELLS - 1 && y == VERTICAL_CELLS - 1) {
|
||||
// Bottom right corner
|
||||
celdas[x][y].setObject(new Obstacle(this, celdas[x][y]));
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(101), 101);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else if (y == 0) {
|
||||
// Top wall
|
||||
celdas[x][y].setObject(new Obstacle(this, celdas[x][y]));
|
||||
if (x == 1) {
|
||||
// Left door frame
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(144), 144);
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(192), 192);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else if (x == 2) {
|
||||
// Door
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(145), 145);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else if (x == 3) {
|
||||
// Right door frame
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(146), 146);
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(194), 194);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else if (x == 8) {
|
||||
// Broken wall piece
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(105), 105);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else if (x % 2 == 0) {
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(34), 34);
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(222), 222);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(35), 35);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (x == 0) {
|
||||
// Left wall
|
||||
celdas[x][y].setObject(new Obstacle(this, celdas[x][y]));
|
||||
if (y % 2 == 0) {
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(49), 49);
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(255), 255);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(65), 65);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (x == HORIZONTAL_CELLS - 1) {
|
||||
// Right wall
|
||||
celdas[x][y].setObject(new Obstacle(this, celdas[x][y]));
|
||||
if (y % 2 == 0) {
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(53), 53);
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(238), 238);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(69), 69);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (y == VERTICAL_CELLS - 1) {
|
||||
// Bottom wall
|
||||
celdas[x][y].setObject(new Obstacle(this, celdas[x][y]));
|
||||
if (x % 2 == 0) {
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(98), 98);
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(207), 207);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
celdas[x][y].addTexture(textureSheet.getTexture(99), 99);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The player starts at the door
|
||||
/*if (x == 2 && y == 1) {
|
||||
celdas[x][y].setObject(new Player(this, celdas[x][y]));
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all the textures that will be shown in the game
|
||||
*/
|
||||
private void loadTextures() {
|
||||
textureSheet = new Sheet("/img/textures/dungeon.png", 64, 64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cells of the game
|
||||
*
|
||||
* @return Returns a matrix of the cells of the game
|
||||
*/
|
||||
public Celda[][] getCeldas() {
|
||||
return celdas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the paintComponent method of JComponent to paint the scene
|
||||
*
|
||||
* @param g The graphics object to paint
|
||||
*/
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
update(g);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the update method of JComponent to do double buffering
|
||||
*
|
||||
* @param g The graphics object
|
||||
*/
|
||||
@Override
|
||||
public void update(Graphics g) {
|
||||
for (int i = 0; i < HORIZONTAL_CELLS; i++) {
|
||||
for (int j = 0; j < VERTICAL_CELLS; j++) {
|
||||
celdas[i][j].paintComponent(g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent canvas of this scene
|
||||
*
|
||||
* @return Returns the parent canvas
|
||||
*/
|
||||
public Lienzo getCanvas() {
|
||||
return canvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if door is closed or not
|
||||
*
|
||||
* @return Returns true if closed or false if open
|
||||
*/
|
||||
public boolean isDoorClosed() {
|
||||
return doorClosed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the state of the door
|
||||
*
|
||||
* @param doorClosed Set to true to the close the door or false to open it
|
||||
*/
|
||||
public void setDoorClosed(boolean doorClosed) {
|
||||
if (doorClosed && !isDoorClosed()) {
|
||||
try {
|
||||
celdas[2][0].addTexture(textureSheet.getTexture(193), 193);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.doorClosed = true;
|
||||
}
|
||||
else if (!doorClosed && isDoorClosed()) {
|
||||
celdas[2][0].removeTopTexture();
|
||||
this.doorClosed = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the texture sheet
|
||||
*
|
||||
* @return Returns the texture sheet
|
||||
*/
|
||||
public Sheet getTextureSheet() {
|
||||
return textureSheet;
|
||||
}
|
||||
}
|
438
src/main/java/cl/cromer/azaraka/Lienzo.java
Normal file
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka;
|
||||
|
||||
import cl.cromer.azaraka.object.Object;
|
||||
import cl.cromer.azaraka.object.*;
|
||||
import cl.cromer.azaraka.sound.Sound;
|
||||
import cl.cromer.azaraka.sound.SoundException;
|
||||
import cl.cromer.azaraka.sprite.Animation;
|
||||
import cl.cromer.azaraka.sprite.AnimationException;
|
||||
|
||||
import javax.sound.sampled.Clip;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* This class extends the canvas to make drawing and listening easier
|
||||
*/
|
||||
public class Lienzo extends Canvas implements Constantes {
|
||||
/**
|
||||
* The game scene
|
||||
*/
|
||||
private final Escenario escenario;
|
||||
/**
|
||||
* The threads for the objects
|
||||
*/
|
||||
private final HashMap<Object, Thread> threads = new HashMap<>();
|
||||
/**
|
||||
* The enemies
|
||||
*/
|
||||
private final ArrayList<Enemy> enemies = new ArrayList<>();
|
||||
/**
|
||||
* The keys
|
||||
*/
|
||||
private final ArrayList<Key> keys = new ArrayList<>();
|
||||
/**
|
||||
* The chests
|
||||
*/
|
||||
private final ArrayList<Chest> chests = new ArrayList<>();
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private final Logger logger;
|
||||
/**
|
||||
* The game over animation
|
||||
*/
|
||||
private final Animation gameOverAnimation;
|
||||
/**
|
||||
* The graphics buffer
|
||||
*/
|
||||
private Graphics graphicBuffer;
|
||||
/**
|
||||
* The image buffer
|
||||
*/
|
||||
private Image imageBuffer;
|
||||
/**
|
||||
* The player
|
||||
*/
|
||||
private Player player;
|
||||
/**
|
||||
* The magic portal
|
||||
*/
|
||||
private Portal portal;
|
||||
/**
|
||||
* The hearts animation
|
||||
*/
|
||||
private Animation heartAnimation;
|
||||
/**
|
||||
* The background music of the game
|
||||
*/
|
||||
private Sound backgroundMusic;
|
||||
/**
|
||||
* The music played when game over shows
|
||||
*/
|
||||
private Sound gameOverMusic;
|
||||
/**
|
||||
* The sound played when a gem is purified or the player wins
|
||||
*/
|
||||
private Sound successSound;
|
||||
/**
|
||||
* Has the game started
|
||||
*/
|
||||
private boolean gameStarted = false;
|
||||
/**
|
||||
* Game over
|
||||
*/
|
||||
private boolean gameOver = false;
|
||||
/**
|
||||
* If the game over loop has been run at least once
|
||||
*/
|
||||
private boolean gameOverRan = false;
|
||||
/**
|
||||
* The current volume
|
||||
*/
|
||||
private float volume = (float) DEFAULT_VOLUME / 100;
|
||||
|
||||
/**
|
||||
* Initialize the canvas
|
||||
*/
|
||||
public Lienzo() {
|
||||
logger = getLogger(this.getClass(), LogLevel.LIENZO);
|
||||
|
||||
// Load the sounds
|
||||
try {
|
||||
backgroundMusic = new Sound("/snd/GameLoop.wav");
|
||||
gameOverMusic = new Sound("/snd/GameOver.wav");
|
||||
successSound = new Sound("/snd/Success.wav");
|
||||
}
|
||||
catch (SoundException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
|
||||
// Load the game over
|
||||
gameOverAnimation = new Animation();
|
||||
gameOverAnimation.addImage(Animation.Direction.NONE, "/img/gameover/gameover.png");
|
||||
|
||||
escenario = new Escenario(this);
|
||||
setBackground(Color.black);
|
||||
setSize(escenario.width, escenario.height);
|
||||
|
||||
Enemy.Direction enemyDirection = Enemy.Direction.DOWN;
|
||||
|
||||
ArrayList<Object> objectList = escenario.generateRandomObjects();
|
||||
for (Object object : objectList) {
|
||||
object.getCelda().setObject(object);
|
||||
if (object instanceof Player) {
|
||||
player = (Player) object;
|
||||
threads.put(object, new Thread(object));
|
||||
}
|
||||
else if (object instanceof Enemy) {
|
||||
((Enemy) object).setDirection(enemyDirection);
|
||||
if (enemyDirection == Enemy.Direction.UP) {
|
||||
enemyDirection = Enemy.Direction.DOWN;
|
||||
}
|
||||
else if (enemyDirection == Enemy.Direction.DOWN) {
|
||||
enemyDirection = Enemy.Direction.LEFT;
|
||||
}
|
||||
else if (enemyDirection == Enemy.Direction.LEFT) {
|
||||
enemyDirection = Enemy.Direction.RIGHT;
|
||||
}
|
||||
else {
|
||||
enemyDirection = Enemy.Direction.UP;
|
||||
}
|
||||
enemies.add((Enemy) object);
|
||||
threads.put(object, new Thread(object));
|
||||
}
|
||||
else if (object instanceof Chest) {
|
||||
chests.add((Chest) object);
|
||||
threads.put(object, new Thread(object));
|
||||
}
|
||||
else if (object instanceof Key) {
|
||||
keys.add((Key) object);
|
||||
threads.put(object, new Thread(object));
|
||||
}
|
||||
else if (object instanceof Portal) {
|
||||
portal = (Portal) object;
|
||||
threads.put(object, new Thread(object));
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<Object, Thread> entry : threads.entrySet()) {
|
||||
Thread thread = entry.getValue();
|
||||
thread.start();
|
||||
}
|
||||
|
||||
addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent event) {
|
||||
super.keyPressed(event);
|
||||
if (!gameOver) {
|
||||
player.keyPressed(event);
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the paint method of Canvas to paint all the scene components
|
||||
*
|
||||
* @param g The graphics object to paint
|
||||
*/
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
update(g);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the update method of Canvas to update using a double buffer
|
||||
*
|
||||
* @param g The graphics object to paint
|
||||
*/
|
||||
@Override
|
||||
public void update(Graphics g) {
|
||||
if (graphicBuffer == null) {
|
||||
imageBuffer = createImage(this.getWidth(), this.getHeight());
|
||||
graphicBuffer = imageBuffer.getGraphics();
|
||||
}
|
||||
|
||||
graphicBuffer.setColor(getBackground());
|
||||
graphicBuffer.fillRect(0, 0, this.getWidth(), this.getHeight());
|
||||
|
||||
int xKey = LEFT_MARGIN;
|
||||
for (Key key : keys) {
|
||||
if (key.getState() == Key.State.HELD) {
|
||||
key.drawAnimation(graphicBuffer, xKey, 8);
|
||||
xKey = xKey + 3 + (key.getAnimationWidth());
|
||||
}
|
||||
}
|
||||
|
||||
if (player != null) {
|
||||
int health = player.getHealth();
|
||||
if (health == 0) {
|
||||
gameOver = true;
|
||||
}
|
||||
int hearts = Player.MAX_HEALTH / 4;
|
||||
if (heartAnimation == null) {
|
||||
heartAnimation = new Animation();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
heartAnimation.addImage(Animation.Direction.NONE, "/img/heart/heart" + i + ".png");
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < hearts; i++) {
|
||||
try {
|
||||
heartAnimation.setCurrentFrame(Math.min(health, 4));
|
||||
int x = (HORIZONTAL_CELLS * CELL_PIXELS) + LEFT_MARGIN - (heartAnimation.getFrame().getWidth() * hearts) + (heartAnimation.getFrame().getWidth() * i);
|
||||
graphicBuffer.drawImage(heartAnimation.getFrame(), x, 8, null);
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
if (health > 0) {
|
||||
health = health - 4;
|
||||
if (health < 0) {
|
||||
health = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gameOver) {
|
||||
if (!gameOverRan) {
|
||||
stopBackgroundMusic();
|
||||
|
||||
try {
|
||||
gameOverMusic.setVolume(volume);
|
||||
gameOverMusic.play();
|
||||
}
|
||||
catch (SoundException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
|
||||
stopThreads();
|
||||
|
||||
gameOverRan = true;
|
||||
}
|
||||
|
||||
// Place the game over image on the screen
|
||||
graphicBuffer.setColor(Color.black);
|
||||
graphicBuffer.drawRect(0, 0, getWidth(), getHeight());
|
||||
try {
|
||||
int x = (getWidth() - gameOverAnimation.getFrame().getWidth()) / 2;
|
||||
int y = (getHeight() - gameOverAnimation.getFrame().getHeight()) / 2;
|
||||
graphicBuffer.drawImage(gameOverAnimation.getFrame(), x, y, null);
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
escenario.paintComponent(graphicBuffer);
|
||||
}
|
||||
|
||||
if (!gameStarted) {
|
||||
gameStarted = true;
|
||||
try {
|
||||
if (!backgroundMusic.isPlaying()) {
|
||||
backgroundMusic.setVolume(volume);
|
||||
backgroundMusic.play();
|
||||
backgroundMusic.setLoops(Clip.LOOP_CONTINUOUSLY);
|
||||
}
|
||||
}
|
||||
catch (SoundException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
g.drawImage(imageBuffer, 0, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the background music
|
||||
*/
|
||||
private void stopBackgroundMusic() {
|
||||
try {
|
||||
if (backgroundMusic.isPlaying()) {
|
||||
backgroundMusic.stop();
|
||||
}
|
||||
}
|
||||
catch (SoundException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop all active threads
|
||||
*/
|
||||
private void stopThreads() {
|
||||
for (Map.Entry<Object, Thread> entry : threads.entrySet()) {
|
||||
Thread thread = entry.getValue();
|
||||
if (thread.isAlive()) {
|
||||
Object object = entry.getKey();
|
||||
object.setActive(false);
|
||||
thread.interrupt();
|
||||
try {
|
||||
thread.join();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
logger.info(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is won
|
||||
*/
|
||||
public void win() {
|
||||
stopBackgroundMusic();
|
||||
|
||||
try {
|
||||
successSound.setVolume(volume);
|
||||
successSound.play();
|
||||
}
|
||||
catch (SoundException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
|
||||
stopThreads();
|
||||
JOptionPane.showMessageDialog(null, "Ganaste!");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the speed of the enemies
|
||||
*
|
||||
* @param speed The new speed
|
||||
*/
|
||||
public void changeSpeed(int speed) {
|
||||
if (speed <= 0) {
|
||||
speed = 1;
|
||||
}
|
||||
for (Enemy enemy : enemies) {
|
||||
enemy.setSpeed(speed);
|
||||
}
|
||||
requestFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current volume
|
||||
*
|
||||
* @return Returns the current volume
|
||||
*/
|
||||
public float getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the volume of the game background music
|
||||
*
|
||||
* @param volume The new volume
|
||||
*/
|
||||
public void changeVolume(float volume) {
|
||||
this.volume = volume;
|
||||
try {
|
||||
backgroundMusic.setVolume(volume);
|
||||
}
|
||||
catch (SoundException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
requestFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player
|
||||
*
|
||||
* @return Returns the player object
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the portal
|
||||
*
|
||||
* @return Returns the portal object
|
||||
*/
|
||||
public Portal getPortal() {
|
||||
return portal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of the keys that exist
|
||||
*
|
||||
* @return Returns all the keys that are in the game
|
||||
*/
|
||||
public ArrayList<Key> getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of the chests that exist
|
||||
*
|
||||
* @return Returns all the chests that are in the game
|
||||
*/
|
||||
public ArrayList<Chest> getChests() {
|
||||
return chests;
|
||||
}
|
||||
}
|
47
src/main/java/cl/cromer/azaraka/Main.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* The main class of the game
|
||||
*/
|
||||
public class Main implements Constantes {
|
||||
|
||||
/**
|
||||
* Initialize the main class
|
||||
*/
|
||||
private Main() {
|
||||
Logger logger = getLogger(this.getClass(), LogLevel.MAIN);
|
||||
|
||||
logger.info("Load main window");
|
||||
VentanaPrincipal ventanaPrincipal = new VentanaPrincipal();
|
||||
ventanaPrincipal.setVisible(true);
|
||||
ventanaPrincipal.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the main window
|
||||
*
|
||||
* @param args The arguments passed to the application
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
new Main();
|
||||
}
|
||||
|
||||
}
|
71
src/main/java/cl/cromer/azaraka/VentanaPrincipal.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka;
|
||||
|
||||
import cl.cromer.azaraka.panel.Config;
|
||||
import cl.cromer.azaraka.panel.Game;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* The main window of the game
|
||||
*/
|
||||
public class VentanaPrincipal extends JFrame implements Constantes {
|
||||
|
||||
/**
|
||||
* Initialize the main window
|
||||
*/
|
||||
public VentanaPrincipal() {
|
||||
Logger logger = getLogger(this.getClass(), LogLevel.VENTANA_PRINCIPAL);
|
||||
|
||||
logger.info("Create panels");
|
||||
|
||||
setExtendedState(this.getExtendedState() | JFrame.MAXIMIZED_BOTH);
|
||||
setSize(Toolkit.getDefaultToolkit().getScreenSize());
|
||||
|
||||
setTitle(TITLE);
|
||||
String icon = "/img/icon.png";
|
||||
try {
|
||||
BufferedImage image = ImageIO.read(getClass().getResourceAsStream(icon));
|
||||
this.setIconImage(image);
|
||||
}
|
||||
catch (IOException | IllegalArgumentException e) {
|
||||
logger.warning("Failed to load icon: " + icon);
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
|
||||
Container contentPane = getContentPane();
|
||||
contentPane.setLayout(new BorderLayout());
|
||||
|
||||
JSplitPane panelSeparator = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
||||
panelSeparator.setOneTouchExpandable(true);
|
||||
|
||||
Game gamePanel = new Game();
|
||||
Config configPanel = new Config(gamePanel);
|
||||
|
||||
panelSeparator.setLeftComponent(gamePanel);
|
||||
panelSeparator.setRightComponent(configPanel);
|
||||
panelSeparator.setDividerLocation(gamePanel.getWidth() + (LEFT_MARGIN * 2));
|
||||
panelSeparator.setDividerSize(0);
|
||||
|
||||
contentPane.add(panelSeparator, BorderLayout.CENTER);
|
||||
}
|
||||
}
|
32
src/main/java/cl/cromer/azaraka/json/Cell.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.json;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This class represents the structure of a cell in JSON
|
||||
*/
|
||||
public class Cell {
|
||||
/**
|
||||
* The type of cell, e.g. player, chest, enemy, etc
|
||||
*/
|
||||
public String type;
|
||||
/**
|
||||
* A list of the textures to apply to the cell
|
||||
*/
|
||||
public ArrayList<Integer> textures = new ArrayList<>();
|
||||
}
|
92
src/main/java/cl/cromer/azaraka/json/Json.java
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.json;
|
||||
|
||||
import cl.cromer.azaraka.Celda;
|
||||
import cl.cromer.azaraka.Constantes;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* This class handles reading and writing of JSON objects
|
||||
*/
|
||||
public class Json implements Constantes {
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private final Logger logger;
|
||||
|
||||
/**
|
||||
* Initialize the JSON object
|
||||
*/
|
||||
public Json() {
|
||||
logger = getLogger(this.getClass(), LogLevel.JSON);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the game cells to a JSON ready object then write it to a file
|
||||
*
|
||||
* @param celdas The cells of the scene to export
|
||||
*/
|
||||
public void exportScene(Celda[][] celdas) {
|
||||
Cell[][] cells = new Cell[celdas.length][celdas[0].length];
|
||||
for (int x = 0; x < celdas.length; x++) {
|
||||
for (int y = 0; y < celdas[x].length; y++) {
|
||||
cells[x][y] = new Cell();
|
||||
if (celdas[x][y].getObject() != null) {
|
||||
cells[x][y].type = celdas[x][y].getObject().getClass().getName();
|
||||
}
|
||||
else {
|
||||
cells[x][y].type = "null";
|
||||
}
|
||||
cells[x][y].textures = celdas[x][y].getTextureNumbers();
|
||||
}
|
||||
}
|
||||
writeScene(cells);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the JSON scene to a file
|
||||
*
|
||||
* @param cells The JSON cells object
|
||||
*/
|
||||
private void writeScene(Cell[][] cells) {
|
||||
GsonBuilder gsonBuilder;
|
||||
if (PRETTY_JSON) {
|
||||
gsonBuilder = new GsonBuilder().setPrettyPrinting();
|
||||
}
|
||||
else {
|
||||
gsonBuilder = new GsonBuilder();
|
||||
}
|
||||
Gson gson = gsonBuilder.create();
|
||||
String json = gson.toJson(cells);
|
||||
|
||||
File file = new File("res/scene.json");
|
||||
try {
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||
fileOutputStream.write(json.getBytes());
|
||||
fileOutputStream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
19
src/main/java/cl/cromer/azaraka/json/package-info.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package handles json files and structures
|
||||
*/
|
||||
package cl.cromer.azaraka.json;
|
121
src/main/java/cl/cromer/azaraka/logging/HtmlFormatter.java
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.logging;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
/**
|
||||
* This class handles formatting the log into a html table
|
||||
*/
|
||||
public class HtmlFormatter extends Formatter {
|
||||
/**
|
||||
* Create a log row in the html table
|
||||
*
|
||||
* @param logRecord The record to insert into the table
|
||||
* @return Returns the log row in html
|
||||
*/
|
||||
public String format(LogRecord logRecord) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append("\t<tr>\n");
|
||||
|
||||
// colorize any levels >= WARNING in red
|
||||
if (logRecord.getLevel().intValue() >= Level.WARNING.intValue()) {
|
||||
stringBuilder.append("\t\t<td style=\"color:red\">");
|
||||
stringBuilder.append("<b>");
|
||||
stringBuilder.append(StringUtils.encodeHtml(logRecord.getLevel().getName()));
|
||||
stringBuilder.append("</b>");
|
||||
}
|
||||
else {
|
||||
stringBuilder.append("\t\t<td>");
|
||||
stringBuilder.append(StringUtils.encodeHtml(logRecord.getLevel().getName()));
|
||||
}
|
||||
stringBuilder.append("</td>\n");
|
||||
|
||||
stringBuilder.append("\t\t<td>");
|
||||
stringBuilder.append(StringUtils.encodeHtml(calculateDate(logRecord.getMillis())));
|
||||
stringBuilder.append("</td>\n");
|
||||
|
||||
stringBuilder.append("\t\t<td>");
|
||||
stringBuilder.append(StringUtils.encodeHtml(logRecord.getSourceClassName()));
|
||||
stringBuilder.append("</td>\n");
|
||||
|
||||
stringBuilder.append("\t\t<td>");
|
||||
stringBuilder.append(StringUtils.encodeHtml(logRecord.getSourceMethodName()));
|
||||
stringBuilder.append("</td>\n");
|
||||
|
||||
stringBuilder.append("\t\t<td>");
|
||||
stringBuilder.append(StringUtils.encodeHtml(formatMessage(logRecord)));
|
||||
stringBuilder.append("</td>\n");
|
||||
|
||||
stringBuilder.append("\t</tr>\n");
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the date and time for the log row
|
||||
*
|
||||
* @param milliseconds The time the log record happened in milliseconds
|
||||
* @return Returns the formatted time
|
||||
*/
|
||||
private String calculateDate(long milliseconds) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd,yyyy HH:mm:ss");
|
||||
Date resultDate = new Date(milliseconds);
|
||||
return dateFormat.format(resultDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called to get the head of the log
|
||||
*
|
||||
* @param handler The handler
|
||||
* @return Returns the header of the log
|
||||
*/
|
||||
public String getHead(Handler handler) {
|
||||
return "<!DOCTYPE html>\n<head>\n<style>\n"
|
||||
+ "table { width: 100%; border: 1px solid black; border-collapse: collapse; }\n"
|
||||
+ "th { font:bold 10pt monospaced; border: 1px solid black; border-collapse: collapse; }\n"
|
||||
+ "td { font:normal 10pt monospaced; border: 1px solid black; border-collapse: collapse; }\n"
|
||||
+ "h1 {font:normal 11pt monospaced;}\n"
|
||||
+ "</style>\n"
|
||||
+ "<title>Log</title>\n"
|
||||
+ "</head>\n"
|
||||
+ "<body>\n"
|
||||
+ "<h1>" + (StringUtils.encodeHtml(new Date().toString())) + "</h1>\n"
|
||||
+ "<table border=\"0\" cellpadding=\"5\" cellspacing=\"3\">\n"
|
||||
+ "\t<tr align=\"left\">\n"
|
||||
+ "\t\t<th style=\"width:10%\">Loglevel</th>\n"
|
||||
+ "\t\t<th style=\"width:15%\">Time</th>\n"
|
||||
+ "\t\t<th style=\"width:10%\">Class</th>\n"
|
||||
+ "\t\t<th style=\"width:10%\">Method</th>\n"
|
||||
+ "\t\t<th style=\"width:55%\">Log Message</th>\n"
|
||||
+ "\t</tr>\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called to get the tail of the log
|
||||
*
|
||||
* @param handler The handler
|
||||
* @return Returns the tail of the log
|
||||
*/
|
||||
public String getTail(Handler handler) {
|
||||
return "</table>\n</body>\n</html>";
|
||||
}
|
||||
}
|
333
src/main/java/cl/cromer/azaraka/logging/StringUtils.java
Normal file
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.logging;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This class handles string formatting for html
|
||||
*/
|
||||
public class StringUtils {
|
||||
/**
|
||||
* A map of all the characters that need to be encoded
|
||||
*/
|
||||
private static final HashMap<Character, String> htmlEncodeChars = new HashMap<>();
|
||||
|
||||
static {
|
||||
// Special characters for HTML
|
||||
htmlEncodeChars.put('\u0026', "&");
|
||||
htmlEncodeChars.put('\u003C', "<");
|
||||
htmlEncodeChars.put('\u003E', ">");
|
||||
htmlEncodeChars.put('\u0022', """);
|
||||
|
||||
htmlEncodeChars.put('\u0152', "Œ");
|
||||
htmlEncodeChars.put('\u0153', "œ");
|
||||
htmlEncodeChars.put('\u0160', "Š");
|
||||
htmlEncodeChars.put('\u0161', "š");
|
||||
htmlEncodeChars.put('\u0178', "Ÿ");
|
||||
htmlEncodeChars.put('\u02C6', "ˆ");
|
||||
htmlEncodeChars.put('\u02DC', "˜");
|
||||
htmlEncodeChars.put('\u2002', " ");
|
||||
htmlEncodeChars.put('\u2003', " ");
|
||||
htmlEncodeChars.put('\u2009', " ");
|
||||
htmlEncodeChars.put('\u200C', "‌");
|
||||
htmlEncodeChars.put('\u200D', "‍");
|
||||
htmlEncodeChars.put('\u200E', "‎");
|
||||
htmlEncodeChars.put('\u200F', "‏");
|
||||
htmlEncodeChars.put('\u2013', "–");
|
||||
htmlEncodeChars.put('\u2014', "—");
|
||||
htmlEncodeChars.put('\u2018', "‘");
|
||||
htmlEncodeChars.put('\u2019', "’");
|
||||
htmlEncodeChars.put('\u201A', "‚");
|
||||
htmlEncodeChars.put('\u201C', "“");
|
||||
htmlEncodeChars.put('\u201D', "”");
|
||||
htmlEncodeChars.put('\u201E', "„");
|
||||
htmlEncodeChars.put('\u2020', "†");
|
||||
htmlEncodeChars.put('\u2021', "‡");
|
||||
htmlEncodeChars.put('\u2030', "‰");
|
||||
htmlEncodeChars.put('\u2039', "‹");
|
||||
htmlEncodeChars.put('\u203A', "›");
|
||||
htmlEncodeChars.put('\u20AC', "€");
|
||||
|
||||
// Character entity references for ISO 8859-1 characters
|
||||
htmlEncodeChars.put('\u00A0', " ");
|
||||
htmlEncodeChars.put('\u00A1', "¡");
|
||||
htmlEncodeChars.put('\u00A2', "¢");
|
||||
htmlEncodeChars.put('\u00A3', "£");
|
||||
htmlEncodeChars.put('\u00A4', "¤");
|
||||
htmlEncodeChars.put('\u00A5', "¥");
|
||||
htmlEncodeChars.put('\u00A6', "¦");
|
||||
htmlEncodeChars.put('\u00A7', "§");
|
||||
htmlEncodeChars.put('\u00A8', "¨");
|
||||
htmlEncodeChars.put('\u00A9', "©");
|
||||
htmlEncodeChars.put('\u00AA', "ª");
|
||||
htmlEncodeChars.put('\u00AB', "«");
|
||||
htmlEncodeChars.put('\u00AC', "¬");
|
||||
htmlEncodeChars.put('\u00AD', "­");
|
||||
htmlEncodeChars.put('\u00AE', "®");
|
||||
htmlEncodeChars.put('\u00AF', "¯");
|
||||
htmlEncodeChars.put('\u00B0', "°");
|
||||
htmlEncodeChars.put('\u00B1', "±");
|
||||
htmlEncodeChars.put('\u00B2', "²");
|
||||
htmlEncodeChars.put('\u00B3', "³");
|
||||
htmlEncodeChars.put('\u00B4', "´");
|
||||
htmlEncodeChars.put('\u00B5', "µ");
|
||||
htmlEncodeChars.put('\u00B6', "¶");
|
||||
htmlEncodeChars.put('\u00B7', "·");
|
||||
htmlEncodeChars.put('\u00B8', "¸");
|
||||
htmlEncodeChars.put('\u00B9', "¹");
|
||||
htmlEncodeChars.put('\u00BA', "º");
|
||||
htmlEncodeChars.put('\u00BB', "»");
|
||||
htmlEncodeChars.put('\u00BC', "¼");
|
||||
htmlEncodeChars.put('\u00BD', "½");
|
||||
htmlEncodeChars.put('\u00BE', "¾");
|
||||
htmlEncodeChars.put('\u00BF', "¿");
|
||||
htmlEncodeChars.put('\u00C0', "À");
|
||||
htmlEncodeChars.put('\u00C1', "Á");
|
||||
htmlEncodeChars.put('\u00C2', "Â");
|
||||
htmlEncodeChars.put('\u00C3', "Ã");
|
||||
htmlEncodeChars.put('\u00C4', "Ä");
|
||||
htmlEncodeChars.put('\u00C5', "Å");
|
||||
htmlEncodeChars.put('\u00C6', "Æ");
|
||||
htmlEncodeChars.put('\u00C7', "Ç");
|
||||
htmlEncodeChars.put('\u00C8', "È");
|
||||
htmlEncodeChars.put('\u00C9', "É");
|
||||
htmlEncodeChars.put('\u00CA', "Ê");
|
||||
htmlEncodeChars.put('\u00CB', "Ë");
|
||||
htmlEncodeChars.put('\u00CC', "Ì");
|
||||
htmlEncodeChars.put('\u00CD', "Í");
|
||||
htmlEncodeChars.put('\u00CE', "Î");
|
||||
htmlEncodeChars.put('\u00CF', "Ï");
|
||||
htmlEncodeChars.put('\u00D0', "Ð");
|
||||
htmlEncodeChars.put('\u00D1', "Ñ");
|
||||
htmlEncodeChars.put('\u00D2', "Ò");
|
||||
htmlEncodeChars.put('\u00D3', "Ó");
|
||||
htmlEncodeChars.put('\u00D4', "Ô");
|
||||
htmlEncodeChars.put('\u00D5', "Õ");
|
||||
htmlEncodeChars.put('\u00D6', "Ö");
|
||||
htmlEncodeChars.put('\u00D7', "×");
|
||||
htmlEncodeChars.put('\u00D8', "Ø");
|
||||
htmlEncodeChars.put('\u00D9', "Ù");
|
||||
htmlEncodeChars.put('\u00DA', "Ú");
|
||||
htmlEncodeChars.put('\u00DB', "Û");
|
||||
htmlEncodeChars.put('\u00DC', "Ü");
|
||||
htmlEncodeChars.put('\u00DD', "Ý");
|
||||
htmlEncodeChars.put('\u00DE', "Þ");
|
||||
htmlEncodeChars.put('\u00DF', "ß");
|
||||
htmlEncodeChars.put('\u00E0', "à");
|
||||
htmlEncodeChars.put('\u00E1', "á");
|
||||
htmlEncodeChars.put('\u00E2', "â");
|
||||
htmlEncodeChars.put('\u00E3', "ã");
|
||||
htmlEncodeChars.put('\u00E4', "ä");
|
||||
htmlEncodeChars.put('\u00E5', "å");
|
||||
htmlEncodeChars.put('\u00E6', "æ");
|
||||
htmlEncodeChars.put('\u00E7', "ç");
|
||||
htmlEncodeChars.put('\u00E8', "è");
|
||||
htmlEncodeChars.put('\u00E9', "é");
|
||||
htmlEncodeChars.put('\u00EA', "ê");
|
||||
htmlEncodeChars.put('\u00EB', "ë");
|
||||
htmlEncodeChars.put('\u00EC', "ì");
|
||||
htmlEncodeChars.put('\u00ED', "í");
|
||||
htmlEncodeChars.put('\u00EE', "î");
|
||||
htmlEncodeChars.put('\u00EF', "ï");
|
||||
htmlEncodeChars.put('\u00F0', "ð");
|
||||
htmlEncodeChars.put('\u00F1', "ñ");
|
||||
htmlEncodeChars.put('\u00F2', "ò");
|
||||
htmlEncodeChars.put('\u00F3', "ó");
|
||||
htmlEncodeChars.put('\u00F4', "ô");
|
||||
htmlEncodeChars.put('\u00F5', "õ");
|
||||
htmlEncodeChars.put('\u00F6', "ö");
|
||||
htmlEncodeChars.put('\u00F7', "÷");
|
||||
htmlEncodeChars.put('\u00F8', "ø");
|
||||
htmlEncodeChars.put('\u00F9', "ù");
|
||||
htmlEncodeChars.put('\u00FA', "ú");
|
||||
htmlEncodeChars.put('\u00FB', "û");
|
||||
htmlEncodeChars.put('\u00FC', "ü");
|
||||
htmlEncodeChars.put('\u00FD', "ý");
|
||||
htmlEncodeChars.put('\u00FE', "þ");
|
||||
htmlEncodeChars.put('\u00FF', "ÿ");
|
||||
|
||||
// Mathematical, Greek and Symbolic characters for HTML
|
||||
htmlEncodeChars.put('\u0192', "ƒ");
|
||||
htmlEncodeChars.put('\u0391', "Α");
|
||||
htmlEncodeChars.put('\u0392', "Β");
|
||||
htmlEncodeChars.put('\u0393', "Γ");
|
||||
htmlEncodeChars.put('\u0394', "Δ");
|
||||
htmlEncodeChars.put('\u0395', "Ε");
|
||||
htmlEncodeChars.put('\u0396', "Ζ");
|
||||
htmlEncodeChars.put('\u0397', "Η");
|
||||
htmlEncodeChars.put('\u0398', "Θ");
|
||||
htmlEncodeChars.put('\u0399', "Ι");
|
||||
htmlEncodeChars.put('\u039A', "Κ");
|
||||
htmlEncodeChars.put('\u039B', "Λ");
|
||||
htmlEncodeChars.put('\u039C', "Μ");
|
||||
htmlEncodeChars.put('\u039D', "Ν");
|
||||
htmlEncodeChars.put('\u039E', "Ξ");
|
||||
htmlEncodeChars.put('\u039F', "Ο");
|
||||
htmlEncodeChars.put('\u03A0', "Π");
|
||||
htmlEncodeChars.put('\u03A1', "Ρ");
|
||||
htmlEncodeChars.put('\u03A3', "Σ");
|
||||
htmlEncodeChars.put('\u03A4', "Τ");
|
||||
htmlEncodeChars.put('\u03A5', "Υ");
|
||||
htmlEncodeChars.put('\u03A6', "Φ");
|
||||
htmlEncodeChars.put('\u03A7', "Χ");
|
||||
htmlEncodeChars.put('\u03A8', "Ψ");
|
||||
htmlEncodeChars.put('\u03A9', "Ω");
|
||||
htmlEncodeChars.put('\u03B1', "α");
|
||||
htmlEncodeChars.put('\u03B2', "β");
|
||||
htmlEncodeChars.put('\u03B3', "γ");
|
||||
htmlEncodeChars.put('\u03B4', "δ");
|
||||
htmlEncodeChars.put('\u03B5', "ε");
|
||||
htmlEncodeChars.put('\u03B6', "ζ");
|
||||
htmlEncodeChars.put('\u03B7', "η");
|
||||
htmlEncodeChars.put('\u03B8', "θ");
|
||||
htmlEncodeChars.put('\u03B9', "ι");
|
||||
htmlEncodeChars.put('\u03BA', "κ");
|
||||
htmlEncodeChars.put('\u03BB', "λ");
|
||||
htmlEncodeChars.put('\u03BC', "μ");
|
||||
htmlEncodeChars.put('\u03BD', "ν");
|
||||
htmlEncodeChars.put('\u03BE', "ξ");
|
||||
htmlEncodeChars.put('\u03BF', "ο");
|
||||
htmlEncodeChars.put('\u03C0', "π");
|
||||
htmlEncodeChars.put('\u03C1', "ρ");
|
||||
htmlEncodeChars.put('\u03C2', "ς");
|
||||
htmlEncodeChars.put('\u03C3', "σ");
|
||||
htmlEncodeChars.put('\u03C4', "τ");
|
||||
htmlEncodeChars.put('\u03C5', "υ");
|
||||
htmlEncodeChars.put('\u03C6', "φ");
|
||||
htmlEncodeChars.put('\u03C7', "χ");
|
||||
htmlEncodeChars.put('\u03C8', "ψ");
|
||||
htmlEncodeChars.put('\u03C9', "ω");
|
||||
htmlEncodeChars.put('\u03D1', "ϑ");
|
||||
htmlEncodeChars.put('\u03D2', "ϒ");
|
||||
htmlEncodeChars.put('\u03D6', "ϖ");
|
||||
htmlEncodeChars.put('\u2022', "•");
|
||||
htmlEncodeChars.put('\u2026', "…");
|
||||
htmlEncodeChars.put('\u2032', "′");
|
||||
htmlEncodeChars.put('\u2033', "″");
|
||||
htmlEncodeChars.put('\u203E', "‾");
|
||||
htmlEncodeChars.put('\u2044', "⁄");
|
||||
htmlEncodeChars.put('\u2118', "℘");
|
||||
htmlEncodeChars.put('\u2111', "ℑ");
|
||||
htmlEncodeChars.put('\u211C', "ℜ");
|
||||
htmlEncodeChars.put('\u2122', "™");
|
||||
htmlEncodeChars.put('\u2135', "ℵ");
|
||||
htmlEncodeChars.put('\u2190', "←");
|
||||
htmlEncodeChars.put('\u2191', "↑");
|
||||
htmlEncodeChars.put('\u2192', "→");
|
||||
htmlEncodeChars.put('\u2193', "↓");
|
||||
htmlEncodeChars.put('\u2194', "↔");
|
||||
htmlEncodeChars.put('\u21B5', "↵");
|
||||
htmlEncodeChars.put('\u21D0', "⇐");
|
||||
htmlEncodeChars.put('\u21D1', "⇑");
|
||||
htmlEncodeChars.put('\u21D2', "⇒");
|
||||
htmlEncodeChars.put('\u21D3', "⇓");
|
||||
htmlEncodeChars.put('\u21D4', "⇔");
|
||||
htmlEncodeChars.put('\u2200', "∀");
|
||||
htmlEncodeChars.put('\u2202', "∂");
|
||||
htmlEncodeChars.put('\u2203', "∃");
|
||||
htmlEncodeChars.put('\u2205', "∅");
|
||||
htmlEncodeChars.put('\u2207', "∇");
|
||||
htmlEncodeChars.put('\u2208', "∈");
|
||||
htmlEncodeChars.put('\u2209', "∉");
|
||||
htmlEncodeChars.put('\u220B', "∋");
|
||||
htmlEncodeChars.put('\u220F', "∏");
|
||||
htmlEncodeChars.put('\u2211', "∑");
|
||||
htmlEncodeChars.put('\u2212', "−");
|
||||
htmlEncodeChars.put('\u2217', "∗");
|
||||
htmlEncodeChars.put('\u221A', "√");
|
||||
htmlEncodeChars.put('\u221D', "∝");
|
||||
htmlEncodeChars.put('\u221E', "∞");
|
||||
htmlEncodeChars.put('\u2220', "∠");
|
||||
htmlEncodeChars.put('\u2227', "∧");
|
||||
htmlEncodeChars.put('\u2228', "∨");
|
||||
htmlEncodeChars.put('\u2229', "∩");
|
||||
htmlEncodeChars.put('\u222A', "∪");
|
||||
htmlEncodeChars.put('\u222B', "∫");
|
||||
htmlEncodeChars.put('\u2234', "∴");
|
||||
htmlEncodeChars.put('\u223C', "∼");
|
||||
htmlEncodeChars.put('\u2245', "≅");
|
||||
htmlEncodeChars.put('\u2248', "≈");
|
||||
htmlEncodeChars.put('\u2260', "≠");
|
||||
htmlEncodeChars.put('\u2261', "≡");
|
||||
htmlEncodeChars.put('\u2264', "≤");
|
||||
htmlEncodeChars.put('\u2265', "≥");
|
||||
htmlEncodeChars.put('\u2282', "⊂");
|
||||
htmlEncodeChars.put('\u2283', "⊃");
|
||||
htmlEncodeChars.put('\u2284', "⊄");
|
||||
htmlEncodeChars.put('\u2286', "⊆");
|
||||
htmlEncodeChars.put('\u2287', "⊇");
|
||||
htmlEncodeChars.put('\u2295', "⊕");
|
||||
htmlEncodeChars.put('\u2297', "⊗");
|
||||
htmlEncodeChars.put('\u22A5', "⊥");
|
||||
htmlEncodeChars.put('\u22C5', "⋅");
|
||||
htmlEncodeChars.put('\u2308', "⌈");
|
||||
htmlEncodeChars.put('\u2309', "⌉");
|
||||
htmlEncodeChars.put('\u230A', "⌊");
|
||||
htmlEncodeChars.put('\u230B', "⌋");
|
||||
htmlEncodeChars.put('\u2329', "⟨");
|
||||
htmlEncodeChars.put('\u232A', "⟩");
|
||||
htmlEncodeChars.put('\u25CA', "◊");
|
||||
htmlEncodeChars.put('\u2660', "♠");
|
||||
htmlEncodeChars.put('\u2663', "♣");
|
||||
htmlEncodeChars.put('\u2665', "♥");
|
||||
htmlEncodeChars.put('\u2666', "♦");
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the string for html characters
|
||||
*
|
||||
* @param source The string to encode
|
||||
* @return Returns a new string that is encoded with html characters
|
||||
*/
|
||||
public static String encodeHtml(String source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringBuffer encoded_string = null;
|
||||
char[] string_to_encode_array = source.toCharArray();
|
||||
int last_match = -1;
|
||||
int difference;
|
||||
|
||||
for (int i = 0; i < string_to_encode_array.length; i++) {
|
||||
char char_to_encode = string_to_encode_array[i];
|
||||
|
||||
if (StringUtils.htmlEncodeChars.containsKey(char_to_encode)) {
|
||||
if (encoded_string == null) {
|
||||
encoded_string = new StringBuffer(source.length());
|
||||
}
|
||||
difference = i - (last_match + 1);
|
||||
if (difference > 0) {
|
||||
encoded_string.append(string_to_encode_array, last_match + 1, difference);
|
||||
}
|
||||
encoded_string.append(StringUtils.htmlEncodeChars.get(char_to_encode));
|
||||
last_match = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (encoded_string == null) {
|
||||
return source;
|
||||
}
|
||||
else {
|
||||
difference = string_to_encode_array.length - (last_match + 1);
|
||||
if (difference > 0) {
|
||||
encoded_string.append(string_to_encode_array, last_match + 1, difference);
|
||||
}
|
||||
return encoded_string.toString();
|
||||
}
|
||||
}
|
||||
}
|
19
src/main/java/cl/cromer/azaraka/logging/package-info.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package handles logging
|
||||
*/
|
||||
package cl.cromer.azaraka.logging;
|
199
src/main/java/cl/cromer/azaraka/object/Chest.java
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.object;
|
||||
|
||||
import cl.cromer.azaraka.Celda;
|
||||
import cl.cromer.azaraka.Constantes;
|
||||
import cl.cromer.azaraka.Escenario;
|
||||
import cl.cromer.azaraka.sound.Sound;
|
||||
import cl.cromer.azaraka.sound.SoundException;
|
||||
import cl.cromer.azaraka.sprite.Animation;
|
||||
import cl.cromer.azaraka.sprite.AnimationException;
|
||||
import cl.cromer.azaraka.sprite.Sheet;
|
||||
import cl.cromer.azaraka.sprite.SheetException;
|
||||
|
||||
/**
|
||||
* This class handles the chests
|
||||
*/
|
||||
public class Chest extends Object implements Constantes {
|
||||
/**
|
||||
* The current state of the chest
|
||||
*/
|
||||
private State state = State.CLOSED;
|
||||
/**
|
||||
* The open chest sound
|
||||
*/
|
||||
private Sound sound;
|
||||
|
||||
/**
|
||||
* Initialize the chest
|
||||
*
|
||||
* @param escenario The scene the chest is in
|
||||
* @param celda The cell that contains the chest
|
||||
*/
|
||||
public Chest(Escenario escenario, Celda celda) {
|
||||
super(escenario, celda);
|
||||
setLogger(getLogger(this.getClass(), LogLevel.CHEST));
|
||||
|
||||
loadChestAnimation();
|
||||
loadChestOpenSound();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the chest open sound
|
||||
*/
|
||||
private void loadChestOpenSound() {
|
||||
try {
|
||||
sound = new Sound("/snd/OpenChest.wav");
|
||||
}
|
||||
catch (SoundException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the chest animation
|
||||
*/
|
||||
private void loadChestAnimation() {
|
||||
Sheet chestSheet = new Sheet("/img/chest/chests.png", 54, 63);
|
||||
try {
|
||||
Animation animation = new Animation();
|
||||
animation.addImage(Animation.Direction.NONE, chestSheet.getTexture(54));
|
||||
animation.addImage(Animation.Direction.NONE, chestSheet.getTexture(66));
|
||||
animation.addImage(Animation.Direction.NONE, chestSheet.getTexture(78));
|
||||
animation.addImage(Animation.Direction.NONE, chestSheet.getTexture(80));
|
||||
animation.setYOffset(0);
|
||||
setAnimation(animation);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the state of the chest
|
||||
*
|
||||
* @return Returns the current state
|
||||
*/
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of the chest
|
||||
*
|
||||
* @param state The new state of the chest
|
||||
*/
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
if (state == State.OPENING) {
|
||||
getLogger().info("Chest is opening");
|
||||
playChestOpenSound();
|
||||
}
|
||||
else if (state == State.OPENED) {
|
||||
getLogger().info("Chest is opened");
|
||||
}
|
||||
else if (state == State.CLOSED) {
|
||||
getLogger().info("Chest is closed");
|
||||
try {
|
||||
getAnimation().setCurrentFrame(0);
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
getEscenario().getCanvas().repaint();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Play the chest opening sound
|
||||
*/
|
||||
private void playChestOpenSound() {
|
||||
try {
|
||||
sound.setVolume(getEscenario().getCanvas().getVolume());
|
||||
sound.play();
|
||||
}
|
||||
catch (SoundException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate the chest opening
|
||||
*/
|
||||
private void animate() {
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
if (getAnimation().getCurrentFrame() == getAnimation().getFrameCount() - 1) {
|
||||
setState(State.OPENED);
|
||||
}
|
||||
}
|
||||
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(200);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
getLogger().info(e.getMessage());
|
||||
}
|
||||
synchronized (this) {
|
||||
if (state == State.OPENING) {
|
||||
animate();
|
||||
getEscenario().getCanvas().repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check what position the chest is located at
|
||||
*
|
||||
* @param x The x position to compare
|
||||
* @param y The y position to compare
|
||||
* @return Returns true if it is the same position or false otherwise
|
||||
*/
|
||||
public boolean checkPosition(int x, int y) {
|
||||
return (getX() == x && getY() == y);
|
||||
}
|
||||
|
||||
/**
|
||||
* The possible states of the chest
|
||||
*/
|
||||
public enum State {
|
||||
/**
|
||||
* The chest is closed
|
||||
*/
|
||||
CLOSED,
|
||||
/**
|
||||
* The chest is opening
|
||||
*/
|
||||
OPENING,
|
||||
/**
|
||||
* The chest is opened
|
||||
*/
|
||||
OPENED
|
||||
}
|
||||
}
|
283
src/main/java/cl/cromer/azaraka/object/Enemy.java
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.object;
|
||||
|
||||
import cl.cromer.azaraka.Celda;
|
||||
import cl.cromer.azaraka.Constantes;
|
||||
import cl.cromer.azaraka.Escenario;
|
||||
import cl.cromer.azaraka.sound.Sound;
|
||||
import cl.cromer.azaraka.sound.SoundException;
|
||||
import cl.cromer.azaraka.sprite.Animation;
|
||||
import cl.cromer.azaraka.sprite.AnimationException;
|
||||
import cl.cromer.azaraka.sprite.SheetException;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
/**
|
||||
* This class handles the enemy object
|
||||
*/
|
||||
public class Enemy extends Object implements Constantes {
|
||||
/**
|
||||
* The lock helps prevent race conditions when checking positioning
|
||||
*/
|
||||
private final Lock lock;
|
||||
/**
|
||||
* The current direction the enemy is facing
|
||||
*/
|
||||
private Direction direction = Direction.LEFT;
|
||||
/**
|
||||
* The speed of the enemy
|
||||
*/
|
||||
private int speed = 500;
|
||||
/**
|
||||
* The enemy attack sound
|
||||
*/
|
||||
private Sound sound;
|
||||
|
||||
/**
|
||||
* Initialize the enemy
|
||||
*
|
||||
* @param escenario The scene the enemy is in
|
||||
* @param celda The cell this enemy is in
|
||||
* @param lock The lock used to prevent the threads from conflicting
|
||||
*/
|
||||
public Enemy(Escenario escenario, Celda celda, Lock lock) {
|
||||
super(escenario, celda);
|
||||
setLogger(getLogger(this.getClass(), LogLevel.ENEMY));
|
||||
this.lock = lock;
|
||||
loadEnemyAnimation();
|
||||
loadAttackSound();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the enemy animation
|
||||
*/
|
||||
private void loadEnemyAnimation() {
|
||||
loadCharacter("/img/enemy/chara4.png", 57);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the attack sound
|
||||
*/
|
||||
private void loadAttackSound() {
|
||||
try {
|
||||
sound = new Sound("/snd/EnemyAttack.wav");
|
||||
}
|
||||
catch (SoundException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Play the attack sound
|
||||
*/
|
||||
private void playAttackSound() {
|
||||
try {
|
||||
sound.setVolume(getEscenario().getCanvas().getVolume());
|
||||
sound.play();
|
||||
}
|
||||
catch (SoundException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the direction of the enemy
|
||||
*
|
||||
* @param direction The direction the enemy is facing
|
||||
*/
|
||||
public void setDirection(Direction direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method handles the enemy's movements
|
||||
*/
|
||||
private void move() {
|
||||
int x = getX();
|
||||
int y = getY();
|
||||
if (direction == Direction.LEFT) {
|
||||
if (x > 0 && getEscenario().getCeldas()[x - 1][y].getObject() == null) {
|
||||
getCelda().setObject(null);
|
||||
setCelda(getEscenario().getCeldas()[x - 1][y]);
|
||||
getCelda().setObject(this);
|
||||
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
setX(getX() - 1);
|
||||
getLogger().info("Move left to x: " + x + " y: " + y);
|
||||
}
|
||||
else if (x > 0 && getEscenario().getCeldas()[x - 1][y].getObject() instanceof Player) {
|
||||
attackPlayer(x - 1, y);
|
||||
}
|
||||
else {
|
||||
getLogger().info("Change to right direction");
|
||||
getAnimation().setCurrentDirection(Animation.Direction.RIGHT);
|
||||
direction = Direction.RIGHT;
|
||||
}
|
||||
}
|
||||
else if (direction == Direction.RIGHT) {
|
||||
if (x < (HORIZONTAL_CELLS - 1) && getEscenario().getCeldas()[x + 1][y].getObject() == null) {
|
||||
getCelda().setObject(null);
|
||||
setCelda(getEscenario().getCeldas()[x + 1][y]);
|
||||
getCelda().setObject(this);
|
||||
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
setX(getX() + 1);
|
||||
getLogger().info("Move right to x: " + x + " y: " + y);
|
||||
}
|
||||
else if (x < (HORIZONTAL_CELLS - 1) && getEscenario().getCeldas()[x + 1][y].getObject() instanceof Player) {
|
||||
attackPlayer(x + 1, y);
|
||||
}
|
||||
else {
|
||||
getLogger().info("Change to left direction");
|
||||
getAnimation().setCurrentDirection(Animation.Direction.LEFT);
|
||||
direction = Direction.LEFT;
|
||||
}
|
||||
}
|
||||
else if (direction == Direction.DOWN) {
|
||||
if (y < (VERTICAL_CELLS) - 1 && getEscenario().getCeldas()[x][y + 1].getObject() == null) {
|
||||
getCelda().setObject(null);
|
||||
setCelda(getEscenario().getCeldas()[x][y + 1]);
|
||||
getCelda().setObject(this);
|
||||
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
setY(getY() + 1);
|
||||
getLogger().info("Move down to x: " + x + " y: " + y);
|
||||
}
|
||||
else if (y < (VERTICAL_CELLS - 1) && getEscenario().getCeldas()[x][y + 1].getObject() instanceof Player) {
|
||||
attackPlayer(x, y + 1);
|
||||
}
|
||||
else {
|
||||
getLogger().info("Change to up direction");
|
||||
getAnimation().setCurrentDirection(Animation.Direction.UP);
|
||||
direction = Direction.UP;
|
||||
}
|
||||
}
|
||||
else if (direction == Direction.UP) {
|
||||
if (y > 0 && getEscenario().getCeldas()[x][y - 1].getObject() == null) {
|
||||
getCelda().setObject(null);
|
||||
setCelda(getEscenario().getCeldas()[x][y - 1]);
|
||||
getCelda().setObject(this);
|
||||
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
setY(getY() - 1);
|
||||
getLogger().info("Move up to x: " + x + " y: " + y);
|
||||
}
|
||||
else if (y > 0 && getEscenario().getCeldas()[x][y - 1].getObject() instanceof Player) {
|
||||
attackPlayer(x, y - 1);
|
||||
}
|
||||
else {
|
||||
getLogger().info("Change to down direction");
|
||||
getAnimation().setCurrentDirection(Animation.Direction.DOWN);
|
||||
direction = Direction.DOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the enemy has found the player attack him
|
||||
*
|
||||
* @param x The x position of the player
|
||||
* @param y The y position of the player
|
||||
*/
|
||||
private void attackPlayer(int x, int y) {
|
||||
if (getEscenario().getCanvas().getPlayer().getHealth() > 0) {
|
||||
getLogger().info("Attacked player at x: " + x + " y: " + y);
|
||||
|
||||
playAttackSound();
|
||||
|
||||
getEscenario().getCanvas().getPlayer().loseHealth(2);
|
||||
try {
|
||||
getEscenario().getCeldas()[x][y].addTexture(getEscenario().getTextureSheet().getTexture(12), 12);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is run constantly by the runnable
|
||||
*/
|
||||
public void run() {
|
||||
super.run();
|
||||
while (getActive()) {
|
||||
try {
|
||||
Thread.sleep(speed);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
getLogger().info(e.getMessage());
|
||||
}
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
move();
|
||||
getEscenario().getCanvas().repaint();
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the speed of the enemy
|
||||
*
|
||||
* @param speed The new speed
|
||||
*/
|
||||
public void setSpeed(int speed) {
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
/**
|
||||
* The possible directions the enemy can face
|
||||
*/
|
||||
public enum Direction {
|
||||
/**
|
||||
* The enemy is facing up
|
||||
*/
|
||||
UP,
|
||||
/**
|
||||
* The enemy is facing down
|
||||
*/
|
||||
DOWN,
|
||||
/**
|
||||
* The enemy is facing left
|
||||
*/
|
||||
LEFT,
|
||||
/**
|
||||
* The enemy is facing right
|
||||
*/
|
||||
RIGHT
|
||||
}
|
||||
}
|
53
src/main/java/cl/cromer/azaraka/object/Gem.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.object;
|
||||
|
||||
import cl.cromer.azaraka.Celda;
|
||||
import cl.cromer.azaraka.Escenario;
|
||||
|
||||
/**
|
||||
* This class contains the gem
|
||||
*/
|
||||
public class Gem extends Object {
|
||||
/**
|
||||
* The current state of the gem
|
||||
*/
|
||||
private State state = State.TAINTED;
|
||||
|
||||
/**
|
||||
* Initialize the gem object
|
||||
*
|
||||
* @param escenario The scene the gem is in
|
||||
* @param celda The cell the gem is in
|
||||
*/
|
||||
public Gem(Escenario escenario, Celda celda) {
|
||||
super(escenario, celda);
|
||||
}
|
||||
|
||||
/**
|
||||
* The possible states of the gem
|
||||
*/
|
||||
private enum State {
|
||||
/**
|
||||
* The gem is tainted
|
||||
*/
|
||||
TAINTED,
|
||||
/**
|
||||
* The gem has been purified
|
||||
*/
|
||||
PURIFIED
|
||||
}
|
||||
}
|
218
src/main/java/cl/cromer/azaraka/object/Key.java
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.object;
|
||||
|
||||
import cl.cromer.azaraka.Celda;
|
||||
import cl.cromer.azaraka.Constantes;
|
||||
import cl.cromer.azaraka.Escenario;
|
||||
import cl.cromer.azaraka.sound.Sound;
|
||||
import cl.cromer.azaraka.sound.SoundException;
|
||||
import cl.cromer.azaraka.sprite.Animation;
|
||||
import cl.cromer.azaraka.sprite.AnimationException;
|
||||
import cl.cromer.azaraka.sprite.Sheet;
|
||||
import cl.cromer.azaraka.sprite.SheetException;
|
||||
|
||||
/**
|
||||
* This class contains the key
|
||||
*/
|
||||
public class Key extends Object implements Constantes {
|
||||
/**
|
||||
* The current state of the key
|
||||
*/
|
||||
private State state = State.UNUSED;
|
||||
/**
|
||||
* The sound when the player gets a key
|
||||
*/
|
||||
private Sound sound;
|
||||
|
||||
/**
|
||||
* Initialize the key
|
||||
*
|
||||
* @param escenario The scene the key is in
|
||||
* @param celda The cell the key is in
|
||||
*/
|
||||
public Key(Escenario escenario, Celda celda) {
|
||||
super(escenario, celda);
|
||||
setLogger(getLogger(this.getClass(), LogLevel.KEY));
|
||||
loadKeyAnimation();
|
||||
loadGetKeySound();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the key sound
|
||||
*/
|
||||
private void loadGetKeySound() {
|
||||
try {
|
||||
sound = new Sound("/snd/GetKey.wav");
|
||||
}
|
||||
catch (SoundException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the key animation
|
||||
*/
|
||||
private void loadKeyAnimation() {
|
||||
Sheet keySheet = new Sheet("/img/key/key.png", 24, 24);
|
||||
Animation animation = new Animation();
|
||||
try {
|
||||
animation.addImage(Animation.Direction.NONE, keySheet.getTexture(0));
|
||||
animation.addImage(Animation.Direction.NONE, keySheet.getTexture(1));
|
||||
animation.addImage(Animation.Direction.NONE, keySheet.getTexture(2));
|
||||
animation.addImage(Animation.Direction.NONE, keySheet.getTexture(3));
|
||||
animation.addImage(Animation.Direction.NONE, keySheet.getTexture(4));
|
||||
animation.addImage(Animation.Direction.NONE, keySheet.getTexture(5));
|
||||
animation.addImage(Animation.Direction.NONE, keySheet.getTexture(6));
|
||||
animation.addImage(Animation.Direction.NONE, keySheet.getTexture(7));
|
||||
setAnimation(animation);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of the key animation
|
||||
*
|
||||
* @return Returns the key animation width
|
||||
*/
|
||||
public int getAnimationWidth() {
|
||||
try {
|
||||
return getAnimation().getFrame().getWidth();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Play the get key sound
|
||||
*/
|
||||
public void playGetKeySound() {
|
||||
try {
|
||||
sound.setVolume(getEscenario().getCanvas().getVolume());
|
||||
sound.play();
|
||||
}
|
||||
catch (SoundException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key
|
||||
*/
|
||||
public void getKey() {
|
||||
// Remove the key from the cell
|
||||
getCelda().setObject(null);
|
||||
setState(State.HELD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current state of the key
|
||||
*
|
||||
* @return Returns the key's state
|
||||
*/
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the new state of the key
|
||||
*
|
||||
* @param state The new state of the key
|
||||
*/
|
||||
public void setState(State state) {
|
||||
if (this.state == State.UNUSED && state == State.HELD) {
|
||||
setUseOffset(false);
|
||||
}
|
||||
else if (this.state == State.HELD && state == State.UNUSED) {
|
||||
setUseOffset(true);
|
||||
}
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method animates the portal
|
||||
*/
|
||||
private void animate() {
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is run when the thread starts
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
while (getActive()) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
getLogger().info(e.getMessage());
|
||||
}
|
||||
synchronized (this) {
|
||||
animate();
|
||||
getEscenario().getCanvas().repaint();
|
||||
}
|
||||
}
|
||||
// The thread was killed, set the animation to frame 4
|
||||
try {
|
||||
if (getAnimation().getCurrentFrame() != 4) {
|
||||
getAnimation().setCurrentFrame(4);
|
||||
}
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check what position the key is located at
|
||||
*
|
||||
* @param x The x position to compare
|
||||
* @param y The y position to compare
|
||||
* @return Returns true if it is the same position or false otherwise
|
||||
*/
|
||||
public boolean checkPosition(int x, int y) {
|
||||
return (getX() == x && getY() == y);
|
||||
}
|
||||
|
||||
/**
|
||||
* The state of the key
|
||||
*/
|
||||
public enum State {
|
||||
/**
|
||||
* The key has been used
|
||||
*/
|
||||
USED,
|
||||
/**
|
||||
* The key has not been used
|
||||
*/
|
||||
UNUSED,
|
||||
/**
|
||||
* The key is held by the player
|
||||
*/
|
||||
HELD
|
||||
}
|
||||
}
|
267
src/main/java/cl/cromer/azaraka/object/Object.java
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
import cl.cromer.azaraka.sprite.Sheet;
|
||||
import cl.cromer.azaraka.sprite.SheetException;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* All game objects extend this class
|
||||
*/
|
||||
public class Object implements Runnable {
|
||||
/**
|
||||
* The scene the object is in
|
||||
*/
|
||||
private final Escenario escenario;
|
||||
/**
|
||||
* The current x position of the object
|
||||
*/
|
||||
private int x;
|
||||
/**
|
||||
* The current y position of the object
|
||||
*/
|
||||
private int y;
|
||||
/**
|
||||
* The cell the object is in
|
||||
*/
|
||||
private Celda celda;
|
||||
/**
|
||||
* The animation of the object
|
||||
*/
|
||||
private Animation animation;
|
||||
/**
|
||||
* Use an offset when drawing the animation
|
||||
*/
|
||||
private boolean useOffset = true;
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private Logger logger;
|
||||
/**
|
||||
* Whether or not the run loop of the object is active
|
||||
*/
|
||||
private boolean active;
|
||||
|
||||
/**
|
||||
* Initialize the object
|
||||
*
|
||||
* @param escenario The scene the object is in
|
||||
* @param celda The cell the object is in
|
||||
*/
|
||||
protected Object(Escenario escenario, Celda celda) {
|
||||
this.escenario = escenario;
|
||||
this.celda = celda;
|
||||
this.x = celda.getX();
|
||||
this.y = celda.getY();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the x position of the object
|
||||
*
|
||||
* @return Returns the x coordinate
|
||||
*/
|
||||
protected int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the x position of the object
|
||||
*
|
||||
* @param x The new x coordinate
|
||||
*/
|
||||
protected void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y position of the object
|
||||
*
|
||||
* @return Returns the y coordinate
|
||||
*/
|
||||
protected int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the y position of the object
|
||||
*
|
||||
* @param y The new y coordinate
|
||||
*/
|
||||
protected void setY(int y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scene the object is in
|
||||
*
|
||||
* @return Returns the scene
|
||||
*/
|
||||
protected Escenario getEscenario() {
|
||||
return escenario;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cell the object is in
|
||||
*
|
||||
* @return Returns the cell
|
||||
*/
|
||||
public Celda getCelda() {
|
||||
return celda;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cell the object is in
|
||||
*
|
||||
* @param celda The cell
|
||||
*/
|
||||
protected void setCelda(Celda celda) {
|
||||
this.celda = celda;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current animation
|
||||
*
|
||||
* @return Returns an animation
|
||||
*/
|
||||
protected Animation getAnimation() {
|
||||
return animation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new animation
|
||||
*
|
||||
* @param animation The new animation
|
||||
*/
|
||||
protected void setAnimation(Animation animation) {
|
||||
this.animation = animation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the use offset for animation
|
||||
*
|
||||
* @param useOffset If true the animation will use an offset to help center it
|
||||
*/
|
||||
protected void setUseOffset(boolean useOffset) {
|
||||
this.useOffset = useOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the character animation
|
||||
*
|
||||
* @param path The path to the image
|
||||
* @param character The character number
|
||||
*/
|
||||
protected void loadCharacter(String path, int character) {
|
||||
Sheet characterSheet = new Sheet(path, 54, 39);
|
||||
try {
|
||||
Animation animation = new Animation();
|
||||
animation.setCurrentDirection(Animation.Direction.DOWN);
|
||||
|
||||
animation.addImage(Animation.Direction.DOWN, characterSheet.getTexture(character));
|
||||
animation.addImage(Animation.Direction.DOWN, characterSheet.getTexture(character + 2));
|
||||
character = character + 12;
|
||||
animation.addImage(Animation.Direction.LEFT, characterSheet.getTexture(character));
|
||||
animation.addImage(Animation.Direction.LEFT, characterSheet.getTexture(character + 2));
|
||||
character = character + 12;
|
||||
animation.addImage(Animation.Direction.RIGHT, characterSheet.getTexture(character));
|
||||
animation.addImage(Animation.Direction.RIGHT, characterSheet.getTexture(character + 2));
|
||||
character = character + 12;
|
||||
animation.addImage(Animation.Direction.UP, characterSheet.getTexture(character));
|
||||
animation.addImage(Animation.Direction.UP, characterSheet.getTexture(character + 2));
|
||||
|
||||
animation.setYOffset(0);
|
||||
|
||||
setAnimation(animation);
|
||||
}
|
||||
catch (SheetException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the animation on the canvas
|
||||
*
|
||||
* @param graphics The graphics object to draw to
|
||||
* @param x The x coordinate to draw to
|
||||
* @param y The y coordinate to draw to
|
||||
*/
|
||||
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);
|
||||
}
|
||||
else {
|
||||
graphics.drawImage(animation.getFrame(), x, y, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logger
|
||||
*
|
||||
* @return Returns a logger
|
||||
*/
|
||||
protected Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the logger
|
||||
*
|
||||
* @param logger The logger to set
|
||||
*/
|
||||
protected void setLogger(Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the active state of the GameObject
|
||||
*
|
||||
* @return Returns true if the object is active or false otherwise
|
||||
*/
|
||||
protected boolean getActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the active state for the GameObject loop
|
||||
*
|
||||
* @param active Set to true to have the run method loop run indefinitely or false to stop the loop
|
||||
*/
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
/**
|
||||
* The run method
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
setActive(true);
|
||||
}
|
||||
}
|
34
src/main/java/cl/cromer/azaraka/object/Obstacle.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.object;
|
||||
|
||||
import cl.cromer.azaraka.Celda;
|
||||
import cl.cromer.azaraka.Escenario;
|
||||
|
||||
/**
|
||||
* This class handles the obstacles
|
||||
*/
|
||||
public class Obstacle extends Object {
|
||||
/**
|
||||
* Initialize the obstacle
|
||||
*
|
||||
* @param escenario The scene the object is in
|
||||
* @param celda The cell the object is in
|
||||
*/
|
||||
public Obstacle(Escenario escenario, Celda celda) {
|
||||
super(escenario, celda);
|
||||
}
|
||||
}
|
489
src/main/java/cl/cromer/azaraka/object/Player.java
Normal file
@@ -0,0 +1,489 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This class contains the player
|
||||
*/
|
||||
public class Player extends Object implements Constantes {
|
||||
/**
|
||||
* The maximum health of the player
|
||||
*/
|
||||
public final static int MAX_HEALTH = 8;
|
||||
/**
|
||||
* Objects that the player is carrying
|
||||
*/
|
||||
private final ArrayList<Object> carrying = new ArrayList<>();
|
||||
/**
|
||||
* The current health of the player
|
||||
*/
|
||||
private int health = MAX_HEALTH;
|
||||
|
||||
/**
|
||||
* Initialize the player
|
||||
*
|
||||
* @param escenario The scene the player is in
|
||||
* @param celda The cell the player is in
|
||||
*/
|
||||
public Player(Escenario escenario, Celda celda) {
|
||||
super(escenario, celda);
|
||||
setLogger(getLogger(this.getClass(), LogLevel.PLAYER));
|
||||
loadPlayerAnimation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the player animation
|
||||
*/
|
||||
private void loadPlayerAnimation() {
|
||||
loadCharacter("/img/player/chara2.png", 6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle keys being pressed in the game
|
||||
*
|
||||
* @param event The event from the keyboard
|
||||
*/
|
||||
public void keyPressed(KeyEvent event) {
|
||||
if (!getEscenario().isDoorClosed()) {
|
||||
getEscenario().setDoorClosed(true);
|
||||
}
|
||||
switch (event.getKeyCode()) {
|
||||
case KeyEvent.VK_UP:
|
||||
moveUp();
|
||||
break;
|
||||
case KeyEvent.VK_DOWN:
|
||||
moveDown();
|
||||
break;
|
||||
case KeyEvent.VK_LEFT:
|
||||
moveLeft();
|
||||
break;
|
||||
case KeyEvent.VK_RIGHT:
|
||||
moveRight();
|
||||
break;
|
||||
case KeyEvent.VK_SPACE:
|
||||
interact();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the player up
|
||||
*/
|
||||
private void moveUp() {
|
||||
int x = getX();
|
||||
int y = getY();
|
||||
getLogger().info("Up key pressed");
|
||||
if (y > 0) {
|
||||
Object type = getEscenario().getCeldas()[x][y - 1].getObject();
|
||||
if (type == null || type instanceof Key) {
|
||||
if (type != null) {
|
||||
for (Key key : getEscenario().getCanvas().getKeys()) {
|
||||
if (key.checkPosition(x, y - 1)) {
|
||||
// Get the key
|
||||
getKey(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCelda().setObject(null);
|
||||
setCelda(getEscenario().getCeldas()[x][y - 1]);
|
||||
getCelda().setObject(this);
|
||||
|
||||
if (changeDirection(Animation.Direction.UP)) {
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (changeDirection(Animation.Direction.UP)) {
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the player down
|
||||
*/
|
||||
private void moveDown() {
|
||||
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) {
|
||||
for (Key key : getEscenario().getCanvas().getKeys()) {
|
||||
if (key.checkPosition(x, y + 1)) {
|
||||
// Get the key
|
||||
getKey(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCelda().setObject(null);
|
||||
setCelda(getEscenario().getCeldas()[x][y + 1]);
|
||||
getCelda().setObject(this);
|
||||
|
||||
if (changeDirection(Animation.Direction.DOWN)) {
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (changeDirection(Animation.Direction.DOWN)) {
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the player to the left
|
||||
*/
|
||||
private void moveLeft() {
|
||||
int x = getX();
|
||||
int y = getY();
|
||||
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) {
|
||||
for (Key key : getEscenario().getCanvas().getKeys()) {
|
||||
if (key.checkPosition(x - 1, y)) {
|
||||
// Get the key
|
||||
getKey(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCelda().setObject(null);
|
||||
setCelda(getEscenario().getCeldas()[x - 1][y]);
|
||||
getCelda().setObject(this);
|
||||
|
||||
if (changeDirection(Animation.Direction.LEFT)) {
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (changeDirection(Animation.Direction.LEFT)) {
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the player to the right
|
||||
*/
|
||||
private void moveRight() {
|
||||
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) {
|
||||
for (Key key : getEscenario().getCanvas().getKeys()) {
|
||||
if (key.checkPosition(x + 1, y)) {
|
||||
// Get the key
|
||||
getKey(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCelda().setObject(null);
|
||||
setCelda(getEscenario().getCeldas()[x + 1][y]);
|
||||
getCelda().setObject(this);
|
||||
|
||||
if (changeDirection(Animation.Direction.RIGHT)) {
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (changeDirection(Animation.Direction.RIGHT)) {
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the direction of the player sprite
|
||||
*
|
||||
* @param direction The new direction
|
||||
* @return Returns true if a direction change is not necessary
|
||||
*/
|
||||
private boolean changeDirection(Animation.Direction direction) {
|
||||
if (getAnimation().getCurrentDirection() != direction) {
|
||||
getAnimation().setCurrentDirection(direction);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key
|
||||
*
|
||||
* @param key The key to get
|
||||
*/
|
||||
private void getKey(Key key) {
|
||||
gainHealth(1);
|
||||
// Kill the loop in the thread
|
||||
key.getKey();
|
||||
//key.setActive(false);
|
||||
key.playGetKeySound();
|
||||
// Add key to inventory
|
||||
carrying.add(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interact with an object in the game
|
||||
*/
|
||||
private void interact() {
|
||||
int x = getX();
|
||||
int y = getY();
|
||||
getLogger().info("Space bar pressed");
|
||||
if (getAnimation().getCurrentDirection() == Animation.Direction.UP) {
|
||||
if (getEscenario().getCeldas()[x][y - 1].getObject() instanceof Chest) {
|
||||
if (hasKey()) {
|
||||
getLogger().info("Player opened chest");
|
||||
|
||||
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);
|
||||
useKey();
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has a key
|
||||
*
|
||||
* @return Returns true if the player has a key or false if they have no keys
|
||||
*/
|
||||
private boolean hasKey() {
|
||||
for (Object object : carrying) {
|
||||
if (object instanceof Key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a key from the player inventory
|
||||
*/
|
||||
private void useKey() {
|
||||
for (Object object : carrying) {
|
||||
if (object instanceof Key) {
|
||||
getLogger().info("Used key");
|
||||
((Key) object).setState(Key.State.USED);
|
||||
carrying.remove(object);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current health of the player
|
||||
*
|
||||
* @return Returns the health value
|
||||
*/
|
||||
public int getHealth() {
|
||||
return health;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lose a variable amount of health
|
||||
*
|
||||
* @param amount The amount to lose
|
||||
*/
|
||||
public void loseHealth(int amount) {
|
||||
if (health > 0) {
|
||||
getLogger().info("Lose " + amount + " health");
|
||||
health = health - amount;
|
||||
if (health < 0) {
|
||||
getLogger().info("Player is dead");
|
||||
health = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gain a variable amount of health
|
||||
*
|
||||
* @param amount The amount of health to gain
|
||||
*/
|
||||
private void gainHealth(int amount) {
|
||||
if (health < MAX_HEALTH) {
|
||||
getLogger().info("Gain " + amount + " health");
|
||||
health = health + amount;
|
||||
if (health > MAX_HEALTH) {
|
||||
health = MAX_HEALTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This runs when the thread starts
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
while (getActive()) {
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
getLogger().info(e.getMessage());
|
||||
}
|
||||
synchronized (this) {
|
||||
loseHealth(1);
|
||||
getEscenario().getCanvas().repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
171
src/main/java/cl/cromer/azaraka/object/Portal.java
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* This class handles the portal functionality
|
||||
*/
|
||||
public class Portal extends Object implements Constantes {
|
||||
/**
|
||||
* The current state of the portal
|
||||
*/
|
||||
private State state = State.INACTIVE;
|
||||
/**
|
||||
* The active animation
|
||||
*/
|
||||
private Animation activeAnimation;
|
||||
/**
|
||||
* The inactive animation
|
||||
*/
|
||||
private Animation inactiveAnimation;
|
||||
|
||||
/**
|
||||
* Initialize the portal
|
||||
*
|
||||
* @param escenario The scene that contains the portal
|
||||
* @param celda The cell the portal is in
|
||||
*/
|
||||
public Portal(Escenario escenario, Celda celda) {
|
||||
super(escenario, celda);
|
||||
setLogger(getLogger(this.getClass(), LogLevel.PORTAL));
|
||||
loadPortalAnimation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the portal animation
|
||||
*/
|
||||
private void loadPortalAnimation() {
|
||||
activeAnimation = new Animation();
|
||||
for (int i = 0; i < 120; i++) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append(i);
|
||||
while (stringBuilder.length() < 3) {
|
||||
stringBuilder.insert(0, 0);
|
||||
}
|
||||
stringBuilder.append(".png");
|
||||
activeAnimation.addImage(Animation.Direction.NONE, "/img/portal/green/" + stringBuilder.toString());
|
||||
}
|
||||
|
||||
inactiveAnimation = new Animation();
|
||||
for (int i = 0; i < 120; i++) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append(i);
|
||||
while (stringBuilder.length() < 3) {
|
||||
stringBuilder.insert(0, 0);
|
||||
}
|
||||
stringBuilder.append(".png");
|
||||
inactiveAnimation.addImage(Animation.Direction.NONE, "/img/portal/gray/" + stringBuilder.toString());
|
||||
}
|
||||
|
||||
setAnimation(inactiveAnimation);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method animates the portal
|
||||
*/
|
||||
private void animate() {
|
||||
try {
|
||||
getAnimation().getNextFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current status of the portal
|
||||
*
|
||||
* @return Returns the status
|
||||
*/
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new status for the portal
|
||||
*
|
||||
* @param state The new status
|
||||
*/
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
int frame = 0;
|
||||
try {
|
||||
frame = getAnimation().getCurrentFrame();
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
|
||||
if (state == State.ACTIVE) {
|
||||
setAnimation(activeAnimation);
|
||||
try {
|
||||
getAnimation().setCurrentFrame(frame);
|
||||
}
|
||||
catch (AnimationException e) {
|
||||
getLogger().warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
else if (state == State.INACTIVE) {
|
||||
setAnimation(inactiveAnimation);
|
||||
try {
|
||||
getAnimation().setCurrentFrame(frame);
|
||||
}
|
||||
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(35);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
getLogger().info(e.getMessage());
|
||||
}
|
||||
synchronized (this) {
|
||||
animate();
|
||||
getEscenario().getCanvas().repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The current state of the portal
|
||||
*/
|
||||
public enum State {
|
||||
/**
|
||||
* The portal is active
|
||||
*/
|
||||
ACTIVE,
|
||||
/**
|
||||
* The portal is inactive
|
||||
*/
|
||||
INACTIVE
|
||||
}
|
||||
}
|
19
src/main/java/cl/cromer/azaraka/object/package-info.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package contains all the objects that can be in a cell
|
||||
*/
|
||||
package cl.cromer.azaraka.object;
|
19
src/main/java/cl/cromer/azaraka/package-info.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package contains the main classes of the game
|
||||
*/
|
||||
package cl.cromer.azaraka;
|
103
src/main/java/cl/cromer/azaraka/panel/Config.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.panel;
|
||||
|
||||
import cl.cromer.azaraka.Constantes;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import java.awt.*;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* The config panel that is shown on the right
|
||||
*/
|
||||
public class Config extends JPanel implements Constantes {
|
||||
/**
|
||||
* The game panel to modify with the new configuration
|
||||
*/
|
||||
private final Game gamePanel;
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private final Logger logger;
|
||||
|
||||
/**
|
||||
* The game panel used to modify with the new config
|
||||
*
|
||||
* @param gamePanel The game panel
|
||||
*/
|
||||
public Config(Game gamePanel) {
|
||||
this.gamePanel = gamePanel;
|
||||
|
||||
logger = getLogger(this.getClass(), LogLevel.CONFIG);
|
||||
|
||||
JLabel speed = new JLabel("Speed");
|
||||
speed.setForeground(Color.yellow);
|
||||
speed.setFont(FONT);
|
||||
speed.setHorizontalAlignment(JLabel.CENTER);
|
||||
speed.setBackground(Color.gray);
|
||||
|
||||
JLabel volume = new JLabel("Volume");
|
||||
volume.setForeground(Color.yellow);
|
||||
volume.setFont(FONT);
|
||||
volume.setHorizontalAlignment(JLabel.CENTER);
|
||||
volume.setBackground(Color.gray);
|
||||
|
||||
JSlider changeVolume = new JSlider(JSlider.HORIZONTAL, MINIMUM_VOLUME, MAXIMUM_VOLUME, DEFAULT_VOLUME);
|
||||
changeVolume.addChangeListener(this::volumeSliderListener);
|
||||
changeVolume.setMajorTickSpacing(10);
|
||||
changeVolume.setPaintTicks(true);
|
||||
changeVolume.setBackground(Color.gray);
|
||||
|
||||
JSlider changeSpeed = new JSlider(JSlider.HORIZONTAL, MINIMUM_SPEED, MAXIMUM_SPEED, DEFAULT_SPEED);
|
||||
changeSpeed.addChangeListener(this::speedSliderListener);
|
||||
changeSpeed.setMajorTickSpacing(100);
|
||||
changeSpeed.setPaintTicks(true);
|
||||
changeSpeed.setBackground(Color.gray);
|
||||
|
||||
setLayout(new GridLayout(2, 2, 5, 5));
|
||||
setBackground(Color.gray);
|
||||
|
||||
add(speed);
|
||||
add(changeSpeed);
|
||||
add(volume);
|
||||
add(changeVolume);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for the speed slider control
|
||||
*
|
||||
* @param changeEvent The event that caused the listener to fire
|
||||
*/
|
||||
private void speedSliderListener(ChangeEvent changeEvent) {
|
||||
JSlider jSlider = (JSlider) changeEvent.getSource();
|
||||
int speed = 500 - jSlider.getValue() + 100;
|
||||
logger.info("Speed slider adjusted: " + speed);
|
||||
gamePanel.getCanvas().changeSpeed(speed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for the volume slider control
|
||||
*
|
||||
* @param changeEvent The event that caused the listener to fire
|
||||
*/
|
||||
private void volumeSliderListener(ChangeEvent changeEvent) {
|
||||
JSlider jSlider = (JSlider) changeEvent.getSource();
|
||||
float volume = (float) jSlider.getValue() / 100;
|
||||
gamePanel.getCanvas().changeVolume(volume);
|
||||
}
|
||||
}
|
55
src/main/java/cl/cromer/azaraka/panel/Game.java
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.panel;
|
||||
|
||||
import cl.cromer.azaraka.Constantes;
|
||||
import cl.cromer.azaraka.Lienzo;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* The game panel
|
||||
*/
|
||||
public class Game extends JPanel implements Constantes {
|
||||
/**
|
||||
* The canvas
|
||||
*/
|
||||
private final Lienzo canvas;
|
||||
|
||||
/**
|
||||
* Initialize the game panel
|
||||
*/
|
||||
public Game() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
canvas = new Lienzo();
|
||||
canvas.setFocusable(true);
|
||||
canvas.requestFocus();
|
||||
add(canvas);
|
||||
|
||||
setSize(canvas.getWidth(), canvas.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the canvas
|
||||
*
|
||||
* @return Returns the game canvas
|
||||
*/
|
||||
public Lienzo getCanvas() {
|
||||
return canvas;
|
||||
}
|
||||
}
|
19
src/main/java/cl/cromer/azaraka/panel/package-info.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package handles creating panels
|
||||
*/
|
||||
package cl.cromer.azaraka.panel;
|
170
src/main/java/cl/cromer/azaraka/sound/Sound.java
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.sound;
|
||||
|
||||
import cl.cromer.azaraka.Constantes;
|
||||
|
||||
import javax.sound.sampled.*;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* This class handles sound
|
||||
*/
|
||||
public class Sound implements Constantes {
|
||||
/**
|
||||
* The path to the sound
|
||||
*/
|
||||
private final String path;
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private final Logger logger;
|
||||
/**
|
||||
* The sound clip to play
|
||||
*/
|
||||
private Clip sound;
|
||||
|
||||
/**
|
||||
* Load the sound
|
||||
*
|
||||
* @param path The path to the sound resource
|
||||
* @throws SoundException Thrown if the sound file could not be loaded
|
||||
*/
|
||||
public Sound(String path) throws SoundException {
|
||||
this.path = path;
|
||||
logger = getLogger(this.getClass(), LogLevel.SOUND);
|
||||
InputStream inputStream = this.getClass().getResourceAsStream(path);
|
||||
if (inputStream == null) {
|
||||
throw new SoundException("Could not load sound: " + path);
|
||||
}
|
||||
try {
|
||||
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(inputStream));
|
||||
DataLine.Info info = new DataLine.Info(Clip.class, audioInputStream.getFormat());
|
||||
sound = (Clip) AudioSystem.getLine(info);
|
||||
sound.open(audioInputStream);
|
||||
audioInputStream.close();
|
||||
}
|
||||
catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
finally {
|
||||
sound.stop();
|
||||
}
|
||||
logger.info("Opened sound: " + path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Play the sound
|
||||
*
|
||||
* @throws SoundException Thrown if the sound clip is null
|
||||
*/
|
||||
public void play() throws SoundException {
|
||||
if (sound == null) {
|
||||
throw new SoundException("Sound is null!");
|
||||
}
|
||||
|
||||
// Stop the sound if it was already playing
|
||||
if (isPlaying()) {
|
||||
sound.stop();
|
||||
}
|
||||
|
||||
sound.setFramePosition(0);
|
||||
sound.start();
|
||||
logger.info("Play sound: " + path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the sound clip is playing or not
|
||||
*
|
||||
* @return Returns true if the sound is playing or false otherwise
|
||||
* @throws SoundException Thrown if the sound clip is null
|
||||
*/
|
||||
public boolean isPlaying() throws SoundException {
|
||||
if (sound == null) {
|
||||
throw new SoundException("Sound is null!");
|
||||
}
|
||||
|
||||
return sound.isActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the sound
|
||||
*
|
||||
* @throws SoundException Thrown if the sound clip is null
|
||||
*/
|
||||
public void stop() throws SoundException {
|
||||
if (sound == null) {
|
||||
throw new SoundException("Sound is null!");
|
||||
}
|
||||
|
||||
if (isPlaying()) {
|
||||
sound.stop();
|
||||
}
|
||||
logger.info("Stop sound: " + path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of loops to play
|
||||
*
|
||||
* @param loops The number of loops, should be n-1
|
||||
* @throws SoundException Thrown if the sound is null
|
||||
*/
|
||||
public void setLoops(int loops) throws SoundException {
|
||||
if (sound == null) {
|
||||
throw new SoundException("Sound is null!");
|
||||
}
|
||||
sound.loop(loops);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the volume of the sound
|
||||
*
|
||||
* @param volume Volume between 0f and 1f
|
||||
* @throws SoundException Thrown if the sound clip is null or the volume is out of range
|
||||
*/
|
||||
public void setVolume(float volume) throws SoundException {
|
||||
if (sound == null) {
|
||||
throw new SoundException("Sound is null!");
|
||||
}
|
||||
|
||||
if (volume < 0f || volume > 1f) {
|
||||
throw new SoundException("Invalid sound range!");
|
||||
}
|
||||
|
||||
if (sound.isControlSupported(FloatControl.Type.MASTER_GAIN)) {
|
||||
FloatControl gainControl = (FloatControl) sound.getControl(FloatControl.Type.MASTER_GAIN);
|
||||
float dB = (float) (Math.log(volume) / Math.log(10.0) * 20.0);
|
||||
logger.info("Set volume " + path + ": " + dB);
|
||||
gainControl.setValue(dB);
|
||||
}
|
||||
else if (sound.isControlSupported(FloatControl.Type.VOLUME)) {
|
||||
logger.info("Gain control not supported");
|
||||
float newVolume = 0;
|
||||
if (volume > 0f) {
|
||||
newVolume = ((volume * 100) * 65536) / 100;
|
||||
}
|
||||
FloatControl volumeControl = (FloatControl) sound.getControl(FloatControl.Type.VOLUME);
|
||||
logger.info("Set volume " + path + ": " + newVolume);
|
||||
volumeControl.setValue(newVolume);
|
||||
}
|
||||
else {
|
||||
logger.info("No control to modify volume");
|
||||
}
|
||||
}
|
||||
}
|
30
src/main/java/cl/cromer/azaraka/sound/SoundException.java
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.sound;
|
||||
|
||||
/**
|
||||
* This exception is thrown when there are problems with a sound
|
||||
*/
|
||||
public class SoundException extends Exception {
|
||||
/**
|
||||
* Throw an error with a message
|
||||
*
|
||||
* @param errorMessage The message
|
||||
*/
|
||||
public SoundException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
}
|
19
src/main/java/cl/cromer/azaraka/sound/package-info.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package handles sounds
|
||||
*/
|
||||
package cl.cromer.azaraka.sound;
|
349
src/main/java/cl/cromer/azaraka/sprite/Animation.java
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.sprite;
|
||||
|
||||
import cl.cromer.azaraka.Constantes;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* This class handles loading the images and animating the sprite
|
||||
*/
|
||||
public class Animation implements Cloneable, Constantes {
|
||||
/**
|
||||
* The collection of all the images that make up the object
|
||||
*/
|
||||
private final HashMap<Direction, ArrayList<BufferedImage>> imageHash;
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private final Logger logger;
|
||||
/**
|
||||
* The current frame the sprite should be showing
|
||||
*/
|
||||
private int currentFrame = 0;
|
||||
/**
|
||||
* The offset in pixels from the left side of the cell to draw the sprite
|
||||
*/
|
||||
private int xOffset = 0;
|
||||
/**
|
||||
* The offset in pixels from the top of the cell to draw the sprite
|
||||
*/
|
||||
private int yOffset = 0;
|
||||
/**
|
||||
* The direction of the image to show
|
||||
*/
|
||||
private Direction currentDirection = Direction.NONE;
|
||||
|
||||
/**
|
||||
* Initialize the sprite
|
||||
*/
|
||||
public Animation() {
|
||||
imageHash = new HashMap<>();
|
||||
logger = getLogger(this.getClass(), LogLevel.ANIMATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale an image
|
||||
*
|
||||
* @param image The image to scale
|
||||
* @param width The new width
|
||||
* @param height The new height
|
||||
* @return Returns the scaled image
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static BufferedImage scaleImage(BufferedImage image, int width, int height) {
|
||||
Image tmpImage = image.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);
|
||||
BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D graphics2D = resized.createGraphics();
|
||||
graphics2D.drawImage(tmpImage, 0, 0, null);
|
||||
graphics2D.dispose();
|
||||
return resized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the offset of x for the sprite
|
||||
*
|
||||
* @return Returns the x offset in pixels
|
||||
*/
|
||||
public int getXOffset() {
|
||||
return xOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the offset of y for the sprite
|
||||
*
|
||||
* @return Returns the y offset in pixels
|
||||
*/
|
||||
public int getYOffset() {
|
||||
return yOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the y offset manually instead of using the automatically detected value
|
||||
*
|
||||
* @param yOffset The new y offset
|
||||
*/
|
||||
public void setYOffset(int yOffset) {
|
||||
this.yOffset = yOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the offset of x for the sprite
|
||||
*
|
||||
* @param x The width x of the image
|
||||
*/
|
||||
private void calculateXOffset(int x) {
|
||||
if (x == CELL_PIXELS) {
|
||||
x = 0;
|
||||
}
|
||||
else {
|
||||
x = (CELL_PIXELS - x) / 2;
|
||||
}
|
||||
this.xOffset = x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the offset of y for the sprite
|
||||
*
|
||||
* @param y The height y of the image
|
||||
*/
|
||||
private void calculateYOffset(int y) {
|
||||
if (y == CELL_PIXELS) {
|
||||
y = 0;
|
||||
}
|
||||
else {
|
||||
y = (CELL_PIXELS - y) / 2;
|
||||
}
|
||||
this.yOffset = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an image to the animation
|
||||
*
|
||||
* @param direction The direction to add the image to
|
||||
* @param path The path to the sprite e.g. res/player/image.png
|
||||
*/
|
||||
public void addImage(Direction direction, String path) {
|
||||
try {
|
||||
BufferedImage bufferedImage = ImageIO.read(getClass().getResourceAsStream(path));
|
||||
addImageToList(direction, bufferedImage);
|
||||
}
|
||||
catch (IOException | IllegalArgumentException e) {
|
||||
logger.warning("Failed to load image: " + path);
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an image to the animation
|
||||
*
|
||||
* @param direction The direction to add the image to
|
||||
* @param bufferedImage The path to the sprite e.g. res/player/image.png
|
||||
*/
|
||||
public void addImage(Direction direction, BufferedImage bufferedImage) {
|
||||
addImageToList(direction, bufferedImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an image to the list of images
|
||||
*
|
||||
* @param direction The direction to add the image to
|
||||
* @param bufferedImage The image to add
|
||||
*/
|
||||
private void addImageToList(Direction direction, BufferedImage bufferedImage) {
|
||||
calculateXOffset(bufferedImage.getWidth());
|
||||
calculateYOffset(bufferedImage.getHeight());
|
||||
|
||||
ArrayList<BufferedImage> images;
|
||||
if (imageHash.containsKey(direction)) {
|
||||
images = imageHash.get(direction);
|
||||
}
|
||||
else {
|
||||
images = new ArrayList<>();
|
||||
}
|
||||
images.add(bufferedImage);
|
||||
imageHash.put(direction, images);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current frame in the sprite
|
||||
*
|
||||
* @return Returns the current frame
|
||||
* @throws AnimationException Thrown when there are no images in the sprite
|
||||
*/
|
||||
public BufferedImage getFrame() throws AnimationException {
|
||||
ArrayList<BufferedImage> images = getImagesFromHash();
|
||||
if (currentFrame >= images.size()) {
|
||||
throw new AnimationException("Animation does not have frame: " + currentFrame);
|
||||
}
|
||||
return images.get(currentFrame);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of frames in the
|
||||
*
|
||||
* @return Returns the amount of frames in the sprite
|
||||
* @throws AnimationException Thrown if there are no images in the animation
|
||||
*/
|
||||
public int getFrameCount() throws AnimationException {
|
||||
return getImagesFromHash().size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current frame
|
||||
*
|
||||
* @return Returns the current frame
|
||||
* @throws AnimationException Thrown if there are no frame in the current animation
|
||||
*/
|
||||
public int getCurrentFrame() throws AnimationException {
|
||||
ArrayList<BufferedImage> images;
|
||||
if (imageHash.containsKey(currentDirection)) {
|
||||
images = imageHash.get(currentDirection);
|
||||
if (images.size() == 0) {
|
||||
throw new AnimationException("The direction has no images assigned!");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new AnimationException("There is no direction assigned to the animation!");
|
||||
}
|
||||
|
||||
return currentFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set which frame is to be shown in the sprite manually
|
||||
*
|
||||
* @param frame The frame to show
|
||||
* @throws AnimationException Thrown if the frame number does not exist
|
||||
*/
|
||||
public void setCurrentFrame(int frame) throws AnimationException {
|
||||
ArrayList<BufferedImage> images;
|
||||
if (imageHash.containsKey(currentDirection)) {
|
||||
images = imageHash.get(currentDirection);
|
||||
}
|
||||
else {
|
||||
throw new AnimationException("There is no direction assigned to the animation");
|
||||
}
|
||||
|
||||
if (frame < 0) {
|
||||
throw new AnimationException("The frame number passed is invalid!");
|
||||
}
|
||||
if (frame > images.size() - 1) {
|
||||
throw new AnimationException("The frame does not exist inside the sprite!");
|
||||
}
|
||||
currentFrame = frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next frame in the sprite
|
||||
*
|
||||
* @throws AnimationException Thrown when there are no images in the sprite
|
||||
*/
|
||||
public void getNextFrame() throws AnimationException {
|
||||
ArrayList<BufferedImage> images = getImagesFromHash();
|
||||
currentFrame++;
|
||||
if (currentFrame >= images.size()) {
|
||||
currentFrame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the images from the HashMap
|
||||
*
|
||||
* @return The images for the specific direction
|
||||
* @throws AnimationException Thrown if there are no images in the hash or no images in the sprite
|
||||
*/
|
||||
private ArrayList<BufferedImage> getImagesFromHash() throws AnimationException {
|
||||
ArrayList<BufferedImage> images;
|
||||
if (imageHash.containsKey(currentDirection)) {
|
||||
images = imageHash.get(currentDirection);
|
||||
}
|
||||
else {
|
||||
throw new AnimationException("The direction has no images assigned!");
|
||||
}
|
||||
|
||||
if (images.size() == 0) {
|
||||
throw new AnimationException("There are no images in the sprite!");
|
||||
}
|
||||
|
||||
return images;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current direction that the animation is using
|
||||
*
|
||||
* @return Returns the current direction
|
||||
*/
|
||||
public Direction getCurrentDirection() {
|
||||
return currentDirection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the animation to the new direction and set the current frame to 0
|
||||
*
|
||||
* @param currentDirection The new direction
|
||||
*/
|
||||
public void setCurrentDirection(Direction currentDirection) {
|
||||
this.currentDirection = currentDirection;
|
||||
currentFrame = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the sprite to be cloned into various cells
|
||||
*
|
||||
* @return The cloned sprite
|
||||
* @throws CloneNotSupportedException Thrown if the object does not support cloning
|
||||
*/
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* The directions that the image can use
|
||||
*/
|
||||
public enum Direction {
|
||||
/**
|
||||
* The image does not belong in a direction
|
||||
*/
|
||||
NONE,
|
||||
/**
|
||||
* The image is facing up
|
||||
*/
|
||||
UP,
|
||||
/**
|
||||
* The image is facing down
|
||||
*/
|
||||
DOWN,
|
||||
/**
|
||||
* The image is facing left
|
||||
*/
|
||||
LEFT,
|
||||
/**
|
||||
* The image is facing right
|
||||
*/
|
||||
RIGHT
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.sprite;
|
||||
|
||||
/**
|
||||
* This exception is thrown when there are problems with a sprite
|
||||
*/
|
||||
public class AnimationException extends Exception {
|
||||
/**
|
||||
* Throw an error with a message
|
||||
*
|
||||
* @param errorMessage The message
|
||||
*/
|
||||
public AnimationException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
}
|
81
src/main/java/cl/cromer/azaraka/sprite/Sheet.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.sprite;
|
||||
|
||||
import cl.cromer.azaraka.Constantes;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* This class handles loading the images and sub-images
|
||||
*/
|
||||
public class Sheet implements Constantes {
|
||||
/**
|
||||
* A list of all the textures in the collection
|
||||
*/
|
||||
private final ArrayList<BufferedImage> images;
|
||||
|
||||
/**
|
||||
* Initialize the texture collection
|
||||
*
|
||||
* @param path The path to the image
|
||||
* @param height The height of the textures in the image
|
||||
* @param width The width of the textures in the image
|
||||
*/
|
||||
public Sheet(String path, int height, int width) {
|
||||
images = new ArrayList<>();
|
||||
Logger logger = getLogger(this.getClass(), LogLevel.SHEET);
|
||||
|
||||
try {
|
||||
BufferedImage image = ImageIO.read(getClass().getResourceAsStream(path));
|
||||
int columns = image.getWidth() / width;
|
||||
int rows = image.getHeight() / height;
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < columns; j++) {
|
||||
BufferedImage subImage = image.getSubimage(j * width, i * height, width, height);
|
||||
images.add(subImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException | IllegalArgumentException e) {
|
||||
logger.warning("Failed to load image: " + path);
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the selected texture
|
||||
*
|
||||
* @param textureNumber The texture to get from the collection
|
||||
* @return Returns the current texture
|
||||
* @throws SheetException Thrown when there are no images in the texture collection
|
||||
*/
|
||||
public BufferedImage getTexture(int textureNumber) throws SheetException {
|
||||
if (images.size() == 0) {
|
||||
throw new SheetException("There are no images in the texture collection!");
|
||||
}
|
||||
if (textureNumber < 0 || textureNumber > images.size() - 1) {
|
||||
throw new SheetException("Invalid texture number!");
|
||||
}
|
||||
return images.get(textureNumber);
|
||||
}
|
||||
}
|
||||
|
||||
|
30
src/main/java/cl/cromer/azaraka/sprite/SheetException.java
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package cl.cromer.azaraka.sprite;
|
||||
|
||||
/**
|
||||
* This exception is thrown when there are problems with a sprite
|
||||
*/
|
||||
public class SheetException extends Exception {
|
||||
/**
|
||||
* Throw an error with a message
|
||||
*
|
||||
* @param errorMessage The message
|
||||
*/
|
||||
public SheetException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
}
|
19
src/main/java/cl/cromer/azaraka/sprite/package-info.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2019 Chris Cromer
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package handles spites, animations, and image sheets
|
||||
*/
|
||||
package cl.cromer.azaraka.sprite;
|
BIN
src/main/resources/img/chest/chests.png
Executable file
After Width: | Height: | Size: 78 KiB |
BIN
src/main/resources/img/enemy/chara4.png
Executable file
After Width: | Height: | Size: 225 KiB |
BIN
src/main/resources/img/enemy/emote4.png
Executable file
After Width: | Height: | Size: 50 KiB |
BIN
src/main/resources/img/gameover/gameover.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
src/main/resources/img/heart/heart0.png
Executable file
After Width: | Height: | Size: 888 B |
BIN
src/main/resources/img/heart/heart1.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
BIN
src/main/resources/img/heart/heart2.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
BIN
src/main/resources/img/heart/heart3.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
BIN
src/main/resources/img/heart/heart4.png
Executable file
After Width: | Height: | Size: 917 B |
BIN
src/main/resources/img/icon.png
Executable file
After Width: | Height: | Size: 411 B |
BIN
src/main/resources/img/key/key.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
src/main/resources/img/player/chara2.png
Executable file
After Width: | Height: | Size: 223 KiB |
BIN
src/main/resources/img/player/emote2.png
Executable file
After Width: | Height: | Size: 159 KiB |
BIN
src/main/resources/img/portal/gray/000.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/001.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/002.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/003.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/004.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/005.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/006.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/007.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/008.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/009.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/010.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/011.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/012.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/013.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/014.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/015.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/016.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
src/main/resources/img/portal/gray/017.png
Normal file
After Width: | Height: | Size: 266 B |
BIN
src/main/resources/img/portal/gray/018.png
Normal file
After Width: | Height: | Size: 266 B |
BIN
src/main/resources/img/portal/gray/019.png
Normal file
After Width: | Height: | Size: 269 B |
BIN
src/main/resources/img/portal/gray/020.png
Normal file
After Width: | Height: | Size: 287 B |
BIN
src/main/resources/img/portal/gray/021.png
Normal file
After Width: | Height: | Size: 290 B |
BIN
src/main/resources/img/portal/gray/022.png
Normal file
After Width: | Height: | Size: 319 B |
BIN
src/main/resources/img/portal/gray/023.png
Normal file
After Width: | Height: | Size: 344 B |
BIN
src/main/resources/img/portal/gray/024.png
Normal file
After Width: | Height: | Size: 375 B |
BIN
src/main/resources/img/portal/gray/025.png
Normal file
After Width: | Height: | Size: 375 B |
BIN
src/main/resources/img/portal/gray/026.png
Normal file
After Width: | Height: | Size: 421 B |
BIN
src/main/resources/img/portal/gray/027.png
Normal file
After Width: | Height: | Size: 465 B |
BIN
src/main/resources/img/portal/gray/028.png
Normal file
After Width: | Height: | Size: 460 B |
BIN
src/main/resources/img/portal/gray/029.png
Normal file
After Width: | Height: | Size: 514 B |
BIN
src/main/resources/img/portal/gray/030.png
Normal file
After Width: | Height: | Size: 557 B |
BIN
src/main/resources/img/portal/gray/031.png
Normal file
After Width: | Height: | Size: 573 B |
BIN
src/main/resources/img/portal/gray/032.png
Normal file
After Width: | Height: | Size: 639 B |
BIN
src/main/resources/img/portal/gray/033.png
Normal file
After Width: | Height: | Size: 693 B |
BIN
src/main/resources/img/portal/gray/034.png
Normal file
After Width: | Height: | Size: 695 B |
BIN
src/main/resources/img/portal/gray/035.png
Normal file
After Width: | Height: | Size: 759 B |
BIN
src/main/resources/img/portal/gray/036.png
Normal file
After Width: | Height: | Size: 764 B |
BIN
src/main/resources/img/portal/gray/037.png
Normal file
After Width: | Height: | Size: 784 B |
BIN
src/main/resources/img/portal/gray/038.png
Normal file
After Width: | Height: | Size: 803 B |
BIN
src/main/resources/img/portal/gray/039.png
Normal file
After Width: | Height: | Size: 838 B |
BIN
src/main/resources/img/portal/gray/040.png
Normal file
After Width: | Height: | Size: 871 B |
BIN
src/main/resources/img/portal/gray/041.png
Normal file
After Width: | Height: | Size: 870 B |
BIN
src/main/resources/img/portal/gray/042.png
Normal file
After Width: | Height: | Size: 885 B |
BIN
src/main/resources/img/portal/gray/043.png
Normal file
After Width: | Height: | Size: 926 B |
BIN
src/main/resources/img/portal/gray/044.png
Normal file
After Width: | Height: | Size: 940 B |
BIN
src/main/resources/img/portal/gray/045.png
Normal file
After Width: | Height: | Size: 1007 B |
BIN
src/main/resources/img/portal/gray/046.png
Normal file
After Width: | Height: | Size: 992 B |
BIN
src/main/resources/img/portal/gray/047.png
Normal file
After Width: | Height: | Size: 977 B |
BIN
src/main/resources/img/portal/gray/048.png
Normal file
After Width: | Height: | Size: 1011 B |
BIN
src/main/resources/img/portal/gray/049.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
src/main/resources/img/portal/gray/050.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
src/main/resources/img/portal/gray/051.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
src/main/resources/img/portal/gray/052.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
src/main/resources/img/portal/gray/053.png
Normal file
After Width: | Height: | Size: 1.1 KiB |