Compare commits
9 Commits
7cc92da012
...
v0.1-engin
| Author | SHA1 | Date | |
|---|---|---|---|
| 57f6312a5a | |||
| 5852a972f4 | |||
| 8025d66fc4 | |||
| ea3813213a | |||
| 0e5b885236 | |||
| 3c599093cf | |||
| 12fb18b1de | |||
| e47b2eeba0 | |||
| 21e85915e9 |
48
DEVLOG.md
Normal file
48
DEVLOG.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Devlog del Proyecto: Masmorres (Physical-Web Crawler)
|
||||
|
||||
Este documento sirve para llevar un control diario del desarrollo, decisiones técnicas y nuevas funcionalidades implementadas en el proyecto.
|
||||
|
||||
## [2025-12-23] - Interacción con Puertas y Navegación
|
||||
|
||||
### Funcionalidades Implementadas
|
||||
- **Sistema de Puertas Interactivas:**
|
||||
- Se eliminó la transición automática entre salas al pisar una puerta.
|
||||
- Ahora las puertas actúan como bloqueos físicos hasta que son "abiertas" explícitamente.
|
||||
- Lógica de selección: Click en una puerta cerrada para seleccionarla (feedback visual amarillo).
|
||||
- **Modal de Interacción:**
|
||||
- Al mover una unidad adyacente a una puerta seleccionada, se dispara un modal UI: "¿Quieres abrir la puerta?".
|
||||
- **Confirmar:** La puerta visual se oculta, la sala destino se renderiza (si no lo estaba) y se permite el paso.
|
||||
- **Cancelar:** Se deselecciona la puerta y se mantiene cerrada.
|
||||
|
||||
### Cambios Técnicos
|
||||
- Modificado `main.js` para incluir `checkDoorInteraction` al finalizar el movimiento.
|
||||
- Nuevo estado en `SESSION`: `selectedDoorId`.
|
||||
- Actualización de `isWalkable` para considerar el estado `isOpen` de las puertas.
|
||||
|
||||
## [2025-12-20] - Sistema Visual Dinámico (Dynamic Wall Opacity)
|
||||
|
||||
### Funcionalidades Implementadas
|
||||
- **Opacidad de Muros Contextual:**
|
||||
- Los muros ahora ajustan su opacidad dinámicamente basándose en la rotación de la cámara (N, S, E, W) para evitar obstruir la visión del jugador.
|
||||
- **Regla General:** Los muros "frontales" a la cámara se vuelven semitransparentes (50%), mientras que los "traseros" permanecen opacos.
|
||||
|
||||
### Cambios Técnicos
|
||||
- Implementada función `getWallOpacity(wallSide, viewDirection)`.
|
||||
- Integración en `setCameraView` para refrescar opacidades al girar la vista.
|
||||
- Los muros ahora tienen la propiedad `userData.wallSide` asignada durante la generación.
|
||||
|
||||
## [2025-12-19] - Feedback de Selección y UI
|
||||
|
||||
### Funcionalidades Implementadas
|
||||
- **Resaltado de Selección (Highlighting):**
|
||||
- Unidades y objetos interactivos ahora muestran un aura/color amarillo al ser seleccionados.
|
||||
- Opacidad reducida al 50% para indicar estado de selección activo.
|
||||
- **Mejoras de Animación:**
|
||||
- Refinamiento del "salto" de los standees al moverse entre casillas.
|
||||
|
||||
## [Inicio del Proyecto] - Manifiesto y Core Loop
|
||||
|
||||
### Visión General
|
||||
- Definido el **Manifiesto Técnico (v2.0)**: Visión de un "Puente Híbrido" entre juego de mesa físico y motor narrativo digital (LLM).
|
||||
- **Generación Procedural:** Algoritmo de mazmorras basado en tiles de 4x4 con expansión orgánica.
|
||||
- **Motor Gráfico:** Three.js con cámara isométrica ortográfica y controles restringidos (N, S, E, W).
|
||||
49
index.html
49
index.html
@@ -1,19 +1,36 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Masmorres Isometric View</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<div id="compass">
|
||||
<div id="compass-n" class="compass-btn active" data-direction="N">N</div>
|
||||
<div id="compass-s" class="compass-btn" data-direction="S">S</div>
|
||||
<div id="compass-e" class="compass-btn" data-direction="E">E</div>
|
||||
<div id="compass-w" class="compass-btn" data-direction="W">W</div>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Masmorres Isometric View</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<div id="hud">
|
||||
<div id="minimap-container">
|
||||
<canvas id="minimap"></canvas>
|
||||
</div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
<div id="compass">
|
||||
<div class="compass-btn" data-dir="N">N</div>
|
||||
<div class="compass-row">
|
||||
<div class="compass-btn" data-dir="W">W</div>
|
||||
<div class="compass-btn" data-dir="E">E</div>
|
||||
</div>
|
||||
<div class="compass-btn" data-dir="S">S</div>
|
||||
</div>
|
||||
<div id="door-modal" class="hidden">
|
||||
<div class="modal-content">
|
||||
<p>¿Quieres abrir la puerta?</p>
|
||||
<button id="btn-open-yes">Sí</button>
|
||||
<button id="btn-open-no">No</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
58
manifest.md
58
manifest.md
@@ -0,0 +1,58 @@
|
||||
# Manifiesto Técnico: Proyecto "Physical-Web Crawler" (v2.0)
|
||||
|
||||
## 1. Visión del Sistema: El Puente Híbrido
|
||||
|
||||
El objetivo es construir un ecosistema de juego donde el software no sea un simple árbitro de reglas, sino un **Director de Juego (DM) proactivo**. El sistema debe coordinar tres realidades:
|
||||
|
||||
1. **Plano Físico:** El tablero táctil, piezas impresas y la disposición espacial real del jugador.
|
||||
2. **Plano Narrativo (LLM):** Un motor de inteligencia artificial que genera tramas, diálogos y consecuencias basadas en la agencia del jugador.
|
||||
3. **Plano de Control (Web/Mobile):** La interfaz técnica que traduce las acciones físicas en datos y las respuestas de la IA en instrucciones visuales y mecánicas.
|
||||
|
||||
## 2. Motor de Narrativa Emergente (AI-DM)
|
||||
|
||||
A diferencia de los juegos de mazmorreo tradicionales con eventos pre-escritos, este sistema integra una **API de inferencia LLM (Self-hosted)** para gestionar la no-linealidad.
|
||||
|
||||
### 2.1. Procesamiento de Intenciones
|
||||
|
||||
El jugador no se limita a opciones predefinidas (A, B o C). A través de la interfaz móvil, puede proponer acciones creativas. El sistema procesará estas entradas mediante:
|
||||
|
||||
* **Prompt Engineering Dinámico:** Se enviará al LLM el estado actual de la mazmorra, la salud del grupo y el inventario, junto con la acción propuesta.
|
||||
* **Generación de Consecuencias:** La IA determinará el éxito o fracaso narrativo, instruyendo al Host para alterar el entorno (ej: "La puerta se bloquea, debes buscar otra salida" o "El enemigo decide parlamentar").
|
||||
|
||||
### 2.2. Arquitectura de IA Económica (Self-Hosted)
|
||||
|
||||
Para garantizar la viabilidad del prototipo y la privacidad de los datos, se optará por soluciones de código abierto:
|
||||
|
||||
* **Motor:** Inferencia mediante *Ollama* o *LocalAI* ejecutando modelos como Llama 3 o Mistral (quantized para latencia mínima).
|
||||
* **Context Management:** Uso de una base de datos vectorial (RAG) ligera para mantener la memoria a largo plazo de la campaña sin saturar la ventana de contexto del modelo.
|
||||
|
||||
## 3. Generación de Espacio Físico No Lineal
|
||||
|
||||
La mazmorra no es un mapa estático, sino un organismo que crece según las decisiones de los jugadores.
|
||||
|
||||
* **Geometría Reactiva:** Si los jugadores deciden retroceder o buscar una ruta alternativa no prevista, el motor de generación de losetas recalcula las probabilidades de conexión basándose en la "intención narrativa" dictada por la IA.
|
||||
* **Mapeado de Colisión Espacial:** El sistema mantiene un gemelo digital de la mesa física. Antes de proponer la colocación de una loseta física (puerta, pasillo, sala), el algoritmo de validación asegura que el espacio físico virtualizado no esté ocupado, garantizando que la expansión sea físicamente posible en la mesa real.
|
||||
|
||||
## 4. Multimedia y Carga Atmosférica
|
||||
|
||||
El Host (PC/Tablet) actúa como el terminal audiovisual de la IA.
|
||||
|
||||
* **Narrativa Multimodal:** La IA genera descripciones que se transforman en voz (TTS) y disparan activos visuales (vídeo/imagen) coherentes con el bioma actual de la mazmorra.
|
||||
* **Dinámica Ambiental:** El audio ambiente y la iluminación de la interfaz mutan en tiempo real según el nivel de peligro o la tensión narrativa detectada por el LLM.
|
||||
|
||||
## 5. El Rol del Jugador: Agencia Total
|
||||
|
||||
El manifiesto establece que el jugador es el motor de la partida:
|
||||
|
||||
1. **Decisión:** El jugador propone una acción (vía voz o texto en el móvil).
|
||||
2. **Interpretación:** La IA valida la acción contra las estadísticas del personaje y el contexto de la sala.
|
||||
3. **Ejecución:** El sistema instruye al jugador sobre qué cambios debe realizar en el tablero físico (colocar nuevas losetas, retirar enemigos, mover atrezzo).
|
||||
|
||||
## 6. Escalabilidad Multijugador
|
||||
|
||||
El sistema debe soportar sesiones síncronas donde:
|
||||
|
||||
* Cada móvil es una extensión de la voluntad del jugador.
|
||||
* El Host centraliza la visión colectiva y la interacción de la IA con el grupo, permitiendo debates entre jugadores que la IA puede "escuchar" e interpretar para ajustar la dificultad o la trama.
|
||||
|
||||
---
|
||||
835
src/main.js
835
src/main.js
File diff suppressed because it is too large
Load Diff
105
src/style.css
105
src/style.css
@@ -25,9 +25,47 @@ canvas {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* HUD Wrapper */
|
||||
#hud {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
/* Dejar pasar clics al juego 3D */
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
/* UI Elements inside HUD (reactivate pointer events) */
|
||||
#hud>* {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* Minimap */
|
||||
#minimap-container {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
border: 2px solid #444;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#minimap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Compass UI */
|
||||
#compass {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
width: 100px;
|
||||
@@ -36,7 +74,6 @@ canvas {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-template-rows: 1fr 1fr 1fr;
|
||||
gap: 2px;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.compass-btn {
|
||||
@@ -84,4 +121,66 @@ canvas {
|
||||
#compass-w {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
}
|
||||
/* Modal Styles */
|
||||
#door-modal {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 2000;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
#door-modal.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: #2a2a2a;
|
||||
padding: 20px;
|
||||
border: 2px solid #555;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.modal-content p {
|
||||
margin-bottom: 20px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.modal-content button {
|
||||
padding: 8px 20px;
|
||||
margin: 0 10px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
#btn-open-yes {
|
||||
background: #4CAF50;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#btn-open-yes:hover {
|
||||
background: #45a049;
|
||||
}
|
||||
|
||||
#btn-open-no {
|
||||
background: #f44336;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#btn-open-no:hover {
|
||||
background: #d32f2f;
|
||||
}
|
||||
|
||||
|
||||
124
src/style.css.bak
Normal file
124
src/style.css.bak
Normal file
@@ -0,0 +1,124 @@
|
||||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
color-scheme: light dark;
|
||||
background-color: #242424;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
overflow: hidden;
|
||||
/* Evitar scrollbars por el canvas */
|
||||
}
|
||||
|
||||
#app {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
canvas {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* HUD Wrapper */
|
||||
#hud {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
/* Dejar pasar clics al juego 3D */
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
/* UI Elements inside HUD (reactivate pointer events) */
|
||||
#hud>* {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* Minimap */
|
||||
#minimap-container {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
border: 2px solid #444;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#minimap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Compass UI */
|
||||
#compass {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-template-rows: 1fr 1fr 1fr;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.compass-btn {
|
||||
background: rgba(50, 50, 50, 0.8);
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.compass-btn:hover {
|
||||
background: rgba(70, 70, 70, 0.9);
|
||||
border-color: rgba(255, 255, 255, 0.5);
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.compass-btn.active {
|
||||
background: rgba(255, 200, 0, 0.9);
|
||||
border-color: rgba(255, 220, 0, 1);
|
||||
color: rgba(0, 0, 0, 1);
|
||||
box-shadow: 0 0 15px rgba(255, 200, 0, 0.6);
|
||||
}
|
||||
|
||||
#compass-n {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
#compass-s {
|
||||
grid-column: 2;
|
||||
grid-row: 3;
|
||||
}
|
||||
|
||||
#compass-e {
|
||||
grid-column: 3;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
#compass-w {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
Reference in New Issue
Block a user