相信大家都玩过王者荣耀吧,那么王者荣耀在html中要怎么实现呢?
话不多说,上代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>王者地图</title><script src="./three.min.js"></script><script src="./MOBAControls.js"></script><script src="./DRACOLoader.min.js"></script><script src="./GLTFLoader.min.js"></script><script src="./nipplejs.min.js"></script><script src="./vconsole.min.js"></script><script src="https://cdn.bootcss.com/tween.js/r14/Tween.min.js"></script>
</head>
<style>html, body, #output{width: 100%;height: 100%;padding: 0;margin: 0;overflow: hidden;}#layer{width: 100%;height: 100%;position: absolute;background-color: rgba(211, 226, 226, 0.4);top: 0;left: 0;}.loading{position: absolute;top: 50%;left: 50%;transform: translateX(-50%) translateY(-50%);z-index: 10;width: 60px;height: 40px;margin: 0 auto;}.loading span{display: inline-block;width: 8px;height: 100%;border-radius: 4px;background: lightgreen;-webkit-animation: load 1s ease infinite;}@-webkit-keyframes load{0%,100%{height: 40px;background: lightgreen;}50%{height: 70px;margin: -15px 0;background: lightblue;}}.loading span:nth-child(2){-webkit-animation-delay:0.2s;}.loading span:nth-child(3){-webkit-animation-delay:0.4s;}.loading span:nth-child(4){-webkit-animation-delay:0.6s;}.loading span:nth-child(5){-webkit-animation-delay:0.8s;}.tip{position: absolute;top: 50%;left: 50%;transform: translateX(-50%) translateY(20px);z-index: 10;}.tip span{color: #0ff}
</style>
<body><div id="layer"><div class="loading"><span></span><span></span><span></span><span></span><span></span></div><div class='tip'><span>开启屏幕旋转可以横置屏幕</span></div></div><div id="output"></div>
</body>
<script>// 'dev' / 'prod'// const evirenment = 'dev'const evirenment = 'prod'if(evirenment == 'dev'){new VConsole()}window.onload = () => {let name = evirenment == 'dev'? '汤圆skr狠人': prompt('请给自己角色取个名字,碰撞检测已暂时被注释', '如: 王xx')name = name || '王xx'let scenelet cameralet rendererconst init = (dom) => {scene = new THREE.Scene()let ambientLight = new THREE.AmbientLight( 0xffffff)scene.add(ambientLight)let light = new THREE.DirectionalLight( 0xffffff)light.castShadow = truelight.shadow.camera.left = light.shadow.camera.bottom = -300light.shadow.camera.right = light.shadow.camera.top = 300light.position.set(10, -50, 100)scene.add(light)size = {width: dom.offsetWidth,height: dom.offsetHeight}camera = new THREE.PerspectiveCamera(45, size.width / size.height, 0.5, 20000)evirenment == 'dev'? camera.position.set(30, 30, 30): camera.position.set(30, 30, 30)camera.up.set(0, 0, 1)renderer = new THREE.WebGLRenderer({antialias: true,alpha: true})renderer.setSize(size.width, size.height)renderer.setClearColor(0x000000)renderer.setPixelRatio(window.devicePixelRatio)dom.appendChild(renderer.domElement)renderer.gammaFactor = 2renderer.gammaOutput = truerenderer.shadowMap.enabled = true}var dom = document.querySelector('#output')init(dom)let controlslet loader = new THREE.GLTFLoader().setPath( evirenment == 'dev' ? './model/': 'https://xiongtongzi.oss-cn-shanghai.aliyuncs.com/model/');THREE.DRACOLoader.setDecoderPath( evirenment == 'dev' ? './model/': 'https://xiongtongzi.oss-cn-shanghai.aliyuncs.com/model/' );loader.setDRACOLoader( new THREE.DRACOLoader() )class LevelBlood{constructor(name, options){this.color = options.color || 0x0000ff // 血条颜色this.totalBlood = options.totalBlood|| 500// 总血量this.currentBlood = options.currentBlood || 500 //即时血量this.totalBlue = options.totalBlue|| 100// 总蓝量this.currentBlue = options.currentBlue || 100 //即时蓝量this.level = options.level || 1//初始等级this.bloodCellNumber = options.cellNumber || 100//单刻度值this.backgroundColor = options.backgroundColor || '#001'//整个背景色this.bloodColor = options.bloodColor || '#0f0' //血条颜色this.blueColor = options.blueColor || '#00f' //蓝条颜色this.totalInLevel = options.totalInLevel || 100 //级内总进度this.inLevel = options.inLevel || 0 //级内进度this.name = namethis.init()this.draw()}init(){this.canvas = document.createElement('canvas')this.canvas.width = 512this.canvas.height = 128this.ctx = this.canvas.getContext('2d')}config(options){this.color = options.color || this.color// 血条颜色this.totalBlood = options.totalBlood|| this.totalBlood// 总血量this.currentBlood = options.currentBlood || this.currentBlood //即时血量this.totalBlue = options.totalBlue|| this.totalBlue// 总蓝量this.currentBlue = options.currentBlue || this.currentBlue //即时蓝量this.level = options.level || this.level//初始等级this.bloodCellNumber = options.cellNumber || this.bloodCellNumber//单刻度值this.backgroundColor = options.backgroundColor || this.backgroundColor//整个背景色this.bloodColor = options.bloodColor || this.bloodColor //血条颜色this.blueColor = options.blueColor || this.blueColor //蓝条颜色this.totalInLevel = options.totalInLevel || this.totalInLevel //级内总进度this.inLevel = options.inLevel || this.inLevel //级内进度this.draw()}draw(){this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)// 绘圆this.ctx.fillStyle = this.backgroundColorlet halfHeight = this.canvas.height / 2let r = halfHeight * .8this.ctx.arc(halfHeight, halfHeight, r, 0, Math.PI * 2)this.ctx.fill()// 绘矩形let rectHeight = 50let marginTop = (this.canvas.height - rectHeight) * .5let marginBottom = (this.canvas.height + rectHeight) * .5this.ctx.fillStyle = this.backgroundColorthis.ctx.beginPath()this.ctx.moveTo(halfHeight, marginTop)this.ctx.lineTo(this.canvas.width, marginTop)this.ctx.lineTo(this.canvas.width, marginBottom)this.ctx.lineTo(halfHeight, marginBottom)this.ctx.lineTo(halfHeight, marginTop)this.ctx.fill()this.ctx.closePath()//级内经验占位this.ctx.strokeStyle = '#000'this.ctx.lineWidth = 5this.ctx.beginPath()this.ctx.arc(halfHeight, halfHeight, r * 0.8, 0, Math.PI * 2)this.ctx.stroke()this.ctx.closePath()//级内经验this.ctx.strokeStyle = '#ff7f00'this.ctx.lineWidth = 5this.ctx.beginPath()this.ctx.arc(halfHeight, halfHeight, r * 0.8, - Math.PI * .5, this.inLevel / this.totalInLevel * Math.PI * 2 - Math.PI * .5)this.ctx.stroke()this.ctx.closePath()// 绘制等级this.ctx.font = 'bold 40px Arial'this.ctx.textAlign = 'center'this.ctx.fillStyle = '#fff'this.ctx.textBaseline ="middle"this.ctx.fillText(this.level, halfHeight, halfHeight)//绘制名称this.ctx.font = 'bold 40px Arial'this.ctx.textAlign = 'center'this.ctx.fillStyle = '#fff'this.ctx.textBaseline ="top"this.ctx.fillText(this.name, (this.canvas.width - this.canvas.height) * .5 + this.canvas.height, 0)let offsetY = 8let offsetX = 8let totalHeight = rectHeight - offsetY * 3let blueBloodStart = halfHeight + rlet bloodBlueTotalLength = this.canvas.width - offsetX - blueBloodStart//绘制蓝条let blueCurrentLength = blueBloodStart + this.currentBlue / this.totalBlue * bloodBlueTotalLengththis.ctx.fillStyle = this.blueColorthis.ctx.beginPath()this.ctx.moveTo(blueBloodStart, marginBottom - totalHeight * .2 - offsetY)this.ctx.lineTo(blueCurrentLength, marginBottom - totalHeight * .2 - offsetY)this.ctx.lineTo(blueCurrentLength, marginBottom - offsetY)this.ctx.lineTo(blueBloodStart, marginBottom - offsetY)this.ctx.lineTo(blueBloodStart, marginBottom - totalHeight * .2 - offsetY)this.ctx.fill()this.ctx.closePath()//绘制血条let bloodCurrentLength = blueBloodStart + this.currentBlood / this.totalBlood * bloodBlueTotalLengththis.ctx.fillStyle = this.bloodColorthis.ctx.beginPath()this.ctx.moveTo(blueBloodStart, marginTop + offsetY)this.ctx.lineTo(bloodCurrentLength, marginTop + offsetY)this.ctx.lineTo(bloodCurrentLength, marginTop + totalHeight * .8 + offsetY)this.ctx.lineTo(blueBloodStart, marginTop + totalHeight * .8 + offsetY)this.ctx.lineTo(blueBloodStart, marginTop + offsetY)this.ctx.fill()this.ctx.closePath()//血量刻度this.ctx.strokeStyle = this.backgroundColorthis.ctx.lineWidth = 6let splitNumber = this.totalBlood / this.bloodCellNumberlet step = (this.canvas.width - offsetX - blueBloodStart) / splitNumberfor(let i = 0; i < splitNumber; i ++){let length = 12if(i % 5 == 0){length = 20}this.ctx.beginPath()this.ctx.moveTo(blueBloodStart + i * step, marginTop + offsetY)this.ctx.lineTo(blueBloodStart + i * step, marginTop + offsetY + length)this.ctx.stroke()this.ctx.closePath()}}test(id){// 测试输出用let dom = document.querySelector(id)dom.appendChild(this.canvas)}}var mixer, action;let ssxObject, ssxOriginRotationlet clock = new THREE.Clock()let deltalet spritelet levelBloodconst speedNumber = evirenment == 'dev' ? 1 : 0.2let speed = new THREE.Vector2()//设置站立const setStand = () => {speed.set(0, 0)action && action.stop()}const go = (x, y) => {speed.set(x, y)action && action.play()}loader.load( 'model.gltf', function ( gltf ) {gltf.scene.rotation.x = Math.PI * .5gltf.scene.rotation.y = -Math.PI * .25gltf.scene.traverse((item) => {if(item.material){item.material = new THREE.MeshBasicMaterial({map: item.material.map, transparent: true, alphaTest: 0.9})}if(item.children.length > 0 && (item.name.includes('地') || item.name.includes('路'))){item.traverse((child) => {child.receiveShadow = true})}})scene.add(gltf.scene)let tl = new THREE.TextureLoader()tl.setPath( evirenment == 'dev' ? './model/': 'https://xiongtongzi.oss-cn-shanghai.aliyuncs.com/model/')loader.load('ssx.gltf', (ssx) => {ssx.scene.rotation.x = Math.PI * .5ssx.scene.rotation.y = Math.PI * 1.5ssxOriginRotation = ssx.scene.rotation.clone()ssx.scene.scale.set(4, 4, 4)ssx.scene.position.set(218.27291759843078, -4.683324102610722, 0)ssx.scene.traverse((obj) => {if(obj.material){let name = obj.nameobj.material.map = tl.load(name + '.png')obj.castShadow = true}})scene.add(ssx.scene)ssxObject = ssx.scenecontrols = new MOBAControls( camera, {dom: renderer.domElement,target: ssxObject})mixer = new THREE.AnimationMixer(ssx.scene)action = mixer.clipAction(ssx.animations[0])levelBlood = new LevelBlood(name + '', {inLevel: 49})levelBlood.test('#output')sprite = new THREE.Sprite(new THREE.SpriteMaterial({map: new THREE.CanvasTexture(levelBlood.canvas),transparent: true,alphaTest: 0.6}))sprite.scale.set(8, 2, 1)scene.add(sprite)document.querySelector('#layer').style.display = 'none'let manager = nipplejs.create({zone: dom,multitouch: true,maxNumberOfNipples: 1,color: 'black'})let position = new THREE.Vector2()manager.on('start', (evt, data) => {let {x, y} = data.positionposition.set(x, y)})let pointerRaycaster = new THREE.Raycaster()manager.on('move', (evt, data) => {let {x, y} = data.positionlet offset = position.clone()let length = offset.sub(new THREE.Vector2(x, y)).length()// 限制最小响应if(length < 20){setStand()return}if(data.angle){let degree = data.angle.radian - Math.PI * .25let {x, y, z} = ssxOriginRotationssxObject.rotation.set(x, y + degree, z)go(- Math.cos(degree), - Math.sin(degree))// let {x: posx, y: posy} = ssxObject.position// // 射线判断// pointerRaycaster.set(new THREE.Vector3(posx, posy, 1), new THREE.Vector3(- Math.cos(degree), - Math.sin(degree), 0).normalize())// let raycasterGet = pointerRaycaster.intersectObjects(gltf.scene.children, true)// // console.log(raycasterGet)// if(raycasterGet.length > 0){// let one = raycasterGet[0]// if(one.distance < 1){// speed.set(0, 0)// console.log('停止')// }// }}else{setStand()}})manager.on('end', (evt, data) => {setStand()position.set(0, 0)})})})// nipple.js全面替代键盘操作// const keyDown = (e) => {// e.preventDefault()// let keyCode = e.keyCode// if(!ssxObject) return// if(keyCode == 87 || keyCode == 38){//w// speed.y = -1// }// if(keyCode == 65 || keyCode == 37){//a// speed.x = 1// }// if(keyCode == 83 || keyCode == 40){//s// speed.y = 1// }// if(keyCode == 68 || keyCode == 39){//d// speed.x = -1// }// }// const keyUp = (e) => {// e.preventDefault()// let keyCode = e.keyCode// if(!ssxObject) return// if(keyCode == 87 || keyCode == 38){// speed.y = 0// }// if(keyCode == 65 || keyCode == 37){// speed.x = 0// }// if(keyCode == 83 || keyCode == 40){// speed.y = 0// }// if(keyCode == 68 || keyCode == 39){// speed.x = 0// }// }const render = () => {controls && controls.update()delta = clock.getDelta()if(ssxObject){if(speed.length() > 0){let {x, y} = speed.clone().normalize().multiplyScalar(speedNumber)ssxObject.position.y += yssxObject.position.x += xlevelBlood.currentBlue > 0 && levelBlood.config({currentBlue: levelBlood.currentBlue - 0.2})levelBlood.currentBlood > 0 && levelBlood.config({currentBlood: levelBlood.currentBlood - 0.1})}else{levelBlood.currentBlue < levelBlood.totalBlue && levelBlood.config({currentBlue: levelBlood.currentBlue + 0.1})levelBlood.currentBlood < levelBlood.totalBlood && levelBlood.config({currentBlood: levelBlood.currentBlood + 0.05})}sprite.material.map.image = levelBlood.canvassprite.material.map.needsUpdate = true}sprite && sprite.position.copy(ssxObject.position).add(new THREE.Vector3(0, 0, 9))mixer && mixer.update( delta );renderer.render(scene, camera)requestAnimationFrame(render)}render()let mouse = new THREE.Vector2()let raycaster = new THREE.Raycaster()const move = (e) => {mouse.x = ((e.clientX - dom.getBoundingClientRect().left) / dom.offsetWidth) * 2 - 1mouse.y = -((e.clientY - dom.getBoundingClientRect().top) / dom.offsetHeight) * 2 + 1raycaster.setFromCamera( mouse, camera )let intersects = raycaster.intersectObjects(scene.children, true)if(intersects.length > 0){console.log(intersects[0])}}dom.addEventListener('click', move, false)const resize = () => {var size = {width: dom.offsetWidth,height: dom.offsetHeight}renderer.setSize(size.width, size.height)camera.aspect = size.width / size.heightcamera.updateProjectionMatrix()}window.addEventListener('resize', resize, false)// const FullScreen = () => {// let isFullscreen = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen// if(!isFullscreen){//进入全屏,多重短路表达式// (document.requestFullscreen && document.requestFullscreen())||// (document.mozRequestFullScreen && document.mozRequestFullScreen())||// (document.webkitRequestFullscreen && document.webkitRequestFullscreen())||// (document.msRequestFullscreen && document.msRequestFullscreen());// }else{ //退出全屏,三目运算符// document.exitFullscreen ? document.exitFullscreen():// document.mozCancelFullScreen ? document.mozCancelFullScreen():// document.webkitExitFullscreen ? document.webkitExitFullscreen():'';// }// }const orientationchange = () => {if(window.innerHeight < window.innerWidth){console.log('full')// document.body.requestFullscreen && document.body.requestFullscreen()}else{console.log('exist')// document.exitFullscreen && document.exitFullscreen()}resize()}// window.addEventListener('orientationchange', orientationchange, false);// window.addEventListener('keydown', keyDown, false)// window.addEventListener('keyup', keyUp, false)}</script>
</html>
代码片段不全
全部代码加我VX :lingyuwuhongyuan领取