最低限のゲームエンジンのソース
// 省略時のゲームブロック要素ID
var g_idStage = "#game-stage";
// ゲーム支援クラス
var clsGameUtl = function(id)
{
this.Element = (id || g_idStage);
// three オブジェクトの引数の格納用
this.Core = {
uFps:60 // 描画速度(frame per second)
};
// インスタンス
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); }
);
}
};
// ゲーム初期化
clsGameUtl.prototype.Initialize = function(Stage, NonRenderer, zIndex)
{
// 描画関数スタック
this.aryLayer = [];
// 当オブジェクトを使用するオブジェクトを記憶
this.Core.Stage = Stage;
// レンダラの初期化
if (!NonRenderer) {
// レンダラの初期化をあれやこれや行う
}
// 開始時間
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.Stop = function()
{
cancelAnimationFrame(this.Core.Timer);
// ゲーム停止フラグを設定
this.Playing = false;
}
// ゲーム開始
clsGameUtl.prototype.DoGame = function()
{
// ゲーム中フラグを設定
this.Playing = true;
// 描画可能なら...
if (this.CanRenderer) {
if (this.Core.Renderer) {
// 3d オブジェクトを使用するなら撮影を行なう
if (this.Use3DObject) {
// 3d ならあれやこれやを行う
}
}
// 描画コールバック
this.DrawLayer(-1);
}
// コールバック
if (this.Playing)
this.Core.Timer = window.requestAnimationFrame(this.DoGame.bind(this));
}
// 描画コールバック
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 (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;
}