ホームページ >ウェブフロントエンド >H5 チュートリアル >HTML5ベースの横型シューティングゲームを詳しく解説

HTML5ベースの横型シューティングゲームを詳しく解説

黄舟
黄舟オリジナル
2017-03-24 15:33:562952ブラウズ

機能説明:

フラッシュゲーム「Double」を参考にしたHTML5ベースの横スクロールシューティングゲーム-エージェント」。 左右の矢印キーで移動を制御し、下矢印キーでジャンプし、スペースキーで射撃します。

このゲームは、自社開発の HTML5 ゲーム フレームワーク cnGameJS に基づいています。 :

HTML5ベースの横型シューティングゲームを詳しく解説実装分析:

1.多層マップについて

以前のHTML5ゲーム「Tank Support Team」では、使用されたマップは単純な単層マップのみでした。つまり、石しかありません。ただし、この単一レイヤーのマップには比較的大きな制限があります (スーパー マリオや上記のゲームなど)。多くの場合、1 つのレイヤーだけでは十分ではありません。ゲームの主人公が立っている障害物に加えて、ゲームの背景 (後ろの壁など) などの要素もあるため、レイヤーを重ねる必要があります。マルチレイヤー表示の目的を達成するためのマップ オブジェクト

新規追加レイヤー オブジェクト:

各レイヤー オブジェクトはレイヤーのスプライトを維持し、それらの更新と描画を担当し、オブジェクト上の指定された座標の値を取得できます。レイヤーオブジェクトのソースコードは以下の通りです:

/**
        *层对象
        **/                               
        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({width:3000,height:3000});
var newLayer=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);

2. モバイルシーンについて

前回のHTML5「ゲームスーパーマリオゲームデモ」では、ゲームプレイヤーの動きをゲームシーンに変換して、プレイヤーの固定とシーンの移動の効果を実現しましたが、この実装方法には大きな問題があります。マップとプレイヤーの xy 値が変更されるため、非常に不便になります より良い実装方法は、プレイヤーとマップの xy 値を変更せず、座標のみを変更することです。

ビューオブジェクトの新しいメソッド: applyInView:

applyIn

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);
描画時:
 this.view.applyInView(function(){
            map.draw();        
        });

このようにして、マップ内のすべての要素がビューに対して相対的に移動します

applyInView の実装原理も非常に単純で、単に継続的に実行するだけです。描画原点とビューを変更します。座標は等しく反対です:

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

このようにして、ビューの座標がどのように変化しても、ビューは常に

canvas

上に視覚的に固定され、他の要素の座標は常に固定されます。ビューに対して視覚的に相対的に。

以上がHTML5ベースの横型シューティングゲームを詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。