效果图:![]()
原生js面向对象方式实现贪吃蛇---斑码出品,必属精品
index.html 入口文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>贪吃蛇</title>
<style>
* {
margin: 0;
padding: 0;
}
.box {
margin: 50px auto;
}
</style>
</head>
<body>
<div class="box"></div>
<script src="js/Food.js"></script>
<script src="js/Game.js"></script>
<script src="js/Map.js"></script>
<script src="js/Snake.js"></script>
<script src="js/Stone.js"></script>
<script>
// 获得容器对象
var container = document.querySelector('.box');
// 准备参数
var map = new Map(container, 750, 750, 15, 15);
// 图片有多个,坐标有多个
var imgsObj = {
head: ['./imgs/1.png', './imgs/2.png', './imgs/3.png', './imgs/4.png'],
body: './imgs/5.png',
foot: ['./imgs/6.png', './imgs/7.png', './imgs/8.png', './imgs/9.png']
}
var snake = new Snake(imgsObj);
// 石头的坐标有多个,石头的坐标不能超越给出的行数和列数的-1
var stone = new Stone('./imgs/block.png', [{row:3, col:3}, {row:3, col:4}, {row:3, col:5}, {row:7, col:3}]);
var food = new Food('./imgs/food.jpg');
// 实例化游戏类,传入四个对象
var game = new Game(snake, stone, map, food);
// 调用游戏对象
game.start();
// 绑定键盘事件
document.onkeydown = function(e) {
// 调用游戏中的按键
game.keydown(e.keyCode);
}
</script>
</body>
</html>
game类
function Game(snake, stone, map, food) {
this.snake = snake;
this.stone = stone;
this.map = map;
this.food = food;
this.dom = this.map.dom;
this.timer = null;
}
// 提供一个按键的处理函数
Game.prototype.keydown = function(v) {
// 判断键盘码的合法性, 除了上下左右,其他的都忽略
if (v >= 37 && v <= 40) {
// 调用蛇头的改变方向
this.snake.changeDirection(v);
}
}
// 检测是否吃到食物
Game.prototype.checkFood = function() {
// 检测蛇头的位置和食物的位置是否相同
var snakeHead = this.snake.arr[0];
var food = this.food.position;
// 判断检测
if (snakeHead.row == food.row && snakeHead.col == food.col) {
// 此时吃到食物
// alert('蛇要长大了');
return true;
}
}
// 检测游戏是否结束
Game.prototype.checkOver = function() {
// 检测蛇头部的位置的合法性
// 获得蛇头的位置
var snakeHead = this.snake.arr[0];
// 边界
if (snakeHead.col < 0 || snakeHead.row < 0 || snakeHead.col > this.map.col - 1 || snakeHead.row > this.map.row - 1) {
return true;
}
// 石头
for (var i = 0; i < this.stone.arr.length; i++) {
if (this.stone.arr[i].row == snakeHead.row && this.stone.arr[i].col == snakeHead.col) {
return true;
}
}
// 蛇的身体和尾部,除了头部
for (var i = 1; i < this.snake.arr.length; i++) {
if (this.snake.arr[i].row == snakeHead.row && this.snake.arr[i].col == snakeHead.col) {
return true;
}
}
}
// 游戏结束的设置
Game.prototype.gameOver = function() {
// 更改背景颜色
document.body.style.backgroundColor = 'rgba(0, 0, 0, .5)';
// 去除所有元素添加背景图
this.map.container.innerHTML = '';
this.map.container.style.backgroundImage = 'url(./imgs/gameover.jpg)';
this.map.container.style.backgroundSize = '100% 100%';
}
// 开始游戏
Game.prototype.start = function() {
// 绘制地图
this.map.render();
// 绘制石头
this.stone.render(this.dom);
// 绘制蛇
this.snake.render(this.dom);
// 随机食物的位置
this.food.randPosition(this.dom, this.snake.arr, this.stone.arr);
// 绘制食物
this.food.render(this.dom);
// 备份this
var me = this;
// 移动
this.timer = setInterval(function() {
// 清屏
me.map.clear();
// 蛇的移动
me.snake.move();
// 检测是否吃到食物
if (me.checkFood()) {
// 蛇要长大
me.snake.grow();
// 食物重新随机
me.food.randPosition(me.dom, me.snake.arr, me.stone.arr);
}
// 检测是否结束游戏
if (me.checkOver()) {
// 结束游戏的设置
me.gameOver();
// 清除定时器
clearInterval(me.timer);
// 后续代码停止执行
return;
}
// 绘制石头
me.stone.render(me.dom);
// 绘制蛇
me.snake.render(me.dom);
// 绘制食物
me.food.render(me.dom);
}, 100);
}
map类
/**
*
* @param {*} container : 整个地图放置的dom结构容器
* @param {*} w : 宽度
* @param {*} h :高度
* @param {*} col :列数
* @param {*} row :行数
*/
function Map(container, w, h, col, row) {
this.container = container;
this.w = w;
this.h = h;
this.col = col;
this.row = row;
this.dom = [];
}
// 绘制地图的方法
Map.prototype.render = function() {
// 创建行
for (var i = 0; i < this.row; i++) {
// 创建行的div
var rowdiv = document.createElement('div');
// 设置行的数组,用于存储生成的coldiv
var rowarr = [];
// 创建列
for (var k = 0; k < this.col; k++) {
// 创建列的div
var coldiv = document.createElement('div');
// 添加样式
coldiv.style.boxSizing = 'border-box';
coldiv.style.border = "1px solid grey";
coldiv.style.float = 'left';
coldiv.style.width = this.w / this.col + 'px';
coldiv.style.height = this.h / this.row + 'px';
// 让列的div上树
rowdiv.appendChild(coldiv);
// 将coldiv放入数组中
rowarr.push(coldiv);
}
// 让行的div上树
this.container.appendChild(rowdiv);
// 将行的数组,放入到整个dom结构中
this.dom.push(rowarr);
}
// 设置样式
this.container.style.width = this.w + 'px';
this.container.style.height = this.h + 'px';
this.container.style.border = '1px solid grey';
}
// 清屏操作
Map.prototype.clear = function() {
for (var row = 0; row < this.dom.length; row++) {
for (var col = 0; col < this.dom[row].length; col++) {
this.dom[row][col].style.backgroundImage = 'none';
}
}
}
food类
function Food(url) {
this.url = url;
this.position = null;
}
// 绘制食物
Food.prototype.render = function(dom) {
// 绘制
dom[this.position.row][this.position.col].style.backgroundImage = 'url(' + this.url + ')';
dom[this.position.row][this.position.col].style.backgroundSize = 'cover';
}
// 随机食物的位置
Food.prototype.randPosition = function(dom, snakeArr, stoneArr) {
// 不能再那些位置
var stopArr = snakeArr.concat(stoneArr);
// 确定随机值
var rowMax = dom.length - 1;
var colMax = dom[0].length - 1;
// 选随机位置
do {
var row = Math.round(Math.random() * rowMax);
var col = Math.round(Math.random() * colMax);
} while((function(row, col){
for (var i = 0; i < stopArr.length; i++) {
// 判断该位置是否和已经存在的位置冲突
if (stopArr[i].row == row && stopArr[i].col == col) {
return true;
}
}
})(row, col));
// 记录食物的坐标
this.position = {
row: row,
col: col
}
}
snake类
function Snake(imgsObj) {
// 图片
this.imgsObj = imgsObj;
// 坐标: 第一个为蛇头,最后一个为尾部
this.arr = [{row:5, col: 8}, {row:5, col: 7}, {row:5, col: 6}];
// 蛇的方向:默认向右
this.direction = 39;
// 蛇头的图片
this.headUrl = imgsObj.head[2];
// 蛇尾图片
this.footUrl = imgsObj.foot[0];
// 声明锁
this.lock = false;
// 声明丢掉尾巴的变量
this.dropTail = null;
}
// 绘制蛇的方法
Snake.prototype.render = function(dom) {
// 绘制蛇头
var row = this.arr[0].row;
var col = this.arr[0].col;
// 确定蛇头的图片
dom[row][col].style.backgroundImage = 'url(' + this.headUrl + ')';
dom[row][col].style.backgroundSize = 'cover';
// 遍历坐标数组进行绘制蛇的身体
for (var i = 1; i < this.arr.length - 1; i++) {
// 接收行和列的坐标
var row = this.arr[i].row;
var col = this.arr[i].col;
// 绘制
dom[row][col].style.backgroundImage = 'url(' + this.imgsObj.body + ')';
dom[row][col].style.backgroundSize = 'cover';
}
// 确定蛇尾的图片
var tail = this.arr[this.arr.length - 1];
var hip = this.arr[this.arr.length - 2];
// 判断屁股和尾巴的位置关系
if (tail.row == hip.row) {
this.footUrl = tail.col > hip.col ? this.imgsObj.foot[2]: this.imgsObj.foot[0];
} else {
this.footUrl = tail.row > hip.row ? this.imgsObj.foot[3]: this.imgsObj.foot[1];
}
// 绘制蛇尾
var row = this.arr[this.arr.length - 1].row;
var col = this.arr[this.arr.length - 1].col;
// 确定蛇头的图片
dom[row][col].style.backgroundImage = 'url(' + this.footUrl + ')';
dom[row][col].style.backgroundSize = 'cover';
}
// 蛇的移动
Snake.prototype.move = function(dom) {
var head = {
row: this.arr[0].row,
col: this.arr[0].col
};
// 判断方向,生成新的头部坐标
switch(this.direction) {
// 向右
case 39:
head.col++;
break;
// 向左
case 37:
head.col--;
break;
// 向上
case 38:
head.row--;
break;
// 向下
case 40:
head.row++;
break;
}
// 改变坐标的数组,将新的头部插入到数组中,将原来的尾部弹出
this.arr.unshift(head);
// 接收丢掉的尾巴
this.dropTail = this.arr.pop();
// 重置锁
this.lock = false;
}
// 改变蛇的方向
Snake.prototype.changeDirection = function(v) {
// 判断锁
if (this.lock) {
// console.log(v, '此时已经上锁');
return;
}
// 更改锁
this.lock = true;
// 方向的判断
if (Math.abs(v - this.direction) % 2 == 1) {
// 改变方向
this.direction = v;
// 改变蛇头图片
this.headUrl = this.imgsObj.head[this.direction - 37];
}
}
// 蛇生长
Snake.prototype.grow = function() {
// 将丢掉的尾巴,放入到数组中
this.arr.push(this.dropTail);
}
stone障碍物类
function Stone(url, arr) {
this.url = url;
this.arr = arr;
}
// 绘制石头
Stone.prototype.render = function(dom) {
// 遍历数组绘制的过程
for (var i = 0; i < this.arr.length; i++) {
// 接收对应的行和列
var row = this.arr[i].row;
var col = this.arr[i].col;
// console.log(this.arr[i]);
// 设置对应的dom
dom[row][col].style.backgroundImage = 'url(' + this.url + ')';
dom[row][col].style.backgroundSize = 'cover';
}
}
代码结构:![]()
原生js面向对象方式实现贪吃蛇---斑码出品,必属精品
游戏中涉及的图片:
图片的命名:
需要下载源文件的朋友可以加入QQ群:1103015245
喜欢的朋友可以点赞收藏分享哦!!!!