Spaces:
Sleeping
Sleeping
| <html> | |
| <head> | |
| <title>Basic Three.js 2.5D Scene</title> | |
| <style> | |
| body { margin: 0; } | |
| canvas { display: block; } | |
| </style> | |
| </head> | |
| <body> | |
| <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'; | |
| let scene, camera, renderer, playerMesh; | |
| let moveForward = false, moveBackward = false, moveLeft = false, moveRight = false; | |
| const playerSpeed = 0.1; | |
| function init() { | |
| // --- Basic Setup --- | |
| scene = new THREE.Scene(); | |
| scene.background = new THREE.Color(0x87CEEB); // Sky blue background | |
| // --- Camera (Orthographic for 2.5D feel) --- | |
| const aspect = window.innerWidth / window.innerHeight; | |
| const viewSize = 15; // How many units are visible vertically | |
| camera = new THREE.OrthographicCamera( | |
| -viewSize * aspect / 2, viewSize * aspect / 2, | |
| viewSize / 2, -viewSize / 2, | |
| 1, 1000 | |
| ); | |
| camera.position.set(5, 10, 5); // Positioned above and looking down | |
| camera.lookAt(0, 0, 0); // Look at the center of the scene | |
| scene.add(camera); | |
| // --- Lighting --- | |
| const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); | |
| scene.add(ambientLight); | |
| const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); | |
| directionalLight.position.set(5, 10, 7.5); | |
| scene.add(directionalLight); | |
| // --- Ground --- | |
| const groundGeometry = new THREE.PlaneGeometry(20, 20); | |
| const groundMaterial = new THREE.MeshLambertMaterial({ color: 0x228B22 }); // Forest green | |
| const groundMesh = new THREE.Mesh(groundGeometry, groundMaterial); | |
| groundMesh.rotation.x = -Math.PI / 2; // Rotate to lie flat | |
| groundMesh.position.y = -0.5; // Slightly below origin | |
| scene.add(groundMesh); | |
| // --- Player Placeholder (Simple Cube) --- | |
| // In a real game, you'd load a sprite/texture here | |
| const playerGeometry = new THREE.BoxGeometry(0.8, 0.8, 0.8); | |
| const playerMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000 }); // Red | |
| playerMesh = new THREE.Mesh(playerGeometry, playerMaterial); | |
| playerMesh.position.y = 0; // Place on top of the ground level | |
| scene.add(playerMesh); | |
| // --- Renderer --- | |
| renderer = new THREE.WebGLRenderer({ antialias: true }); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| document.body.appendChild(renderer.domElement); | |
| // --- Event Listeners for Movement --- | |
| document.addEventListener('keydown', onKeyDown); | |
| document.addEventListener('keyup', onKeyUp); | |
| window.addEventListener('resize', onWindowResize); // Handle window resizing | |
| // --- Start Animation --- | |
| animate(); | |
| } | |
| function onKeyDown(event) { | |
| switch (event.code) { | |
| case 'KeyW': | |
| case 'ArrowUp': | |
| moveForward = true; | |
| break; | |
| case 'KeyS': | |
| case 'ArrowDown': | |
| moveBackward = true; | |
| break; | |
| case 'KeyA': | |
| case 'ArrowLeft': | |
| moveLeft = true; | |
| break; | |
| case 'KeyD': | |
| case 'ArrowRight': | |
| moveRight = true; | |
| break; | |
| } | |
| } | |
| function onKeyUp(event) { | |
| switch (event.code) { | |
| case 'KeyW': | |
| case 'ArrowUp': | |
| moveForward = false; | |
| break; | |
| case 'KeyS': | |
| case 'ArrowDown': | |
| moveBackward = false; | |
| break; | |
| case 'KeyA': | |
| case 'ArrowLeft': | |
| moveLeft = false; | |
| break; | |
| case 'KeyD': | |
| case 'ArrowRight': | |
| moveRight = false; | |
| break; | |
| } | |
| } | |
| function updatePlayerPosition() { | |
| if (!playerMesh) return; | |
| const moveVector = new THREE.Vector3(); | |
| if (moveForward) moveVector.z -= 1; | |
| if (moveBackward) moveVector.z += 1; | |
| if (moveLeft) moveVector.x -= 1; | |
| if (moveRight) moveVector.x += 1; | |
| // Normalize diagonal movement and apply speed | |
| if (moveVector.lengthSq() > 0) { // Check if there's any movement | |
| moveVector.normalize().multiplyScalar(playerSpeed); | |
| playerMesh.position.add(moveVector); | |
| } | |
| // Keep camera centered on player (optional basic follow) | |
| // camera.position.x = playerMesh.position.x; | |
| // camera.position.z = playerMesh.position.z + 5; // Adjust Z offset as needed | |
| // camera.lookAt(playerMesh.position); | |
| } | |
| function onWindowResize() { | |
| const aspect = window.innerWidth / window.innerHeight; | |
| const viewSize = 15; | |
| camera.left = -viewSize * aspect / 2; | |
| camera.right = viewSize * aspect / 2; | |
| camera.top = viewSize / 2; | |
| camera.bottom = -viewSize / 2; | |
| camera.updateProjectionMatrix(); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| } | |
| function animate() { | |
| requestAnimationFrame(animate); // Loop the animation | |
| updatePlayerPosition(); // Update player based on input | |
| renderer.render(scene, camera); // Render the scene | |
| } | |
| // --- Start the app --- | |
| init(); | |
| </script> | |
| </body> | |
| </html> |