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.
É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
Implémentation du code
vue3、vite
基础架构; 视图选用 canvas
Définition de base des variables
<script setup lang="ts"> import { ref, onMounted } from 'vue' 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 = 'right' // top | down | left | right // 当前方向 let elementWidth = 10 // 元素尺寸 let step = 10 // 速度 let store = ref(0) // 分数 let status = ref('start') // 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>
function handleInit() { canvas = document.getElementById('canvas') if (canvas?.getContext) { ctx = canvas?.getContext('2d') canvas.addEventListener('mousemove', e => { ctx.clearRect(10, height.value - 20, 120, 40) ctx.fillText(`当前鼠标位置:${e.offsetX}, ${e.offsetY}`, 10, height.value - 10) }) document.addEventListener('keydown', e => { e.preventDefault() if (Direction[e.keyCode]) { direction = Direction[e.keyCode] } }) process = setInterval(handleRenderSnake, 150) handleRenderFood() // window.requestAnimationFrame(handleRenderSnake) } else { alert('您的浏览器不支持 canvas') } }
Dessin de nourriture
// 绘制食物 function handleRenderFood() { ctx.clearRect(foodCoordinate[0], foodCoordinate[1], 10, 10) foodCoordinate = [(Math.random() * width.value) | 0, (Math.random() * height.value) | 0] ctx.fillStyle = '#eb2f96' ctx.fillRect(foodCoordinate[0], foodCoordinate[1], 10, 10) }
Dessin de tête/corps de serpent
function handleRenderSnake() { switch (direction) { case 'top': if (snakeList.slice(-1)[0][1] <= 0) { status.value = 'over' return } snakeList.push([ snakeList[snakeList.length - 1][0], snakeList[snakeList.length - 1][1] - step, ]) handleUpdateVerify() break case 'down': if (snakeList.slice(-1)[0][1] >= height.value - 1) { status.value = 'over' return } snakeList.push([ snakeList[snakeList.length - 1][0], snakeList[snakeList.length - 1][1] + step, ]) handleUpdateVerify() break ...
Algorithme de collision, conditions aux limites
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 === 'pause') { clearInterval(process) } if (store.value >= 100) { status.value = 'success' 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
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!