Package invaders101

Source Code of invaders101.Game

package invaders101;

import invaders101.spritesystem.ImageCache;
import invaders101.spritesystem.SpriteFactory;
import invaders101.entities.MovingGameEntity;
import invaders101.entities.ShotEntity;
import invaders101.entities.AlienEntity;
import invaders101.entities.ShipEntity;
import invaders101.entities.AlienBonusShip;
import invaders101.entities.BaseEntity;
import invaders101.interfaces.Drawable;
import invaders101.interfaces.Updateable;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;

/**
* Clase que controla el desarrollo del juego
* @author Alejandro Cerutti, Mauricio Blint, Patricio Marrone
*/
public class Game extends JPanel {

    private static final int WIN_LEVEL = 10;
    private enum MainMessage {

        GAME_OVER("GAME OVER!"),
        LEVEL_UP("LEVEL UP!"),
        SPACE_INVADERS("SPACE INVADERS"),
        YOU_WIN("YOU WIN!!");
        private String message;

        MainMessage(String message) {
            this.message = message;
        }

        public String getMessage() {
            return message;
        }
    }
    public static final int SCREEN_HEIGHT = 600;
    public static final int SCREEN_WIDTH = 800;
    private Random randomGenerator = new Random();
    private static SpriteFactory spriteFactory;
    /** Estrategia para la gestion del buffer, permite usar page flipping acelerado */
    private BufferStrategy strategy;
    /** True si el juego está actualmente "corriendo" */
    private boolean gameRunning = true;
    private boolean logicRequiredThisLoop = false;
    private String title;
    /** Lista de todas las entidades existentes en el juego */
    private ArrayList<BaseEntity> entities = new ArrayList();
    /** Lista de las entidades a remover del juego en el actual loop */
    private ArrayList removeList = new ArrayList();
    private ArrayList<BaseEntity> addList = new ArrayList<BaseEntity>();
    /** Entidad que representa al jugador */
    private ShipEntity ship;
    /** La velocidad a la que la nave deberia moverse (pixels/sec) */

    private boolean shouldRestart = false;

    /** Número de aliens en pantalla */
    private int alienCount;
    private long millisToNextBonus = 0;
    /** Mensaje que se muestra mientras se espera por una tecla apretada */
    private String message = "";
    private KeyInputHandler keyInputHandler;
    private ScoreHandler scoreHandler;
    private int level = 1;
    private int lives = 3;
    private MainMessage mainMessage = MainMessage.SPACE_INVADERS;

    /**
     * Constructor del juego
     * @param title
     */
    public Game(String title) {
        this.title = title;
    }

    private void processInsertionsDeletions() {
        // elimina cualquier entidad que alla sido marcada para limpiar
        if (!addList.isEmpty()) {
            entities.addAll(addList);
            addList.clear();
        }
        if (!removeList.isEmpty()) {
            entities.removeAll(removeList);
            removeList.clear();
        }
    }

    private void resetBonusTimer() {
        this.millisToNextBonus = 1000 * (int) (10 + randomGenerator.nextFloat() * 5);
    }

    private void checkForBonusAlien(long delta) {
        //Si ya existe un alien en pantalla, no realiza ninguna acción
        if (AlienBonusShip.getBonusAlienCount() > 0) {
            return;
        }
        millisToNextBonus -= delta;
        if (millisToNextBonus <= 0) {
            BaseEntity bounusAlien = new AlienBonusShip(
                    this, 50, 50,
                    0.1f + randomGenerator.nextFloat() * 0.05f);
            this.resetBonusTimer();
            this.addEntity(bounusAlien);
        }
    }

    /**
     * Limpia datos viejos e inicializa las entidades
     */
    protected void startGame() {
        if (lives == -1) {
            this.lives = 3;
            this.scoreHandler.resetScore();
            this.level = 1;
        }
        //Limpia las entidades del nivel o pantalla anterior
        for (BaseEntity entity : entities) {
            entity.onCleanUp();
        }
        addList.clear();
        removeList.clear();
        entities.clear();
        //Reinicia las entidades del juegi
        initEntities();
        keyInputHandler.resetKeys();

        keyInputHandler.setWaitingForRestart(false);
        shouldRestart = false;
    }

    public void addScore(int score) {
        scoreHandler.addScore(score);
    }

    /**
     * Inicializa el estado inicial de los aliens y la nave del jugador.
     * Cada entidad se añadirá a la lista general de las entidades en el juego.
     */
    protected void initEntities() {
        // crea la nave del jugador y la coloca en el centro de la pantalla

        ship = new ShipEntity(this, SCREEN_WIDTH / 2, SCREEN_HEIGHT - 50);
        ship.init();

        entities.add(ship);

        //crea un bloque de aliens
        alienCount = 0;
        //Separaciones en X e Y entre las naves enemigas
        int separationX = 50, separationY = 45;
        for (int row = 0; row < 3; row++) { //3
            for (int x = 0; x < 11; x++) { //11
                MovingGameEntity alien = new AlienEntity(this, 100 + (x * separationX), (100) + row * separationY);
                entities.add(alien);
                alienCount++;
            }
        }
    }

    /**
     * Notificacion de una entidad del juego que la logica
     * debe ser actualizada
     */
    public void updateLogic() {
        logicRequiredThisLoop = true;
    }

    /**
     * Elimina una entidad del juego. La misma no se movera
     * ni sera pintada
     *
     * @param entity la entidad que debe ser eliminada
     */
    public void removeEntity(BaseEntity entity) {
        entity.onCleanUp();
        removeList.add(entity);
    }

    /**
     * Añade una entidad al juego.
     * @param entity La entidad a ser añadida
     */
    public void addEntity(BaseEntity entity) {
        addList.add(entity);
    }

    /**
     * Notifica que el jugador a perdido
     */
    public void notifyDeath(String message) {
        lives = -1;
        this.message = message;
        keyInputHandler.setWaitingForKeyPress(true);
        this.mainMessage = MainMessage.GAME_OVER;
    }

    /**
     * Notifica que el jugador ganó, por lo tanto
     * todos los aliens han sido eliminados.
     */
    public void notifyWin() {
        this.mainMessage = MainMessage.YOU_WIN;
        message = "¡Felicidades! ¡Tu ganas!";
        this.shouldRestart = true;
        //Informa que debe reiniciar el juego
        this.lives = -1;
        keyInputHandler.setWaitingForKeyPress(true);
    }

    /**
     * Notifica al juego que se ha pasado al siguiente nivel
     */
    public void levelUp() {
        //Informa que el juego debe esperar a que ser presione una tecla
        keyInputHandler.setWaitingForKeyPress(true);
        //El juego debe reiniciarse el próximo ciclo
        shouldRestart = true;
        //Aumenta el contador de niveles
        if (level >= WIN_LEVEL) {
            notifyWin();
        } else {
            mainMessage = MainMessage.LEVEL_UP;
            this.message = "¡Prepárate para la próxima oleada!";
            level++;
        }
    }

    public int getLevel() {
        return level;
    }

    public int getLifes() {
        return lives;
    }

    public void loseLife() {
        lives--;
    }

    /**
     * Notifica que el alien a sido eliminado
     */
    public void notifyAlienKilled() {
        // reduce la cuenta de aliens.
        alienCount--;

        //si es 0 el jugador ganó y pasa de nivel
        if (alienCount == 0) {
            levelUp();
        }

        //los aliens que no han sido eliminados aceleraran un 2%
        AlienEntity.setGroupDx(AlienEntity.getGroupDx() * 1.02);
    }


    /**
     * Este loop corre durante todo el juego y es
     * responsable de las siguientes actividades:
     * - Determinar a qué velocidad avanza el juego para
     *   actualizar la posición de las naves
     * - Computar las colisiones
     * - Mover las entidades del juego
     * - Dibujar en pantalla los contenidos del juego.
     * - Actualizar las entidades
     */
    public void run() {
        init();
        long lastLoopTime = System.currentTimeMillis();

        // Mantiene el loop principal hasta que termine el juego
        while (gameRunning) {
            shouldRestart = shouldRestart || this.keyInputHandler.isWaitingForRestart();
            if (shouldRestart) {
                this.startGame();
            }

            // Calcula la cantidad de segundos desde el último ciclo
            long delta = System.currentTimeMillis() - lastLoopTime;
            lastLoopTime = System.currentTimeMillis();

            processInsertionsDeletions();
            this.draw();
            if (!keyInputHandler.isWaitingForKeyPress()) {
                this.computeCollisions();
                this.moveAliensForward();
                this.update(delta);
                this.checkForBonusAlien(delta);
            }

            try {
                Thread.sleep(lastLoopTime + 10 - System.currentTimeMillis());
            } catch (Exception e) {
            }
        }
    }

    /**
     * Método de fuerza bruta para colisiones, compara cada entidad en contra
     * de todas las entidades. Si alguna de ellas colision, notifica
     * a  ambas entidades que una colision a ocurrido.
     */
    private void computeCollisions() {
        for (int p = 0; p < entities.size(); p++) {
            if (entities.get(p) instanceof MovingGameEntity) {
                MovingGameEntity entity1 = (MovingGameEntity) entities.get(p);
                for (int s = p + 1; s < entities.size(); s++) {
                    if (entities.get(s) instanceof MovingGameEntity) {
                        MovingGameEntity entity2 = (MovingGameEntity) entities.get(s);
                        if (entity1.isCollidingWith(entity2)) {
                            entity1.notifyCollisionWith(entity2);
                            entity2.notifyCollisionWith(entity1);
                        }
                    }
                }
            }
        }
    }

    /**
     * Informa al juego que los aliens deben cambiar
     * de dirección en conjunto.
     */
    private void moveAliensForward() {
        if (logicRequiredThisLoop) {
            AlienEntity.revertGroupDirection();
            for (BaseEntity entity : entities) {
                if (entity instanceof AlienEntity) {
                    AlienEntity alien = (AlienEntity) entity;
                    alien.moveForward();
                }
            }
            logicRequiredThisLoop = false;
        }
    }

    /**
     * Dibuja las vidas del jugador en pantalla
     * @param ref La url de la sprite
     * @param x La posición x donde se tiene que dibujar la primera vida
     * @param y La posición y donde se tiene que dibujar la primera vida
     * @param g El contexto gráfico
     * @param vidas El número de vidas a dibujar
     */
    private void drawLives(String ref, int x, int y, Graphics g, int vidas) {
        Image life = ImageCache.getInstance().getImage(ref);
        int separation = 35;
        for (int i = 0; i < vidas; i++) {
            g.drawImage(life, x + separation * i, y, null);
        }

        if (vidas == 0) {
            g.setColor(Color.red);
            g.setFont(new Font("Arial", Font.BOLD, 20));
            g.drawString("WARNING!!!", SCREEN_HEIGHT, 534);
        }
    }

    /**
     * Dibuja los elementos gráficos del juego en pantalla
     */
    private void draw() {
        //Recupera el contexto gráfico del juego
        //Crea un contexto grafico para el drawing buffer
        Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
        g.setColor(Color.black);
        g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

        // ciclo que dibuja todas las entidades que tiene el juego
        for (int i = 0; i < entities.size(); i++) {
            if (entities.get(i) instanceof Drawable) {
                Drawable entity = (Drawable) entities.get(i);
                entity.draw(g);
            }
        }
        drawLives("sprites/life.png", SCREEN_HEIGHT, 550, g, lives);

        // Si está esperando que se presione una tecla
        // muestra un mensaje
        if (keyInputHandler.isWaitingForKeyPress()) {
            g.setColor(Color.white);
            g.setFont(new Font("Tahoma", Font.BOLD, 25));
            g.drawString(mainMessage.getMessage(), (SCREEN_WIDTH - g.getFontMetrics().stringWidth(mainMessage.getMessage())) / 2, 300);

            g.setFont(new Font("Tahoma", Font.BOLD, 16));
            g.drawString(message, (SCREEN_WIDTH - g.getFontMetrics().stringWidth(message)) / 2, 330);
            String pressKeyMessage = "Presione enter para continuar";
            g.drawString(pressKeyMessage, (SCREEN_WIDTH - g.getFontMetrics().stringWidth(pressKeyMessage)) / 2, 350);
        }
        g.setColor(Color.white);
        g.setFont(new Font("Arial", Font.BOLD, 20));
        g.drawString("Score: " + scoreHandler.getScore(), 100, 534);

        g.setColor(Color.white);
        g.setFont(new Font("Arial", Font.BOLD, 20));
        g.drawString("Level: " + level, 100, 500);


        //Terminada la etapa de dibujo, limpia los gràficos
        //y muestra los gráficos del back buffer
        g.dispose();
        strategy.show();
    }

    private void update(long delta) {
        for (int i = 0; i < entities.size(); i++) {
            Updateable entity = entities.get(i);
            entity.update(delta);
        }
        ship.hadleShipInput(keyInputHandler.isLeftPressed(), keyInputHandler.isRightPressed(),
                keyInputHandler.isFirePressed());
    }

    /**
     * Realiza la inicialización básica del juego.
     * Éste método sólo debería correr una vez por ejecución
     */
    protected void init() {
        initGameWindow();
        initEntities();
        //Llama a la inicialización de los sonidos
        SoundEffect.init();
    }

    /**
     * Prepara la ventana donde correrá el juego
     */
    protected void initGameWindow() {
        Dimension size = new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT);

        JFrame container = new JFrame(this.title);
        container.setSize(size);
        container.setPreferredSize(size);
        container.setResizable(false);


        // Añade un listener para que el programa se cierre cuando el
        // usuario cierre la ventana
        container.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        // Hace que la ventana sea visible
        container.setVisible(true);

        // crea el buffering strategy el cual va a permitir
        // manejar los gráficos acelerados
        // el parametro 2 son los buffers a utilizar
        container.createBufferStrategy(2);
        strategy = container.getBufferStrategy();

        // Asigna propiedades de dimensión al área del juego
        this.setPreferredSize(size);
        this.setMaximumSize(size);
        this.setMinimumSize(size);
        this.setSize(size);

        //Utiliza el área de juego como la hoja
        //de contenidos de la ventana
        container.setContentPane(this);

        // Desactiva el llamado a repaint automático. Los llamados
        // a paint serán hechos manualmente en modo acelerado
        this.setIgnoreRepaint(true);

        // agrega un sistema para las entradas del teclado
        // KeyInputHandler maneja la entrada del teclado
        this.addKeyListener(keyInputHandler = new KeyInputHandler(this));

        // solicita el foco de atencion para que se capturen los key events
        this.requestFocus();

        //Reinicia el temporizador del juego e inicializa el puntaje
        resetBonusTimer();
        scoreHandler = new ScoreHandler();
    }
}
TOP

Related Classes of invaders101.Game

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.