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

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

功能说明:

基于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 = 0len = 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 = beginYylen = beginY + row * cellSize[1]; i < ylen; i += cellSize[1]) {    //根据地图矩阵,绘制每个方格  
                    currentRow = (i - beginY) / cellSize[1];  
                    col=mapMatrix[currentRow].length;  
                    for (var j = beginXxlen = 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设计特效
责任编辑:林师授 来源: Cson的博客
相关推荐

2012-03-16 09:35:52

HTML 5

2013-06-26 10:12:09

HTML5ichartjs

2013-03-06 15:05:44

移动浏览器移动游戏HTML5

2014-12-30 17:13:51

HTML5

2013-10-21 15:24:49

html5游戏

2013-06-24 14:55:30

HTML5

2015-07-08 16:38:10

Cocos游戏引擎

2016-04-18 16:20:55

2011-12-09 20:25:16

HTML5

2011-08-01 16:43:51

ibmdwHTML5Dojo

2013-08-01 10:28:52

移动通讯应用KikHTML5游戏

2013-03-06 16:14:16

UCHTML5游戏引擎

2012-03-06 10:56:32

HTML 5

2015-07-06 09:57:04

HTML5CSS框架BootFlat

2012-03-29 09:18:47

HTML5WEB

2015-12-03 15:22:01

HTML5游戏建议

2014-12-15 10:10:26

HTML5游戏引擎

2013-01-24 10:26:04

HTML5HTML 5HTML5的未来

2014-11-12 16:00:12

火舞游戏

2013-05-28 11:08:51

人脸识别html5
点赞
收藏

51CTO技术栈公众号