用原生js+html写一个像素鸟游戏

释放双眼,带上耳机,听听看~!

看一下全部的代码把:
HTML代码
<!DOCTYPE html>
<html lang=”en”>

<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<meta http-equiv=”X-UA-Compatible” content=”ie=edge”>
<title>像素鸟</title>
<link rel=”stylesheet” href=”index.css”>
</head>

<body>
<!– 这是游戏的容器 –>
<div id=”game”>
<!– 天空容器 –>
<div class=”sky”></div>
<!– 大地容器 –>
<div class=”land”></div>
<!– 小鸟容器 –>
<div class=”bird”></div>
<!– 柱子的容器,后期自动生成的,这里只是为了调节样式 –>
<!– <div class=”pipeup”></div>
<div class=”pipedown”></div> –>
</div>
<p class=”msg”>回车键开始/暂停,空格键跳跃</p>
<script src=”./index.js”></script>
</body>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
CSS代码
#game {
width: 800px;
height: 600px;
border: 2px solid;
margin: 0 auto;
position: relative;
overflow: hidden;
}

#game .sky {
width: 1600px;
height: 600px;
background: url(‘./img/sky.png’);
position: absolute;
left: 0;
top: 0;
}

#game .land {
width: 1600px;
height: 112px;
background: url(‘./img/land.png’);
position: absolute;
left: 0;
bottom: 0;
}

#game .bird {
width: 33px;
height: 26px;
background: url(‘./img/bird.png’);
position: absolute;
left: 200px;
top: 150px;
z-index: 1;
background-position: -8px -10px;
}

#game .pipeup {
background: url(“img/pipeDown.png”) no-repeat left bottom;
width: 52px;
height: 200px;
position: absolute;
top: 0;
right: 0;
}

#game .pipedown {
background: url(“img/pipeUp.png”) no-repeat;
width: 52px;
height: 200px;
position: absolute;
bottom: 112px;
right: 0;
}

.msg {
text-align: center;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
JS代码

let skyBg, landBg, bird, game, pipes;

// 考虑到计时器的使用频率非常的高,所以专门封装一个函数
// 该函数返回一个对象,对象包含两个属性
// start:创建一个计时器 stop:停止计时器
// duration:计时器每隔多少毫秒执行
// callback:每隔duration毫秒执行callback函数
// thisObj:为了得到正确的this指向
let getTimer = function (duration, thisObj, callback) {
var timer = null;
return {
start: function () {
if (!timer) {
timer = setInterval(function () {
callback.bind(thisObj)();
}, duration);
}
},
stop: function () {
if (timer) {
clearInterval(timer);
timer = null;
}
}
};
}

// 系统对象,统一管理其他对象的开始和结束
game = {
paused : true, // 当前游戏是否暂停
isGmaeOver : false, // 当前游戏是否结束
dom : document.querySelector(‘#game’),
start : function(){
skyBg.timer.start();
landBg.timer.start();
bird.wingTimer.start();
bird.dropTimer.start();
pipes.produceTimer.start();
pipes.moveTimer.start();
},
stop : function(){
skyBg.timer.stop();
landBg.timer.stop();
bird.wingTimer.stop();
bird.dropTimer.stop();
pipes.produceTimer.stop();
pipes.moveTimer.stop();
},
// 该方法用于判断游戏是否结束
gameOver : function(){
// 游戏有两种情况都会导致游戏结束:1. 小鸟落地 2. 小鸟碰撞柱子
// 1. 小鸟落地
if(bird.top === 462){
console.log(‘游戏结束’);

this.isGmaeOver = true;
this.stop();
}
// 2. 小鸟是否碰撞到柱子(需要检测碰撞)
// 小鸟中心点
let bx = bird.left + (bird.width/2);
let by = bird.top + (bird.height/2);
// 柱子中心点
for(let i=0;i<pipes.all.length;i++){
let p = pipes.all[i]; // 当前的柱子
// 获取当前柱子的中心点
let px = p.left + (p.width/2);
let py = p.top + (p.height/2);
// 判断是否碰撞
if(Math.abs(bx – px) < (p.width + bird.width) / 2 &&
Math.abs(by – py) < (p.height + bird.height) / 2){
console.log(‘游戏结束’);
this.isGmaeOver = true;
this.stop();
}

}
}
}

// 天空对象
skyBg = {
left: 0,
dom: document.querySelector(‘#game .sky’),
// 该方法用于重新更新天空的 left 值
show: function () {
this.dom.style.left = this.left + ‘px’
}
}
skyBg.timer = getTimer(30, skyBg, function () {
this.left -= 1;
if (this.left === -800) {
this.left = 0;
}
this.show();
})

// 大地对象
landBg = {
left: 0,
dom: document.querySelector(‘#game .land’),
show() {
this.dom.style.left = this.left + ‘px’
}
}
landBg.timer = getTimer(30, landBg, function () {
this.left -= 2
if (this.left === -800) {
this.left = 0;
}
this.show();
})

// 小鸟对象
bird = {
width : 33,
height : 26,
top : 150,
left : 200,
dom : document.querySelector(‘#game .bird’),
wingIndex : 0, // 该属性用于记录当前小鸟的背景图片
speed : 0, // 小鸟往下面掉的速度
a : 0.005, // 加速度
// 显示小鸟的方法:统一在 show 方法中显示小鸟的最终状态
show : function(){
// 根据图片的索引,来设置当前小鸟背景图的位置
if(this.wingIndex === 0){
this.dom.style.backgroundPosition = ‘-8px -10px’;
} else if(this.wingIndex === 1){
this.dom.style.backgroundPosition = ‘-60px -10px’;
} else {
this.dom.style.backgroundPosition = ‘-113px -10px’;
}
// 设置小鸟的 top 值
this.dom.style.top = this.top + ‘px’;
},
// 设置小鸟的 top 值
setTop(newTop){
if(newTop < 0){
newTop = 0;
}
if(newTop > 462){
newTop = 462;
}
this.top = newTop;
},
jump(){
this.speed = -0.5;
}
}
// 让小鸟不停的扇动翅膀的计时器
bird.wingTimer = getTimer(100,bird,function(){
// 这里面主要要做的事儿:修改 wingIndex,然后调用 show
this.wingIndex = (this.wingIndex + 1) % 3;
this.show();
});
bird.dropTimer = getTimer(16,bird,function(){
// 主要要做的事儿:改变高度,然后调用 setTop 方法以及 show 方法
// 小鸟做的是匀加速运动
// s = vt + 1/2 * a * t * t
// 如何获取匀加速的末速度:v = v0 + at
let s = this.speed * 16 + 0.5 * this.a * 16 * 16;
this.speed = this.speed + this.a * 16;
this.setTop(this.top + s);
this.show();
});

// 上下的管道
pipes = {
width: 52,
getRandom : function(min,max){
return Math.floor(Math.random() * (max – min) + min);
},
all : [], // 用于存放所有的柱子
// 创建柱子的方法
createPipe() {
let minHeight = 60, // 柱子最小的高度
gap = 150; // 中间的间隙
maxHeight = 488 – gap – minHeight;
// 接下来确定一组柱子的高度
let h1 = this.getRandom(minHeight,maxHeight),
h2 = 488 – gap – h1;
// 接下来根据这两个高度来创建柱子
// 上面的柱子
let div1 = document.createElement(“div”);
div1.className = “pipeup”;
div1.style.height = h1 + “px”;
div1.style.left = “800px”;
game.dom.appendChild(div1);
this.all.push({
dom : div1,
height : h1,
width : this.width,
top : 0,
left : 800
});
// 下面的柱子
let div2 = document.createElement(“div”);
div2.className = “pipedown”;
div2.style.height = h2 + “px”;
div2.style.left = “800px”;
game.dom.appendChild(div2);
this.all.push({
dom : div2,
height : h2,
width : this.width,
top : h1 + gap,
left : 800
});
},
}
// 创建柱子
pipes.produceTimer = getTimer(2500,pipes,function(){
this.createPipe();
})

// 移动柱子
pipes.moveTimer = getTimer(30,pipes,function(){
// 因为要移动所有的柱子 && 对游戏进行积分
for(let i=0;i<this.all.length;i++){
let p = this.all[i]; // 得到当前的柱子
p.left -= 2;
if(p.left < -p.width){
p.dom.remove();
this.all.splice(i,1);
i–;
} else {
p.dom.style.left = p.left + ‘px’;
}

//判断柱子是否过了小鸟,若过了则说明小鸟过了一根柱子
if(p.left<=(bird.left-pipes.width)){
console.log(“+1”);

}

}

game.gameOver(); // 每次柱子移动后,都需要判断游戏是否结束
});

document.documentElement.onkeydown = function(e){
if(e.key === ‘ ‘){
bird.jump();
}
if(e.key === ‘Enter’){
// 按下回车键后,有三种状态(游戏运行中,游戏暂停中,游戏已结束)
if(game.isGmaeOver){
location.reload();
}
if(game.paused){
game.start();
game.paused = !game.paused
} else {
game.stop();
game.paused = !game.paused
}

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
注:鸟的下落速度可能比较快,(可通过修改下图位置的参数更改)有些其它功能还没实现,可自行添加

人已赞赏
首页

Linux 用户名、主机添加背景色

2019-12-18 23:54:22

首页

基于Bootstrap的网页“音乐播放器博物馆” --- 处女作!

2019-12-18 23:56:56

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索