JavaScript实现Fly Bird小游戏

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 )

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 (i2) {i = 0} }if (bird.fallSpeed < 0) { bird.div.style.backgroundImage = up[j++]; if (j2) {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;

};

//待添加功能

//点击开始按键进入游戏界面

}

添加小鸟后的效果

play01.gif

3.2 障碍(上管道和下管道)

block示意图.png

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

block.js

function Block() {

this.upDivWrap = null;

this.downDivWrap = null;

this.downHeight = baseObj.randomNum(0,150);//随机生成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,同时在数组中删除block。

var blocksArr = [];

var blockDistance = baseObj.randomNum(130,250);

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

}

}

}

当前的游戏效果

play02.gif

3.3 计分器

游戏中的计分器相对较好实现,我们就实现最大为三位数的计分器吧。

html

css样式

#score{ position:absolute; left: 130px; top:50px; z-index: 1; } #score div{ height: 39px; width: 28px; float: left; background-image: url(…/img/0.jpg); display: none; }

js

var jsScore = document.getElementById(“score”);

var jsNum1 = document.getElementById(“num1”);

var jsNum2 = document.getElementById(“num2”);

var jsNum3 = document.getElementById(“num3”);

var score = 0;

实现计数器功能,最重要的是如何判断走过水管的数量,我们以水管的位置来判断。bird的定位left为50px,水管的宽度是62px,当水管越过小鸟的时候,水管距离它父级的定位offsetLeft 是 -12px。每当有一个水管到达此位置,score++;

在start按钮的事件处理程序中加入

jsNum1.style.display = “block”;// 在点击开始之后,让计数器显示出来。

if (blocksArr[0].downDivWrap.offsetLeft == -12) {

score++;//积分面板

if (score < 10) {

jsNum1.style.backgroundImage = “url(img/” + score + “.jpg)”;

} else if (score < 100) {

jsNum2.style.display = “block”;

jsNum1.style.backgroundImage = “url(img/” + parseInt(score/10) + “.jpg)”;

jsNum2.style.backgroundImage = “url(img/” + score%10 + “.jpg)”;

} else if (score < 1000) {

jsNum3.style.display = “block”;

jsNum1.style.backgroundImage = “url(img/” + parseInt(score/100) + “.jpg)”;

jsNum2.style.backgroundImage = “url(img/” + parseInt(score/10)%10 + “.jpg)”;

jsNum3.style.backgroundImage = “url(img/” + score%10 + “.jpg)”;

}

console.log(score);

}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

前端校招精编面试解析大全点击这里获取完整版pdf查看

自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-RFEicuNQ-1712926644281)]

[外链图片转存中…(img-1CRN04sl-1712926644282)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

[外链图片转存中…(img-0aUxpTR6-1712926644282)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

前端校招精编面试解析大全点击这里获取完整版pdf查看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值