效果圖:
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';
}
}
代碼結構:
遊戲中涉及的圖檔:
圖檔的命名:
需要下載下傳源檔案的朋友可以加入QQ群:1103015245
喜歡的朋友可以點贊收藏分享哦!!!!