Maison  >  Article  >  interface Web  >  Comment utiliser Vue3+Canvas pour implémenter un simple jeu de serpent

Comment utiliser Vue3+Canvas pour implémenter un simple jeu de serpent

王林
王林avant
2023-05-12 21:58:041260parcourir

    Comment utiliser Vue3+Canvas pour implémenter un simple jeu de serpent

    Règles

    Comment jouer : Le joueur utilise les touches de direction pour contrôler un long serpent afin d'avaler continuellement des haricots. En même temps, le corps du serpent continue de grandir avec les haricots avalés. la tête touche le corps du serpent ou la partie de barrière est terminée.

    Idée

    Éléments : bordure, tête de serpent, corps de serpent, nourriture

    Bordure : saisissez le nombre de lignes Séparé du corps du serpent, lorsque la nourriture est mangée, la queue du corps du serpent est ajoutée par

    Nourriture : le l'emplacement est généré aléatoirement ;

    Organigramme

    Comment utiliser Vue3+Canvas pour implémenter un simple jeu de serpentImplémentation du code

    Pile technologique

    Choisissez

    la technologie à implémenter, par rapport à dom Les performances sont meilleures

    vue3、vite 基础架构; 视图选用 canvasDéfinition de base des variables

    <script setup lang="ts">
      import { ref, onMounted } from &#39;vue&#39;
      
      let width = ref(600) // 地图默认宽度
      let height = ref(400) // 地图默认高度
      let canvas: any = null // canvas 对象
      let ctx: any = null // canvas 渲染上下文对象
      let snakeList = [[0, 100], [10, 100],] // 蛇的点位坐标
      let direction = &#39;right&#39; // top | down | left | right // 当前方向
      let elementWidth = 10 // 元素尺寸
      let step = 10 // 速度
      let store = ref(0) // 分数
      let status = ref(&#39;start&#39;) // unStart | start | pause | over | success(通关) // 状态
      let foodCoordinate: any = [
        ((Math.random() * width.value) / 10) | 0,
        ((Math.random() * height.value) / 10) | 0,
      ] // 食物坐标
      let process: any = null // 定时器 Id
    </script>

    L'initialisation

    est exécutée dans onMount ; éd , effectuant principalement le dessin de cartes, la détection des coordonnées de la souris, la surveillance de la direction, le dessin des aliments, l'activation de la minuterie et d'autres opérations.

    function handleInit() {
      canvas = document.getElementById(&#39;canvas&#39;)
    
      if (canvas?.getContext) {
        ctx = canvas?.getContext(&#39;2d&#39;)
    
        canvas.addEventListener(&#39;mousemove&#39;, e => {
          ctx.clearRect(10, height.value - 20, 120, 40)
          ctx.fillText(`当前鼠标位置:${e.offsetX}, ${e.offsetY}`, 10, height.value - 10)
        })
    
        document.addEventListener(&#39;keydown&#39;, e => {
          e.preventDefault()
    
          if (Direction[e.keyCode]) {
            direction = Direction[e.keyCode]
          }
        })
    
        process = setInterval(handleRenderSnake, 150)
        handleRenderFood()
        // window.requestAnimationFrame(handleRenderSnake)
      } else {
        alert(&#39;您的浏览器不支持 canvas&#39;)
      }
    }

    Dessin de nourriture

    Lorsque la nourriture est mangée, elle doit être détruite et régénérée

    // 绘制食物
    function handleRenderFood() {
      ctx.clearRect(foodCoordinate[0], foodCoordinate[1], 10, 10)
      foodCoordinate = [(Math.random() * width.value) | 0, (Math.random() * height.value) | 0]
      ctx.fillStyle = &#39;#eb2f96&#39;
      ctx.fillRect(foodCoordinate[0], foodCoordinate[1], 10, 10)
    }

    Dessin de tête/corps de serpent

    Le serpent est représenté par un tableau bidimensionnel, chaque nœud représente une partie du corps, le Le premier nœud représente la tête du serpent. Le mouvement du serpent est obtenu en supprimant le nœud de queue et en ajoutant le nœud de tête. Le nœud du milieu n'a pas besoin d'être déplacé et le traitement dans les quatre directions est légèrement différent. Notez que lorsque de la nourriture est mangée, le nœud de queue du cadre actuel n'est plus supprimé et la longueur du corps du serpent est augmentée de 1.

    function handleRenderSnake() {
      switch (direction) {
        case &#39;top&#39;:
          if (snakeList.slice(-1)[0][1] <= 0) {
            status.value = &#39;over&#39;
            return
          }
    
          snakeList.push([
            snakeList[snakeList.length - 1][0],
            snakeList[snakeList.length - 1][1] - step,
          ])
          handleUpdateVerify()
          break
        case &#39;down&#39;:
          if (snakeList.slice(-1)[0][1] >= height.value - 1) {
            status.value = &#39;over&#39;
            return
          }
    
          snakeList.push([
            snakeList[snakeList.length - 1][0],
            snakeList[snakeList.length - 1][1] + step,
          ])
          handleUpdateVerify()
    
          break
          ...

    Algorithme de collision, conditions aux limites

    Lorsque la tête du serpent touche le bord de la carte, le jeu sera terminé. Il vous suffit de calculer si les prochaines coordonnées dépasseront la taille de la carte en fonction des coordonnées actuelles et de la direction actuelle. la tête de serpent.

    Méthode de calcul pour manger de la nourriture : Calculez respectivement les valeurs absolues des axes x et y des coordonnées de la tête de serpent et des coordonnées de la nourriture. Si elle est plus petite que la taille de l'élément, elle est considérée comme ayant été en contact.

    // 更新校验
    function handleUpdateVerify() {
      if (status.value === &#39;pause&#39;) {
        clearInterval(process)
      }
    
      if (store.value >= 100) {
        status.value = &#39;success&#39;
        return
      }
    
      for (let i of snakeList) {
        ctx.clearRect(i[0], i[1], elementWidth, elementWidth)
      }
    
      let currentSnake = snakeList.slice(-1)[0]
      if (
        Math.abs(currentSnake[0] - foodCoordinate[0]) < 10 &&
        Math.abs(currentSnake[1] - foodCoordinate[1]) < 10
      ) {
        store.value++
        handleRenderFood()
      } else {
        snakeList.shift()
      }
    }

    Calcul des points, pause, continuation et autres fonctions

    La variable globale status représente l'état de la situation actuelle Lorsque status === 'pause', l'opération de pause est déclenchée, la variable timer est supprimée et le redémarrage. est cliqué sur le bouton pour générer un nouveau dispositif de minuterie.

    Lorsque de la nourriture est mangée, la variable globale store ++ est liée de manière bidirectionnelle à la page pour l'affichage. Définissez temporairement le score pour qu'il dépasse 100 pour passer le niveau.

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer