Imagen de ejemplo del juego con sistema de disparos
Vamos a mejorar nuestro juego anterior para incluir:
Necesitarás estos archivos en la carpeta de recursos (src/main/resources/):
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;
}
}
}
Este código completo con sistema de disparos es perfecto para enseñar a tus alumnos sobre: