UNPKG

@akashic/akashic-sandbox

Version:
1,206 lines (1,205 loc) 1.91 MB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.engineFilesV2_1_54 = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ module.exports = require('./lib/main.node'); },{"./lib/main.node":2}],2:[function(require,module,exports){ (function() { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var g; (function (g) { /** * アセット読み込み失敗時のエラーの種別。 * * この値はあくまでもエラーメッセージ出力のための補助情報であり、 * 網羅性・厳密性を追求したものではないことに注意。 */ var AssetLoadErrorType; (function (AssetLoadErrorType) { /** * 明示されていない(以下のいずれかかもしれないし、そうでないかもしれない)。 */ AssetLoadErrorType[AssetLoadErrorType["Unspecified"] = 0] = "Unspecified"; /** * エンジンの再試行回数上限設定値を超えた。 */ AssetLoadErrorType[AssetLoadErrorType["RetryLimitExceeded"] = 1] = "RetryLimitExceeded"; /** * ネットワークエラー。タイムアウトなど。 */ AssetLoadErrorType[AssetLoadErrorType["NetworkError"] = 2] = "NetworkError"; /** * リクエストに問題があるエラー。HTTP 4XX など。 */ AssetLoadErrorType[AssetLoadErrorType["ClientError"] = 3] = "ClientError"; /** * サーバ側のエラー。HTTP 5XX など。 */ AssetLoadErrorType[AssetLoadErrorType["ServerError"] = 4] = "ServerError"; })(AssetLoadErrorType = g.AssetLoadErrorType || (g.AssetLoadErrorType = {})); })(g || (g = {})); var g; (function (g) { /** * 例外生成ファクトリ。 * エンジン内部での例外生成に利用するもので、ゲーム開発者は通常本モジュールを利用する必要はない。 */ var ExceptionFactory; (function (ExceptionFactory) { function createAssertionError(message, cause) { var e = new Error(message); e.name = "AssertionError"; e.cause = cause; return e; } ExceptionFactory.createAssertionError = createAssertionError; function createTypeMismatchError(methodName, expected, actual, cause) { var message = "Type mismatch on " + methodName + "," + " expected type is " + expected; if (arguments.length > 2) { // actual 指定時 try { var actualString; if (actual && actual.constructor && actual.constructor.name) { actualString = actual.constructor.name; } else { actualString = typeof actual; } message += ", actual type is " + (actualString.length > 40 ? actualString.substr(0, 40) : actualString); } catch (ex) { // メッセージ取得時に例外が発生したらactualの型情報出力はあきらめる } } message += "."; var e = new Error(message); e.name = "TypeMismatchError"; e.cause = cause; e.expected = expected; e.actual = actual; return e; } ExceptionFactory.createTypeMismatchError = createTypeMismatchError; function createAssetLoadError(message, retriable, type, cause) { if (retriable === void 0) { retriable = true; } if (type === void 0) { type = g.AssetLoadErrorType.Unspecified; } var e = new Error(message); e.name = "AssetLoadError"; e.cause = cause; e.retriable = retriable; e.type = type; return e; } ExceptionFactory.createAssetLoadError = createAssetLoadError; })(ExceptionFactory = g.ExceptionFactory || (g.ExceptionFactory = {})); })(g || (g = {})); var g; (function (g) { /** * リソースの生成を行うクラス。 * * このクラス (の実装クラス) のインスタンスはエンジンによって生成される。ゲーム開発者が生成する必要はない。 * またこのクラスの各種アセット生成メソッドは、エンジンによって暗黙に呼び出されるものである。 * 通常ゲーム開発者が呼び出す必要はない。 */ var ResourceFactory = /** @class */ (function () { function ResourceFactory() { } ResourceFactory.prototype.createSurfaceAtlas = function (width, height) { return new g.SurfaceAtlas(this.createSurface(width, height)); }; /** * 指定Surfaceから指定範囲を切り取ったSurfaceを返す。 * 範囲を指定しない場合は、指定SurfaceをコピーしたSurfaceを返す。 */ ResourceFactory.prototype.createTrimmedSurface = function (targetSurface, targetArea) { var area = targetArea || { x: 0, y: 0, width: targetSurface.width, height: targetSurface.height }; var surface = this.createSurface(area.width, area.height); var renderer = surface.renderer(); renderer.begin(); renderer.drawImage(targetSurface, area.x, area.y, area.width, area.height, 0, 0); renderer.end(); return surface; }; return ResourceFactory; }()); g.ResourceFactory = ResourceFactory; })(g || (g = {})); var g; (function (g) { var RequireCachedValue = /** @class */ (function () { function RequireCachedValue(value) { this._value = value; } /** * @private */ RequireCachedValue.prototype._cachedValue = function () { return this._value; }; return RequireCachedValue; }()); g.RequireCachedValue = RequireCachedValue; })(g || (g = {})); var g; (function (g) { /** * 乱数生成器。 * `RandomGenerator#get()` によって、新しい乱数を生成することができる。 */ var RandomGenerator = /** @class */ (function () { function RandomGenerator(seed) { this.seed = seed; this[0] = this; } return RandomGenerator; }()); g.RandomGenerator = RandomGenerator; })(g || (g = {})); var g; (function (g) { /** * 各種リソースを表すクラス。 * 本クラスのインスタンスをゲーム開発者が直接生成することはない。 * game.jsonによって定義された内容をもとに暗黙的に生成されたインスタンスを、 * Scene#assets、またはGame#assetsによって取得して利用する。 */ var Asset = /** @class */ (function () { function Asset(id, path) { this.id = id; this.originalPath = path; this.path = this._assetPathFilter(path); this.onDestroyed = new g.Trigger(); } Asset.prototype.destroy = function () { this.onDestroyed.fire(this); this.id = undefined; this.originalPath = undefined; this.path = undefined; this.onDestroyed.destroy(); this.onDestroyed = undefined; }; Asset.prototype.destroyed = function () { return this.id === undefined; }; /** * 現在利用中で解放出来ない `Asset` かどうかを返す。 * 戻り値は、利用中である場合真、でなければ偽である。 * * 本メソッドは通常 `false` が返るべきである。 * 例えば `Sprite` の元画像として使われているケース等では、その `Sprite` によって `Asset` は `Surface` に変換されているべきで、 * `Asset` が利用中で解放出来ない状態になっていない事を各プラットフォームで保障する必要がある。 * * 唯一、例外的に本メソッドが `true` を返すことがあるのは音楽を表す `Asset` である。 * BGM等はシーンをまたいで演奏することもありえる上、 * 演奏中のリソースのコピーを常に各プラットフォームに強制するにはコストがかかりすぎるため、 * 本メソッドは `true` を返し、適切なタイミングで `Asset` が解放されるよう制御する必要がある。 */ Asset.prototype.inUse = function () { return false; }; /** * @private */ Asset.prototype._assetPathFilter = function (path) { // 拡張子の補完・読み替えが必要なassetはこれをオーバーライドすればよい。(対応形式が限定されるaudioなどの場合) return path; }; return Asset; }()); g.Asset = Asset; /** * 画像リソースを表すクラス。 * 本クラスのインスタンスをゲーム開発者が直接生成することはない。 * game.jsonによって定義された内容をもとに暗黙的に生成されたインスタンスを、 * Scene#assets、またはGame#assetsによって取得して利用する。 * * width, heightでメタデータとして画像の大きさをとることは出来るが、 * ゲーム開発者はそれ以外の情報を本クラスから直接は取得せず、Sprite等に本リソースを指定して利用する。 */ var ImageAsset = /** @class */ (function (_super) { __extends(ImageAsset, _super); function ImageAsset(id, assetPath, width, height) { var _this = _super.call(this, id, assetPath) || this; _this.width = width; _this.height = height; return _this; } ImageAsset.prototype.initialize = function (hint) { this.hint = hint; }; return ImageAsset; }(Asset)); g.ImageAsset = ImageAsset; /** * 動画リソースを表すクラス。 * 本クラスのインスタンスをゲーム開発者が直接生成することはない。 * game.jsonによって定義された内容をもとに暗黙的に生成されたインスタンスを、 * Scene#assets、またはGame#assetsによって取得して利用する。 */ var VideoAsset = /** @class */ (function (_super) { __extends(VideoAsset, _super); function VideoAsset(id, assetPath, width, height, system, loop, useRealSize) { var _this = _super.call(this, id, assetPath, width, height) || this; _this.realWidth = 0; _this.realHeight = 0; _this._system = system; _this._loop = loop; _this._useRealSize = useRealSize; return _this; } VideoAsset.prototype.play = function (_loop) { this.getPlayer().play(this); return this.getPlayer(); }; VideoAsset.prototype.stop = function () { this.getPlayer().stop(); }; VideoAsset.prototype.destroy = function () { this._system = undefined; _super.prototype.destroy.call(this); }; return VideoAsset; }(ImageAsset)); g.VideoAsset = VideoAsset; /** * 音リソースを表すクラス。 * 本クラスのインスタンスをゲーム開発者が直接生成することはない。 * game.jsonによって定義された内容をもとに暗黙的に生成されたインスタンスを、 * Scene#assets、またはGame#assetsによって取得して利用する。 * * AudioAsset#playを呼び出す事で、その音を再生することが出来る。 */ var AudioAsset = /** @class */ (function (_super) { __extends(AudioAsset, _super); function AudioAsset(id, assetPath, duration, system, loop, hint) { var _this = _super.call(this, id, assetPath) || this; _this.duration = duration; _this.loop = loop; _this.hint = hint; _this._system = system; _this.data = undefined; return _this; } AudioAsset.prototype.play = function () { var player = this._system.createPlayer(); player.play(this); this._lastPlayedPlayer = player; return player; }; AudioAsset.prototype.stop = function () { var players = this._system.findPlayers(this); for (var i = 0; i < players.length; ++i) players[i].stop(); }; AudioAsset.prototype.inUse = function () { return this._system.findPlayers(this).length > 0; }; AudioAsset.prototype.destroy = function () { if (this._system) this.stop(); this.data = undefined; this._system = undefined; this._lastPlayedPlayer = undefined; _super.prototype.destroy.call(this); }; return AudioAsset; }(Asset)); g.AudioAsset = AudioAsset; /** * 文字列リソースを表すクラス。 * 本クラスのインスタンスをゲーム開発者が直接生成することはない。 * game.jsonによって定義された内容をもとに暗黙的に生成されたインスタンスを、 * Scene#assets、またはGame#assetsによって取得して利用する。 * * TextAsset#dataによって、本リソースが保持する文字列を取得することが出来る。 */ var TextAsset = /** @class */ (function (_super) { __extends(TextAsset, _super); function TextAsset(id, assetPath) { var _this = _super.call(this, id, assetPath) || this; _this.data = undefined; return _this; } TextAsset.prototype.destroy = function () { this.data = undefined; _super.prototype.destroy.call(this); }; return TextAsset; }(Asset)); g.TextAsset = TextAsset; /** * スクリプトリソースを表すクラス。 * 本クラスのインスタンスをゲーム開発者が直接生成することはない。 * game.jsonによって定義された内容をもとに暗黙的に生成されたインスタンスを、 * Scene#assets、またはGame#assetsによって取得して利用する。 * * ScriptAsset#executeによって、本リソースが表すスクリプトを実行し、その結果を受け取る事が出来る。 * requireによる参照とは異なり、executeはキャッシュされないため、何度でも呼び出し違う結果を受け取ることが出来る。 */ var ScriptAsset = /** @class */ (function (_super) { __extends(ScriptAsset, _super); function ScriptAsset() { return _super !== null && _super.apply(this, arguments) || this; } ScriptAsset.prototype.destroy = function () { this.script = undefined; _super.prototype.destroy.call(this); }; return ScriptAsset; }(Asset)); g.ScriptAsset = ScriptAsset; })(g || (g = {})); var g; (function (g) { var AssetLoadingInfo = /** @class */ (function () { function AssetLoadingInfo(asset, handler) { this.asset = asset; this.handlers = [handler]; this.errorCount = 0; this.loading = false; } return AssetLoadingInfo; }()); function normalizeAudioSystemConfMap(confMap) { confMap = confMap || {}; var systemDefaults = { music: { loop: true, hint: { streaming: true } }, sound: { loop: false, hint: { streaming: false } } }; for (var key in systemDefaults) { if (!(key in confMap)) { confMap[key] = systemDefaults[key]; } } return confMap; } /** * `Asset` を管理するクラス。 * * このクラスのインスタンスは `Game` に一つデフォルトで存在する(デフォルトアセットマネージャ)。 * デフォルトアセットマネージャは、game.json に記述された通常のアセットを読み込むために利用される。 * * ゲーム開発者は、game.json に記述のないリソースを取得するために、このクラスのインスタンスを独自に生成してよい。 */ var AssetManager = /** @class */ (function () { /** * `AssetManager` のインスタンスを生成する。 * * @param game このインスタンスが属するゲーム * @param conf このアセットマネージャに与えるアセット定義。game.json の `"assets"` に相当。 */ function AssetManager(game, conf, audioSystemConfMap, moduleMainScripts) { this.game = game; this.configuration = this._normalize(conf || {}, normalizeAudioSystemConfMap(audioSystemConfMap)); this._assets = {}; this._liveAssetVirtualPathTable = {}; this._liveAbsolutePathTable = {}; this._moduleMainScripts = moduleMainScripts ? moduleMainScripts : {}; this._refCounts = {}; this._loadings = {}; } /** * このインスタンスを破棄する。 */ AssetManager.prototype.destroy = function () { var assetIds = Object.keys(this._refCounts); for (var i = 0; i < assetIds.length; ++i) { this._releaseAsset(assetIds[i]); } this.game = undefined; this.configuration = undefined; this._assets = undefined; this._liveAssetVirtualPathTable = undefined; this._liveAbsolutePathTable = undefined; this._refCounts = undefined; this._loadings = undefined; }; /** * このインスタンスが破棄済みであるかどうかを返す。 */ AssetManager.prototype.destroyed = function () { return this.game === undefined; }; /** * `Asset` の読み込みを再試行する。 * * 引数 `asset` は読み込みの失敗が (`Scene#assetLoadFail` で) 通知されたアセットでなければならない。 * @param asset 読み込みを再試行するアセット */ AssetManager.prototype.retryLoad = function (asset) { if (!this._loadings.hasOwnProperty(asset.id)) throw g.ExceptionFactory.createAssertionError("AssetManager#retryLoad: invalid argument."); var loadingInfo = this._loadings[asset.id]; if (loadingInfo.errorCount > AssetManager.MAX_ERROR_COUNT) { // DynamicAsset はエラーが規定回数超えた場合は例外にせず諦める。 if (!this.configuration[asset.id]) return; throw g.ExceptionFactory.createAssertionError("AssetManager#retryLoad: too many retrying."); } if (!loadingInfo.loading) { loadingInfo.loading = true; asset._load(this); } }; /** * このインスタンスに与えられた `AssetConfigurationMap` のうち、グローバルアセットのIDをすべて返す。 */ AssetManager.prototype.globalAssetIds = function () { var ret = []; var conf = this.configuration; for (var p in conf) { if (!conf.hasOwnProperty(p)) continue; if (conf[p].global) ret.push(p); } return ret; }; /** * アセットの取得を要求する。 * * 要求したアセットが読み込み済みでない場合、読み込みが行われる。 * 取得した結果は `handler` を通して通知される。 * ゲーム開発者はこのメソッドを呼び出してアセットを取得した場合、 * 同じアセットID(または取得したアセット)で `unrefAsset()` を呼び出さなければならない。 * * @param assetIdOrConf 要求するアセットのIDまたは設定 * @param handler 要求結果を受け取るハンドラ */ AssetManager.prototype.requestAsset = function (assetIdOrConf, handler) { var assetId = typeof assetIdOrConf === "string" ? assetIdOrConf : assetIdOrConf.id; var waiting = false; var loadingInfo; if (this._assets.hasOwnProperty(assetId)) { ++this._refCounts[assetId]; handler._onAssetLoad(this._assets[assetId]); } else if (this._loadings.hasOwnProperty(assetId)) { loadingInfo = this._loadings[assetId]; loadingInfo.handlers.push(handler); ++this._refCounts[assetId]; waiting = true; } else { var a = this._createAssetFor(assetIdOrConf); loadingInfo = new AssetLoadingInfo(a, handler); this._loadings[assetId] = loadingInfo; this._refCounts[assetId] = 1; waiting = true; loadingInfo.loading = true; a._load(this); } return waiting; }; /** * アセットの参照カウントを減らす。 * 引数の各要素で `unrefAsset()` を呼び出す。 * * @param assetOrId 参照カウントを減らすアセットまたはアセットID */ AssetManager.prototype.unrefAsset = function (assetOrId) { var assetId = typeof assetOrId === "string" ? assetOrId : assetOrId.id; if (--this._refCounts[assetId] > 0) return; this._releaseAsset(assetId); }; /** * 複数のアセットの取得を要求する。 * 引数の各要素で `requestAsset()` を呼び出す。 * * @param assetIdOrConfs 取得するアセットのIDまたはアセット定義 * @param handler 取得の結果を受け取るハンドラ */ AssetManager.prototype.requestAssets = function (assetIdOrConfs, handler) { var waitingCount = 0; for (var i = 0, len = assetIdOrConfs.length; i < len; ++i) { if (this.requestAsset(assetIdOrConfs[i], handler)) { ++waitingCount; } } return waitingCount; }; /** * 複数のアセットを解放する。 * 引数の各要素で `unrefAsset()` を呼び出す。 * * @param assetOrIds 参照カウントを減らすアセットまたはアセットID * @private */ AssetManager.prototype.unrefAssets = function (assetOrIds) { for (var i = 0, len = assetOrIds.length; i < len; ++i) { this.unrefAsset(assetOrIds[i]); } }; AssetManager.prototype._normalize = function (configuration, audioSystemConfMap) { var ret = {}; if (!(configuration instanceof Object)) throw g.ExceptionFactory.createAssertionError("AssetManager#_normalize: invalid arguments."); for (var p in configuration) { if (!configuration.hasOwnProperty(p)) continue; var conf = Object.create(configuration[p]); if (!conf.path) { throw g.ExceptionFactory.createAssertionError("AssetManager#_normalize: No path given for: " + p); } if (!conf.virtualPath) { throw g.ExceptionFactory.createAssertionError("AssetManager#_normalize: No virtualPath given for: " + p); } if (!conf.type) { throw g.ExceptionFactory.createAssertionError("AssetManager#_normalize: No type given for: " + p); } if (conf.type === "image") { if (typeof conf.width !== "number") throw g.ExceptionFactory.createAssertionError("AssetManager#_normalize: wrong width given for the image asset: " + p); if (typeof conf.height !== "number") throw g.ExceptionFactory.createAssertionError("AssetManager#_normalize: wrong height given for the image asset: " + p); } if (conf.type === "audio") { // durationというメンバは後から追加したため、古いgame.jsonではundefinedになる場合がある if (conf.duration === undefined) conf.duration = 0; var audioSystemConf = audioSystemConfMap[conf.systemId]; if (conf.loop === undefined) { conf.loop = !!audioSystemConf && !!audioSystemConf.loop; } if (conf.hint === undefined) { conf.hint = audioSystemConf ? audioSystemConf.hint : {}; } } if (conf.type === "video") { if (!conf.useRealSize) { if (typeof conf.width !== "number") throw g.ExceptionFactory.createAssertionError("AssetManager#_normalize: wrong width given for the video asset: " + p); if (typeof conf.height !== "number") throw g.ExceptionFactory.createAssertionError("AssetManager#_normalize: wrong height given for the video asset: " + p); conf.useRealSize = false; } } if (!conf.global) conf.global = false; ret[p] = conf; } return ret; }; /** * @private */ AssetManager.prototype._createAssetFor = function (idOrConf) { var id; var uri; var conf; if (typeof idOrConf === "string") { id = idOrConf; conf = this.configuration[id]; uri = this.configuration[id].path; } else { var dynConf = idOrConf; id = dynConf.id; conf = dynConf; uri = dynConf.uri; } var resourceFactory = this.game.resourceFactory; if (!conf) throw g.ExceptionFactory.createAssertionError("AssetManager#_createAssetFor: unknown asset ID: " + id); switch (conf.type) { case "image": var asset = resourceFactory.createImageAsset(id, uri, conf.width, conf.height); asset.initialize(conf.hint); return asset; case "audio": var system = conf.systemId ? this.game.audio[conf.systemId] : this.game.audio[this.game.defaultAudioSystemId]; return resourceFactory.createAudioAsset(id, uri, conf.duration, system, conf.loop, conf.hint); case "text": return resourceFactory.createTextAsset(id, uri); case "script": return resourceFactory.createScriptAsset(id, uri); case "video": // VideoSystemはまだ中身が定義されていなが、将来のためにVideoAssetにVideoSystemを渡すという体裁だけが整えられている。 // 以上を踏まえ、ここでは簡単のために都度新たなVideoSystemインスタンスを生成している。 return resourceFactory.createVideoAsset(id, uri, conf.width, conf.height, new g.VideoSystem(), conf.loop, conf.useRealSize); default: throw g.ExceptionFactory.createAssertionError("AssertionError#_createAssetFor: unknown asset type " + conf.type + " for asset ID: " + id); } }; AssetManager.prototype._releaseAsset = function (assetId) { var asset = this._assets[assetId] || (this._loadings[assetId] && this._loadings[assetId].asset); var path; if (asset) { path = asset.path; if (asset.inUse()) { if (asset instanceof g.AudioAsset) { asset._system.requestDestroy(asset); } else if (asset instanceof g.VideoAsset) { // NOTE: 一旦再生完了を待たずに破棄することにする // TODO: 再生中の動画を破棄するタイミングをどのように扱うか検討し実装 asset.destroy(); } else { throw g.ExceptionFactory.createAssertionError("AssetManager#unrefAssets: Unsupported in-use " + asset.id); } } else { asset.destroy(); } } delete this._refCounts[assetId]; delete this._loadings[assetId]; delete this._assets[assetId]; if (this.configuration[assetId]) { var virtualPath = this.configuration[assetId].virtualPath; if (virtualPath && this._liveAssetVirtualPathTable.hasOwnProperty(virtualPath)) delete this._liveAssetVirtualPathTable[virtualPath]; if (path && this._liveAbsolutePathTable.hasOwnProperty(path)) delete this._liveAbsolutePathTable[path]; } }; /** * 現在ロード中のアセットの数。(デバッグ用; 直接の用途はない) * @private */ AssetManager.prototype._countLoadingAsset = function () { return Object.keys(this._loadings).length; }; /** * @private */ AssetManager.prototype._onAssetError = function (asset, error) { // ロード中に Scene が破棄されていた場合などで、asset が破棄済みになることがある if (this.destroyed() || asset.destroyed()) return; var loadingInfo = this._loadings[asset.id]; var hs = loadingInfo.handlers; loadingInfo.loading = false; ++loadingInfo.errorCount; if (loadingInfo.errorCount > AssetManager.MAX_ERROR_COUNT && error.retriable) { error = g.ExceptionFactory.createAssetLoadError("Retry limit exceeded", false, g.AssetLoadErrorType.RetryLimitExceeded, error); } if (!error.retriable) delete this._loadings[asset.id]; for (var i = 0; i < hs.length; ++i) hs[i]._onAssetError(asset, error, this); }; /** * @private */ AssetManager.prototype._onAssetLoad = function (asset) { // ロード中に Scene が破棄されていた場合などで、asset が破棄済みになることがある if (this.destroyed() || asset.destroyed()) return; var loadingInfo = this._loadings[asset.id]; loadingInfo.loading = false; delete this._loadings[asset.id]; this._assets[asset.id] = asset; // DynamicAsset の場合は configuration に書かれていないので以下の判定が偽になる if (this.configuration[asset.id]) { var virtualPath = this.configuration[asset.id].virtualPath; if (!this._liveAssetVirtualPathTable.hasOwnProperty(virtualPath)) { this._liveAssetVirtualPathTable[virtualPath] = asset; } else { if (this._liveAssetVirtualPathTable[virtualPath].path !== asset.path) throw g.ExceptionFactory.createAssertionError("AssetManager#_onAssetLoad(): duplicated asset path"); } if (!this._liveAbsolutePathTable.hasOwnProperty(asset.path)) this._liveAbsolutePathTable[asset.path] = virtualPath; } var hs = loadingInfo.handlers; for (var i = 0; i < hs.length; ++i) hs[i]._onAssetLoad(asset); }; AssetManager.MAX_ERROR_COUNT = 3; return AssetManager; }()); g.AssetManager = AssetManager; })(g || (g = {})); var g; (function (g) { /** * node.js の require() ライクな読み込み処理を行い、その結果を返す。 * * node.jsのrequireに限りなく近いモデルでrequireする。 * ただしアセットIDで該当すればそちらを優先する。また node.js のコアモジュールには対応していない。 * 通常、ゲーム開発者が利用するのは `Module#require()` であり、このメソッドはその内部実装を提供する。 * @param game requireを実行するコンテキストを表すGameインスタンス * @param path requireのパス。相対パスと、Asset識別名を利用することが出来る。 * なお、./xxx.json のようにjsonを指定する場合、そのAssetはTextAssetである必要がある。 * その他の形式である場合、そのAssetはScriptAssetである必要がある。 * @param currentModule このrequireを実行した Module * @returns {any} スクリプト実行結果。通常はScriptAsset#executeの結果。 * 例外的に、jsonであればTextAsset#dataをJSON.parseした結果が返る */ function _require(game, path, currentModule) { // Node.js の require の挙動については http://nodejs.jp/nodejs.org_ja/api/modules.html も参照。 var targetScriptAsset; var resolvedPath; var liveAssetVirtualPathTable = game._assetManager._liveAssetVirtualPathTable; var moduleMainScripts = game._assetManager._moduleMainScripts; // 0. アセットIDらしい場合はまず当該アセットを探す if (path.indexOf("/") === -1) { if (game._assetManager._assets.hasOwnProperty(path)) { targetScriptAsset = game._assetManager._assets[path]; resolvedPath = game._assetManager._liveAbsolutePathTable[targetScriptAsset.path]; } } // 1. If X is a core module, // (何もしない。コアモジュールには対応していない。ゲーム開発者は自分でコアモジュールへの依存を解決する必要がある) if (/^\.\/|^\.\.\/|^\//.test(path)) { // 2. If X begins with './' or '/' or '../' if (currentModule) { if (!currentModule._virtualDirname) throw g.ExceptionFactory.createAssertionError("g._require: require from DynamicAsset is not supported"); resolvedPath = g.PathUtil.resolvePath(currentModule._virtualDirname, path); } else { if (!/^\.\//.test(path)) throw g.ExceptionFactory.createAssertionError("g._require: entry point path must start with './'"); resolvedPath = path.substring(2); } if (game._scriptCaches.hasOwnProperty(resolvedPath)) { return game._scriptCaches[resolvedPath]._cachedValue(); } else if (game._scriptCaches.hasOwnProperty(resolvedPath + ".js")) { return game._scriptCaches[resolvedPath + ".js"]._cachedValue(); } // 2.a. LOAD_AS_FILE(Y + X) if (!targetScriptAsset) targetScriptAsset = g.Util.findAssetByPathAsFile(resolvedPath, liveAssetVirtualPathTable); // 2.b. LOAD_AS_DIRECTORY(Y + X) if (!targetScriptAsset) targetScriptAsset = g.Util.findAssetByPathAsDirectory(resolvedPath, liveAssetVirtualPathTable); } else { // 3. LOAD_NODE_MODULES(X, dirname(Y)) // `path` は node module の名前であると仮定して探す // akashic-engine独自仕様: 対象の `path` が `moduleMainScripts` に指定されていたらそちらを参照する if (moduleMainScripts[path]) { resolvedPath = moduleMainScripts[path]; targetScriptAsset = game._assetManager._liveAssetVirtualPathTable[resolvedPath]; } if (!targetScriptAsset) { var dirs = currentModule ? currentModule.paths : []; dirs.push("node_modules"); for (var i = 0; i < dirs.length; ++i) { var dir = dirs[i]; resolvedPath = g.PathUtil.resolvePath(dir, path); targetScriptAsset = g.Util.findAssetByPathAsFile(resolvedPath, liveAssetVirtualPathTable); if (targetScriptAsset) break; targetScriptAsset = g.Util.findAssetByPathAsDirectory(resolvedPath, liveAssetVirtualPathTable); if (targetScriptAsset) break; } } } if (targetScriptAsset) { if (game._scriptCaches.hasOwnProperty(resolvedPath)) return game._scriptCaches[resolvedPath]._cachedValue(); if (targetScriptAsset instanceof g.ScriptAsset) { var context = new g.ScriptAssetContext(game, targetScriptAsset); game._scriptCaches[resolvedPath] = context; return context._executeScript(currentModule); } else if (targetScriptAsset instanceof g.TextAsset) { // JSONの場合の特殊挙動をトレースするためのコード。node.jsの仕様に準ずる if (targetScriptAsset && g.PathUtil.resolveExtname(path) === ".json") { // Note: node.jsではここでBOMの排除をしているが、いったんakashicでは排除しないで実装 var cache = (game._scriptCaches[resolvedPath] = new g.RequireCachedValue(JSON.parse(targetScriptAsset.data))); return cache._cachedValue(); } } } throw g.ExceptionFactory.createAssertionError("g._require: can not find module: " + path); } g._require = _require; /** * Node.js が提供する module の互換クラス。 */ var Module = /** @class */ (function () { function Module(game, id, path) { var _this = this; var dirname = g.PathUtil.resolveDirname(path); // `virtualPath` と `virtualDirname` は `DynamicAsset` の場合は `undefined` になる。 var virtualPath = game._assetManager._liveAbsolutePathTable[path]; var virtualDirname = virtualPath ? g.PathUtil.resolveDirname(virtualPath) : undefined; var _g = Object.create(g, { game: { value: game, enumerable: true }, filename: { value: path, enumerable: true }, dirname: { value: dirname, enumerable: true }, module: { value: this, writable: true, enumerable: true, configurable: true } }); this.id = id; this.filename = path; this.exports = {}; this.parent = null; // Node.js と互換 this.loaded = false; this.children = []; this.paths = virtualDirname ? g.PathUtil.makeNodeModulePaths(virtualDirname) : []; this._dirname = dirname; this._virtualDirname = virtualDirname; this._g = _g; // メソッドとしてではなく単体で呼ばれるのでメソッドにせずここで実体を代入する this.require = function (path) { return path === "g" ? _g : g._require(game, path, _this); }; } return Module; }()); g.Module = Module; })(g || (g = {})); var g; (function (g) { /** * `ScriptAsset` の実行コンテキスト。 * 通常スクリプトアセットを実行するためにはこのクラスを経由する。 * * ゲーム開発者がこのクラスを利用する必要はない。 * スクリプトアセットを実行する場合は、暗黙にこのクラスを利用する `require()` を用いること。 */ var ScriptAssetContext = /** @class */ (function () { function ScriptAssetContext(game, asset) { this._game = game; this._asset = asset; this._module = new g.Module(game, asset.path, asset.path); this._g = this._module._g; this._started = false; } /** * @private */ ScriptAssetContext.prototype._cachedValue = function () { if (!this._started) throw g.ExceptionFactory.createAssertionError("ScriptAssetContext#_cachedValue: not executed yet."); return this._module.exports; }; /** * @private */ ScriptAssetContext.prototype._executeScript = function (currentModule) { if (this._started) return this._module.exports; if (currentModule) { // Node.js 互換挙動: Module#parent は一番最初に require() した module になる this._module.parent = currentModule; // Node.js 互換挙動: 親 module の children には自身が実行中の段階で既に追加されている currentModule.children.push(this._module); } this._started = true; this._asset.execute(this._g); this._module.loaded = true; return this._module.exports; }; return ScriptAssetContext; }()); g.ScriptAssetContext = ScriptAssetContext; })(g || (g = {})); var g; (function (g) { /** * 変換行列を一般的なJavaScriptのみで表したクラス。 * 通常ゲーム開発者が本クラスを直接利用する事はない。 * 各フィールド、メソッドの詳細は `Matrix` インターフェースの説明を参照。 */ var PlainMatrix = /** @class */ (function () { function PlainMatrix(widthOrSrc, height, scaleX, scaleY, angle, anchorX, anchorY) { // TODO: (GAMEDEV-845) Float32Arrayの方が速いらしいので、polyfillして使うかどうか検討 if (widthOrSrc === undefined) { this._modified = false; this._matrix = [1, 0, 0, 1, 0, 0]; } else if (typeof widthOrSrc === "number") { this._modified = false; this._matrix = new Array(6); if (anchorX != null && anchorY != null) { this.updateWithAnchor(widthOrSrc, height, scaleX, scaleY, angle, 0, 0, anchorX, anchorY); } else { this.update(widthOrSrc, height, scaleX, scaleY, angle, 0, 0); } } else { this._modified = widthOrSrc._modified; this._matrix = [ widthOrSrc._matrix[0], widthOrSrc._matrix[1], widthOrSrc._matrix[2], widthOrSrc._matrix[3], widthOrSrc._matrix[4], widthOrSrc._matrix[5] ]; } } PlainMatrix.prototype.update = function (width, height, scaleX, scaleY, angle, x, y) { // ここで求める変換行列Mは、引数で指定された変形を、拡大・回転・平行移動の順に適用するものである。 // 変形の原点は引数で指定された矩形の中心、すなわち (width/2, height/2) の位置である。従って // M = A^-1 T R S A // である。ただしここでA, S, R, Tは、それぞれ以下を表す変換行列である: // A: 矩形の中心を原点に移す(平行移動する)変換 // S: X軸方向にscaleX倍、Y軸方向にscaleY倍する変換 // R: angle度だけ回転する変換 // T: x, yの値だけ平行移動する変換 // それらは次のように表せる: // 1 0 -w sx 0 0 c -s 0 1 0 x // A = [ 0 1 -h] S = [ 0 sy 0] R = [ s c 0] T = [ 0 1 y] // 0 0 1 0 0 1 0 0 1 0 0 1 // ここで sx, sy は scaleX, scaleY であり、c, s は cos(theta), sin(theta) // (ただし theta = angle * PI / 180)、w = (width / 2), h = (height / 2) である。 // 以下の実装は、M の各要素をそれぞれ計算して直接求めている。 var r = (angle * Math.PI) / 180; var _cos = Math.cos(r); var _sin = Math.sin(r); var a = _cos * scaleX; var b = _sin * scaleX; var c = _sin * scaleY; var d = _cos * scaleY; var w = width / 2; var h = height / 2; this._matrix[0] = a; this._matrix[1] = b; this._matrix[2] = -c; this._matrix[3] = d; this._matrix[4] = -a * w + c * h + w + x; this._matrix[5] = -b * w - d * h + h + y; }; PlainMatrix.prototype.updateWithAnchor = function (width, height, scaleX, scaleY, angle, x, y, anchorX, anchorY) { // ここで求める変換行列Mは、引数で指定された変形を、拡大・回転・平行移動の順に適用するものである。 // 変形の原点は引数で指定された位置の原寸大、すなわち (anchorX * width, anchorY * height) の位置である。従って // M = A^-1 T R S A // である。ただしここでA, S, R, Tは、それぞれ以下を表す変換行列である: // A: アンカーを原点に移す(平行移動する)変換 // S: X軸方向にscaleX倍、Y軸方向にscaleY倍する変換 // R: angle度だけ回転する変換 // T: x, yの値だけ平行移動する変換 // それらは次のように表せる: // 1 0 -w sx 0 0 c -s 0 1 0 x-w // A = [ 0 1 -h] S = [ 0 sy 0] R = [ s c 0] T = [ 0 1 y-h] // 0 0 1 0 0 1 0 0 1 0 0 1 // ここで sx, sy は scaleX, scaleY であり、c, s は cos(theta), sin(theta) // (ただし theta = angle * PI / 180)、w = anchorX * width, h = anchorY * height である。 // 以下の実装は、M の各要素をそれぞれ計算して直接求めている。 var r = (angle * Math.PI) / 180; var _cos = Math.cos(r); var _sin = Math.sin(r); var a = _cos * scaleX; var b = _sin * scaleX; var c = _sin * scaleY; var d = _cos * scaleY; var w = anchorX * width; var h = anchorY * height; this._matrix[0] = a; this._matrix[1] = b; this._matrix[2] = -c; this._matrix[3] = d; this._matrix[4] = -a * w + c * h + x; this._matrix[5] = -b * w - d * h + y; }; PlainMatrix.prototype.updateByInverse = function (width, height, scaleX, scaleY, angle, x, y) { // ここで求める変換行列は、update() の求める行列Mの逆行列、M^-1である。update() のコメントに記述のとおり、 // M = A^-1 T R S A // であるから、 // M^-1 = A^-1 S^-1 R^-1 T^-1 A // それぞれは次のように表せる: // 1 0 w 1/sx 0 0 c s 0 1 0 -x // A^-1 = [ 0 1 h] S^-1 = [ 0 1/sy 0] R^-1 = [ -s c 0] T^-1 = [ 0 1 -y] // 0 0 1 0 0 1 0 0 1 0 0 1 // ここで各変数は update() のコメントのものと同様である。 // 以下の実装は、M^-1 の各要素をそれぞれ計算して直接求めている。 var r = (angle * Math.PI) / 180; var _cos = Math.cos(r); var _sin = Math.sin(r); var a = _cos / scaleX; var b = _sin / scaleY; var c = _sin / scaleX; var d = _cos / scaleY; var w = width / 2; var h = height / 2; this._matrix[0] = a; this._matrix[1] = -b; this._matrix[2] = c; this._matrix[3] = d; this._matrix[4] = -a * (w + x) - c * (h + y) + w; this._matrix[5] = b * (w + x) - d * (h + y) + h; }; PlainMatrix.prototype.updateByInverseWithAnchor = function (width, height, scaleX, scaleY, angle, x, y, anchorX, anchorY) { // ここで求める変換行列は、updateWithAnchor() の求める行列Mの逆行列、M^-1である。updateWithAnchor() のコメントに記述のとおり、 // M = A^-1 T R S A // であるから、 // M^-1 = A^-1 S^-1 R^-1 T^-1 A // それぞれは次のように表せる: // 1 0 w 1/sx 0 0 c s 0 1 0 -x+w // A^-1 = [ 0 1 h] S^-1 = [ 0 1/sy 0] R^-1 = [ -s c 0] T^-1 = [ 0 1 -y+h] // 0 0 1 0 0 1 0 0 1 0 0 1 // ここで各変数は updateWithAnchor() のコメントのものと同様である。 // 以下の実装は、M^-1 の各要素をそれぞれ計算して直接求めている。 var r = (angle * Math.PI) / 180; var _cos = Math.cos(r); var _sin = Math.sin(r); var a = _cos / scaleX; var b = _sin / scaleY; var c = _sin / scaleX; var d = _cos / scaleY; var w = anchorX * width; var h = anchorY * height; this._matrix[0] = a; this._matrix[1] = -b; this._matrix[2] = c; this._matrix[3] = d; this._matrix[4] = -a * x - c * y + w; this._matrix[5] = b * x - d * y + h; }; PlainMatrix.prototype.multiply = function (matrix) { var m1 = this._matrix; var m2 = matrix._matrix; var m10 = m1[0]; var m11 = m1[1]; var m12 = m1[2]; var m13 = m1[3]; m1[0] = m10 * m2[0] + m12 * m2[1]; m1[1] = m11 * m2[0] + m13 * m2[1]; m1[2] = m10 * m2[2] + m12 * m2[3]; m1[3] = m11 * m2[2] + m13 * m2[3]; m1[4] = m10 * m2[4] + m12 * m2[5] + m1[4]; m1[5] = m11 * m2[4] + m13 * m2[5] + m1[5]; }; PlainMatrix.prototype.multiplyNew = function (matrix) { var ret = this.clone(); ret.multiply(matrix); return ret; }; PlainMatrix.prototype.reset = function (x, y) { this._matrix[0] = 1; this._matrix[1] = 0; this._matrix[2] = 0; this._matrix[3] = 1; this._matrix[4] = x || 0; this._matrix[5] = y || 0; }; PlainMatrix.prototype.clone = function () { return new PlainMatrix(this); }; PlainMatrix.prototype.multiplyInverseForPoint = function (point) { var m = this._matrix; // id = inverse of the determinant var _id = 1 / (m[0] * m[3] + m[2] * -m[1]); return { x: m[3] * _id * point.x + -m[2] * _id * point.y + (m[5] * m[2] - m[4] * m[3]) * _id, y: m[0] * _id * point.y + -m[1] * _id * point.x + (-m[5] * m[0] + m[4] * m[1]) * _id }; }; PlainMatrix.prototype.scale = function (x, y) { var m = this._matrix; m[0] *= x; m[1] *= y; m[2] *= x; m[3] *= y; m[4] *= x; m[5] *= y; }; PlainMatrix.prototype.multiplyPoint = function (point) { var m = this._matrix; var x = m[0] * point.x + m[2] * point.y + m[4]; var y = m[1] * point.x + m[3] * point.y + m[5]; return { x: x, y: y }; }; return PlainMatrix; }()); g.PlainMatrix = PlainMatrix; })(g || (g = {})); var g; (function (g) { /** * ユーティリティ。 */ var Util; (function (Util) { /** * 2点間(P1..P2)の距離(pixel)を返す。 * @param {number} p1x P1-X * @param {number} p1y P1-Y * @param {number} p2x P2-X * @param {number} p2y P2-Y */ function distance(p1x, p1y, p2x, p2y) { return Math.sqrt(Math.pow(p1x - p2x, 2) + Math.pow(p1y - p2y, 2)); } Util.distance = distance; /** * 2点間(P1..P2)の距離(pixel)を返す。 * @param {CommonOffset} p1 座標1 * @param {CommonOffset} p2 座標2 */ function distanceBetweenOffsets(p1, p2) { return Util.distance(p1.x, p1.y, p2.x, p2.y); } Util.distanceBetweenOffsets = distanceBetweenOffsets; /** * 2つの矩形の中心座標(P1..P2)間の距離(pixel)を返す。 * @param {CommonArea} p1 矩形1 * @param {CommonArea} p2 矩形2 */ function distanceBetweenAreas(p1, p2) { return Util.distance(p1.x + p1.width / 2, p1.y + p1.height / 2, p2.x + p2.width / 2, p2.y + p2.height / 2); } Util.distanceBetweenAreas = distanceBetweenAreas; // Note: オーバーロードされているのでjsdoc省略 function createMatrix(width, height, scaleX, scaleY, angle, anchorX, anchorY) { // Note: asm.js対応環境ではasm.js対応のMatrixを生成するなどしたいため、オーバーヘッドを許容する if (width === undefined) return new g.PlainMatrix(); return new g.PlainMatrix(width, height, scaleX, scaleY, angle, anchorX, anchorY); } Util.createMatrix = createMatrix; /** * e の描画内容を持つ Sprite を生成する。 * @param scene 作成したSpriteを登録するScene * @param e Sprite化したいE * @param camera 使用カメラ */ function createSpriteFromE(scene, e, camera) { var oldX = e.x; var oldY = e.y; var x = 0; var y = 0; var width = e.width; var height = e.height; var boundingRect = e.calculateBoundingRect(camera); if (!boundingRect) { throw g.ExceptionFactory.createAssertionError("Util#createSpriteFromE: camera must look e"); } width = boundingRect.right - boundingRect.left; height = boundingRect.bottom - boundingRect.top; if (boundingRect.left < e.x) x = e.x - boundingRect.left; if (bound