今天练习了一下JS,写了一个吃豆人的小demo
首先定义一个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来创建吃豆人中元素呢,我们知道,吃豆人中有墙壁,吃豆人,金币以及怪物。比方说,我们通过数组的方式来存放这些元素,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 += "";
}else if(game[i] === 2){
html += "";
}else if(game[i] === 3){
html += "";
}else if(game[i] === 4){
html += "";
}
}
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 += "";
} else if (game[i][j] === 2) {
html += "";
} else if (game[i][j] === 3) {
html += "";
} else if (game[i][j] === 4) {
html += "";
}
}
html += "";
}
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 += "";
}else if(game[i] === 2){
html += "";
}else if(game[i] === 3){
html += "";
}else if(game[i] === 4){
html += "";
}
}
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幽灵,通过一个计时器来回移动形成对吃豆人的阻挡,也可以通过一定的算法让幽灵去追踪吃豆人。