Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Basic 3D Setup Test</title> | |
<style> | |
/* --- Minimal Base Styles --- */ | |
body { | |
font-family: 'Courier New', monospace; | |
background-color: #222; | |
color: #eee; | |
margin: 0; | |
padding: 0; | |
overflow: hidden; /* Prevent scrollbars */ | |
display: flex; | |
flex-direction: column; | |
height: 100vh; /* Full viewport height */ | |
} | |
/* --- Layout --- */ | |
#game-container { | |
display: flex; | |
flex-grow: 1; /* Fill remaining vertical space */ | |
overflow: hidden; | |
} | |
#scene-container { | |
flex-grow: 3; /* Give more space to 3D view */ | |
position: relative; | |
border-right: 2px solid #555; | |
min-width: 200px; | |
background-color: #1a1a1a; | |
height: 100%; /* Ensure it takes full height of flex parent */ | |
box-sizing: border-box; /* Include border in size */ | |
} | |
#ui-container { | |
flex-grow: 2; /* Space for UI elements */ | |
padding: 20px; | |
overflow-y: auto; /* Allow scrolling if content overflows */ | |
background-color: #333; | |
min-width: 280px; | |
height: 100%; /* Ensure it takes full height of flex parent */ | |
box-sizing: border-box; /* Include padding in size */ | |
} | |
#scene-container canvas { | |
display: block; /* Remove extra space below canvas */ | |
} | |
/* --- Basic UI Placeholders --- */ | |
#ui-container h2 { | |
color: #ffcc66; | |
margin-top: 0; | |
margin-bottom: 15px; | |
border-bottom: 1px solid #555; | |
padding-bottom: 10px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="game-container"> | |
<div id="scene-container"> | |
</div> | |
<div id="ui-container"> | |
<h2 id="story-title">UI Panel</h2> | |
<div id="story-content"> | |
<p>This panel will hold the story text, choices, and character sheet later.</p> | |
<p>Focus is on getting the 3D cube rendering in the left panel.</p> | |
</div> | |
</div> | |
</div> | |
<script type="importmap"> | |
{ | |
"imports": { | |
"three": "https://unpkg.com/[email protected]/build/three.module.js", | |
"three/addons/": "https://unpkg.com/[email protected]/examples/jsm/" | |
} | |
} | |
</script> | |
<script type="module"> | |
import * as THREE from 'three'; | |
// OrbitControls is not used in this minimal version | |
// import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; | |
// --- DOM Elements --- | |
const sceneContainer = document.getElementById('scene-container'); | |
// References to UI elements (not used in this version, but kept for context) | |
// const storyTitleElement = document.getElementById('story-title'); | |
// const storyContentElement = document.getElementById('story-content'); | |
// const choicesElement = document.getElementById('choices'); | |
// const statsElement = document.getElementById('stats-display'); | |
// const inventoryElement = document.getElementById('inventory-display'); | |
// --- Three.js Setup --- | |
let scene, camera, renderer, cube; // Basic scene objects | |
function initThreeJS() { | |
console.log("Attempting to initialize Three.js..."); // Debug log | |
if (!sceneContainer) { | |
console.error("Scene container not found!"); | |
return; // Stop if container doesn't exist | |
} | |
// Scene | |
scene = new THREE.Scene(); | |
scene.background = new THREE.Color(0x222222); // Dark grey background | |
// Camera | |
// Use container dimensions for aspect ratio calculation | |
const width = sceneContainer.clientWidth; | |
const height = sceneContainer.clientHeight; | |
if (width === 0 || height === 0) { | |
console.warn("Scene container has zero dimensions on init. Renderer/Camera might be sized incorrectly."); | |
} | |
camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000); | |
camera.position.z = 5; // Position camera back | |
// Renderer | |
renderer = new THREE.WebGLRenderer({ antialias: true }); | |
// Set size explicitly, fallback if container size is 0 initially | |
renderer.setSize(width || 400, height || 300); // Use fallback size if needed | |
sceneContainer.appendChild(renderer.domElement); // Add canvas to the container | |
console.log("Renderer initialized and added to DOM."); | |
// Basic Lighting | |
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); // Soft white light | |
scene.add(ambientLight); | |
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0); | |
directionalLight.position.set(5, 10, 7.5); // Position the light | |
scene.add(directionalLight); | |
// Basic Cube Object | |
const geometry = new THREE.BoxGeometry(1, 1, 1); // 1x1x1 cube | |
const material = new THREE.MeshStandardMaterial({ color: 0xcccccc }); // Light grey color | |
cube = new THREE.Mesh(geometry, material); | |
scene.add(cube); // Add cube to the scene | |
console.log("Cube created and added to scene."); | |
// Handle Resize | |
window.addEventListener('resize', onWindowResize, false); | |
// Initial resize call in case the flexbox layout takes a moment | |
setTimeout(onWindowResize, 100); // Delay slightly to help layout settle | |
// Start Animation Loop | |
animate(); | |
console.log("Animation loop started."); | |
} | |
function onWindowResize() { | |
if (!renderer || !camera || !sceneContainer) return; | |
const width = sceneContainer.clientWidth; | |
const height = sceneContainer.clientHeight; | |
// Only resize if dimensions are valid | |
if (width > 0 && height > 0) { | |
camera.aspect = width / height; | |
camera.updateProjectionMatrix(); // Important after changing aspect | |
renderer.setSize(width, height); | |
// console.log(`Resized to ${width}x${height}`); // Debug log for resize | |
} else { | |
console.warn("onWindowResize called with zero dimensions."); | |
} | |
} | |
function animate() { | |
requestAnimationFrame(animate); // Loop the animation | |
// Simple cube rotation | |
if (cube) { | |
cube.rotation.x += 0.005; | |
cube.rotation.y += 0.005; | |
} | |
// Render the scene | |
if (renderer && scene && camera) { | |
renderer.render(scene, camera); | |
} | |
} | |
// --- Initialization --- | |
// Wait for the basic HTML structure to be ready before running the script | |
document.addEventListener('DOMContentLoaded', () => { | |
console.log("DOM Content Loaded. Initializing..."); | |
try { | |
initThreeJS(); | |
} catch (error) { | |
console.error("Error during initialization:", error); | |
// Display error to user in the UI panel | |
const uiContainer = document.getElementById('ui-container'); | |
if (uiContainer) { | |
uiContainer.innerHTML = `<h2>Error</h2><p>Failed to initialize 3D scene. Please check the browser console (F12) for details.</p><pre>${error.message}\n${error.stack}</pre>`; | |
} | |
} | |
}); | |
</script> | |
</body> | |
</html> |