首頁 > 軟體

基於vite2+vue3製作個招財貓遊戲

2022-05-26 18:02:23

介紹

端午將至,大家都開始吃粽子了麼,你是喜歡吃北方的甜的紅棗粽?還是南方的大肉粽呢?

本期我們將使用vite2與vue3開發出一個招財貓小遊戲,通過考驗眼力和預判能力,在圖案不停捲動的同時選出可以轉出不同的素材最終得到粽子獎勵,康康你能用多少次才會轉出自己喜愛口味的粽子吧~

演示

預覽地址:jsmask.gitee.io/dwgame_laohuji/

正文

遊戲分析

在開發之前,我們要想好遊戲設計和規則是如何,才能進行往下進行。通過上圖的演示和規則介紹,我們大致可以瞭解遊戲流程了。

然後,根據瞭解的流程,進行拆解,接下來我們主要會講解這些問題:

  • 招財貓css3幀動畫。
  • 圖案條帶中的素材在vite2的批次載入。
  • 老虎機圖案自定義條帶生成。
  • 老虎機無限捲動。
  • 讓老虎機停止並且獲取抽獎碼。
  • 獲得粽子後的紙屑飛舞效果的實現。

招財動畫

下圖是本期用的所有素材,招財貓招手的是由四張圖拼湊而成的,用了一些線上的雪碧圖生成工具。在裡面我們會得到每張圖對應的 background-position , 最後再用 animation 來完成這個幀動畫。其中,animation-timing-function:steps(1, end) 是幀動畫實現的核心,steps() 函數符號定義了一個階梯函數,將輸出值的域劃分為等距階梯。第一個值是需要傳入正數,表示等距的數,而後一個表示插值的位置。

.cat {
  width: 574px;
  height: 630px;
  margin: 0px auto;
  position: relative;
  background-image: url("../assets/image/cat.png");
  background-position: -10px -10px;
  &.active {
    animation: play-game 0.64s steps(1, end) infinite;
  }
  @keyframes play-game {
    0% {
      background-position: -10px -10px;
    }
    33% {
      background-position: -604px -10px;
    }
    66% {
      background-position: -1198px -10px;
    }
    100% {
      background-position: -10px -660px;
    }
  }
}

素材載入

我們後面需要通過canvas合成條帶,所以要先載入出需要轉出的圖案來。

按照原始的方案來,我們要手寫好多圖片資原始檔的引入,所以十分麻煩。

import item0 from "../assets/image/item_0.png"
import item1 from "../assets/image/item_1.png"
import item2 from "../assets/image/item_2.png"
// ...more
import item9 from "../assets/image/item_9.png"

但是,Vite 中提供了 import.meta.glob 的語法糖來解決這種批次匯入的問題,一次性載入出這些圖片檔案來。

const imgs = import.meta.globEager("../assets/image/item_*.png");

let num = Object.keys(imgs).length;
let items = Object.values(imgs).map((mod) => {
  let img = new Image();
  img.onload = () => --num <= 0 && initGame();
  img.src = mod.default;
  return img;
});

當然我們這裡用 import.meta.globEager 來可以同步載入這些資源。

條帶生成

所謂的條帶,就是老虎機中捲動的背景圖,不停改變 backgroundPositionY 來實現捲動效果,是老虎機的核心,所使用到的條帶自然就是重中之重,但在我們平時開發條帶一般都是設計給的圖片,但經常替換圖片後又要重新問他們要新圖甚是麻煩。所以,這裡我想用 canvas 把剛才的那十張圖案拼接起來,形成條帶供我們使用。上一步,我們已經把資源載入完成了,接下來,可以需要寫一個 createBackgroundImage 函數。

function createBackgroundImage({items = [], w = 45, h = 60, size = 40,test=false}) {
  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");
  canvas.width = ctx.width = w;
  canvas.height = ctx.height = h * items.length;
  let BackgroundImage = [...items];
  BackgroundImage.forEach((img, i) => {
    ctx.save();
    ctx.drawImage(img, (w - size) / 2, (h - size) / 2 + h * i, size, size);
    if(test){
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      ctx.font = "bold 36px Baloo Bhaijaan";
      ctx.fillText(i, w / 2, h * i + h / 2 + 5, w);
    }
    ctx.restore();
  });
  return convertCanvasToImage(canvas);
}

function convertCanvasToImage(canvas) {
  var image = new Image();
  image.src = canvas.toDataURL("image/png");
  return image;
}

export default createBackgroundImage;

這裡我們不光可以傳入資源陣列,而且可以傳入塊的寬和高,還有圖案的大小,為了方便測試後面驗證開獎碼的正確性,加入 test 欄位,如果開啟,則會繪製上對應的數位編號。

無限捲動

當我們點選開始遊戲按鈕後,剛才生成出的條帶就會不停的改變 backgroundPositionY ,那有什麼好辦法可以輕鬆控制這件事呢?

這裡我推薦使用anime.js ,它一個功能強大且輕量級的 JavaScript 動畫庫。

# NPM
npm i animejs -S
# YARN
yarn add animejs
# PNPM
pnpm i animejs -S
<ul class="content">
    <li
        ref="block"
        v-for="(item, index) in 3"
        :key="index"
        :style="{ backgroundImage: `url(${backgroundImage.src})` }"
        >
        <button :disabled="stops[index]" @click="handleStop(index)">
            Stop
        </button>
    </li>
</ul>
import anime from "animejs";
function play() {
  if (isActive.value) return false;
  isActive.value = true;
  count.value += 1;
  block.value.forEach((el, index) => {
    setTimeout(() => {
      stops.value[index] = false;
      let y = parseInt(el.style.backgroundPositionY || "0", 10);
      animes.value[index] = anime({
        targets: el,
        backgroundPositionY: [h / 2, h * items.length + h / 2],
        loop: true, // 迴圈播放
        direction: "normal", // 方向
        easing: "linear", // 時間曲線
        duration: 1200, // 播放時間
        autoplay: true, // 是否立即播放
      });
    }, index * 240);
  });
}

play 方法時,我們獲取當繫結好條帶的元素塊,通過 animejsbackgroundPositionY 屬性設定一個陣列,這個陣列第0位代表起始狀態,第1位代表要到達的狀態。然後把 loop 屬性設定 true 。那麼一個簡單的條帶無限捲動就完成了。

中獎判定

function handleStop(index) {
  stops.value[index] = true;
  let el = block.value[index];
  let y = parseInt(el.style.backgroundPositionY || "0", 10);
  animes.value[index].remove(el);
  let n = Math.round((y - h / 2) / h);
  el.style.backgroundPositionY = n * h + h / 2 + "px";
  giftCode.value[index] = (10 - n) % 10;
  if (stops.value.find((item) => !item) === undefined) {
    getResult();
  }
}

當我們每按停一個時,我們會迅速移除對應元素 animejs 動畫,計算並賦值給最數值最接近的座標點。然後獲取到其對應的數位編號存起來形成抽獎碼陣列,當三個全部停止時,會呼叫 getResult 方法來根據剛才得到的抽獎碼來開獎。

const giftData = [
    {
        name: "紅棗粽",
        score: 100,
        show: true,
        type:1,
        value: ["012", "025", "126", "256"],
    },
    // ...
]
function getResult() {
  let str = giftCode.value.sort().join("");
  let _obj = giftData.find((item) => item.value.includes(str));
  if (!_obj) return (isActive.value = false);
  if (_obj.show) {
    giftObj.value = _obj;
    ruleShow.value = false;
    giftShow.value = true;
  } else {
    confetti();
    hideGift();
  }
}

這裡,我們把得到的抽獎碼進行從小往大排列生成字串,然後在 giftData 陣列中找尋配合的組合,達成後進行不同的獎勵畫面。

紙屑飛舞

這裡我使用了 canvas-confetti,它是專門來製作紙屑飛散的動畫庫。其原理是在頁面建立了canvas (也可以指定容器), 然後在裡面繪製了幾種形狀可供選擇,通過數學計算,模擬了很多物理運動來完成紙屑動畫多彩的效果。

# NPM
npm i canvas-confetti -S
# YARN
yarn add canvas-confetti
# PNPM
pnpm i canvas-confetti -S
import confetti from "canvas-confetti";
function handleSucces() {
  let endTime = Date.now() + 3 * 1000;
  const colors = ["#bb0000", "#ffffff"];
  (function frame() {
    confetti({
      particleCount: 2,
      angle: 45,
      spread: 155,
      origin: { x: 0 },
      colors: colors,
    });
    confetti({
      particleCount: 2,
      angle: 135,
      spread: 60,
      origin: { x: 1 },
      colors: colors,
    });
    if (Date.now() < endTime) {
      requestAnimationFrame(frame);
    }
  })();
}

結語

現在已經把大家開發這類專案可能遭遇的問題或者方案大致給大家講述完了。不知道,給你帶來的幫助是多是少,也不知道大家點選了多少次才得到喜歡吃的粽子了,但不管是什麼,開心快樂就好,最後祝大家端午安康,財運,福運多多,幸福滿滿。

到此這篇關於基於vite2+vue3製作個招財貓遊戲的文章就介紹到這了,更多相關vite2 vue3招財貓遊戲內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com