JavaScript实践|青训营

189 阅读3分钟

像素鸟

游戏画面上下分布一些管道,小鸟飞行,点击小鸟则小鸟向上飞行,碰到管道游戏结束。

HTML结构

创建游戏背景和小鸟

<body>
    <!-- 游戏背景 -->
  <div id="game">
    <!-- 小鸟 -->
    <div id="bird"></div>
  </div>
</body>

使用div划分一个游戏区域,在该区域中划分一个区域显示小鸟。

CSS表现

游戏背景区域元素设置相对定位,背景显示背景图片,小鸟区域元素设置绝对定位,网页初始效果如下: QQ截图20230829220556.png

JS

初始化背景图以及小鸟的位置,游戏开始时,小鸟飞行,通过背景向左运动实现,即在X轴方向的位置不断减小,实现小鸟向右飞行效果,背景每次移动-5px。通过JS选择id为"game"的元素,通过backgroundPositionX修改背景位置,使其每次移动-5px。

<script>
    //获取游戏背景和小鸟
  var game = document.getElementById('game');
  var birdEle = document.getElementById('bird');

  //初始化背景图
  var sky = {
    x: 0 //背景图初始位置为0
  }
 
  //初始化小鸟
  var bird = {
    speedX: 5, //小鸟在X轴的速度
    SpeedY: 0, //小鸟在Y轴的速度
    //小鸟坐标
    x: birdEle.offsetLeft, //小鸟初始位置在绝对定位的位置
    y: birdEle.offsetTop,
  }
 
  var runing = true; //游戏状态
 
  setInterval(function () {
    if (runing) {
      //小鸟飞行(其实是背景在动)
      sky.x -= 5; //背景每次-5px,以实现向左运动的效果
      game.style.backgroundPositionX = sky.x + 'px';
      
    }
  }, 30);
</script>

效果如下图所示: QQ录屏20230829222133.gif

接下来实现小鸟向上向下飞行的功能,小鸟自动向下飞行,每次点击后小鸟向上飞行10px,通过JS实现小鸟自动向下飞行,在backgroundPositionX代码后增加如下代码:

//小鸟上下运动
      bird.SpeedY += 1; //自动向下
      bird.y += bird.SpeedY; //小鸟自动不断向下运动
      birdEle.style.top = bird.y + 'px';

设置鼠标点击事件,在setInterval函数后添加代码实现鼠标点击事件,让小鸟向上飞行:

//点击时小鸟向上运动
    document.onclick = function () {
    bird.SpeedY = -10; //点击一次向上运动10px

由于小鸟向上向下飞行可能会触碰到背景底部或顶部,所以设置小鸟超出游戏背景顶部或底部时游戏结束,在top代码前增加判断小鸟是否超出游戏背景顶部或底部语句:

//判断游戏状态
      if (bird.y < 0) { //超出游戏背景顶部时游戏结束
        runing = false;
        bird.y = 0;
      }
      if (bird.y + birdEle.offsetHeight > 650) { //超出游戏背景底部时游戏结束
        runing = false;
        bird.y = 650 - birdEle.offsetHeight;
      }

得到效果如下: QQ录屏20230829224317_1.gif

接下来创建管道,X方向上管道和下管道位置相同,Y方向上上下管道的高度随机,但中间要空出200px位置,以供小鸟通过。通过JS新建div将上下管道加载到页面中,上管道高度在200px-300px之间,下管道高度为游戏背景高度减去上管道高度减去中间空出来的200px,管道宽度同一设置为52px,一共设置4组管道,每组之间相隔250px。

//创建管道
  function creatPipe(position) {
    var pipe = {};
    pipe.x = position;
    pipe.upHeight = 200 + parseInt(Math.random() * 100); //上管道高度为200 - 300px
    pipe.doHeight = 650 - pipe.upHeight - 200; //下管道高度
    pipe.doTop = pipe.upHeight + 200; //上下两管道之间200px
 
    //创建上管道
    var upPipe = document.createElement('div'); //新建div
    upPipe.style.width = '52px';
    upPipe.style.height = pipe.upHeight + 'px';
    upPipe.style.background = 'url(./img/pipe2.png) no-repeat center bottom';
    upPipe.style.position = 'absolute';
    upPipe.style.top = '0px';
    upPipe.style.left = pipe.x + 'px';
    game.appendChild(upPipe); //将上管道追加到游戏页面中
 
    //创建下管道
    var doPipe = document.createElement('div'); //新建div
    doPipe.style.width = '52px';
    doPipe.style.height = pipe.doHeight + 'px';
    doPipe.style.background = 'url(./img/pipe1.png) no-repeat center top';
    doPipe.style.position = 'absolute';
    doPipe.style.top = pipe.doTop + 'px';
    doPipe.style.left = pipe.x + 'px';
    game.appendChild(doPipe); //将下管道追加到游戏页面中
  }

  creatPipe(400); //产生四组管道
  creatPipe(650);
  creatPipe(900);
  creatPipe(1150);

效果如下: QQ截图20230829231118.png

接下来实现管道向左运动,与背景图向左的操作类似,也是通过在X轴方向的位置不断减小实现,当第一组管道向左运动移出游戏界面最左侧时最后一组管道右侧在X轴上位置为750px,设置下一组管道左侧在X轴上位置应该为948px,可以实现循环效果。在createPipe函数最后增加如下代码:

//管道进行运动
    setInterval(function () {
      if (runing) { //游戏处于运行状态时管道再运动
        pipe.x -= 2; //x方向不断-2px,以实现管道向左运动的效果
        upPipe.style.left = pipe.x + 'px';
        doPipe.style.left = pipe.x + 'px';
        if (pipe.x < -52) { //管道移出最左侧时回到原位,实现不间断效果
          pipe.x = 948;
        }    
      }
    }, 30)

效果如下(加速了5倍): QQ录屏20230829233005.gif

从上面效果图可以看到小鸟会触碰到管道,接下来实现小鸟触碰到管道则游戏结束功能,定义上下管道的临界值,也就是上下管道自身区域,小鸟位置与上下管道位置重合时游戏结束。效果如下(加速了5倍): QQ录屏20230829235024.gif