3D対応版のゲームエンジンのソース

// << 三次元描画手順 >>
//  1.ローカル座標 
//  2.ワールド座標変換 
//  2.ワールド座標 
//  4.ビュー座標変換 
//  5.ビュー座標 
//  6.プロジェクション座標変換(射影変換) 
//  7.プロジェクション座標 
//  8.スクリーン座標変換 
//  9.スクリーン座標 
//  10.描画(レンダリング)
// << 座標の意味 >>
//  1. ローカル座標
//      物の座標=>物の大きさ=>縦がいくら、横がいくら、奥行きがいくら等
//      形状・構造・寸法を一定のきまりに従って記した図面上の座標
//      原点(x:0,y:0,z:0)からの相対で寸法を示す。例えば幅が60ならXは -30 ~ +30 として配置する。
//  2. ワールド座標
//      物を配置する世界。例えば物が役者で世界が舞台だとすると舞台上のどの位置に役者が
//      いるべきかを決める。舞台の中央位置を原点として相対的な座標とする。
//  3. ビュー座標
//      観察者のワールド座標上の位置。舞台の芝居を見る人の目の位置や、あるいはカメラ撮影をしている
//      場合はカメラの位置を表す。x, y, z の座標と向きを持つ。芝居を寝そべって横になりながら見る場合等
//      頭がどの方向を向いているかで、見え方が変わる。カメラ座標、視野座標などとも呼ぶ。
//  4. プロジェクション座標
//      3D の情報であるビュー座標を、投影により 2D の情報に変換した座標。 透視投影を行う。つまり
//      近くの物は大きく見えて遠くの物は小さく見える座標として二次元空間にプロットする。
//      画面(canvas)の中央が(x:0, y:0) になる。-1 から 1 の間の正規化座標とする。舞台の芝居を写真に
//      とると二次元空間に転写されるが立体感は残る。
//  5. スクリーン座標
//      プロジェクション座標をスクリーン上にプロットする。画面左上が(x:0, y:0)になる。
// << 行列演算 >>
//  求めたい行列 = 拡大行列 * 回転行列 * 平行移動行列
// << 3dcg フレームワーク >>
//  Three.js を採用 右手座標系 右方向がX軸のプラス方向、上方向がY軸のプラス方向、手前方向がZ軸のプラス方向
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// 省略時のゲームブロック要素ID
var g_idStage = "#game-stage";
// 待機メッセージ
var MsgWaiting = {
    Loading:"Now Loading"
    , Walking:"Now Auto Walk"
};
// マウス操作
var EvtMouse = {
    Click:1
    , Move:2
    , Down:3
    , Up:4
};
// ゲーム支援クラス
var clsGameUtl = function(id)
{
    this.Element = (id || g_idStage);
    // マウス操作制御用
    this.MouseState = {};
    this.ResetMouseState();
    // three オブジェクトの引数の格納用
    this.Core = {
        uFov: 60                    // 画角度(度数)
        , uNear: 1                  // 手前の臨界
        , uFar: 1000                // 奥側の臨界
        , uLightColor: "white"      // 光源の色
        , uLightIntensity: 1        // 光源の強さ
        , uFps:60                   // 描画速度(frame per second)
    };
    // 3d 描画使用有無
    this.Use3DObject = false;
    // 描画可否
    this.CanRenderer = true;
    // レンダリング停止
    this.StopRendering = false;
    // wait スタイルパラメータ設定
    this.WaitStyle = {
        Font:{ bold:true, size:18, family:"monospace" }
        , StrokeStyle:"red"
        , FillStyle:"white"
    };
    // レンダリング処理低下フラグ
    this.SlowRenderer = false;
    // インスタンス
    var inst = this;
    // フレーム処理を行う関数を得る
    if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = (
          window.webkitRequestAnimationFrame
          || window.mozRequestAnimationFrame
          || window.oRequestAnimationFrame
          || window.msRequestAnimationFrame
          || function(callback) { return window.setTimeout(callback, 1000 / inst.Core.uFps); }
        );
    }
    // フレーム停止を行う関数を得る
    if (!window.cancelAnimationFrame) {
        window.cancelAnimationFrame = (
          window.webkitCancelRequestAnimationFrame
          || window.mozCancelRequestAnimationFrame
          || window.oCancelRequestAnimationFrame
          || window.msCancelRequestAnimationFrame
          || function(id) { window.clearTimeout(id); }
        );
    }
};
// ゲーム初期化
// Stage 当オブジェクトを使用するオブジェクト
clsGameUtl.prototype.Initialize = function(Stage, NonRenderer, zIndex)
{
    // 複数回呼び出しのためにシーンを破棄
    this.Dispose();
    // 描画関数スタック
    this.aryLayer = [];
    // 呼び出し要求スタック
    this.Dispatch = [];
    // キー入力キューバッファ
    this.KeyDownQueue = [];
    // 当オブジェクトを使用するオブジェクトを記憶
    this.Core.Stage = Stage;
    // レンダラの初期化
    if (!NonRenderer) {
        // 大きさを得る
        var cx = $(this.Element).width();
        var cy = $(this.Element).height();
        // レンダラの生成
        this.Core.Renderer = new THREE.CanvasRenderer({ alpha:true });
        this.Core.Renderer.setSize(cx, cy);
        // 第1引数が色、第2引数がアルファ値(0~1
        this.Core.Renderer.setClearColor(0x000000, 0);
        // レンダー要素のスタイル設定(親の左上に合わす)
        this.Core.Renderer.domElement.style.position = "absolute";
        this.Core.Renderer.domElement.style.left = "0px";
        this.Core.Renderer.domElement.style.top = "0px";
        this.Core.Renderer.domElement.style.zIndex = (zIndex || 0);
        // ゲームブロックにレンダラを追加
        $(this.Element).append(this.Core.Renderer.domElement);
        // キャンバスを得る
        this.Core.Canvas = this.Core.Renderer.domElement.getContext('2d');
        // 3d オブジェクト生成
        if (this.Use3DObject) {
            // アスペクト比
            var ap = cx / cy;
            // シーンの作成
            this.Core.Scene = new THREE.Scene();
            // カメラの作成
            this.Core.Camera = new THREE.PerspectiveCamera(this.Core.uFov, ap, this.Core.uNear, this.Core.uFar);
            // カメラの位置
            this.Core.Camera.position = new THREE.Vector3(0, 0, 500);
            // カメラの注視点
            this.Core.Camera.lookAt(new THREE.Vector3(0, 0, 0));
            // カメラをシーンに結び付ける
            this.Core.Scene.add(this.Core.Camera);
            // ライトの作成
            this.Core.Light = new THREE.DirectionalLight(this.Core.uLightColor, this.Core.uLightIntensity);
            this.Core.Light.position = new THREE.Vector3(0, 0, 250);
            this.Core.Scene.add(this.Core.Light);
            // 照り返しなどの環境光を疑似的に再現するライト
            this.Core.Ambient = new THREE.AmbientLight(0x333333);
            this.Core.Scene.add(this.Core.Ambient);
        }
    }
    // 開始時間
    this.StartTime = this.GetTime();
}
// レイア生成
clsGameUtl.prototype.CreateLayer = function(callback, newLayer, wantClear, wantHover, zIndex)
{
    var idx = this.aryLayer.length;
    // 描画用パラメータ記憶用
    var p = { wantClear:wantClear, wantHover:wantHover, layer:idx, Frame:-1 };
    // 新規レイアならキャンバスを作成
    if (newLayer) {
        var sz = this.GetSize();
        var ec = this.NewHiddenCanvas(this.Element, sz.cx, sz.cy);
        // 可視の状態で初期化
        $(ec).css("visibility", "visible");
        $(ec).css("z-index", zIndex || 0);
        p.Elemnt = ec;
        p.Canvas = ec.getContext("2d");
    }
    else
        p.Elemnt = this.Element;
    // コールバックを記憶する
    this.aryLayer.push( { fnc:callback, prm:p } );
    // THREE のオブジェクト指標を記憶する
    if (!newLayer)
        this.Core.RendererIndex = idx;
    // レイア番号を返す
    return idx;
}
// 定期呼び出し関数登録
clsGameUtl.prototype.AddDispatch = function(callback)
{
    var idx = this.Dispatch.length;
    var prm = { Frame:-1 };
    // コールバックを記憶する
    this.Dispatch.push( { fnc:callback, prm:prm } );
    // 呼び出し番号を返す
    return idx;
}
// 定期ユーザ関数呼び出し
clsGameUtl.prototype.DoDispatch = function(idx)
{
    if (idx >= 0) {
        if (idx < this.Dispatch.length) {
            // ユーザ関数を呼び出す
            if (this.Dispatch[idx].fnc)
                this.Dispatch[idx].fnc.call(this.Core.Stage, this.Dispatch[idx].prm);
        }
    }
    else
    {
        for (var idx = 0; idx < this.Dispatch.length; idx++)
            this.DoDispatch(idx);
    }
}
// keydown イベントの設定
clsGameUtl.prototype.EnterKeyDown = function(callback)
{
    this.KeyDownProc = callback;
    // キー入力イベントの設定
    window.addEventListener('keydown', this.KeyDown.bind(this));
}
// キー入力
clsGameUtl.prototype.KeyDown = function(e)
{
    // キーをキューに入れる
    this.KeyDownQueue.push(e);
    // デフォルトイベントをキャンセルする
    e.preventDefault();
}
// キー入力キューをクリア
clsGameUtl.prototype.ClearKeyDownQueue = function()
{
    this.KeyDownQueue = [];
}
// ゲーム開始
clsGameUtl.prototype.DoGame = function()
{
    // ゲーム中フラグを設定
    this.Playing = true;
    // キー入力を渡す
    if (this.KeyDownProc) {
        if (this.KeyDownQueue.length > 0) {
            var e = this.KeyDownQueue.shift();
            this.KeyDownProc.call(this.Core.Stage, e);
        }
    }
    // 描画可能なら...
    if (this.CanRenderer) {
        // 描画コールバック
        this.DrawLayer(-1);
        // ユーザ関数呼び出し
        this.DoDispatch(-1);
        // レンダリング
        if (this.Core.Renderer) {
            // 3d オブジェクトを使用するなら撮影を行なう
            if (this.Use3DObject) {
                var prm = this.aryLayer[this.Core.RendererIndex].prm;
                // レダリング開始時刻
                var st = this.GetTime();
                // 消去要求を設定してレンダリング
                if (!this.StopRendering) {
                    this.Core.Renderer.autoClear = prm.wantClear;
                    this.Core.Renderer.render(this.Core.Scene, this.Core.Camera);
                }
                // レダリング終了時刻
                var ed = this.GetTime();
                // フレーム時間より遅いならレンダリング処理低下フラグを立てる
                if (!this.SlowRenderer)
                    this.SlowRenderer = ((ed - st) > (1000 / this.Core.uFps));
            }
        }
    }
    // コールバック
    if (this.Playing)
        this.Core.Timer = window.requestAnimationFrame(this.DoGame.bind(this));
}
// ゲーム停止
clsGameUtl.prototype.Stop = function()
{
    if (this.Playing) {
        cancelAnimationFrame(this.Core.Timer);
        this.Playing = false;
    }
}
// 描画実行
// 描画コールバック
clsGameUtl.prototype.DrawLayer = function(idx)
{
    if (idx >= 0) {
        if (idx < this.aryLayer.length) {
            var p = this.aryLayer[idx].prm;
            var c = (p.Canvas ? p.Canvas : this.Core.Canvas);
            // 消去要求ならキャンバスを消去
            if (p.Canvas && p.wantClear)
                this.ClearCanvas(p);
            // ユーザ関数を呼び出す
            if (p.StopDrawLayer)
                this.ClearCanvas(p);
            else if (this.aryLayer[idx].fnc)
                this.aryLayer[idx].fnc.call(this.Core.Stage, c, p);
        }
    }
    else
    {
        for (var idx = 0; idx < this.aryLayer.length; idx++)
            this.DrawLayer(idx);
    }
}
// 非表示 canvas 生成
clsGameUtl.prototype.NewHiddenCanvas = function(id, w, h, zIndex)
{
    // キャンバスタグ生成
    var cvs = document.createElement('canvas');
    // サイズを設定し非表示とする
    cvs.style.position = "absolute";
    cvs.style.left = "0px";
    cvs.style.top = "0px";
    cvs.style.border = "none";
    cvs.style.visibility = "hidden";
    cvs.style.zindex = (zIndex || 0);
    cvs.width = w;
    cvs.height = h;
    // 子要素を親へ追加
    $(id).append(cvs);
    // エレメントを返す
    return cvs;
}
// Dateよりも詳細な時間を取得
clsGameUtl.prototype.GetTime = function()
{
    var fncNow = (
        window.performance
        && (
            performance.now
            || performance.mozNow
            || performance.msNow
            || performance.oNow
            || performance.webkitNow
        )
    );
    // 現在時間を返す
    return (fncNow && fncNow.call(performance)) || ( new Date().getTime());
}
// 次のフレーム番号を得る
clsGameUtl.prototype.GetNextFrame = function(obj, interval, numFrame)
{
    var curFrame = (obj.Frame ? obj.Frame : 0);
    // 前回のフレーム時刻を記憶
    if (!obj.Time)
        obj.Time = this.GetTime();
    // フレーム更新間隔時間を過ぎたら次のフレームに移る
    if (this.GetTime() - obj.Time >= interval) {
        curFrame++;
        obj.Time = this.GetTime();
    }
    // フレーム番号を返す
    return (curFrame % numFrame);
}
// ゲーム領域のサイズ取得
clsGameUtl.prototype.GetSize = function()
{
    return ( { cx:$(this.Element).width(), cy:$(this.Element).height() } );
}
// 画像ロード
clsGameUtl.prototype.LoadImage = function(url)
{
    // 画像オブジェクト生成
    var img = new Image();
    // ソースを設定
    img.src = url;
    // 画像オブジェクトを返す
    return img;
}
// オブジェクトの破棄
clsGameUtl.prototype.FreeObject = function(obj)
{
    if (obj) {
        if (obj.children) {
            while (obj.children.length > 0) {
                var child = obj.children[0];
                obj.remove(child);
                child = this.FreeObject(child);
            }
        }
        // dispose 関数を持つオブジェクトは呼び出す
        if (obj.dispose)
            obj.dispose();
    }
    // 確実な undefined を返す
    return void 0;
}
// オブジェクトの破棄
clsGameUtl.prototype.Dispose = function(obj)
{
    // 複数回呼び出しのためにシーンを破棄
    this.Core.Scene = this.FreeObject(this.Core.Scene);
    // 複数回呼び出しのためにレンダラを破棄
    if (this.Core.Renderer) {
        $(this.Core.Renderer.domElement).remove();
        this.Core.Renderer = this.FreeObject(this.Core.Renderer);
    }
    // 最後は null を返す
    return null;
}
// 2D座標を3D座標に変換
clsGameUtl.prototype.UnprojectPosition = function(x, y)
{
    var sz = this.GetSize();
    // 2D座標を3D座標に変換
    var vector = new THREE.Vector3((x / sz.cx) * 2 - 1, -(y / sz.cy) * 2 + 1, 1);
    // プロジェクタ生成
    var projector = new THREE.Projector();
    // スクリーンから3D世界へ変換
    projector.unprojectVector(vector, this.Core.Camera);
    // 結果を返す
    return vector;
}
// 3D座標を2D座標に変換
clsGameUtl.prototype.ProjectPosition = function(Vector3, CenterOrigin)
{
    // プロジェクタ生成
    var projector = new THREE.Projector();
    // 画面サイズ取得
    var sz = this.GetSize();
    // 指定の3D座標を得る
    var v3 = Vector3.clone();
    // スクリーン座標を得る
    var v2 = projector.projectVector(v3, this.Core.Camera);
    // 画面中心原点を画面左上原点での座標に変換
    if (!CenterOrigin) {
        v2.x = (v2.x + 1) / 2 * sz.cx;
        v2.y = - (v2.y - 1) / 2 * sz.cy;
    }
    // 結果を返す
    return v2;
}
// キャンバス消去
clsGameUtl.prototype.ClearCanvas = function(p)
{
    if (p.Canvas) {
        var sz = this.GetSize();
        p.Canvas.save();
        p.Canvas.setTransform(1, 0, 0, 1, 0, 0);
        p.Canvas.clearRect(0, 0, sz.cx, sz.cy);
        p.Canvas.restore();
    }
    else
        this.Core.Renderer.clear();
}
// レイア消去
clsGameUtl.prototype.ClearLayer = function(idx)
{
    if (idx >= 0) {
        if (idx < this.aryLayer.length) {
            var p = this.aryLayer[idx].prm;
            // 描画を消去
            this.ClearCanvas(p);
        }
    }
    else {
        for (var idx = 0; idx < this.aryLayer.length; idx++)
            this.ClearLayer(idx);
    }
}
// 原点を中心にする
clsGameUtl.prototype.TranslateToCenter = function(idx)
{
    var sz = this.GetSize();
    // レイア属性取得
    var p = this.aryLayer[idx].prm;
    // レイアの原点を画面中央に設定
    p.Canvas.translate(sz.cx / 2, sz.cy / 2);
    // レイアのY軸の向きを数学座標に設定
    p.Canvas.scale(1, -1);
}
// Now Waiting
clsGameUtl.prototype.NowWaiting = function(idUse, idDraw, prmMsg)
{
    var InThread = $(idDraw).data('Thread');
    // 未表示状態なら...
    if (!InThread) {
        var o = $(idUse).offset();
        var w = $(idUse).width();
        var h = $(idUse).height();
        // 描画領域を親ブロックに重ねる
        $(idDraw).offset(o).width(w).height(h).css("visibility", "visible");
        // canvas ブロックを生成
        var cvs = this.NewHiddenCanvas(idDraw, w, h, 1);
        // canvas ブロックを表示可にする
        $(cvs).css("visibility", "visible");
        // canvas を得る
        var ctx = cvs.getContext("2d");
        // 回転角を記憶する
        $(idDraw).data('Angle', 0);
        // 当オブジェクトを記憶
        var inst = this;
        // Now Loading 表示予約
        var t = setInterval(
            function() {
                if ($(idDraw).css('visibility') == 'visible') {
                    // サイズを得る
                    var w = $(idDraw).width();
                    var h = $(idDraw).height();
                    var r = Math.min(w, h) / 2 - 10;
                    // 回転角を得る
                    var deg = $(idDraw).data('Angle');
                    // 回転角の設定
                    deg += (deg < 360 ? 15 : -deg);
                    // 視覚効果オブジェクト生成
                    var ef = new clsEffect();
                    // パラメータ設定
                    ef.Opts.Font = inst.WaitStyle.Font;
                    ef.Opts.StrokeStyle = inst.WaitStyle.StrokeStyle;
                    ef.Opts.FillStyle = inst.WaitStyle.FillStyle;
                    // 回転描画
                    ef.DrawRotateText(ctx, w, h, deg, r, prmMsg);
                    // 回転角の再記憶
                    $(idDraw).data('Angle', deg);
                }
                else
                    clearInterval(t);
            }
            , 64
        );
        // 表示状態である事を記憶
        $(idDraw).data('Thread', true);
    }
}
// End waiting
clsGameUtl.prototype.EndWaiting = function(idDraw)
{
    $(idDraw).css("visibility", "hidden").width(0).height(0).empty();
    $(idDraw).data('Thread', false);
}
// OK 付きメッセージ表示
clsGameUtl.prototype.MessageBox = function(idUse, idDraw, html)
{
    var o = $(idUse).offset();
    var w = $(idUse).width();
    var h = $(idUse).height();
    // 描画領域を親ブロックに重ねる
    $(idDraw).offset(o).width(w).height(h).css("visibility", "visible");
    // html 子要素を削除
    jQuery(idDraw).empty();
    // 要素を追加
    jQuery(idDraw).append(html);
}
// バルーン表示
clsGameUtl.prototype.ShowStatus = function(id, html, pos)
{
    var style = {
        border: 'solid 4px #5baec0'
        , padding: '2px'
        , fontSize: '10px'
        , lineHeight: '16px'
        , fontWeight: 'bold'
        , backgroundColor: '#666'
        , color: '#fff'
        , opacity: '1'
    };
    // バルーン表示
    $(id).showBalloon({ contents:html, position:pos, css: style });
}
// バルーン非表示
clsGameUtl.prototype.HideStatus = function(id)
{
    $(id).hideBalloon();
}
// ゲージ設定
clsGameUtl.prototype.SetGaugeBar = function(idUse, idDraw, maxValue, curValue)
{
    var o = $(idUse).offset();
    var w = $(idUse).width();
    var h = $(idUse).height();
    // 描画領域を親ブロックに重ねる
    $(idDraw).offset(o).width(w).height(h).css("visibility", "visible").empty();
    // canvas ブロックを生成
    var cvs = this.NewHiddenCanvas(idDraw, w, h);
    // canvas ブロックを表示可にする
    $(cvs).css("visibility", "visible");
    // canvas を得る
    var ctx = cvs.getContext("2d");
    // 描画する
    this.DrawGauge(ctx, 0, 0, w, h, maxValue, curValue, "bold 12px monospace", "aqua", "crimson", null);
}
// ゲージ描画
clsGameUtl.prototype.DrawGauge = function(ctx, x, y, w, h, maxValue, curValue, font, gaugeColor, textColor, backColor)
{
    var v = Math.floor((maxValue - curValue) / maxValue * 100);
    // 率を描画
    ctx.beginPath();
    // フォント
    ctx.font = font;
    // 背景
    if (backColor) {
        ctx.fillStyle = backColor;
        ctx.fillRect(x, y, w, h);
    }
    // ゲージの色
    ctx.fillStyle = gaugeColor;
    ctx.fillRect(x, y, w * (v / 100), h);
    // テキスト配置
    ctx.textAlign = "center";
    // テキスト色
    ctx.fillStyle = textColor;
    // テキスト描画
    ctx.fillText(v + "%", x + w / 2, y + h - 2);
    // 終了
    ctx.closePath();
}
// マウス操作制御用変数初期化
clsGameUtl.prototype.ResetMouseState = function()
{
    this.MouseState.Button = { Left:false, Middle:false, Right:false };
    this.MouseState.MapX = this.MouseState.MapY = -1;
    this.MouseState.PushX = this.MouseState.PushY = -1;
    this.MouseState.CanClick = false;
    this.MouseState.CanMove = true;
    this.MouseState.Hover = false;
    this.MouseState.Drag = false;
    this.MouseState.Action = 0;
}
// マウスイベントの設定
clsGameUtl.prototype.EnterMouse = function(LayerIdx, CallBack, CellSize)
{
    // レイアに未登録は何もしない
    if (!(LayerIdx >= 0 && LayerIdx < this.aryLayer.length))
        return;
    // 初期化
    var prm = this.aryLayer[LayerIdx].prm;
    var eid = "id" + cmnGetUID();
    // レイアに id を設定
    $(prm.Elemnt).attr('id', eid);
    // jquery 操作 id を記憶
    this.MouseState.idStage = "#" + eid;
    // イベント関数内使用 id
    var idStage = this.MouseState.idStage;
    // 自分自身の判別用にデータを設定する
    $(idStage).data(idStage, true);
    // マウスハンドラ
    var fncMouseEvent = function(inst) {
        // クリック
        $(idStage).click (
            function(e) {
                if ($(e.target).data(idStage)) {
                    if (inst.MouseState.CanClick) {
                        // マウス座標を設定
                        inst.MouseState.Pos = cmnGetMousePos(e);
                        // マップ上のセル位置
                        inst.MouseState.PushX = cmnDivision(inst.MouseState.Pos.offsetX, CellSize);
                        inst.MouseState.PushY = cmnDivision(inst.MouseState.Pos.offsetY, CellSize);
                        // その他
                        inst.MouseState.Drag = false;
                        inst.MouseState.CanMove = false;
                        inst.MouseState.Action = EvtMouse.Click;
                        // ゲーム中なら通知する
                        if (inst.Playing)
                            CallBack.call(inst.Core.Stage);
                    }
                }
                // ブラウザが最初から持っているアクションを中断
                e.preventDefault();
                return false;
            }
        );
        // マウスダウン
        $(idStage).mousedown (
            function(e) {
                if ($(e.target).data(idStage)) {
                    // マウス座標を設定
                    inst.MouseState.Pos = cmnGetMousePos(e);
                    // マップ上のセル位置
                    inst.MouseState.PushX = cmnDivision(inst.MouseState.Pos.offsetX, CellSize);
                    inst.MouseState.PushY = cmnDivision(inst.MouseState.Pos.offsetY, CellSize);
                    // マウスボタン設定
                    inst.MouseState.Button.Left = (e.which == 1);
                    inst.MouseState.Button.Middle = (e.which == 2);
                    inst.MouseState.Button.Right = (e.which == 3);
                    inst.MouseState.Action = EvtMouse.Down;
                    // ゲーム中なら通知する
                    if (inst.Playing)
                        CallBack.call(inst.Core.Stage);
                }
                // ブラウザが最初から持っているアクションを中断
                e.preventDefault();
                return false;
            }
        );
        // マウスアップ
        $(idStage).mouseup (
            function(e) {
                if ($(e.target).data(idStage)) {
                    // 左ボタン
                    if (e.which == 1)
                        inst.MouseState.Button.Left = false;
                    // 中ボタン
                    if (e.which == 2)
                        inst.MouseState.Button.Middle = false;
                    // 右ボタン
                    if (e.which == 3)
                        inst.MouseState.Button.Right = false;
                    // ドラッグと移動中処理可能を倒す
                    inst.MouseState.Drag = false;
                    inst.MouseState.CanMove = true;
                    inst.MouseState.Action = EvtMouse.Up;
                    // ゲーム中なら通知する
                    if (inst.Playing)
                        CallBack.call(inst.Core.Stage);
                }
                // ブラウザが最初から持っているアクションを中断
                e.preventDefault();
                return false;
            }
        );
        // マウス上乗り
        $(idStage).hover(
            function() {
                // マウス操作制御用変数初期化
                inst.ResetMouseState();
                inst.MouseState.Hover = true;
            }
            , function() {
                // マウス操作制御用変数初期化
                inst.ResetMouseState();
                inst.MouseState.Hover = false;
            }
        );
        // 移動
        $(idStage).mousemove (
            function(e) {
                if (inst.MouseState.Hover) {
                    if ($(e.target).data(idStage)) {
                        if (inst.MouseState.CanMove) {
                            // マウス座標を設定
                            inst.MouseState.Pos = cmnGetMousePos(e);
                            // マップ上のセル位置
                            var px = cmnDivision(inst.MouseState.Pos.offsetX, CellSize);
                            var py = cmnDivision(inst.MouseState.Pos.offsetY, CellSize);
                            // マップ上の移動判定
                            var Moved = (inst.MouseState.MapX != px || inst.MouseState.MapY != py);
                            // マップ上の移動があれば通知する
                            if (Moved) {
                                inst.MouseState.MapX = px;
                                inst.MouseState.MapY = py;
                                inst.MouseState.Action = EvtMouse.Move;
                                // ゲーム中なら通知する
                                if (inst.Playing)
                                    CallBack.call(inst.Core.Stage);
                            }
                        }
                    }
                }
                // ブラウザが最初から持っているアクションを中断
                e.preventDefault();
                return false;
            }
        );
    };
    fncMouseEvent(this);
}