Rumah  >  Artikel  >  hujung hadapan web  >  Gunakan HTML5 Canvas untuk mencipta kemahiran tutorial game_html5 melancap mudah

Gunakan HTML5 Canvas untuk mencipta kemahiran tutorial game_html5 melancap mudah

WBOY
WBOYasal
2016-05-16 15:46:342068semak imbas

Saya pernah melihat permainan melancap dalam DEMO Donnet sebelum ini, dan kemudian saya menurunkan gambar dan audionya. . . . Saya menulis semula hanya untuk suka-suka. Sekadar hiburan. . . . . . Saya tidak menggunakan rangka kerja, saya menulis semua js sendiri. . . . . . Jadi ini adalah tutorial mudah Ia mungkin berguna kepada mereka yang baru berjinak-jinak dengan kanvas untuk masa yang lama.

Tanpa berlengah lagi, mari kita mulakan dengan DEMO: Permainan Pesawat Terbang Poster asal menulis ini hanya untuk keseronokan, dan tidak berniat untuk menulisnya dalam permainan yang serius.

Mari kita masuk ke topik: Fail permainan melancap termasuk fail entri index.html, fail pemprosesan logik allSprite.js sprite, fail pemprosesan loading.js dan data.js (beberapa data yang dimulakan).

Pertama sekali, permainan biasa pada asasnya memerlukan pemuatan Halaman pemuatan digunakan untuk pramuat data, termasuk imej helaian sprite, audio, dsb. Kerana ini adalah permainan kecil, hanya beberapa audio dan imej yang perlu dimuatkan. Kod pemuatan di dalamnya terutamanya yang berikut adalah untuk membuat animasi memuatkan, jadi saya tidak akan menyiarkannya, lihat sahaja konsol dalam DEMO:

Kod XML/HTMLSalin kandungan ke papan keratan
  1. loadImg:function(data){   
  2.             var _ini = ini;   
  3.              var dataIndex = 0;   
  4.             li();   
  5.             fungsi li(){   
  6.                 jika(data[dataIndex].indexOf("mp3")>=0){   
  7.                     var audio = dokumen.createElement("audio");   
  8.                     document.body.appendChild(audio);   
  9.                     audio.pramuat = "auto";   
  10.                     audio.src = data[dataIndex];   
  11.                     audio.oncanplaythrough = fungsi(){   >
  12.                          ini.oncanplaythrough = null;   
  13.                         Indeks data ;   
  14.                          jika(Index data===datas.length){   
  15.                             _ini.peratus = 100;   
  16.                         } lain {   
  17.                             _this.percent = parseInt0.   
  18.                             li.call(_this);   
  19.                         }   
  20.                     }   
  21.                 }lain {   
  22.                     preLoadImg(datas[dataIndex] , function(){   
  23.                         Indeks data ;   
  24.                          jika(Index data===datas.length){   
  25.                             _ini.peratus = 100;   
  26.                         } lain {   
  27.                             _this.percent = parseInt0.   
  28.                             li.call(_this);   
  29.                         }   
  30.                     })   
  31.                 }   
  32.             }   
  33.         },   
  34.   
  35. //再贴出preLoadImg的方法   
  36. fungsi preLoadImg(src , panggilan balik){   
  37.     var img = baharu Imej();   
  38.     img.src = src;   
  39.     jika(img.complete){   
  40.         panggilan balik.panggilan(img);   
  41.     }lain {   
  42.         img.onload = fungsi(){   
  43.             panggilan balik.panggilan(img);   
  44.         }   
  45.     }   
  46. }     


Saya mula-mula menggunakan tatasusunan untuk menyimpan pautan ke fail dalam data.js, dan kemudian menentukan sama ada pautan ini adalah gambar atau audio Jika ia adalah gambar, gunakan preLoadImg untuk memuatkannya adalah sangat mudah, hanya buat gambar baharu, kemudian tetapkan pautan kepadanya, dan panggil semula selepas dimuatkan. Audio dimuatkan dengan menjana objek dom audio HTML5 dan memberikan pautan kepadanya Audio mempunyai acara "canplaythrough". , yang bermaksud bahawa apabila canplaythrough dipanggil, audio telah hampir dimuatkan dan audio seterusnya boleh dimuatkan. Sama seperti ini, selepas semuanya dimuatkan, panggilan balik dibuat dan permainan bermula.

Permainan dimulakan memerlukan banyak objek, jadi saya menyatukannya menjadi satu objek sprite Pergerakan setiap bingkai antara objek yang berbeza boleh ditulis secara berasingan menggunakan gelagat.

Kod XML/HTMLSalin kandungan ke papan keratan
  1. W.Sprite = fungsi(nama , pelukis , tingkah laku , args){   
  2.     jika(nama !== tidak ditentukan) nama.ini = nama;   
  3.     jika(pelukis !== tidak ditentukan) pelukis ini = pelukis;   
  4.     ini.top = 0;   
  5.     ini.kiri = 0;   
  6.     ini.lebar = 0;   
  7.     ini.tinggi = 0;   
  8.     ini.velocityX = 3;   
  9.     ini.halajuY = 2;   
  10.     ini.kelihatan = benar;   
  11.     ini.animating = palsu;   
  12.     ini.tingkah laku = tingkah laku;   
  13.     ini.rotateAngle = 0;   
  14.     ini.darah = 50;   
  15.     ini.fullBlood = 50;   
  16.     jika(nama==="pelan"){   
  17.         ini.rotateSpeed = 0.05;   
  18.         ini.putar Kiri = salah;   
  19.         ini.putarkan Kanan = salah;   
  20.         ini.api = salah;   
  21.         ini.firePerFrame = 10;   
  22.         ini.fireLevel = 1;   
  23.     }lain jika(nama==="bintang"){   
  24.         ini.lebar = Matematik.random()*2;   
  25.         ini.kelajuan = 1*ini.lebar/2;   
  26.         ini.lightLength = 5;   
  27.         this.cacheCanvas = dokumen.createElement("kanvas");   
  28.         iniini.cacheCtx = this.cacheCanvas.getContext('2d');   
  29.         iniini.cacheCanvas.width = ini.lebar ini.lightLength*2;   
  30.         iniini.cacheCanvas.height = ini.lebar ini.lightLength*2;   
  31.         this.painter.cache(this);   
  32.     }lain jika(nama==="badPlan"){   
  33.         ini.badKind = 1;   
  34.         ini.kelajuan = 2;   
  35.         ini.rotateAngle = Math.PI;   
  36.     }lain jika(nama==="missle"){   
  37.         ini.lebar = missleWidth;   
  38.     }lain jika(nama==="boom"){   
  39.         ini.lebar = boomWidth;   
  40.     }lain jika(nama==="makanan"){   
  41.         ini.lebar = 40;   
  42.         ini.kelajuan = 3;   
  43.         ini.jenis = "LevelUP"  
  44.     }  
  45.     ini.ke Kiri = salah;   
  46.     ini.toTop = palsu;   
  47.     ini.ke Kanan = salah;   
  48.     ini.toBottom = palsu;   
  49.   
  50.     this.outArcRadius = Math.sqrt((this.width/2*this.width/2 )*2);   
  51.   
  52.     if(args){   
  53.         untuk(var arg dalam args){   
  54.             ini[arg] = args[arg];   
  55.         }   
  56.     }   
  57. }   
  58. Sprite.prototype = {   
  59.     pembina:Sprite,   
  60.     paint:function(){   
  61.         jika(ini.nama==="badPlan"){this.update();}   
  62.   
  63.         jika(pelukis ini !== tidak ditentukan && ini.kelihatan){   
  64.             jika(this.name!=="badPlan") {   
  65.                 ini.kemas kini();   
  66.             }   
  67.              jika(nama.ini==="rancangan"||nama.ini===" missle"||nama.ini==="badPlan"){   
  68.                 ctx.save();   
  69.                 ctx.translate(ini.kiri , ini.atas);   
  70.                 ctx.rotate(this.rotateAngle);   
  71.                 ini.pelukis.cat(ini);   
  72.                 ctx.restore();   
  73.             }lain {   
  74.                 ini.pelukis.cat(ini);   
  75.             }   
  76.         }   
  77.     },
  78. kemas kini:fungsi(masa){
  79. jika(tingkah laku ini){
  80. untuk(var i=0;i<ini.tingkah laku.panjang;i ){
  81. this.behaviors[i].execute(this,time);
  82.                                                                 
  83.                                                               
  84. }
  85. }
Selepas menulis kelas elf, anda boleh menjana objek berbeza dengan menulis setiap pelukis dan tingkah laku. Langkah seterusnya ialah menulis pelukis Pelukis terbahagi kepada dua jenis, satu pelukis biasa, dan satu lagi pelukis lembaran sprite Kerana animasi letupan dan animasi menembak kapal terbang tidak boleh dilakukan dengan hanya satu gambar, jadi anda perlu menggunakan Masanya. kepada helaian sprite:



2015511181456172.png (168×24)

Untuk melukis ini, anda perlu menyesuaikan pelukis helaian sprite untuk mereka Berikut adalah pelukis helaian sprite yang paling mudah Mengikut kerumitan permainan, kaedah penulisan helaian sprite boleh diubah suai sehingga ia sesuai , prinsipnya serupa, iaitu Hanya pengubahsuaian kecil:

2015511181533636.png (896×64)

Kod XML/HTML

Salin kandungan ke papan keratan
  1. var SpriteSheetPainter = fungsi(sel){   <🎜
  2.             ini.sel = sel || [];   
  3.              ini.cellIndex = 0;   
  4.         }   
  5.         SpriteSheetPainter.prototype = {   
  6.             advance:function(){   
  7.                  jika(ini.cellIndex === ini.cells.length-1){   
  8.                     ini.cellIndex = 0;   
  9.                 }   
  10.                 lain ini.cellIndex ;   
  11.             },   
  12.             paint:function(sprite){   
  13.                 var sel = ini.sel[this.cellIndex];   
  14.                 context.drawImage(spritesheet , cell.x , cell.y , cell.w , cell.h , sprite.left , sprite.top , cell.w , cell.h);   
  15.             }   
  16.         }     
而普通的绘制器就更简单了,直接写一个pelukis,把要画的什么东西都写进去个。

有了精灵类和精灵表绘制器后,我们就可以把星星,飞机,子弹:爆炸对来象整个allSprite.js的代码:


Kod JavaScript
复制内容到剪贴板
  1. (fungsi(W){   
  2.     "gunakan ketat"  
  3.     var planWidth = 24,   
  4.         planHeight = 24,   
  5.         missleWidth = 70,   
  6.         missleHeight = 70,   
  7.         lebar lebar = 60;   
  8.     //精灵类   
  9.     W.Sprite = fungsi(nama , pelukis , tingkah laku , args){   
  10.         jika(nama !== tidak ditentukan) ini.name = nama;   
  11.         jika(pelukis !== tidak ditentukan) ini.pelukis = pelukis;   
  12.         ini.atas = 0;   
  13.         ini.kiri = 0;   
  14.         ini.lebar = 0;   
  15.         ini.tinggi = 0;   
  16.         ini.velocityX = 3;   
  17.         ini.velocityY = 2;   
  18.         ini.kelihatan = benar;   
  19.         ini.menghidupkan = palsu;   
  20.         ini.tingkah laku = tingkah laku;   
  21.         ini.rotateAngle = 0;   
  22.         ini.darah = 50;   
  23.         ini.fullBlood = 50;   
  24.         jika(nama==="pelan"){   
  25.              ini.rotateSpeed = 0.05;   
  26.              ini.rotateLeft = false;   
  27.             ini.rotateRight = salah;   
  28.              ini.api = palsu;   
  29.             ini.firePerFrame = 10;   
  30.             ini.fireLevel = 1;   
  31.         }lain jika(nama==="bintang" ){   
  32.             ini.width = Math.random()*2;   
  33.              ini.kelajuan = 1*ini.lebar/2;   
  34.              ini.lightLength = 5;   
  35.             ini.cacheCanvas = document.createElement("kanvas");   
  36.              ini.cacheCtx = ini.cacheCanvas.getContext2(🎜>'<'' 🎜>);   
  37.             ini.cacheCanvas.width = ini.lebar .cacheCanvas.width = ini.lebar
  38. <🎜 🎜>.lightLength*2;                 ini.cacheCanvas.height = ini.lebar .cacheCanvas.height = 
  39. ini.lebar <🎜 🎜>.lightLength*2;                 ini
  40. .painter.cache(
  41. ini);            }lain jika
  42. (nama===
  43. "badPlan" ){   
  44.              
  45. ini.badKind = 1;   
  46.             
  47. ini.kelajuan = 2;   
  48.             
  49. ini.rotateAngle = Math.PI;            }lain jika
  50. (nama===
  51. "missle" ){   
  52.              
  53. ini.width = missleWidth;            }lain jika
  54. (nama===
  55. "boom" ){   
  56.             
  57. ini<🎜><🎜>.width = boomWidth;   <🎜><🎜> <🎜><🎜>        }lain jika(nama==="makanan"){   
  58.             ini.lebar = 40;   
  59.             ini.kelajuan = 3;   
  60.              ini.jenis = "LevelUP"  
  61.         }   
  62.         ini.ke Kiri = salah;   
  63.         ini.toTop = salah;   
  64.         ini.ke Kanan = salah;   
  65.         ini.toBottom = palsu;   
  66.   
  67.         ini.outArcRadius = Math.sqrt((ini.lebar/2*ini.lebar/2)*2);   
  68.   
  69.         jika(args){   
  70.              untuk(var arg dalam arg
  71.                 ini[arg] = args[arg];   
  72.             }   
  73.         }   
  74.     }   
  75.     Sprite.prototype = {   
  76.         pembina:Sprite,   
  77.         cat:fungsi(){   
  78.              jika(ini.name==="badPlan"<🎜 ){ini.kemas kini();}   
  79.   
  80.              jika(ini.pelukis !== undefined && (ini
  81. .pelukis !== undefined && 
  82. ini><🎜 .kelihatan){                    jika(ini.nama!==
  83. <🎜<>"Rancangan buruk"
  84. ) {                        ini
  85. .kemas kini();   <🎜> <🎜><🎜>                }  
  86.                 jika(ini.name==="rancangan" ||ini.name==="missle"||ini .name==="badPlan"){   
  87.                     ctx.save();   
  88.                     ctx.translate(ini.kiri , ini.atas);   
  89.                     ctx.rotate(ini.rotateAngle);   
  90.                     ini.pelukis.cat(ini);   
  91.                     ctx.restore();   
  92.                 }lain {   
  93.                     ini.pelukis.cat(ini);   
  94.                 }   
  95.             }   
  96.         },   
  97.         kemas kini:fungsi(masa){   
  98.              jika(ini.kelakuan){   
  99.                 untuk(var i=0;i<ini 🎜>.kelakuan.panjang;i ){   
  100.                     ini.tingkah laku[i].laksanakan(ini,masa);   
  101.                 }   
  102.             }   
  103.         }   
  104.     }  
  105.   
  106.     // 精灵表绘制器   
  107.     W.SpriteSheetPainter = Funktion(Zellen , isloop , endCallback , spritesheet){   
  108.         dieses.cells = cells || [];   
  109.         this.cellIndex = 0;   
  110.         this.dateCount = null;   
  111.         dieses.isloop = isloop;   
  112.         dieses.endCallback = endCallback;   
  113.         dieses.spritesheet = spritesheet;   
  114.     }   
  115.     SpriteSheetPainter.prototype = {   
  116.         advance:Funktion(){   
  117.             this.cellIndex = this.isloop?(this.cellIndex===this.cells.length-1?0:this.cellIndex 1):(dies.cellIndex 1);   
  118.         },   
  119.         paint:function(sprite){   
  120.             if(this.dateCount===null){   
  121.                                 }else {   
  122.                 var newd = 
  123. new
  124.  Date();                                        
  125. if
  126. (tc>40){                         this.advance();   
  127.                      dieses.dateCount = newd;   
  128.                 }                }  
  129.             if(this.cellIndex<this. celles.length || . this.isloop){   
  130.                 .cellIndex];                    ctx.drawImage(this.spritesheet , cell.x , cell.y , cell.w , cell.h , sprite.left-sprite.width/ 2 , sprite.top-sprite.width/2 , cell.w , cell.h);                } 
  131. else
  132.  if(
  133. this
  134. .endCallback) {                    dieses.endCallback.call(sprite);                    
  135. this
  136. .cellIndex = 0;                }   
  137.         }        }   
  138.   
  139.     
  140. //特制飞机精灵表绘制器
  141.   
  142.     W.controllSpriteSheetPainter = 
  143. Funktion
  144. (Zellen , Spritesheet){            
  145. dieses
  146. .cells = cells || [];            
  147. this
  148. .cellIndex = 0;            
  149. this
  150. .dateCount = null;   
  151.         this.isActive = false;   
  152.         this.derection = true;   
  153.         dieses.spritesheet = spritesheet;        }  
  154.     controllSpriteSheetPainter.prototype = {   
  155.         advance:Funktion(){   
  156.             if(this.isActive){   
  157.                 this.cellIndex ;   
  158.                 >.cells.length){                        this.cellIndex = 0;                           
  159.                 }                }   
  160.         },            paint:function(sprite){   
  161.             
  162. if
  163. (
  164. this
  165. .dateCount===
  166. null
  167. ){                       
  168.             }else {                    var newd = 
  169. new
  170.  Date();                                        
  171. if
  172. (tc>sprite.firePerFrame){                        
  173. this
  174. .advance();                         dieses.dateCount = newd;   
  175.                 }                }                
  176. var
  177.  cell = this.cells[
  178. this
  179. .cellIndex];                ctx.drawImage(
  180. this
  181. .spritesheet , cell.x , cell.y , cell.w , cell.h , -planWidth/2 , -planHeight/ 2 , cell.w , cell.h);            }  
  182.     }   
  183.   
  184.     W.planBehavior = [   
  185.         {execute:function(sprite,time){   
  186.             if(sprite.toTop){   
  187.                 sprite.top = sprite.top
  188.             }   
  189.             if(sprite.toLeft){   
  190.                 sprite.left = sprite.left
  191.             }   
  192.             if(sprite.toRight){   
  193.                 sprite.left = sprite.left>canvas.width-planWidth/2? sprite.left : sprite.left sprite.velocityX;   
  194.             }   
  195.             if(sprite.toBottom){   
  196.                 sprite.top = sprite.top>canvas.height-planHeight/2? sprite.top : sprite.top sprite.velocityY;   
  197.             }   
  198.             if(sprite.rotateLeft){   
  199.                 sprite.rotateAngle -= sprite.rotateSpeed;   
  200.             }   
  201.             if(sprite.rotateRight){   
  202.                 sprite.rotateAngle  = sprite.rotateSpeed;   
Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn