versión inicial del juego

This commit is contained in:
2025-12-30 23:24:58 +01:00
commit 7dbc77e75a
34 changed files with 1589 additions and 0 deletions

150
src/view/CameraManager.js Normal file
View File

@@ -0,0 +1,150 @@
import * as THREE from 'three';
import { DIRECTIONS } from '../engine/dungeon/Constants.js';
export class CameraManager {
constructor(renderer) {
this.renderer = renderer; // Reference to GameRenderer to access scenes/resize if needed
// Configuration
this.zoomLevel = 20; // Orthographic zoom factor
this.aspect = window.innerWidth / window.innerHeight;
// Isometric Setup: Orthographic Camera
// Left, Right, Top, Bottom, Near, Far
// Dimensions determined by zoomLevel and aspect
this.camera = new THREE.OrthographicCamera(
-this.zoomLevel * this.aspect,
this.zoomLevel * this.aspect,
this.zoomLevel,
-this.zoomLevel,
1,
1000
);
// Initial Position: Isometric View
// Looking from "High Corner"
this.camera.position.set(20, 20, 20);
this.camera.lookAt(0, 0, 0);
// --- Controls State ---
this.isDragging = false;
this.lastMouseX = 0;
this.lastMouseY = 0;
this.panSpeed = 0.5;
// Current Snap View (North, East, South, West)
// We'll define View Angles relative to "Target"
this.currentViewAngle = 0; // 0 = North? We'll refine mapping.
this.setupInputListeners();
}
getCamera() {
return this.camera;
}
setupInputListeners() {
// Zoom (Mouse Wheel)
window.addEventListener('wheel', (e) => {
e.preventDefault();
// Adjust Zoom Level property
if (e.deltaY < 0) this.zoomLevel = Math.max(5, this.zoomLevel - 1);
else this.zoomLevel = Math.min(50, this.zoomLevel + 1);
this.updateProjection();
}, { passive: false });
// Pan Listeners (Middle Click)
window.addEventListener('mousedown', (e) => {
if (e.button === 1) { // Middle Mouse
this.isDragging = true;
this.lastMouseX = e.clientX;
this.lastMouseY = e.clientY;
}
});
window.addEventListener('mouseup', () => {
this.isDragging = false;
});
window.addEventListener('mousemove', (e) => {
if (this.isDragging) {
const dx = e.clientX - this.lastMouseX;
const dy = e.clientY - this.lastMouseY;
this.lastMouseX = e.clientX;
this.lastMouseY = e.clientY;
this.pan(-dx, dy); // Invert X usually feels natural (drag ground)
}
});
// Resize Listener linkage
window.addEventListener('resize', () => {
this.aspect = window.innerWidth / window.innerHeight;
this.updateProjection();
});
}
updateProjection() {
this.camera.left = -this.zoomLevel * this.aspect;
this.camera.right = this.zoomLevel * this.aspect;
this.camera.top = this.zoomLevel;
this.camera.bottom = -this.zoomLevel;
this.camera.updateProjectionMatrix();
}
pan(dx, dy) {
// Panning moves the camera position relative to its local axes
// X movement moves Right/Left
// Y movement moves Up/Down (in screen space)
// Since we are isometric, "Up/Down" on screen means moving along the projected Z axis basically.
// Simple implementation: Translate on X and Z (Ground Plane)
// We need to convert screen delta to world delta based on current rotation?
// For 'Fixed' views, it's easier.
const moveSpeed = this.panSpeed * 0.1 * (this.zoomLevel / 10);
// Basic Pan relative to world for now:
// We really want to move camera.translateX/Y?
this.camera.translateX(dx * moveSpeed);
this.camera.translateY(dy * moveSpeed);
}
// --- Fixed Orbit Logic ---
// N, S, E, W
setIsoView(direction) {
// Standard Isometric look from corner
// Distance
const dist = 40;
const height = 30; // 35 degrees up approx?
let x, z;
switch (direction) {
case DIRECTIONS.NORTH: // Looking North means camera is at South?
// Or Looking FROM North?
// Usually "North View" means "Top of map is North".
// In 3D Iso, standard is X=Right, Z=Down(South).
// "Normal" view: Camera at +X, +Z looking at origin?
x = dist; z = dist;
break;
case DIRECTIONS.SOUTH:
x = -dist; z = -dist;
break;
case DIRECTIONS.EAST:
x = dist; z = -dist;
break;
case DIRECTIONS.WEST:
x = -dist; z = dist;
break;
default:
x = dist; z = dist;
}
this.camera.position.set(x, height, z);
this.camera.lookAt(0, 0, 0); // Need to orbit around a pivot actually if we want to pan...
// If we pan, camera.lookAt overrides position logic unless we move the visual target.
// TODO: Implement OrbitControls-like logic with a target.
}
}