游戏地址:http://www.zangzhihong.com/flybird/index.html html部分 <!DOCTYPE html> |
|
<!-- This html make by zzh 2017-11-9 --> | |
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> | |
<!-- 未解决问题1,分数显示的逻辑问题。2定时器未完全清除的问题。 --> | |
<!-- 制作该小游戏的过程中更加深刻的理解了定时器的使用(定时器使用后在某些场合会产生定时器叠加,导致速度越来越快,在管道的向左移动中,定时器必须绑定在每个管道上管道才能被正确的创建) | |
,以及单体单例模式的开发,对模块化的概念有了更深的理解,对帧动画的原理有了更加清晰的认识,对高级事件的用法更加熟悉 --> | |
<!-- 后续需要改进的,游戏中场景的自适应宽高并且能让检测碰撞正常检测,对一些小地方的优化 --> | |
<head> | |
<meta charset="utf-8" /> | |
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no,minimal-ui"> | |
<title>小蠢鸟</title> | |
<!--<link rel="icon" href="favicon.png" type="images/bird0.png">--> | |
<link rel="shortcut icon" href="images/bird0.png" type="image/png"> | |
<link rel="stylesheet" href="css/flybird.css" /> | |
</head> | |
<body> | |
<div id="container"><!--游戏场景容器 --> | |
<div class="head"> <!--游戏场景界面的标题 --> | |
<img src="images/head.jpg" /> | |
<span class="jump_bird"></span> | |
</div> | |
<div class="score"></div><!--游戏场分数显示 --> | |
<div class="start"><!--游戏开始按钮 --> | |
<img src="images/start.jpg" /> | |
</div> | |
<div class="slider"><!--游戏持续滑动的滑块 --> | |
<img src="images/slider.jpg" /> | |
<img src="images/slider.jpg" /> | |
</div> | |
<div id="flybird"></div><!--小鸟 --> | |
<div class="pipe"></div><!--管道容器 --> | |
<div class="gameover"><!--游戏结束界面 --> | |
<img src="images/game_over.jpg" /> | |
</div> | |
<div class="message"><!--游戏结束界面显示框 --> | |
<img src="images/message.jpg" /> | |
</div> | |
<div class="best_score"></div><!--最高成绩显示 --> | |
<div class="result"> | |
<img src="images/ok.jpg" /> | |
</div> | |
</div> | |
<audio class='bgm' src="source/game_music.mp3" autoplay="autoplay" loop="loop"></audio><!--游戏主背景音乐 --> | |
<audio class='gameover_bgm' src="source/game_over.mp3" autoplay="autoplay"></audio><!--游戏结束音乐 --> | |
<audio class='up_bgm' src="source/bullet.mp3" autoplay="autoplay"></audio><!--点击小鸟上升的音乐 --> | |
</body> | |
<script type="text/javascript" src="js/flybird.js"></script> | |
</html> |
js部分
//make by zzh 2017-11-9 var Game = { wrap: document.getElementById('container'),//获取游戏舞台
head: document.getElementsByClassName('head')[0],//开始场景标题
start: document.getElementsByClassName('start')[0],//开始按钮
bird: document.getElementById('flybird'),//小鸟
message: document.getElementsByClassName('message')[0],//显示信息
result: document.getElementsByClassName('result')[0],//再玩一次
game_over: document.getElementsByClassName('gameover')[0],//游戏结束显示的图标
bgm: document.getElementsByClassName('bgm')[0],//背景音乐
gameover_bgm: document.getElementsByClassName('gameover_bgm')[0],//结束背景音乐
up_bgm: document.getElementsByClassName('up_bgm')[0],//小鸟向上的背景音乐
score_tip: document.getElementsByClassName('score')[0],//分数显示模块
bestScore: document.getElementsByClassName('best_score')[0],//最高成绩显示模块
speed: 0,//初始速度
score_index: 0,//初始化分数
// max_score: 0,
maxspeed: 10,//最大速度
downtime: null,//定时器的初始状态
uptime: null,
pipetime: null,
pipecreatetime: null,
init: function () {//游戏场景初始化
this.gameover_bgm.pause();
this.up_bgm.pause();
this.bgm.pause()
var _this = this;
this.result.onclick = function () {
Game.playagain(); } this.start.onclick = function () {//click start button begin game,开始游戏
_this.bgm.play()
Game.score();
_this.score_tip.style.display = "block";
_this.head.style.display = 'none';
_this.start.style.display = 'none';
_this.bird.style.top = '200px';
_this.bird.className = 'bird';
Game.pipecreatetime = setInterval(Game.pipe, 3000);
document.onclick = function () {
_this.jump(); }
} }, down: function () {//bird fly to down
Game.speed += 1;
Game.bird.className = 'flybirddown';
if (Game.speed >= Game.maxspeed) {
Game.speed = Game.maxspeed;
} if (Game.bird.offsetTop >= 500 || Game.bird.offsetTop <= 0) {
Game.gameover() } Game.bird.style.top = Game.bird.offsetTop + Game.speed + 'px'; }, up: function () { //bird fly to up
Game.speed -=1;
Game.bird.className = 'flybirdup';
Game.up_bgm.play()
if (Game.speed <= 0) {
Game.speed = 0;
clearInterval(Game.uptime);
Game.downtime = setInterval(Game.down, 30);
}
Game.bird.style.top = Game.bird.offsetTop - Game.speed + 'px'; }, jump: function () {//bird jump methods
Game.speed = Game.maxspeed;
clearInterval(Game.uptime);
clearInterval(Game.downtime);
Game.uptime = setInterval(Game.up, 30);
}, rand: function (min, max) { //input mini num and max mun create a random
return Math.floor(Math.random() * (max - min) + min); }, pipe: function () {//create pipe
var in_pipe = document.getElementsByClassName('pipe')[0];
var sm_pipe = document.createElement('div');
sm_pipe.className = 'sm_pipe';
in_pipe.appendChild(sm_pipe);
var topheight = Game.rand(80, 300);
var bottomheight = 530 - 150 - topheight;
if (Game.score_index >= 1000) {
bottomheight = 530 - 125 - topheight;
} else if (Game.score_index >= 2000) {
bottomheight = 530 - 100 - topheight;
} else if (Game.score_index >= 2000) {
bottomheight = 530 - 75 - topheight;
} else if (Game.score_index >= 3000) {
bottomheight = 530 - 50 - topheight;
}
sm_pipe.innerHTML = '<div class="top_pipe"><div style="height:' + topheight + 'px"></div></div><div class="bottom_pipe"><div style="height:' + bottomheight + 'px"></div></div>'
var maxwidth = Game.wrap.offsetWidth;
sm_pipe.style.left = maxwidth + 'px';
// sm_pipe.pipetime = null;
clearInterval(sm_pipe.pipetime);
sm_pipe.pipetime = setInterval(function () {
maxwidth -= 3;
sm_pipe.style.left = maxwidth + 'px';
Game.collision()
if (maxwidth <= -60) {
clearInterval(sm_pipe.pipetime);
in_pipe.removeChild(sm_pipe);
} if (sm_pipe.offsetLeft <= 30) {
Game.score(); } }, 30)
}, collision: function () {//用小鸟去和生成的管道循环判断是否碰撞
var getallsm_pipe = document.getElementsByClassName('sm_pipe')
for (var i = 0; i < getallsm_pipe.length; i++) {
var top_pipe = getallsm_pipe[i].getElementsByClassName('top_pipe')[0];
var bottom_pipe = getallsm_pipe[i].getElementsByClassName('bottom_pipe')[0];
Game.knock(top_pipe, getallsm_pipe[i]);
Game.knock(bottom_pipe, getallsm_pipe[i]);
} }, score: function () {//分数统计 Game.score_tip.innerHTML = '分数:' + Game.score_index; Game.score_index++;
}, knock: function (obj1, obj2) {//碰撞检测
var l1 = Game.bird.offsetLeft;//小鸟左边距离边框的距离
var r1 = l1 + Game.bird.offsetWidth;//小鸟左边距离边框的距离加上自己的宽度
var t1 = Game.bird.offsetTop;//小鸟距离上边框的高度
var b1 = t1 + Game.bird.offsetHeight//小鸟距离上边框的高度加上自身的高度
var l2 = obj2.offsetLeft;//管道距离左边的距离
var r2 = l2 + obj2.offsetWidth;//管道距离左边的距离加上自身的宽度
var t2 = obj1.offsetTop;//管道距离上边的距离
var b2 = t2 + obj1.offsetHeight;//管道距离上边的距离加上管道自身高度的距离
//判断条件 if (r1 > l2 && l1 < r2 && b1 > t2 && t1 < b2) {
Game.gameover() } }, gameover: function () {//游戏结束
Game.gameover_bgm.play();
document.onclick=null;
Game.bgm.pause();
clearInterval(Game.downtime)
clearInterval(Game.uptime)
clearInterval(Game.pipecreatetime)
clearInterval(Game.pipetime)
// clearInterval(sm_pipe.pipetime);
Game.message.style.display = "block";
Game.head.style.display = "none";
Game.result.style.display = "block";
Game.game_over.style.display = "block";
Game.bird.style.top = '503px';
Game.bestScore.style.display='block';
if(localStorage.max_score){ if(Game.score_index>= localStorage.max_score) { localStorage.max_score= Game.score_index Game.bestScore.innerHTML= localStorage.max_score
}else{ Game.bestScore.innerHTML= localStorage.max_score } }else{ localStorage.max_score=0; }
}, playagain: function () {//再玩一次
Game.bgm.play();
Game.score_index = 0;
Game.score();
Game.bestScore.style.display='none';
Game.head.style.display = 'none';
Game.start.style.display = 'none';
Game.bird.style.top = '200px';
Game.bird.className = 'bird';
Game.message.style.display = "none";
Game.head.style.display = "none";
Game.result.style.display = "none";
Game.game_over.style.display = "none";
Game.pipecreatetime = setInterval(Game.pipe, 3000);
document.onclick = function () {
Game.jump(); } } } Game.init();
CSS部分
html,body{
margin:0;
padding:0;
100%;
height:100%;
}
#container {
position: relative;
top:0;
left:0;
overflow:hidden;
343px;
height: 600px;
background:url('../images/bg.jpg');
background-size:100% 100%;
background-repeat:repeat;
margin:0 auto;
}
.head {
position: absolute;
top: 100px;
left: 50px;
animation: title 1s infinite alternate;
}
.jump_bird {
position: absolute;
top: 8px;
left: 190px;
40px;
height:26px;
animation: bird .4s infinite alternate;
}
.start{
position:absolute;
top:290px;
left:120px;
}
.slider{
position:absolute;
690px;
top:530px;
animation:slider 3s linear infinite;
}
.slider img{
float: left;
}
#flybird{
position:absolute;
top:200px;
left:50px;
}
.bird {
40px;
height: 30px;
animation: bird .4s infinite alternate;
}
.flybirddown {
40px;
height: 30px;
animation: birddown .4s infinite alternate;
}
.flybirdup {
40px;
height: 30px;
animation: birdup .4s infinite alternate;
}
@keyframes slider{
0%{
left:0;
}
100%{
left:-343px;
}
}
@keyframes title{
0% {
top: 100px;
}
100% {
top: 120px;
}
}
@keyframes bird {
0% {
background: url('../images/bird0.png');
}
100% {
background: url('../images/bird1.png')
}
}
@keyframes birddown{
0% {
background: url('../images/down_bird0.png');
}
100% {
background: url('../images/down_bird1.png')
}
}
@keyframes birdup {
0% {
background: url('../images/up_bird0.png');
}
100% {
background: url('../images/up_bird1.png')
}
}
.sm_pipe{
position:absolute;
top:0;
62px;
height:530px;
}
.top_pipe {
100%;
position: absolute;
top: 0;
background: url(../images/up_mod.png);
}
.top_pipe div {
background: url(../images/up_pipe.png) 0 bottom no-repeat;
}
.bottom_pipe {
100%;
position: absolute;
bottom: 0;
background: url(../images/down_mod.png);
}
.bottom_pipe div {
background: url(../images/down_pipe.png) 0 top no-repeat;
}
.gameover {
display: none;
position: absolute;
top: 103px;
left: 46px;
animation:over 1s linear;
}
.message{
display:none;
position:absolute;
top:165px;
left:25px;
}
.result {
display: none;
position: absolute;
top: 338px;
left: 105px;
animation: ok 1s linear;
}
.score {
display: none;
position: absolute;
top: 80px;
left: 120px;
100px;
height:50px;
z-index:10;
color:#0094ff;
font-size:20px;
font-weight:bold;
text-align:center;
}
.best_score{
display: none;
position: absolute;
top: 257px;
left: 202px;
100px;
text-align: center;
font-size: 20px;
color: red;
font-weight: bold;
}
@keyframes over{
0%{
top:-10px;
}
100%{
top:103px;
}
}
@keyframes ok{
0% {
left: 0px;
}
100% {
left: 105px;
}
}