JavaScript实现Fly Bird小游戏


Posted in Javascript onDecember 15, 2016

本教程为大家分享了Fly Bird小游戏的制作流程,供大家参考,具体内容如下

1.分析页面结构,理清需求和功能

游戏有三个界面,分别是开始界面,游戏界面和游戏结束界面。

1.1 开始界面

JavaScript实现Fly Bird小游戏

start.gif

游戏的大背景
上下移动的游戏标题和翅膀摆动的小鸟
start 按钮,点击进入游戏界面
一直移动的地面

1.2 游戏界面

JavaScript实现Fly Bird小游戏

play.gif

显示越过障碍数量的计分器
移动的障碍物,分别是上管道和下管道
点击游戏界面,小鸟向上飞起,然后在重力作用下下坠,
当小鸟和管道碰撞后,结束界面弹出,同时小鸟落到地面

1.3 结束界面

GAMEOVER 提示面板
OK 按钮

2. 开发“开始界面”

考虑到草地的移动效果,我们在页面中加入两个草地

2.1 HTML

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8" />
  <title>Fly Bird</title>
  <link rel="stylesheet" type="text/css" href="css/index.css"/>
 </head>
 <body>
  <div id="wrapBg"> <!--游戏背景-->
   <div id="headTitle"> <!--开始标题-->
    <img id="headBird" src="img/bird0.png" alt="小鸟" /> <!--标题中的小鸟-->
   </div>
   <button id="startBtn" ></button> <!--开始按钮-->
   <div id="grassLand1"></div> <!--草地1-->
   <div id="grassLand2"></div> <!--草地2-->
  </div>
 </body>
</html>

2.2 CSS

#wrapBg{/*游戏背景*/
 width: 343px;height: 480px; 
 margin: 0 auto;
 background-image:url(../img/bg.jpg);
 position: relative;
 top: 100px;
 overflow: hidden;
}
#headTitle{/*开始标题*/
 width: 236px;height: 77px;
 background-image: url(../img/head.jpg);
 position: absolute; left: 53px; top: 100px;
}
#headBird{/*开始标题中的小鸟*/
 float:right;
 margin-top: 25px;
}
#startBtn{/*开始按钮*/
 width: 85px;height: 29px;
 padding: 0;margin: 0;
 background-image: url(../img/start.jpg);
 position: absolute;left: 129px;top: 250px;
}
#grassLand1{/*草地1*/
 height: 14px;width: 343px;
 background-image: url(../img/banner.jpg);
 position: absolute;top: 423px;
}
#grassLand2{/*草地2*/
 height: 14px;width: 343px;
 background-image: url(../img/banner.jpg);
 position: absolute;top: 423px;left: 343px;
}

将wrapBg中的overflow:hidden 注释掉的页面效果

JavaScript实现Fly Bird小游戏

开始界面.jpg

2.3 JS

小鸟煽动翅膀的效果需要用到逐帧动画的原理
逐帧动画是一种常见的动画形式(Frame By Frame),其原理是在“连续的关键帧”中分解动画动作,也就是在时间轴的每帧上逐帧绘制不同的内容,使其连续播放而成动画。

JavaScript实现Fly Bird小游戏

2.3.1 开始标题的摆动

var jsHeadTitle = document.getElementById("headTitle");// 获取标题
  var jsHeadBird = document.getElementById("headBird"); // 获取标题中小鸟

  var Y = 3;//标题的摆动幅度
  var index = 0;
  var imgArr = ["img/bird0.png","img/bird1.png"] 
  //将小鸟图片路径放入一个数组,利用逐帧动画的原理做出小鸟翅膀摆动的样子
  var headWaveTimer = setInterval(headWave,200); //设置标题上下摆动的定时器
  function headWave() {
   Y *= -1;
   jsHeadTitle.style.top = jsHeadTitle.offsetTop + Y + "px";
   jsHeadBird.src = imgArr[index++];
   if (index == 2) {
    index = 0;
   }
  }

2.3.2 移动的草地

var jsGrassLand1 = document.getElementById("grassLand1"); //获取草地1
  var jsGrassLand2 = document.getElementById("grassLand2"); //获取草地2

  var landTimer = setInterval(landRun,30); //让草地动起来的定时器
  function landRun() {
   if (jsGrassLand1.offsetLeft <= -343) {
    jsGrassLand1.style.left = "343px";
   }
   if (jsGrassLand2.offsetLeft <= -343) {
    jsGrassLand2.style.left = "343px";
   }
   jsGrassLand1.style.left = jsGrassLand1.offsetLeft - 3 + "px";
   jsGrassLand2.style.left = jsGrassLand2.offsetLeft - 3 + "px";
  }

2.3.3 Start按键

var jsStartBtn = document.getElementById("startBtn");
  jsStartBtn.onclick = function() { //为start按键添加点击事件处理程序
   jsHeadTitle.style.display = "none"; //隐藏标题
   clearInterval(headWaveTimer); //关闭让标题摆动的定时器
   jsStartBtn.style.display = "none"; //隐藏按键
   //待添加功能
   //点击开始按键进入游戏界面
  }

完成后的效果(注释掉了wrapBg中的overflow:hidden )

JavaScript实现Fly Bird小游戏

start01.gif

接下来我们开发“游戏界面”
3. “游戏界面”的开发
游戏界面中有三样元素,分别是“小鸟”,“障碍”,和“计分器”,我们依次来创建相应的对象。
3.1 小鸟
首先,创建小鸟的对象, bird.js 文件。

var bird = {
 flyTimer:null,//小鸟飞翔定时器
 wingTimer:null,//小鸟翅膀摆动定时器

 div:document.createElement("div"),
 showBird:function(parentObj) {
  this.div.style.width = "40px";
  this.div.style.height = "28px";
  this.div.style.backgroundImage = "url(img/bird0.png)";
  this.div.style.backgroundRepeat = "no-repeat";
  this.div.style.position = "absolute";
  this.div.style.left = "50px";
  this.div.style.top = "200px";
  this.div.style.zIndex = "1";

  parentObj.appendChild(this.div); //将小鸟DIV插入游戏界面中
 },

 fallSpeed: 0, //小鸟下落速度
 flyBird: function(){ //控制小鸟飞翔下落的函数
  bird.flyTimer = setInterval(fly,40);
  function fly() {
   bird.div.style.top = bird.div.offsetTop + bird.fallSpeed++ + "px";
   if (bird.div.offsetTop < 0) { 
    bird.fallSpeed = 2; //这里用于控制小鸟不要飞出界面
   }
   if (bird.div.offsetTop >= 395) {
    bird.fallSpeed = 0;
    clearInterval(bird.flyTimer); //一旦飞到地面,清除定时器
    clearInterval(bird.wingTimer); //清除翅膀摆动定时器
   }
   if (bird.fallSpeed > 12) {
    bird.fallSpeed = 12; //鸟的最大下落速度控制在12
   }
  }
 },

 wingWave: function() { //控制小鸟煽动翅膀的函数
  var up = ["url(img/up_bird0.png)", "url(img/up_bird1.png)"];
  var down = ["url(img/down_bird0.png)", "url(img/down_bird1.png)"];
  var i = 0, j = 0;
  bird.wingTimer = setInterval(wing,120);//逐帧动画,小鸟煽动翅膀
  function wing() {
   if (bird.fallSpeed > 0) {
    bird.div.style.backgroundImage = down[i++];
    if (i==2) {i = 0}
   }if (bird.fallSpeed < 0) {
    bird.div.style.backgroundImage = up[j++];
    if (j==2) {j = 0}
   }
  }
 }, 
};

下面,实现点击start按钮时,加载小鸟。(在之前的代码基础上添加)

jsStartBtn.onclick = function() { //为start按键添加点击事件处理程序
 jsHeadTitle.style.display = "none"; //隐藏标题
 clearInterval(headWaveTimer); //关闭让标题摆动的定时器
 jsStartBtn.style.display = "none"; //隐藏按键
 bird.showBird(jsWrapBg); //插入小鸟到界面中
 bird.flyBird(); //控制小鸟飞翔下落
 bird.wingWave(); //逐帧动画,小鸟煽动翅膀
 jsWrapBg.onclick = function(){
  bird.fallSpeed = -8;
 };
 //待添加功能
 //点击开始按键进入游戏界面
}

添加小鸟后的效果

JavaScript实现Fly Bird小游戏

play01.gif

3.2 障碍(上方水管和下方水管)

JavaScript实现Fly Bird小游戏

block示意图.png

障碍分为上方管道和下方管道,如示意图所示结构嵌套,这样就可以通过随机设置DownDiv2的高度和gapHeight的高度,来改变生成障碍的形态
block.js

function Block() {
 this.upDivWrap = null;
 this.downDivWrap = null;
 this.downHeight = baseObj.randomNum(0,150);
 this.gapHeight = baseObj.randomNum(150,160);
 this.upHeight = 312 - this.downHeight - this.gapHeight;

 // 用来生成Div的方法
 this.createDiv = function(url, height, positionType, left, top) {
  var newDiv = document.createElement("div");
  newDiv.style.width = "62px";
  newDiv.style.height = height;
  newDiv.style.position = positionType;
  newDiv.style.left = left;
  newDiv.style.top = top;
  newDiv.style.backgroundImage = url; //"url(/img/0.jpg)"
  return newDiv;
 };

 this.createBlock = function() {
  var upDiv1 = this.createDiv("url(img/up_mod.png)", this.upHeight + "px");
  var upDiv2 = this.createDiv("url(img/up_pipe.png)", "60px");
  this.upDivWrap = this.createDiv(null, null, "absolute", "450px");
  this.upDivWrap.appendChild(upDiv1);
  this.upDivWrap.appendChild(upDiv2);//生成上方管道

  var downDiv1 = this.createDiv("url(img/down_pipe.png)", "60px");
  var downDiv2 = this.createDiv("url(img/down_mod.png)", this.downHeight +"px");
  this.downDivWrap = this.createDiv(null, null, "absolute", "450px", 363 - this.downHeight + "px");
  this.downDivWrap.appendChild(downDiv1);
  this.downDivWrap.appendChild(downDiv2); //生成下方的管道

  jsWrapBg.appendChild(this.upDivWrap);
  jsWrapBg.appendChild(this.downDivWrap);
 };

 this.moveBlock = function() { //控制管道移动的方法
  this.upDivWrap.style.left = this.upDivWrap.offsetLeft - 3 + "px";
  this.downDivWrap.style.left = this.downDivWrap.offsetLeft - 3 + "px";
 }; 
}

公共对象文件 baseObj.js ,用来提供随机数,和两个矩形div的碰撞检测

var baseObj = {
 //随机数
 randomNum: function(min, max) {
  return parseInt(Math.random() * (max - min + 1) + min);
 },

 //两个矩形元素之间的碰撞检测
 rectangleCrashExamine: function (obj1, obj2) {
   var obj1Left = obj1.offsetLeft;
   var obj1Width = obj1.offsetLeft + obj1.offsetWidth;
   var obj1Top = obj1.offsetTop;
   var obj1Height = obj1.offsetTop + obj1.offsetHeight;

   var obj2Left = obj2.offsetLeft;
   var obj2Width = obj2.offsetLeft + obj2.offsetWidth;
   var obj2Top = obj2.offsetTop;
   var obj2Height = obj2.offsetTop + obj2.offsetHeight;

   if (!(obj1Left > obj2Width || obj1Width < obj2Left || obj1Top > obj2Height || obj1Height < obj2Top)) {
    return true;
   }
   return false;
 },
};

下面我的想法是在start按钮点击的时候创建一个block,把这个block存储到数组 blocksArr 中,在 landTimer 定时器的方法 landRun 中检查此数组的长度,如果数组不为空数组,那么就让数组中所有的block移动。
检查最后一个block离开的距离,达到一定距离,就重新new 一个block,添加到数组。
检查第一个block,一旦达到一定位置,就在结构中移除downDivWrap 和 upDivWrap,同时在数组中删除。

var landTimer = setInterval(landRun,30); //让草地动起来的定时器
  function landRun() {
   if (jsGrassLand1.offsetLeft <= -343) {
    jsGrassLand1.style.left = "343px";
   }
   if (jsGrassLand2.offsetLeft <= -343) {
    jsGrassLand2.style.left = "343px";
   }
   jsGrassLand1.style.left = jsGrassLand1.offsetLeft - 3 + "px";
   jsGrassLand2.style.left = jsGrassLand2.offsetLeft - 3 + "px";

   if (blocksArr.length) {
    for (var i = 0; i < blocksArr.length; i++) {
     blocksArr[i].moveBlock();
     var x =baseObj.rectangleCrashExamine(blocksArr[i].downDivWrap, bird.div);
     var y = baseObj.rectangleCrashExamine(blocksArr[i].upDivWrap, bird.div);
     var z = bird.div.offsetTop >= 390;
     if (x || y || z) {
      window.clearInterval(landTimer);//清除landTimer定时器
      bird.fallSpeed = 0; //小鸟下落
      jsWrapBg.onclick = null; //消除点击事件

     }
    }
    if (blocksArr[blocksArr.length - 1].downDivWrap.offsetLeft < (450 - blockDistance)) {
      blockDistance = baseObj.randomNum(130,250);
      var newBlock = new Block();
      newBlock.createBlock();
      blocksArr.push(newBlock);
    }

    if (blocksArr[0].downDivWrap.offsetLeft < -50) {
      jsWrapBg.removeChild(blocksArr[0].downDivWrap);
      jsWrapBg.removeChild(blocksArr[0].upDivWrap);
      blocksArr.shift(blocksArr[0]);
    }
   }
  }

当前的游戏效果

JavaScript实现Fly Bird小游戏

play02.gif

3.3 计分器

游戏中的计分器相对较好实现    

<div id="score">
    <div id="num1"></div>
    <div id="num2"></div>
    <div id="num3"></div>
   </div>
  var jsScore = document.getElementById("score");
  var jsNum1 = document.getElementById("num1");
  var jsNum2 = document.getElementById("num2");
  var jsNum3 = document.getElementById("num3");
  var score = 0;

今天先这样了,改天再写。哈哈

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Google排名中的10个最著名的 JavaScript库
Apr 27 Javascript
基于jquery的滑动样例代码
Nov 20 Javascript
document.documentElement和document.body区别介绍
Sep 16 Javascript
ie8下修改input的type属性报错的解决方法
Sep 16 Javascript
Javascript核心读书有感之语言核心
Feb 01 Javascript
JS从一组数据中找到指定的单条数据的方法
Jun 02 Javascript
Vue 进阶教程之v-model详解
May 06 Javascript
JS简单获得节点元素的方法示例
Feb 10 Javascript
微信小程序实现分享到朋友圈功能
Jul 19 Javascript
webpack安装配置与常见使用过程详解(结合vue)
Jun 01 Javascript
微信小程序实现多选框功能的实例代码
Jun 24 Javascript
JS如何在不同平台实现多语言方式
Jul 16 Javascript
JS中对数组元素进行增删改移的方法总结
Dec 15 #Javascript
JS去除重复并统计数量的实现方法
Dec 15 #Javascript
javascript基于原型链的继承及call和apply函数用法分析
Dec 15 #Javascript
移动端脚本框架Hammer.js
Dec 15 #Javascript
WEB开发之注册页面验证码倒计时代码的实现
Dec 15 #Javascript
浅谈javascript alert和confirm的美化
Dec 15 #Javascript
JavaScript模板引擎Template.js使用详解
Dec 15 #Javascript
You might like
利用 window_onload 实现select默认选择
2006/10/09 PHP
php遍历CSV类实例
2015/04/14 PHP
PHP goto语句用法实例
2019/08/06 PHP
js打开新窗口方法整理
2014/02/17 Javascript
ECMAScript5中的对象存取器属性:getter和setter介绍
2014/12/08 Javascript
javacript使用break内层跳出外层循环分析
2015/01/12 Javascript
提交按钮的name='submit'引起的js失效问题及原因
2015/02/25 Javascript
js仿苹果iwatch外观的计时器代码分享
2015/08/26 Javascript
javascript实现无缝上下滚动特效
2015/12/16 Javascript
原生javascript实现自动更新的时间日期
2016/02/12 Javascript
Js的Array数组对象详解
2016/02/22 Javascript
浅谈EasyUI常用控件的禁用方法
2016/11/09 Javascript
浅谈js数组和splice的用法
2016/12/04 Javascript
详解AngularJS脏检查机制及$timeout的妙用
2017/06/19 Javascript
微信小程序利用swiper+css实现购物车商品删除功能
2019/03/06 Javascript
javascript自定义日期比较函数用法示例
2019/07/22 Javascript
js实现旋转的星空效果
2019/11/01 Javascript
python实现的udp协议Server和Client代码实例
2014/06/04 Python
python写xml文件的操作实例
2014/10/05 Python
对pandas的dataframe绘图并保存的实现方法
2017/08/05 Python
详解Python 协程的详细用法使用和例子
2018/06/15 Python
python实现简单登陆系统
2018/10/18 Python
python3.6实现学生信息管理系统
2019/02/21 Python
用Python实现将一张图片分成9宫格的示例
2019/07/05 Python
python图片指定区域替换img.paste函数的使用
2020/04/09 Python
美国最大婚纱连锁店运营商:David’s Bridal
2019/03/12 全球购物
汽车运用工程毕业生自荐信
2013/10/29 职场文书
建筑公司员工自我鉴定
2014/04/08 职场文书
民族团结先进集体事迹材料
2014/05/22 职场文书
北京爱情故事观后感
2015/06/12 职场文书
python中Tkinter 窗口之输入框和文本框的实现
2021/04/12 Python
javascript数组includes、reduce的基本使用
2021/07/02 Javascript
Python之matplotlib绘制折线图
2022/04/13 Python
Python Matplotlib绘制两个Y轴图像
2022/04/13 Python
Hive导入csv文件示例
2022/06/25 数据库
Pygame游戏开发之太空射击实战敌人精灵篇
2022/08/05 Python