欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲

 更新時(shí)間:2021年04月23日 10:06:02   作者:登樓痕  
這篇文章主要介紹了VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲,需要的朋友可以參考下本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

之前的canvas小游戲系列歡迎大家戳:

《VUE實(shí)現(xiàn)一個(gè)Flappy Bird~~~》

《猜單詞游戲》

《VUE+Canvas 實(shí)現(xiàn)桌面彈球消磚塊小游戲》

《VUE+Canvas實(shí)現(xiàn)雷霆戰(zhàn)機(jī)打字類(lèi)小游戲》

如標(biāo)題,這個(gè)游戲大家也玩過(guò),隨處可見(jiàn),左右方向鍵控制財(cái)神移動(dòng),接住從天而降的金元寶等,時(shí)間一到,則游戲結(jié)束。先來(lái)看一下效果:

相比于之前的雷霆戰(zhàn)機(jī)要打出四處飛的子彈,這次元素的運(yùn)動(dòng)軌跡就很單一了,垂直方向的珠寶和水平移動(dòng)的財(cái)神爺,類(lèi)似于之前的代碼,這里就說(shuō)一下關(guān)鍵步驟點(diǎn)吧:

1、鍵盤(pán)控制水平移動(dòng)的財(cái)神爺

這個(gè)很簡(jiǎn)單,同理于《VUE+Canvas 實(shí)現(xiàn)桌面彈球消磚塊小游戲》滑塊的控制:

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、從天而降的珠寶

這個(gè)也很簡(jiǎn)單,但要注意的是,珠寶的初始x值不能隨機(jī)取0~clientWidth了,因?yàn)檫@樣很容易造成珠寶堆積在一起,影響了游戲的可玩性,所以珠寶最好是分散在不同的軌道上,這里我們把畫(huà)布寬度分為5條軌道,初始珠寶的時(shí)候,我們就把珠寶分散在軌道上,并且y值隨機(jī)在一定高度造成參差。而后新生成的珠寶都依據(jù)軌道分布來(lái)生成,避免珠寶擠在一起。

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
      ) {
        // 判斷和財(cái)神的觸碰范圍
        _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函數(shù)過(guò)濾掉應(yīng)該消失的珠寶,如果用for+splice+i--的方法會(huì)造成抖動(dòng)。

然后給予每個(gè)珠寶隨機(jī)的運(yùn)動(dòng)速度,當(dāng)珠寶進(jìn)入財(cái)神爺?shù)膱D片范圍時(shí)則累加相應(yīng)分?jǐn)?shù)。

3、倒計(jì)時(shí)圓環(huán)

設(shè)置倒計(jì)時(shí)30s,那么在requestAnimationFrame的回調(diào)里計(jì)算當(dāng)前時(shí)間與上次時(shí)間戳毫秒差值是否大于1000,實(shí)現(xiàn)秒的計(jì)算,然后取另一時(shí)間戳累加progress,實(shí)現(xiàn)圓環(huán)的平滑移動(dòng)。

drawCountDown() {
      // 畫(huà)進(jìn)度環(huán)
      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();
 
      // 畫(huà)內(nèi)填充圓
      _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();
        }
})();

至此,一個(gè)非常簡(jiǎn)單的財(cái)神爺接元寶的小游戲就完成了,當(dāng)然可以為了增加難度,設(shè)置不間斷地丟炸彈這一環(huán)節(jié),原理同珠寶的運(yùn)動(dòng)是一樣的。

下面還是附上全部代碼,供大家參考學(xué)習(xí):

<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/財(cái)神爺.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() {
      // 畫(huà)進(jìn)度環(huán)
      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();
 
      // 畫(huà)內(nèi)填充圓
      _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
      ) {
        // 判斷和財(cái)神的觸碰范圍
        _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>

到此這篇關(guān)于VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲的文章就介紹到這了,更多相關(guān)vue接元寶游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論