three编写一个微信跳一跳小游戏效果代码
代码语言:html
所属分类:游戏
代码描述:three编写一个微信跳一跳小游戏效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, maximum-scale=1, user-scalable=no"> <style> body{ padding: 0; margin: 0; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .mask{ display: none; flex-direction: column; justify-content: center; align-items: center; position: fixed; width: 100%; height: 100%; background: rgba(0,0,0,0.4); } .content{ display: flex; flex-direction: column; align-items: center; justify-content: center; width: 500px; height: 500px; border-radius: 20px; background: rgba(0,0,0,0.4); border: 5px solid rgba(255,255,255,0.05); } .score-container{ color: #ffffff; /* color: #232323; */ text-align: center; } .title{ font-size: 20px; font-weight: bold; /* color: rgba(255,255,255,0.6); */ } .score{ font-size: 100px; font-weight: bold; margin-top: 20px; } button.restart{ width: 200px; height: 40px; border-radius: 20px; background: white; border: none; font-weight: bold; font-size: 20px; cursor: pointer; } button.restart:hover{ color:#232323; } .info{ margin: 20px 0; position: absolute; text-align: center; width:100%; color: rgba(255,255,255,0.2); } .info a{ /* display: block; */ font-size: 16px; line-height: 28px; color: rgba(255,255,255,0.2); /* color: #232323; */ text-decoration: none; } a.title{ font-size: 20px; font-weight: bold; } .score-gaming{ margin-top: 10px; color: rgba(255,255,255,1); font-size: 16px; } </style> </head> <body> <div class="mask"> <div class="content"> <div class="score-container"> <p class="title">本次得分</p> <p>历史最高: <span class="record">0</span></p> <p class="score">0</p> </div> <button class="restart"> 重新开始 </button> </div> </div> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.88.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/createjs-1.3.2.js"></script> <script> // 通过canvas创建材质 var canvasTexture = null; function clock() { canvasTexture = document.createElement('canvas'); canvasTexture.width=200; canvasTexture.height=200; var ctx = canvasTexture.getContext('2d'); if(ctx){ var timerId; var frameRate = 60; function canvObject(){ this.x = 0; this.y = 0; this.rotation = 0; this.borderWidth = 2; this.borderColor = '#000000'; this.fill = false; this.fillColor = '#ff0000'; this.update = function(){ if(!this.ctx)throw new Error('你没有指定ctx对象。'); var ctx = this.ctx ctx.save(); ctx.lineWidth = this.borderWidth; ctx.strokeStyle = this.borderColor; ctx.fillStyle = this.fillColor; ctx.translate(this.x, this.y); if(this.rotation)ctx.rotate(this.rotation * Math.PI/180); if(this.draw)this.draw(ctx); if(this.fill)ctx.fill(); ctx.stroke(); ctx.restore(); } }; function Line(){}; Line.prototype = new canvObject(); Line.prototype.fill = false; Line.prototype.start = [0,0]; Line.prototype.end = [5,5]; Line.prototype.draw = function(ctx){ ctx.beginPath(); ctx.moveTo.apply(ctx,this.start); ctx.lineTo.apply(ctx,this.end); ctx.closePath(); }; function Circle(){}; Circle.prototype = new canvObject(); Circle.prototype.draw = function(ctx){ ctx.beginPath(); ctx.arc(0, 0, this.radius, 0, 2 * Math.PI, true); ctx.closePath(); }; var circle = new Circle(); circle.ctx = ctx; circle.x = 100; circle.y = 100; circle.radius = 90; circle.fill = true; circle.borderWidth = 6; circle.fillColor = '#ffffff'; var hour = new Line(); hour.ctx = ctx; hour.x = 100; hour.y = 100; hour.borderColor = "#000000"; hour.borderWidth = 10; hour.rotation = 0; hour.start = [0,20]; hour.end = [0,-50]; var minute = new Line(); minute.ctx = ctx; minute.x = 100; minute.y = 100; minute.borderColor = "#333333"; minute.borderWidth = 7; minute.rotation = 0; minute.start = [0,20]; minute.end = [0,-70]; var seconds = new Line(); seconds.ctx = ctx; seconds.x = 100; seconds.y = 100; seconds.borderColor = "#ff0000"; seconds.borderWidth = 4; seconds.rotation = 0; seconds.start = [0,20]; seconds.end = [0,-80]; var center = new Circle(); center.ctx = ctx; center.x = 100; center.y = 100; center.radius = 5; center.fill = true; center.borderColor = 'orange'; for(var i=0,ls=[],cache;i<12;i++){ cache = ls[i] = new Line(); cache.ctx = ctx; cache.x = 100; cache.y = 100; cache.borderColor = "orange"; cache.borderWidth = 2; cache.rotation = i * 30; cache.start = [0,-70]; cache.end = [0,-80]; } timerId = setInterval(function(){ // 清除画布 ctx.clearRect(0,0,200,200); // 填充背景色 ctx.fillStyle = 'orange'; ctx.fillRect(0,0,200,200); // 表盘 circle.update(); // 刻度 for(var i=0;cache=ls[i++];)cache.update(); // 时针 hour.rotation = (new Date()).getHours() * 30; hour.update(); // 分针 minute.rotation = (new Date()).getMinutes() * 6; minute.update(); // 秒针 seconds.rotation = (new Date()).getSeconds() * 6; seconds.update(); // 中心圆 center.update(); },(1000/frameRate)|0); }else{ alert('您的浏览器不支持Canvas无法预览!"'); } } clock(); var Game = function () { // 基本参数 this.config = { isMobile: false, helper: false, // 默认关闭helper background: 0x282828, // 背景颜色 ground: -1, // 地面y坐标 fallingSpeed: 0.2, // 游戏失败掉落速度 cubeColor: 0xbebebe, cubeWidth: 3, // 方块宽度 cubeHeight: 1, // 方块高度 cubeDeep: 3, // 方块深度 // cubeWidth: 4, // 方块宽度 // cubeHeight: 2, // 方块高度 // cubeDeep: 4, // 方块深度 jumperColor: 0x333333, jumperWidth: 1, // jumper宽度 jumperHeight: 2, // jumper高度 jumperDeep: 1, // jumper深度 } // 游戏状态 this.score = 0 this.size = { width: window.innerWidth, height: window.innerHeight } this.scene = new THREE.Scene() this.cameraPos = { current: new THREE.Vector3(0, 0, 0), // 摄像机当前的坐标 next: new THREE.Vector3() // 摄像机即将要移到的位置 } this.camera = new THREE.OrthographicCamera(this.size.width / -80, this.size.width / 80, this.size.height / 80, this.size.height / -80, 0, 5000) this.renderer = new THREE.WebGLRenderer({antialias: true}) var planceGeometry = new THREE.PlaneGeometry(this.size.width, this.size.height); // PlaneGeometry: 翻译 平面几何 (参数: 宽60, 高20) var planeMaterial = new THREE.MeshLambertMaterial({ color: 0xdddddd }); // MeshLambertMaterial: 翻译 网格材质 (用来设置平面的外观, 颜色,透明度等) var plane = new THREE.Mesh(planceGeometry, planeMaterial); // 把这2个对象合并到一个名为plane(平面)的Mesh(网格)对象中 plane.receiveShadow = true; // 平面接收阴影 plane.rotation.x = -0.5*Math.PI; // 绕x轴旋转90度 plane.position.x = 0; // 平面坐标位置 plane.position.y = -1; plane.position.z = 0; this.plane = plane; this.scene.add(this.plane); // 将平面添加到场景 this.cubes = [] // 方块数组 this.cubeStat = { nextDir: '' // 下一个方块相对于当前方块的方向: 'left' 或 'right' } this.jumperStat = { ready: false, // 鼠标按完没有 xSpeed: 0, // xSpeed根据鼠标按的时间进行赋值 ySpeed: 0 // ySpeed根据鼠标按的时间进行赋值 } this.falledStat = { location: -1, // jumper所在的位置 distance: 0 // jumper和最近方块的距离 } this.fallingStat = { speed: 0.2, // 游戏失败后垂直方向上的掉落速度 end: false // 掉到地面没有 } this.combo = 0; // 连续调到中心的次数,起始为0 } Game.prototype = { init: function () { this._checkUserAgent() // 检测是否移动端 this._setCamera() // 设置摄像机位置 this._setRenderer() // 设置渲染器参数 this._setLight() // 设置光照 this._createCube() // 加一个方块 this._createCube() // 再加一个方块 this._createJumper() // 加入游戏者jumper this._updateCamera() // 更新相机坐标 if(this.config.helper){ // 开启helper this._createHelpers(); } var self = this var mouseEvents = (self.config.isMobile) ? { down: 'touchstart', up: 'touchend', } : { down: 'mousedown', up: 'mouseup', } // 事件绑定到canvas中 var canvas = document.querySelector('canvas') canvas.addEventListener(mouseEvents.down, function () { // console.log('mousedown'); self._handleMousedown() }) // 监听鼠标松开的事件 canvas.addEventListener(mouseEvents.up, function (evt) { // console.log('mouseup'); self._handleMouseup() }) // 监听窗口变化的事件 window.addEventListener('resize', function () { self._handleWindowResize() }) }, // 游戏失败重新开始的初始化配置 restart: function () { this.score = 0 this.cameraPos = { current: new THREE.Vector3(0, 0, 0), next: new THREE.Vector3() } this.fallingStat = { speed: 0.2, end: false } // 删除所有方块 var length = this.cubes.length for(var i=0; i < length; i++){ this.scene.remove(this.cubes.pop()) } // 删除jumper this.scene.remove(this.jumper) // 显示的分数设为 0 this.successCallback(this.score) this._createCube() this._createCube() this._createJumper() this._updateCamera() }, // 游戏成功的执行函数, 外部传入 addSuccessFn: function (fn) { this.successCallback = fn }, // 游戏失败的执行函数, 外部传入 addFailedFn: function (fn) { this.failedCallback = fn }, // 检测是否手机端 _checkUserAgent: function () { var n = navigator.userAgent; if (n.match(/Android/i) || n.match(/webOS/i) || n.match(/iPhone/i) || n.match(/iPad/i) || n.match(/iPod/i) || n.match(/BlackBerry/i)){ this.config.isMobile = true } }, // THREE.js辅助工具 _createHelpers: function () { // 法向量辅助线 var axesHelper = new THREE.AxesHelper(10) this.scene.add(axesHelper); // 平行光辅助线 var helper = new THREE.DirectionalLightHelper(this.directionalLight, 5 ); this.scene.add( helper ); }, // 窗口缩放绑定的函数 _handleWindowResize: function () { this._setSize() this.camera.left = this.size.width / -80 this.camera.right = this.size.width / 80 this.camera.top = this.size.height / 80 this.camera.bottom = this.size.height / -80 this.camera.updateProjectionMatrix() this.renderer.setSize(this.size.width, this.size.height) this._render() }, /** *鼠标按下或触摸开始绑定的函数 *根据鼠标按下的时间来给 xSpeed 和 ySpeed 赋值 *@return {Number} this.jumperStat.xSpeed 水平方向上的速度 *@return {Number} this.jumperStat.ySpeed 垂直方向上的速度 **/ _handleMousedown: function () { var self = this function act() { // if (!self.jumperStat.ready && self.jumper.scale.y > 0.02) { // 以jumperBody蓄力一半为最大值 if (!self.jumperStat.ready && self.jumperBody.scale.y > 0.02 && self.jumperBody.scale.y >= 0.5) { self.jumperBody.scale.y -= 0.01 // jumper随按压时间降低高度,即减小jumper.scale.y值 // self.jumper.scale.y -= 0.01 // jumper随按压时间降低高度,即减小jumper.scale.y值 self.jumperHead.position.y -= 0.02 // jumper头部跟随下降 self.jumperStat.xSpeed += 0.004 self.jumperStat.ySpeed += 0.008 self.jumperStat.yTimes = (1 - self.jumperBody.scale.y) / 0.01; // 计算倍数, 用于jumper在y轴的旋转 // console.log( self.jumperBody.scale.y, self.jumperStat.yTimes ); self.mouseDownFrameHandler = requestAnimationFrame(act); } self._render(self.scene, self.camera); } act(); }, // 鼠标松开或触摸结束绑定的函数 _handleMouseup: function () { var self = this // 标记鼠标已经松开 self.jumperStat.ready = true; cancelAnimationFrame(self.mouseDownFrameHandler); var frameHandler; function act() { // 判断jumper是在方块水平面之上,是的话说明需要继续运动 // if (self.jumper.position.y >= 1) { // 此处不应该只判断jumper的位置,而是应该判断jumper的y速度 if (self.jumperStat.ySpeed > 0 || self.jumper.position.y >= 1) { // jumper根据下一个方块的位置来确定水平运动方向 var jumperRotateBase = self.jumperStat.yTimes / 2; if (self.cubeStat.nextDir === 'left') { self.jumper.position.x -= self.jumperStat.xSpeed // 在20倍以上的程度才有翻转效果 // if(self.jumperStat.yTimes > 30){ // // 小人起跳翻转 // if(self.jumper.rotation.z < Math.PI*2){ // self.jumper.rotation.z += Math.PI / jumperRotateBase; // } // // 到达最高点 // if(self.jumperStat.ySpeed == 0){ // self.jumper.rotation.z = Math.PI; // } // } } else { self.jumper.position.z -= self.jumperStat.xSpeed // 在20倍以上的程度才有翻转效果 // if(self.jumperStat.yTimes > 30){ // // 小人起跳翻转 // if(self.jumper.rotation.x < Math.PI*2){ // self.jumper.rotation.x -= Math.PI / jumperRotateBase; // } // // 到达最高点 // if(self.jumperStat.ySpeed == 0){ // self.jumper.rotation.x = -Math.PI; // } // } } // jumper在垂直方向上运动 self.jumper.position.y += self.jumperStat.ySpeed // 运动伴随着缩放 if ( self.jumperBody.scale.y < 1 ) { self.jumperBody.scale.y += 0.02; self.jumperHead.position.y += 0.02 // 头部跟随上升 } // jumper在垂直方向上先上升后下降 self.jumperStat.ySpeed -= 0.01 // 每一次的变化,渲染器都要重新渲染,才能看到渲染效果 self._render(self.scene, self.camera) frameHandler = requestAnimationFrame(act); }else{ cancelAnimationFrame(frameHandler); landed(); } } function landed() { // 用于测试combo,手动设置掉到正中心 // self.jumper.position.x = self.cubes[self.cubes.length - 1].position.x; // self.jumper.position.z = self.cubes[self.cubes.length - 1].position.z; // jumper掉落到方块水平位置,开始充值状态,并开始判断掉落是否成功 self.jumperStat.ready = false self.jumperStat.xSpeed = 0 self.jumperStat.ySpeed = 0 self.jumper.position.y = .5 // 还原jumper的旋转角度和head的位置 self.jumper.rotation.z = 0 self.jumper.rotation.x = 0 self.jumperHead.position.y = 0 self._checkInCube(); if (self.falledStat.location === 1) { // 播放掉落成功音效 if(ActMusic){ ActMusic.play(); } // 掉落成功,进入下一步 self.score += Math.pow(2, self.combo); // 随着combo self._createCube() self._updateCamera() if (self.successCallback) { self.successCallback(self.score) } } else { // 掉落失败,进入失败动画 self._falling(); // // 播放掉落失败音效 if(FallMusic){ FallMusic.play(); } } } act(); }, /** *游戏失败执行的碰撞效果 *@param {String} dir 传入一个参数用于控制倒下的方向:'rightTop','rightBottom','leftTop','leftBottom','none' **/ _fallingRotate: function (dir) { var self = this var offset = self.falledStat.distance - self.config.cubeWidth / 2 var rotateAxis = 'z' // 旋转轴 var rotateAdd = self.jumper.rotation[rotateAxis] + 0.1 // 旋转速度 var rotateTo = self.jumper.rotation[rotateAxis] < Math.PI/2 // 旋转结束的弧度 var fallingTo = self.config.ground + self.config.jumperWidth / 2 + offset if (dir === 'rightTop') { rotateAxis = 'x' rotateAdd = self.jumper.rotation[rotateAxis] - 0.1 rotateTo = self.jumper.rotation[rotateAxis] > -Math.PI/2 self.jumper.translate.z = offset // self.jumper.geometry.translate.z = offset } else if (dir === 'rightBottom') { rotateAxis = 'x' rotateAdd = self.jumper.rotation[rotateAxis] + 0.1 rotateTo = self.jumper.rotation[rotateAxis] < Math.PI/2 self.jumper.translate.z = -offset // self.jumper.geometry.translate.z = -offset } else if (dir === 'leftBottom') { rotateAxis = 'z' rotateAdd = self.jumper.rotation[rotateAxis] - 0.1 rotateTo = self.jumper.rotation[rotateAxis] > -Math.PI/2 self.jumper.translate.x = -offset // self.jumper.geometry.translate.x = -offset } else if (dir === 'leftTop') { rotateAxis = 'z' rotateAdd = self.jumper.rotation[rotateAxis] + 0.1 rotateTo = self.jumper.rotation[rotateAxis] < Math.PI/2 self.jumper.translate.x = offset // self.jumper.geometry.translate.x = offset } else if (dir === 'none') { rotateTo = false fallingTo = self.config.ground } else { throw Error('Arguments Error') } if (!self.fallingStat.end) { if (rotateTo) { self.jumper.rotation[rotateAxis] = rotateAdd } else if (self.jumper.position.y > fallingTo) { self.jumper.position.y -= self.config.fallingSpeed } else { self.fallingStat.end = true } self._render() requestAnimationFrame(function(.........完整代码请登录后点击上方下载按钮下载查看
网友评论0