<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>飞翔的小鸟</title> <style type="text/css"> @keyframes move{ 0% {top: 100px;} 50%{top: 120px;} 100%{top: 100px;} } @keyframes sliderMove{ 0%{left:0;} 100%{left: -343px;} } @keyframes birdMove{ 0%{background: url(img/bird0.png);} 100%{background: url(img/bird1.png);} } *{margin: 0; padding: 0; list-style: none;} #fbWrap{ 343px; height: 480px; background: url(img/bg.jpg); margin: 0 auto; position: relative; overflow: hidden;} #sliderWrap{position: absolute; top: 422px; 99999px; animation: sliderMove 4s linear infinite;} #sliderWrap img{float: left;} #head{position: absolute; top: 100px; left: 55px; animation: move 2s ease-in infinite;} #head span{position: absolute; left: 200px; background: url(img/bird0.png); height: 26px; 40px; top: 20px; animation: birdMove 0.5s linear infinite;} #scoring{position: absolute; top: 50px; text-align: center; 100%; z-index: 2;} #pipeWrap{height: 100%;} .pipe{ 62px; height: 88%; position: absolute;} .top_pipe{position: absolute; top: 0; background: url(img/up_mod.png); 62px;} .top_pipe div{background: url(img/up_pipe.png) 0 bottom no-repeat;} .bottom_pipe{background: url(img/down_mod.png); 62px; position: absolute; bottom: 0;} .bottom_pipe div{background: url(img/down_pipe.png) 0 top no-repeat;} #flappyBird{position: absolute; left: 50px; top: 200px; display: none;} #menu{position: absolute; left: 59px; top: 300px; text-align: center;} #start{height: 29px; 85px; float: left; background: url(img/start.jpg);} #submit{height: 29px; 85px; float: left; margin-left: 30px; background: url(img/submit.jpg);} #message{ 269px; height: 135px; background: url(img/message.jpg); position: absolute; left: 34px; top: 500px; font-size: 30px; font-weight: bold; -webkit-transition:all 1s cubic-bezier(0.2,-0.5,0.8,1.5);} #endScoring{position: absolute; right: 25px; top: 30px;} #oldScoring{position: absolute; right: 25px; top: 80px;} #gameover{position: absolute; top: -50px; left: 65px; -webkit-transition:all 1s cubic-bezier(0.2,-0.5,0.8,1.5);} #ok{position: absolute; top: 320px; left:-120px; -webkit-transition:all 1s cubic-bezier(0.2,-0.5,0.8,1.5);} </style> </head> <body> <div id="fbWrap"> <div id="sliderWrap"> <img src="img/slider.jpg" alt=""> <img src="img/slider.jpg" alt=""> </div> <div id="head"><img src="img/head.jpg" alt=""><span></span></div> <div id="scoring"><img src="img/0.jpg" alt=""></div> <ul id="pipeWrap"> <!-- <li class="pipe" style="left:200px;"> <div class="top_pipe"> <div style="height:120px;"></div> </div> <div class="bottom_pipe"> <div style="height:180px;"></div> </div> </li> --> </ul> <div id="flappyBird" class="up"><img src="img/bird0.png" alt=""></div> <div id="menu"> <div id="start"></div> <div id="submit"></div> </div> <div id="message"> <div id="endScoring">121</div> <div id="oldScoring">12</div> </div> <div id="ok"><img src="img/ok.jpg" alt=""></div> <div id="gameover"><img src="img/game_over.jpg" alt=""></div> <audio id="gameMusic" loop src="音频/game_music.mp3"></audio> <audio id="bullet" src="音频/bullet.mp3"></audio> <audio id="gameOverMusic" src="音频/game_over.mp3"></audio> </div> </body> </html> <script type="text/javascript"> var fbWrap=document.getElementById("fbWrap"); var oHead=document.getElementById("head"); var scoring=document.getElementById("scoring"); var pipeWrap=document.getElementById("pipeWrap"); var flappyBird=document.getElementById("flappyBird"); var flappyBirdImg=flappyBird.children[0]; var menu=document.getElementById("menu"); var start=document.getElementById("start"); var message=document.getElementById("message"); var endScoring=document.getElementById("endScoring"); var oldScoring=document.getElementById("oldScoring"); var gameover=document.getElementById("gameover"); var gameMusic=document.getElementById("gameMusic"); var bullet=document.getElementById("bullet"); var gameOverMusic=document.getElementById("gameOverMusic"); var aScoringImg=["img/0.jpg","img/1.jpg","img/2.jpg","img/3.jpg","img/4.jpg","img/5.jpg","img/6.jpg","img/7.jpg","img/8.jpg","img/9.jpg"]; var downTimer=null;//小鸟下落定时器 var upTimer=null;//小鸟飞起定时器 var crashTestTimer=null;//碰撞检测定时器 var speedupTimer=null;//切换小鸟图片定时器 var createPipeTimer = null;//创建管道 var speed=0;//初始速度 var maxSpeed=8;//最大速度 var gameIsOver=false;//假设游戏结束为假 var scoringNumber=0;//分数 var arrImg = [];//分数图片数组 // 进入游戏就把图片预加载一下 loadImg(); // 重置 ok.onclick = function () { // 点击ok重新加载当前文档 location.reload(); //重新加载当前文件的方法 } // 点击开始按钮,游戏开始 start.onclick = function (ev) { // 将开始菜单上没用的部分隐藏掉 oHead.style.display = 'none'; menu.style.display = 'none'; // 打开游戏音乐 gameMusic.play(); // 阻止冒泡事件 // 不同版本下的事件对象不同,先做下兼容 var oEvent = ev || window.event; oEvent.cancelBubble = true; // 显示小鸟 flappyBird.style.display = 'block'; // 如果不点击屏幕,那小鸟下落摔到地上 downTimer = setInterval(down,30); // 如果点击屏幕,调用fnTouch document.addEventListener('click', fnTouch, false); // 进行碰撞检测 crashTestTimer = setInterval(function () { // 先获取屏幕上所有的管道 var aLi = pipeWrap.getElementsByTagName('li'); // 遍历所有的li for (var i=0; i<aLi.length; i++) { // 每个li中有两根管道,需要分别检测两根管道 crashTest(aLi[i].children[0]); crashTest(aLi[i].children[1]); } // 边缘检测 rangeTest(); },30); //生成管道 createPipeTimer = setInterval(createPipe,3000); // 阻止默认行为 return false; } // 碰撞检测函数 function crashTest(obj){ var l1=flappyBird.offsetLeft; var r1=l1+flappyBird.offsetWidth; var t1=flappyBird.offsetTop; var b1=t1+flappyBird.offsetHeight; console.log('offsetLeft'+obj.offsetLeft); console.log('offsetParent'+obj.offsetParent.offsetLeft); //obj.offsetLeft //obj是上管道或者下管道 //obj.offsetLeft代表的上下管道距离oLi的left值,所以为0 //得不到我们想要获取的值,所以我们写成obj.offsetParent.offsetLeft //obj.offsetParent表示 //找到 var l2=obj.offsetParent.offsetLeft; var r2=l2+obj.offsetWidth; var t2=obj.offsetTop; var b2=t2+obj.offsetHeight; if (r1>l2&&l1<r2&&b1>t2&&t1<b2){ fnGameOver(); } } //边缘检测 function rangeTest() { var t1 = flappyBird.offsetTop; var b1 = t1 + flappyBird.offsetHeight; if(t1 <= 0 || t1 >= 392){ //如果小鸟掉在地上或者超出天花板 fnGameOver(); } } //游戏结束 function fnGameOver(){ //游戏结束关闭所以定时器 clearInterval(upTimer); clearInterval(downTimer); clearInterval(crashTestTimer); clearInterval(speedupTimer); clearInterval(createPipeTimer); //停止游戏音乐 gameMusic.pause(); //打开游戏结束音乐 if(!gameIsOver){ gameOverMusic.play(); } //gameover中的各种菜单和按钮出现 gameover.style.top = '120px'; message.style.top = '180px'; ok.style.left = '118px'; //小鸟落下 gameoverDown(); //显示分数 endScoring.innerHTML = scoringNumber; //记录最佳成绩 //本地存储,我们选择localstorage存储 //首先先从本地读出历史最好成绩 //将best跟本次分数比较,如果本次分数高,更新localstorage存储中的最好成绩;如果本次分数低,不做更新 if(window.localStorage.getItem('scoring') < scoringNumber){ //将新的最好成绩存入 window.localStorage.setItem('scoring',scoringNumber); //在bset的地方显示最好的成绩 oldScoring.innerHTML = window.localStorage.getItem('scoring'); } //将gameisover置为true gameIsOver = true; } //生成管道:隔一定时间间隔生成管道,生成的管道移动 function createPipe(){ //生成管道,创建元素 var oLi = document.createElement('li'); oLi.className = 'pipe'; var bAddScoring = true;//记录这根管道是否被计算过 //管道生成后默认在屏幕的最左侧 //我们让管道向右移动一个屏幕的宽度,也就是maxWigth //然后让maxWidth递减,并将maxWidth的值赋给管道的.left,实现移动 var maxWidth = fbWrap.offsetWidth; oLi.style.left = maxWidth + 'px'; //管道的长度随机生成 var topHeight = rand(52,250); var bottomHeight = 300-topHeight; //向oli添加代码 oLi.innerHTML = "<div class='top_pipe'>"+ "<div style='height:"+topHeight+"px;'></div>"+ "</div>"+ "<div class='bottom_pipe'>"+ "<div style='height:"+bottomHeight+"px;'></div>"+ "</div>" //将生成的管道追加到父级 pipeWrap.appendChild(oLi); //管道移动 oLi.leftTimer = setInterval(function(){ maxWidth -= 2; //管道移动过程中,gameover,需要清除.leftTimer定时器 if(gameIsOver){ clearInterval(oLi.leftTimer); return; } //管道移动出屏幕,需要把管道移除 if(maxWidth < -oLi.offsetWidth){ clearInterval(oLi.leftTimer); pipeWrap.removeChild(oLi); } //小鸟顺利的从管道通过,也就是管道顺利的移动到了屏幕左侧附近 //小鸟顺利通过管道后需要计算分数,加分 //如果不用bAddScoring记录这根管子是否计算过 //那么当管道的maxWidth<25之后,每次走到这个判断条件都会进行加分 if(bAddScoring && maxWidth<=25){ scoringNumber++; //计算分数 fnScoring(); bAddScoring = false; } oLi.style.left = maxWidth + 'px'; },30); } //计算分数的函数 function fnScoring(){ //先把原来图片清除掉 scoring.innerHTML = ''; //scoringNumber是一个数,比如13,我们要是想取出1和3,把scoringNumber //转化成一个字符串更容易操作,只需遍历字符串,取出每个字符即可 //数字和字符串先加,得到字符串,+空字符串,就把ScoringNumber转化成了字符串 var sScoring = scoringNumber+''; for(var i = 0;i < sScoring.length; i++){ var oImg = document.createElement('img'); oImg.src = arrImg[sScoring.charAt(i)].src; scoring.appendChild(oImg); } } //生成随机 function rand(min,max){ return parseInt(min+Math.random()*(max-min)); } // 小鸟的行为 // 上升,下落,屏幕被点击时加速,gameover时挂掉下落 // 小鸟上升过程 function up() { // 向上是一个减速过程 speed -= 0.7; // 当速度减小到0的时候开始下落 // 对speed进行取整的方法:parseInt() if (parseInt(speed) <= 0) { // 下落首先要换图片 flappyBirdImg.src = 'img/down_bird1.png'; speed = 0; clearInterval(upTimer); // 开始下落 downTimer = setInterval(down,30); } flappyBird.style.top = flappyBird.offsetTop- speed +'px'; } // 封装下落的过程 function down() { // 下落是越落越快的过程 speed += 0.4; // 速度不允许一直变大,当speed>=maxSpeed时,就让速度一直为maxSpeed,也就是一直以最大速度下落 if (speed >= maxSpeed) { speed = maxSpeed; } flappyBird.style.top = flappyBird.offsetTop + speed + 'px'; } // 屏幕被点击时 function fnTouch() { // gameIsOver:通过一个bool值gameIsOver,来记录游戏是否结束 // 判断,当游戏的状态为没有结束时,点击屏幕才有作用 if (!gameIsOver) { // 播放小鸟被点击的音乐 bullet.play(); // 清除一下定时器 clearInterval(speedupTimer); clearInterval(upTimer); clearInterval(downTimer); // 点击屏幕小鸟飞行的速度变快 speed = 8; // 小鸟飞行的过程 // 点击屏幕的时候小鸟飞行的速度变快变为8,然后就开始减速向上飞 // 速度从8开始慢慢递减 // 当速度减到0的时候小鸟开始下落 // 下落的过程是越落越快的,也就是说速度递增 // 点击屏幕,让小鸟以8的速度飞两次(飞两个时间间隔),然后开始减速上升 // index用来记录飞行次数 var index = 0; speedupTimer = setInterval(function () { // 小鸟由静止到飞行,先更换图片 flappyBirdImg.src = 'img/up_bird1.png'; index++; if (index>1) { clearInterval(speedupTimer); // 开始减速上飞 upTimer = setInterval(up, 30); } // 小鸟向上飞实际上是更改top值 flappyBird.style.top = flappyBird.offsetTop - speed + 'px'; },30); } } // 小鸟挂掉 function gameoverDown() { flappyBird.style.transition = 'all 0.5s linear'; flappyBirdImg.src = 'img/down_bird1.png'; flappyBird.style.top = '392px'; } // 图片预加载 function loadImg() { // aScoringImg:分数图片存放在这个数组中 // 循环遍历aScoringImg数组 for (var i=0; i<aScoringImg.length; i++) { // 创建图片的对象 var newImg = new Image(); // 将aScoringImg数组中的图片路径赋给newImg对象 newImg.src = aScoringImg[i]; // 图片对象自带onload方法,这个方法会在图片加载完成后立即调用 // 也就是保证图片能够提前被预加载出来 newImg.onload = function () { // arrImg中的图片已经预加载完成 arrImg.push(this); } } } </script>