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 相关文章推荐
javascript模拟评分控件实现方法
May 13 Javascript
JavaScript+html5 canvas实现图片破碎重组动画特效
Feb 22 Javascript
Javascript点击按钮随机改变数字与其颜色
Sep 01 Javascript
Angular2中select用法之设置默认值与事件详解
May 07 Javascript
简单两步使用node发送qq邮件的方法
Mar 01 Javascript
javascript中call()、apply()的区别
Mar 21 Javascript
setTimeout与setInterval的区别浅析
Mar 23 Javascript
基于vue如何发布一个npm包的方法步骤
May 15 Javascript
ES6中let、const的区别及变量的解构赋值操作方法实例分析
Oct 15 Javascript
JS一次前端面试经历记录
Mar 19 Javascript
vue 使用原生组件上传图片的实例
Sep 08 Javascript
vue切换菜单取消未完成接口请求的案例
Nov 13 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 PDO函数库详解
2010/04/27 PHP
shopex主机报错误请求解决方案(No such file or directory)
2011/12/27 PHP
php中mysql连接和基本操作代码(快速测试使用,简单方便)
2014/04/25 PHP
yii框架配置默认controller和action示例
2014/04/30 PHP
PHP使用MPDF类生成PDF的方法
2015/12/08 PHP
Yii中的relations数据关联查询及统计功能用法详解
2016/07/14 PHP
基于PHP制作验证码
2016/10/12 PHP
js汉字排序问题 支持中英文混排,兼容各浏览器,包括CHROME
2011/12/20 Javascript
js 使FORM表单的所有元素不可编辑的示例代码
2013/10/17 Javascript
AngularJS通过$location获取及改变当前页面的URL
2016/09/23 Javascript
预防网页挂马的方法总结
2016/11/03 Javascript
javascript兼容性(实例讲解)
2017/08/15 Javascript
利用ES6的Promise.all实现至少请求多长时间的实例
2017/08/28 Javascript
Vue 中mixin 的用法详解
2018/04/23 Javascript
JS对象与json字符串相互转换实现方法示例
2018/06/14 Javascript
Vue.js实现的购物车功能详解
2019/01/27 Javascript
vue实现鼠标移入移出事件代码实例
2019/03/27 Javascript
微信小程序开发之点击按钮退出小程序的实现方法
2019/04/26 Javascript
node.js的http.createServer过程深入解析
2019/06/06 Javascript
Vue 打包的静态文件不能直接运行的原因及解决办法
2020/11/19 Vue.js
python中mechanize库的简单使用示例
2014/01/10 Python
django传值给模板, 再用JS接收并进行操作的实例
2018/05/28 Python
深入浅析Python中的迭代器
2019/06/04 Python
django实现用户注册实例讲解
2019/10/30 Python
TensorFlow实现checkpoint文件转换为pb文件
2020/02/10 Python
python 识别登录验证码图片功能的实现代码(完整代码)
2020/07/03 Python
彼得罗夫美国官网:Peter Thomas Roth美国(青瓜面膜)
2017/11/05 全球购物
美国在线轮胎零售商:SimpleTire
2019/04/08 全球购物
匡威西班牙官网:Converse西班牙
2019/10/01 全球购物
大学生作弊检讨书
2014/02/19 职场文书
《珍珠泉》教学反思
2014/02/20 职场文书
竞选团支书演讲稿
2014/04/28 职场文书
学习普通话的体会
2014/11/07 职场文书
六一儿童节园长致辞
2015/07/31 职场文书
2015年公司中秋节致辞
2015/07/31 职场文书
解决Goland 同一个package中函数互相调用的问题
2021/05/06 Golang