我正在参加 码上掘金体验活动,详情:show出你的创意代码块
前言
今天给大家分享一个网页小游戏贪吃蛇,相当经典的一款童年游戏,从零开始,构建一个完整的游戏应用,接下来开始吧。
代码
正文
1、画图
首先我们做的是一个游戏,要知道他具体包含什么,然后再逐个的列出来,最后在使用html代码组装起来。我大概设计了一下页面,具体包括得分框、贪吃蛇身体、贪吃蛇头部、要吃掉的道具、各个控制开始暂停的按钮以及控制上下左右的按键。
1.1 把整个布局画出来
html代码如下
<div class="content">
<div class="left-box">
<div class="score">
得分:
<span id="score">
0
</span>
</div>
<div id="gameBox"class="gameBox">
<div class="bg-img-box">
<div id="head"class="head snake">
<img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fis5.mzstatic.com%2Fimage%2Fthumb%2FPurple122%2Fv4%2F34%2F95%2F80%2F34958089-1d33-a766-84f8-f060a85728ca%2Fsource%2F1024x1024bb.jpeg&refer=http%3A%2F%2Fis5.mzstatic.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1652539374&t=8fcd0bcd14b49c9a6bf9e45e3b1efc95">
</div>
</div>
</div>
</div>
再加css 的修饰,得到效果如下:
1.2把初始值的身体放上去
上面我们把贪吃蛇的头部已经放出来了,那么我们要在它的后面增加初始长度身体,我们设置了25px的身体,后面将会用到这个值。因为身体都是动态的,因为要吃了道具就会增加身体长度,所以我们使用js代码进行增加身体,方法如下:
function addBody(x, y, type) {
type = type || " snakeBody";
var html = "<div class='" + type + " snake'></div>";
var $snakeBody = $(html);
$snakeBody.css("left", x + "px");
$snakeBody.css("top", y + "px");
$gameBox.append($snakeBody);
if(type != "egg") {
bodyArry.push($snakeBody);
} else {
$egg = $snakeBody;
}
}
我们设置了addBody方法,进行身体及道具(我这里叫它蛋蛋)的添加,原理就是在游戏页面容器进行传入x/y坐标,添加一个身体或者蛋。我们开始的时候先加两个身体的长度,这两个坐标需要跟头部连在一起代码及效果图如下:
addBody(180, 200);
addBody(160, 200);
2、添加随机道具
贪吃蛇游戏就是要在图上随机显示一个道具,然后操作贪吃蛇去吃它进而增加身体长度,所以我们要用js代码进行随机生成渲染,代码如下:
function addEgg() {
eggX = Math.round(Math.random() * gameGround.x / 25) * step;
eggY = Math.round(Math.random() * gameGround.y / 25) * step;
addBody(eggX, eggY, "egg");
}
以上代码我们设置了一个addEgg的方法,来对随机道具的生成,就是整个图的高度和宽度除25(这个是之前说身体的宽度),再成step(这个变量是每操作一步走的宽度),这样就得到了道具的随机坐标,然后使用之前的addBody进行增加在游戏界面上,就完成了蛋蛋的添加,效果如下:
3、操作贪吃蛇
3.1设置移动函数
游戏就是需要人为的操作,我们要让它动起来就是需要按钮或者按键进行整条贪吃蛇的移动。 首先我们使用先定义移动的方法,代码如下:
function move(key) {
if(key == 37) {
typeY = 0; //左
typeX = -1;
} else if(key == 38) { //上
typeX = 0;
typeY = -1;
} else if(key == 39) {
typeY = 0; //右
typeX = 1;
} else if(key == 40) { //下
typeY = 1;
typeX = 0;
} else if(key == 32) { //下
clearInterval(timer);
} else if(key == 13) { //下
snakeRun();
} else {
if(key) {
return;
}
}
var oldHeadX = +$head.css('left').split("px")[0];
var oldHeadY = +$head.css('top').split("px")[0];
var moveX = typeX * step;
var moveY = typeY * step;
$head.css("left", "+=" + moveX + "px");
$head.css("top", "+=" + moveY + "px");
bodyArry[bodyArry.length - 1].css("left", oldHeadX + "px");
bodyArry[bodyArry.length - 1].css("top", oldHeadY + "px");
if(bodyArry.length > 1) {
bodyArry.unshift(bodyArry[bodyArry.length - 1]);
bodyArry.pop();
}
if(gameOver()) {
myAlert();
}
eatEgg();
gameOver();
}
以上代码定义了move方法,用来移动贪吃蛇以及其他逻辑的判断。具体思路是依据每个按键的值来判断是向哪边移动,然后没执行一次整体的移动就乘以step(每一步移动的距离),然后拿到距离再让整个贪吃蛇各个部分一起移动。
3.2设置其他方法
上面代码我们看到了调用了gameOver、eatEgg、myAlert等方法,下面我来解释一下他们的作用及具体代码。 gameOver方法用判断游戏是否结束,我设计了只要蛇头撞到了游戏页面边缘或者撞到了自己的身体,就让游戏结束,代码如下:
function gameOver() {
//撞墙
var headX = +$head.css("left").split("px")[0];
var headY = +$head.css("top").split("px")[0];
if(headX > gameGround.x - 21 || headX < 0 || headY > gameGround.y - 30 || headY < 0) {
return true;
}
//撞自己
for(var i = 0; i < bodyArry.length; i++) {
if(headX == bodyArry[i].css("left").split("px")[0] && headY == bodyArry[i].css("top").split("px")[0]) {
return true;
}
};
return false;
}
要洗结束了,我们就要有所提升,所以写了个alert方法,代码如下;
function myAlert() {
bgm1.pause();
bgm2.pause();
bgm3.pause();
$("#myAlert-bk").show();
$("#myAlert").show();
clearInterval(timer);
overAudio.play();
}
接下来就是eatEgg方法,吃到道具之后就让身体增加一个长度,代码如下:
function eatEgg() {
if($head.css("left") == $egg.css("left") &&
$head.css("top") == $egg.css("top")) {
eatAudio.play();
$egg.removeClass("egg").addClass("snakeBody");
bodyArry.push($egg);
addEgg();
$("#score").html(++score);
if(score == 3) {
clearInterval(timer);
colorRun();
snakeRun(150);
bgm1.pause();
bgm2.play();
} else if(score == 8) {
clearInterval(timer);
clearInterval(colorTimer);
$(".score").css("background-color", "#F5D994");
snakeRun(300);
bgm2.pause();
bgm3.play();
} else if(score == 12) {
clearInterval(timer);
clearInterval(colorTimer);
$(".score").css("background-color", "#C8C6CA");
$(".gameBox").css("background-color", "#AFACB1");
snakeRun(100);
bgm3.pause();
bgm2.play();
}
}
}
3.3 自己动
看了上面的代码,会发现我有很大清理定时器的东西,是因为我用定时器让贪吃蛇自己动起来,如果我们不改变方向,它就会往一个方向移动,直到游戏结束,代码如下:
function snakeRun(speed) {
timer = setInterval(function() {
move();
}, speed);
}
3.4其他乐趣体验
看了3.2的代码我们还发现我设计了其他的方法,判断分数然后进行不一样的界面及声音的操作,我用了不同的bgm(都是拿了超级玛丽的声音)和得分表的颜色变化,来表示得分情况及紧张感,同时进行了贪吃蛇的加速增加难度。(具体可以体验一下游戏,或者看下具体代码。)
3.5手机操作
为了让手机可以直接操作,我设计点击游戏界面中间点到上下左右的地方,进行移动。具体代码如下:
$("#gameBox").bind("touchend", function(evt) {
var touch = evt.originalEvent.changedTouches[0];
var snake = {
x: $("#head").offset().left + step / 2,
y: $("#head").offset().top + step / 2
}
var x = touch.clientX - snake.x;
var y = touch.clientY - snake.y;
if(Math.abs(y) > Math.abs(x)) {
//上下移动
if(y > 0) {
move(40);
} else {
move(38);
}
} else {
//左右移动
if(x > 0) {
move(39);
} else {
move(37);
}
}
})
4、最后效果
结语
本次分享了一个贪吃蛇小游戏的制作,其实主要是整个游戏的逻辑理解,然后和前端知识进行整合。