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
- loadImg:function(data){
-
var _ini = ini;
-
var dataIndex = 0;
- li();
- fungsi li(){
-
jika(data[dataIndex].indexOf("mp3")>=0){
-
var audio = dokumen.createElement("audio");
- document.body.appendChild(audio);
-
audio.pramuat = "auto";
-
audio.src = data[dataIndex];
-
audio.oncanplaythrough = fungsi(){ >
-
ini.oncanplaythrough = null;
- Indeks data ;
-
jika(Index data===datas.length){
-
_ini.peratus = 100;
- } lain {
-
_this.percent = parseInt0.
- li.call(_this);
- }
- }
- }lain {
- preLoadImg(datas[dataIndex] , function(){
- Indeks data ;
-
jika(Index data===datas.length){
-
_ini.peratus = 100;
- } lain {
-
_this.percent = parseInt0.
- li.call(_this);
- }
- })
- }
- }
- },
-
- //再贴出preLoadImg的方法
- fungsi preLoadImg(src , panggilan balik){
-
var img = baharu Imej();
-
img.src = src;
- jika(img.complete){
- panggilan balik.panggilan(img);
- }lain {
-
img.onload = fungsi(){
- panggilan balik.panggilan(img);
- }
- }
-
}
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
- W.Sprite = fungsi(nama , pelukis , tingkah laku , args){
-
jika(nama !== tidak ditentukan) nama.ini = nama;
-
jika(pelukis !== tidak ditentukan) pelukis ini = pelukis;
-
ini.top = 0;
-
ini.kiri = 0;
-
ini.lebar = 0;
-
ini.tinggi = 0;
-
ini.velocityX = 3;
-
ini.halajuY = 2;
-
ini.kelihatan = benar;
-
ini.animating = palsu;
-
ini.tingkah laku = tingkah laku;
-
ini.rotateAngle = 0;
-
ini.darah = 50;
-
ini.fullBlood = 50;
-
jika(nama==="pelan"){
-
ini.rotateSpeed = 0.05;
-
ini.putar Kiri = salah;
-
ini.putarkan Kanan = salah;
-
ini.api = salah;
-
ini.firePerFrame = 10;
-
ini.fireLevel = 1;
-
}lain jika(nama==="bintang"){
-
ini.lebar = Matematik.random()*2;
-
ini.kelajuan = 1*ini.lebar/2;
-
ini.lightLength = 5;
-
this.cacheCanvas = dokumen.createElement("kanvas");
-
iniini.cacheCtx = this.cacheCanvas.getContext('2d');
-
iniini.cacheCanvas.width = ini.lebar ini.lightLength*2;
-
iniini.cacheCanvas.height = ini.lebar ini.lightLength*2;
- this.painter.cache(this);
-
}lain jika(nama==="badPlan"){
-
ini.badKind = 1;
-
ini.kelajuan = 2;
-
ini.rotateAngle = Math.PI;
-
}lain jika(nama==="missle"){
-
ini.lebar = missleWidth;
-
}lain jika(nama==="boom"){
-
ini.lebar = boomWidth;
-
}lain jika(nama==="makanan"){
-
ini.lebar = 40;
-
ini.kelajuan = 3;
-
ini.jenis = "LevelUP"
- }
-
ini.ke Kiri = salah;
-
ini.toTop = palsu;
-
ini.ke Kanan = salah;
-
ini.toBottom = palsu;
-
-
this.outArcRadius = Math.sqrt((this.width/2*this.width/2 )*2);
-
- if(args){
- untuk(var arg dalam args){
- ini[arg] = args[arg];
- }
- }
- }
-
Sprite.prototype = {
- pembina:Sprite,
- paint:function(){
-
jika(ini.nama==="badPlan"){this.update();}
-
- jika(pelukis ini !== tidak ditentukan && ini.kelihatan){
- jika(this.name!=="badPlan") {
- ini.kemas kini();
- }
-
jika(nama.ini==="rancangan"||nama.ini===" missle"||nama.ini==="badPlan"){
- ctx.save();
- ctx.translate(ini.kiri , ini.atas);
- ctx.rotate(this.rotateAngle);
- ini.pelukis.cat(ini);
- ctx.restore();
- }lain {
- ini.pelukis.cat(ini);
- }
- }
- },
- kemas kini:fungsi(masa){
- jika(tingkah laku ini){
-
untuk(var i=0;i<ini.tingkah laku.panjang;i ){
- this.behaviors[i].execute(this,time);
-
- }
- }
-
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:
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:
Kod XML/HTML
Salin kandungan ke papan keratan
- var SpriteSheetPainter = fungsi(sel){ <🎜
- ini.sel = sel || [];
- ini.cellIndex = 0;
- }
- SpriteSheetPainter.prototype = {
- advance:function(){
- jika(ini.cellIndex === ini.cells.length-1){
- ini.cellIndex = 0;
- }
- lain ini.cellIndex ;
- },
- paint:function(sprite){
- var sel = ini.sel[this.cellIndex];
- context.drawImage(spritesheet , cell.x , cell.y , cell.w , cell.h , sprite.left , sprite.top , cell.w , cell.h);
- }
- }
而普通的绘制器就更简单了,直接写一个pelukis,把要画的什么东西都写进去个。
有了精灵类和精灵表绘制器后,我们就可以把星星,飞机,子弹:爆炸对来象整个allSprite.js的代码:
Kod JavaScript
复制内容到剪贴板
- (fungsi(W){
- "gunakan ketat"
- var planWidth = 24,
- planHeight = 24,
- missleWidth = 70,
- missleHeight = 70,
- lebar lebar = 60;
-
- W.Sprite = fungsi(nama , pelukis , tingkah laku , args){
- jika(nama !== tidak ditentukan) ini.name = nama;
- jika(pelukis !== tidak ditentukan) ini.pelukis = pelukis;
- ini.atas = 0;
- ini.kiri = 0;
- ini.lebar = 0;
- ini.tinggi = 0;
- ini.velocityX = 3;
- ini.velocityY = 2;
- ini.kelihatan = benar;
- ini.menghidupkan = palsu;
- ini.tingkah laku = tingkah laku;
- ini.rotateAngle = 0;
- ini.darah = 50;
- ini.fullBlood = 50;
- jika(nama==="pelan"){
- ini.rotateSpeed = 0.05;
- ini.rotateLeft = false;
- ini.rotateRight = salah;
- ini.api = palsu;
- ini.firePerFrame = 10;
- ini.fireLevel = 1;
- }lain jika(nama==="bintang" ){
- ini.width = Math.random()*2;
- ini.kelajuan = 1*ini.lebar/2;
- ini.lightLength = 5;
- ini.cacheCanvas = document.createElement("kanvas");
- ini.cacheCtx = ini.cacheCanvas.getContext2(🎜>'<'' 🎜>);
- ini.cacheCanvas.width = ini.lebar .cacheCanvas.width = ini.lebar
- <🎜 🎜>.lightLength*2;
ini.cacheCanvas.height = ini.lebar .cacheCanvas.height =
- ini.lebar <🎜 🎜>.lightLength*2;
ini
.painter.cache(- ini);
}lain jika
(nama===- "badPlan" ){
- ini.badKind = 1;
- ini.kelajuan = 2;
- ini.rotateAngle = Math.PI;
}lain jika
(nama===- "missle" ){
- ini.width = missleWidth;
}lain jika
(nama===- "boom" ){
- ini<🎜><🎜>.width = boomWidth; <🎜><🎜>
<🎜><🎜> }lain jika(nama==="makanan"){
- ini.lebar = 40;
- ini.kelajuan = 3;
- ini.jenis = "LevelUP"
- }
- ini.ke Kiri = salah;
- ini.toTop = salah;
- ini.ke Kanan = salah;
- ini.toBottom = palsu;
-
- ini.outArcRadius = Math.sqrt((ini.lebar/2*ini.lebar/2)*2);
-
- jika(args){
- untuk(var arg dalam arg
-
ini[arg] = args[arg];
-
}
-
}
-
}
-
Sprite.prototype = {
-
pembina:Sprite,
-
cat:fungsi(){
-
jika(ini.name==="badPlan"<🎜 ){ini.kemas kini();}
-
- jika(ini.pelukis !== undefined && (ini
.pelukis !== undefined && - ini><🎜 .kelihatan){
jika(ini.nama!==
<🎜<>"Rancangan buruk" - ) {
ini
- .kemas kini(); <🎜>
<🎜><🎜> }
- jika(ini.name==="rancangan" ||ini.name==="missle"||ini .name==="badPlan"){
-
ctx.save();
-
ctx.translate(ini.kiri , ini.atas);
-
ctx.rotate(ini.rotateAngle);
-
ini.pelukis.cat(ini);
-
ctx.restore();
-
}lain {
-
ini.pelukis.cat(ini);
-
}
-
}
-
},
-
kemas kini:fungsi(masa){
-
jika(ini.kelakuan){
-
untuk(var i=0;i<ini 🎜>.kelakuan.panjang;i ){
- ini.tingkah laku[i].laksanakan(ini,masa);
- }
- }
- }
- }
W.SpriteSheetPainter = Funktion(Zellen , isloop , endCallback , spritesheet){
dieses.cells = cells || [];
this.cellIndex = 0;
this.dateCount = null;
dieses.isloop = isloop;
dieses.endCallback = endCallback;
dieses.spritesheet = spritesheet;
}
SpriteSheetPainter.prototype = {
advance:Funktion(){
this.cellIndex = this.isloop?(this.cellIndex===this.cells.length-1?0:this.cellIndex 1):(dies.cellIndex 1);
},
paint:function(sprite){
if(this.dateCount===null){
}else {
var newd = new
Date();
if
(tc>40){
this.advance();
dieses.dateCount = newd;
}
}
if(this.cellIndex<this. celles.length || . this.isloop){
.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);
} else
if(this
.endCallback) {
dieses.endCallback.call(sprite);
this
.cellIndex = 0;
}
}
}
//特制飞机精灵表绘制器
W.controllSpriteSheetPainter = Funktion
(Zellen , Spritesheet){ dieses
.cells = cells || [];
this
.cellIndex = 0;
this
.dateCount = null;
this.isActive = false;
this.derection = true;
dieses.spritesheet = spritesheet;
}
controllSpriteSheetPainter.prototype = {
advance:Funktion(){
if(this.isActive){
this.cellIndex ;
>.cells.length){
this.cellIndex = 0;
}
}
},
paint:function(sprite){
if
(this
.dateCount===null
){
}else {
var newd = new
Date();
if
(tc>sprite.firePerFrame){
this
.advance();
dieses.dateCount = newd;
}
}
var
cell = this.cells[
this
.cellIndex];
ctx.drawImage(
this
.spritesheet , cell.x , cell.y , cell.w , cell.h , -planWidth/2 , -planHeight/ 2 , cell.w , cell.h);
}
}
W.planBehavior = [
{execute:function(sprite,time){
if(sprite.toTop){
sprite.top = sprite.top
}
if(sprite.toLeft){
sprite.left = sprite.left
}
if(sprite.toRight){
sprite.left = sprite.left>canvas.width-planWidth/2? sprite.left : sprite.left sprite.velocityX;
}
if(sprite.toBottom){
sprite.top = sprite.top>canvas.height-planHeight/2? sprite.top : sprite.top sprite.velocityY;
}
if(sprite.rotateLeft){
sprite.rotateAngle -= sprite.rotateSpeed;
}
if(sprite.rotateRight){
sprite.rotateAngle = sprite.rotateSpeed;