Toggle navigation
在线编辑器
在线代码
文本比较
jQuery下载
前端库
在线手册
登录/注册
下载代码
html
css
js
分享到微信朋友圈
X
html
0
↑
←
↓
→
Retry
css
@import url('https://fonts.googleapis.com/css?family=Press+Start+2P'); body { margin: 0; font-family: 'Press Start 2P', cursive; font-size: 2em; color: white; } button { outline: none; cursor: pointer; } #counter { position: absolute; top: 20px; right: 20px; } #end { position: absolute; min-width: 100%; min-height: 100%; display: flex; align-items: center; justify-content: center; visibility: hidden; } #end button { background-color: red; padding: 20px 50px 20px 50px; font-family: inherit; font-size: inherit; } #controlls { position: absolute; min-width: 100%; min-height: 100%; display: flex; align-items: flex-end; justify-content: center; } #controlls div { margin-bottom: 20px; font-size: 0; max-width: 180px; } #controlls button { width: 50px; font-family: inherit; font-size: 30px; border: 3px solid white; color: white; background-color: transparent; margin: 5px; } #controlls button:first-of-type { width: 170px; }
JavaScript
const counterDOM = document.getElementById('counter'); const endDOM = document.getElementById('end'); const scene = new THREE.Scene(); const distance = 500; const camera = new THREE.OrthographicCamera( window.innerWidth/-2, window.innerWidth/2, window.innerHeight / 2, window.innerHeight / -2, 0.1, 10000 ); camera.rotation.x = 50*Math.PI/180; camera.rotation.y = 20*Math.PI/180; camera.rotation.z = 10*Math.PI/180; const initialCameraPositionY = -Math.tan(camera.rotation.x)*distance; const initialCameraPositionX = Math.tan(camera.rotation.y)*Math.sqrt(distance**2 + initialCameraPositionY**2); camera.position.y = initialCameraPositionY; camera.position.x = initialCameraPositionX; camera.position.z = distance; const zoom = 2; const chickenSize = 15; const positionWidth = 42; const columns = 17; const boardWidth = positionWidth*columns; const stepTime = 200; // Miliseconds it takes for the chicken to take a step forward, backward, left or right let lanes; let currentLane; let currentColumn; let previousTimestamp; let startMoving; let moves; let stepStartTimestamp; const carFrontTexture = new Texture(40,80,[{x: 0, y: 10, w: 30, h: 60 }]); const carBackTexture = new Texture(40,80,[{x: 10, y: 10, w: 30, h: 60 }]); const carRightSideTexture = new Texture(110,40,[{x: 10, y: 0, w: 50, h: 30 }, {x: 70, y: 0, w: 30, h: 30 }]); const carLeftSideTexture = new Texture(110,40,[{x: 10, y: 10, w: 50, h: 30 }, {x: 70, y: 10, w: 30, h: 30 }]); const truckFrontTexture = new Texture(30,30,[{x: 15, y: 0, w: 10, h: 30 }]); const truckRightSideTexture = new Texture(25,30,[{x: 0, y: 15, w: 10, h: 10 }]); const truckLeftSideTexture = new Texture(25,30,[{x: 0, y: 5, w: 10, h: 10 }]); const generateLanes = () => [-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9].map((index) => { const lane = new Lane(index); lane.mesh.position.y = index*positionWidth*zoom; scene.add( lane.mesh ); return lane; }).filter((lane) => lane.index >= 0); const addLane = () => { const index = lanes.length; const lane = new Lane(index); lane.mesh.position.y = index*positionWidth*zoom; scene.add(lane.mesh); lanes.push(lane); } const chicken = new Chicken(); scene.add( chicken ); const laneTypes = ['car', 'truck', 'forest']; const laneSpeeds = [2, 2.5, 3]; const vechicleColors = [0xa52523, 0xbdb638, 0x78b14b]; const threeHeights = [20,45,60]; const initaliseValues = () => { lanes = generateLanes() currentLane = 0; currentColumn = Math.floor(columns/2); previousTimestamp = null; startMoving = false; moves = []; stepStartTimestamp; chicken.position.x = 0; chicken.position.y = 0; camera.position.y = initialCameraPositionY; camera.position.x = initialCameraPositionX; } initaliseValues(); const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6); scene.add(hemiLight) dirLight = new THREE.DirectionalLight(0xffffff, 0.6); dirLight.position.set(-100, -100, 200); dirLight.castShadow = true; scene.add(dirLight); dirLight.shadow.mapSize.width = 2048; dirLight.shadow.mapSize.height = 2048; var d = 500; dirLight.shadow.camera.left = - d; dirLight.shadow.camera.right = d; dirLight.shadow.camera.top = d; dirLight.shadow.camera.bottom = - d; // var helper = new THREE.CameraHelper( dirLight.shadow.camera ); // var helper = new THREE.CameraHelper( camera ); // scene.add(helper) backLight = new THREE.DirectionalLight(0x000000, .4); backLight.position.set(200, 200, 50); backLight.castShadow = true; scene.add(backLight) function Texture(width, height, rects) { const canvas = document.createElement( "canvas" ); canvas.width = width; canvas.height = height; const context = canvas.getContext( "2d" ); context.fillStyle = "#ffffff"; context.fillRect( 0, 0, width, height ); context.fillStyle = "rgba(0,0,0,0.6)"; rects.forEach(rect => { context.fillRect(rect.x, rect.y, rect.w, rect.h); }); return new THREE.CanvasTexture(canvas); } function Wheel() { const wheel = new THREE.Mesh( new THREE.BoxBufferGeometry( 12*zoom, 33*zoom, 12*zoom ), new THREE.MeshLambertMaterial( { color: 0x333333, flatShading: true } ) ); wheel.position.z = 6*zoom; return wheel; } function Car() { const car = new THREE.Group(); const color = vechicleColors[Math.floor(Math.random() * vechicleColors.length)]; const main = new THREE.Mesh( new THREE.BoxBufferGeometry( 60*zoom, 30*zoom, 15*zoom ), new THREE.MeshPhongMaterial( { color, flatShading: true } ) ); main.position.z = 12*zoom; main.castShadow = true; main.receiveShadow = true; car.add(main) const cabin = new THREE.Mesh( new THREE.BoxBufferGeometry( 33*zoom, 24*zoom, 12*zoom ), [ new THREE.MeshPhongMaterial( { color: 0xcccccc, flatShading: true, map: carBackTexture } ), new THREE.MeshPhongMaterial( { color: 0xcccccc, flatShading: true, map: carFrontTexture } ), new THREE.MeshPhongMaterial( { color: 0xcccccc, flatShading: true, map: carRightSideTexture } ), new THREE.MeshPhongMaterial( { color: 0xcccccc, flatShading: true, map: carLeftSideTexture } ), new THREE.MeshPhongMaterial( { color: 0xcccccc, flatShading: true } ), // top new THREE.MeshPhongMaterial( { color: 0xcccccc, flatShading: true } ) // bottom ] ); cabin.position.x = 6*zoom; cabin.position.z = 25.5*zoom; cabin.castShadow = true; cabin.receiveShadow = true; car.add( cabin ); const frontWheel = new Wheel(); frontWheel.position.x = -18*zoom; car.add( frontWheel ); const backWheel = new Wheel(); backWheel.position.x = 18*zoom; car.add( backWheel ); car.castShadow = true; car.receiveShadow = false; return car; } function Truck() { const truck = new THREE.Group(); const color = vechicleColors[Math.floor(Math.random() * vechicleColors.length)]; const base = new THREE.Mesh( new THREE.BoxBufferGeometry( 100*zoom, 25*zoom, 5*zoom ), new THREE.MeshLambertMaterial( { color: 0xb4c6fc, flatShading: true } ) ); base.position.z = 10*zoom; truck.add(base) const cargo = new THREE.Mesh( new THREE.BoxBufferGeometry( 75*zoom, 35*zoom, 40*zoom ), new THREE.MeshPhongMaterial( { color: 0xb4c6fc, flatShading: true } ) ); cargo.position.x = 15*zoom; cargo.position.z = 30*zoom; cargo.castShadow = true; cargo.receiveShadow = true; truck.add(cargo) const cabin = new THREE.Mesh( new THREE.BoxBufferGeometry( 25*zoom, 30*zoom, 30*zoom ), [ new THREE.MeshPhongMaterial( { color, flatShading: true } ), // back new THREE.MeshPhongMaterial( { color, flatShading: true, map: truckFrontTexture } ), new THREE.MeshPhongMaterial( { color, flatShading: true, map: truckRightSideTexture } ), new THREE.MeshPhongMaterial( { color, flatShading: true, map: truckLeftSideTexture } ), new THREE.MeshPhongMaterial( { color, flatShading: true } ), // top new THREE.MeshPhongMaterial( { color, flatShading: true } ) // bottom ] ); cabin.position.x = -40*zoom; cabin.position.z = 20*zoom; cabin.castShadow = true; cabin.receiveShadow = true; truck.add( cabin ); const frontWheel = new Wheel(); frontWheel.position.x = -38*zoom; truck.add( frontWheel ); const middleWheel = new Wheel(); middleWheel.position.x = -10*zoom; truck.add( middleWheel ); const backWheel = new Wheel(); backWheel.position.x = 30*zoom; truck.add( backWheel ); return truck; } function Three() { const three = new THREE.Group(); const trunk = new THREE.Mesh( new THREE.BoxBufferGeometry( 15*zoom, 15*zoom, 20*zoom ), new THREE.MeshPhongMaterial( { color: 0x4d2926, flatShading: true } ) ); trunk.position.z = 10*zoom; trunk.castShadow = true; trunk.receiveShadow = true; three.add(trunk); height = threeHeights[Math.floor(Math.random()*threeHeights.length)]; const crown = new THREE.Mesh( new THREE.BoxBufferGeometry( 30*zoom, 30*zoom, height*zoom ), new THREE.MeshLambertMaterial( { color: 0x7aa21d, flatShading: true } ) ); crown.position.z = (height/2+20)*zoom; crown.castShadow = true; crown.receiveShadow = false; three.add(crown); return three; } function Chicken() { const chicken = new THREE.Group(); const body = new THREE.Mesh( new THREE.BoxBufferGeometry( chickenSize*zoom, chickenSize*zoom, 20*zoom ), new THREE.MeshPhongMaterial( { color: 0xffffff, flatShading: true } ) ); body.position.z = 10*zoom; body.castShadow = true; body.receiveShadow = true; chicken.add(body); const rowel = new THREE.Mesh( new THREE.BoxBufferGeometry( 2*zoom, 4*zoom, 2*zoom ), new THREE.MeshLambertMaterial( { color: 0xF0619A, flatShading: true } ) ); rowel.position.z = 21*zoom; rowel.castShadow = true; rowel.receiveShadow = false; chicken.add(rowel); return chicken; } function Road() { const road = new THREE.Group(); const createSection = color => new THREE.Mesh( new THREE.PlaneBufferGeometry( boardWidth*zoom, positionWidth*zoom ), new THREE.MeshPhongMaterial( { color } ) ); const middle = createSection(0x454A59); middle.receiveShadow = true; road.add(middle); const left = createSection(0x393D49); left.position.x = - boardWidth*zoom; road.add(left); const right = createSection(0x393D49); right.position.x = boardWidth*zoom; road.add(right); return road; } function Grass() { const grass = new THREE.Group(); const createSection = color => new THREE.Mesh( new THREE.BoxBufferGeometry( boardWidth*zoom, positionWidth*zoom, 3*zoom ), new THREE.MeshPhongMaterial( { color } ) ); const middle = createSection(0xbaf455); middle.receiveShadow = true; grass.add(middle); const left = createSection(0x99C846); left.position.x = - boardWidth*zoom; grass.add(left); const right = createSection(0x99C846); right.position.x = boardWidth*zoom; grass.add(right); grass.position.z = 1.5*zoom; return grass; } function Lane(index) { this.index = index; this.type = index <= 0 ? 'field' : laneTypes[Math.floor(Math.random()*laneTypes.length)]; switch(this.type) { case 'field': { this.type = 'field'; this.mesh = new Grass(); break; } case 'forest': { this.mesh = new Grass(); this.occupiedPositions = new Set(); this.threes = [1,2,3,4].map(() => { const three = new Three(); let position; do { position = Math.floor(Math.random()*columns); }while(this.occupiedPositions.has(position)) this.occupiedPositions.add(position); three.position.x = (position*positionWidth+positionWidth/2)*zoom-boardWidth*zoom/2; this.mesh.add( three ); return three; }) break; } case 'car' : { this.mesh = new Road(); this.direction = Math.random() >= 0.5; const occupiedPositions = new Set(); this.vechicles = [1,2,3].map(() => { const vechicle = new Car(); let position; do { position = Math.floor(Math.random()*columns/2); }while(occupiedPositions.has(position)) occupiedPositions.add(position); vechicle.position.x = (position*positionWidth*2+positionWidth/2)*zoom-boardWidth*zoom/2; if(!this.direction) vechicle.rotation.z = Math.PI; this.mesh.add( vechicle ); return vechicle; }) this.speed = laneSpeeds[Math.floor(Math.random()*laneSpeeds.length)]; break; } case 'truck' : { this.mesh = new Road(); this.direction = Math.random() >= 0.5; const occupiedPositions = new Set(); this.vechicles = [1,2].map(() => { const vechicle = new Truck(); let position; do { position = Math.floor(Math.random()*columns/3); }while(occupiedPositions.has(position)) occupiedPositions.add(position); vechicle.position.x = (position*positionWidth*3+positionWidth/2)*zoom-boardWidth*zoom/2; if(!this.direction) vechicle.rotation.z = Math.PI; this.mesh.add( vechicle ); return vechicle; }) this.speed = laneSpeeds[Math.floor(Math.random()*laneSpeeds.length)]; break; } } } document.querySelector("#retry").addEventListener("click", () => { lanes.forEach(lane => scene.remove( lane.mesh )); initaliseValues(); endDOM.style.visibility = 'hidden'; }); document.getElementById('forward').addEventListener("click", () => move('forward')); document.getElementById('backward').addEventListener("click", () => move('backward')); document.getElementById('left').addEventListener("click", () => move('left')); document.getElementById('right').addEventListener("click", () => move('right')); window.addEventListener("keydown", event => { if (event.keyCode == '38') { // up arrow move('forward'); } else if (event.keyCode == '40') { // down arrow move('backward'); } else if (event.keyCode == '37') { // left arrow move('left'); } else if (event.keyCode == '39') { // right arrow move('right'); } }); function move(direction) { const finalPositions = moves.reduce((position,move) => { if(move === 'forward') return {lane: position.lane+1, column: position.column}; if(move === 'backward') return {lane: position.lane-1, column: position.column}; if(move === 'left') return {lane: position.lane, column: position.column-1}; if(move === 'right') return {lane: position.lane, column: position.column+1}; }, {lane: currentLane, column: currentColumn}) if (direction === 'forward') { if(lanes[finalPositions.lane+1].type === 'forest' && lanes[finalPositions.lane+1].occupiedPositions.has(finalPositions.column)) return; if(!stepStartTimestamp) startMoving = true; addLane(); } else if (direction === 'backward') { if(finalPositions.lane === 0) return; if(lanes[finalPositions.lane-1].type === 'forest' && lanes[finalPositions.lane-1].occupiedPositions.has(finalPositions.column)) return; if(!stepStartTimestamp) startMoving = true; } else if (direction === 'left') { if(finalPositions.column === 0) return; if(lanes[finalPositions.lane].type === 'forest' && lanes[finalPositions.lane].occupiedPositions.has(finalPositions.column-1)) return; if(!stepStartTimestamp) startMoving = true; } else if (direction === 'right') { if(finalPositions.column === columns - 1 ) return; if(lanes[finalPositions.lane].type === 'forest' && lanes[finalPositions.lane].occupiedPositions.has(finalPositions.column+1)) return; if(!stepStartTimestamp) startMoving = true; } moves.push(direction); } function animate(timestamp) { requestAnimationFrame( animate ); if(!previousTimestamp) previousTimestamp = timestamp; const delta = timestamp - previousTimestamp; previousTimestamp = timestamp; // Animate cars and trucks moving on the lane lanes.forEach(lane => { if(lane.type === 'car' || lane.type === 'truck') { const aBitBeforeTheBeginingOfLane = -boardWidth*zoom/2 - positionWidth*2*zoom; const aBitAfterTheEndOFLane = boardWidth*zoom/2 + positionWidth*2*zoom; lane.vechicles.forEach(vechicle => { if(lane.direction) { vechicle.position.x = vechicle.position.x < aBitBeforeTheBeginingOfLane ? aBitAfterTheEndOFLane : vechicle.position.x -= lane.speed/16*delta; }else{ vechicle.position.x = vechicle.position.x > aBitAfterTheEndOFLane ? aBitBeforeTheBeginingOfLane : vechicle.position.x += lane.speed/16*delta; } }); } }); if(startMoving) { stepStartTimestamp = timestamp; startMoving = false; } if(stepStartTimestamp) { const moveDeltaTime = timestamp - stepStartTimestamp; const moveDeltaDistance = Math.min(moveDeltaTime/stepTime,1)*positionWidth*zoom; const jumpDeltaDistance = Math.sin(Math.min(moveDeltaTime/stepTime,1)*Math.PI)*8*zoom; switch(moves[0]) { case 'forward': { camera.position.y = initialCameraPositionY + currentLane*positionWidth*zoom + moveDeltaDistance; chicken.position.y = currentLane*positionWidth*zoom + moveDeltaDistance; // initial chicken position is 0 chicken.position.z = jumpDeltaDistance; break; } case 'backward': { camera.position.y = initialCameraPositionY + currentLane*positionWidth*zoom - moveDeltaDistance; chicken.position.y = currentLane*positionWidth*zoom - moveDeltaDistance; chicken.position.z = jumpDeltaDistance; break; } case 'left': { camera.position.x = initialCameraPositionX + (currentColumn*positionWidth+positionWidth/2)*zoom -boardWidth*zoom/2 - moveDeltaDistance; chicken.position.x = (currentColumn*positionWidth+positionWidth/2)*zoom -boardWidth*zoom/2 - moveDeltaDistance; // initial chicken position is 0 chicken.position.z = jumpDeltaDistance; break; } case 'right': { camera.position.x = initialCameraPositionX + (currentColumn*positionWidth+positionWidth/2)*zoom -boardWidth*zoom/2 + moveDeltaDistance; chicken.position.x = (currentColumn*positionWidth+positionWidth/2)*zoom -boardWidth*zoom/2 + moveDeltaDistance; chicken.position.z = jumpDeltaDistance; break; } } // Once a step has ended if(moveDeltaTime > stepTime) { switch(moves[0]) { case 'forward': { currentLane++; counterDOM.innerHTML = currentLane; break; } case 'backward': { currentLane--; counterDOM.innerHTML = currentLane; break; } case 'left': { currentColumn--; break; } case 'right': { currentColumn++; break; } } moves.shift(); // If more steps are to be taken then restart counter otherwise stop stepping stepStartTimestamp = moves.length === 0 ? null : timestamp; } } // Hit test if(lanes[currentLane].type === 'car' || lanes[currentLane].type === 'truck') { const chickenMinX = chicken.position.x - chickenSize*zoom/2; const chickenMaxX = chicken.position.x + chickenSize*zoom/2; const vechicleLength = { car: 60, truck: 105}[lanes[currentLane].type]; lanes[currentLane].vechicles.forEach(vechicle => { const carMinX = vechicle.position.x - vechicleLength*zoom/2; const carMaxX = vechicle.position.x + vechicleLength*zoom/2; if(chickenMaxX > carMinX && chickenMinX < carMaxX) { endDOM.style.visibility = 'visible'; } }); } renderer.render( scene, camera ); } requestAnimationFrame( animate );
粒子
时间
文字
hover
canvas
3d
游戏
音乐
火焰
水波
轮播图
鼠标跟随
动画
css
加载动画
导航
菜单
按钮
滑块
tab
弹出层
统计图
svg
×
Close
在线代码下载提示
开通在线代码永久免费下载,需支付20jQ币
开通后,在线代码模块中所有代码可终身免费下!
您已开通在线代码永久免费下载,关闭提示框后,点下载代码可直接下载!
您已经开通过在线代码永久免费下载
对不起,您的jQ币不足!可通过发布资源 或
直接充值获取jQ币
取消
开通下载
<!doctype html> <html> <head> <meta charset="utf-8"> <title>three.js横穿马路小游戏-jq22.com</title> <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script> <style>
</style> </head> <body>
<script>
</script>
</body> </html>
2012-2021 jQuery插件库版权所有
jquery插件
|
jq22工具库
|
网页技术
|
广告合作
|
在线反馈
|
版权声明
沪ICP备13043785号-1
浙公网安备 33041102000314号