如何用vue框架写个接元宝小游戏

Admin 2022-10-20 群英技术资讯 359 次浏览

这篇文章将为大家详细讲解有关“如何用vue框架写个接元宝小游戏”的知识,下文有详细的介绍,小编觉得挺实用的,对大家学习或工作或许有帮助,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。




如标题,这个游戏大家也玩过,随处可见,左右方向键控制财神移动,接住从天而降的金元宝等,时间一到,则游戏结束。先来看一下效果:

相比于之前的雷霆战机要打出四处飞的子弹,这次元素的运动轨迹就很单一了,垂直方向的珠宝和水平移动的财神爷,类似于之前的代码,这里就说一下关键步骤点吧:

1、键盘控制水平移动的财神爷

这个很简单,同理于《VUE+Canvas 实现桌面弹球消砖块小游戏》滑块的控制:

drawCaishen() {        let _this = this ;        _this.ctx.save();        _this.ctx.drawImage(          _this.caishenImg,          _this.caishen.x,          _this.caishen.y,          120,          120        );        _this.ctx.restore(); }, moveCaishen() {        this .caishen.x += this .caishen.dx;        if ( this .caishen.x > this .clientWidth - 120) {          this .caishen.x = this .clientWidth - 120;        } else if ( this .caishen.x < 0) {          this .caishen.x = 0;        } }

2、从天而降的珠宝

这个也很简单,但要注意的是,珠宝的初始x值不能随机取0~clientWidth了,因为这样很容易造成珠宝堆积在一起,影响了游戏的可玩性,所以珠宝最好是分散在不同的轨道上,这里我们把画布宽度分为5条轨道,初始珠宝的时候,我们就把珠宝分散在轨道上,并且y值随机在一定高度造成参差。而后新生成的珠宝都依据轨道分布来生成,避免珠宝挤在一起。

generateTreasure() {        let _this = this ;        if (_this.treasureArr.length < MaxNum) {          let random = Math.floor(Math.random() * TreasureNames.length);          let channel = _this.getRandomArbitrary(1, 5);          _this.treasureArr.push({            x: _this.channelWidth * (1 / 2 + (channel - 1)) - 30,            y: 0,            name: TreasureNames[random],            speed: _this.getRandomArbitrary(2, 4)          });        } }, filterTreasure(item) {        let _this = this ;        if (          item.x <= _this.caishen.x + 110 &&          item.x >= _this.caishen.x &&          item.y > _this.caishen.y        ) {          // 判断和财神的触碰范围          _this.score += _this.treasureObj[item.name].score;          return false ;        }        if (item.y >= _this.clientHeight) {          return false ;        }        return true ; }, drawTreasure() {        let _this = this ;        _this.treasureArr = _this.treasureArr.filter(_this.filterTreasure);        _this.treasureArr.forEach(item => {          _this.ctx.drawImage(            _this.treasureObj[item.name].src,            item.x,            item.y,            60,            60          );          item.y += item.speed;        }); }, getRandomArbitrary(min, max) {        return Math.random() * (max - min) + min; }

这里用filter函数过滤掉应该消失的珠宝,如果用for+splice+i--的方法会造成抖动。

然后给予每个珠宝随机的运动速度,当珠宝进入财神爷的图片范围时则累加相应分数。

3、倒计时圆环

设置倒计时30s,那么在requestAnimationFrame的回调里计算当前时间与上次时间戳毫秒差值是否大于1000,实现秒的计算,然后取另一时间戳累加progress,实现圆环的平滑移动。

drawCountDown() {        // 画进度环        let _this = this ;        _this.progress += Date.now() - _this.timeTag2;        _this.timeTag2 = Date.now();        _this.ctx.beginPath();        _this.ctx.moveTo(50, 50);        _this.ctx.arc(          50,          50,          40,          Math.PI * 1.5,          Math.PI * (1.5 + 2 * (_this.progress / (countDownInit * 1000))),          false        );        _this.ctx.closePath();        _this.ctx.fillStyle = "yellow" ;        _this.ctx.fill();          // 画内填充圆        _this.ctx.beginPath();        _this.ctx.arc(50, 50, 30, 0, Math.PI * 2);        _this.ctx.closePath();        _this.ctx.fillStyle = "#fff" ;        _this.ctx.fill();          // 填充文字        _this.ctx.font = "bold 16px Microsoft YaHei" ;       

_this.ctx.fillStyle = "#333" ;        _this.ctx.textAlign = "center" ;        _this.ctx.textBaseline = "middle" ;        _this.ctx.moveTo(50, 50);        _this.ctx.fillText(_this.countDown + "s" , 50, 50);      }

( function animloop() {          _this.ctx.clearRect(0, 0, _this.clientWidth, _this.clientHeight);          _this.loop();          animationId = window.requestAnimationFrame(animloop);          if (_this.countDown === 0) {            _this.gameOver = true ;            window.cancelAnimationFrame(animationId);          }          if (Date.now() - _this.timeTag >= 1000) {            _this.countDown--;            _this.timeTag = Date.now();          } })();

至此,一个非常简单的财神爷接元宝的小游戏就完成了,当然可以为了增加难度,设置不间断地丢炸弹这一环节,原理同珠宝的运动是一样的。

下面还是附上全部代码,供大家参考学习:

?
<template>    <div class= "caishen" >      <canvas id= "caishen" width= "1200" height= "750" ></canvas>      <div class= "container" v- if = "gameOver" >        <div class= "dialog" >          <p class= "once-again" >恭喜!</p>          <p class= "once-again" >本回合夺宝:{{ score }}分</p>        </div>      </div>    </div> </template>   <script> const TreasureNames = [    "yuanbao" ,    "tongqian" ,    "jintiao" ,    "shuijin_red" ,    "shuijin_blue" ,    "fudai" ]; let animationId = null ; let countDownInit = 0; const MaxNum = 5; export default {    name: "CaiShen" ,    data() {      return {        score: 0,        ctx: null ,        caishenImg: null ,        clientWidth: 0,        clientHeight: 0,        channelWidth: 0,        caishen: {          x: 0,          y: 0,          speed: 8,          dx: 0        },        progress: 0,        countDown: 30,        timeTag: Date.now(),        timeTag2: Date.now(),        treasureArr: [],        gameOver: false ,        treasureObj: {          yuanbao: {            score: 5,            src: null          },          tongqian: {            score: 2,            src: null          },          jintiao: {            score: 10,            src: null          },          shuijin_red: {            score: 20,            src: null          },          shuijin_blue: {            score: 15,            src: null          },          fudai: {            score: 8,            src: null          }        }      };    },    mounted() {      let _this = this ;      let container = document.getElementById( "caishen" );      _this.ctx = container.getContext( "2d" );      _this.clientWidth = container.width;      _this.clientHeight = container.height;      _this.channelWidth = Math.floor(_this.clientWidth / 5);      _this.caishenImg = new Image();      _this.caishenImg.src = require( "@/assets/img/caishen/财神爷.png" );        _this.initTreasures();      countDownInit = _this.countDown;      _this.caishen.x = _this.clientWidth / 2 - 60;      _this.caishen.y = _this.clientHeight - 120;      document.onkeydown = function (e) {        let key = window.event.keyCode;        if (key === 37) {          // 左键          _this.caishen.dx = -_this.caishen.speed;        } else if (key === 39) {          // 右键          _this.caishen.dx = _this.caishen.speed;        }      };      document.onkeyup = function (e) {        _this.caishen.dx = 0;      };      _this.caishenImg.onload = function () {        ( function animloop() {          _this.ctx.clearRect(0, 0, _this.clientWidth, _this.clientHeight);          _this.loop();          animationId = window.requestAnimationFrame(animloop);          if (_this.countDown === 0) {            _this.gameOver = true ;            window.cancelAnimationFrame(animationId);          }          if (Date.now() - _this.timeTag >= 1000) {            _this.countDown--;            _this.timeTag = Date.now();          }        })();      };    },    methods: {      initTreasures() {        let _this = this ;        Object.keys(_this.treasureObj).forEach(key => {          _this.treasureObj[key].src = new Image();          _this.treasureObj[            key          ].src.src = require(`@/assets/img/caishen/${key}.png`);        });        for (let i = 0; i < MaxNum; i++) {          let random = Math.floor(Math.random() * TreasureNames.length);          _this.treasureArr.push({            x: _this.channelWidth * (1 / 2 + i) - 30,            y: _this.getRandomArbitrary(0, 20),            name: TreasureNames[random],            speed: _this.getRandomArbitrary(2, 4)          });        }      },      loop() {        let _this = this ;        _this.drawCountDown();        _this.drawCaishen();        _this.moveCaishen();        _this.generateTreasure();        _this.drawTreasure();        _this.drawScore();      },      drawCaishen() {        let _this = this ;        _this.ctx.save();        _this.ctx.drawImage(          _this.caishenImg,          _this.caishen.x,          _this.caishen.y,          120,          120        );        _this.ctx.restore();      },      moveCaishen() {        this .caishen.x += this .caishen.dx;        if ( this .caishen.x > this .clientWidth - 120) {          this .caishen.x = this .clientWidth - 120;        } else if ( this .caishen.x < 0) {          this .caishen.x = 0;        }      },      drawScore() {        let _this = this ;        _this.ctx.beginPath();        _this.ctx.fillStyle = "#fff" ;        _this.ctx.textAlign = "center" ;        _this.ctx.textBaseline = "middle" ;        _this.ctx.fillText(_this.score + "分" , 30, _this.clientHeight - 10);        _this.ctx.closePath();      },      drawCountDown() {        // 画进度环        let _this = this ;        _this.progress += Date.now() - _this.timeTag2;        _this.timeTag2 = Date.now();        _this.ctx.beginPath();        _this.ctx.moveTo(50, 50);        _this.ctx.arc(          50,          50,          40,          Math.PI * 1.5,          Math.PI * (1.5 + 2 * (_this.progress / (countDownInit * 1000))),          false        );        _this.ctx.closePath();        _this.ctx.fillStyle = "yellow" ;        _this.ctx.fill();          // 画内填充圆        _this.ctx.beginPath();        _this.ctx.arc(50, 50, 30, 0, Math.PI * 2);        _this.ctx.closePath();        _this.ctx.fillStyle = "#fff" ;        _this.ctx.fill();          // 填充文字        _this.ctx.font = "bold 16px Microsoft YaHei" ;        _this.ctx.fillStyle = "#333" ;        _this.ctx.textAlign = "center" ;        _this.ctx.textBaseline = "middle" ;        _this.ctx.moveTo(50, 50);        _this.ctx.fillText(_this.countDown + "s" , 50, 50);      },      filterTreasure(item) {        let _this = this ;        if (          item.x <= _this.caishen.x + 110 &&          item.x >= _this.caishen.x &&          item.y > _this.caishen.y        ) {          // 判断和财神的触碰范围          _this.score += _this.treasureObj[item.name].score;          return false ;        }        if (item.y >= _this.clientHeight) {          return false ;        }        return true ;      },      drawTreasure() {        let _this = this ;        _this.treasureArr = _this.treasureArr.filter(_this.filterTreasure);        _this.treasureArr.forEach(item => {          _this.ctx.drawImage(            _this.treasureObj[item.name].src,            item.x,            item.y,            60,            60          );          item.y += item.speed;        });      },      getRandomArbitrary(min, max) {        return Math.random() * (max - min) + min;      },      generateTreasure() {        let _this = this ;        if (_this.treasureArr.length < MaxNum) {          let random = Math.floor(Math.random() * TreasureNames.length);          let channel = _this.getRandomArbitrary(1, 5);          _this.treasureArr.push({            x: _this.channelWidth * (1 / 2 + (channel - 1)) - 30,            y: 0,            name: TreasureNames[random],            speed: _this.getRandomArbitrary(2, 4)          });        }      }    } }; </script>   <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped lang= "scss" > #caishen {    background-color: #b00600;    background-image: url( "~assets/img/caishen/brick-wall.png" ); } .container {    position: absolute;    top: 0;    right: 0;    bottom: 0;    left: 0;    background-color: rgba(0, 0, 0, 0.3);    text-align: center;    font-size: 0;    white-space: nowrap;    overflow: auto; } .container:after {    content: "" ;    display: inline-block;    height: 100%;    vertical-align: middle; } .dialog {    width: 400px;    height: 300px;    background: rgba(255, 255, 255, 0.5);    box-shadow: 3px 3px 6px 3px rgba(0, 0, 0, 0.3);    display: inline-block;    vertical-align: middle;    text-align: left;    font-size: 28px;    color: #fff;    font-weight: 600;    border-radius: 10px;    white-space: normal;    text-align: center;    .once-again-btn {      background: #1f9a9a;      border: none;      color: #fff;    } } </style>

到此,关于“如何用vue框架写个接元宝小游戏”的学习就结束了,希望能够解决大家的疑惑,另外大家动手实践也很重要,对大家加深理解和学习很有帮助。如果想要学习更多的相关知识,欢迎关注群英网络,小编每天都会给大家分享实用的文章!

群英智防CDN,智能加速解决方案
标签: vue接元宝游戏

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

猜你喜欢

成为群英会员,开启智能安全云计算之旅

立即注册
专业资深工程师驻守
7X24小时快速响应
一站式无忧技术支持
免费备案服务
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
在线客服
微信公众号
返回顶部
返回顶部 返回顶部
在线客服
在线客服