Clase 1 - Introducción a Swing y Movimiento Básico
Uso de JFrame, JPanel
Cargar imágenes con ImageIcon
Movimiento básico con teclas (uso de KeyListener)
Crear personaje y moverlo con flechas
Mini actividad: Mover personaje por la pantalla
Clase 2 - Animación por Repaint y Temporizador
Uso de Timer para animaciones
repaint() y ciclo de juego simple
Crear loop de movimiento constante (ej: enemigo o nube moviéndose)
Control de FPS básico - para regular cuántas veces por segundo se actualiza y
dibuja la pantalla. Esto asegura una experiencia visual fluida y evita que el
programa consuma demasiados recursos del sistema.
¿Para qué sirve el control de FPS?
Evita que el juego corra demasiado rápido.
Reduce el uso de CPU/GPU, manteniendo el rendimiento estable.
Sincroniza la lógica del juego y la animación con un ritmo constante.
Proporciona una experiencia más predecible para los jugadores.
actividad: Crear un objeto que se mueva solo (ej: nube o enemigo)
Clase 3 - Colisiones
Detectar colisiones entre dos objetos (Rectangle o intersects)
Crear límites de pantalla
Mini actividad: Evitar que personaje atraviese paredes o choque con un enemigo
Clase 4 - Múltiples enemigos/objetos
Manejo de arrays o listas de objetos (ArrayList de enemigos, por ejemplo)
Dibujo y movimiento de múltiples enemigos
Generar enemigos de forma aleatoria
Mini actividad: Esquivar varios enemigos que se mueven por pantalla
Clase 5 - Disparos y Ataques
Crear un proyectil (bala, disparo, etc.)
Movimiento del disparo
Detectar colisión de disparo con enemigo
Eliminar enemigo al recibir impacto
Mini actividad: Matar enemigo con un disparo
Clase 6 - Contadores, Puntos y HUD
Mostrar puntaje, vidas, tiempo en pantalla (HUD)
Crear sistema de puntos (por cada enemigo destruido)
Mostrar texto en pantalla con Graphics.drawString()
Mini actividad: Contar enemigos eliminados y mostrarlo en pantalla
Clase 7 - Menú de Inicio / Fin de Juego
Crear pantalla de inicio con opciones (Start, Exit)
Transición entre pantallas (inicio → juego → game over)
Detectar condición de derrota o victoria
Mini actividad: Mostrar “Game Over” al perder todas las vidas
Clase 8 - Examen Final + Tema: Música o Efectos Sonoros
Examen práctico: Crear un mini juego funcional con movimiento, colisiones y
puntaje
Tema nuevo: Añadir música de fondo o efectos de sonido con javax.sound.sampled
Evaluación: funcionamiento, limpieza del código, cumplimiento del objetivo
// Importamos las librerías necesarias para la interfaz gráfica, gráficos y eventos
import javax.swing.*; // Para JPanel, ImageIcon, Timer, etc.
import java.awt.*; // Para Graphics, Color, Dimension, etc.
import java.awt.event.*; // Para eventos de teclado y timer
// Clase que extiende JPanel para crear un panel personalizado donde se dibuja el juego
// Implementa KeyListener para capturar teclas y ActionListener para eventos del timer
public class GamePanel extends JPanel implements KeyListener, ActionListener {
// Variables para almacenar las imágenes del jugador y enemigo
ImageIcon jugadorImg, enemigoImg;
// Posiciones en X e Y del jugador y enemigo en la ventana
int jugadorX = 300, jugadorY = 400;
int enemigoX = 0, enemigoY = 100;
// Velocidades de movimiento del jugador y enemigo
int velocidadJugador = 5;
int velocidadEnemigo = 2;
// Timer para controlar el refresco de pantalla y animaciones
Timer timer;
// Constante para definir los cuadros por segundo (Frames Per Second)
final int FPS = 60;
// Constructor de la clase GamePanel
public GamePanel() {
// Establece el tamaño preferido del panel (ancho x alto)
setPreferredSize(new Dimension(800, 600));
// Hace que el panel pueda recibir eventos de teclado
setFocusable(true);
// Añade el escuchador de teclado para detectar pulsaciones
addKeyListener(this);
// Carga las imágenes una sola vez al iniciar el panel
jugadorImg = new ImageIcon(getClass().getResource("animal.png"));
enemigoImg = new ImageIcon(getClass().getResource("enemigo.png"));
// Inicializa el timer para llamar al método actionPerformed cada 1000/FPS
milisegundos
timer = new Timer(1000 / FPS, this);
timer.start(); // Inicia el timer
// Método que dibuja todo en el panel. Se llama automáticamente cuando hay que
repintar.
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // Limpia el dibujo anterior
// Para crear un degradado en el fondo, se usa Graphics2D que extiende a Graphics
Graphics2D g2d = (Graphics2D) g;
// Definimos dos colores para el degradado (de azul claro a azul oscuro)
Color colorInicio = new Color(135, 206, 250); // azul claro
Color colorFin = new Color(25, 25, 112); // azul oscuro
// Creamos el objeto GradientPaint para el degradado vertical del fondo
GradientPaint gp = new GradientPaint(0, 0, colorInicio, 0, getHeight(), colorFin);
// Asignamos el degradado como pintura actual para el Graphics2D
g2d.setPaint(gp);
// Pintamos un rectángulo que cubre todo el panel con el degradado
g2d.fillRect(0, 0, getWidth(), getHeight());
// Dibujamos la imagen del jugador si está cargada correctamente
if (jugadorImg != null)
// Dibuja la imagen del jugador en la posición jugadorX, jugadorY con tamaño
80x100
g.drawImage(jugadorImg.getImage(), jugadorX, jugadorY, 80, 100, this);
else {
// Si no se carga la imagen, dibuja un rectángulo rojo como sustituto
g.setColor(Color.RED);
g.fillRect(jugadorX, jugadorY, 80, 100);
}
// Dibujamos la imagen del enemigo si está cargada correctamente
if (enemigoImg != null)
// Dibuja la imagen del enemigo en la posición enemigoX, enemigoY con tamaño
150x100
g.drawImage(enemigoImg.getImage(), enemigoX, enemigoY, 150, 100, this);
else {
// Si no se carga la imagen, dibuja un óvalo gris como sustituto
g.setColor(Color.GRAY);
g.fillOval(enemigoX, enemigoY, 150, 100);
// Finalmente dibujamos el texto que muestra los FPS en la esquina superior izquierda
g.setColor(Color.WHITE);
g.drawString("FPS: " + FPS, 10, 20);
// Método que se ejecuta cada vez que el timer "dispara" un evento (cada frame)
@Override
public void actionPerformed(ActionEvent e) {
// Actualiza la posición X del enemigo para que se mueva hacia la derecha
enemigoX += velocidadEnemigo;
// Si el enemigo sale del lado derecho de la ventana, reaparece por la izquierda
if (enemigoX > getWidth()) {
enemigoX = -150; // reinicia posición (negativo para que aparezca suavemente)
}
// Solicita que el panel se repinte para actualizar la posición en pantalla
repaint();
// Método llamado cuando se presiona una tecla
@Override
public void keyPressed(KeyEvent e) {
// Detectamos qué tecla se presionó y movemos el jugador en consecuencia
if (e.getKeyCode() == KeyEvent.VK_A) jugadorX -= velocidadJugador; // mover
izquierda
if (e.getKeyCode() == KeyEvent.VK_D) jugadorX += velocidadJugador; // mover
derecha
if (e.getKeyCode() == KeyEvent.VK_W) jugadorY -= velocidadJugador; // mover arriba
if (e.getKeyCode() == KeyEvent.VK_S) jugadorY += velocidadJugador; // mover abajo
// Repinta para mostrar el movimiento del jugador
repaint();
// Método requerido por KeyListener pero no usado aquí
@Override
public void keyTyped(KeyEvent e) {}
// Método requerido por KeyListener pero no usado aquí
@Override
public void keyReleased(KeyEvent e) {}
GAME WINDOW
// Clase principal que lanza la ventana del juego
public class GameWindow {
public static void main(String[] args) {
// Crea un nuevo objeto JFrame (ventana) con el título "Mini Juego"
javax.swing.JFrame frame = new javax.swing.JFrame("Mini Juego");
// Crea una instancia del panel del juego donde se dibujará todo
GamePanel panel = new GamePanel();
// Agrega el panel a la ventana
frame.add(panel);
// Ajusta automáticamente el tamaño de la ventana al tamaño preferido del panel
(800x600)
frame.pack();
// Hace que al cerrar la ventana se termine el programa
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
// Centra la ventana en el centro de la pantalla
frame.setLocationRelativeTo(null);
// Hace visible la ventana (si no pones esto, no se muestra nada)
frame.setVisible(true);