CLASE PRINCIPAL
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package robots2D;
import java.io.File;
import org.lwjgl.LWJGLUtil;
import org.newdawn.slick.*;
import org.newdawn.slick.Input.*;
import org.newdawn.slick.font.effects.ColorEffect;
import org.newdawn.slick.tiled.*;
/**
* JUEGO DE LOS ROBOTS - aplicación base para el desarrollo del examen de la segunda evaluación
*
*
*/
public class Robots2D extends BasicGame {
// Tilemap
private TiledMap mapa;
// Estado del jugador
private float jugadorX, jugadorY;
private SpriteSheet cuadros;
private SpriteSheet cuadrosRobot;
// Posición del corazón
private float corazonX, corazonY;
private Image corazon;
// NUEVO: Para almacenar la explosión
private SpriteSheet explosion;
private Animation jugador;
private Animation jugadorArriba;
private Animation jugadorDerecha;
private Animation jugadorAbajo;
private Animation jugadorIzquierda;
private boolean jugadorVivo;
// Estado de los robots
private Animation[] robot;
private Animation robotArriba;
private Animation robotDerecha;
private Animation robotAbajo;
private Animation robotIzquierda;
private float[] robotX, robotY;
private boolean[] robotVivo;
private boolean[] robotVisible;
private float[] robotVelocidad;
private int numeroRobotsVivos;
private static final int TOTAL_ROBOTS = 30;
// Escritura de cadenas
private UnicodeFont fuente;
// Contador de tiempo
private long tiempo;
// NUEVO: Música y sonidos
private Music musica;
private Sound sonido;
public Robots2D(String name) {
super(name);
}
public static void main(String[] args) {
System.setProperty("org.lwjgl.librarypath", new File(new File(System.getProperty("user.dir"), "native"), LWJGLUtil.getPlatformName()).getAbsolutePath());
System.setProperty("net.java.games.input.librarypath", System.getProperty("org.lwjgl.librarypath"));
try {
AppGameContainer container = new AppGameContainer(new Robots2D("PMDM06 - Tarea"));
container.setDisplayMode(640, 480, false);
container.setTargetFrameRate(60);
container.setVSync(true);
container.setShowFPS(false);
container.setUpdateOnlyWhenVisible(false);
container.start();
} catch (SlickException e) {
}
}
@Override
public void init(GameContainer gc) throws SlickException {
// cargar mapa
mapa = new TiledMap("data/mapa.tmx", "data");
corazon = new Image("data/corazon.png");
// cargar spritesheets
cuadros = new SpriteSheet("data/heroe.png", 24, 32);
cuadrosRobot = new SpriteSheet("data/robot.png", 24, 32);
explosion = new SpriteSheet("data/explosion.png", 32, 32); // NUEVO
// cargar animaciones del jugador
jugadorArriba = new Animation(cuadros, 0, 0, 2, 0, true, 150, false);
jugadorDerecha = new Animation(cuadros, 0, 1, 2, 1, true, 150, false);
jugadorAbajo = new Animation(cuadros, 0, 2, 2, 2, true, 150, false);
jugadorIzquierda = new Animation(cuadros, 0, 3, 2, 3, true, 150, false);
jugador = jugadorAbajo;
// cargar animaciones del robot
robotArriba = new Animation(cuadrosRobot, 0, 0, 2, 0, true, 150, true);
robotDerecha = new Animation(cuadrosRobot, 0, 1, 2, 1, true, 150, true);
robotAbajo = new Animation(cuadrosRobot, 0, 2, 2, 2, true, 150, true);
robotIzquierda = new Animation(cuadrosRobot, 0, 3, 2, 3, true, 150, true);
// estado inicial del jugador
jugadorX = 320;
jugadorY = 240;
jugadorVivo = true;
// estado inicial de los robots
robot = new Animation[TOTAL_ROBOTS];
robotX = new float[TOTAL_ROBOTS];
robotY = new float[TOTAL_ROBOTS];
robotVivo = new boolean[TOTAL_ROBOTS];
robotVelocidad = new float[TOTAL_ROBOTS];
// NUEVO: Un robot puede estar muerto pero visible mientras explota
robotVisible = new boolean[TOTAL_ROBOTS];
numeroRobotsVivos = TOTAL_ROBOTS;
// los colocamos repartidos al azar
for (int i=0;i<TOTAL_ROBOTS;i++) {
// Cogemos una coordenada X alejada del centro
float X = (float)((Math.random()*(gc.getWidth()/2-100)));
// ¿En la izquierda o en la derecha?
if (Math.random()<0.5f) {
robotX[i] = X;
robot[i] = robotDerecha; // mirar a la derecha
}
else {
robotX[i] = gc.getWidth()-X;
robot[i] = robotIzquierda; // mirar a la izquierda
}
// Cogemos una coordenada Y alejada del centro teniendo en cuenta
// que los primeros 64 píxeles no se pueden usar porque está
// el marcador
float Y = 64 + (float)((Math.random()*(gc.getHeight()/2-132)));
// ¿En la parte de arriba o de abajo?
if (Math.random()<0.5f) {
robotY[i] = Y;
}
else {
robotY[i] = gc.getHeight()-Y;
}
}
corazonX = (float)((Math.random()*(gc.getWidth()/2)));
corazonY = 64 + (float)((Math.random()*(gc.getHeight()/2)));
// indicamos que, de momento, los robots están vivos
for (int i = 0; i < TOTAL_ROBOTS; i++) {
robotVivo[i] = true;
robotVisible[i] = true;
// NUEVO: Que algunos empiecen más o menos rápidos
robotVelocidad[i] = 0.25f + 0.5f * (float) Math.random();
}
// cargar tipo de letra de la carpeta data y todos los símboles
// que podamos necesitar
fuente = new UnicodeFont("data/tuffy.ttf", 28, false, false);
// añade las letras ASCII estándar
fuente.addAsciiGlyphs();
// y ahora añadimos los caracteres españoles
fuente.addGlyphs("áéíóúÁÉÍÓÚñÑ¡¿");
// en Slick es obligatorio añadir un efecto para poder dibujar
// texto. Añadimos un efecto vacío.
fuente.getEffects().add(new ColorEffect(java.awt.Color.WHITE));
// cargamos los símbolos del tipo de letra
fuente.loadGlyphs();
// a partir de ahora, llamado a fuente.drawString(x, y, texto) ¡podremos
// escribir en el contenedor!
// NUEVO: Añadimos música de fondo y cargamos los efectos de sonido
musica = new Music("data/tuturne land!.mod");
sonido = new Sound("data/8bit_bomb_explosion.wav");
musica.loop();
// comenzar cuenta de tiempo. Apuntamos el número que contiene el
// reloj del sistema en milisegundos. De esta forma, restando esta
// cantidad a la cuenta actual nos dice el número de milisengudos
// que han transcurrido.
tiempo = System.currentTimeMillis();
}
@Override
public void update(GameContainer gc, int delta) throws SlickException {
Input entrada = gc.getInput();
// si se pulsa Esc, salir
if (entrada.isKeyDown(Input.KEY_ESCAPE)) { // Tecla ESC
gc.exit();
}
// si no quedan robots o ha muerto el jugador, no actualizar nada
if ((jugadorVivo == false) || (numeroRobotsVivos == 0)) {
return;
}
// movimiento del jugador
if (entrada.isKeyDown(Input.KEY_DOWN)) { // Tecla abajo
jugadorY += delta * 0.1f;
// evitar que nos salgamos por la parte inferior del contenedor
if (jugadorY > (gc.getHeight() - jugador.getHeight())) {
jugadorY = (gc.getHeight() - jugador.getHeight());
}
jugador = jugadorAbajo;
jugador.update(delta);
}
if (entrada.isKeyDown(Input.KEY_UP)) { // Tecla arriba
jugadorY -= delta * 0.1f;
// evitar que nos salgamos por la parte superior del contenedor
if (jugadorY < 32) {
jugadorY = 32;
}
jugador = jugadorArriba;
jugador.update(delta);
}
if (entrada.isKeyDown(Input.KEY_RIGHT)) { // Tecla derecha
jugadorX += delta * 0.1f;
// evitar que nos salgamos por la derecha del contenedor
if (jugadorX > (gc.getWidth() - jugador.getWidth())) {
jugadorX = (gc.getWidth() - jugador.getWidth());
}
jugador = jugadorDerecha;
jugador.update(delta);
}
if (entrada.isKeyDown(Input.KEY_LEFT)) { // Tecla izquierda
jugadorX -= delta * 0.1f;
// evitar que nos salgamos por la izquierda del contenedor
if (jugadorX < 0) {
jugadorX = 0;
}
jugador = jugadorIzquierda;
jugador.update(delta);
}
// NUEVO: Movemos los robots hacia el jugador si están vivos
// cada 50 segundos, el robot se moverá un 50% más rápido
// respecto a la velocidad inicial
float prisa = 1.0f + (System.currentTimeMillis() - tiempo) / 50000.0f; // cuanto mayor sea, más rápido irán
for (int i = 0; i < TOTAL_ROBOTS; i++) {
if (robotVivo[i]) {
// calculamos la escala del movimiento, pero la acotaremos
// para que no sean demasiado rápidos o el jugador nunca
// podría escapar
float escalaFinal = prisa * 0.1f * robotVelocidad[i];
escalaFinal = escalaFinal > 1.15 ? 1.15f : escalaFinal;
if (robotY[i] > jugadorY) {
robotY[i] -= delta * escalaFinal;
robot[i] = robotArriba;
}
if (robotY[i] < jugadorY) {
robotY[i] += delta * escalaFinal;
robot[i] = robotAbajo;
}
if (robotX[i] > jugadorX) {
robotX[i] -= delta * escalaFinal;
robot[i] = robotIzquierda;
}
if (robotX[i] < jugadorX) {
robotX[i] += delta * escalaFinal;
robot[i] = robotDerecha;
}
} else {
// si el robot está visible pero su animación se ha parado
// es que acaba de termina la animación de la explosión,
// así que lo ocultamos
if ((robotVisible[i]) && (robot[i].isStopped())) {
robotVisible[i] = false;
}
}
}
// NUEVO: Comprobar si han chocado entre sí o con el jugador
for (int i = 0; i < TOTAL_ROBOTS; i++) {
if (robotVivo[i]) {
// ¿Ha chocado el robot 'i' con el jugador?
// Para nosotros habrán colisionado cuando
// la parte izquierda de sus bases estén a menos de 4
// píxeles en vertical y en horizontal
if ((Math.abs(robotX[i] - jugadorX) < 4.0f)
&& (Math.abs(robotY[i] - jugadorY) < 4.0f)) {
// Sí: robot muerto
robotVivo[i] = false;
// Hacerlo explotar una sola vez
robot[i] = new Animation(explosion, 0, 0, 3, 3, true, 100, true);
robot[i].setLooping(false);
// Aunque no sirve de mucho, ¡un robot menos!
numeroRobotsVivos -= 1;
// Reproducir explosión
sonido.play();
// El jugador ha muerto
jugadorVivo = false;
}
// ¿Ha chocado el robot 'i' con otro robot?
for (int j = 0; j < TOTAL_ROBOTS; j++) {
// Cuidado, hay que evita comprobar si hemos chocado con
// nosotros o nada más empezar explotaremos
if (i != j && robotVivo[j]) {
// Para nosotros habrán colisionado los robots cuando
// la parte izquierda de sus bases estén a menos de 4
// píxeles en vertical y en horizontal
if ((Math.abs(robotX[i] - robotX[j]) < 4.0f)
&& (Math.abs(robotY[i] - robotY[j]) < 4.0f)) {
// Sí: robots muertos
robotVivo[i] = false;
robotVivo[j] = false;
// Crear una nueva explosión y asignársela a los
// dos robots ya que explotan simultáneamente
robot[i] = new Animation(explosion, 0, 0, 3, 3, true, 100, true);
// Que sólo exploten una vez
robot[i].setLooping(false);
robot[j] = robot[i];
// Dos robots menos
numeroRobotsVivos -= 2;
// Reproducir explosión
sonido.play();
// Si ya no quedan robots, ¡hemos ganado!
if (numeroRobotsVivos == 100) {
// Cambiar música
musica = new Music("data/bi-menu.xm");
musica.loop();
}
// Esto es para evitar que un robot ya
// muerto destruya a otro
break;
}
}
}
}
}
if ((Math.abs((jugadorX+jugador.getWidth()) - (corazonX + corazon.getWidth())) < 13.0f)
&& (Math.abs((jugadorY+jugador.getHeight()) - (corazonY+corazon.getHeight())) < 10.0f)) {
numeroRobotsVivos=0;
}
}
@Override
public void render(GameContainer gc, Graphics g) throws SlickException {
// dibujar tilemap
mapa.render(0, 0);
corazon.draw(corazonX,corazonY);
// dibujar jugador. NUEVO: sólo si está vivo
if (jugadorVivo == true) {
jugador.draw(jugadorX, jugadorY);
}
// dibujar robots si están visibles
for (int i = 0; i < TOTAL_ROBOTS; i++) {
if (robotVisible[i]) {
robot[i].draw(robotX[i], robotY[i]);
}
}
// dibujar robots restantes
fuente.drawString(400, 10, "Quedan " + numeroRobotsVivos + " robots");
if (jugadorVivo == false) {
String gameOver = "Fin de juego";
// dibujamos el texto centrado en el contenedor
fuente.drawString((gc.getWidth() - fuente.getWidth(gameOver)) / 2, (gc.getHeight() - fuente.getHeight(gameOver)) / 2, gameOver, Color.red);
return;
} else {
if (numeroRobotsVivos == 0) {
String gameOver = "¡Has ganado!";
// dibujamos el texto centrado en el contenedor
fuente.drawString((gc.getWidth() - fuente.getWidth(gameOver)) / 2, (gc.getHeight() - fuente.getHeight(gameOver)) / 2, gameOver, Color.yellow);
return;
}
}
// dibujar tiempo transcurrido si no ha acabado el juego
fuente.drawString(40, 10, "Tiempo: " + (System.currentTimeMillis() - tiempo) / 1000);
}
}