基于HTML5的横版射击游戏发布

功能说明:

基于HTML5的横版射击游戏,参考自flash游戏《双面特工》左右方向键控制移动,下方向键蹲下,上方向键跳跃,空格键射击。体验前请先关闭输入法。

该游戏基于自己开发的HTML5游戏框架cnGameJS。

效果预览:

移步原文预览

实现分析:

1.关于多层地图。

在上一个HTML5游戏《坦克后援队》中,所用的地图只为简单的单层地图,意思是地图中除了石头就是空地,仅仅只有一层的地图。但是这种单层地图具有比较大的局限性,如果需要实现场景类的游戏(例如超级玛丽和上面的游戏),只有一层的地图往往是不够的,因为我们除了游戏主角所站的障碍物外,还有游戏背景等元素(例如后面的墙壁等),因此我们需要为地图对象分层,从而达到多层展示的目的。

新增的layer对象:

每个layer对象维护该层的sprite,负责更新和绘制它们,并且可以获取指定坐标在该层的矩阵上的值。layer对象源码如下:

  
  
  
  
  1. /**  
  2.         *层对象  
  3.         **/                                 
  4.         var layer = function(id,mapMatrix, options) {  
  5.       
  6.             if (!(this instanceof arguments.callee)) {  
  7.                 return new arguments.callee(id,mapMatrix, options);  
  8.             }  
  9.             this.init(id,mapMatrix, options);  
  10.         }  
  11.         layer.prototype={  
  12.               
  13.             /**  
  14.             *初始化  
  15.             **/  
  16.             init: function(id,mapMatrix,options) {  
  17.                 /**  
  18.                 *默认对象  
  19.                 **/      
  20.                 var defaultObj = {  
  21.                     cellSize: [32, 32],   //方格宽,高  
  22.                     x: 0,                      //layer起始x  
  23.                     y: 0                  //layer起始y  
  24.       
  25.                 };      
  26.                 optionsoptions = options || {};  
  27.                 options = cg.core.extend(defaultObj, options);  
  28.                 this.id=options.id;  
  29.                 this.mapMatrix = mapMatrix;  
  30.                 this.cellSize = options.cellSize;  
  31.                 this.x = options.x;  
  32.                 this.y = options.y;  
  33.                 this.row = mapMatrix.length; //有多少行  
  34.                 thisthis.width=this.cellSize[0]* mapMatrix[0].length;  
  35.                 thisthis.height=this.cellSize[1]* this.row;  
  36.                 this.spriteList=new cg.SpriteList();//该层上的sprite列表  
  37.                 this.imgsReference=options.imgsReference;//图片引用字典:{"1":{src:"xxx.png",x:0,y:0},"2":{src:"xxx.png",x:1,y:1}}  
  38.                 this.zIindex=options.zIndex;  
  39.             },  
  40.             /**  
  41.             *添加sprite  
  42.             **/              
  43.             addSprites:function(sprites){  
  44.                 if (cg.core.isArray(sprites)) {  
  45.                     for (var i = 0len = sprites.length; i < len; i++) {  
  46.                         arguments.callee.call(this, sprites[i]);  
  47.                     }  
  48.                 }  
  49.                 else{  
  50.                     this.spriteList.add(sprites);  
  51.                     sprites.layer=this;  
  52.                 }                  
  53.                   
  54.             },  
  55.             /**  
  56.             *获取特定对象在layer中处于的方格的值  
  57.             **/  
  58.             getPosValue: function(x, y) {  
  59.                 if (cg.core.isObject(x)) {  
  60.                     y = x.y;  
  61.                     xx = x.x;  
  62.                 }  
  63.                 var isUndefined = cg.core.isUndefined;  
  64.                 y = Math.floor(y / this.cellSize[1]);  
  65.                 x = Math.floor(x / this.cellSize[0]);  
  66.                 if (!isUndefined(this.mapMatrix[y]) && !isUndefined(this.mapMatrix[y][x])) {  
  67.                     return this.mapMatrix[y][x];  
  68.                 }  
  69.                 return undefined;  
  70.             },  
  71.             /**  
  72.             *获取特定对象在layer中处于的方格索引  
  73.             **/  
  74.             getCurrentIndex: function(x, y) {  
  75.                 if (cg.core.isObject(x)) {  
  76.                     y = x.y;  
  77.                     xx = x.x;  
  78.                 }  
  79.                 return [Math.floor(x / this.cellSize[0]), Math.floor(y / this.cellSize[1])];  
  80.             },  
  81.             /**  
  82.             *获取特定对象是否刚好与格子重合  
  83.             **/  
  84.             isMatchCell: function(x, y) {  
  85.                 if (cg.core.isObject(x)) {  
  86.                     y = x.y;  
  87.                     xx = x.x;  
  88.                 }  
  89.                 return (x % this.cellSize[0] == 0) && (y % this.cellSize[1] == 0);  
  90.             },  
  91.             /**  
  92.             *设置layer对应位置的值  
  93.             **/  
  94.             setPosValue: function(x, y, value) {  
  95.                 this.mapMatrix[y][x] = value;  
  96.             },  
  97.             /**  
  98.             *更新层上的sprite列表  
  99.             **/              
  100.             update:function(duration){  
  101.                 this.spriteList.update(duration);  
  102.                   
  103.             },  
  104.             /**  
  105.             *根据layer的矩阵绘制layer和该layer上的所有sprite  
  106.             **/  
  107.             draw: function() {  
  108.                 var mapMatrix = this.mapMatrix;  
  109.                 var beginX = this.x;  
  110.                 var beginY = this.y;  
  111.                 var cellSize = this.cellSize;  
  112.                 var currentRow;  
  113.                 var currentCol  
  114.                 var currentObj;  
  115.                 var row = this.row;  
  116.                 var img;  
  117.                 var col;  
  118.                 for (var i = beginYylen = beginY + row * cellSize[1]; i < ylen; i += cellSize[1]) {    //根据地图矩阵,绘制每个方格  
  119.                     currentRow = (i - beginY) / cellSize[1];  
  120.                     col=mapMatrix[currentRow].length;  
  121.                     for (var j = beginXxlen = beginX + col * cellSize[0]; j < xlen; j += cellSize[0]) {  
  122.                         currentCol = (j - beginX) / cellSize[0];  
  123.                         currentObj = this.imgsReference[mapMatrix[currentRow][currentCol]];  
  124.                         if(currentObj){  
  125.                             currentObjcurrentObj.x = currentObj.x || 0;  
  126.                             currentObjcurrentObj.y = currentObj.y || 0;  
  127.                             img = cg.loader.loadedImgs[currentObj.src];  
  128.                             //绘制特定坐标的图像  
  129.                             cg.context.drawImage(img, currentObj.x, currentObj.y, cellSize[0], cellSize[1], j, i, cellSize[0], cellSize[1]);   
  130.                         }  
  131.                     }  
  132.                 }  
  133.                 //更新该layer上所有sprite  
  134.                 this.spriteList.draw();  
  135.       
  136.             }  
  137.         } 

之后我们可以很方便地创建不同的层,并添加到地图中:

  
  
  
  
  1. /*    背景矩阵    */  
  2. var bgMatrix = [  
  3.                     [1,1,1],  
  4.                     [1,1,1],  
  5.                     [1,1,1]  
  6.                 ];  
  7.  
  8. this.map = new cnGame.Map({width:3000,height:3000});  
  9. var newnewLayer=new cnGame.Layer("bg",bgMatrix, { cellSize: [1000, 1000], width: this.map.width, height: this.map.height });  
  10. newLayer.imgsReference={ "1": { src: srcObj.bg }};  
  11. this.map.addLayer(newLayer); 

2.关于移动场景。 

在上一次的HTML5《游戏超级玛丽游戏demo》中,我们通过使游戏玩家的移动转换为游戏场景的移动来实现玩家固定,场景移动的效果,但是这种实现方法有比较大的问题,因为它干涉了地图和玩家的xy值的变化,因此会带来很多不便。更好的实现方法是,保持玩家和地图的xy值不变,只改变绘制它们时原点的坐标。

view对象新增的方法:applyInView:

applyInView方法的作用是在不改变地图和玩家实际坐标的前提下,在绘制时使view固定,其他游戏元素相对于view移动,实现移动背景的效果。例如,我们需要使玩家相对于view中点固定,该map上的其他所有游戏元素相对于view移动,我们只需要在初始化时:

  
  
  
  
  1. this.view=new cnGame.View({map:this.map,x:0,y:0,width:cnGame.width,height:cnGame.height});  
  2. this.view.centerElem(this.player,true); 

在绘制时:

  
  
  
  
  1. this.view.applyInView(function(){  
  2.             map.draw();          
  3.         }); 

这样map内所有元素都会相对于view而移动。

而applyInView的实现原理也非常简单,它只是不断使绘制的原点和view的坐标等长且相反:

  
  
  
  
  1. /**  
  2.             *使坐标相对于view  
  3.             **/  
  4.             applyInView:function(func){      
  5.                 cg.context.save();  
  6.                 cg.context.translate(-this.x, -this.y);  
  7.                 func();  
  8.                 cg.context.restore();  
  9.             }, 

这样无论view的坐标如何变化,view在视觉上始终固定在canvas,其他元素的坐标在视觉上始终相对于view。

该游戏所有源码下载地址:点击下载

原文链接:http://www.cnblogs.com/Cson/archive/2012/03/15/2398129.html

你可能感兴趣的:(基于HTML5的横版射击游戏发布)