HollowBond/Public/ecma/Views/DungeonHudView.ecma.js

174 lines
7.5 KiB
JavaScript

"use strict";
const DungeonHudView = (function(){
const DungeonHudView = function(hollow_bond, dungeon){
const self = this;
let hud_container = null;
// Referencias a las etiquetas de texto del HUD
const dom = {
pos: null,
feet: null,
chunk: null,
room_id: null,
room_bounds_xz: null,
room_bounds_y: null,
room_status: null,
physics: null
};
const setup_view = () => {
// Estilos incrustados para no depender de CSS externo
const style = document.createElement("style");
style.textContent = `
.dungeon-debug-hud {
position: absolute;
top: 15px;
left: 15px;
background: rgba(10, 12, 16, 0.82);
border: 1px solid rgba(0, 188, 212, 0.35);
border-radius: 4px;
padding: 10px 14px;
font-family: 'Consolas', 'Courier New', monospace;
font-size: 11px;
color: #d1d5db;
z-index: 1000;
pointer-events: none;
line-height: 1.45;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.6);
min-width: 290px;
}
.ddh-title {
font-weight: bold;
color: #00e5ff;
letter-spacing: 1px;
margin-bottom: 6px;
border-bottom: 1px solid rgba(0, 188, 212, 0.2);
padding-bottom: 3px;
}
.ddh-row {
display: flex;
justify-content: space-between;
gap: 12px;
}
.ddh-label {
color: #8892b0;
}
.ddh-val {
color: #fff;
font-weight: bold;
}
.ddh-alert {
color: #ff5252 !important;
}
.ddh-ok {
color: #69f0ae !important;
}
.ddh-hint {
margin-top: 8px;
padding-top: 5px;
border-top: 1px dashed rgba(255, 255, 255, 0.15);
color: #ffb74d;
font-size: 10px;
}
`;
document.head.appendChild(style);
hud_container = document.createElement("div");
hud_container.className = "dungeon-debug-hud";
hud_container.innerHTML = `
<div class="ddh-title">TELEMETRÍA DEL JUGADOR</div>
<div class="ddh-row"><span class="ddh-label">Cámara (X, Y, Z):</span><span class="ddh-val" id="ddh-pos">-</span></div>
<div class="ddh-row"><span class="ddh-label">Pies Y (Piso Est.):</span><span class="ddh-val" id="ddh-feet">-</span></div>
<div class="ddh-row"><span class="ddh-label">Chunk activo:</span><span class="ddh-val" id="ddh-chunk">-</span></div>
<div class="ddh-title" style="margin-top: 6px; color: #ffd54f;">SALA ACTUAL</div>
<div class="ddh-row"><span class="ddh-label">ID Sala:</span><span class="ddh-val" id="ddh-room-id">-</span></div>
<div class="ddh-row"><span class="ddh-label">Cota XZ Sala:</span><span class="ddh-val" id="ddh-bounds-xz">-</span></div>
<div class="ddh-row"><span class="ddh-label">Cota Y Sala (Piso):</span><span class="ddh-val" id="ddh-bounds-y">-</span></div>
<div class="ddh-row"><span class="ddh-label">Dentro del Collider:</span><span class="ddh-val" id="ddh-room-status">-</span></div>
<div class="ddh-title" style="margin-top: 6px; color: #b388ff;">FÍSICAS / ESTADO</div>
<div class="ddh-row"><span class="ddh-label">Suelo firme / Vel Y:</span><span class="ddh-val" id="ddh-physics">-</span></div>
<div class="ddh-hint">[WASD] Moverse | [Espacio] Saltar | [Shift] Correr | [Ratón] Mirar</div>
`;
hollow_bond.item_self.appendChild(hud_container);
dom.pos = hud_container.querySelector("#ddh-pos");
dom.feet = hud_container.querySelector("#ddh-feet");
dom.chunk = hud_container.querySelector("#ddh-chunk");
dom.room_id = hud_container.querySelector("#ddh-room-id");
dom.room_bounds_xz = hud_container.querySelector("#ddh-bounds-xz");
dom.room_bounds_y = hud_container.querySelector("#ddh-bounds-y");
dom.room_status = hud_container.querySelector("#ddh-room-status");
dom.physics = hud_container.querySelector("#ddh-physics");
};
this.tick = () => {
if(!dungeon || !dungeon.camera || !hud_container) return;
const pos = dungeon.camera.position;
const floor_h = hollow_bond.room_height || 3;
const controls = hollow_bond.controls?.game;
const eye_height = controls?.current_height || 1.75;
const feet_y = pos.y - eye_height;
const estimated_floor = Math.round(feet_y / floor_h);
// 1. Posición y piso estimado
dom.pos.textContent = `${pos.x.toFixed(2)}, ${pos.y.toFixed(2)}, ${pos.z.toFixed(2)}`;
dom.feet.textContent = `${feet_y.toFixed(2)}m (Piso: ${estimated_floor})`;
// 2. Coordenadas de Chunk
const c = dungeon.current_chunk;
dom.chunk.textContent = `[${c.x}, ${c.y}, ${c.z}]`;
// 3. Sala activa
const cur_room = dungeon.current_room;
if(cur_room && cur_room.model){
const m = cur_room.model;
const room_py = Math.round(m.y / m.height);
const is_inside = cur_room.collider ? cur_room.collider.contains(pos.x, feet_y, pos.z) : false;
dom.room_id.textContent = m.id;
dom.room_bounds_xz.textContent = `X:[${m.x}..${(m.x + m.width)}] Z:[${m.z}..${(m.z + m.depth)}]`;
dom.room_bounds_y.textContent = `Y:[${m.y}..${(m.y + m.height)}] (Piso: ${room_py})`;
if(is_inside){
dom.room_status.textContent = "SÍ (OK)";
dom.room_status.className = "ddh-val ddh-ok";
} else {
dom.room_status.textContent = "⚠️ FUERA DE LÍMITES";
dom.room_status.className = "ddh-val ddh-alert";
}
} else {
dom.room_id.textContent = "SIN ASIGNAR";
dom.room_bounds_xz.textContent = "-";
dom.room_bounds_y.textContent = "-";
dom.room_status.textContent = "⚠️ EN EL VACÍO";
dom.room_status.className = "ddh-val ddh-alert";
}
// 4. Estado de físicas
if(controls){
const grounded_str = controls.is_grounded ? "Suelo: SÍ" : "Suelo: NO";
const vel_str = `VelY: ${(controls.velocity_y || 0).toFixed(2)}`;
dom.physics.textContent = `${grounded_str} | ${vel_str}`;
dom.physics.className = controls.is_grounded ? "ddh-val ddh-ok" : "ddh-val";
}
};
this.destroy = () => {
if(hud_container && hud_container.parentNode){
hud_container.parentNode.removeChild(hud_container);
hud_container = null;
}
};
setup_view();
};
return DungeonHudView;
})();