使用DOM画蛇
上一篇中我们将整个游戏划分了模块,主要有main.js, snake.js, food.js三个模块,然后在main模块中使用了window.requestAnimationFrame()请求动画帧函数, 通过这个函数不断重复调用update()和draw()函数,这两个函数用于更新界面和重绘游戏中的蛇和食物, 到现在为止并没有实现这两个函数的具体功能,在这一篇中我们将使用JavaScript DOM技术把蛇画出来。
JavaScript DOM
DOM 全称文档对象模型,在前端是将WEB页面和JavaScript脚本语言连接起来,提供了一套API(应用程序编程接口)用于操作HTML元素、处理事件等,在贪吃蛇游戏中我们需要用到几个DOM API来创建蛇和食物:
怎样获取HTML元素?
1 2 document .getElementById();document .querySelector();
怎样创建HTML元素?
1 document .createElement()
怎样修改元素的样式属性?
1 2 3 元素.style = ... 元素.className = ... 元素.classList.add(...)
怎样添加元素?
JavaScript中如何定义数组?
1 const snakeBody = [ 数组内容 ]
绘制蛇身体和头部
HTML代码就不重复了,先在main.js文件中获取网页中id为game-board的元素, 然后再绘制蛇或食物的时候需要传递这个HTML元素给drawSnake方法, 关键代码如下:
获取HTML元素的关键代码
1 2 3 let gameBoard = document .getElementById('game-board' )let gameBoard = document .querySelector('#game-board' )
调用绘制蛇和食物的关键代码
1 2 drawSnake(gameBoard) drawFood(gameBoard)
完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import {update as updateSnake, draw as drawSnake} from './snake.js' import {update as updateFood, draw as drawFood} from './food.js' let gameBoard = document .getElementById('game-board' )function main (currentTime ) { window .requestAnimationFrame(main) update() draw() } window .requestAnimationFrame(main)function update ( ) { updateSnake() updateFood() } function draw ( ) { drawSnake(gameBoard) drawFood(gameBoard) }
下面将会在snake.js模块中实现draw方法
在snake.js模块中需要定义蛇,我们使用一个数组来表示,数组中的每一个元素代表蛇的每一个部分的坐标位置,包括x和y, 因为game-board采用的是网格布局,所以每一项(也就是单元格) 都有固定的坐标, 这个坐标(x,y)不能为0,也不能超过在CSS中设定的网格数(网页中设定的是50) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #game-board { background-color : rgb (250 , 245 , 245 ); width : 100vmin ; height : 100vmin ; display : grid; grid-template-rows: repeat (50 , 1 fr); grid-template-columns : repeat (50 , 1 fr); } .snake-head { background-image : url ('./images/head1.png' ); background-size : cover; } .snake-body { background-color : hsl (200 ,100% ,50% ); border-radius : 80% ; }
蛇用一个对象数组表示,数组中的每个对象表示蛇的一部分
1 2 3 const snakeBody = [ {x : 2 , y : 2 }, ]
在draw函数中根据snakeBody数组的大小创建多个div元素,用于显示蛇,蛇的长度在后面的游戏过程中会要增加,所以这个snakeBody数组会动态改变大小, 创建div元素并设定它的样式代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 const snakeElement = document .createElement('div' )snakeElement.style.gridRowStart = snakeBody[0 ].x snakeElement.style.gridColumnStart = snakeBody[0 ].y snakeElement.style.backgroundColor = 'hsl(200,100%,50%)' snakeElement.style.border = '.25vmin solid black' gameBoard.appendChild(snakeElement)
通过循环画蛇,一开始仅有一个蛇头,可以自行在snakeBody中添加对象并查看效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 for (var i=0 ;i<=snakeBody.length;i++) { const snakeElement = document .createElement('div' ) snakeElement.style.gridRowStart = snakeBody[i].x snakeElement.style.gridColumnStart = snakeBody[i].y snakeElement.style.backgroundColor = 'hsl(200,100%,50%)' snakeElement.style.border = '.25vmin solid black' gameBoard.appendChild(snakeElement) }
实现的代码删除和背景颜色和边框,使用classList.add方法添加样式,snake.js完整代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function update ( ) { console .log('更新蛇' ) } function draw (gameBoard ) { for (var i=0 ;i<=snakeBody.length;i++) { const snakeElement = document .createElement('div' ) snakeElement.style.gridRowStart = snakeBody[i].x snakeElement.style.gridColumnStart = snakeBody[i].y if (index == 0 ) { snakeElement.classList.add('snake-head' ) } else { snakeElement.classList.add('snake-body' ) } gameBoard.appendChild(snakeElement) } } export {update, draw}
画食物的函数在这里就没有贴出代码,可以自己参考画蛇的方法完成食物的绘制