DOM综合案例-飞翔的小鸟

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

1- 预览与下载

  • 点此预览
  • 下载链接:https://pan.baidu.com/s/1FMZU3Xb0BteyoYXrNFUzyw
  • 提取码:duan

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




    
    Title
    



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

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

  • 由于管道需要需要后续动态添加,所以可以将与管道相关的元素注释掉。

  • 点击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- 小鸟上升及加速下落

  • 游戏舞台中引入小鸟图片

  • 为小鸟图片增加样式
/*  小鸟  */
#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 = `
        
`; // 将创建的管道放置在舞台尾部 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- 让草地进行均速移动

  • 在游戏舞台中增加草地元素



  • 为草地增加样式
/*草地*/
#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
  • 增加小鸟撞击后的样式
/*死亡*/
.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- 增加音乐-完整代码




    
    Title
    



你可能感兴趣的:(DOM综合案例-飞翔的小鸟)