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

基于HTML5的横版射击游戏,参考自flash游戏《双面特工》。左右方向键控制移动,下方向键蹲下,上
首页 新闻资讯 行业资讯 基于HTML5的横版射击游戏发布

功能说明:

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

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

效果预览:

移步原文预览

实现分析:

1.关于多层地图。  

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

新增的layer对象:

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

复制

/**          *层对象          **/                                         var layer = function(id,mapMatrix, options) {                    if (!(this instanceof arguments.callee)) {                  return new arguments.callee(id,mapMatrix, options);              }              this.init(id,mapMatrix, options);          }          layer.prototype={                            /**              *初始化              **/              init: function(id,mapMatrix,options) {                  /**                  *默认对象                  **/                      var defaultObj = {                      cellSize: [32, 32],   //方格宽,高                      x: 0,                      //layer起始x                      y: 0                  //layer起始y                        };                      optionsoptions = options || {};                  options = cg.core.extend(defaultObj, options);                  this.id=options.id;                  this.mapMatrix = mapMatrix;                  this.cellSize = options.cellSize;                  this.x = options.x;                  this.y = options.y;                  this.row = mapMatrix.length; //有多少行                  thisthis.width=this.cellSize[0]* mapMatrix[0].length;                  thisthis.height=this.cellSize[1]* this.row;                  this.spriteList=new cg.SpriteList();//该层上的sprite列表                  this.imgsReference=options.imgsReference;//图片引用字典:{"1":{src:"xxx.png",x:0,y:0},"2":{src:"xxx.png",x:1,y:1}}                  this.zIindex=options.zIndex;              },              /**              *添加sprite              **/                          addSprites:function(sprites){                  if (cg.core.isArray(sprites)) {                      for (var i = 0, len = sprites.length; i < len; i++) {                          arguments.callee.call(this, sprites[i]);                      }                  }                  else{                      this.spriteList.add(sprites);                      sprites.layer=this;                  }                                                },              /**              *获取特定对象在layer中处于的方格的值              **/              getPosValue: function(x, y) {                  if (cg.core.isObject(x)) {                      y = x.y;                      xx = x.x;                  }                  var isUndefined = cg.core.isUndefined;                  y = Math.floor(y / this.cellSize[1]);                  x = Math.floor(x / this.cellSize[0]);                  if (!isUndefined(this.mapMatrix[y]) && !isUndefined(this.mapMatrix[y][x])) {                      return this.mapMatrix[y][x];                  }                  return undefined;              },              /**              *获取特定对象在layer中处于的方格索引              **/              getCurrentIndex: function(x, y) {                  if (cg.core.isObject(x)) {                      y = x.y;                      xx = x.x;                  }                  return [Math.floor(x / this.cellSize[0]), Math.floor(y / this.cellSize[1])];              },              /**              *获取特定对象是否刚好与格子重合              **/              isMatchCell: function(x, y) {                  if (cg.core.isObject(x)) {                      y = x.y;                      xx = x.x;                  }                  return (x % this.cellSize[0] == 0) && (y % this.cellSize[1] == 0);              },              /**              *设置layer对应位置的值              **/              setPosValue: function(x, y, value) {                  this.mapMatrix[y][x] = value;              },              /**              *更新层上的sprite列表              **/                          update:function(duration){                  this.spriteList.update(duration);                                },              /**              *根据layer的矩阵绘制layer和该layer上的所有sprite              **/              draw: function() {                  var mapMatrix = this.mapMatrix;                  var beginX = this.x;                  var beginY = this.y;                  var cellSize = this.cellSize;                  var currentRow;                  var currentCol                  var currentObj;                  var row = this.row;                  var img;                  var col;                  for (var i = beginY, ylen = beginY + row * cellSize[1]; i < ylen; i += cellSize[1]) {    //根据地图矩阵,绘制每个方格                      currentRow = (i - beginY) / cellSize[1];                      col=mapMatrix[currentRow].length;                      for (var j = beginX, xlen = beginX + col * cellSize[0]; j < xlen; j += cellSize[0]) {                          currentCol = (j - beginX) / cellSize[0];                          currentObj = this.imgsReference[mapMatrix[currentRow][currentCol]];                          if(currentObj){                              currentObjcurrentObj.x = currentObj.x || 0;                              currentObjcurrentObj.y = currentObj.y || 0;                              img = cg.loader.loadedImgs[currentObj.src];                              //绘制特定坐标的图像                              cg.context.drawImage(img, currentObj.x, currentObj.y, cellSize[0], cellSize[1], j, i, cellSize[0], cellSize[1]);                           }                      }                  }                  //更新该layer上所有sprite                  this.spriteList.draw();                    }          }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

  • 18.

  • 19.

  • 20.

  • 21.

  • 22.

  • 23.

  • 24.

  • 25.

  • 26.

  • 27.

  • 28.

  • 29.

  • 30.

  • 31.

  • 32.

  • 33.

  • 34.

  • 35.

  • 36.

  • 37.

  • 38.

  • 39.

  • 40.

  • 41.

  • 42.

  • 43.

  • 44.

  • 45.

  • 46.

  • 47.

  • 48.

  • 49.

  • 50.

  • 51.

  • 52.

  • 53.

  • 54.

  • 55.

  • 56.

  • 57.

  • 58.

  • 59.

  • 60.

  • 61.

  • 62.

  • 63.

  • 64.

  • 65.

  • 66.

  • 67.

  • 68.

  • 69.

  • 70.

  • 71.

  • 72.

  • 73.

  • 74.

  • 75.

  • 76.

  • 77.

  • 78.

  • 79.

  • 80.

  • 81.

  • 82.

  • 83.

  • 84.

  • 85.

  • 86.

  • 87.

  • 88.

  • 89.

  • 90.

  • 91.

  • 92.

  • 93.

  • 94.

  • 95.

  • 96.

  • 97.

  • 98.

  • 99.

  • 100.

  • 101.

  • 102.

  • 103.

  • 104.

  • 105.

  • 106.

  • 107.

  • 108.

  • 109.

  • 110.

  • 111.

  • 112.

  • 113.

  • 114.

  • 115.

  • 116.

  • 117.

  • 118.

  • 119.

  • 120.

  • 121.

  • 122.

  • 123.

  • 124.

  • 125.

  • 126.

  • 127.

  • 128.

  • 129.

  • 130.

  • 131.

  • 132.

  • 133.

  • 134.

  • 135.

  • 136.

  • 137.

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

复制

/*    背景矩阵    */  var bgMatrix = [                      [1,1,1],                      [1,1,1],                      [1,1,1]                  ];   this.map = new cnGame.Map({width:3000,height:3000});  var newnewLayer=new cnGame.Layer("bg",bgMatrix, { cellSize: [1000, 1000], width: this.map.width, height: this.map.height });  newLayer.imgsReference={ "1": { src: srcObj.bg }};  this.map.addLayer(newLayer);
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

2.关于移动场景。 

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

view对象新增的方法:applyInView:

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

复制

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

  • 2.

在绘制时:

复制

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

  • 2.

  • 3.

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

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

复制

/**              *使坐标相对于view              **/              applyInView:function(func){                      cg.context.save();                  cg.context.translate(-this.x, -this.y);                  func();                  cg.context.restore();              },
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

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

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

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

【编辑推荐】

  1. HTML5人工智能基础及OO实践

  2. 10个绝对让你疯狂的HTML5和JS实验性展示

  3. 浅谈Web自动化测试原理

  4. HTML5游戏开发的五个最佳实践

  5. 分享21个最新的超酷web设计特效

13    2012-04-01 10:02:00    HTML5