为了账号安全,请及时绑定邮箱和手机立即绑定

JaveScript 之 飞翔的小鸟

大家都玩过飞翔的小鸟吧,我仿照小游戏写了一份.

你还在为得不到高分而苦恼吗?你还在为想挑战自己而找不到方法吗???
现在只需要修改下源代码,一切都不是问题!
HTML 部分:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>飞鸟-自作</title>
        <link rel="stylesheet" href="css/飞鸟-自作.css" />
    </head>
    <body>
        <div id="wrap">
            <!--开始菜单-->
            <div id="menuGame">
                <!--字-->
                <img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/head.jpg" alt="" />
                <!--鸟-->
                <img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/bird.png"/>
                <!--开始按钮-->
                <img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/start.jpg" alt="" id="start"/>
            </div>
            <!--游戏内容-->
            <div id="content">
                <!--飞鸟-->
                <img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/bird.png" alt="" id="bird"/>
                <!--分数-->
                <div id="score">
                    <img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/0.jpg" alt="" />
                </div>
                <!--管道-->
                <ul id="pipes">
                    <!--<li class="pipe">-->
                        <!--上管道-->
                        <!--<div class="up_pipe"></div>-->
                        <!--下管道-->
                        <!--<div class="down_pipe"></div>-->
                    <!--</li>-->
                </ul>
                <!--草地-->
                <div id="grass">
                    <img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/banner.jpg" alt="" />
                    <img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/banner.jpg" alt="" />
                </div>
                <!--结束界面-->
                <div id="menuOver">
                    <img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="img/message.jpg" alt="" />
                    <span id="nowScore">0</span>
                    <span id="bestScore">0</span>
                </div>
            </div>
            <!--音乐-->
            <!--背景音乐-->
            <audio class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="music/game_music.mp3" id="musicGame"></audio>
            <!--点击音乐-->
            <audio class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="music/bullet.mp3" id="musicBullet"></audio>
            <!--结束音乐-->
            <audio class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="music/game_over.mp3" id="musicOver"></audio>
        </div>
    </body>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="js/飞鸟-自作.js"></script>
</html>

CSS 部分:

*{
    margin:0;
    padding: 0;
}
#wrap{
    width: 343px;
    height: 480px;
    margin: 20px auto;
    background: url(../img/bg.jpg);
    position: relative;
    overflow: hidden;
}
#menuGame{
    width: 100%;
    height: 100%;
    position: absolute;
}
#menuGame img:first-child {
    position: absolute;
    top: 100px;
    left: 55px;
}
#menuGame img:nth-child(2){
    position: absolute;
    top: 125px;
    right: 55px;
    animation: fly 1s linear infinite;
}
@keyframes fly {
    0%{
        top:125px;
    }
    25%{
        top: 105px;
    }
    75%{
        top:145px
    }
    100%{
        top: 125px;
    }
}
#start{
    position: absolute;
    top:240px;
    left: 50%;
    margin-left: -50px;
    z-index: 1;
}
#content{
    width: 100%;
    height: 100%;
    position: absolute;
}
#bird{
    position: absolute;
    top: 40%;
    left: 60px;
    display: none;
    z-index: 1;
    /*border: 1px solid red;*/
}
#score{
    position: absolute;
    left: 50%;
    margin-left: -10px;
    display: none;
    z-index: 1;
}
#pipes{
    height: 423px;
    list-style-type: none;
    /*position: absolute;*/
    /*width: 343px;*/
    /*border: 1px solid black;*/

}
.pipe{
    width: 60px;
    height: 423px;
    position: absolute;
    /*border: 1px solid transparent;*/
}
.up_pipe{
    width: 62px;
    background: url(../img/up_pipe.png) bottom no-repeat,url(../img/up_mod.png) repeat-y;
    position: absolute;
    top: 0;
}
.down_pipe{
    width: 62px;
    background: url(../img/down_pipe.png) top no-repeat,url(../img/down_mod.png) repeat-y;
    position: absolute;
    bottom:0;
}
#grass{
    width: 1000px;
    position: absolute;
    left: 0;
    bottom: 43px;
}
#grass > img{
    width: 343px;
    float: left;
}
#menuOver{
    position: absolute;
    top: 110px;
    left: 35px;
    display: none;
}
#nowScore{
    position: absolute;
    right: 50px;
    top: 38px;
}
#bestScore{
    position: absolute;
    right: 50px;
    top: 90px;
}

下面是重头戏 JS 部分:

//封装函数- 通过 id 获取元素
function get(type){
    return document.getElementById(type);
}
//获取元素
var wrap = get('wrap');
var menuGame = get('menuGame');
var start = get('start');
var content = get('content');
var li = get('li');
var score = get('score');
var pipesUl = get('pipes');
var grass = get('grass');
var musicGame = get('musicGame');
var musicBullet = get('musicBullet');
var musicOver = get('musicOver');
var menuOver = get('menuOver');
var nowScore = get('nowScore');
var bestScore = get('bestScore');
//为开始按钮添加点击事件
start.onclick = function () {
    //第一步:开始菜单消失
    menuGame.style.display = 'none'
    //第二步:让消失的出现
    bird.style.display = 'block';
    score.style.display = 'block';
    //第三步:背景音乐
    musicGame.play();
    musicGame.loop = true;
    //第四步:草地移动
    setInterval(grassMove,30);
    //第五步:小鸟下落
     flyTime = setInterval(birdFly,30);
    //第六步:点击屏幕让小鸟飞翔
    content.onclick = function () {
        speed = -8;
        //添加点击音乐
        musicBullet.play();
    }
    //第七步:生成管道
    creatPipesTimer = setInterval(creatPipes,3500);
    //第八步:判断是否碰撞
    setInterval(function () {
        //获取 li
        var lis = pipesUl.getElementsByClassName('pipe');
        for (var i = 0;i < lis.length;i++) {
            //console.log(i);
            console.log(lis[i].offsetParent.offsetLeft )
            //只有当小鸟的左边距不大于管道的右边距时,判断是否碰撞
            if (lis[i].offsetLeft + lis[i].offsetWidth > bird.offsetLeft ) {
                //判断上管道时候与小鸟碰撞
                if(crash(bird, lis[i].firstElementChild)){
                    console.log('撞墙了');
                    gameOver();
                }
                //判断下管道与小鸟碰撞
                if(crash(bird,lis[i].lastElementChild)){
                     console.log('撞墙了')
                     gameOver();
                }
            }
        }
    },15)
}
//草地移动
var grassLeft = 0;//记录 grass 的 left
function grassMove () {
    grassLeft -= 2;
    grass.style.left = grassLeft + 'px';
    if(grassLeft < -343) {
        grassLeft = 0;
    }
}
//小鸟下落
var speed = 0;//记录小鸟下落的速度
var pres = 0;//记录小鸟上刻的高度
var flyTime;//定义小鸟下落的定时器
function birdFly () {
     speed += 0.5;
     //设置最大速度
     if(speed > 8){
        speed = 8;
     }
     var birdTop = bird.offsetTop + speed;
     //小鸟上升和下降分别赋予不同的图片
     if (pres > birdTop) {
         bird.src = 'img/up_bird.png'

     }else {
         bird.src = 'img/down_bird.png';
     }
     //当小鸟落到地上时
     if (birdTop > wrap.clientHeight - bird.offsetHeight - 55) {
        birdTop = wrap.clientHeight - bird.offsetHeight - 55;
        //清除定时器
        clearInterval(flyTime);
        //游戏结束
        gameOver();
     }
     //当小鸟到顶时,
     if (birdTop < 0) {
        birdTop = 0;
        clearInterval(flyTime);
        gameOver();
     }
     //修改小鸟的位置
     bird.style.top = birdTop + 'px';
     //将此刻小鸟的高度赋值给 pres
     pres = birdTop;
}
//封装随机函数
function randomNum (m,n) {
    return Math.floor(Math.random() * (n - m + 1) + m)
}
//生成管道
var creatPipesTimer;//定义创建管道的定时器
function creatPipes () {
    //创建单个管道
    var li = document.createElement('li');
    li.className = 'pipe';
    li.style.left =  pipesUl.offsetWidth + 'px';
    pipesUl.appendChild(li);
    //随机上管道的高度
    var topHeight = randomNum(50,250);
    //下管道的高度
    var downHeight = li.offsetHeight - topHeight - 120;
    //alert(li.offsetHeight)
    //创建上.下管道
    var top_pipe = document.createElement('div');
    var down_pipe = document.createElement('div');
    top_pipe.className = 'up_pipe';
    down_pipe.className = 'down_pipe'
    top_pipe.style.height = topHeight + 'px';
    down_pipe.style.height = downHeight + 'px';
    li.appendChild(top_pipe);
    li.appendChild(down_pipe);
    //管道移动
    var distance = pipesUl.clientWidth;
    var pipeMoveTimer = setInterval (function () {
        distance--;
        li.style.left = distance + 'px';
        //当管道出屏幕时
        if(distance < -li.offsetWidth) {
            clearInterval(pipeMoveTimer);
            //清除管道(减少内存)
            pipesUl.removeChild(li);
        }
        //得分
        if (distance == 0){
            changeScore();
        }
    },15) 
}
//得分
var num = 0;//记录分数
function changeScore () {
    num++;
    //清除图片
    score.innerHTML = "";
    //添加图片
    if (num < 10) {
        var img = document.createElement("img");
        img.src = "img/" + num + ".jpg";
        score.appendChild(img);
    } else {
        //当得到两位数以上分数时
        //十位上的图片
        score.style.left = '160px';
        var img1 = document.createElement("img");
        img1.src = "img/" + Math.floor(num / 10) + ".jpg";
        score.appendChild(img1);
        //个位上的图片
        var img2 = document.createElement("img");
        img2.src = "img/" + num % 10 + ".jpg";
        score.appendChild(img2);
    }
}
//判断两个物体是否相碰,是则返回 true, 反之返回 false;
function crash (obj1,obj2) {
     var bool = true;
     //获取 obj1 的左.右.上.下边距
     var left1 = obj1.offsetLeft;
     var right1 = obj1.offsetLeft + obj1.offsetWidth;
     var top1 = obj1.offsetTop;
     var bottom1 = obj1.offsetTop + obj1.offsetHeight; 
     //获取 obj2 的左.右.上.下边距
     var left2 = obj2.parentElement.offsetLeft;
     var right2 = obj2.parentElement.offsetLeft + obj2.offsetWidth;
     var top2 = obj2.offsetTop;
     var bottom2 = obj2.offsetTop + obj2.offsetHeight; 
     //判断碰撞的条件
     if (!(bottom1 < top2  left1 > right2  top1 > bottom2  right1 < left2)){
        bool = true;//碰撞
     }else {
        bool = false;//不碰撞
     }
     return bool;
}
//结束游戏
function gameOver () {
    //结束界面
    menuOver.style.display = 'block';
    menuOver.style.zIndex = '2';
    //背景音乐消失
    musicGame.pause();
    //结束音乐出现
    musicOver.play();
    //停止所有的计时器
    //注: 当网页加载完成后, 创建的计时器的id是递增的, 
    //只要能拿到最后一个计时器的id, 遍历所有的小于id的计时器,
    //依次清除, 即可做到清除所有计时器
    var end = setInterval(function () {},1);
    for (var i = 1;i <= end;i++) {
        clearInterval(i);
    }
    //显示得分
    nowScore.innerHTML = num;
    //获取最好的成绩
    if (localStorage.bestScore) {
        var a = localStorage.bestScore > num ? localStorage.bestScore : num;
        bestScore.innerHTML = a;
        localStorage.bestScore = a;
    } else {
        bestScore.innerHTML = num;
        localStorage.bestScore = num;
    }
}

注:因为这个项目较以往比较大,所以 css 部分和 js 部分,我单独写出来了.
css 文件名为 飞鸟-自作.css; js 文件名为 飞鸟-自作. js.放在各自文件夹
下 ,代码中均有说明.

点击查看更多内容
40人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
109
获赞与收藏
1111

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消