使用Three.js开发一个简单的3D-RPG游戏

266 阅读2分钟

使用GPT生成

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple RPG Game with Three.js</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
        #info {
            position: absolute;
            top: 10px;
            width: 100%;
            text-align: center;
            color: white;
            z-index: 1;
        }
    </style>
</head>
<body>
    <div id="info">Use arrow keys to move the character. Press space to attack.</div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <script>
        let scene, camera, renderer, player;
        let enemies = [];
        let playerSpeed = 0.1;
        let attackRange = 1.5;

        function init() {
            // Scene setup
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0x87ceeb);

            // Camera setup
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.set(0, 5, 10);
            camera.lookAt(0, 0, 0);

            // Renderer setup
            renderer = new THREE.WebGLRenderer();
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMap.enabled = true;
            document.body.appendChild(renderer.domElement);

            // Lighting
            const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
            scene.add(ambientLight);

            const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
            directionalLight.position.set(5, 10, 7.5);
            directionalLight.castShadow = true;
            directionalLight.shadow.mapSize.width = 1024;
            directionalLight.shadow.mapSize.height = 1024;
            scene.add(directionalLight);

            // Ground
            const groundGeometry = new THREE.PlaneGeometry(20, 20);
            const groundMaterial = new THREE.MeshStandardMaterial({ color: 0x228B22 });
            const ground = new THREE.Mesh(groundGeometry, groundMaterial);
            ground.rotation.x = -Math.PI / 2;
            ground.receiveShadow = true;
            scene.add(ground);

            // Player
            player = createPlayer();
            scene.add(player);

            // Enemies
            const enemyGeometry = new THREE.BoxGeometry(1, 1, 1);
            const enemyMaterial = new THREE.MeshStandardMaterial({ color: 0x0000ff });
            for (let i = 0; i < 5; i++) {
                let enemy = new THREE.Mesh(enemyGeometry, enemyMaterial);
                enemy.position.set(Math.random() * 16 - 8, 0.5, Math.random() * 16 - 8);
                enemy.castShadow = true;
                enemies.push(enemy);
                scene.add(enemy);
            }

            // Trees
            for (let i = 0; i < 10; i++) {
                addTree(Math.random() * 16 - 8, Math.random() * 16 - 8);
            }

            // Rocks
            for (let i = 0; i < 5; i++) {
                addRock(Math.random() * 16 - 8, Math.random() * 16 - 8);
            }

            // Event listeners
            window.addEventListener('resize', onWindowResize, false);
            document.addEventListener('keydown', onDocumentKeyDown, false);
        }

        function createPlayer() {
            const player = new THREE.Group();

            // Head
            const headGeometry = new THREE.BoxGeometry(1, 1, 1);
            const headMaterial = new THREE.MeshStandardMaterial({ color: 0xffcc99 });
            const head = new THREE.Mesh(headGeometry, headMaterial);
            head.position.set(0, 1.5, 0);
            head.castShadow = true;
            player.add(head);

            // Eyes
            const eyeGeometry = new THREE.BoxGeometry(0.1, 0.1, 0.1);
            const eyeMaterial = new THREE.MeshStandardMaterial({ color: 0x000000 });
            const leftEye = new THREE.Mesh(eyeGeometry, eyeMaterial);
            leftEye.position.set(-0.2, 1.6, 0.5);
            player.add(leftEye);

            const rightEye = new THREE.Mesh(eyeGeometry, eyeMaterial);
            rightEye.position.set(0.2, 1.6, 0.5);
            player.add(rightEye);

            // Mouth
            const mouthGeometry = new THREE.BoxGeometry(0.4, 0.1, 0.1);
            const mouthMaterial = new THREE.MeshStandardMaterial({ color: 0x000000 });
            const mouth = new THREE.Mesh(mouthGeometry, mouthMaterial);
            mouth.position.set(0, 1.3, 0.5);
            player.add(mouth);

            // Body
            const bodyGeometry = new THREE.BoxGeometry(1, 1.5, 0.5);
            const bodyMaterial = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
            const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
            body.position.set(0, 0.75, 0);
            body.castShadow = true;
            player.add(body);

            // Arms
            const armGeometry = new THREE.BoxGeometry(0.3, 1, 0.3);
            const armMaterial = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
            const leftArm = new THREE.Mesh(armGeometry, armMaterial);
            leftArm.position.set(-0.65, 0.75, 0);
            leftArm.castShadow = true;
            player.add(leftArm);

            const rightArm = new THREE.Mesh(armGeometry, armMaterial);
            rightArm.position.set(0.65, 0.75, 0);
            rightArm.castShadow = true;
            player.add(rightArm);

            // Legs
            const legGeometry = new THREE.BoxGeometry(0.4, 1, 0.4);
            const legMaterial = new THREE.MeshStandardMaterial({ color: 0x0000ff });
            const leftLeg = new THREE.Mesh(legGeometry, legMaterial);
            leftLeg.position.set(-0.3, -0.25, 0);
            leftLeg.castShadow = true;
            player.add(leftLeg);

            const rightLeg = new THREE.Mesh(legGeometry, legMaterial);
            rightLeg.position.set(0.3, -0.25, 0);
            rightLeg.castShadow = true;
            player.add(rightLeg);

            // Sword
            const swordGeometry = new THREE.BoxGeometry(0.1, 0.6, 0.1);
            const swordMaterial = new THREE.MeshStandardMaterial({ color: 0x00ffff });
            const sword = new THREE.Mesh(swordGeometry, swordMaterial);
            sword.position.set(0.75, 1, 0.4);
            sword.castShadow = true;
            player.add(sword);

            player.position.y = 1;
            player.castShadow = true;

            return player;
        }

        function addTree(x, z) {
            const trunkGeometry = new THREE.CylinderGeometry(0.2, 0.2, 2);
            const trunkMaterial = new THREE.MeshStandardMaterial({ color: 0x8B4513 });
            const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
            trunk.position.set(x, 1, z);
            trunk.castShadow = true;
            trunk.receiveShadow = true;
            scene.add(trunk);

            const leavesGeometry = new THREE.SphereGeometry(1);
            const leavesMaterial = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
            const leaves = new THREE.Mesh(leavesGeometry, leavesMaterial);
            leaves.position.set(x, 2.5, z);
            leaves.castShadow = true;
            leaves.receiveShadow = true;
            scene.add(leaves);
        }

        function addRock(x, z) {
            const rockGeometry = new THREE.DodecahedronGeometry(0.5);
            const rockMaterial = new THREE.MeshStandardMaterial({ color: 0x808080 });
            const rock = new THREE.Mesh(rockGeometry, rockMaterial);
            rock.position.set(x, 0.25, z);
            rock.castShadow = true;
            rock.receiveShadow = true;
            scene.add(rock);
        }

        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }

        function onDocumentKeyDown(event) {
            switch (event.key) {
                case 'ArrowUp':
                    player.position.z -= playerSpeed;
                    break;
                case 'ArrowDown':
                    player.position.z += playerSpeed;
                    break;
                case 'ArrowLeft':
                    player.position.x -= playerSpeed;
                    break;
                case 'ArrowRight':
                    player.position.x += playerSpeed;
                    break;
                case ' ':
                    attack();
                    break;
            }
        }

        function attack() {
            enemies.forEach((enemy, index) => {
                if (player.position.distanceTo(enemy.position) < attackRange) {
                    scene.remove(enemy);
                    enemies.splice(index, 1);
                    console.log('Enemy defeated!');
                }
            });
        }

        function animate() {
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
        }

        init();
        animate();
    </script>
</body>
</html>