package com.me.invaders.screens; import java.util.ArrayList; import java.util.Random; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture.TextureFilter; import com.badlogic.gdx.math.Vector2; import com.me.invaders.spaceInvaders; import com.me.invaders.charapters.Alien; import com.me.invaders.charapters.AlienBonus; import com.me.invaders.charapters.Ball; import com.me.invaders.charapters.MegaShotShip; import com.me.invaders.charapters.Ship; import com.me.invaders.charapters.Shot; import com.me.invaders.charapters.ShotAlien; import com.me.invaders.charapters.ShotShip; public class GameScreen extends AbstractScreen { // Implementa la interfaz de Screen, es decir, se comportara con las caracteristicas de una pantalla // sus funciones se llaman automaticamente cuando ocurre el evento al que estan asociadas (renderizar, //reescalar, pausar, resumir...) menos con dispose, para liberar los recursos hay que llamar a dispose manualmente private static final float LIMITE_DISPARO = Gdx.graphics.getHeight(); // La distancia que tiene que recorrer el disparo. private static final float MAXIMO_ALIENS_FILA = 8; // Numero maximo de aliens private static final float DISTANCIA = 50; // Distancia en el eje x donde se van colocando los aliens. private static final float ALTURA = Gdx.graphics.getHeight() - 70; // Distancia en el eje y donde empiezan los aliens. private static final float MARGEN_IZQUIERDO = 50; // Limite de los aliens a la izquierda. private static final float MARGEN_DERECHO = Gdx.graphics.getWidth(); // Limite de los aliens a la derecha. private static final float SPEED = 1.2f; // Velocidad del juego cuando se inicia. private static final float AUMENTO_DE_VELOCIDAD = 1.5f; // Velocidad que se le van a aumentar a los aliens cuando se pasa cada fase. private static final float FRECUENCIA_ALIEN_BONUS = 4; // Frecuencia con la que sale el alienBonus private Texture TexturaFondo; // Una Texture es una clase que envuelve una textura estandar de OpenGL, se utiliza para imagenes simples. private Texture texturaAlien1, texturaAlien2, texturaAlien3, texturaAlien4; // Textura de los aliens private Ship nave; // Nave del juego. private ArrayList<Alien> aliensTipo1; // Los aliens tipo1 del juego. private ArrayList<Alien> aliensTipo2; // Los aliens tipo2 del juego. private ArrayList<Alien> aliensTipo3; // Los aliens tipo3 del juego. private ArrayList<Alien> aliensTipo4; // Los aliens tipo4 del juego. private Shot disparoNave; // El disparo que matará los aliens. private Shot disparoAlien; // El disparo que lanzarán los aliens para destruir la nave. private boolean actualizarDisparoNave; // Actualiza el disparo de la nave. private boolean actualizarDisparoAlien; // Actualiza el disparo de los aliens. private boolean gameOver; // Te indica si has perdido o no. private int marcadorDePuntos; // Sirve para contar los puntos al destruir aliens. private float velocidadAliens; // La velocidad con la que se moveran los aliens. Aumentará a medida que se avance en las distintas fases. private Random aleatorio; // Permite usar números aleatorios private int vidasNave; // Vidas que tendrá nuestra nave. private Ball bola; // Bola que al coger la nave le permite realizar un disparo especial. private Random random; // Permite generar números aleatorios. private boolean megaDisparo; /// Booleano que determina si se puede disparar el mega disparo. private boolean naveBonus; // Booleano que indica si hay una nave bonus en juego private AlienBonus alienBonus; // Nuestro objeto que va a ser la nave alien bonus. public GameScreen(spaceInvaders invaders) { super(invaders); } @Override public void show() { //Creamos las texturas, primero el fondo del juego. TexturaFondo = invaders.getManager().get("data/Background.png", Texture.class); // Asociamos la textura con la imagen correspondiente TexturaFondo.setFilter(TextureFilter.Linear, TextureFilter.Linear); // con setFilter controlamos la forma en la que la imagen se //reescala, le añadimos el parametro TextureFilter.Linear en ambos casos, para que este reescalado sea lineal. // Creamos la nave nave = new Ship(invaders, new Vector2(10,10)); //Creamos la nave en la posición de la panatalla que queremos(10, 10), y ancho y altura de la imagen. // Creamos los aliens y los introducimos en los ArrayList(Uno por los 4 tipos de alien que hay). aliensTipo1 = new ArrayList<Alien>(); // Inicializamos los ArrayList aliensTipo2 = new ArrayList<Alien>(); aliensTipo3 = new ArrayList<Alien>(); aliensTipo4 = new ArrayList<Alien>(); velocidadAliens = SPEED; // La velocidad de inicio. crearAliens(); // Crea los aliens en el juego aleatorio = new Random(); gameOver = false; marcadorDePuntos = 0; // Los puntos al empezar el juego. vidasNave = 3; // Ponemos las vidas que tiene que tener la nave. random = new Random(); // Para generar números aleatorios. // Bola que se genera en una parte aleatoria de la pantalla. bola = new Ball(invaders, new Vector2(random.nextInt(Gdx.graphics.getWidth() - invaders.getManager().get("data/bolaBalaEspecial.png", Texture.class).getWidth()), Gdx.graphics.getHeight())); naveBonus = false; } private void crearAliens() { // Crea los aliens. // Creamos los aliens tipo1 texturaAlien1 = invaders.getManager().get("data/alien1.png", Texture.class); texturaAlien1.setFilter(TextureFilter.Linear, TextureFilter.Linear); float altura = ALTURA; // La altura a la que tienen que estar los aliens en la pantalla. posicionarAliens(aliensTipo1, texturaAlien1, altura); altura = reducirAlturaAliens(texturaAlien1, altura); // Creamos los aliens tipo2 texturaAlien2 = invaders.getManager().get("data/alien2.png", Texture.class); texturaAlien2.setFilter(TextureFilter.Linear, TextureFilter.Linear); posicionarAliens(aliensTipo2, texturaAlien2, altura); altura = reducirAlturaAliens(texturaAlien2, altura); // Creamos los aliens tipo3 texturaAlien3 = invaders.getManager().get("data/alien3.png", Texture.class); texturaAlien3.setFilter(TextureFilter.Linear, TextureFilter.Linear); posicionarAliens(aliensTipo3, texturaAlien3, altura); altura = reducirAlturaAliens(texturaAlien3, altura); // Creamos los aliens tipo4 texturaAlien4 = invaders.getManager().get("data/alien4.png", Texture.class); texturaAlien4.setFilter(TextureFilter.Linear, TextureFilter.Linear); posicionarAliens(aliensTipo4, texturaAlien4, altura); actualizarDisparoNave = false; actualizarDisparoAlien = false; } private void posicionarAliens(ArrayList<Alien> aliens, Texture texturaAlien, float altura) { // Método que sirve para ubicar los aliens en la pantalla float distancia = DISTANCIA; // Distancia a la que tiene que estar cada alien en la pantalla. float limiteDerecha = MARGEN_DERECHO - ((texturaAlien.getWidth() + 5) * MAXIMO_ALIENS_FILA); // Sirve para establecer el limite de cada alien por la derecha. float limiteIzquierda = MARGEN_IZQUIERDO; // Sirve para establecer el limite de cada alien por la izquierda. for(int i = 0; i < MAXIMO_ALIENS_FILA ; i++) { aliens.add(new Alien(texturaAlien, new Vector2(distancia, altura), limiteIzquierda, limiteDerecha, velocidadAliens)); distancia = distancia + texturaAlien.getHeight() + 5; limiteDerecha = limiteDerecha + texturaAlien.getHeight() + 5; // Actalizamos los 3 valores para crear el siguiente alien. limiteIzquierda = limiteIzquierda + texturaAlien.getHeight() + 5; } } private float reducirAlturaAliens(Texture texturaAlien, float altura) { // Descender la altura de la nueva fila de aliens return altura - texturaAlien.getHeight() - 5; } @Override public void render(float delta) { Gdx.gl.glClearColor(0, 0, 0, 1); //Gdx es una clase con la que podemos acceder a variables que hacen referencia a todos los subsitemas, como son graficos, audio, ficheros, entrada y aplicaciones // gl es una variable de tipo GL, nos permite acceder a metodos de GL10, GL11 y GL20 //En este caso glClearColor es un bucle (game loop) que establecera el fondo de la pantalla negro (0,0,0) con transparencia 1 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); // Despues de la funcion anterior es necesario ejecutar esta, para que se lleve a cabo volverAlMenu(); // Método que permite volver a atras al menú principal. //Hacemos que se actualizen los parametros de la nave en la pantalla. boolean naveDispara = nave.update(); // Devuelve true si se ha disparado. // Se actualizan todos los valores de los distintos tipos de disparos. disparoNaveUpdate(naveDispara); disparoAlienUpdate(); // Actualizamos la bola del mega disparo. bolaUpdate(); // Hacemos que se actualizen los parametros de los aliens de cada tipo aliensUpdate(aliensTipo1); aliensUpdate(aliensTipo2); aliensUpdate(aliensTipo3); aliensUpdate(aliensTipo4); // Se actializa el alien bonus alienBonusUpdate(); batch.begin(); // Aqui por fin comenzamos el renderizado //Dibujamos el fondo batch.draw(TexturaFondo, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); //La dibujamos en la esquina inferior derecha, tamaño natural //Dibujamos nuestra nave nave.draw(batch); //Dibujamos la bola bola.draw(batch); //Dibujamos los aliens pintarAliens(aliensTipo1, texturaAlien1); pintarAliens(aliensTipo2, texturaAlien2); pintarAliens(aliensTipo3, texturaAlien3); pintarAliens(aliensTipo4, texturaAlien4); //Dibujamos el alien bonus if(naveBonus) alienBonus.draw(batch); //Dibujamos los disparo si hay alguno. if(actualizarDisparoNave) disparoNave.draw(batch); if(actualizarDisparoAlien) disparoAlien.draw(batch); // Pinta los puntos que se tienen en la pantalla. invaders.getFont().draw(batch, Integer.toString(marcadorDePuntos), 10, Gdx.graphics.getHeight() - 10); //Pintamos las vidas de la nave. for(int i = 0; i < vidasNave; i++) batch.draw(invaders.getManager().get("data/ship.png", Texture.class), Gdx.graphics.getWidth() - 40 - i*35, Gdx.graphics.getHeight() - 40, 30, 30); batch.end(); // Terminamos el renderizado. comprobarFinalDelJuego(); } private void bolaUpdate() { // Actualiza la bola bola.update(); if(bola.colisionConNave(nave)) { // Si colisiona con la nave megaDisparo = true; // Se activa el mega disparo bola.setPosicion(random.nextInt(Gdx.graphics.getWidth() - invaders.getManager().get("data/bolaBalaEspecial.png", Texture.class).getWidth()), Gdx.graphics.getHeight()); } else if(bola.getPosicion().y < 0 - invaders.getManager().get("data/bolaBalaEspecial.png", Texture.class).getHeight()) // Si se esconde por abajo de la pantalla. bola.setPosicion(random.nextInt(Gdx.graphics.getWidth() - invaders.getManager().get("data/bolaBalaEspecial.png", Texture.class).getWidth()), Gdx.graphics.getHeight()); } private void disparoNaveUpdate(boolean naveDispara) { // Método que actualiza el disparo de la nave. // Creamos el disparo si se ha realizado if(naveDispara && !actualizarDisparoNave) { if(megaDisparo) { disparoNave = new MegaShotShip(invaders, new Vector2(nave.getPosicion().x, nave.getAltura() + 12)); megaDisparo = false; } else disparoNave = new ShotShip(invaders, new Vector2(nave.getPosicion().x + (nave.getAnchura() / 2 - 1), nave.getAltura() + 12)); disparoNave.disparoSonido(); // Sonido del disparo. actualizarDisparoNave = true; // Esta variable sirve para no hacer un disparo hasta que se termine el actual y para actualizar los parametros del mismo. } //Hacemos que se actualizen los parametros del disparo en la pantalla si hay efectuado uno. if(actualizarDisparoNave) { disparoNave.update(); if(disparoNave.getPosicion().y + disparoNave.getAltura() > LIMITE_DISPARO)// Cuando llegue al final de la pantalla actualizarDisparoNave = false; } } private void disparoAlienUpdate() { // Método que actualiza el disparo de los aliens. // Creamos el disparo si se ha realizado if(!actualizarDisparoAlien) { ArrayList<Alien> filaDisparo = filaDeDisparo(); int alienAleatorio = aleatorio.nextInt(filaDisparo.size()); disparoAlien = new ShotAlien(invaders, new Vector2(filaDisparo.get(alienAleatorio).getPosicion().x + (filaDisparo.get(alienAleatorio).getAnchura() / 2 - 1), filaDisparo.get(alienAleatorio).getPosicion().y - 5)); disparoAlien.disparoSonido(); // Sonido del disparo. actualizarDisparoAlien = true; // Esta variable sirve para no hacer un disparo hasta que se termine el actual y para actualizar los parametros del mismo. } //Hacemos que se actualizen los parametros del disparo en la pantalla si hay efectuado uno. if(actualizarDisparoAlien) { disparoAlien.update(); if(nave.tocadoPorDisparo(disparoAlien)) { // Si el disparo toca la nave, pues pierde una vida disparoAlien.naveTocada(); nave.volverAPosicionInicial(); vidasNave--; // Disminuimos las vidas if(vidasNave == 0) // Si las vidas se quedan a 0 gameOver = true; // Perdemos } else if(disparoAlien.getPosicion().y < 0) { // Cuando llegue al final de la pantalla actualizarDisparoAlien = false; } } } private ArrayList<Alien> filaDeDisparo() { // Permite comprobar la fila mas en el sur de la pantalla para disparar. Dispara por fila siempre y cuando existan aliens en la misma if(aliensTipo4.isEmpty()) { if(aliensTipo3.isEmpty()) { if(aliensTipo2.isEmpty()) { return aliensTipo1; } else return aliensTipo2; } else return aliensTipo3; } else return aliensTipo4; } private void aliensUpdate(ArrayList<Alien> aliens) { // Esta función permite controlar los eventos que puedan pasarles a los aliens for(int i = 0; i < aliens.size(); i++) { aliens.get(i).update(); comprobarDerrota(aliens.get(i).getBordes().y); // Comprobamos si los aliens han llegado a la nave para indicar el "GameOver". if(actualizarDisparoNave && aliens.get(i).Muerto(disparoNave)) { // Si hay un disparo efectuado y le ha dado al alien marcadorDePuntos += 10; // Se aumenta en 10 la puntuación cuando se destruye un alien. aliens.remove(i); // Se destruye el alien!! disparoNave.alienMuerto(); // Permite quitar el disparo de la pantalla y hace el sonido de explosion } } } private void alienBonusUpdate() { // Método que permite actualizar los aliens if(naveBonus) { // Si existe alien bonus alienBonus.update(); if(actualizarDisparoNave && alienBonus.Muerto(disparoNave)) { // Si hay un disparo efectuado y le ha dado al alien bonus marcadorDePuntos += 100; // Se aumenta la puntuación de forma considerable naveBonus = false; disparoNave.alienMuerto(); // Permite quitar el disparo de la pantalla y hace el sonido de explosion } else if(alienBonus.getPosicion().x > Gdx.graphics.getWidth()) // Si ha pasado del límite de la pantalla se quita. naveBonus = false; } float valorDeFrecuencia = -1; if(aliensTipo1.isEmpty()) if(aliensTipo2.isEmpty()) if(aliensTipo3.isEmpty()) if(aliensTipo4.isEmpty()) valorDeFrecuencia = -1; // Valor que nunca va a tomar la operación. else valorDeFrecuencia = aliensTipo4.get(0).getContadorDeBajadas() % FRECUENCIA_ALIEN_BONUS; else valorDeFrecuencia = aliensTipo3.get(0).getContadorDeBajadas() % FRECUENCIA_ALIEN_BONUS; else valorDeFrecuencia = aliensTipo2.get(0).getContadorDeBajadas() % FRECUENCIA_ALIEN_BONUS; else valorDeFrecuencia = aliensTipo1.get(0).getContadorDeBajadas() % FRECUENCIA_ALIEN_BONUS; if(!naveBonus && valorDeFrecuencia == 0 && aliensTipo1.get(0).getContadorDeBajadas() != 0) { // Si no existe un alien bonus y las bajadas de los aliens entre la frecuencia da como resto 0 naveBonus = true; alienBonus = new AlienBonus(invaders, new Vector2(-invaders.getManager().get("data/naveAlienBonus.png", Texture.class).getWidth(), Gdx.graphics.getHeight() - invaders.getManager().get("data/naveAlienBonus.png", Texture.class).getHeight()), velocidadAliens); } } private void pintarAliens(ArrayList<Alien> aliens, Texture texturaAlien) { // Pinta los aliens en la pantalla por cada lista for(Alien alien : aliens) { alien.draw(batch); } } private void volverAlMenu() { // Método privado que tiene los botones para volver al menú durante el juego if(Gdx.input.isKeyPressed(Keys.ESCAPE) || Gdx.input.isKeyPressed(Keys.BACK) || Gdx.input.isKeyPressed(Keys.MENU)) invaders.setScreen(invaders.PRINCIPAL); } private boolean estanTodosLosAliensDestruidos() { // Si se han destruido todo los aliens. return (aliensTipo1.isEmpty() && aliensTipo2.isEmpty() && aliensTipo3.isEmpty() && aliensTipo4.isEmpty()); } private void comprobarFinalDelJuego() { // Comprueba si se ha acabado el juego if(estanTodosLosAliensDestruidos()) { // Ganaste!! velocidadAliens *= AUMENTO_DE_VELOCIDAD; // Si se destruyen todos los aliens, se aumenta la velocidad. crearAliens(); // Crear de nuevo con mas velocidad y se sigue jugando. } else if(gameOver) { // Perdiste... guardarRecord(); invaders.setScreen(invaders.GAMEOVER); } } private void guardarRecord() { // Esta función permite almacenar en el dispositivo la puntuación siempre que sea superior a las 3 mejores if(marcadorDePuntos > invaders.getPreferencias().getInteger("primerRecord", 0)) { // Si es la mayor puntuación obtenida en el juego. invaders.getPreferencias().putInteger("tercerRecord", invaders.getPreferencias().getInteger("segundoRecord", 0)); // Desplazamos los records a una posición más baja. invaders.getPreferencias().putInteger("segundoRecord", invaders.getPreferencias().getInteger("primerRecord", 0)); // El segundo al tercero, y el primero al segundo. invaders.getPreferencias().putInteger("primerRecord", marcadorDePuntos); // Introducimos en el primer record el mejor obtenido. } else if(marcadorDePuntos > invaders.getPreferencias().getInteger("segundoRecord", 0)) { invaders.getPreferencias().putInteger("tercerRecord", invaders.getPreferencias().getInteger("segundoRecord", 0)); invaders.getPreferencias().putInteger("segundoRecord", marcadorDePuntos); } else if(marcadorDePuntos > invaders.getPreferencias().getInteger("tercerRecord", 0)) invaders.getPreferencias().putInteger("tercerRecord", marcadorDePuntos); invaders.getPreferencias().flush(); } private void comprobarDerrota(float numero) { // Si algun alien ha llegado a la nave. if(numero < 50) { gameOver = true; } } @Override public void resize(int width, int height) { } @Override public void hide() { // TODO Auto-generated method stub } @Override public void pause() { // TODO Auto-generated method stub } @Override public void resume() { // TODO Auto-generated method stub } @Override public void dispose() { // TODO Auto-generated method stub } }