Modo Un Jugador - vykymoon/rpg-character-creator GitHub Wiki
Desde la galería, Jugar ▶ abre un mapa donde el personaje elegido se mueve libremente y puede entrar en un encuentro. Paquete: com.proyecto.rpg.game + ui/PlayController.
Controles
| Tecla | Acción |
|---|---|
| W / A / S / D | Mover arriba / izquierda / abajo / derecha |
| E | Abrir/cerrar el inventario (mientras está abierto no hay movimiento) |
Componentes
| Clase | Rol |
|---|---|
PlayController |
Controlador de play.fxml: crea el contexto, el loop y el renderizado |
PlayContext |
Agrupa Player, GameMap y si el inventario está abierto |
Player |
Posición (x, y) en píxeles, tamaño 40 px, velocidad 180 px/s |
game.GameMap |
Límites del mapa; clampX/clampY impiden salirse |
InputHandler |
Teclas pulsadas → Command (patrón Command) |
Command / MoveCommand |
MoveCommand(dx, dy) mueve velocidad × Δt píxeles |
MapRenderer |
Dibuja /sprites/map/background.jpg (o limpia el lienzo si falta) |
EncounterZone |
Zona elíptica que dispara el encuentro |
InventoryOverlay |
Panel de inventario estilo pergamino |
Game loop
PlayController usa un AnimationTimer. En cada frame:
Δt = (now - lastNanos) / 1e9
inputHandler.tick(context, Δt) // ejecuta MoveCommand por cada tecla pulsada
render() // fondo + zona + avatar del jugador
checkEncounter() // ¿el centro del jugador está en la zona?
El movimiento usa delta time, por lo que la velocidad es la misma sin importar los FPS.
Inicialización
- El mapa tiene el tamaño del
Canvas. - El jugador aparece en el centro del mapa.
- La
EncounterZone(90×70 px) se coloca centrada abajo, a 20 px del borde inferior, como "salida" al final del camino. - El avatar del jugador es la foto de su raza (
RaceAvatarLoader).
Inventario
InventoryOverlay es un VBox (máx. 340×440) superpuesto sobre el mapa con:
- Cabecera: foto de la raza, nombre y "Raza · Clase".
- Grilla VESTUARIO con un slot de 56 px por pieza equipada (sprite vía
SpriteLoader) y tooltip. Si no hay piezas: "Sin vestuario equipado".
Encuentro y combate
Cuando el centro del jugador entra en la EncounterZone, el loop se detiene y se navega a battle.fxml con BattleController.
- Muestra "¡Un enemigo apareció!", la imagen del enemigo y su nombre.
- El enemigo se define solo por el nombre de su PNG en
/sprites/battle/(por defectoenemy.png). El nombre visible sale del archivo:lobo_negro.png→ "Un lobo negro". Si falta la imagen, se oculta sin dejar hueco. - Para otro enemigo:
new BattleController(character, "lobo_negro.png"). - Huir vuelve a la galería.
- Combatir es un placeholder (
TODO): la lógica de turnos no está implementada.
Salir
El botón "atrás" (onBack) detiene el loop y vuelve a la galería.