Dans l'article précédent, nous avons partagé avec vous comment écrire un jeu de push box avec JS et H5. Cet article partage principalement avec vous comment écrire un jeu classique : version simple de Flappy Bird en utilisant les balises js et H5
Avertissement : je suis nouveau sur JS et H5. Cet article implique l'écriture de méthodes et d'algorithmes. S'il y a une meilleure amélioration, veuillez me donner vos suggestions~<.>
1. Exigences de capacités :Nous devons d'abord créer 4 classes : game.html (utilisée pour exécuter le jeu), game.js (utilisée pour écrire la logique). part), paint.js (utilisé pour dessiner des objets), pojo.js (utilisé pour créer des objets et les encapsuler)
classe game.html :
Écrit en HTML5, il faut ajouter , et j'ai l'habitude de mettre la marge à 0 :
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8" /> <title>flappy bird</title> <style> /*设置边距为0*/ body{ margin:0px; overflow:hidden; } /*加背景*/ #can1{ background-image: url(背景.jpg); background-size:100%100%; } </style> <script type="text/javascript" src="pojo.js"></script> <script type="text/javascript" src="game.js"></script> <script type="text/javascript" src="paint.js"></script> <!--调用run()--> <script> window.onload = function (){ run(); }; </script> </head> <body> <!--画布标签,设置长宽像素--> <canvas id="can1" width="1536" height="733"></canvas> <!--加入背景音乐--> <audio src="bgm.mp3" autoplay loop></audio> <!--加入点击鼠标触发的音效--> <audio id="audio1" autoplay></audio> </body> </html>
En fait, le run( ) est appelée dans le fichier html, et la balise
Le format d'écriture est le suivant :
Remarque : Nous devons prendre en compte tous les attributs de l'oiseau et les encapsuler dans le jeu. Utilisez
//鸟类(圆代替) function Bird(color){ //鸟的颜色 this.color = color; //鸟巩膜的颜色 this.eyeColor = 'white'; //鸟巩膜的半径 this.eyeRadius = 10; //鸟瞳孔的颜色 this.eyeInsideColor = 'black'; //鸟瞳孔的半径 this.eyeInsideRadius = '2.5'; //鸟初始位置 this.left = 100; this.top = 300; //鸟身体半径 this.size = 25; //鸟的速度 this.v = 0; //向下为+ 向上为- //分数计算 this.score = 0; //是否存活 this.isLive = true; }
en js et ensuite nous devons écrire la classe pilier :
Ensuite, nous devons écrire la classe pilier. paint.js , c'est aussi une classe plutôt gênante. Vous devez utiliser
//柱子类 //上面下面各一个,在一个竖直线上; //上下柱子的间隔固定; //左右两列柱子间隔固定; //柱子的粗细固定; //柱子相对鸟的速度 function Pillar(position, length){ //柱子颜色 this.color = 'lime'; //柱子向左移动速度 this.v = 8; //柱子宽度 this.width = 80; //柱子位置,是每个柱子左上角的位置 this.position = position; //柱子长度 this.length = length; //柱子是否存在,意思一会解释 this.isLive = true; //鸟是否通过当前柱子 this.isPass = false; }
Tout d'abord et surtout, je recommande de mettre paint.js en haut. à chaque fois : Effacer l'écran (si ce n'est pas clair, le dernier dessin restera quand même et deviendra la « piste de mouvement ») :
Ensuite, on dessine l'oiseau, Avant En réalisant l'oiseau, je recommande d'utiliser un outil de dessin pour dessiner la forme générale de l'oiseau afin de pouvoir le dessiner avec du code plus tard. C'est le motif de l'oiseau que j'ai conçu (les ailes sont un peu compliquées et je ne sais pas). comment les dessiner encore, donc je ne les ai pas dessinés dans le programme, désolé)
//清屏 function clearScreen(ctx){ ctx.clearRect(0, 0, 1536, 750); }
Une fois le design terminé, nous peut commencer à peindre dans paint.js (j'ai écrit l'acquisition de la toile et la création du pinceau dans In game.js au lieu de paint.js) :
C'est à quoi ça ressemble une fois dessiné (j'ai envie de rire rien qu'en le regardant :) )
//画鸟,同样,所有的变量属性都要考虑到,并且在画巩膜,瞳孔,嘴唇时候都要以变量作为基准!里面的参数需要耐下心来调整。 function paintBird(ctx, left, top, size, color){ ctx.beginPath(); ctx.fillStyle = color; ctx.arc(left, top, size, 0, 2*Math.PI);//left:100 top:300 size:25 ctx.fill(); //画巩膜 ctx.beginPath(); ctx.fillStyle = bird.eyeColor; ctx.arc(left+13,top-8,bird.eyeRadius,0,2*Math.PI); ctx.fill(); //画瞳孔 ctx.beginPath(); ctx.fillStyle = bird.eyeInsideColor; ctx.arc(left+18,top-8,bird.eyeInsideRadius,0,2*Math.PI); ctx.fill(); //画嘴唇 ctx.beginPath(); ctx.strokeStyle = 'black'; ctx.fillStyle = '#FC6747'; ctx.moveTo(left+4, top+3); ctx.lineTo(left+29, top+3); ctx.lineTo(left+33, top+6); ctx.lineTo(left+29, top+9); ctx.lineTo(left+32, top+12); ctx.lineTo(left+29, top+15); ctx.lineTo(left+4, top+15); ctx.lineTo(left+1, top+9); ctx.closePath(); ctx.stroke(); ctx.fill(); ctx.beginPath(); ctx.strokeStyle = 'black'; ctx.moveTo(left+1,top+9); ctx.lineTo(left+29,top+9); ctx.stroke(); //画翅膀,简易版先不画 }
Puis dessinez les piliers :
Ensuite, nous devons également afficher le score :
//画柱子,我用了渐变色,虽然调整的并不是很好,但是还能看 function paintPillar(ctx, left, top, width, height){ ctx.beginPath(); var grd=ctx.createLinearGradient(left,top,left+height,top); grd.addColorStop(0,"green"); grd.addColorStop(0.45,"white"); grd.addColorStop(1,"green"); ctx.fillStyle = grd; ctx.fillRect(left, top, width, height); }
À ce stade, nous avons fait la moitié du travail. le game.js le plus difficile, qui doit prendre en compte la logique, les collisions, le mouvement, le score et bien d'autres problèmes.
//计分 function paintScore(ctx, score){ ctx.fillStyle = 'red'; ctx.font = '40px 黑体'; ctx.fillText('分数:'+score, 1320, 40); }
Présentez d'abord comment concevoir la chute libre d'un oiseau :
Suivez les méthode ci-dessus, écrivez le programme comme suit :
Ensuite est game.js, pour une explication facile, je vais l'expliquer directement dans le code lors de l'écriture :
//点击鼠标事件 document.onmousedown = function (ev){ //每点击一下出来音效 var oAudio = document.getElementById('audio1'); oAudio.src = '扇翅膀emm.wav'; //每点击一下做一次竖直上抛 jump(bird); } //鸟自由落体 function drop(bird){ bird.top = bird.top+bird.v; bird.v++; } //设置竖直上抛,直接将速度修改为负数即可 function jump(bird){ bird.v = -13; }
4. Résumé :
1. Lors de la création avec Canvas ou JS, vous devez avoir besoin des classes ci-dessus (bien sûr, elles peuvent être combinées, afin d'identifier la fonction de chaque classe, je l'ai divisé en ces quatre classes), vous devez avoir une pensée orientée objet Lorsque vous dessinez, utilisez les paramètres de l'objet pour dessiner, par exemple ://游戏逻辑中枢 //创建鸟的对象 var bird = new Bird('#FBEE30'); //创建柱子对象,把20个柱子放到数组中 var pillar = new Array(20); var count = 0; function run(){ //获取画布 var oCan = document.getElementById('can1'); //创建画笔,2d var ctx = oCan.getContext('2d'); //这timer1是游戏页面显示的东西的线程,每25毫秒刷新一次 var timer1 = setInterval(function (){ //每次画之前先清屏 clearScreen(ctx); //判断鸟是否碰上柱子(是否死亡),死亡则弹框,结束线程 if(!bird.isLive){ alert('游戏结束!你的分数是'+bird.score+'!你好菜啊!') clearInterval(timer1); clearInterval(timer2); } //降落一下 drop(bird); //判断鸟是否通过柱子 for(var i = 0; i < pillar.length; i++){ if(pillar[i] != null && pillar[i].isLive){ //移动柱子 movePillar(pillar[i]); //画柱子 paintPillar(ctx, pillar[i].position.x, pillar[i].position.y, pillar[i].width, pillar[i].length); //计分,如果每个鸟的身体(圆)的左边通过一个柱子的最右边时,加一分 if(pillar[i].position.x+pillar[i].width <= bird.left-bird.size && !pillar[i].isPass){ //这里是因为每次通过上下两个柱子,如果是++的话就会每次加2,所以用+=0.5 bird.score += 0.5; //通过的柱子将isPass设置为true,否则程序将默认鸟通过了所有柱子,就会加每次21 pillar[i].isPass = true; } } } //检验鸟碰到柱子 for(var i = 0; i < pillar.length; i++){ if(pillar[i] != null && pillar[i].isLive){ judgeImpact(bird, pillar[i]); } } //死亡后执行 //画鸟 paintBird(ctx, bird.left, bird.top, bird.size, bird.color); paintScore(ctx, bird.score); }, 25); //这个timer2是创建柱子的线程 var timer2 = setInterval(function (){ //上面的柱子的长度 var l = Math.random()*330+100; //上面柱子,用json传变量 pillar[count++] = new Pillar({x:1536, y:0}, l); //下面柱子 pillar[count++] = new Pillar({x:1536, y:l+200}, 733-l-200); //如果柱子达到20个,自动将第20个设置为第0个,节省了内存,属于算法优化 if(count == 20){ count = 0; } }, 1100); } //点击鼠标事件 document.onmousedown = function (ev){ //每点击一下出来音效 var oAudio = document.getElementById('audio1'); oAudio.src = '扇翅膀emm.wav'; //每点击一下做一次竖直上抛 jump(bird); } //鸟自由落体 function drop(bird){ bird.top = bird.top+bird.v; bird.v++; } //设置竖直上抛,直接将速度修改为负数即可 function jump(bird){ bird.v = -13; } //移动柱子 function movePillar(pillar){ pillar.position.x -= pillar.v; //如果柱子移动出画布,将isLive设置为false if(pillar.position.x < -80){ pillar.isLive = false; } } //检测鸟和柱子碰撞 function judgeImpact(bird, pillar){ //碰到上边框,死亡 if(bird.top < bird.size){ bird.isLive = false; bird.top = bird.size; } //碰到下边框,死亡 else if(bird.top > 733-bird.size){ bird.isLive = false; bird.top = 733-bird.size; } //当小鸟嵌入上下柱子的左边时(检验鸟是否碰到柱子的左边) if(Math.abs(bird.left-pillar.position.x) <= bird.size){ //碰到上面柱子的左边 if(pillar.position.y == 0){ if(bird.top < pillar.length){ bird.isLive = false; bird.left = pillar.position.x-bird.size; } } //碰到下面柱子的左边 else{ if(bird.top > pillar.position.y){ bird.isLive = false; bird.left = pillar.position.x-bird.size; } } } //如果是上面柱子 if(pillar.position.y == 0){ //如果小鸟高度小于上面柱子 if(Math.abs(bird.top-pillar.length) <= bird.size){ //并且小鸟在两个柱子之间,死亡 if(bird.left+bird.size > pillar.position.x && bird.left+bird.size < pillar.position.x+pillar.width+30){ bird.isLive = false; bird.top = pillar.length+bird.size; } } } //如果是下面柱子 else{ //如果小鸟高度大于 下面柱子上方距离顶部的高度 if(Math.abs(bird.top-pillar.position.y) <= bird.size){ //并且小鸟在两个柱子之间,死亡 if(bird.left+bird.size > pillar.position.x && bird.left+bird.size < pillar.position.x+pillar.width+30){ bird.isLive = false; bird.top = pillar.position.y-bird.size; } } } }
paintPillar(ctx, pillar[i].position.x, pillar[i].position.y, pillar[i].width, pillar[i].length);
2.关于柱子,我们必须符合这一条逻辑:先创建柱子数组(array),然后创建每个柱子,再画柱子,再移动,四个步骤缺一不可。
3.其中有对于算法的优化:在创建柱子的数组中,我们没有设置很多个柱子(比如说10000,虽然也不可能达到那么高的分),因为这样每25毫秒就要创建那么多柱子,再画和移动,内存占用很高,我们只用建立一个能存放20个柱子的数组,出屏幕的清掉,位置由新的代替,这样就极大程度减少了对内存的需要。
4.关于调试参数(比如说画鸟),要耐心调整,直到满意为止。
5.在检测鸟和柱子的碰幢时候,需要在逻辑上下功夫,建议先在稿纸上画出碰撞条件,再编写程序。
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!