国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > JavaScript > 正文

JavaScript實(shí)現(xiàn)Fly Bird小游戲

2019-11-19 18:28:22
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本教程為大家分享了Fly Bird小游戲的制作流程,供大家參考,具體內(nèi)容如下

1.分析頁(yè)面結(jié)構(gòu),理清需求和功能

游戲有三個(gè)界面,分別是開(kāi)始界面,游戲界面和游戲結(jié)束界面。

1.1 開(kāi)始界面

start.gif

游戲的大背景
上下移動(dòng)的游戲標(biāo)題和翅膀擺動(dòng)的小鳥(niǎo)
start 按鈕,點(diǎn)擊進(jìn)入游戲界面
一直移動(dòng)的地面

1.2 游戲界面

play.gif

顯示越過(guò)障礙數(shù)量的計(jì)分器
移動(dòng)的障礙物,分別是上管道和下管道
點(diǎn)擊游戲界面,小鳥(niǎo)向上飛起,然后在重力作用下下墜,
當(dāng)小鳥(niǎo)和管道碰撞后,結(jié)束界面彈出,同時(shí)小鳥(niǎo)落到地面

1.3 結(jié)束界面

GAMEOVER 提示面板
OK 按鈕

2. 開(kāi)發(fā)“開(kāi)始界面”

考慮到草地的移動(dòng)效果,我們?cè)陧?yè)面中加入兩個(gè)草地

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"> <!--開(kāi)始標(biāo)題-->    <img id="headBird" src="img/bird0.png" alt="小鳥(niǎo)" /> <!--標(biāo)題中的小鳥(niǎo)-->   </div>   <button id="startBtn" ></button> <!--開(kāi)始按鈕-->   <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{/*開(kāi)始標(biāo)題*/ width: 236px;height: 77px; background-image: url(../img/head.jpg); position: absolute; left: 53px; top: 100px;}#headBird{/*開(kāi)始標(biāo)題中的小鳥(niǎo)*/ float:right; margin-top: 25px;}#startBtn{/*開(kāi)始按鈕*/ 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 注釋掉的頁(yè)面效果

開(kāi)始界面.jpg

2.3 JS

小鳥(niǎo)煽動(dòng)翅膀的效果需要用到逐幀動(dòng)畫(huà)的原理
逐幀動(dòng)畫(huà)是一種常見(jiàn)的動(dòng)畫(huà)形式(Frame By Frame),其原理是在“連續(xù)的關(guān)鍵幀”中分解動(dòng)畫(huà)動(dòng)作,也就是在時(shí)間軸的每幀上逐幀繪制不同的內(nèi)容,使其連續(xù)播放而成動(dòng)畫(huà)。

2.3.1 開(kāi)始標(biāo)題的擺動(dòng)

 var jsHeadTitle = document.getElementById("headTitle");// 獲取標(biāo)題  var jsHeadBird = document.getElementById("headBird"); // 獲取標(biāo)題中小鳥(niǎo)  var Y = 3;//標(biāo)題的擺動(dòng)幅度  var index = 0;  var imgArr = ["img/bird0.png","img/bird1.png"]   //將小鳥(niǎo)圖片路徑放入一個(gè)數(shù)組,利用逐幀動(dòng)畫(huà)的原理做出小鳥(niǎo)翅膀擺動(dòng)的樣子  var headWaveTimer = setInterval(headWave,200); //設(shè)置標(biāo)題上下擺動(dòng)的定時(shí)器  function headWave() {   Y *= -1;   jsHeadTitle.style.top = jsHeadTitle.offsetTop + Y + "px";   jsHeadBird.src = imgArr[index++];   if (index == 2) {    index = 0;   }  }

2.3.2 移動(dòng)的草地

  var jsGrassLand1 = document.getElementById("grassLand1"); //獲取草地1  var jsGrassLand2 = document.getElementById("grassLand2"); //獲取草地2  var landTimer = setInterval(landRun,30); //讓草地動(dòng)起來(lái)的定時(shí)器  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按鍵添加點(diǎn)擊事件處理程序   jsHeadTitle.style.display = "none"; //隱藏標(biāo)題   clearInterval(headWaveTimer); //關(guān)閉讓標(biāo)題擺動(dòng)的定時(shí)器   jsStartBtn.style.display = "none"; //隱藏按鍵   //待添加功能   //點(diǎn)擊開(kāi)始按鍵進(jìn)入游戲界面  }

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

start01.gif

接下來(lái)我們開(kāi)發(fā)“游戲界面”
3. “游戲界面”的開(kāi)發(fā)
游戲界面中有三樣元素,分別是“小鳥(niǎo)”,“障礙”,和“計(jì)分器”,我們依次來(lái)創(chuàng)建相應(yīng)的對(duì)象。
3.1 小鳥(niǎo)
首先,創(chuàng)建小鳥(niǎo)的對(duì)象, bird.js 文件。

var bird = { flyTimer:null,//小鳥(niǎo)飛翔定時(shí)器 wingTimer:null,//小鳥(niǎo)翅膀擺動(dòng)定時(shí)器 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); //將小鳥(niǎo)DIV插入游戲界面中 }, fallSpeed: 0, //小鳥(niǎo)下落速度 flyBird: function(){ //控制小鳥(niǎo)飛翔下落的函數(shù)  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; //這里用于控制小鳥(niǎo)不要飛出界面   }   if (bird.div.offsetTop >= 395) {    bird.fallSpeed = 0;    clearInterval(bird.flyTimer); //一旦飛到地面,清除定時(shí)器    clearInterval(bird.wingTimer); //清除翅膀擺動(dòng)定時(shí)器   }   if (bird.fallSpeed > 12) {    bird.fallSpeed = 12; //鳥(niǎo)的最大下落速度控制在12   }  } }, wingWave: function() { //控制小鳥(niǎo)煽動(dòng)翅膀的函數(shù)  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);//逐幀動(dòng)畫(huà),小鳥(niǎo)煽動(dòng)翅膀  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}   }  } }, };

下面,實(shí)現(xiàn)點(diǎn)擊start按鈕時(shí),加載小鳥(niǎo)。(在之前的代碼基礎(chǔ)上添加)

jsStartBtn.onclick = function() { //為start按鍵添加點(diǎn)擊事件處理程序 jsHeadTitle.style.display = "none"; //隱藏標(biāo)題 clearInterval(headWaveTimer); //關(guān)閉讓標(biāo)題擺動(dòng)的定時(shí)器 jsStartBtn.style.display = "none"; //隱藏按鍵 bird.showBird(jsWrapBg); //插入小鳥(niǎo)到界面中 bird.flyBird(); //控制小鳥(niǎo)飛翔下落 bird.wingWave(); //逐幀動(dòng)畫(huà),小鳥(niǎo)煽動(dòng)翅膀 jsWrapBg.onclick = function(){  bird.fallSpeed = -8; }; //待添加功能 //點(diǎn)擊開(kāi)始按鍵進(jìn)入游戲界面}

添加小鳥(niǎo)后的效果

play01.gif

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

block示意圖.png

障礙分為上方管道和下方管道,如示意圖所示結(jié)構(gòu)嵌套,這樣就可以通過(guò)隨機(jī)設(shè)置DownDiv2的高度和gapHeight的高度,來(lái)改變生成障礙的形態(tài)
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; // 用來(lái)生成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() { //控制管道移動(dòng)的方法  this.upDivWrap.style.left = this.upDivWrap.offsetLeft - 3 + "px";  this.downDivWrap.style.left = this.downDivWrap.offsetLeft - 3 + "px"; }; }

公共對(duì)象文件 baseObj.js ,用來(lái)提供隨機(jī)數(shù),和兩個(gè)矩形div的碰撞檢測(cè)

var baseObj = { //隨機(jī)數(shù) randomNum: function(min, max) {  return parseInt(Math.random() * (max - min + 1) + min); }, //兩個(gè)矩形元素之間的碰撞檢測(cè) 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按鈕點(diǎn)擊的時(shí)候創(chuàng)建一個(gè)block,把這個(gè)block存儲(chǔ)到數(shù)組 blocksArr 中,在 landTimer 定時(shí)器的方法 landRun 中檢查此數(shù)組的長(zhǎng)度,如果數(shù)組不為空數(shù)組,那么就讓數(shù)組中所有的block移動(dòng)。
檢查最后一個(gè)block離開(kāi)的距離,達(dá)到一定距離,就重新new 一個(gè)block,添加到數(shù)組。
檢查第一個(gè)block,一旦達(dá)到一定位置,就在結(jié)構(gòu)中移除downDivWrap 和 upDivWrap,同時(shí)在數(shù)組中刪除。

  var landTimer = setInterval(landRun,30); //讓草地動(dòng)起來(lái)的定時(shí)器  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定時(shí)器      bird.fallSpeed = 0; //小鳥(niǎo)下落      jsWrapBg.onclick = null; //消除點(diǎn)擊事件     }    }    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]);    }   }  }

當(dāng)前的游戲效果

play02.gif

3.3 計(jì)分器

游戲中的計(jì)分器相對(duì)較好實(shí)現(xiàn)    

  <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;

今天先這樣了,改天再寫(xiě)。哈哈

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 浠水县| 丹阳市| 庄河市| 汉中市| 新和县| 塘沽区| 台东市| 南昌市| 抚顺县| 罗田县| 穆棱市| 曲水县| 新泰市| 永年县| 滦平县| 自贡市| 墨江| 威海市| 潜江市| 五寨县| 鹤峰县| 西宁市| 农安县| 西丰县| 苏尼特右旗| 保亭| 肥东县| 陈巴尔虎旗| 扬州市| 忻州市| 桂林市| 东乌珠穆沁旗| 监利县| 泉州市| 宜阳县| 南城县| 山阳县| 斗六市| 扎兰屯市| 威海市| 丹东市|