Fix tile rendering dimensions and alignment, update tile definitions to use height
This commit is contained in:
154
src/main.js
154
src/main.js
@@ -1,69 +1,50 @@
|
||||
|
||||
import { GameEngine } from './engine/game/GameEngine.js';
|
||||
import { GameRenderer } from './view/GameRenderer.js';
|
||||
import { CameraManager } from './view/CameraManager.js';
|
||||
import { UIManager } from './view/UIManager.js';
|
||||
import { DoorModal } from './view/DoorModal.js';
|
||||
import { MissionConfig, MISSION_TYPES } from './engine/dungeon/MissionConfig.js';
|
||||
|
||||
console.log("Initializing Warhammer Quest Engine... SYSTEM: GAME_LOOP_ARC_V1");
|
||||
window.TEXTURE_DEBUG = true;
|
||||
console.log("🏗️ Warhammer Quest - Manual Dungeon Construction");
|
||||
|
||||
// 1. Setup Mission
|
||||
const mission = new MissionConfig({
|
||||
id: 'mission_1',
|
||||
name: 'The First Dive',
|
||||
name: 'Manual Construction',
|
||||
type: MISSION_TYPES.ESCAPE,
|
||||
minTiles: 6
|
||||
minTiles: 13
|
||||
});
|
||||
|
||||
// 2. Initialize Core Systems
|
||||
const renderer = new GameRenderer('app'); // Visuals
|
||||
const cameraManager = new CameraManager(renderer); // Camera
|
||||
const game = new GameEngine(); // Logic Brain
|
||||
|
||||
// 3. Initialize UI
|
||||
// UIManager currently reads directly from DungeonGenerator for minimap
|
||||
const renderer = new GameRenderer('app');
|
||||
const cameraManager = new CameraManager(renderer);
|
||||
const game = new GameEngine();
|
||||
const ui = new UIManager(cameraManager, game);
|
||||
const doorModal = new DoorModal();
|
||||
|
||||
// Global Access for Debugging in Browser Console
|
||||
// Global Access
|
||||
window.GAME = game;
|
||||
window.RENDERER = renderer;
|
||||
|
||||
// 4. Bridge Logic & View (Event Hook)
|
||||
// When logic places a tile, we tell the renderer to spawn 3D meshes.
|
||||
// Ideally, this should be an Event in GameEngine, but we keep this patch for now to verify.
|
||||
// 3. Connect Dungeon Generator to Renderer
|
||||
const generator = game.dungeon;
|
||||
const originalPlaceTile = generator.grid.placeTile.bind(generator.grid);
|
||||
|
||||
generator.grid.placeTile = (instance, def) => {
|
||||
// 1. Execute Logic
|
||||
originalPlaceTile(instance, def);
|
||||
generator.grid.placeTile = (instance, variant, card) => {
|
||||
originalPlaceTile(instance, variant);
|
||||
|
||||
// 2. Execute Visuals
|
||||
const cells = generator.grid.getGlobalCells(def, instance.x, instance.y, instance.rotation);
|
||||
renderer.addTile(cells, def.type, def, instance);
|
||||
const cells = generator.grid.calculateCells(variant, instance.x, instance.y);
|
||||
renderer.addTile(cells, card.type, card, instance);
|
||||
|
||||
// 3. Update Exits Visuals
|
||||
setTimeout(() => {
|
||||
renderer.renderExits(generator.pendingExits);
|
||||
}, 50); // Small delay to ensure logic updated pendingExits
|
||||
renderer.renderExits(generator.availableExits);
|
||||
}, 50);
|
||||
};
|
||||
|
||||
// 5. Connect UI Buttons to Game Actions (Temporary)
|
||||
// We will add a temporary button in pure JS here or modify UIManager later.
|
||||
// For now, let's expose a global function for the UI to call if needed,
|
||||
// or simply rely on UIManager updates.
|
||||
|
||||
// 6. Start the Game
|
||||
// 5a. Bridge Game Interactions
|
||||
// 5a. Bridge Game Interactions
|
||||
// 4. Connect Player to Renderer
|
||||
game.onEntityUpdate = (entity) => {
|
||||
renderer.addEntity(entity);
|
||||
renderer.updateEntityPosition(entity);
|
||||
|
||||
// Initial Center on Player Spawn
|
||||
// Center camera on player spawn
|
||||
if (entity.id === 'p1' && !entity._centered) {
|
||||
cameraManager.centerOn(entity.x, entity.y);
|
||||
entity._centered = true;
|
||||
@@ -79,85 +60,84 @@ game.onEntitySelect = (entityId, isSelected) => {
|
||||
};
|
||||
|
||||
renderer.onHeroFinishedMove = (x, y) => {
|
||||
// x, y are World Coordinates (x, -z grid)
|
||||
// Actually, renderer returns Mesh Position.
|
||||
// Mesh X = Grid X. Mesh Z = -Grid Y.
|
||||
// Camera centerOn takes (Grid X, Grid Y).
|
||||
// So we need to convert back?
|
||||
// centerOn implementation: this.target.set(x, 0, -y);
|
||||
// If onHeroFinishedMove passes (mesh.x, -mesh.z), that is (Grid X, Grid Y).
|
||||
|
||||
// Let's verify what we passed in renderer:
|
||||
// this.onHeroFinishedMove(mesh.position.x, -mesh.position.z);
|
||||
// So if mesh is at (5, 1.5, -5), we pass (5, 5).
|
||||
// centerOn(5, 5) -> target(5, 0, -5). Correct.
|
||||
|
||||
cameraManager.centerOn(x, y);
|
||||
};
|
||||
|
||||
game.onPathChange = (path) => {
|
||||
renderer.highlightCells(path);
|
||||
// 5. Connect Generator State to UI
|
||||
generator.onStateChange = (state) => {
|
||||
console.log(`[Main] State: ${state}`);
|
||||
|
||||
if (state === 'PLACING_TILE') {
|
||||
ui.showPlacementControls(true);
|
||||
} else {
|
||||
ui.showPlacementControls(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Custom click handler that checks for doors first
|
||||
const handleCellClick = async (x, y, doorMesh) => {
|
||||
// If doorMesh is provided, user clicked directly on a door texture
|
||||
generator.onPlacementUpdate = (preview) => {
|
||||
if (preview) {
|
||||
renderer.showPlacementPreview(preview);
|
||||
ui.updatePlacementStatus(preview.isValid);
|
||||
} else {
|
||||
renderer.hidePlacementPreview();
|
||||
}
|
||||
};
|
||||
|
||||
// 6. Handle Clicks
|
||||
const handleClick = (x, y, doorMesh) => {
|
||||
// PRIORITY 1: Tile Placement Mode - ignore all clicks
|
||||
if (generator.state === 'PLACING_TILE') {
|
||||
console.log('[Main] Use placement controls to place tile');
|
||||
return;
|
||||
}
|
||||
|
||||
// PRIORITY 2: Door Click (must be adjacent to player)
|
||||
if (doorMesh && doorMesh.userData.isDoor && !doorMesh.userData.isOpen) {
|
||||
// Get player position
|
||||
const player = game.player;
|
||||
if (!player) {
|
||||
console.log('[Main] Player not found');
|
||||
return;
|
||||
}
|
||||
const doorExit = doorMesh.userData.cells[0];
|
||||
|
||||
// Check if player is adjacent to the door
|
||||
if (renderer.isPlayerAdjacentToDoor(player.x, player.y, doorMesh)) {
|
||||
// Show modal
|
||||
const confirmed = await doorModal.show('¿Quieres abrir la puerta?');
|
||||
if (game.isPlayerAdjacentToDoor(doorExit)) {
|
||||
console.log('[Main] 🚪 Opening door and drawing tile...');
|
||||
|
||||
if (confirmed) {
|
||||
// Open the door
|
||||
renderer.openDoor(doorMesh);
|
||||
// Open door visually
|
||||
renderer.openDoor(doorMesh);
|
||||
|
||||
// Trigger exploration of the next tile
|
||||
const exitCell = doorMesh.userData.cells[0];
|
||||
console.log('[Main] Opening door at exit:', exitCell);
|
||||
|
||||
// Call game logic to explore through this exit
|
||||
game.exploreExit(exitCell);
|
||||
// Get proper exit data with direction
|
||||
const exitData = doorMesh.userData.exitData;
|
||||
if (exitData) {
|
||||
generator.selectDoor(exitData);
|
||||
} else {
|
||||
console.error('[Main] Door missing exitData');
|
||||
}
|
||||
} else {
|
||||
console.log('[Main] Player is not adjacent to the door. Move closer first.');
|
||||
console.log('[Main] ⚠️ Move adjacent to the door first');
|
||||
}
|
||||
} else if (x !== null && y !== null) {
|
||||
// Normal cell click (no door involved)
|
||||
return;
|
||||
}
|
||||
|
||||
// PRIORITY 3: Normal cell click (player selection/movement)
|
||||
if (x !== null && y !== null) {
|
||||
game.onCellClick(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
renderer.setupInteraction(
|
||||
() => cameraManager.getCamera(),
|
||||
handleCellClick,
|
||||
(x, y) => game.onCellRightClick(x, y)
|
||||
handleClick,
|
||||
() => { } // No right-click
|
||||
);
|
||||
|
||||
console.log("--- Starting Game Session ---");
|
||||
// 7. Start
|
||||
console.log("--- Starting Game ---");
|
||||
game.startMission(mission);
|
||||
|
||||
// 7. Render Loop
|
||||
// 8. Render Loop
|
||||
const animate = (time) => {
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
// Update Game Logic (State Machine, Timers, etc)
|
||||
game.update(time);
|
||||
|
||||
// Update Camera Animations
|
||||
cameraManager.update(time);
|
||||
|
||||
// Update Visual Animations
|
||||
renderer.updateAnimations(time);
|
||||
|
||||
// Render Frame
|
||||
renderer.render(cameraManager.getCamera());
|
||||
};
|
||||
animate(0);
|
||||
|
||||
console.log("✅ Ready - Move barbarian next to a door and click it");
|
||||
|
||||
Reference in New Issue
Block a user