08 · GPT-6.1 Sol / low · 原场景逻辑源码

返回测评 · 运行原作品 · 下载原始源码

本页只阅读源码,不运行代码;行号对应原文件,完整成品保持原交付字节。

1import * as THREE from './three.module.js';2const canvas=document.querySelector('canvas');3const scene=new THREE.Scene(); scene.background=new THREE.Color('#a9deef');scene.fog=new THREE.Fog('#a9deef',65,155);4const renderer=new THREE.WebGLRenderer({canvas,antialias:true});renderer.setPixelRatio(Math.min(devicePixelRatio,2));renderer.shadowMap.enabled=true;renderer.shadowMap.type=THREE.PCFSoftShadowMap;renderer.outputColorSpace=THREE.SRGBColorSpace;renderer.toneMapping=THREE.ACESFilmicToneMapping;renderer.toneMappingExposure=1.2;5const camera=new THREE.PerspectiveCamera(42,1,.1,250);6scene.add(new THREE.HemisphereLight(0xe1f5ff,0xb4a18a,2.6));const sun=new THREE.DirectionalLight(0xffe2b4,3.4);sun.position.set(-15,30,20);sun.castShadow=true;sun.shadow.mapSize.set(2048,2048);Object.assign(sun.shadow.camera,{left:-35,right:35,top:35,bottom:-35});scene.add(sun);7const mat=(c,roughness=.7)=>new THREE.MeshStandardMaterial({color:c,roughness});8const sand=mat('#ead5a5'),road=mat('#596771'),white=mat('#fff7df'),green=mat('#479881'),orange=mat('#e5a454'),cream=mat('#ffe3b3'),black=mat('#293640'),pink=mat('#e59e96'),teal=mat('#4cc2ba'),metal=mat('#e8f0e8',.3);9function mesh(g,m,p,x=0,y=0,z=0){const o=new THREE.Mesh(g,m);o.position.set(x,y,z);o.castShadow=true;o.receiveShadow=true;p.add(o);return o;}10const box=(p,m,x,y,z,a,b,c)=>mesh(new THREE.BoxGeometry(a,b,c),m,p,x,y,z);11const ball=(p,m,x,y,z,a,b=a,c=a)=>{let o=mesh(new THREE.SphereGeometry(1,24,16),m,p,x,y,z);o.scale.set(a,b,c);return o;};12function rod(p,m,a,b,r){const A=new THREE.Vector3(...a),B=new THREE.Vector3(...b),o=mesh(new THREE.CylinderGeometry(r,r,A.distanceTo(B),12),m,p);o.position.copy(A).add(B).multiplyScalar(.5);o.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0),B.sub(A).normalize());return o;}13box(scene,sand,0,-.35,0,95,.6,240);box(scene,road,0,-.015,0,8,.12,240);box(scene,white,-3.7,.055,0,.09,.015,240);box(scene,white,3.7,.055,0,.09,.015,240);14const oceanMat=new THREE.MeshStandardMaterial({color:'#42b5c6',roughness:.24,metalness:.18});const water=mesh(new THREE.PlaneGeometry(110,240,55,90),oceanMat,scene,-64,-.08,0);water.rotation.x=-Math.PI/2;15const moving=new THREE.Group();scene.add(moving);16for(let z=-110;z<110;z+=8){box(moving,white,0,.06,z,.12,.02,3.6);box(moving,white,-7,.08,z,1.3,.02,.16);}17for(let z=-110;z<110;z+=12){box(moving,metal,-5,.55,z,.12,1.1,.12);box(moving,metal,-5,1,z+6,.1,.1,12);}18function palm(x,z){const p=new THREE.Group();p.position.set(x,0,z);moving.add(p);rod(p,mat('#b3986b'),[0,0,0],[.35,5.4,0],.17);for(let i=0;i<7;i++){const leaf=ball(p,green,.35,5.35,0,1.7,.13,.36);leaf.rotation.z=.2;leaf.rotation.y=i*Math.PI*2/7;leaf.position.x+=Math.cos(i*Math.PI*2/7)*1.15;leaf.position.z+=Math.sin(i*Math.PI*2/7)*1.15;}ball(p,green,.35,5.4,0,.4);}19for(let z=-100;z<110;z+=22){palm(7.5,z);ball(moving,mat('#9cba8b'),10,.5,z+8,2,.7,1.4);}20for(let z=-105;z<110;z+=24){const parasol=mesh(new THREE.ConeGeometry(1.8,.7,12),mat(z%48?'#f1ad85':'#faf1cf'),moving,-10,2,z);rod(moving,white,[-10,0,z],[-10,1.9,z],.06);box(moving,teal,-10,.2,z+2,1,.15,1.8);}21for(let i=0;i<30;i++){const o=box(moving,white,-13-(i%5)*6,.025,-110+i*7,2+(i%4),.018,.07);o.material=new THREE.MeshBasicMaterial({color:'#b2ede8',transparent:true,opacity:.5});}22const ride=new THREE.Group();ride.position.set(1.65,0,0);scene.add(ride);23const wheels=[];for(const z of [-.95,1.05]){const pivot=new THREE.Group();pivot.position.set(0,.43,z);ride.add(pivot);const tire=mesh(new THREE.TorusGeometry(.33,.105,12,32),black,pivot);tire.rotation.y=Math.PI/2;const hub=mesh(new THREE.CylinderGeometry(.24,.24,.13,24),metal,pivot);hub.rotation.z=Math.PI/2;for(let i=0;i<6;i++){const a=i*Math.PI/3;rod(pivot,teal,[0,0,0],[0,Math.cos(a)*.25,Math.sin(a)*.25],.022);}wheels.push(pivot);}24box(ride,teal,0,.55,.05,.7,.25,1.5);ball(ride,teal,0,.77,-.8,.45,.43,.43);box(ride,black,0,1.13,-.38,.73,.18,.85);box(ride,teal,0,1.13,.8,.62,1.15,.24);ball(ride,white,0,1.52,1,.22,.16,.09);rod(ride,metal,[0,.55,1.05],[0,1.85,.85],.065);rod(ride,black,[-.48,1.85,.85],[.48,1.85,.85],.055);25for(const x of [-.45,.45]){rod(ride,metal,[x,1.85,.85],[x*1.35,2.18,.85],.023);ball(ride,black,x*1.35,2.2,.85,.12,.085,.05);}26box(ride,mat('#d9af7c'),0,1.31,-1,.65,.5,.48);box(ride,cream,0,1.58,-1,.69,.06,.52);27const cat=new THREE.Group();ride.add(cat);ball(cat,orange,0,1.65,-.3,.42,.6,.35);ball(cat,cream,0,1.66,-.015,.28,.42,.07);const head=new THREE.Group();head.position.set(0,2.35,-.16);cat.add(head);ball(head,orange,0,0,0,.5,.46,.43);28for(const x of [-.32,.32]){const e=mesh(new THREE.ConeGeometry(.2,.43,3),orange,head,x,.42,0);e.rotation.y=Math.PI/2;const inner=mesh(new THREE.ConeGeometry(.12,.27,3),pink,head,x,.44,.09);inner.rotation.y=Math.PI/2;ball(head,cream,x*.57,-.13,.36,.21,.15,.1);ball(head,black,x*.68,.065,.386,.057,.08,.035);ball(head,white,x*.68-.014,.09,.416,.015);for(let i=0;i<3;i++)rod(head,cream,[x*.6,-.13+i*.025,.4],[x*1.8,-.12+(i-1)*.1,.39],.008);}29ball(head,pink,0,-.08,.465,.06,.045,.035);rod(head,black,[0,-.12,.45],[0,-.18,.46],.009);30const helmet=ball(head,mat('#f1efe1'),0,.23,-.025,.52,.31,.46);box(head,teal,0,.28,.433,.5,.08,.05);31for(const x of [-1,1]){rod(cat,orange,[x*.31,1.9,-.2],[x*.4,1.73,.4],.12);rod(cat,orange,[x*.4,1.73,.4],[x*.43,1.85,.85],.1);ball(cat,cream,x*.43,1.85,.85,.12);rod(cat,orange,[x*.25,1.35,-.4],[x*.4,.85,-.15],.16);rod(cat,cream,[x*.4,.85,-.15],[x*.37,.72,.3],.11);ball(cat,cream,x*.37,.72,.35,.14,.09,.24);}32const tail=new THREE.Group();tail.position.set(.25,1.35,-.55);cat.add(tail);rod(tail,orange,[0,0,0],[.3,.1,-.55],.11);rod(tail,orange,[.3,.1,-.55],[.38,.55,-.8],.09);ball(tail,cream,.38,.55,-.8,.095);33const scarf=mesh(new THREE.ConeGeometry(.15,.8,4),mat('#ee745e'),cat,-.25,2.02,-.6);scarf.rotation.x=-1.4;ball(cat,scarf.material,0,2.03,-.1,.35,.09,.32);34const birds=[];for(let i=0;i<7;i++){const g=new THREE.Group();scene.add(g);for(const s of [-1,1])rod(g,white,[0,0,0],[s*.4,.16,0],.025);g.position.set(-20-i*3,8+i%3,-20+i*9);birds.push(g);}35moving.children.forEach(o=>o.userData.baseZ=o.position.z);36let paused=false,speed=1,view='follow',time=0,distance=0,yaw=.0,pitch=.12,zoom=1,drag=false,lastX=0,lastY=0;37const pause=document.querySelector('#pause');pause.onclick=()=>{paused=!paused;pause.textContent=paused?'继续骑行':'暂停';};document.querySelector('#speed').oninput=e=>{speed=+e.target.value;document.querySelector('#speedValue').textContent=speed.toFixed(1)+'×';};document.querySelectorAll('[data-view]').forEach(b=>b.onclick=()=>{view=b.dataset.view;document.querySelectorAll('[data-view]').forEach(n=>n.classList.toggle('active',n===b));yaw=0;zoom=1;});38canvas.onpointerdown=e=>{drag=true;lastX=e.clientX;lastY=e.clientY;canvas.setPointerCapture(e.pointerId);};canvas.onpointerup=()=>drag=false;canvas.onpointermove=e=>{if(drag){yaw-=(e.clientX-lastX)*.006;pitch=Math.max(-.25,Math.min(.65,pitch+(e.clientY-lastY)*.004));lastX=e.clientX;lastY=e.clientY;}};canvas.onwheel=e=>{e.preventDefault();zoom=Math.min(1.8,Math.max(.65,zoom+e.deltaY*.001));};window.onkeydown=e=>{if(e.code==='Space'&&e.target.tagName!=='INPUT'){e.preventDefault();pause.click();}};39function resize(){renderer.setSize(innerWidth,innerHeight);camera.aspect=innerWidth/innerHeight;camera.updateProjectionMatrix();}addEventListener('resize',resize);resize();40const clock=new THREE.Clock();function animate(){requestAnimationFrame(animate);const dt=Math.min(clock.getDelta(),.05);if(!paused){time+=dt*speed;const delta=dt*speed*6;distance+=delta;moving.children.forEach(o=>o.position.z=((o.userData.baseZ+distance+120)%240)-120);wheels.forEach(w=>w.rotation.x+=delta/.43);ride.position.y=Math.sin(time*8)*.018;tail.rotation.z=Math.sin(time*2.5)*.12;head.rotation.y=Math.sin(time*.7)*.08;scarf.rotation.z=Math.sin(time*9)*.16;const arr=water.geometry.attributes.position;for(let i=0;i<arr.count;i++)arr.setZ(i,Math.sin(arr.getX(i)*.3+time)*.065+Math.sin(arr.getY(i)*.22+time*1.5)*.04);arr.needsUpdate=true;birds.forEach((b,i)=>{b.position.z=((time*2+i*9+30)%90)-45;b.position.y=8+i%3+Math.sin(time*3+i)*.2;});}const base=view==='wide'?new THREE.Vector3(17,15,23):view==='front'?new THREE.Vector3(6,4.4,12):new THREE.Vector3(7.8,4.8,8.5);base.multiplyScalar(zoom);base.applyAxisAngle(new THREE.Vector3(0,1,0),yaw);base.y+=pitch*8;const target=new THREE.Vector3(1.65,1.5,0);camera.position.lerp(base.add(target),.065);camera.lookAt(target);renderer.render(scene,camera);document.querySelector('#km').textContent=(distance/1000).toFixed(2);}41window.sceneStatus=()=>({paused,time,distance,wheelAngle:wheels[0].rotation.x,view,webgl:renderer.info.render.calls>0});animate();