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 相关文章推荐
8个实用的jQuery技巧
Mar 04 Javascript
jQuery实现的指纹扫描效果实例(附演示与demo源码下载)
Jan 26 Javascript
移动端js图片查看器
Nov 17 Javascript
JS实现图片垂直居中显示小结
Dec 13 Javascript
jQuery实现的鼠标滚轮控制图片缩放功能实例
Oct 14 jQuery
vue下history模式刷新后404错误解决方法
Aug 18 Javascript
ndm:NPM的桌面GUI应用程序
Oct 15 Javascript
Vue CLI3.0中使用jQuery和Bootstrap的方法
Feb 28 jQuery
微信小程序生成分享海报方法(附带二维码生成)
Mar 29 Javascript
JS中call()和apply()的功能及用法实例分析
Jun 28 Javascript
vue学习笔记之Vue中css动画原理简单示例
Feb 29 Javascript
JS canvas实现画板和签字板功能
Feb 23 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
PHP执行速率优化技巧小结
2008/03/15 PHP
PHP header函数分析详解
2011/08/06 PHP
选择PHP作为网站开发语言的原因分享
2012/01/03 PHP
列举PHP的Yii 2框架的开发优势
2015/07/03 PHP
php记录搜索引擎爬行记录的实现代码
2018/03/02 PHP
List Information About the Binary Files Used by an Application
2007/06/18 Javascript
js中的for如何实现foreach中的遍历
2014/05/31 Javascript
究竟什么是Node.js?Node.js有什么好处?
2015/05/29 Javascript
js简单实现Select互换数据的方法
2015/08/17 Javascript
JavaScript代码轻松实现网页内容禁止复制(代码简单)
2015/10/23 Javascript
JavaScript操作URL的相关内容集锦
2015/10/29 Javascript
JavaScript操作XML/HTML比较常用的对象属性集锦
2015/10/30 Javascript
ui组件之input多选下拉实现方法(带有搜索功能)
2016/07/14 Javascript
AngularJs bootstrap搭载前台框架——基础页面
2016/09/01 Javascript
详解JavaScript中数组的reduce方法
2016/12/02 Javascript
详解mpvue中小程序自定义导航组件开发指南
2019/02/11 Javascript
vue实现pdf文档在线预览功能
2019/11/26 Javascript
[01:02:46]VGJ.S vs NB 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
[01:18:45]DOTA2-DPC中国联赛 正赛 DLG vs Dragon BO3 第三场2月1日
2021/03/11 DOTA
Python实现过滤单个Android程序日志脚本分享
2015/01/16 Python
python 求一个列表中所有元素的乘积实例
2019/06/11 Python
基于pandas中expand的作用详解
2019/12/17 Python
python3中sys.argv的实例用法
2020/04/24 Python
最新Python idle下载、安装与使用教程图文详解
2020/11/28 Python
三星印度官网:Samsung印度
2019/08/03 全球购物
介绍一下Java中的static关键字
2012/05/12 面试题
冰淇淋店的创业计划书
2014/02/07 职场文书
办公室主任职责范本
2014/03/07 职场文书
爱心活动计划书
2014/04/26 职场文书
2014年优质护理服务工作总结
2014/11/14 职场文书
又涨知识了,自律到底多重要?
2019/06/27 职场文书
2019年妇科护士的自我鉴定(3篇)
2019/09/26 职场文书
导游词之沈阳植物园
2019/11/30 职场文书
go:垃圾回收GC触发条件详解
2021/04/24 Golang
如何使用PyCharm及常用配置详解
2021/06/03 Python
Python中22个万用公式的小结
2021/07/21 Python