Usa vite2+vue3 para escribir un [juego del gato de la suerte] para sintetizar deliciosos dumplings

Participo en el "Concurso creativo de principios de verano" para obtener más información, consulte: Concurso creativo de principios de verano

introducir

Se acerca el Dragon Boat Festival, ¿todo el mundo ha empezado a comer dumplings? ¿Te gusta comer los dulces dumplings rojos de azufaifo del norte? ¿O las grandes albóndigas de carne del sur?

En este número, usaremos vite2 y vue3 para desarrollar un minijuego del gato de la suerte. Al probar la vista y la capacidad de juicio previo, puede seleccionar diferentes materiales que se pueden transferir mientras el patrón continúa desplazándose y finalmente obtener la recompensa de zongzi. , puedes usarlo. ¿Cuántas veces sacarás tu zongzi favorito?

manifestación

vista previa del rey gato.gif

Dirección de vista previa: jsmask.gitee.io/dwgame_laoh…

texto

Análisis del juego

Reglas Detalles.png

Antes del desarrollo, debemos pensar en cómo son el diseño y las reglas del juego antes de poder continuar. A través de la demostración y la introducción de reglas en la figura anterior, podemos comprender aproximadamente el flujo del juego.

Luego, de acuerdo con la comprensión del proceso, desmantelar, luego explicaremos principalmente estos problemas:

  1. Animación de fotograma css3 del gato de la suerte.
  2. El material de la tira patrón se carga por lotes en vite2.
  3. Generación de tiras personalizadas de patrón de máquina tragamonedas.
  4. Máquinas tragamonedas con desplazamiento infinito.
  5. Detenga la máquina tragamonedas y obtenga el código de la rifa.
  6. La realización del efecto volador de confeti después de obtener el zongzi.

Animación afortunada

material.png

La siguiente imagen muestra todos los materiales utilizados en este número. El gato de la suerte que hace señas se compone de cuatro imágenes, y se utilizan algunas herramientas de generación de imágenes de sprites en línea. En él, obtendremos la imagen correspondiente de cada imagen background-positiony finalmente la usaremos animationpara completar la animación del cuadro. Entre ellos, animation-timing-function:steps(1, end) es el núcleo de la implementación de la animación de fotogramas.El steps()símbolo de función define una función de paso, que divide el dominio de los valores de salida en pasos equidistantes. El primer valor es un número positivo que debe pasarse, que representa el número equidistante, y el último representa la posición de la interpolación.

.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;
    }
  }
}
复制代码

carga de materiales

Necesitamos sintetizar la tira a través del lienzo más tarde, por lo que primero debemos cargar el patrón que debe transferirse.

De acuerdo con el plan original, tenemos que introducir muchos archivos de recursos de imágenes a mano, por lo que es muy problemático.

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"
复制代码

Sin embargo, Vite import.meta.globproporciona azúcar sintáctico para resolver el problema de la importación por lotes y cargar estos archivos de imagen a la vez.

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;
});
复制代码

Por supuesto, podemos usarlo aquí import.meta.globEagerpara cargar estos recursos de forma sincrónica.

carga.png

条带生成

所谓的条带,就是老虎机中滚动的背景图,不停改变 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 字段,如果开启,则会绘制上对应的数字编号。

raya.png

无限滚动

当我们点击开始游戏按钮后,刚才生成出的条带就会不停的改变 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 。那么一个简单的条带无限滚动就完成了。

pergamino.gif

中奖判定

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 数组中找寻配合的组合,达成后进行不同的奖励画面。

纸屑飞舞

Aquí estoy usando canvas-confetti , que es una biblioteca para animaciones de confeti volador. El principio es crear una página canvas(también puede especificar un contenedor) y luego dibujar varias formas para elegir. A través de cálculos matemáticos, se simulan muchos movimientos físicos para completar el efecto colorido de la animación de confeti.

# 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);
    }
  })();
}
复制代码

confeti.png

Epílogo

Ahora, los problemas o soluciones que puede encontrar en el desarrollo de dichos proyectos se le han descrito a grandes rasgos. No sé cuánta ayuda te brinda, y no sé cuántas veces hiciste clic para obtener tu zongzi favorito, pero no importa lo que sea, solo sé feliz y feliz. Finalmente, les deseo a todos un saludable Dragon Boat Festival, riqueza y buena fortuna, mucha, mucha felicidad.

Supongo que te gusta

Origin juejin.im/post/7101111168571277349
Recomendado
Clasificación