返回顶部
首页 > 资讯 > 前端开发 > JavaScript >VUE实现一个Flappy Bird游戏的示例代码
  • 487
分享到

VUE实现一个Flappy Bird游戏的示例代码

2024-04-02 19:04:59 487人浏览 泡泡鱼
摘要

Flappy Bird是一个非常简单的小游戏,在app上大家都玩过。这里就用Vue来实现一个简单的PC版Flappy Bird,娱乐一下~~~~~ 要实现这个游戏,首先来分析一下游戏

Flappy Bird是一个非常简单的小游戏,在app上大家都玩过。这里就用Vue来实现一个简单的PC版Flappy Bird,娱乐一下~~~~~

要实现这个游戏,首先来分析一下游戏界面里哪几块东西需要动起来:

1、第一当然就是上下移动的小鸟;

2、横向移动的背景图,让小鸟看起来在横向飞行;

3、从画面右端进入的一排排管道。

这样很明确了,我们让上面3块内容按照规律运动起来,然后再加上规则边界判断和计分,就可以得到一个完整的游戏。所以就一块块来解决。

先来定义一些常量和变量:


let rafId = null; // requestAnimationFrame的ID
let startSpeed = 1;
const SPEED = 0.04; // 加速度
const UP = 5.0; // 速度累加上限
const UP_SUM = 30; // 按一次跳跃的高度
const BIRD_WIDTH = 50; // 小鸟图片宽50px
const PIPE_DISTANCE = 350; // 管道之间的横向距离
let id = 0; // 管道唯一id,从0开始计数
 
...
 
data() {
    return {
      start: false,
      clientWidth: 0,
      clientHeight: 0,
      spaceHeight: [240, 200, 160], // 上管道与下管道之间的距离
      pipeArr: [], // 管道数组
      score: 0, // 得分
      jumpSum: 0, // 当前跳跃相对高度
      jumpFlag: false, // true-按下空格键跳跃上升阶段;false-自由落体阶段
      dropBirdImg: require("@/assets/img/bird/bird0_0.png"),
      flyBirdImg: require("@/assets/img/bird/bird0_2.png"),
      gameOver: false, // 游戏失败的flag,用于停止动画帧
    };
},

1、上下移动的小鸟

为了分别控制小鸟和管道的位置,元素定位均采用position: absolute

小鸟本身就是个div+背景图,然后定义一下在界面里的初始位置:


<div class="bird" id="bird" ref="bird"></div>
 
 #bird {
      height: 50px;
      width: 50px;
      border-radius: 50%;
      background: url("~assets/img/bird/bird0_1.png") no-repeat center/contain;
      // 小鸟初始位置
      position: absolute;
      left: 300px;
      top: 300px;
}

然后,在什么都不操作的情况下,小鸟从初始位置开始"坠落",小鸟的坠落是一个越落越快的过程,在这里我没有用物理的重力加速度公式,只是简单模拟了一个曲线加速过程。这是一个持续的动画,所以把这个动作放在动画帧里,即requestAnimationFrame,每一帧的函数定义为loop()。

所以在loop函数中,根据offsetTop和父元素的clientHeight来判断小鸟是否触碰到了画面的上下边界,是则游戏结束;否,则增加style.top让小鸟坠落。


loop() {
      let _this = this;
      if (_this.jumpFlag) {
        // 小鸟跳跃
        _this.jump();
      }
      let top = _this.$refs.bird.offsetTop;
      if (top > _this.clientHeight - BIRD_WIDTH || top <= 0) {
        // 碰到边界,游戏结束
        _this.resetGame();
      } else if (!_this.jumpFlag) {
        _this.$refs.bird.style.background = `url('${_this.dropBirdImg}') no-repeat center/contain`;
        _this.$refs.bird.style.top = top + startSpeed * startSpeed + "px"; // 模拟加速坠落
        if (startSpeed < UP) {
          startSpeed += SPEED;
        }
      }
      _this.pipesMove(); // 管道移动
}

游戏中,玩家按下空格键,小鸟会向上跳跃一段距离,用this.jumpFlag[true/false]来记录这一状态,当按下时,置为true,loop函数中小鸟jump(),在jump到一定距离后,jumpFlag置为false,小鸟开始坠落。

所以,jump函数很容易实现:


jump() {
      let _this = this;
      _this.$refs.bird.style.background = `url('${_this.flyBirdImg}') no-repeat center/contain`;
      if (_this.jumpSum > UP_SUM) {
        // 到顶部就落下
        _this.jumpFlag = false;
        _this.jumpSum = 0;
        startSpeed = 1;
      } else {
        _this.$refs.bird.style.top = _this.$refs.bird.offsetTop - 8 + "px";
        _this.jumpSum += 8;
      }
}

2、横向移动的背景图

这个比较简单,就是background-position无限循环切换就行了,位置根据自己下载的背景图素材宽度决定。


animation: bgMove 8s linear infinite;
      @keyframes bgMove {
        0% {
          background-position: 805px 0;
        }
        100% {
          background-position: 0 0;
        }
}

经过这两步,我们就可以得到一个正在飞行的小鸟了,用document.onkeydown监听空格键来切换jumpFlag,如下图:

3、从右往左一移动进入管道

管道是由上下两个div组成,每个div通过不同的top: -xx和bottom: -yy实现中间有间隙。

首先实现生成一个随机间隙管道的函数,管道存放在pipeArr对象数组中:


addPipe(id) {
      let obj = {};
      let top_num = this.sum(10, 170);
      let height = this.spaceHeight[
        Math.floor(Math.random() * this.spaceHeight.length)
      ]; // 随机选取间隙值
      let bottom_num = height - top_num;
      obj.top = top_num;
      obj.id = id;
      obj.right = -(PIPE_DISTANCE / 2);
      obj.bottom = bottom_num;
      this.pipeArr.push(obj);
},
sum(m, n) {
      // 随机n-m之间的数字
      return Math.floor(Math.random() * (m - n) + n);
}

然后需要将管道移动起来,即loop()中管道移动函数pipesMove(),整个函数实现如下:


pipesMove() {
      let _this = this;
      if (_this.pipeArr.length === 0) {
        return;
      }
      let right0 = _this.pipeArr[0].right;
      if (right0 > this.clientWidth + 300) {
        this.pipeArr.shift();
      }
      let right_last = _this.pipeArr[_this.pipeArr.length - 1].right;
      if (right_last >= PIPE_DISTANCE / 2) {
        id++;
        this.addPipe(id);
      }
      for (let i = 0; i < _this.pipeArr.length; i++) {
        // 判断一下小鸟是否接触到了管道,小鸟50*50,left:300px;管道宽100px;管道进入范围right是width-450到width-300
        if (
          _this.pipeArr[i].right >= _this.clientWidth - 450 &&
          _this.pipeArr[i].right <= _this.clientWidth - 300
        ) {
          // 该管道进入了小鸟触碰范围
          let bird_top = _this.$refs.bird.offsetTop;
          // 12是小鸟图片素材上下有空白间隙
          if (
            bird_top <= _this.clientHeight / 2 - _this.pipeArr[i].top - 12 ||
            bird_top >=
              _this.clientHeight / 2 + _this.pipeArr[i].bottom - BIRD_WIDTH + 12
          ) {
            // 碰到了管道
            _this.resetGame();
            return;
          }
        }
        if (_this.pipeArr[i].right === _this.clientWidth - 300 && _this.pipeArr[i].right === _this.clientWidth - 301) { // 当某个管道刚好在小鸟左边,证明小鸟通过该管道,根据管道id算出小鸟得分
          _this.score = _this.pipeArr[i].id + 1;
        }
        _this.pipeArr[i].right = _this.pipeArr[i].right + 2; // 管道每帧移动2px
      }
}

这里做了五件事:

(1)管道出了左边画面后shift()最左的管道;

(2)最右的管道离画面右侧一定距离后,加入新的一根管道;

(3)循环遍历中,判断小鸟是否进入了某一根管道的范围,判断小鸟top是否有触碰到上下管道,触碰则输;

(4)当某一个管道刚好位于小鸟左侧时,证明小鸟成功通过,分数+1;

(5)每个管道移动2px像素,数值记录在right属性里。

通过DOM里:style设置right就可以使得管道横向移动了


<section class="pipes-wrap" ref="pipes">
          <div
            class="pipe-item"
            v-for="(item, index) in pipeArr"
            :key="item.id"
            :id="'pipe' + index"
            :style="'right:' + item.right + 'px;'"
          >
            <div
              class="pipe pipe-top"
              :style="'top:-' + item.top + 'px;'"
            ></div>
            <div
              class="pipe pipe-bottom"
              :style="'bottom:-' + item.bottom + 'px;'"
            ></div>
          </div>
</section>
 
.pipes-wrap {
        position: relative;
        height: 100%;
        overflow: hidden;
        .pipe-item {
          position: absolute;
          height: 100%;
          width: 100px;
          .pipe {
            width: 100%;
            height: 50%;
            position: relative;
          }
          .pipe-top {
            background: url('"~assets/img/bird/pipe_down.png') no-repeat;
            background-size: 100px;
            background-position: bottom;
          }
          .pipe-bottom {
            background: url('"~assets/img/bird/pipe_up.png') no-repeat;
            background-size: 100px;
            background-position: top;
          }
        }
}

以上就是vue实现flappy bird的思路和核心代码了,总共也就两百多行代码。在我看来,难点主要集中在管道的移动、触碰判定以及分数计算上。当然代码里还有很多可以优化的不足点,共勉~~

--结束END--

本文标题: VUE实现一个Flappy Bird游戏的示例代码

本文链接: https://lsjlt.com/news/123614.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • VUE实现一个Flappy Bird游戏的示例代码
    Flappy Bird是一个非常简单的小游戏,在app上大家都玩过。这里就用VUE来实现一个简单的PC版Flappy Bird,娱乐一下~~~~~ 要实现这个游戏,首先来分析一下游戏...
    99+
    2024-04-02
  • 基于JS实现Flappy Bird游戏的示例代码
    前言 Flappy Bird 是一款无尽的游戏,玩家可以控制一只鸟。玩家必须保护小鸟免于与管道等障碍物相撞。每次小鸟通过管道时,分数都会增加一。当小鸟与管道碰撞或因重力而坠落时,游戏...
    99+
    2024-04-02
  • 利用python实现flappy bird 游戏(完整代码)
    第一个python文件,flappybirdmain.py ,程序中已经有详细注释.。 程序大概流程:1.加载图片素材文件 2.绘画开始界面,等待程序开始(按空格) 3 .程序刷新,...
    99+
    2024-04-02
  • Vue实现Chrome小恐龙游戏的示例代码
    目录前言复刻画面动画效果路面动画障碍物动画恐龙动画响应事件碰撞检测部署总结前言 几年前,Google 给 Chrome 浏览器加了一个有趣的彩蛋:如果你在未联网的情况下访问网页,会看...
    99+
    2024-04-02
  • Vue实现红包雨小游戏的示例代码
    目录0 写在前面1 准备工作2 设计HTML+CSS样式3 设计JavaScript逻辑4 完整代码0 写在前面 红包也叫压岁钱,是过农历春节时长辈给小孩儿用红纸包裹的礼金。据传明清...
    99+
    2024-04-02
  • Python实现小游戏的源代码示例
    这篇文章将为大家详细讲解有关Python实现小游戏的源代码示例,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1、21点数字小游戏展示:首先配置文件的源码:'''配置文件'&...
    99+
    2023-06-14
  • Java实现经典游戏打砖块游戏的示例代码
    目录前言主要设计功能截图代码实现游戏核心类小球类砖块类总结前言 《JAVA打砖块》游戏是自制的游戏。玩家操作一根萤幕上水平的“棒子”,让一颗不断弹来弹去的&l...
    99+
    2024-04-02
  • Vue实现红包雨小游戏的示例代码是什么
    本篇文章为大家展示了Vue实现红包雨小游戏的示例代码是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。0 写在前面红包也叫压岁钱,是过农历春节时长辈给小孩儿用红纸包裹的礼金。据传明清时期,压岁钱大...
    99+
    2023-06-29
  • Python实现不一样的猜数字游戏的示例代码
    目录前言正文一、运行环境二、代码展示三、效果展示前言 日子从不亏欠,每一个努力向上的人, 未来的走运, 都是过往尽力的积累。 人勤春来早,奋进正当时。新春伊始,我们迎来了2023年开...
    99+
    2023-02-02
    Python猜数字游戏 Python猜数字 Python 游戏
  • Java实现经典游戏2048的示例代码
    目录前言主要设计功能截图代码实现界面布局类业务逻辑类总结前言 2014年Gabriele Cirulli利用周末的时间写2048这个游戏的程序,仅仅只是好玩而已。他想用一种不同的视觉...
    99+
    2024-04-02
  • Java实现经典游戏FlappyBird的示例代码
    目录前言主要设计功能截图代码实现游戏启动类核心类工具类总结前言 《布谷鸟闯关-简单版》是一个基于java的布谷鸟闯关游戏,摁上键控制鸟的位置穿过管道间的缝隙,需要做碰撞检测,监听键盘...
    99+
    2024-04-02
  • HTML+JS实现猜拳游戏的示例代码
    目录效果图关于JS构建过程添加事件监听器函数 gameRules()函数 whoWon()效果图 游戏可以通过这个链接进入 关于JS构建过程 首先,我创建了一个对象,其中包含每种可...
    99+
    2024-04-02
  • Python实现21点小游戏的示例代码
    目录游戏玩法代码 - v1测试代码 - v2测试游戏玩法 游戏玩法: 该游戏由 2 到 6 个人玩,使用除大小王之外的 52 张牌, 游戏者的目标是使手中的牌的点数之和不超过 21 ...
    99+
    2024-04-02
  • C/C++实现精灵游戏的示例代码
    目录前言创建win32项目游戏效果核心代码前言 采用面向过程的遍程思想,通过acllib图形库来实现。 acllib下载地址:acllib tom,jerry,dog,heart以及...
    99+
    2024-04-02
  • Python实现炸金花游戏的示例代码
    今天的第二个作品,哈哈哈哈,搞起来感觉还挺有意思的,不过代码里纸牌J,Q,K,A几个数字被我替换成了11,12,13,14......主要是没有想到简单的办法让其比较,索性都用数字了...
    99+
    2024-04-02
  • Java实现贪吃蛇游戏的示例代码
    目录项目演示项目实战1. 游戏的主启动类2. 游戏的面板3. 数据中心4. 绘制静态面板5. 绘制静态小蛇6. 绘制动态小蛇7. 设置游戏状态8. 让蛇动起来9. 绘制食物布局10....
    99+
    2024-04-02
  • Java实现warcraft java版游戏的示例代码
    目录前言主要需求功能截图代码实现启动入口ModelAttacker类ModelUnit类总结前言 致敬经典的warcraft,《warcraft java版》是一款即时战略题材单机游...
    99+
    2024-04-02
  • Java实现扑克牌游戏的示例代码
    目录一、三人扑克二、具体实现Card类生成52张牌打乱顺序发牌三、完整代码一、三人扑克 想不想带上好朋友来上一局三人扑克呢。 二、具体实现 Card类 定义一个花色color变量和...
    99+
    2024-04-02
  • Java实现萝卜勇者游戏的示例代码
    目录前言主要设计功能截图代码实现启动类键盘监听核心算法总结前言 《萝卜勇者》是由国内玩家自制的一款独立游戏,玩家扮演萝卜勇士闯关,打败各种邪恶的敌人,获得最后的胜利。 《萝卜勇者》游...
    99+
    2024-04-02
  • Java+Swing实现五子棋游戏的示例代码
    目录一、系统介绍1.开发环境2.技术选型3.系统功能二、系统展示三、部分代码AI.javaChess.javaGobang.javaGobangListener.java一、系统介绍...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作