🎮ArcadeLab

手机3D自由跑酷

by BoldEagle86
106 lines4.5 KB🛠️ Three.js (3D graphics)
▶ Play
<!DOCTYPE html>
 <html lang="zh-CN">
 <head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
 <title>手机3D自由跑酷</title>
 <style>
 *{margin:0;padding:0;touch-action:none;}
 body{overflow:hidden;background:#111;color:#fff;font-size:14px;}
 #tip{position:absolute;top:10px;left:10px;z-index:99;background:rgba(0,0,0,0.4);padding:6px;border-radius:6px;}
 /* 虚拟触屏按键 */
 .ctrl{position:absolute;width:70px;height:70px;border-radius:50%;background:rgba(255,255,255,0.15);border:1px solid #fff;display:flex;align-items:center;justify-content:center;font-size:24px;user-select:none;}
 #btnW{left:50%;transform:translateX(-50%);bottom:110px;}
 #btnA{left:20px;bottom:40px;}
 #btnD{right:20px;bottom:40px;}
 #btnJump{left:50%;transform:translateX(-50%);bottom:20px;width:120px;height:60px;border-radius:12px;background:rgba(60,180,255,0.3);}
 </style>
 </head>
 <body>
 <div id="tip">滑动屏幕转动视角<br>点击画面锁定镜头</div>
 <div class="ctrl" id="btnW">前</div>
 <div class="ctrl" id="btnA">左</div>
 <div class="ctrl" id="btnD">右</div>
 <div class="ctrl" id="btnJump">跳跃</div>
 <script src="https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.min.js"></script>
 <script src="https://cdn.jsdelivr.net/npm/three@0.160.0/examples/js/controls/PointerLockControls.js"></script>
 <script>
 let scene, camera, renderer, controls;
 let playerVelocity = new THREE.Vector3();
 let moveForward = false, moveLeft = false, moveRight = false;
 let canJump = false;
 const gravity = -0.012;
 init();
 animate();
 function init(){
     scene = new THREE.Scene();
     scene.background = new THREE.Color(0x87ceeb);
     camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
     camera.position.set(0, 1.8, 0);
     renderer = new THREE.WebGLRenderer({antialias:true});
     renderer.setSize(window.innerWidth, window.innerHeight);
     document.body.appendChild(renderer.domElement);
     controls = new THREE.PointerLockControls(camera, document.body);
     document.body.addEventListener('click', ()=>controls.lock());
     // 场景光照
     const dirLight = new THREE.DirectionalLight(0xffffff,1);
     dirLight.position.set(50,100,50);
     scene.add(dirLight);
     scene.add(new THREE.AmbientLight(0xcccccc,0.4));
     // 长条跑道地面
     const groundGeo = new THREE.PlaneGeometry(200,20);
     const groundMat = new THREE.MeshLambertMaterial({color:0x337733});
     const ground = new THREE.Mesh(groundGeo, groundMat);
     ground.rotation.x = -Math.PI/2;
     ground.position.y = 0;
     scene.add(ground);
     // 随机高低跳台障碍
     for(let i=1; i<=30; i++){
         const h = Math.random()*1.5 + 0.3;
         const platGeo = new THREE.BoxGeometry(4, h, 3);
         const platMat = new THREE.MeshLambertMaterial({color:0x664422});
         const plat = new THREE.Mesh(platGeo, platMat);
         plat.position.set((Math.random()-0.5)*8, h/2, -i*12);
         scene.add(plat);
     }
     // 触屏按键逻辑
     const btnW = document.getElementById('btnW');
     const btnA = document.getElementById('btnA');
     const btnD = document.getElementById('btnD');
     const btnJump = document.getElementById('btnJump');
     btnW.addEventListener('touchstart',()=>moveForward=true);
     btnW.addEventListener('touchend',()=>moveForward=false);
     btnA.addEventListener('touchstart',()=>moveLeft=true);
     btnA.addEventListener('touchend',()=>moveLeft=false);
     btnD.addEventListener('touchstart',()=>moveRight=true);
     btnD.addEventListener('touchend',()=>moveRight=false);
     btnJump.addEventListener('touchstart',()=>{if(canJump) playerVelocity.y = 0.22});
     window.addEventListener('resize', onWindowResize);
 }
 function onWindowResize(){
     camera.aspect = window.innerWidth/window.innerHeight;
     camera.updateProjectionMatrix();
     renderer.setSize(window.innerWidth, window.innerHeight);
 }
 function animate(){
     requestAnimationFrame(animate);
     playerVelocity.x *= 0.88;
     playerVelocity.z *= 0.88;
     playerVelocity.y += gravity;
     canJump = false;
     if(moveForward) playerVelocity.z -= 0.15;
     if(moveLeft) playerVelocity.x -= 0.15;
     if(moveRight) playerVelocity.x += 0.15;
     controls.moveRight(-playerVelocity.x);
     controls.moveForward(-playerVelocity.z);
     camera.position.y += playerVelocity.y;
     // 落地判定
     if(camera.position.y <= 1.8){
         playerVelocity.y = 0;
         camera.position.y = 1.8;
         canJump = true;
     }
     renderer.render(scene, camera);
 }
 </script>
 </body>

Game Source: 手机3D自由跑酷

Creator: BoldEagle86

Libraries: three

Complexity: moderate (106 lines, 4.5 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: 3d-boldeagle86" to link back to the original. Then publish at arcadelab.ai/publish.