html5游戏之贪吃蛇
刚开始接触前端知识已经是某一个燥热的夏天的一个下午的…………
诶,前不久听一个兄弟说前端可以做游戏,我还不信,这玩意儿看着就复杂,前端还可以做???我寻思着要不去试试,说干就干。就把它给弄明白——贪吃蛇。
不,不,不,不是那,是游戏贪吃蛇。
自娱一下,嘿嘿嘿,好了进入主题:
html代码
在HTML代码中主要使用到的是html5新增的标签 canvas 画布标签、 audio 音频标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="./css/index.css" />
</head>
<body>
<!-- 内容区域 -->
<div id="box">
<!-- canvas是一种绘图技术,由JavaScript来进行操作,能够实现图形或图片的绘制,
并且配合JavaScript中的定时器等技术实现页面的动态效果
1.使用canvas需要在页面上添加canvas 标签,用于充当画布的角色
2需要利用js提供的函数来获取画笔,来进行画笔工作
3.利用画笔以及js提供的内置函数来完成绘图操作 -->
<!-- canvas是专门来绘制的画布标签,对外会表现为一个块级元素 -->
<canvas id="Snack"></canvas>
<!-- 工具栏,主要负责负数和按钮 -->
<div id="toolbar">
<div id="GameScore">
0分
</div>
<div id="GameTime">
0s
</div>
<div id="buttons">
<button type="button" id="start" onclick="start()"></button>
<button type="button" id="pause" onclick="pause()"></button>
</div>
</div>
<div id="GameOver">
<img src="image/gameover.png">
</div>
</div>
<audio src="./audio/Cut_01.mp3" id="bgmusic" preload="auto" loop></audio>
<audio src="./audio/si.mp3" id="addmusic" preload="auto"></audio>
<audio src="./audio/boing3.wav" id="overmusic" preload="auto" loop></audio>
</body>
<script src="js/SnackPart.js" type="text/javascript" charset="utf-8"></script>
<script src="js/track.js" type="text/javascript" charset="utf-8"></script>
<script src="./js/index.js" type="text/javascript" charset="utf-8"></script>
</html>
css代码
#box{
margin: 200px auto;
width: 654px;
height: 446px;
background:url(../image/bg.png);
position: relative;
}
#toolbar{
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 36px;
background:url(../image/toolbar1.png);
color: white;
font-weight: 700;
display: flex;
line-height: 29px;
}
#GameScore{
flex: 8;
text-indent: 3.5rem;
}
#GameTime{
flex: 9;
text-indent: 4.5rem;
}
#buttons{
flex: 5;
margin-left: -50px;
}
#start,#pause{
height: 27px;
width: 55px;
border: none;
}
#start{
background: url(../image/start.png) no-repeat center;
background-size: cover;
}
#pause{
background: url(../image/pause.png) no-repeat center;
background-size: cover;
}
#Snack{
width: 600px;
height: 360px;
position: absolute;
top: 33px;
left: 29px;
}
#GameOver{
display: none;
width: 100%;
height: 100%;
position: relative;
}
#GameOver img{
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: block;
margin: auto;
width: 60%;
height: 60%;
}
JavaScript代码
在js中主要运用到画布画笔,定时器,监听键盘的点击事件以及类的使用等相关知识
var canvas = document.getElementById('Snack');
var ctx = canvas.getContext('2d');//获取画笔
var GameOverImg = document.getElementById('GameOver');
var GameTime = document.getElementById('GameTime');
var Start = document.getElementById('start');
var bgmusic = document.getElementById('bgmusic');
var overmusic = document.getElementById('overmusic');
var addmusic = document.getElementById('addmusic');
//将画布的宽高调整为和css设置的高度一致
canvas.width = 600;
canvas.height = 360;
var headDir = 2; //0 下,1 上,2 右, 3左
//设置蛇数组,默认是只有头部和尾部
var SnackArr = [new SnackPart(1,0,headDir,-1),new SnackPart(0,0,headDir,0)];
//控制蛇的速度300ms
var speed = 300;
//记录头部的运动轨迹,
var track = []
//保存食物的坐标
var foodLocation = {x:-1,y:-1};
//保存尾部最后的一个位置
var toadd = {};
var GameOver = false;
//计时间
var time = 0;
//定时器
var countTimer = null;
var timer=null;
/*
**第一部分
*/
//在js中加载需要绘制的图片
var headimg = document.createElement('img');
var footimg = document.createElement('img');
var bodyimg = document.createElement('img');
var foodimg = document.createElement('img')
//在js中,给图片元素天剑设置src属性浏览器就会自动加载给图片到内存中,js可以操作
//保证图片加载完成后才执行
headimg.src = './image/head.png';
footimg.src = './image/foot.png';
foodimg.src = './image/egg.png';
bodyimg.src = './image/body.png'
headimg.onload = function(){
footimg.onload = function(){
bodyimg.onload =function(){
renderSnack()
}
}
}
foodimg.onload =function(){
createRandomFood();
renderFood()
}
//绘制贪吃蛇
function renderSnack(){
//绘制我们贪吃蛇的向下部分
//drawImage(九个参数),我们绘制什么,在画布中的那个区域绘制,绘制图片的那个区域
//drawImage(img对象,图片绘制的左上角坐标x,和,以及绘制的区域宽,高,画布绘制区域的左上坐标的x,和y,以及绘制区域的宽,高度)
var head = SnackArr[0];
var foot = SnackArr[1]
ctx.drawImage(headimg,headDir*40,0,40,40,head.x*20,head.y*20,20,20);
ctx.drawImage(footimg,SnackArr[SnackArr.length-1].dir*40,0,40,40,SnackArr[SnackArr.length-1].x*20,SnackArr[SnackArr.length-1].y*20,20,20);
for(var i = 1;i<SnackArr.length-1;i++)
{
ctx.drawImage(bodyimg,0,0,40,40,SnackArr[i].x*20,SnackArr[i].y*20,20,20);
}
}
// 键盘监听事件
document.body.onkeydown = function(res){
switch (res.keyCode){
case 37 :
headDir = 3;
break;
case 38 :
headDir = 1;
break;
case 39 :
headDir = 2;
break;
case 40 :
headDir = 0;
break;
}
}
//计时器
function count(){
countTimer = setInterval(()=>{
time ++;
GameTime.innerHTML = time+'s';
},1000)
}
//定时绘制图片
function drawInverval(){
timer=setInterval(()=>{
move();
out();
// 清除当前画布上的图案 画笔.clearRect(起始坐标x,y,擦除画布宽度,高度)
ctx.clearRect(0,0,canvas.width,canvas.height);
eat();
renderFood();
renderSnack();
if(GameOver)
{
clearInterval(timer)
clearInterval(countTimer)
GameOver = false
GameOverImg.style.display = "block";
bgmusic.pause();
overmusic.play();
}
console.log("当前速度为:",speed)
},speed);
}
//点击暂停
function pause(){
bgmusic.pause();
clearInterval(timer);
clearInterval(countTimer);
Start.disabled = false;
}
//开始的定时器
function start(){
Start.disabled = "disabled"
count();
bgmusic.play();
drawInverval();
}
//move函数,规定蛇的身体移动
function move(){
//把头部当前的位置添加到当前的轨迹数组中
track.push(new tracks(SnackArr[0].x,SnackArr[0].y,headDir))
switch(headDir)
{
case 0:
SnackArr[0].y++;
break;
case 1:
SnackArr[0].y--;
break;
case 2:
SnackArr[0].x++;
break;
case 3:
SnackArr[0].x--;
break;
}
//身体移动
var foot = SnackArr[SnackArr.length-1]
toadd = {x:foot.x,y:foot.y,dir:foot.dir,next:foot.next};
for(var i = 1;i < SnackArr.length;i++)
{
var s = SnackArr[i];
var next = track[s.next];
s.x=next.x;
s.y=next.y;
s.dir = next.dir
s.next++;
}
}
//第三部分贪吃蛇生长
// 随机食物
function createRandomFood(){
var x = parseInt(Math.random()*30)
var y = parseInt(Math.random()*18)
foodLocation.x = x;
foodLocation.y = y;
}
//绘制食物
function renderFood(){
ctx.drawImage(foodimg,0,0,40,40,foodLocation.x*20,foodLocation.y*20,20,20)
}
//判断是否可以吃食物
function eat(){
//头部的位置和食物的位置是否yizhi
var head = SnackArr[0];
if(head.x==foodLocation.x&&head.y == foodLocation.y)
{
//贪吃蛇生长
SnackArr.push(toadd);
createRandomFood();
addmusic.play();
if((SnackArr.length-2)%5==0)
{
console.log(SnackArr.length+'hhh')
speed -=speed*0.2; //改变速度
clearInterval(timer);
drawInverval();
}
document.getElementById('GameScore').innerHTML =(SnackArr.length-2) + "分";
}
}
//判断出界以及碰到自己
function out(){
var x = SnackArr[0].x;
var y = SnackArr[0].y;
if(x<0||x>=30||y<0||y>=18)
{
GameOver = true;
}
for(var i = 1;i < SnackArr.length; i++)
{
if(SnackArr[i].x==x&&SnackArr[i].y==y)
{
GameOver = true
}
}
}
两个类SnackPart
class SnackPart { //蛇身体
constructor(x,y,dir,next) {
this.x = x;
this.y = y;
this.dir = dir;
this.next = next;
}
}
class tracks {//蛇头走过的路径
constructor(x,y,dir) {
this.x = x;
this.y = y;
this.dir = dir;
}
}
运行看看效果:
操作了几把,真的是手笨,分数一次都没过50,哎~~
愣着干哈快去自己写一个,弄来玩玩~…
对了告诉你一个小秘密,需要图片资源源码的可以私聊我哟