美文网首页
DOM综合案例-飞翔的小鸟

DOM综合案例-飞翔的小鸟

作者: 张培跃 | 来源:发表于2022-04-11 19:46 被阅读0次

    JS初学者往往有一个特点:一听就懂,一写就懵。
    纠其原因:
    1-代码练习太少,导致根基不扎实
    2-代码练习太少,导致经验无积累。
    3-代码练习太少,导致思路不清晰。
    所以代码一定要多多练习,无捷径可寻,希望通过以下个案例,可以对大家学习JS有所帮助。

    1- 预览与下载

    2- 完成游戏样式及基本结构

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            * {
                pading: 0;
                margin: 0;
            }
    
            body {
                user-select: none;
            }
    
            /* 游戏舞台 */
            #app {
                position: relative;
                width: 343px;
                height: 480px;
                background: url("./img/bg.jpg");
                margin: 20px auto;
                overflow: hidden;
            }
    
            /*  分数  */
            #score {
                position: absolute;
                width: 100%;
                left: 0;
                top: 20px;
                text-align: center;
                font-size: 0;
                z-index: 1;
            }
    
            /*  开场动画  */
            .startAnimate {
                width: 236px;
                height: 77px;
                background-image: url("./img/head.jpg");
                position: absolute;
                top: 150px;
                left: calc(50% - 118px);
                animation: startAnimate 1s alternate infinite;
                z-index: 9;
            }
    
            @keyframes startAnimate {
                from {
                    top: 120px;
                }
                to {
                    top: 150px;
                }
            }
    
            .animate-bird {
                position: absolute;
                width: 40px;
                height: 26px;
                background-image: url("./img/bird0.png");
                right: 0;
                top: calc(50% - 13px);
                animation: bird 1s alternate infinite;
                z-index: 9;
            }
    
            @keyframes bird {
                from {
                    background-image: url("./img/bird0.png");
    
                }
                to {
                    background-image: url("./img/bird1.png");
                }
            }
    
            /*开始按钮*/
            #start {
                position: 85px;
                height: 29px;
                position: absolute;
                left: calc(50% - 42.5px);
                top: 260px;
                cursor: pointer;
                z-index: 9;
            }
            /*  管道  */
            .pipe {
                width: 62px;
                height: 423px;
                position: absolute;
                left: 200px;
                bottom: 57px;
            }
            .pipe_up {
                position: relative;
                left: 0;
                top: 0;
                height:100px;
                background: url("./img/up_mod.png") repeat-y;
            }
            .pipe_up img{
                position: absolute;
                bottom: 0;
            }
            .pipe_down {
                position: absolute;
                left: 0;
                bottom: 0;
                height:223px;
                background: url("./img/down_mod.png") repeat-y;
            }
        </style>
    </head>
    <body>
    <!--  游戏舞台  -->
    <div id="app">
        <!--  分数  -->
        <div id="score">
            <img src="./img/0.jpg" alt="">
            <img src="./img/0.jpg" alt="">
            <img src="./img/0.jpg" alt="">
        </div>
        <!--  开场动画  -->
        <div class="startAnimate">
            <div class="animate-bird"></div>
        </div>
        <!--  开始按钮  -->
        <img id="start" src="./img/start.jpg" alt="">
        <!--  管道  -->
        <div class="pipe">
            <!--  上管道  -->
            <div class="pipe_up">
                <img src="./img/up_pipe.png" alt="">
            </div>
            <!--  下管道  -->
            <div class="pipe_down">
                <img src="./img/down_pipe.png" alt="">
            </div>
        </div>
    </div>
    </body>
    </html>
    

    预览效果:https://qianduanmao.com/demo/dom/xiaoniao/1.html

    3- 点击开始按钮进入游戏

    • 由于管道需要需要后续动态添加,所以可以将与管道相关的元素注释掉。
    <!--  游戏舞台  -->
    <div id="app">
        <!--  分数  -->
        <div id="score">
            <img src="./img/0.jpg" alt="">
            <img src="./img/0.jpg" alt="">
            <img src="./img/0.jpg" alt="">
        </div>
        <!--  开场动画  -->
        <div class="startAnimate">
            <div class="animate-bird"></div>
        </div>
        <!--  开始按钮  -->
        <img id="start" src="./img/start.jpg" alt="">
        <!--  管道注释掉,因为管道需要后续动态生成  -->
    <!--    <div class="pipe">-->
    <!--        &lt;!&ndash;  上管道  &ndash;&gt;-->
    <!--        <div class="pipe_up">-->
    <!--            <img src="./img/up_pipe.png" alt="">-->
    <!--        </div>-->
    <!--        &lt;!&ndash;  下管道  &ndash;&gt;-->
    <!--        <div class="pipe_down">-->
    <!--            <img src="./img/down_pipe.png" alt="">-->
    <!--        </div>-->
    <!--    </div>-->
    </div>
    
    • 点击start按钮,隐藏开场动画及start按钮
    // 获得开场动画元素
    var startAnimate = document.querySelector('.startAnimate');
    // 获得开始按钮
    var start = document.querySelector('#start');
    // 点击按钮
    start.onclick = function(){
        // 隐藏开场动画及开始按钮
        startAnimate.style.display = this.style.display = 'none';
    }
    

    预览效果:https://qianduanmao.com/demo/dom/xiaoniao/2.html

    4- 小鸟上升及加速下落

    • 游戏舞台中引入小鸟图片
    <img id="bird" src="./img/bird0.png" alt="">
    
    • 为小鸟图片增加样式
    /*  小鸟  */
    #bird {
        position: absolute;
        left: 30px;
        top: 50px;
        display: none;
        z-index: 10;
    }
    
    • JS代码更改如下:
    // 获得开场动画元素
    var startAnimate = document.querySelector('.startAnimate');
    // 获得开始按钮
    var start = document.querySelector('#start');
    // +获得小鸟元素
    var bird = document.querySelector("#bird");
    // +获得后台元素
    var app = document.querySelector("#app");
    // 点击按钮
    start.onclick = function () {
        // 隐藏开场动画及开始按钮
        startAnimate.style.display = this.style.display = 'none';
        // + 小鸟显示
        bird.style.display = 'block';
        // + 小鸟下落速度,正数向下速度,负数为向上速度
        bird.speed = 0;
        // + 允许下降最大距离:57为马路的高度
        bird.distanceMaxDecline = app.clientHeight - 57 - bird.offsetHeight;
        // + 是否死亡,初始值为false
        bird.isDie = false;
        // + 增加定时器
        bird.fly = setInterval(flyInterval.bind(bird), 20);
        // + 为舞台增加点击事件
        app.onclick = birderRise;
    }
    
    // + 单击舞台的处理函数
    function birderRise() {
        // 小鸟加速度设置为-5,向上飞翔
        bird.speed = -5;
    }
    
    // + 小鸟飞翔计时器
    function flyInterval() {
        // 加速度为0.5
        this.speed += 0.5;
        // 如果速度为正数,则下落,正数上升,设置图片
        this.src = this.speed > 0 ? "./img/down_bird0.png":"./img/bird0.png";
        // 小鸟下落的距离
        var distanceDecline = this.offsetTop + this.speed;
        // 如果触地则死亡
        if (distanceDecline > this.distanceMaxDecline) {
            // 设置为下降最大距离
            this.style.top = this.distanceMaxDecline + "px";
            // 死亡
            this.isDie = true;
            // 关闭小鸟定时器
            clearInterval(this.fly);
            return;
        }
        // distanceDecline不允许小于0
        if (distanceDecline < 0) distanceDecline = 0;
        // 设置top值
        this.style.top = distanceDecline + "px";
    }
    

    预览效果:https://qianduanmao.com/demo/dom/xiaoniao/3.html

    5- 隔3s生成一次管道

    • 创建工具函数,用于生成指定范围的整数
    // 工具函数:生成指定范围的随机整数
    function getRandom(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min);
    }
    
    • 创建生成管道方法
    // 创建管道
    function createPipe(){
        var pipe = document.createElement("div");
        pipe.className = "pipe";
        pipe.score =  1;// 指定增加分值
        // 上管道宽度
        var upHeight = getRandom(60,263);
        // 下管道的高度
        var downHeight = app.clientHeight-57-100-upHeight;
        pipe.innerHTML = `
            <div style="height:${upHeight}px" class="pipe_up">
            <img src="./img/up_pipe.png" alt="">
            </div>
            <div style="height:${downHeight}px" class="pipe_down">
            <img src="./img/down_pipe.png" alt="">
            </div>
        `;
        // 将创建的管道放置在舞台尾部
        app.appendChild(pipe);
    }
    
    • 增加全局变量
    // +记录生成管道定时器
    var pipeTimer;
    
    • 在start按钮的事件处理函数中增加定时器隔3秒调用一次createPipe
    // 点击按钮
    start.onclick = function () {
        // 隐藏开场动画及开始按钮
        startAnimate.style.display = this.style.display = 'none';
        // 小鸟显示
        bird.style.display = 'block';
        // 小鸟下落速度,正数向下速度,负数为向上速度
        bird.speed = 0;
        // 允许下降最大距离:57为马路的高度
        bird.distanceMaxDecline = app.clientHeight - 57 - bird.offsetHeight;
        // 是否死亡,初始值为false
        bird.isDie = false;
        // 增加定时器
        bird.fly = setInterval(flyInterval.bind(bird), 30);
        // +管道定时器
        pipeTimer = setInterval(createPipe,3000);
        // 为舞台增加点击事件
        app.onclick = birderRise;
    }
    

    预览效果:https://qianduanmao.com/demo/dom/xiaoniao/4.html

    6- 管道均速移动并统计分数

    • 由于管道要动态生产,需要将管道的初始位置调整为游戏舞台右侧。
    /*  管道  */
    .pipe {
        width: 62px;
        height: 423px;
        position: absolute;
        left: 343px;/*修改为343*/
        bottom: 57px;
    }
    
    • 增加全局变量
    // +获得分数元素
    var score = document.querySelectorAll("#score>img");
    
    • 增加小鸟总分数属性
    // 点击按钮
    start.onclick = function () {
        // 隐藏开场动画及开始按钮
        startAnimate.style.display = this.style.display = 'none';
        // 小鸟显示
        bird.style.display = 'block';
        // 小鸟下落速度,正数向下速度,负数为向上速度
        bird.speed = 0;
        // 允许下降最大距离:57为马路的高度
        bird.distanceMaxDecline = app.clientHeight - 57 - bird.offsetHeight;
        // 是否死亡,初始值为false
        bird.isDie = false;
        // +小鸟总分
        bird.scoreSum = 0;
        // 增加定时器
        bird.fly = setInterval(flyInterval.bind(bird), 30);
        // 管道定时器
        pipeTimer = setInterval(createPipe,3000);
        // 为舞台增加点击事件
        app.onclick = birderRise;
    }
    
    • 增加管理均速移动方法,并统计分数
    // 管道移动
    function pipeMove(){
        // 每次移动2像素
        var distance  = this.offsetLeft -2;
        // 让管道开始移动
        this.style.left = distance+"px";
        // 判断管道是否已经移出舞台
        if(distance<-this.offsetWidth){
            // 移除定时器
            clearInterval(this.moveTimer);
            // 移除管道
            app.removeChild(this);
        }else if(distance<-(this.offsetWidth-bird.offsetLeft)){
            // 小鸟过了管道加分
            if(this.score > 0){
                bird.scoreSum+=this.score;
                score[0].src="./img/"+parseInt(bird.scoreSum/100)+".jpg";
                score[1].src="./img/"+parseInt((bird.scoreSum%100)/10)+".jpg";
                score[2].src="./img/"+parseInt(bird.scoreSum%10)+".jpg";
                this.score = 0;
            }
        }
    }
    
    
    • 在createPipe函数中调用pipeMove
    // 创建管道
    function createPipe(){
        // 。。。
        // 。。。
        // 。。。
        // +增加定时器,让管道均速移动
        pipe.moveTimer = setInterval(pipeMove.bind(pipe),30);
    }
    
    

    预览效果:https://qianduanmao.com/demo/dom/xiaoniao/5.html

    7- 让草地进行均速移动

    • 在游戏舞台中增加草地元素
    <!--  草地  -->
    <div id="banner">
        <img src="img/banner.jpg"/>
        <img src="img/banner.jpg"/>
    </div>
    
    
    • 为草地增加样式
    /*草地*/
    #banner{
        position: absolute;
        left:0;
        top:423px;
        font-size: 0;
        width: 200%;
    }
    
    
    • 全局获得草地元素,并增加移动初始值
    // 获得草地
    var banner = document.querySelector("#banner");
    // 向左移动的数值
    banner.distanceLeft = 0;
    
    • 增加草地移动函数
    // 草地向左移动
    function bannerMove(){
        // 向左移动的数值 (距离)+2
        banner.distanceLeft -= 2;
        // 判断最左侧图片是否消失在舞台中
        if(banner.distanceLeft < -app.clientWidth){
            // 向左移动的距离为0
            banner.distanceLeft = 0;
            // 将banner当中的第一个DOM元素放置到banner的尾部
            banner.appendChild(banner.firstElementChild);
        }
        banner.style.left = banner.distanceLeft+"px";
    }
    
    • 在start按钮的事件处理函数中增加定时器,调用bannerMove
    // 草地移动
    banner.timer = setInterval(bannerMove,30);
    

    预览效果:https://qianduanmao.com/demo/dom/xiaoniao/6.html

    8- 检测碰撞游戏结束

    • 增加碰撞检测函数
    // 是否小鸟与柱子进行了碰撞
    function crashFn(pipe){
        // 相撞:四个条件必须同时满足
        // bird与pipe
        // 1- bird的右边 大于等于 pipe的左边
        // 2- bird的下边 大于等于  pipe的上边
        // 3- bird的左边 小于等于  pipe的右边
        // 4- bird的上边 小于等于  pipe的下边
    
        // bird:
        var birdLeft = bird.offsetLeft;//左边
        var birdRight = birdLeft+bird.offsetWidth;// 右边
        var birdTop = bird.offsetTop;// 上边
        var birdBottom = birdTop+bird.offsetHeight;// 下边
    
        // pipe
        var pipeLeft = pipe.parentNode.offsetLeft;
        var pipeRight = pipeLeft+pipe.offsetWidth;
        var pipeTop = pipe.offsetTop;
        var pipeBottom = pipeTop+pipe.offsetHeight;
        if(birdRight>=pipeLeft
           && birdBottom>=pipeTop
           && birdLeft<=pipeRight
           && birdTop<=pipeBottom){
            return true;// 相撞了
        }
        return false;// 没有相撞
    }
    
    • 在flyInterval函数中判断是否碰撞
    // 小鸟飞翔计时器
    function flyInterval() {
        // 加速度为0.5
        this.speed += 0.5;
        // 如果速度为正数,则下落,正数上升,设置图片
        this.src = this.speed > 0 ? "./img/down_bird0.png":"./img/bird0.png";
        // 小鸟下落的距离
        var distanceDecline = this.offsetTop + this.speed;
        // 如果触地则死亡
        if (distanceDecline > this.distanceMaxDecline) {
            distanceDecline = this.distanceMaxDecline;
            // 小鸟死亡
            this.isDie = true;
        }
        // distanceDecline不允许小于0
        if (distanceDecline < 0) distanceDecline = 0;
        // 设置top值
        this.style.top = distanceDecline + "px";
        // + 小鸟未亡,检测管道是否与小鸟相撞
        if(!this.isDie){
            var pipes = document.querySelectorAll(".pipe div");
            for(var i=0;i<pipes.length;i++){
                // 相撞
                if(crashFn(pipes[i])){
                    bird.isDie = true;
                    bird.className = "die";
                    break;
                }
            }
        }
        // + 判断小鸟是否死亡
        if(bird.isDie){
            // 关闭小鸟定时器
            clearInterval(this.fly);
            // 关闭管道定时器
            clearInterval(pipeTimer);
            // 关闭草地定时器
            clearInterval(banner.timer)
            // 显示开场动画及开始按钮
            startAnimate.style.display = start.style.display = 'block';
        }
    }
    
    • 增加小鸟撞击后的样式
    /*死亡*/
    .die{
        transition:0.5s;
        top:393px !important;
    }
    
    • pipeMove函数判断小鸟是否死亡
    // + 判断小鸟是否死亡
    if(bird.isDie){
        // 关闭管道移动定时器
        clearInterval(this.moveTimer)
        // 清除管道
        app.removeChild(this);
        return;
    }
    
    • 重置游戏
    // 点击按钮
    start.onclick = function () {
        // + 重置分数
        score[0].src = score[1].src = score[2].src = "./img/0.jpg";
        // + 重置小鸟高度
        bird.style.top = "50px";
        // + 清除小鸟样式
        bird.className = null;
        // 隐藏开场动画及开始按钮
        startAnimate.style.display = this.style.display = 'none';
        // 小鸟显示
        bird.style.display = 'block';
        // 小鸟下落速度,正数向下速度,负数为向上速度
        bird.speed = 0;
        // 允许下降最大距离:57为马路的高度
        bird.distanceMaxDecline = app.clientHeight - 57 - bird.offsetHeight;
        // 是否死亡,初始值为false
        bird.isDie = false;
        // 小鸟总分
        bird.scoreSum = 0;
        // 增加定时器
        bird.fly = setInterval(flyInterval.bind(bird), 30);
        // 管道定时器
        pipeTimer = setInterval(createPipe, 3000);
        // 草地移动
        banner.timer = setInterval(bannerMove, 30);
        // 为舞台增加点击事件
        app.onclick = birderRise;
    }
    
    

    预览效果:https://qianduanmao.com/demo/dom/xiaoniao/7.html

    9- 增加音乐-完整代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            * {
                pading: 0;
                margin: 0;
            }
    
            body {
                user-select: none;
            }
    
            /* 游戏舞台 */
            #app {
                position: relative;
                width: 343px;
                height: 480px;
                background: url("./img/bg.jpg");
                margin: 20px auto;
                overflow: hidden;
            }
    
            /*  分数  */
            #score {
                position: absolute;
                width: 100%;
                left: 0;
                top: 20px;
                text-align: center;
                font-size: 0;
                z-index: 1;
            }
    
            /*  开场动画  */
            .startAnimate {
                width: 236px;
                height: 77px;
                background-image: url("./img/head.jpg");
                position: absolute;
                top: 150px;
                left: calc(50% - 118px);
                animation: startAnimate 1s alternate infinite;
                z-index: 9;
            }
    
            @keyframes startAnimate {
                from {
                    top: 120px;
                }
                to {
                    top: 150px;
                }
            }
    
            .animate-bird {
                position: absolute;
                width: 40px;
                height: 26px;
                background-image: url("./img/bird0.png");
                right: 0;
                top: calc(50% - 13px);
                animation: bird 1s alternate infinite;
                z-index: 9;
            }
    
            @keyframes bird {
                from {
                    background-image: url("./img/bird0.png");
    
                }
                to {
                    background-image: url("./img/bird1.png");
                }
            }
    
            /*开始按钮*/
            #start {
                position: 85px;
                height: 29px;
                position: absolute;
                left: calc(50% - 42.5px);
                top: 260px;
                cursor: pointer;
                z-index: 9;
            }
    
            /*  管道  */
            .pipe {
                width: 62px;
                height: 423px;
                position: absolute;
                left: 343px; /*修改为343*/
                bottom: 57px;
            }
    
            .pipe_up {
                position: relative;
                left: 0;
                top: 0;
                height: 100px;
                background: url("./img/up_mod.png") repeat-y;
            }
    
            .pipe_up img {
                position: absolute;
                bottom: 0;
            }
    
            .pipe_down {
                position: absolute;
                left: 0;
                bottom: 0;
                height: 223px;
                background: url("./img/down_mod.png") repeat-y;
            }
    
            /*  小鸟  */
            #bird {
                position: absolute;
                left: 30px;
                top: 50px;
                display: none;
                z-index: 10;
            }
    
            /*草地*/
            #banner {
                position: absolute;
                left: 0;
                top: 423px;
                font-size: 0;
                width: 200%;
            }
    
            /*死亡*/
            .die {
                transition: 0.5s;
                top: 393px !important;
            }
        </style>
    </head>
    <body>
    <!--  游戏舞台  -->
    <div id="app">
        <!--  分数  -->
        <div id="score">
            <img src="./img/0.jpg" alt="">
            <img src="./img/0.jpg" alt="">
            <img src="./img/0.jpg" alt="">
        </div>
        <img id="bird" src="./img/bird0.png" alt="">
        <!--  开场动画  -->
        <div class="startAnimate">
            <div class="animate-bird"></div>
        </div>
        <!--  开始按钮  -->
        <img id="start" src="./img/start.jpg" alt="">
        <!--  草地  -->
        <div id="banner">
            <img src="img/banner.jpg"/>
            <img src="img/banner.jpg"/>
        </div>
    
        <audio preload="auto"
               loop
               src="./music/game_music.mp3">
        </audio>
        <audio preload="auto"
               src="./music/game_over.mp3">
        </audio>
        <audio preload="auto"
               src="./music/bullet.mp3">
        </audio>
    </div>
    </body>
    <script>
        var audios = document.querySelectorAll("audio");
        // 获得开场动画元素
        var startAnimate = document.querySelector('.startAnimate');
        // 获得开始按钮
        var start = document.querySelector('#start');
        // 获得小鸟元素
        var bird = document.querySelector("#bird");
        // 获得后台元素
        var app = document.querySelector("#app");
        // 获得分数元素
        var score = document.querySelectorAll("#score>img");
        // 获得草地
        var banner = document.querySelector("#banner");
        // 向左移动的数值
        banner.distanceLeft = 0;
        // 记录生成管道定时器
        var pipeTimer;
        // 点击按钮
        start.onclick = function () {
            audios[0].play();
            // 重置分数
            score[0].src = score[1].src = score[2].src = "./img/0.jpg";
            // 重置小鸟高度
            bird.style.top = "50px";
            // 清除小鸟样式
            bird.className = null;
            // 隐藏开场动画及开始按钮
            startAnimate.style.display = this.style.display = 'none';
            // 小鸟显示
            bird.style.display = 'block';
            // 小鸟下落速度,正数向下速度,负数为向上速度
            bird.speed = 0;
            // 允许下降最大距离:57为马路的高度
            bird.distanceMaxDecline = app.clientHeight - 57 - bird.offsetHeight;
            // 是否死亡,初始值为false
            bird.isDie = false;
            // 小鸟总分
            bird.scoreSum = 0;
            // 增加定时器
            bird.fly = setInterval(flyInterval.bind(bird), 30);
            // 管道定时器
            pipeTimer = setInterval(createPipe, 3000);
            // 草地移动
            banner.timer = setInterval(bannerMove, 30);
            // 为舞台增加点击事件
            app.onclick = birderRise;
        }
    
        // 单击舞台的处理函数
        function birderRise() {
            audios[2].play();
            // 小鸟加速度设置为-5,向上飞翔
            bird.speed = -5;
        }
    
        // 小鸟飞翔计时器
        function flyInterval() {
            // 加速度为0.5
            this.speed += 0.5;
            // 如果速度为正数,则下落,正数上升,设置图片
            this.src = this.speed > 0 ? "./img/down_bird0.png" : "./img/bird0.png";
            // 小鸟下落的距离
            var distanceDecline = this.offsetTop + this.speed;
            // 如果触地则死亡
            if (distanceDecline > this.distanceMaxDecline) {
                distanceDecline = this.distanceMaxDecline;
                // 小鸟死亡
                this.isDie = true;
            }
            // distanceDecline不允许小于0
            if (distanceDecline < 0) distanceDecline = 0;
            // 设置top值
            this.style.top = distanceDecline + "px";
            // 小鸟未亡,检测管道是否与小鸟相撞
            if (!this.isDie) {
                var pipes = document.querySelectorAll(".pipe div");
                for (var i = 0; i < pipes.length; i++) {
                    // 相撞
                    if (crashFn(pipes[i])) {
                        bird.isDie = true;
                        bird.className = "die";
                        break;
                    }
                }
            }
            // 判断小鸟是否死亡
            if (bird.isDie) {
                audios[0].pause();
                audios[1].play();
                // 关闭小鸟定时器
                clearInterval(this.fly);
                // 关闭管道定时器
                clearInterval(pipeTimer);
                // 关闭草地定时器
                clearInterval(banner.timer);
                // 显示开场动画及开始按钮
                startAnimate.style.display = start.style.display = 'block';
            }
    
        }
    
        // 创建管道
        function createPipe() {
            var pipe = document.createElement("div");
            pipe.className = "pipe";
            pipe.score = 1;// 指定增加分值
            // 上管道宽度
            var upHeight = getRandom(60, 263);
            // 下管道的高度
            var downHeight = app.clientHeight - 57 - 100 - upHeight;
            pipe.innerHTML = `
                <div style="height:${upHeight}px" class="pipe_up">
                   <img src="./img/up_pipe.png" alt="">
                </div>
                <div style="height:${downHeight}px" class="pipe_down">
                   <img src="./img/down_pipe.png" alt="">
                </div>
            `;
            // 将创建的管道放置在舞台尾部
            app.appendChild(pipe);
            // 增加定时器,让管道均速移动
            pipe.moveTimer = setInterval(pipeMove.bind(pipe), 30);
        }
    
        // 管道移动
        function pipeMove() {
            // 判断小鸟是否死亡
            if (bird.isDie) {
                // 关闭管道移动定时器
                clearInterval(this.moveTimer)
                // 清除管道
                app.removeChild(this);
                return;
            }
            // 每次移动2像素
            var distance = this.offsetLeft - 2;
            // 让管道开始移动
            this.style.left = distance + "px";
            // 判断管道是否已经移出舞台
            if (distance < -this.offsetWidth) {
                // 移除定时器
                clearInterval(this.moveTimer);
                // 移除管道
                app.removeChild(this);
            } else if (distance < -(this.offsetWidth - bird.offsetLeft)) {
                // 小鸟过了管道加分
                if (this.score > 0) {
                    bird.scoreSum += this.score;
                    score[0].src = "./img/" + parseInt(bird.scoreSum / 100) + ".jpg";
                    score[1].src = "./img/" + parseInt((bird.scoreSum % 100) / 10) + ".jpg";
                    score[2].src = "./img/" + parseInt(bird.scoreSum % 10) + ".jpg";
                    this.score = 0;
                }
            }
        }
    
        // 草地向左移动
        function bannerMove() {
            // 向左移动的数值 (距离)+2
            banner.distanceLeft -= 2;
            // 判断最左侧图片是否消失在舞台中
            if (banner.distanceLeft < -app.clientWidth) {
                // 向左移动的距离为0
                banner.distanceLeft = 0;
                // 将banner当中的第一个DOM元素放置到banner的尾部
                banner.appendChild(banner.firstElementChild);
            }
            banner.style.left = banner.distanceLeft + "px";
        }
    
        // 是否小鸟与柱子进行了碰撞
        function crashFn(pipe) {
            // 相撞:四个条件必须同时满足
            // bird与pipe
            // 1- bird的右边 大于等于 pipe的左边
            // 2- bird的下边 大于等于  pipe的上边
            // 3- bird的左边 小于等于  pipe的右边
            // 4- bird的上边 小于等于  pipe的下边
    
            // bird:
            var birdLeft = bird.offsetLeft;//左边
            var birdRight = birdLeft + bird.offsetWidth;// 右边
            var birdTop = bird.offsetTop;// 上边
            var birdBottom = birdTop + bird.offsetHeight;// 下边
    
            // pipe
            var pipeLeft = pipe.parentNode.offsetLeft;
            var pipeRight = pipeLeft + pipe.offsetWidth;
            var pipeTop = pipe.offsetTop;
            var pipeBottom = pipeTop + pipe.offsetHeight;
            if (birdRight >= pipeLeft
                && birdBottom >= pipeTop
                && birdLeft <= pipeRight
                && birdTop <= pipeBottom) {
                return true;// 相撞了
            }
            return false;// 没有相撞
        }
    
        // 工具函数:生成指定范围的随机整数
        function getRandom(min, max) {
            return Math.floor(Math.random() * (max - min + 1) + min);
        }
    </script>
    </html>
    

    相关文章

      网友评论

          本文标题:DOM综合案例-飞翔的小鸟

          本文链接:https://www.haomeiwen.com/subject/bolwsrtx.html