【pixi.js】画面にマップチップを表示しよう:PIXI.Sprite編

javascript

GUI Sprite

こんにちは。継続の錬金術士なおキーヌです。

ブログ毎日更新は120日目になります。

【pixi.js】Spriteを学ぶ前にGUIスペースを確保しようの続きですね。

今回からPIXI.Sprite編ということで画像を使いますので、下記のリンクからファイルをダウンロードして、
解凍して出てきた中身を全てsrcディレクトリの中にドラッグ&ドロップで入れてください。

PIXI.Sprite用のファイルをDL

それではSpriteについて学んでいきます。

Spriteはゲームらしくするには必須の手法なのでしっかりと学んでください。

結論から言うと100%理解する必要は無いので、まずはSpriteを使った画像の表示をするためのやり方を覚えていきましょう。

前回から打って変わってガラリとソースコードが変化します。

いつも通り最後にソースコードを乗せておくので動かない場合は照らし合わせてください。

といってもGraphicsを使っていたところをSpriteに置き換えてるだけです。

が、画像をロードするためにローダーという概念も使いますので、
今までと比べて少しだけ難易度があがりますが、なるべくわかりやすく説明していこうと思います。

ひとまずGraphics型の配列をSprite型に置き換えてみましょう。

GraphicsクラスをSpriteクラスに置き換えてみよう

変数宣言の部分でArray<PIXI.Graphics>になっていたものを、
Array<PIXI.Sprite>に変更するだけです。

    // マップ用変数
    private MapChips:Array<PIXI.Sprite> = [];

    // Window背景変数
    private GuiFrameBacks:Array<PIXI.Graphics> = [];

    // GUI用変数
    private GuiFrame:Array<PIXI.Sprite> = [];

    // マップデータ
    private MapData:Array<number> = [
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
    ];

新しくGraphics配列とマップデータを用意していますが、あとから使いますので記述しておいてください。

次に、生成する部分をSrpiteに変更したいのですがその前に画像をロードして
テクスチャとして渡すという処理をしなければいけません。

今回初めて学ぶローディング処理を作ってみましょう。

ローダーを用意する

第一回目から土台を用意した時に既にローダーのエイリアスがあったことに気付いていましたでしょうか?
使うまで消そうと思ったのですが、すぐに使用すると思ってエイリアスだけ設定しておいたのです。

    // ローダー
    private PIXI_loader = PIXI.loader
    // リソースローダー
    private PIXI_resources= PIXI.loader.resources

ローダーとリソースローダーがあるのですが、使い方としては

ローダーで画像そのものを読み込み

リソースローダーは読み込んだ画像を使う時に使用します。

それではまずはローダーを使ってみましょう。

    // PIXIローダー
    private loadingResrouces() {
        // エイリアスで設定したローダーの呼び出し
        this.PIXI_loader
        // addメソッドの引数にロードしたい画像ファイルパスを渡す
        .add(__dirname + "/src/assets/images/games/mapchip/testmap.png")
        .add(__dirname + "/src/assets/images/games/system/system.png")
        .add(__dirname + "/src/json/spritesheets/mapchip/testmap.json")
        .add(__dirname + "/src/json/spritesheets/system/system.json")
        // チェーンメソッドでプログレス機能を稼働
        .on("progress", (loader, resource)=>{
            console.log("progress: " + loader.progress + "%"); 
        })
        // ロード終了後に実行する関数を指定する
        .load(() => {
            // 
            this.spriteSetup();
            //  ループ関数起動
            this.setup();
        })
    }

新しくloadingResroucesメソッドを作ります。

エイリアスを作ったthis.PIXI_loaderを使ってaddメソッドを呼び出します。

この際、引数に読み込みたいファイルパスを指定します。

記事の冒頭で画像とjsonファイルをダウンロードしてもらったと思うので、指定のディレクトリに入っていると思いますが
もう一度ちゃんと格納できているか確認しておいてください。

addメソッドはメソッドチェーンで連続して読み込みたいファイルを指定できる

メソッドチェーンの仕組みは割愛しますが、loaderがこういう使い方をしなければいけないようなので
ヘタに自分なりのやり方をするのではなくてちゃんと従っておきましょう。

画像ファイルであるpngと画像ファイルの情報をまとめたjsonファイルは基本的にセットで使います。

1枚絵のようなものはjsonファイルは不要ですが、ウィンドウ用のパーツやキャラクターの歩行グラフィック等は
切り取り情報などをまとめたjsonファイルが必須です。

このjsonファイルを作るにはTexturePackerGUIというソフト等を使って作ると楽です。

今回は私がjsonファイルを構築したので作り方は割愛します。

onメソッドで特定の処理を実行することが可能

今のところ詳しく調べていないので、progressという命令を起動すればローディング状況を知ることが出来ます。

現在はconsole.logに出していますが、これを活用すればローディング画面などを作ることが出来ます。

そのうちローディング画面の作り方も公開しようと思います。

loadメソッドは読み込み終わった後に実行したい処理を記述する

Spriteの設定をするのは基本的にここで指定しましょう。

このローダーは非同期処理で動いているので、これ以外の場所で動かすと画像が読み込む前にSprite設定の実行が去れてしまい、
画像が読み込まれていないのに設定しようとするのでエラーが出てしまいます。

Spriteの設定をまとめたメソッドはこのloadメソッドの中で呼び出しましょう。

各種Spriteを設定するspriteSetup関数を作ろう

ローダーがファイルの読み込みを完了したらSpriteのテクスチャに画像を適用することが出来るので
設定をまとめたspriteSetup関数を作ってみましょう

テクスチャをまとめたスプライトシートを使う

jsonファイルで画像を分割した情報を記載しているので、それぞれの画像のテクスチャをkey:value型のオブジェクトを取得できます。

    // セットアップ関数
    private spriteSetup() {
        // テクスチャを準備する
        let mapchips:PIXI.Spritesheet | undefined = this.PIXI_resources[__dirname + "/src/json/spritesheets/mapchip/testmap.json"].spritesheet;
        let systemGraphics:PIXI.Spritesheet | undefined = this.PIXI_resources[__dirname + "/src/json/spritesheets/system/system.json"].spritesheet;
        if(mapchips !== undefined && systemGraphics !== undefined) {
            this.MapChipsInit(mapchips);
            this.GuiFrameInit(systemGraphics);
        }
        // オブジェクトをステージに追加
        this.addStageInit();
    }

今度はエイリアスで設定したリソースローダーを使います。

ローダーで読み込んだファイルパス+拡張子で呼び出すことができ、メソッドのspritesheetを呼び出すことで
読み込んだ画像のスプライトシートを取得することが出来ます。

その後、取得して格納した変数がundefinedでないか調べてから、Spriteを生成するメソッドを呼び出しましょう。

プログラム小話:例外処理について

ちょっとTypeScriptの話になるのですが、型にPIXI.Spritesheetのほかにundefinedと指定していますが
これをしないとエラーになってしまいます。

というのも、ファイルを読み込むという処理はTypeScriptやJavascriptに限らずエラーが発生する場合があります。

例えばファイルそのものは存在してても、ファイルが壊れていて読み込めない場合に正常に読み込みません。

その際に例外処理という記法をしなければプログラムそのものがエラーで止まってしまうことがあります。

TypeScriptもそれに習って取得できなかった時の準備をしておかなければいけません。

ifでundefined出ないか調べているのはそれが理由です。

MapChipInitをSpriteに変更しよう

PIXI.Graphicsの時からだいぶ変化しました。

引数の型もPIXI.Spritesheetに変化していますので気を付けてください。

引数には先ほどのリソースローダーで取得したものを渡す予定です。

    // テクスチャネームを返す
    private getTextureName(str:string, i:number) {
        return `${str}${i}.png`;
    }

    // マップチップ初期化
    private MapChipsInit(textureData:PIXI.Spritesheet) {
        // y座標折り返しカウント
        let yCount:number = 0;
        // 画面サイズ分のマップチップ配列生成
        for (let i=0; i<this.MapData.length; i++ ) {
            // 長いのでテクスチャ名のエイリアスを作っておく
            let textureName = this.getTextureName(textureData.data.meta.name,this.MapData[i]);
            // i番目の配列にnewする
            this.MapChips[i] = new PIXI.Sprite(textureData.textures[textureName]);
            // i番目のx座標設定
            this.MapChips[i].x = ((i%SYSTEM.gridX) * SYSTEM.chipSize) + SYSTEM.fixMapPosition;
            // X座標が端っこまで行ったら改行する
            if(i !== 0 && i%SYSTEM.gridX === 0) {
              // y座標折り返しカウントをインクリメント
              yCount++;
            } 
            // i番目のy座標設定
            this.MapChips[i].y = yCount * SYSTEM.chipSize + SYSTEM.fixMapPosition;
            // i番目の横幅設定
            this.MapChips[i].width = SYSTEM.chipSize;
            // i番目の縦幅設定
            this.MapChips[i].height = SYSTEM.chipSize;
        }
    }

やっていることはGraphicsの時とあまり変わっていません。

PIXI.Spriteに変化したので、newするときにテクスチャを渡してあげます。

テクスチャは渡された引数からjsonで記述している名前を指定すると対応したテクスチャを取得することが出来ます。

getTextureNameについて

テクスチャ名を取得するためのコードが長いのでエイリアスを作ってみやすいようにしているだけです。

直接記述しても問題ないのでお好きなように記述してください。

気を付けてほしいのは、拡張子(ここでは.png)までつけるのを忘れないようにしてください。

後は一次元配列を二次元配列のように描写するだけです。

今回からマップチップを並べるのでswのフラグによる色の切り替えはすべて削除しています。

GuiFrameInitをSpriteに変更しよう

少し長くなってしまいますが、やっていることは結構単純なのでしっかりと見ていきましょう。

    // GUIフレーム用意関数
    private GuiFrameInit(textureData:PIXI.Spritesheet) {

        // iを8で割った余りによって生成するものを変化させる
        for (let i=0; i<SYSTEM.guiParams.length; i++) {
            if(i%8 < 4) {
                switch(i%8) {
                    case 0:
                        // フレーム左上
                        this.GuiFrame[i] = new PIXI.Sprite(textureData.textures["windowLeftTop.png"]);
                        break;
                    case 1:
                        // フレーム左下
                        this.GuiFrame[i] = new PIXI.Sprite(textureData.textures["windowLeftBottom.png"]);
                        break;
                    case 2:
                        // フレーム右上
                        this.GuiFrame[i] = new PIXI.Sprite(textureData.textures["windowRightTop.png"]);
                        break;
                    case 3:
                        // フレーム右下
                        this.GuiFrame[i] = new PIXI.Sprite(textureData.textures["windowRightBottom.png"]);
                        break;
                }
            } else {
                switch(i%8) {
                    case 4:
                        // フレーム上部繰り返し用
                        this.GuiFrame[i] = new PIXI.extras.TilingSprite(textureData.textures["windowRepeatFrameTop.png"]);
                        break;
                    case 5:
                        // フレーム下部繰り返し用
                        this.GuiFrame[i] = new PIXI.extras.TilingSprite(textureData.textures["windowRepeatFrameBottom.png"]);
                        break;
                    case 6:
                        // フレーム左部繰り返し用
                        this.GuiFrame[i] = new PIXI.extras.TilingSprite(textureData.textures["windowRepeatFrameTop.png"]);
                        break;
                    case 7:
                        // フレーム右部繰り返し用
                        this.GuiFrame[i] = new PIXI.extras.TilingSprite(textureData.textures["windowRepeatFrameBottom.png"]);
                        break;
                }                
            }
        }

        // ウィンドウ背景スプライト生成
        for (let i=0; i<SYSTEM.windowBack.length; i++) {
            this.GuiFrameBacks[i] = new PIXI.Graphics();
        }

        // ウィンドウ背景設定
        this.GuiFrameBacks.map((item,key) => {
            item.x = SYSTEM.windowBack[key].x;
            item.y = SYSTEM.windowBack[key].y;
            item.width = SYSTEM.windowBack[key].width;
            item.height = SYSTEM.windowBack[key].height;
            item.alpha = SYSTEM.windowBack[key].alpha;
            item.beginFill(SYSTEM.windowBack[key].color);
            item.drawRect(0,0,SYSTEM.windowBack[key].width,SYSTEM.windowBack[key].height);
            item.endFill();
        });

        // 全てのGUIチップサイズを一旦設定
        this.GuiFrame.map( (item,key) => {
            item.x = SYSTEM.guiParams[key].x;
            item.y = SYSTEM.guiParams[key].y;
            item.width = SYSTEM.guiParams[key].width;
            item.height = SYSTEM.guiParams[key].height;
            item.rotation = SYSTEM.guiParams[key].rotation;
            item.anchor.set( SYSTEM.guiParams[key].anchor,SYSTEM.guiParams[key].anchor);
        });
    }

とても長いですね。

上から見ていきましょう。

iを8で割った余りによって生成するものを変化させる

と書いているところのコードですが、フレーム枠のSpriteを作っています。

詳細を書くと角になる四隅の角用スプライトと、上下左右の辺用のスプライトで合計8つ使いますね。

今回はマップを囲む用のフレーム枠、メッセージ用のフレーム枠、ステータス描写用のフレーム枠、お金を表示するためのフレーム枠の
4つのフレームを用意したいので8×4で32つのSpriteが必要になります。

32回ループして、ループ数を8で割った余り(i%8)を見ると

0..1..2..3..4..5..6..7..0

という風に0~7繰り返し値を得ることが出来ます。

テクスチャ名をリテラルで表記していますが、今のところいい方法が思いつかないのでそのままにしています。

今回作るゲームはそこまで長いプログラムでもないので支障はないでしょう。

PIXI.extras.TilingSpriteについて

ループの中のiが4以上の時に条件として一致する部分、つまりGUIフレームの辺の部分のSpriteですね。

普通のSpriteと違ってextras.TilingSpriteを使用しています。

親がSpriteなのでSprite型でも入れることが出来ます。

TilingSpriteとは、その名の通りタイル状にSpriteを並べるために使用します。

変の画像は4×4の小さい画像で同じ画像を繰り返し表示したいときとかに有効です。

使い方はSpriteと大して違わないので、今のところは深くは説明しません。

知りたい方はPIXI.JSのリファレンスを見てください。

ウィンドウ背景スプライト生成

GUIフレームだけでは真っ黒で物足りないので、背景を用意してみましょう。

冒頭で用意したWindow背景用の配列に組み込んでいきます。

やっていることはGraphicsでべた塗りをしてフレームの位置に合わせているだけなので割愛します。

1つだけ言うと、4つの矩形を用意するのですがマップを表示しているところは透明にしています。

実はこれはゲームにおいて結構重要で、画面を暗転したりする際に透明度を少しずつ上げたり下げたりして、
フェードインアウトの効果を使用できるようになります。

後はGUIフレームも背景もmapメソッドを使って自分の配列分処理を回して、
SYSTEMモジュールに組み込んでいる値を渡して生成しましょう。

最後に出力結果を乗せておきます。

pixi.js コンパイル結果

マップデータについて

最後にマップデータについて説明しておきます。

しれっとマップデータを描写していましたが、冒頭で用意したマップデータを使って配列を作っています。

その配列の値を見て、該当するテクスチャの番号と一致したものを描写するようにしています。

これはRPG系のマップ作りの基本になります。

もう一度見ておきましょう。

    // マップデータ
    private MapData:Array<number> = [
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
    ];

今のところマップエディタが無いので全部手打ちで作りましたが、
本来はマップエディタを作って保存した時にこの形に出力するのがゲーム作りにおいてのデファクトスタンダードです。

よく見てみるとマップにみえてこないですか?

これで言えば2が壁で1が地面です。

ちなみに1のところを0に変えると真っ黒になるので落とし穴みたいな感じで使えたりします。

──今後やっていくことを話しておくと、このマップと同じ配列を用意して
0は通行可能、1は通行不可能、等することで衝突判定を作ることが出来ます。

アクションゲームでの衝突判定は矩形に対して条件式を作りましたが、
RPGなどのグリッドで移動するタイプのゲームは衝突判定の作り方が劇的に楽になります。

その先の数字は何かということだけを判断して分岐すればいいので、
ゲームプログラミング初心者は実は簡単なRPGを作るのが一番向いていると個人的に思います。

利用した素材について

今回、ゲームぽくするためにドット絵を用意したかったのですがゲームプログラミングを優先するため
ぴぽや倉庫」様から素材をお借りしております。

一応、切り取り、素材を配布という形になるので
改造と再配布に該当してしまうのでダメかなーと思って規約を見たところ、どちらも有償でなければ大丈夫だということで
今回利用させていただくことになりました。

今回ゲームを作っていく上で色々活用させていこうと考えております。

自作画像は後から設定すればいいので、ゲームプログラミングに集中できますね。感謝です。

いつも通り最後に今回のソースコードを貼っておきます。

それでは。

import * as PIXI from 'pixi.js'
import { SYSTEM } from '../../config/system';

class PIXI_MainProcess {

    /**
     * ----------------------------------------------------
     * エイリアス作成
     * ----------------------------------------------------
     *  */ 
    // pixi.jsアプリケーション
    private PIXI_Application = PIXI.Application
    // ローダー
    private PIXI_loader = PIXI.loader
    // リソースローダー
    private PIXI_resources= PIXI.loader.resources

    /**
     * ----------------------------------------------------
     * クラス変数
     * ----------------------------------------------------
     *  */ 
    // pixiアプリケーション生成
    private App:PIXI.Application = this.pixiApplicationCreate(SYSTEM.width,SYSTEM.height);

    //--------------------------------------------

    // マップ用変数
    private MapChips:Array<PIXI.Sprite> = [];

    // Window背景変数
    private GuiFrameBacks:Array<PIXI.Graphics> = [];

    // GUI用変数
    private GuiFrame:Array<PIXI.Sprite> = [];

    // マップデータ
    private MapData:Array<number> = [
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
    ]

    //--------------------------------------------

    // コンストラクタ
    constructor() {
        // 初期化プロセス
        this.initializePIXI();
    }

    // 初期化プロセス
    private initializePIXI() {

        // ピクセル倍率変更
        this.pixelScaleUP();

        // htmlのbodyにPIXIAPPを追加
        document.body.appendChild(this.App.view);

        // Sprite初期化
        this.loadingResrouces();

    }

    // PIXIアプリケーションオブジェクト作成
    private pixiApplicationCreate(screenWidth:number,screenHeight:number) {
        return new this.PIXI_Application({
            width:screenWidth,
            height:screenHeight,
            antialias: false,
            transparent: false,
            resolution: 2
            }
        );
    }

    // ピクセル倍率を2倍に変更
    private pixelScaleUP() {
        this.App.renderer.roundPixels = true;
        this.App.renderer.resize(SYSTEM.width, SYSTEM.height);
        this.App.stage.scale.set(1,1);
        this.App.stage.interactive = true;
        PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.NEAREST;
    }


    // // セットアップ関数
    private setup() {
        this.App.ticker.add(delta => this.gameloop(delta));
    }

    // メインループ
    private gameloop(delta:number) {
    }

    // PIXIローダー
    private loadingResrouces() {
        // エイリアスで設定したローダーの呼び出し
        this.PIXI_loader
        // addメソッドの引数にロードしたい画像ファイルパスを渡す
        .add(__dirname + "/src/assets/images/games/mapchip/testmap.png")
        .add(__dirname + "/src/assets/images/games/system/system.png")
        .add(__dirname + "/src/json/spritesheets/mapchip/testmap.json")
        .add(__dirname + "/src/json/spritesheets/system/system.json")
        // チェーンメソッドでプログレス機能を稼働
        .on("progress", (loader, resource)=>{
            console.log("progress: " + loader.progress + "%"); 
        })
        // ロード終了後に実行する関数を指定する
        .load(() => {
            this.spriteSetup();
        })
    }

    // テクスチャネームを返す
    private getTextureName(str:string, i:number) {
        return `${str}${i}.png`;
    }

    // セットアップ関数
    private spriteSetup() {
        // テクスチャを準備する
        let mapchips:PIXI.Spritesheet | undefined = this.PIXI_resources[__dirname + "/src/json/spritesheets/mapchip/testmap.json"].spritesheet;
        let systemGraphics:PIXI.Spritesheet | undefined = this.PIXI_resources[__dirname + "/src/json/spritesheets/system/system.json"].spritesheet;
        if(mapchips !== undefined && systemGraphics !== undefined) {
            this.MapChipsInit(mapchips);
            this.GuiFrameInit(systemGraphics);
        }
        // オブジェクトをステージに追加
        this.addStageInit();
    }

    // マップチップ初期化
    private MapChipsInit(textureData:PIXI.Spritesheet) {
        // y座標折り返しカウント
        let yCount:number = 0;
        // 画面サイズ分のマップチップ配列生成
        for (let i=0; i<this.MapData.length; i++ ) {
            // 長いのでテクスチャ名のエイリアスを作っておく
            let textureName = this.getTextureName(textureData.data.meta.name,this.MapData[i]);
            // i番目の配列にnewする
            this.MapChips[i] = new PIXI.Sprite(textureData.textures[textureName]);
            // i番目のx座標設定
            this.MapChips[i].x = ((i%SYSTEM.gridX) * SYSTEM.chipSize) + SYSTEM.fixMapPosition;
            // X座標が端っこまで行ったら改行する
            if(i !== 0 && i%SYSTEM.gridX === 0) {
              // y座標折り返しカウントをインクリメント
              yCount++;
            } 
            // i番目のy座標設定
            this.MapChips[i].y = yCount * SYSTEM.chipSize + SYSTEM.fixMapPosition;
            // i番目の横幅設定
            this.MapChips[i].width = SYSTEM.chipSize;
            // i番目の縦幅設定
            this.MapChips[i].height = SYSTEM.chipSize;
        }
    }

    // GUIフレーム用意関数
    private GuiFrameInit(textureData:PIXI.Spritesheet) {

        // iを8で割った余りによって生成するものを変化させる
        for (let i=0; i<SYSTEM.guiParams.length; i++) {
            if(i%8 < 4) {
                switch(i%8) {
                    case 0:
                        // フレーム左上
                        this.GuiFrame[i] = new PIXI.Sprite(textureData.textures["windowLeftTop.png"]);
                        break;
                    case 1:
                        // フレーム左下
                        this.GuiFrame[i] = new PIXI.Sprite(textureData.textures["windowLeftBottom.png"]);
                        break;
                    case 2:
                        // フレーム右上
                        this.GuiFrame[i] = new PIXI.Sprite(textureData.textures["windowRightTop.png"]);
                        break;
                    case 3:
                        // フレーム右下
                        this.GuiFrame[i] = new PIXI.Sprite(textureData.textures["windowRightBottom.png"]);
                        break;
                }
            } else {
                switch(i%8) {
                    case 4:
                        // フレーム上部繰り返し用
                        this.GuiFrame[i] = new PIXI.extras.TilingSprite(textureData.textures["windowRepeatFrameTop.png"]);
                        break;
                    case 5:
                        // フレーム下部繰り返し用
                        this.GuiFrame[i] = new PIXI.extras.TilingSprite(textureData.textures["windowRepeatFrameBottom.png"]);
                        break;
                    case 6:
                        // フレーム左部繰り返し用
                        this.GuiFrame[i] = new PIXI.extras.TilingSprite(textureData.textures["windowRepeatFrameTop.png"]);
                        break;
                    case 7:
                        // フレーム右部繰り返し用
                        this.GuiFrame[i] = new PIXI.extras.TilingSprite(textureData.textures["windowRepeatFrameBottom.png"]);
                        break;
                }                
            }
        }

        // ウィンドウ背景スプライト生成
        for (let i=0; i<SYSTEM.windowBack.length; i++) {
            this.GuiFrameBacks[i] = new PIXI.Graphics();
        }

        // ウィンドウ背景設定
        this.GuiFrameBacks.map((item,key) => {
            item.x = SYSTEM.windowBack[key].x;
            item.y = SYSTEM.windowBack[key].y;
            item.width = SYSTEM.windowBack[key].width;
            item.height = SYSTEM.windowBack[key].height;
            item.alpha = SYSTEM.windowBack[key].alpha;
            item.beginFill(SYSTEM.windowBack[key].color);
            item.drawRect(0,0,SYSTEM.windowBack[key].width,SYSTEM.windowBack[key].height);
            item.endFill();
        });

        // 全てのGUIチップサイズを一旦設定
        this.GuiFrame.map( (item,key) => {
            item.x = SYSTEM.guiParams[key].x;
            item.y = SYSTEM.guiParams[key].y;
            item.width = SYSTEM.guiParams[key].width;
            item.height = SYSTEM.guiParams[key].height;
            item.rotation = SYSTEM.guiParams[key].rotation;
            item.anchor.set( SYSTEM.guiParams[key].anchor,SYSTEM.guiParams[key].anchor);
        });
    }

    // 初回ステージ追加
    private addStageInit() {
        // マップチップ配列をステージに追加
        this.addStageArray(this.MapChips);
        // GUIフレーム配列をステージに追加
        this.addStageArray(this.GuiFrame);
        // GUIフレーム背景配列をステージに追加
        this.addStageArrayGraphic(this.GuiFrameBacks);
    }

    // 配列ステージ追加メソッド(Sprite版)
    private addStageArray(ary:Array<PIXI.Sprite>) {
        ary.map( (item) => {
            this.App.stage.addChild(item);
        });
    }
    // 配列ステージ追加メソッド(Graphics版)
    private addStageArrayGraphic(ary:Array<PIXI.Graphics>) {
        ary.map( (item) => {
            this.App.stage.addChild(item);
        });
    }

}

export default PIXI_MainProcess;

const GameFrame:PIXI_MainProcess = new PIXI_MainProcess;