v2 からの移行
INFO
このページは、 Akashic Engine v2 で作成されたコンテンツを v3 に移行する ためのものです。 新たにゲームを作成する場合は次の Akashic Engine 入門 » akashic の導入 に進んでください。
Akashic Engine v3 では、v2 から主に内部構造を整理したバージョンですが、一部破壊的に変更した仕様があり、ゲーム開発者に影響します。 この文書では、Akashic Engine v2 系で作成されたコンテンツを v3 に移行するために必要な作業と、主な追加機能を紹介します。
目次
設定の更新 (必須)
v2 で作られたコンテンツを v3 に移行するには、次の作業が必要です。
- game.json を変更して v3 コンテンツとして扱うよう設定する
- (TypeScript のみ) 型定義ファイルを index.runtime.d.ts に移行する
- (TypeScript のみ) allowUmdGlobalAccess オプションを有効にする
これらは v2 系で作られた全てのゲームで必要です。
INFO
akashic-cli の最新バージョンを用いて akashic init -t javascript
などを実行した場合、これらの作業はすべて済んだ状態で生成されます。 あくまでも Akashic Engine v2 で作成されたコンテンツを Akashic Engine v3 へ移行する場合に必要な作業です。
game.json の sandbox-runtime を "3" にする
ゲームディレクトリにある game.json を編集して、 environment
プロパティ内の sandbox-rutnime
の値を "3"
に変更してください。
{
...
"environment": {
- "sandbox-runtime": "2"
+ "sandbox-runtime": "3"
}
}
akashic sandbox
や akashic serve
コマンドは、この値によってゲームの実行に利用するエンジンのバージョンを決めています。
(TypeScript のみ) 開発時に参照する型定義ファイルを "lib/main.d.ts" から "index.runtime.d.ts" へ
TypeScript で開発している場合、型定義ファイルも v3 系のものを利用する必要があります。また v3 系ではこの型定義ファイル名が変更されています。
まず次のコマンドで Akashic Engine v3 をインストールします。
npm install --save-dev @akashic/akashic-engine@3
型定義ファイルが lib/main.d.ts
から index.runtime.d.ts
に変更されているので、 tsconfig.json の files
プロパティを下記のように変更します。
"files": [
- "node_modules/@akashic/akashic-engine/lib/main.d.ts"
+ "node_modules/@akashic/akashic-engine/index.runtime.d.ts"
],
(TypeScript のみ) allowUmdGlobalAccess を有効にする
エンジン内部の変更のため、 TypeScript コンパイル時のオプションとして --allowUmdGlobalAccess
が必要になりました。
tsconfig.json の compilerOptions
プロパティに allowUmdGlobalAccess
(--
なし) を追加します。
"compilerOptions": {
...
+ "allowUmdGlobalAccess": true
},
--allowUmdGlobalAccess
が必須になるため、TypeScript の要求バージョンが 3.5 以上になります。 バージョン 3.5 未満の場合は、TypeScript を 3.5 以上に更新してください。
仕様変更への追従 (必須)
v3 では、v2 での非推奨機能の廃止を中心に、いくつかの仕様変更が行われています。 当該の機能を利用している場合は追従が必要になります。
アンカーポイント未指定時の回転・拡縮の基準点が左上に
v2 では、アンカーポイント未指定 (デフォルト) の場合、「座標 (x, y) の基点はエンティティの左上、回転・拡大縮小の基点はエンティティの中央」になっていました。 一方で、アンカーポイントを指定した場合は、座標・回転・拡大縮小の基点が全てアンカーポイントの位置になっていました。
Akashic Engine v3 からはこの不整合を解消して単純化します: アンカーポイントのデフォルト値は (0, 0) になります 。つまり、特に指定してしない場合、座標・回転・拡大縮小の基点はエンティティの左上端に統一されます。
なお移行措置として、 g.E#anchorX
または g.E#anchorY
に明示的に null
を指定することで v2 のデフォルトの挙動を再現できます。これは非推奨の挙動です。
const e = new g.E({
...
anchorX: null // 前バージョンのデフォルト挙動の再現
});
Game#random[0] の廃止
非推奨だった g.game.random[0]
が廃止されます。同じ形で利用できる g.game.random
を利用してください。
g.game.random.generate();
Scene#setTimeout(), Scene#setInterval() の一部引数順序のメソッドの廃止
g.Scene#setInterval()
および g.Scene#setTimeout()
で非推奨だった引数順序のメソッドが廃止になりました。
下記の形式を利用してください。
setInterval(handler: () => void, interval: number, owner?: any)
setTimeout(handler: () => void, milliseconds: number, owner?: any)
SystemLabel の廃止
g.SystemLabel
および g.Renderer#drawSystemText()
が廃止になりました。 g.DynamicFont
を利用してください。 DynamicFont
の利用はこちらのページを参照してください。
Util のいくつかのメソッドの移動
g.Util
の一部メソッドを移動しました。利用している場合は追従が必要となります。
createSpriteFromE()
:g.SpriteFactory.createSpriteFromE()
を利用してください。createSpriteFromScene()
:g.SpriteFactory.createSpriteFromScene()
を利用してください。asSurface()
:g.SurfaceUtil.asSurface()
を利用してください。createMatrix()
: 廃止になりました。new g.PlainMatrix()
を利用してください。
ResourceFactory#createTrimmedSurface()の廃止
指定した Surface から指定範囲を切り取った Surface を返す g.ResourceFactory#createTrimmedSurface()
が廃止になりました。コンテンツ側で下記のような同様の処理を実装する必要があります。
function createTrimmedSurface(targetSurface, targetArea) {
const surface = g.game.resourceFactory.createSurface(width, height);
const renderer = surface.renderer();
renderer.begin();
renderer.drawImage(
targetSurface,
targetArea.x,
targetArea.y,
targetArea.width,
targetArea.height,
0,
0
);
renderer.end();
return surface;
}
各種 enum の廃止
g.TickGenerationMode
が廃止になりました。利用している場合、代わりにg.TickGenerationModeString
("by-clock" | "manual"
) を利用してください。- TypeScript では
g.Scene#tickGenerationMode
の型がg.TickGenerationModeString
になります。
- TypeScript では
g.LocalTickMode
が廃止になりました。 利用している場合、代わりにg.LocalTickModeString
("full-local" | "non-local" | "interpolate-local"
) を利用してください。- TypeScript では
g.Scene#local
の型がg.LocalTickModeString
になります。 - これにより、
g.Scene#local
が boolean だった当時 (v1 系) のコードとは互換性がなくなります。
前バージョン(v2.x.x 以前) のコード
jsconst scene = new g.Scene({ ..., tickGenerationMode: g.TickGenerationMode.Manual, local: g.LocalTickMode.NonLocal });
Akashic Engine v3 のコード
jsconst scene = new g.Scene({ ..., tickGenerationMode: "manual", local: "non-local" });
- TypeScript では
g.SceneState
が廃止になりました。 -g.Scene#state
の型,g.Scene#onStateChange
の通知する型がg.SceneStateString
("destroyed" | "standby" | "active" | "deactive" | "before-destroyed"
) になります。前バージョン(v2.x.x 以前) のコード
jsscene.stateChanged.add((state) => { if (state === g.SceneState.Destroyed) { ... } });
Akashic Engine v3 のコード
jsscene.onStateChange.add((state) => { if (state === "destroyed") { ... } });
非推奨機能の変更
新たに次の機能が非推奨になります。v3 では旧バージョンとの互換性が維持されますが、移行を推奨します。
Trigger 名の移行
Game#join
や Scene#loaded
など、統一感のなかったトリガーの変数名を整理しました。前バージョン(v2.x.x 以前)のトリガーの変数名は非推奨となります。
下記の表ではトリガー名が変更となった一部のクラスを記述しています。
クラス名 | 前バージョン(v2.x.x 以前)のトリガー名 | Akashic Engine v3 のトリガー名 |
---|---|---|
Game | join | onJoin |
leave | onLeave | |
N/A | onPlayerInfo | |
skippingChanged | onSkipChange | |
Scene | update | onUpdate |
loaded | onLoad | |
assetLoaded | onAssetLoad | |
assetLoadFailed | onAssetLoadFailure | |
assetLoadCompleted | onAssetLoadComplete | |
stateChanged | onStateChange | |
message | onMessage | |
pointDownCapture | onPointDownCapture | |
pointMoveCapture | onPointMoveCapture | |
pointUpCapture | onPointUpCapture | |
operation | onOperation |
enum の移行
g.CompositeOperation
が非推奨になりました。代わりに ("source-over" | "source-atop" | "lighter" | "copy" | "experimental-source-in" | "experimental-source-out" | "experimental-destination-atop" | "experimental-destination-in" | "destination-out" | "destination-over" | "xor"
) を利用してください。前バージョン(v2.x.x 以前) のコード
jsconst green = new g.FilledRect({ scene: scene, x: 50, width: 100, height: 100, cssColor: "green", compositeOperation: g.CompositeOperation.SourceOver });
Akashic Engine v3 のコード
jsconst green = new g.FilledRect({ scene: scene, x: 50, width: 100, height: 100, cssColor: "green", compositeOperation: "source-over" });
g.TextAlign
が非推奨になりました。代わりに ("left" | "center" | "right"
) を利用してください。g.FontWeight
が非推奨になりました。 代わりに ("normal" | "bold"
) を利用してください。g.FontFamily
が非推奨になりました。 代わりに"serif" | "sans-serif" | "monospace"
を利用してください。前バージョン(v2.x.x 以前)のコード
jsconst font = new g.DynamicFont({ ... fontWeight: g.FontWeight.Bold, fontFamily: ["Meiryo", g.FontFamily.Serif] }); const label = new g.Label({ ... textAlign: g.TextAlign.Center });
Akashic Engine v3 のコード
jsconst font = new g.DynamicFont({ ... fontWeight: "bold" fontFamily: ["Meiryo", "serif"], }); const label = new g.Label({ ... textAlign: "center" });
上記の変更に伴い互換性維持のため、TypeScript では一部の型が変化します。
g.E#compositeOperation
:g.CompositeOperation | g.CompositeOperationString
になります。g.Label#textAlign
:g.TextAlign | g.TextAlignString
になります。g.Label#fontWeight
:g.FontWeight | g.FontWeightString
になります。
RandomGenerator#get() の移行
g.RandomGenerator#get()
が非推奨になりました。代わりに g.RandomGenerator#generate()
を利用してください。
NinePatchSurfaceEffector の移行
g.NinePatchSurfaceEffector
が非推奨になりました。代わりに g.SurfaceUtil#drawNinePatch() を利用してください。
追加機能など
読み込むアセットをファイルパスで複数まとめて指定できるように
g.Scene のコンストラクタ引数に assetPaths?: string[]
が追加されます。
アセット ID の配列を渡す従来の assetIds?: string[]
とは異なり、ファイルパスの配列を渡すことで読み込むアセットを指定できるようになります。 ここでのファイルパスは game.json のあるディレクトリをルート (/
) とする スラッシュ区切りの絶対パスとなります。以降これをファイルパス形式と呼びます。
また、アセットパス形式では glob のサブセット文法(**
, *
, ?
) をサポートしています。 (**
はあらゆるファイルや 0 個以上のディレクトリ、サブディレクトリにマッチします。 *
は 0 文字以上任意の文字列にマッチします。 ?
は任意の 1 文字にマッチします。)
const scene = new g.Scene({
game: g.game,
assetPaths: ["/image/character01.png", "/assets/**/*"]
});
上記サンプルコードの assetPaths
のグロブ指定("/assets/**/*"
)では、assets ディレクトリに下記のようなファイルが存在する場合、全てのファイルが対象となります。
- assets/scenarios/scenario1.txt
- assets/scenarios/scenario2.txt
- assets/map.json
(対応するアセットが game.json に登録されている必要は引き続きあります)
アセットを ID やファイルパスで、種類別に取得できるように
g.Scene#asset
が追加されます。この値は、読み込み済みのアセットを種類別に取得する次のようなメソッドを提供します。
- ファイルパス形式での取得:
getImage()
,getAudio()
など - ファイルパスのパターンから複数まとめて取得:
getAllImages()
,getAllAudios()
など - アセット ID からの取得:
getImageById()
,getAudioById()
など
これによってたとえば次のように、ファイルパス形式でアセットを種類ごとに取得できます。
// 画像アセットの取得
const playerImage = scene.asset.getImage("/assets/player/image.png");
const player = new g.Sprite({
scene: scene,
src: playerImage,
width: playerImage.width,
height: playerImage.height
});
// オーディオアセットの取得
// (game.json での記述同様、オーディオアセットに限り、拡張子抜きで指定する必要があります)
const bgm = scene.asset.getAudio("/audio/bgm01");
bgm.play();
getAllImages()
等のグロブによる複数検索では、該当するアセットの配列を返します。 アセットの指定には assetPaths
と同様に glob のサブセット文法(**
, *
, ?
) を利用できます。
// 複数の画像アセットの取得
const thumbnails = scene.asset.getAllImages("/assets/**/*.png");
for (let i = 0; i < thumbnails.length; i++) {
const thumbnail = new g.Sprite({
scene: scene,
src: thumbnails[i],
width: thumbnails[i].width,
height: thumbnails[i].height
});
...
}
// 複数のオーディオアセットの取得
const audios = scene.asset.getAllAudios("/audio/bgm*");
for (let i = 0; i < audios.length; i++) {
audios[i].stop();
}
アセット ID による取得 (getImageById()
など) は、g.Scene#assets
と同様の機能です。 ただし TypeScript では as g.ImageAsset
等のダウンキャストが不要になります。
// g.Scene#assets でのアセットの取得
const imageWidth = (scene.assets["foo"] as g.ImageAsset).width;
// getImageById()での取得
const imageWidth = scene.asset.getImageById("foo").width;
// (返り値の型が ImageAsset になっているので、キャストなしで `width` にアクセスできます)
g.Scene#assets
の完全な機能一覧は API リファレンス を参照してください。
assets/ ディレクトリに全ての種類のアセットを置けるように
従来の image/
, audio/
などのディレクトリに加えて、 assets/
ディレクトリが利用できるようになりました。 このディレクトリ内においたアセットは、 akashic scan asset
でスキャンされ、 game.json に登録されます。
ただし assets/
は、他のディレクトリと次の点で異なります。
- 全ての種類のアセットがスキャンされ登録される
- アセットの種別がファイルの拡張子から自動的に決定される
- アセット ID が不定になる
これにより、従来は不可能だった次のようなフォルダ構造が可能になります。
- assets/
- stage1/
- map.json
- background.png
- bgm.aac
- bgm.ogg
- stage2/
- map.json
- background.png
- bgm.aac
- bgm.ogg
- stage1/
「アセット ID が不定になる」ため、利用には上述の filePaths
や scene.assets.getImage()
などを利用することになります。 この仕様の背景などについては Akashic Engine 入門 » 複数のアセットをまとめて扱う をご覧ください。
TIP
厳密には、これは Akashic Engine の追加機能ではなく、 akashic scan asset
コマンドの機能拡張です (akashic-cli v1.14.3 以降で利用可能)。ただし上述のとおり「アセット ID が不定になる」性質上、v3 の追加機能がないと利用できません。事実上 v3 以降専用の仕様となります。
エンティティの座標系を変換するメソッドを追加
エンティティの座標系を変換するメソッド E#localToGlobal()
, E#globalToLocal()
が追加されます。
g.E#localToGlobal()
はローカル座標をグローバル座標に変換します。
const parentEntity = new g.E({ scene: scene, x: 100, y: 100 });
const nestedEntity = new g.E({ scene: scene, parent: parentEntity });
// nestedEntity のローカル座標系での座標 (10, 20) はグローバル座標系では (110, 120)となります。
const globalPoint = nestedEntity.localToGlobal({ x: 10, y: 20 });
g.E#globalToLocal()
はグローバル座標をローカル座標に変換します。
const parentEntity = new g.E({ scene: scene, x: 100, y: 100 });
const nestedEntity = new g.E({ scene: scene, parent: parentEntity });
// nestedEntity のグローバル系での座標 (110, 120) はローカル座標系では (10, 20)となります。
const localPoint = nestedEntity.globalToLocal({ x: 110, y: 120 });
デフォルトローディングシーンで背景が透過で画面右下にプログレスバーが表示できるように
defaultLoadingScene に "compact"
が追加されます。
game.json の defaultLoadingScene に "compact"
を指定した時、ローディング画面が以下のように表示されます。
- 背景が透過になります。 (下記画像では灰色部分が背景で透過されて表示されています。)
- プログレスバーが画面中央ではなく右下の方に小さく表示されます。
g.PlayerInfoEvent の追加
このイベントを g.game.raiseEvent()
すると、以降 g.PointDownEvent
等の player.name
プロパティに反映されるようになります。このイベントは、将来マルチプレイでのプレイヤー名を取得・通知するために先行して追加されるものです。
シーンスタックから取り除くシーンの数を指定できるように
g.Game#popScene()
の第 2 引数に step?: number
が追加されます。
step
に指定した数だけ pop が行われるようになります。step のデフォルト値は 1 です。
g.game.popScene(false, 3);
ナインパッチを描画するメソッドの追加
SurfaceUtil に NinePatch を描画するメソッド g.SurfaceUtil#drawNinePatch()
が追加されます。 これは対象の Surface
にナインパッチ処理された Surface
を描画する機能です。
const destSurface = game.resourceFactory.createSurface(100, 100);
const srcSurface = game.resourceFactory.createSurface(100, 100);
const borderWidth = { top: 1, bottom: 2, left: 3, right: 4 };
SurfaceUtil.drawNinePatch(destSurface, srcSurface, borderWidth);
操作プラグインを登録、開始、停止を行うメソッドの追加
g.OperationPluginManager
に以下のメソッドが追加されます。
- register(): 操作プラグインを手動で登録します。
- start(): 操作プラグインを開始します。
- stop():操作プラグインを停止します。