吃豆人小游戏
今天练习了一下JS,写了一个吃豆人的小demo
Html以及CSS部分
首先定义一个div
,用来存放吃豆人的一些元素,我们给他加一个id="game"
,然后我们在这div里面添加我们要写的标签。
<div id="game"><div class="wall"></div><div class="wall"></div><div class="wall"></div>
</div>
在这里我们向game
里面添加了3堵墙,然后再来编写一下css
代码:
#game {position: absolute;left: 50%;top: 50%;font-size: 0;transform: translateX(-50%) translateY(-50%);
}
.wall {display: inline-block;width: 50px;height: 50px;background-color: darkblue;border: 2px solid lightsteelblue;box-sizing: border-box;
}
css
部分用了absolute
绝对定位,向浏览器左侧以及顶部隔离50%,然后通过transform
属性使其自身反方向移动50%,就可以不用通过设置game
的宽高,然后再用margin-left
和margin-top
的方式来将#game
居中。
浏览器效果
接着我们用一个br
标签换行,来写第二行和第三行:
<div id="game"><div class="wall"></div><div class="wall"></div><div class="wall"></div><div class="wall"></div><div class="wall"></div></br><div class="wall"></div><div class="coin"></div><div class="pacman"></div><div class="coin"></div><div class="wall"></div></br><div class="wall"></div><div class="wall"></div><div class="wall"></div><div class="wall"></div><div class="wall"></div>
</div>
把金币和吃豆人的CSS
补上去
/* 金币 */
.coin {display: inline-block;width: 50px;height: 50px;background-image: url("./../images/coin.png");background-position: center center;background-repeat: no-repeat;
}
/* 背景 */
.bg {display: inline-block;width: 50px;height: 50px;background-color: #000;
}
/* 吃豆人 */
.pacman {display: inline-block;width: 50px;height: 50px;background-image: url("./../images/pacman.png");
}
发现重复的代码有很多,可以简化一下,将#game
下面的所有的div
标签都设置为行块元素,再设置宽高:
#game>div {display: inline-block;width: 50px;height: 50px;
}.wall {background-color: darkblue;border: 2px solid lightsteelblue;box-sizing: border-box;
}.coin {background-image: url("./../images/coin.png");background-position: center center;background-repeat: no-repeat;
}.bg {background-color: #000;
}.pacman {background-image: url("./../images/pacman.png");
}
现在,我们在浏览器里面看一下效果:
这样,我们最简单的一个吃豆人小地图就做好了,如果需要更多的墙以及金币的话,都可以通过添加div
来实现,但是这种方法很不便捷,并且也不好阅读,下面我们就可以通过js来动态的创建我们的吃豆人地图。
JS部分
那么如何通过JS来创建吃豆人中元素呢,我们知道,吃豆人中有墙壁,吃豆人,金币以及怪物。比方说,我们通过数组的方式来存放这些元素,1
就是墙壁,2
就是金币,3
当作空白处的背景,4
就是吃豆人。(这里我们不涉及到怪物monster)
首先我们定义一个数组:
var game = [1,2,3,4];
然后我们通过for
循环将数组里面的内容渲染出来:
var html = "";var gameMap = document.getElementById("game");for(var i = 0; i < game.length; i++){if(game[i] === 1){html += "<div class='wall'></div>";}else if(game[i] === 2){html += "<div class='coin'></div>";}else if(game[i] === 3){html += "<div class='bg'></div>";}else if(game[i] === 4){html += "<div class='pacman'></div>";}}gameMap.innerHTML = html;
在上面的代码中,首先定义了一个空的字符串,然后获取到game
元素,通过for
循环和if
判断将对应的元素渲染到页面中。
看一下浏览器的效果:
总所周知,数组里面可以存放任何元素,那么我们可以往数组里面加数组,用一个二维数组的形式,将吃豆人地图弄出来。然后再用for
循环将其渲染。
var game = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],[1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1],[1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1],[1, 2, 1, 1, 2, 2, 2, 1, 1, 2, 1],[1, 2, 2, 2, 2, 4, 2, 2, 2, 2, 1],[1, 3, 1, 2, 1, 2, 1, 2, 1, 3, 1],[1, 3, 1, 2, 1, 2, 1, 2, 1, 3, 1],[1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1],[1, 2, 1, 1, 2, 2, 2, 1, 1, 2, 1],[1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1],[1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1],[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];
var html = "";
var gameMap = document.getElementById("game");for (var i = 0; i < game.length; i++) {for (var j = 0; j < game[i].length; j++) {if (game[i][j] === 1) {html += "<div class='wall'></div>";} else if (game[i][j] === 2) {html += "<div class='coin'></div>";} else if (game[i][j] === 3) {html += "<div class='bg'></div>";} else if (game[i][j] === 4) {html += "<div class='pacman'></div>";}}html += "</br>";}
gameMap.innerHTML = html;
由于我们吃豆人空白背景定义的是黑色,所以我们也将body
背景设置为黑色,这样看起来就不突兀。
然后我们在浏览器里面看一下效果:
接下来我们就要实现吃豆人上下左右的移动以及吃掉豆子。
首先我们要弄清楚吃豆人该如何移动,比方说现在吃豆人的位置是在第5行,第6列,如果向右边移动那么就是第5行,第7列,向左边移动就是第5行,第5列。以此类推,左右移动就是行不变,列改变;
上下移动就是列不变,行改变。根据这个思路,我们来写一下代码:
首先要将当前吃豆人的位置获取到
var pacman = {x: 4,y: 5,dir:"pacman-right" // 吃豆人移动的状态
}
然后我们来创建键盘事件 需要注意的是我们在改变吃豆人位置的时候又会将页面重新渲染,所以我们可以将上面利用for
循环渲染的页面的代码写成一个函数
将
for
循环这段代码写成函数
function draw(){var html = "";var gameMap = document.getElementById("game");for(var i = 0; i < game.length; i++){if(game[i] === 1){c html += "<div class='wall'></div>";}else if(game[i] === 2){html += "<div class='coin'></div>";}else if(game[i] === 3){html += "<div class='bg'></div>";}else if(game[i] === 4){html += "<div class='pacman'></div>";}}gameMap.innerHTML = html;
}
draw();
键盘点击事件
document.onkeydown = function (event) {if (event.code === "ArrowRight") {pacman.dir = "pacman-right"; // 改变吃豆人行走的状态if (game[pacman.x][pacman.y + 1] !== 1) { // 判断边界值game[pacman.x][pacman.y] = 3;pacman.y += 1;game[pacman.x][pacman.y] = 4;draw();}} else if (event.code === "ArrowLeft") {pacman.dir = "pacman-left";if (game[pacman.x][pacman.y - 1] !== 1) {game[pacman.x][pacman.y] = 3;pacman.y -= 1;game[pacman.x][pacman.y] = 4;draw();}} else if (event.code === "ArrowUp") {if (game[pacman.x - 1][pacman.y] !== 1) {pacman.dir = "pacman-up";game[pacman.x][pacman.y] = 3;pacman.x -= 1;game[pacman.x][pacman.y] = 4;draw();}} else if (event.code === "ArrowDown") {if (game[pacman.x + 1][pacman.y] !== 1) {pacman.dir = "pacman-down";game[pacman.x][pacman.y] = 3;pacman.x += 1;game[pacman.x][pacman.y] = 4;draw();}}
}
吃豆人的移动加入了边界值的判断,如果说吃豆人的周围都是强的话,是不能再移动的,如果不加这个边界值,那么吃豆人就会超出墙壁,十分无敌。
在移动时,我们在吃豆人的div
里面添加了"pacman-right"
然后通过改变这个CSS属性去改变吃豆人移动时的状态,相应的,我们也要在CSS里面添加对应的代码:
.pacman-left {background-image: url("./../images/pacman-left.png");
}.pacman-up {background-image: url("./../images/pacman-up.png");
}.pacman-down {background-image: url("./../images/pacman-down.png");
}
不用写pacman-right
是因为吃豆人默认就是朝向右边。
到这里,我们的吃豆人简单小游戏就制作完成了,我们也可以再添加一些其他的东西,比如说monster幽灵,通过一个计时器来回移动形成对吃豆人的阻挡,也可以通过一定的算法让幽灵去追踪吃豆人。