Guía para Crear un Juego con Sistema de Disparos en Java

Juego Java con sistema de disparos

Imagen de ejemplo del juego con sistema de disparos

¿Qué vamos a hacer?

Vamos a mejorar nuestro juego anterior para incluir:

Paso 1: Preparar los recursos

Necesitarás estos archivos en la carpeta de recursos (src/main/resources/):

Paso 2: Código completo con sistema de disparos

Crea una nueva clase llamada JuegoConDisparos y copia el siguiente código:


package com.mycompany.juegodisparos;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.sound.sampled.*;

public class JuegoConDisparos extends JFrame {
    // Jugador
    private int jugadorX = 180;
    private int jugadorY = 250;
    private final int VELOCIDAD_JUGADOR = 5;
    private int vidas = 3;
    private int puntuacion = 0;
    
    // Balas
    private List<Bala> balas = new ArrayList<>();
    private final int VELOCIDAD_BALA = 7;
    
    // Enemigos
    private List<Enemigo> enemigos = new ArrayList<>();
    private List<Particula> particulas = new ArrayList<>();
    private final int VELOCIDAD_ENEMIGOS = 2;
    private boolean enemigosDerecha = true;
    
    // Tamaño de la ventana
    private final int ANCHO = 400;
    private final int ALTO = 400;
    
    // Sonidos
    private Clip sonidoExplosion;
    private Clip sonidoDisparo;
    
    private final JPanel panelJuego;
    
    public JuegoConDisparos() {
        setTitle("Juego con Sistema de Disparos");
        setSize(ANCHO, ALTO);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        
        // Cargar sonidos
        cargarSonidos();
        
        // Crear enemigos
        crearEnemigos();
        
        // Crear un JPanel personalizado
        panelJuego = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                dibujarJugador(g);
                dibujarBalas(g);
                dibujarEnemigos(g);
                dibujarParticulas(g);
                dibujarHUD(g);
            }
        };
        
        panelJuego.setBackground(Color.BLACK);
        add(panelJuego);
        
        // Temporizador principal del juego
        Timer timerJuego = new Timer(16, e -> {
            moverEnemigos();
            moverBalas();
            moverParticulas();
            verificarColisiones();
            panelJuego.repaint();
        });
        timerJuego.start();
        
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_LEFT:
                    case KeyEvent.VK_A:
                        jugadorX -= VELOCIDAD_JUGADOR;
                        break;
                    case KeyEvent.VK_RIGHT:
                    case KeyEvent.VK_D:
                        jugadorX += VELOCIDAD_JUGADOR;
                        break;
                    case KeyEvent.VK_UP:
                    case KeyEvent.VK_W:
                        jugadorY -= VELOCIDAD_JUGADOR;
                        break;
                    case KeyEvent.VK_DOWN:
                    case KeyEvent.VK_S:
                        jugadorY += VELOCIDAD_JUGADOR;
                        break;
                    case KeyEvent.VK_SPACE:
                        disparar();
                        break;
                }
                
                // Limitar movimiento del jugador
                jugadorX = Math.max(10, Math.min(jugadorX, ANCHO - 50));
                jugadorY = Math.max(10, Math.min(jugadorY, ALTO - 50));
                
                panelJuego.repaint();
            }
        });
    }
    
    private void cargarSonidos() {
        try {
            // Sonido de explosión
            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(
                getClass().getResource("/explosion.wav"));
            sonidoExplosion = AudioSystem.getClip();
            sonidoExplosion.open(audioInputStream);
            
            // Sonido de disparo
            audioInputStream = AudioSystem.getAudioInputStream(
                getClass().getResource("/disparo.wav"));
            sonidoDisparo = AudioSystem.getClip();
            sonidoDisparo.open(audioInputStream);
        } catch (Exception e) {
            System.out.println("Error al cargar los sonidos: " + e.getMessage());
        }
    }
    
    private void crearEnemigos() {
        int espacio = 70;
        for (int i = 0; i < 4; i++) {
            enemigos.add(new Enemigo(50 + i * espacio, 50));
        }
    }
    
    private void dibujarJugador(Graphics g) {
        // Dibujar nave del jugador
        g.setColor(Color.GREEN);
        
        // Cuerpo principal de la nave (3x3 cuadrados)
        g.fillRect(jugadorX, jugadorY, 30, 30);
        
        // Punta de la nave
        g.fillRect(jugadorX + 10, jugadorY - 10, 10, 10);
        
        // Alas de la nave
        g.fillRect(jugadorX - 10, jugadorY + 10, 10, 10);
        g.fillRect(jugadorX + 30, jugadorY + 10, 10, 10);
    }
    
    private void dibujarBalas(Graphics g) {
        g.setColor(Color.YELLOW);
        for (Bala bala : balas) {
            g.fillRect(bala.x, bala.y, bala.ancho, bala.alto);
        }
    }
    
    private void dibujarEnemigos(Graphics g) {
        g.setColor(Color.BLUE);
        for (Enemigo enemigo : enemigos) {
            // Dibujar enemigo (2x2 cuadrados)
            g.fillRect(enemigo.x, enemigo.y, 20, 20);
            g.fillRect(enemigo.x + 20, enemigo.y, 20, 20);
            g.fillRect(enemigo.x, enemigo.y + 20, 20, 20);
            g.fillRect(enemigo.x + 20, enemigo.y + 20, 20, 20);
        }
    }
    
    private void dibujarParticulas(Graphics g) {
        g.setColor(Color.RED);
        for (Particula particula : particulas) {
            g.fillRect(particula.x, particula.y, particula.tamano, particula.tamano);
        }
    }
    
    private void dibujarHUD(Graphics g) {
        g.setColor(Color.WHITE);
        g.drawString("Vidas: " + vidas, 10, 20);
        g.drawString("Puntuación: " + puntuacion, ANCHO - 120, 20);
    }
    
    private void disparar() {
        // Crear nueva bala en la posición del jugador
        int balaX = jugadorX + 15; // Centrada en la nave
        int balaY = jugadorY - 10; // Desde la punta de la nave
        balas.add(new Bala(balaX, balaY));
        
        // Reproducir sonido de disparo
        if (sonidoDisparo != null) {
            sonidoDisparo.setFramePosition(0);
            sonidoDisparo.start();
        }
    }
    
    private void moverEnemigos() {
        boolean cambiarDireccion = false;
        
        // Mover todos los enemigos
        for (Enemigo enemigo : enemigos) {
            if (enemigosDerecha) {
                enemigo.x += VELOCIDAD_ENEMIGOS;
                if (enemigo.x > ANCHO - 40) {
                    cambiarDireccion = true;
                }
            } else {
                enemigo.x -= VELOCIDAD_ENEMIGOS;
                if (enemigo.x < 0) {
                    cambiarDireccion = true;
                }
            }
        }
        
        // Cambiar dirección si es necesario
        if (cambiarDireccion) {
            enemigosDerecha = !enemigosDerecha;
            // Mover enemigos hacia abajo un poco
            for (Enemigo enemigo : enemigos) {
                enemigo.y += 10;
                
                // Verificar si los enemigos llegaron muy abajo
                if (enemigo.y > ALTO - 100) {
                    perderVida();
                    enemigo.y = 50; // Resetear posición
                }
            }
        }
    }
    
    private void moverBalas() {
        for (int i = balas.size() - 1; i >= 0; i--) {
            Bala bala = balas.get(i);
            bala.y -= VELOCIDAD_BALA;
            
            // Eliminar balas que salen de la pantalla
            if (bala.y < 0) {
                balas.remove(i);
            }
        }
    }
    
    private void moverParticulas() {
        for (int i = particulas.size() - 1; i >= 0; i--) {
            Particula p = particulas.get(i);
            p.x += p.velX;
            p.y += p.velY;
            
            // Eliminar partículas que salen de la pantalla
            if (p.x < 0 || p.x > ANCHO || p.y < 0 || p.y > ALTO) {
                particulas.remove(i);
            }
        }
    }
    
    private void verificarColisiones() {
        Rectangle jugadorRect = new Rectangle(jugadorX, jugadorY, 40, 40);
        
        // Verificar colisión jugador-enemigo
        for (int i = enemigos.size() - 1; i >= 0; i--) {
            Enemigo enemigo = enemigos.get(i);
            Rectangle enemigoRect = new Rectangle(enemigo.x, enemigo.y, 40, 40);
            
            if (jugadorRect.intersects(enemigoRect)) {
                explotarEnemigo(i);
                perderVida();
            }
        }
        
        // Verificar colisión bala-enemigo
        for (int i = balas.size() - 1; i >= 0; i--) {
            Bala bala = balas.get(i);
            Rectangle balaRect = new Rectangle(bala.x, bala.y, bala.ancho, bala.alto);
            
            for (int j = enemigos.size() - 1; j >= 0; j--) {
                Enemigo enemigo = enemigos.get(j);
                Rectangle enemigoRect = new Rectangle(enemigo.x, enemigo.y, 40, 40);
                
                if (balaRect.intersects(enemigoRect)) {
                    explotarEnemigo(j);
                    balas.remove(i);
                    puntuacion += 100;
                    break; // Una bala solo puede destruir un enemigo
                }
            }
        }
    }
    
    private void explotarEnemigo(int indiceEnemigo) {
        Enemigo enemigo = enemigos.get(indiceEnemigo);
        
        // Reproducir sonido de explosión
        if (sonidoExplosion != null) {
            sonidoExplosion.setFramePosition(0);
            sonidoExplosion.start();
        }
        
        // Crear partículas de explosión
        crearExplosion(enemigo.x, enemigo.y);
        
        // Eliminar el enemigo
        enemigos.remove(indiceEnemigo);
        
        // Si no quedan enemigos, crear nuevos
        if (enemigos.isEmpty()) {
            crearEnemigos();
        }
    }
    
    private void crearExplosion(int x, int y) {
        Random rand = new Random();
        // Crear 16 partículas (los 4 cuadrados del enemigo divididos en 4 cada uno)
        for (int i = 0; i < 16; i++) {
            particulas.add(new Particula(
                x + rand.nextInt(40),
                y + rand.nextInt(40),
                rand.nextInt(5) + 2,
                rand.nextInt(5) - 2,
                rand.nextInt(5) - 2
            ));
        }
    }
    
    private void perderVida() {
        vidas--;
        
        // Verificar si el juego terminó
        if (vidas <= 0) {
            JOptionPane.showMessageDialog(this, 
                "¡Game Over!\nPuntuación final: " + puntuacion);
            System.exit(0);
        }
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JuegoConDisparos juego = new JuegoConDisparos();
            juego.setVisible(true);
        });
    }
    
    // Clase interna para representar enemigos
    class Enemigo {
        int x;
        int y;
        
        Enemigo(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    
    // Clase interna para representar balas
    class Bala {
        int x;
        int y;
        final int ancho = 5;
        final int alto = 15;
        
        Bala(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    
    // Clase interna para partículas de explosión
    class Particula {
        int x;
        int y;
        int tamano;
        int velX;
        int velY;
        
        Particula(int x, int y, int tamano, int velX, int velY) {
            this.x = x;
            this.y = y;
            this.tamano = tamano;
            this.velX = velX;
            this.velY = velY;
        }
    }
}
    

Paso 3: Explicación de las nuevas características

1. Sistema de disparos

2. Colisiones bala-enemigo

3. Sistema de puntuación

4. Mejoras adicionales

Paso 4: Ejecutar el programa

  1. Coloca los archivos de sonido en src/main/resources/
  2. Ejecuta el programa
  3. Usa WASD o flechas para moverte
  4. Presiona ESPACIO para disparar
  5. Destruye enemigos para ganar puntos
  6. Evita que los enemigos lleguen abajo o choquen contigo

Consejos para la clase:

Posibles mejoras adicionales

¡Listo para la clase!

Este código completo con sistema de disparos es perfecto para enseñar a tus alumnos sobre: