Le jeu dispose de trois interfaces, à savoir l'interface de démarrage, l'interface de jeu et l'interface de fin de jeu.
L'arrière-plan du jeu
Le titre du jeu monte et descend et l'oiseau aux ailes battantes
Bouton Démarrer, cliquez pour entrer dans l'interface du jeu
Le sol qui ne cesse de bouger
Score indiquant le nombre d'obstacles franchis
Les obstacles mobiles sont le tuyau supérieur et le tuyau inférieur
Cliquez sur l'interface du jeu, l'oiseau vole vers le haut puis tombe sous l'action de la gravité
Lorsque l'oiseau entre en collision avec le tuyau, l'interface finale apparaît et l'oiseau tombe. mis à la terre en même temps
Panneau d'invite de jeu
Bouton OK
Considérant l'effet de mouvement de l'herbe, nous avons ajouté deux champs d'herbe à la page
<!DOCTYPE html><html><head><meta charset="utf-8" /><title>Fly Bird</title><link rel="stylesheet" type="text/css" href="css/index.css?1.1.11"/></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>
#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; }
L'effet de page du débordement de commentaires : caché dans wrapBg
oiseau L'effet du battement d'ailes nécessite l'utilisation du principe de l'animation image par image
L'animation image par image est une forme courante d'animation (Frame By Frame). Son principe est de décomposer l'animation en "images clés continues", c'est-à-dire de dessiner différents contenus image par image sur chaque image de la timeline, afin qu'elle puisse être jouée en continu pour former une animation. .
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; } }
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"; }
var jsStartBtn = document.getElementById("startBtn"); jsStartBtn.onclick = function() { //为start按键添加点击事件处理程序 jsHeadTitle.style.display = "none"; //隐藏标题 clearInterval(headWaveTimer); //关闭让标题摆动的定时器 jsStartBtn.style.display = "none"; //隐藏按键//待添加功能//点击开始按键进入游戏界面 }
L'effet fini (Commenter overflow:hidden in wrapBg)
Ensuite, nous développons "l'interface de jeu"
Il y a trois éléments dans l'interface de jeu, à savoir "oiseau", "obstacle" et "score". Nous créerons tour à tour l'objet correspondant.
Tout d'abord, créez l'objet oiseau, le fichier 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} } } }, };
Ensuite, chargez l'oiseau lorsque vous cliquez sur le bouton Démarrer. (Ajouté en fonction du code précédent)
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; };//待添加功能//点击开始按键进入游戏界面 }
L'effet après l'ajout de l'oiseau
Les obstacles sont divisés en tuyau supérieur et tuyau inférieur, Comme le montre le diagramme schématique, la structure est imbriquée, de sorte que la forme de l'obstacle généré puisse être modifiée en définissant aléatoirement la hauteur de DownDiv2 et la hauteur de 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"; }; }
Fichier d'objet public baseObj.js, utilisé pour fournir des nombres aléatoires et une détection de collision entre deux divs rectangulaires
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; }, };
Mon idée ci-dessous est de créer un bloc lorsque vous cliquez sur le bouton Démarrer et de stocker ce bloc dans le tableau blocksArr , vérifiez la longueur de ce tableau dans landTimer méthode timer landRun Si le tableau n'est pas un tableau vide, laissez tous les blocs du tableau se déplacer.
Vérifiez la distance laissée par le dernier bloc du tableau. Lorsqu'il atteint une certaine distance, créez un nouveau bloc et ajoutez-le au tableau.
Vérifiez le premier bloc du tableau. Une fois qu'il atteint une certaine position, supprimez downDivWrap et upDivWrap dans la structure et supprimez le bloc du tableau.
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]); } } }
Effet de jeu actuel
游戏中的计分器相对较好实现,我们就实现最大为三位数的计分器吧。
html
<div id="score"> <div id="num1"></div> <div id="num2"></div> <div id="num3"></div> </div>
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); }
目前效果 ,计数器功能完成。
当小鸟和管道碰撞或者和地面碰撞时候,隐藏计分器,弹出结束面板。
结束界面主要有“结束面板”和“ok”按钮,这里需要为“ok”按钮添加点击事件。
<div id="gameOver"> <img src="img/game_over.jpg" alt="game over" /> <img src="img/message.jpg" alt="message" /> <img id="ok" src="img/ok.jpg" alt="ok" /> </div>
#gameOver{position: absolute;top: 100px;text-align: center;display: none;z-index: 1; }
为“OK”按钮添加事件
jsOkBtn.onclick = function() {window.location.href = "index.html"; //刷新页面 }
最终效果
有兴趣的朋友,可以加群下载代码,然后加上音效
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!