前提:游戏玩腻了?作为一名合格的程序员,应该自己开发小游戏来玩,玩腻了,自己就再去开发个游戏,利用这一特点实现永动机。既可以学习,也可以娱乐。
本次开发的是贪吃蛇小游戏。使用技术:html、css、原生js、部分es6语法
贪吃蛇实现原理:利用绝对定位的left和top来小蛇进行移动
开发游戏的思路:
- 首先在页面上放一个大的盒子(box),加上border,相当于一个围栏。这个大盒子就是游戏区域。
- 在box中,又四个盒子,2个body盒子作为蛇的身体(初始长度为2),snake作为蛇头部,food作为食物。
- 将蛇的身体的第一段放在left:0;right:0这个位置,第二段向右偏移50px(因为蛇的一段身体的宽高是50*50),蛇的头部向右偏移100px。这就是蛇的初始位置。
- 蛇的移动:我们要知道,蛇的身体是跟着蛇的方向来移动的。我们可以通过移动蛇头,然后利用循环或者递归来使蛇的一段段身体来移动(就是第一段身体移动到蛇头的位置,第二段身体移动到第一段身体的位置),为了防止蛇的身体和头部的位置重叠,我们就从最后一段开始移动,而不是使蛇头先移动。
- 食物的随机出现:因为我蛇每次移动都是50px,所以食物的left和top位置都是50的倍数(0-1000中),Math.floor(Math.random() * 20) * 50就是取50的倍数,范围是0-1000.
- 判断蛇有没有撞到身体或者吃到食物或者撞到墙:就利用蛇头的left和top跟他们比较,如果相等就撞到获取吃到食物。
- 自动移动:利用时间间隔函数。
- 其他的功能:代码注释都有详细说明,如果还有不懂的可以评论或者私信我!
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<style>
* {
padding: 0;
margin: 0;
}
.box {
position: relative;
width: 1000px;
height: 1000px;
margin: 50px auto;
border: 1px solid red;
}
.snake {
position: absolute;
width: 50px;
height: 50px;
background-color: red;
}
.food {
position: absolute;
top: 100px;
left: 100px;
width: 50px;
height: 50px;
background-color: pink;
}
.body {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
background-color: green;
}
</style>
</head>
<body>
<div class="box">
<div class="body"></div>
<!--由于two的style样式使用dom.style获取不到,就写到了行内样式中-->
<div class="body" id="two" style="top:0px;left:50px"></div>
<div class="snake"></div>
<div class="food"></div>
</div>
</body>
<script src="./贪吃蛇.js"></script>
</html>
class Snake {
constructor() {
this.snake = document.querySelector('.snake')
this.food = document.querySelector('.food')
this.bodys = document.querySelectorAll('.body')
this.top = 0
this.left = 100
this.lastTop = '' //记录蛇身体最后一段的top
this.lastLeft = '' //记录蛇身体最后一段的left
this.lastBody = null //蛇的最后一段,没吃到食物为null
this.snakeMoveByAuto = null
this.init()
}
// 初始化
init () {
this.snake.style.top = this.top + 'px'
this.snake.style.left = this.left + 'px'
this.foodAppearByRandom()
// 监听键盘的事件
document.querySelector('body').onkeydown = (e) => {
clearInterval(this.snakeMoveByAuto)
switch (e.keyCode) {
case 87: //w键
this.snakeMoveByAuto = setInterval(() => this.snakeMove(-50, 0), 500)
break;
case 65: // a键
this.snakeMoveByAuto = setInterval(() => this.snakeMove(0, -50), 500)
break;
case 83: // s键
this.snakeMoveByAuto = setInterval(() => this.snakeMove(50, 0), 500)
break;
case 68: // d键
this.snakeMoveByAuto = setInterval(() => this.snakeMove(0, 50), 500)
break;
}
}
}
// 食物随机出现
foodAppearByRandom () {
let length = this.bodys.length
this.food.style.top = Math.floor(Math.random() * 20) * 50 + 'px'
this.food.style.left = Math.floor(Math.random() * 20) * 50 + 'px'
// 防止食物刷新在同一位置
if (this.snake.style.top === this.food.style.top && this.snake.style.left === this.food.style.left) {
this.foodAppearByRandom()
}
// 防止食物刷新在蛇身上
for (var i = 0; i < length; i++) {
if (this.food.style.top === this.bodys[i].style.top && this.food.style.left === this.bodys[i].style.left) {
this.foodAppearByRandom()
}
}
}
// 移动蛇位置
snakeMove (top, left) {
let newTop = parseInt(this.snake.style.top.slice(0, -2)) + top
let newLeft = parseInt(this.snake.style.left.slice(0, -2)) + left
let length = this.bodys.length
// 阻止蛇走出方框
// 因为盒子的宽高是50px,就各自减50
if (newTop < 0 || newTop > 950 || newLeft < 0 || newLeft > 950) {
clearInterval(this.snakeMoveByAuto)
alert('gg')
window.location.reload()
return
}
// 让蛇身体后一个跟着前一个移动
for (var i = 0; i < length - 1; i++) {
console.log(this.bodys[i + 1].style.left)
this.bodys[i].style.left = this.bodys[i + 1].style.left
this.bodys[i].style.top = this.bodys[i + 1].style.top
}
// 让蛇身体的最后部分跟着蛇的头移动
this.bodys[length - 1].style.top = this.snake.style.top
this.bodys[length - 1].style.left = this.snake.style.left
// 让蛇的头部移动
this.snake.style.top = newTop + 'px'
this.snake.style.left = newLeft + 'px'
// 蛇吃到食物
if (this.snake.style.top === this.food.style.top && this.snake.style.left === this.food.style.left) {
this.lastTop = this.bodys[0].style.top
this.lastLeft = this.bodys[0].style.left
this.foodAppearByRandom()
this.snakeChangeBig()
}
// 循环判断蛇有没有撞到自己的身体
for (var i = 0; i < length; i++) {
if (this.snake.style.top === this.bodys[i].style.top && this.snake.style.left === this.bodys[i].style.left) {
clearInterval(this.snakeMoveByAuto)
alert('gg')
window.location.reload()
}
}
}
// 蛇吃到食物变大
snakeChangeBig () {
// 创建蛇身体最后一段
this.lastBody = document.createElement('div')
this.lastBody.className = 'body'
this.lastBody.style.top = this.lastTop
this.lastBody.style.left = this.lastLeft
document.querySelector('.box').prepend(this.lastBody)
// 因为添加了蛇的最后一段,所以要更新this.bodys
this.bodys = document.querySelectorAll('.body')
}
}
var snake = new Snake()
游戏操作:使用键盘的wasd来控制方向。
GitHub项目:https://github.com/wa545464/H5-
小白运行教程:
创建一个html文件,html文件内容如下,然后用浏览器打开该html文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<style>
* {
padding: 0;
margin: 0;
}
.box {
position: relative;
width: 1000px;
height: 1000px;
margin: 50px auto;
border: 1px solid red;
}
.snake {
position: absolute;
width: 50px;
height: 50px;
background-color: red;
}
.food {
position: absolute;
top: 100px;
left: 100px;
width: 50px;
height: 50px;
background-color: pink;
}
.body {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
background-color: green;
}
</style>
</head>
<body>
<div class="box">
<div class="body"></div>
<!--由于two的style样式使用dom.style获取不到,就写到了行内样式中-->
<div class="body" id="two" style="top:0px;left:50px"></div>
<div class="snake"></div>
<div class="food"></div>
</div>
</body>
<script>
class Snake {
constructor() {
this.snake = document.querySelector('.snake')
this.food = document.querySelector('.food')
this.bodys = document.querySelectorAll('.body')
this.top = 0
this.left = 100
this.lastTop = '' //记录蛇身体最后一段的top
this.lastLeft = '' //记录蛇身体最后一段的left
this.lastBody = null //蛇的最后一段,没吃到食物为null
this.snakeMoveByAuto = null
this.init()
}
// 初始化
init () {
this.snake.style.top = this.top + 'px'
this.snake.style.left = this.left + 'px'
this.foodAppearByRandom()
// 监听键盘的事件
document.querySelector('body').onkeydown = (e) => {
clearInterval(this.snakeMoveByAuto)
switch (e.keyCode) {
case 87: //w键
this.snakeMoveByAuto = setInterval(() => this.snakeMove(-50, 0), 500)
break;
case 65: // a键
this.snakeMoveByAuto = setInterval(() => this.snakeMove(0, -50), 500)
break;
case 83: // s键
this.snakeMoveByAuto = setInterval(() => this.snakeMove(50, 0), 500)
break;
case 68: // d键
this.snakeMoveByAuto = setInterval(() => this.snakeMove(0, 50), 500)
break;
}
}
}
// 食物随机出现
foodAppearByRandom () {
let length = this.bodys.length
this.food.style.top = Math.floor(Math.random() * 20) * 50 + 'px'
this.food.style.left = Math.floor(Math.random() * 20) * 50 + 'px'
// 防止食物刷新在同一位置
if (this.snake.style.top === this.food.style.top && this.snake.style.left === this.food.style.left) {
this.foodAppearByRandom()
}
// 防止食物刷新在蛇身上
for (var i = 0; i < length; i++) {
if (this.food.style.top === this.bodys[i].style.top && this.food.style.left === this.bodys[i].style.left) {
this.foodAppearByRandom()
}
}
}
// 移动蛇位置
snakeMove (top, left) {
let newTop = parseInt(this.snake.style.top.slice(0, -2)) + top
let newLeft = parseInt(this.snake.style.left.slice(0, -2)) + left
let length = this.bodys.length
// 阻止蛇走出方框
// 因为盒子的宽高是50px,就各自减50
if (newTop < 0 || newTop > 950 || newLeft < 0 || newLeft > 950) {
clearInterval(this.snakeMoveByAuto)
alert('gg')
window.location.reload()
return
}
// 让蛇身体后一个跟着前一个移动
for (var i = 0; i < length - 1; i++) {
console.log(this.bodys[i + 1].style.left)
this.bodys[i].style.left = this.bodys[i + 1].style.left
this.bodys[i].style.top = this.bodys[i + 1].style.top
}
// 让蛇身体的最后部分跟着蛇的头移动
this.bodys[length - 1].style.top = this.snake.style.top
this.bodys[length - 1].style.left = this.snake.style.left
// 让蛇的头部移动
this.snake.style.top = newTop + 'px'
this.snake.style.left = newLeft + 'px'
// 蛇吃到食物
if (this.snake.style.top === this.food.style.top && this.snake.style.left === this.food.style.left) {
this.lastTop = this.bodys[0].style.top
this.lastLeft = this.bodys[0].style.left
this.foodAppearByRandom()
this.snakeChangeBig()
}
// 循环判断蛇有没有撞到自己的身体
for (var i = 0; i < length; i++) {
if (this.snake.style.top === this.bodys[i].style.top && this.snake.style.left === this.bodys[i].style.left) {
clearInterval(this.snakeMoveByAuto)
alert('gg')
window.location.reload()
}
}
}
// 蛇吃到食物变大
snakeChangeBig () {
// 创建蛇身体最后一段
this.lastBody = document.createElement('div')
this.lastBody.className = 'body'
this.lastBody.style.top = this.lastTop
this.lastBody.style.left = this.lastLeft
document.querySelector('.box').prepend(this.lastBody)
// 因为添加了蛇的最后一段,所以要更新this.bodys
this.bodys = document.querySelectorAll('.body')
}
}
var snake = new Snake()
</script>
</html>