萬盛學電腦網

 萬盛學電腦網 >> 網頁制作 >> Html5 >> 利用HTML5 Canvas制作一個簡單的打飛機游戲

利用HTML5 Canvas制作一個簡單的打飛機游戲

   之前在當耐特的DEMO裡看到個打飛機的游戲,然後就把他的圖片和音頻扒了了下來。。。。自己憑著玩的心情重新寫了一個。僅供娛樂哈。。。。。。我沒有用框架,所有js都是自己寫的。。。。。。所以就可以來當個簡單的教程,對那些剛玩canvas的,或許能有些幫助,樓主玩canvas也不是很久,技術不是很好,請見諒哈。

  閒話不多說,先上DEMO撒:飛機游戲 樓主寫這個人純碎娛樂,沒想著寫成多正式的游戲哈。

  步入主題啦:打飛機游戲文件有index.html入口文件,allSprite.js精靈的邏輯處理文件,loading.js加載處理文件以及data.js(初始化的一些數據)。

  首先,正常的游戲基本上都需要一個loading,loading頁面就是用來預加載數據的,包括精靈表圖片,音頻等,因為這是個小游戲,要加載的就只有一些音頻和圖片。裡面的加載代碼主要就下面這些,其他是制作loading動畫的,那個比較簡單,就不貼了,如果有興趣的直接在DEMO裡看控制台就行了:

  XML/HTML Code復制內容到剪貼板

  loadImg:function(datas){

  var _this = this;

  var dataIndex = 0;

  li();

  function li(){

  if(datas[dataIndex].indexOf("mp3")>=0){

  var audio = document.createElement("audio");

  document.body.appendChild(audio);

  audio.preload = "auto";

  audio.src = datas[dataIndex];

  audio.oncanplaythrough = function(){

  this.oncanplaythrough = null;

  dataIndex++;

  if(dataIndex===datas.length){

  _this.percent = 100;

  }else {

  _this.percent = parseInt(dataIndex/datas.length*100);

  li.call(_this);

  }

  }

  }else {

  preLoadImg(datas[dataIndex] , function(){

  dataIndex++;

  if(dataIndex===datas.length){

  _this.percent = 100;

  } else {

  _this.percent = parseInt(dataIndex/datas.length*100);

  li.call(_this);

  }

  })

  }

  }

  },

  //再貼出preLoadImg的方法

  function preLoadImg(src , callback){

  var img = new Image();

  img.src = src;

  if(img.complete){

  callback.call(img);

  }else {

  img.onload = function(){

  callback.call(img);

  }

  }

  }

  我先在data.js裡面用一個數組保存文件的鏈接,然後判斷這些鏈接是圖片還是音頻,如果是圖片就用preLoadImg加載,預加載圖片的代碼很簡單,就是new一個圖片對象,然後把鏈接賦給它,加載完後再回調。音頻的加載則是通過生成一個HTML5的audio dom對象,把鏈接賦給它,audio有一個事件“canplaythrough”,浏覽器預計能夠在不停下來進行緩沖的情況下持續播放指定的音頻/視頻時,會發生 canplaythrough 事件,也就是說當canplaythrough被調用時,音頻就已經被加載的差不多了,可以進行下一個音頻的加載了。就這樣當把所有東西都加載完後,再進行回調,開始游戲。

  游戲開始了,一個游戲,會需要很多的對象,所以我就統一寫成了一個精靈對象,不同對象之間的每一幀的運動情況直接用behavior來分別編寫就行了。

  XML/HTML Code復制內容到剪貼板

  W.Sprite = function(name , painter , behaviors , args){

  if(name !== undefined) this.name = name;

  if(painter !== undefined) this.painter = painter;

  this.top = 0;

  this.left = 0;

  this.width = 0;

  this.height = 0;

  this.velocityX = 3;

  this.velocityY = 2;

  this.visible = true;

  this.animating = false;

  this.behaviors = behaviors;

  this.rotateAngle = 0;

  this.blood = 50;

  this.fullBlood = 50;

  if(name==="plan"){

  this.rotateSpeed = 0.05;

  this.rotateLeft = false;

  this.rotateRight = false;

  this.fire = false;

  this.firePerFrame = 10;

  this.fireLevel = 1;

  }else if(name==="star"){

  this.width = Math.random()*2;

  this.speed = 1*this.width/2;

  this.lightLength = 5;

  this.cacheCanvas = document.createElement("canvas");

  thisthis.cacheCtx = this.cacheCanvas.getContext('2d');

  thisthis.cacheCanvas.width = this.width+this.lightLength*2;

  thisthis.cacheCanvas.height = this.width+this.lightLength*2;

  this.painter.cache(this);

  }else if(name==="badPlan"){

  this.badKind = 1;

  this.speed = 2;

  this.rotateAngle = Math.PI;

  }else if(name==="missle"){

  this.width = missleWidth;

  }else if(name==="boom"){

  this.width = boomWidth;

  }else if(name==="food"){

  this.width = 40;

  this.speed = 3;

  this.kind = "LevelUP"

  }

  this.toLeft = false;

  this.toTop = false;

  this.toRight = false;

  this.toBottom = false;

  this.outArcRadius = Math.sqrt((this.width/2*this.width/2)*2);

  if(args){

  for(var arg in args){

  this[arg] = args[arg];

  }

  }

  }

  Sprite.prototype = {

  constructor:Sprite,

  paint:function(){

  if(this.name==="badPlan"){this.update();}

  if(this.painter !== undefined && this.visible){

  if(this.name!=="badPlan") {

  this.update();

  }

  if(this.name==="plan"||this.name==="missle"||this.name==="badPlan"){

  ctx.save();

  ctx.translate(this.left , this.top);

  ctx.rotate(this.rotateAngle);

  this.painter.paint(this);

  ctx.restore();

  }else {

  this.painter.paint(this);

  }

  }

  },

  update:function(time){

  if(this.behaviors){

  for(var i=0;i

  this.behaviors[i].execute(this,time);

  }

  }

  }

  }

  寫出精靈類後,就可以通過編寫每個的painter以及behavior來生成不同的對象了。接下來就是寫painter了,painter分成兩種,一種是普通的painter,一種就是精靈表painter,因為像爆炸動畫,飛機開槍動畫,都不是一張圖片就能搞定的,所以就需要用到精靈表了:

2015511181456172.png (168×24)
2015511181533636.png (896×64)

  而繪制這些就要為他們定制一個精靈表繪制器,下面這個是最簡單的精靈表繪制器,針對游戲的復雜性可以相對的修改精靈表寫法,直到合適,不過原理都大同小異,就是小修小改而已:

  XML/HTML Code復制內容到剪貼板

  var SpriteSheetPainter = function(cells){

  this.cells = cells || [];

  this.cellIndex = 0;

  }

  SpriteSheetPainter.prototype = {

  advance:function(){

  if(this.cellIndex === this.cells.length-1){

  this.cellIndex = 0;

  }

  else this.cellIndex++;

  },

  paint:function(sprite){

  var cell = this.cells[this.cellIndex];

  context.drawImage(spritesheet , cell.x , cell.y , cell.w , cell.h , sprite.left , sprite.top , cell.w , cell.h);

  }

  }

  而普通的繪制器就更簡單了,直接寫一個painter,把要畫的什麼東西都寫進去就行了。

  有了精靈類和精靈表繪制器後,我們就可以把星星,飛機,子彈,爆炸對象都寫出來了:下面是整個allSprite.js的代碼:

  JavaScript Code復制內容到剪貼板

  (function(W){

  "use strict"

  var planWidth = 24,

  planHeight = 24,

  missleWidth = 70,

  missleHeight = 70,

  boomWidth = 60;<

copyright © 萬盛學電腦網 all rights reserved