首先先看一个效果图
利用面向对象思想, 我把他分为了 食物类 蛇类 还有一个主文件 游戏类 此外 因为食物是随机生成的,所以,我也定义了一个生成随机数的类
下面请看代码:
生成随机数类(util.js)
export function getRandom(a,b){
let max = Math.max(a,b);
let min = Math.min(a,b);
return parseInt(Math.random() * (max - min))+min;
}
食物类(food.js)
import { getRandom } from "./util.js";
class Food{
constructor({ x = 1, y = 1, width = 20, height = 20, color = 'green' } = {} ){
this.element = [];
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
}
render(map){
this.remove();
this.x = getRandom(0, map.offsetWidth / this.width - 9) * this.width;
this.y = getRandom(0, map.offsetHeight / this.height - 1) * this.height;
let div = document.createElement('div');
map.appendChild(div);
this.element.push(div);
div.style.position = 'absolute';
div.style.left = this.x + 'px';
div.style.top = this.y + 'px';
div.style.width = this.width + 'px';
div.style.height = this.height + 'px';
div.style.backgroundColor = this.color;
}
remove(){
for(let i = this.element.length-1; i >= 0; i--){
this.element[i].parentNode.removeChild(this.element[i]);
this.element.splice(i, 1);
}
}
}
export default Food;
蛇类(snake.js)
class Snake{
constructor({width = 20, height = 20, direction = 'right'} = {}){
this.element = [];
this.width = width;
this.height = height;
this.direction = direction; //蛇移动的方向
//蛇的身体(蛇节), 第一个是蛇头
this.body = [
{x: 3, y: 2, color: 'red'},
{x: 2, y: 2, color: 'blue'},
{x: 1, y: 2, color: 'blue'}
];
}
move(food,map){
for(let i = this.body.length - 1; i > 0; i--){
this.body[i].x = this.body[i - 1].x;
this.body[i].y = this.body[i - 1].y;
}
let head = this.body[0];
//移动的方向
switch(this.direction){
case 'right':
head.x += 1;
break;
case 'left':
head.x -= 1;
break;
case 'top':
head.y -= 1;
break;
case 'bottom':
head.y += 1;
break;
}
let headX = head.x * this.width;
let headY = head.y * this.height;
if(headX === food.x && headY === food.y){
let last = this.body[this.body.length - 1];
this.body.push({
x: last.x,
y: last.y,
color: last.color
})
food.render(map); // 重新生成一个食物
}
}
render(map){
this.remove();
for(let i = 0, len = this.body.length; i < len; i++){
let object = this.body[i];
let div = document.createElement('div');
map.appendChild(div);
this.element.push(div);
//设置样式
div.style.position = 'absolute';
div.style.width = this.width + 'px';
div.style.height = this.height + 'px';
div.style.left = object.x * this.width + 'px';
div.style.top = object.y * this.height + 'px';
div.style.backgroundColor = object.color;
}
}
remove(){
//从大到小
for(let i = this.element.length-1; i >= 0; i--){
//删除真实dom
this.element[i].parentNode.removeChild(this.element[i]);
//删除数组中的元素
this.element.splice(i, 1);
}
}
}
export default Snake;
游戏类(game.js)
import Food from "./food.js";
import Snake from "./snake.js";
//游戏的入口文件
class Game{
constructor(){
this.food = new Food();
this.snake = new Snake();
this.map = map;
this.timerId = null;
}
start(){
this.food.render(this.map);
this.snake.render(this.map);
this.bindKey();
this.runSnake();
}
bindKey() {
document.addEventListener('keydown', e => {
//这里相应的键值会传到snake.js中相应的direction
switch(e.keyCode){
case 37:
this.snake.direction = 'left';
break;
case 38:
this.snake.direction = 'top';
break;
case 39:
this.snake.direction = 'right';
break;
case 40:
this.snake.direction = 'bottom';
break;
}
})
};
runSnake() {
this.timerId = setInterval( () =>{
this.snake.move(this.food, this.map);
let maxX = this.map.offsetWidth / this.snake.width;
let maxY = this.map.offsetHeight / this.snake.height;
let headX = this.snake.body[0].x;
let headY = this.snake.body[0].y;
if(headX <= 0 || headX >= maxX || headY <= 0 || headY >= maxY){
alert("Game over ");
clearInterval(this.timerId);
return
}
this.snake.render(this.map);
}, 500)
}
}
export default Game;
最后再定义一个html文件,用于启动(注意es6启动必须以服务启动)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="map" style=" width:80%;height:400px;border: 1px solid orange;"> </div>
<script type="module">
import Game from './game.js'
let map = document.getElementById('map');
let game = new Game(map);
game.start();
</script>
</body>
</html>
最后在我看来es6相比es5 真的代码美观了好多,也节省了好多代码 ,最重要的是,这个面向对象的思想降低了模块之间的耦合性,总体来说,还不错