CSS页面代码:
.games {
width: 400px;
height: 400px;
margin: 40px auto 0;
background: #999;
position: relative;
}
.mask {
width: 100%;
height: 100%;
font-size: 24px;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, .6);
position: absolute;
left: 0;
top: 0;
z-index: 99;
}
.btns-box {
width: 400px;
margin: 20px auto 0;
display: flex;
justify-content: center;
}
.btn-item {
margin-right: 10px;
padding: 6px 16px;
color: #fff;
background-color: rgb(109, 105, 106);
cursor: pointer;
border-radius: 4px;
}
HTML页面代码如下:
<div class="games"></div>
<div class="btns-box">
<div class="btn-item btn-start">开始</div>
<div class="btn-item btn-stop">暂停</div>
</div>
引入JS详细代码:
<script src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
<script>
// 获取随机数
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min) + min + 1);
}
// 创建snake对象
function Snake(games, games_w, games_h) {
// 游戏界面
this.games = games;
// 界面宽度
this.games_w = games_w;
// 界面高度
this.games_h = games_h;
// 小蛇每一节宽度
this.width = 20;
// 小蛇每一节高度
this.height = 20;
// 小蛇身体坐标保存数组
this.body = [];
// 小蛇移动方向
this.dir = '';
// 小蛇上次移动方向保留
this.lastDir = '';
}
// 小蛇初始化
Snake.prototype.init = function () {
this.body = [
[1, 1, '#eee', null],
[2, 1, '#eee', null],
[3, 1, '#000', null]
];
this.dir = 'right';
this.lastDir = 'right';
this.create();
this.changeDir();
}
// 在游戏界面中创建小蛇
Snake.prototype.create = function () {
let _body = this.body;
// 循环每个坐标在游戏界面中显示
for (let i = 0; i < _body.length; i++) {
if (_body[i][3] == null) {
_body[i][3] = $('<div></div>');
}
_body[i][3].css({
'width': this.width + 'px',
'height': this.height + 'px',
'position': 'absolute',
'left': this.width * _body[i][0] + 'px',
'top': this.height * _body[i][1] + 'px',
'background-color': _body[i][2],
'border-radius': this.width + 'px'
});
this.games.append(_body[i][3]);
}
}
// 小蛇移动方法
Snake.prototype.move = function () {
let _body = this.body,
_length = _body.length;
// 小蛇移动原理
// 将头部按照对应的方向移动
// 后面的一节身体坐标取上一节身体的上一个坐标,依次往后替换
for (let i = 0; i < _length - 1; i++) {
_body[i][0] = _body[i + 1][0];
_body[i][1] = _body[i + 1][1];
}
let sn_head = _body[_length - 1];
// 根据方向移动头部
switch (this.dir) {
case 'left':
sn_head[0] -= 1;
break;
case 'right':
sn_head[0] += 1;
break;
case 'up':
sn_head[1] -= 1;
break;
case 'down':
sn_head[1] += 1;
break;
}
this.lastDir = this.dir;
// 如果游戏已经结束,就不再进行渲染
if(this.isOver()){
return;
}
this.create();
}
// 切换方向原理
Snake.prototype.changeDir = function () {
let _this = this;
$(document).keydown(function (e) {
let _lastDir = _this.lastDir;
switch (e.key) {
case 'ArrowLeft':
_this.dir = _lastDir == 'right' ? 'right' : 'left';
break;
case 'ArrowRight':
_this.dir = _lastDir == 'left' ? 'left' : 'right';
break;
case 'ArrowUp':
_this.dir = _lastDir == 'down' ? 'down' : 'up';
break;
case 'ArrowDown':
_this.dir = _lastDir == 'up' ? 'up' : 'down';
break;
}
})
}
Snake.prototype.isOver = function () {
let _body = this.body,
_x = _body[_body.length- 1][0],
_y = _body[_body.length- 1][1],
_mx = this.games_w / this.width - 1,
_my = this.games_h / this.height - 1;
// 判断蛇头是否碰墙
if (_x < 0 || _y < 0 || _x >= _mx || _y >= _my) {
return true;
}
// 判断蛇头是否碰到自身
for (let i = 0; i < _body.length - 1; i++) {
if (_x == _body[i][0] && _y == _body[i][1]) {
return true;
}
}
}
// 创建食物对象
function Foods(games, games_w, games_h, snake) {
this.games = games;
this.width = 20;
this.height = 20;
this.body = [-1, -1, '#f00', null];
this.games_w = games_w;
this.games_h = games_h;
this.snake = snake;
}
Foods.prototype.init = function () {
this.create();
this.isEat();
}
Foods.prototype.create = function () {
let _body = this.body,
_snake_body = this.snake.body,
isHave = false;
_body[0] = getRandom(0, this.games_w / this.width - 1);
_body[1] = getRandom(0, this.games_h / this.height - 1);
// 在游戏界面生成随机的食物
// 如果食物生成到蛇身上,就重新生成
for (let i = 0; i < _snake_body.length; i++) {
if (_body[0] == _snake_body[i][0] && _body[1] == _snake_body[i][1]) {
isHave = true;
break;
}
}
if (isHave) {
this.create();
return false;
}
_body[3] = $('<div></div>');
_body[3].css({
'width': this.width + 'px',
'height': this.height + 'px',
'position': 'absolute',
'left': this.width * (this.body[0]) + 'px',
'top': this.height * (this.body[1]) + 'px',
'background-color': this.body[2],
'border-radius': this.width + 'px',
});
this.games.append(_body[3]);
}
// 判断蛇是否吃到食物
Foods.prototype.isEat = function () {
// 吃到食物就向蛇身体数组添加一组值
let _snake_body_head = this.snake.body[this.snake.body.length-1];
if (this.body[0] == _snake_body_head[0] && this.body[1] == _snake_body_head[1]) {
this.body[3].remove();
this.create();
this.snake.body.unshift([-1, -1, "#eee", null]);
}
}
// 创建游戏对象
function Games(games) {
this.games = games;
this.games_w = games.width();
this.games_h = games.height();
this.snake = new Snake(this.games, this.games_w, this.games_h);
this.food = new Foods(this.games, this.games_w, this.games_h, this.snake);
this.timer = null;
this.isStart = false;
this.isEnd = false;
this.isPause = false;
this.init();
}
Games.prototype.init = function () {
let _snake = this.snake,
_food = this.food;
this.isEnd = false;
this.games.empty();
_snake.init();
_food.init();
}
Games.prototype.start = function () {
// 判断是否已经开始,如果已经开始就不再继续点击了
if (this.isStart) return;
let _snake = this.snake,
_food = this.food,
_this = this;
_this.isStart = true;
_this.isPause = false;
_this.games.find('.mask').remove();
if (_this.isEnd) {
_this.init();
}
_this.timer = setInterval(function () {
if (_snake.isOver()) {
clearInterval(_this.timer);
_this.isEnd = true;
_this.isStart = false;
_this.end('游戏结束');
return false;
}
_snake.move();
_food.isEat();
}, 500);
}
Games.prototype.end = function (text) {
let _end = $('<div class="mask">' + text + '</div>');
this.games.append(_end);
}
Games.prototype.stop = function () {
// 判断是否已经暂停,如果已经暂停就不能继续点击了
if (this.isPause) return;
this.isPause = true;
this.isStart = false;
clearInterval(this.timer);
this.end('游戏暂停');
}
let games = new Games($('.games'));
$('.btn-start').click(function () {
games.start();
});
$('.btn-stop').click(function () {
games.stop();
});
</script>
运行效果如图: