zoukankan      html  css  js  c++  java
  • 【CSON原创】基于HTML5的横版射击游戏发布

    功能说明:

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

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

    效果预览:

      

     

    实现分析:

      1.关于多层地图。  

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

      新增的layer对象:

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

      

    View Code
            /**
    *层对象
    *
    */
    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

    };
    options = 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; //有多少行
    this.width=this.cellSize[0]* mapMatrix[0].length;
    this.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;
    x = 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;
    x = 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;
    x = 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){
    currentObj.x = currentObj.x || 0;
    currentObj.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();

    }
    }

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

    /*    背景矩阵    */
    var bgMatrix = [
    [1,1,1],
    [1,1,1],
    [1,1,1]
    ];

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

      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,cnGame.width,height:cnGame.height});
    this.view.centerElem(this.player,true);

      在绘制时:

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

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

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

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

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

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

      欢迎转载,请标明出处:http://www.cnblogs.com/Cson/archive/2012/03/15/2398129.html



  • 相关阅读:
    DevExpress ASP.NET 使用经验谈(5)-通过ASPxGridView实现CRUD操作
    DevExpress ASP.NET 使用经验谈(4)-CriteriaOperator的使用
    DevExpress ASP.NET 使用经验谈(3)-XPO对象的使用(使用指定数据连接)
    DevExpress ASP.NET 使用经验谈(2)-XPO对象的使用(使用默认数据连接)
    DevExpress ASP.NET 使用经验谈(1)-XPO模型的创建
    C#堆栈原理(我有两个例子测试你到底会不会)
    C# static 干货全解析
    C# 链接 SQLite问题汇总
    EFCore AsNoTracking方法不能使用的问题;EFCore 如何取消跟踪
    2019-1-3 每日一记
  • 原文地址:https://www.cnblogs.com/Cson/p/2398129.html
Copyright © 2011-2022 走看看