ゲームが複雑になると、利用するアセットも多くなり、それを扱うコードも煩雑になりがちです。 Akashic Engine は、アセットを複数まとめて管理しやすくするためのいくつかの機能を提供しています。
これまでの文書では、画像アセットは image/
、オーディオアセットは audio/
など、アセットの種類別にフォルダが分かれていました。
これは akashic scan asset
コマンドが、それらのディレクトリを検索する仕様になっているためです。
しかし複雑なゲームでは、アセットを種類ではなく意味で分類・整理したいかもしれません。
たとえばステージごとにマップデータと BGM と画像をまとめて保存する、という形にしたくなるかもしれません。
このような場合には、 assets/
ディレクトリが利用できます。
これは akashic scan asset
コマンドがアセットを検索するディレクトリの一つです (akashic-cli v1.14.3 から) 。
ただし他のディレクトリと次の点で異なります:
これによりたとえば次のようなフォルダ構造が可能になります:
assets/
以外のディレクトリでは、アセット ID はファイル名の basename (拡張子を抜いた部分) になります。
しかしこれには「basename が重複するアセットを一切作れない」という制限がつきます。
たとえば上の例に似た audio/stage1/bgm.m4a
と audio/stage2/bgm.m4a
を置くと、アセット ID が bgm
で重複してエラーになります。
assets/
ディレクトリは、この問題を回避するため、そもそもアセット ID を保証しません。
これにより basename の重複したアセットを許容します。ただしアセット ID でのアクセスはできなくなります (不定のため)。
Akashic Engine v3 以降では、後述のとおりアセットのファイルパスを使ってアセットを取得できるため、そちらを利用することになります。
これまでの例では、 g.Scene
の生成時に assetIds
として利用するアセットの ID を指定していました。
const scene = new g.Scene({
game: g.game,
assetIds: ["character01", "bgm01"]
});
これの代わりに、 assetPaths
を使うと、ファイルパスで読み込むアセットを指定することができます。
ここでファイルパスは、 game.json のあるディレクトリをルート (/
) とする スラッシュ区切りの絶対パスです (以降これをアセットパス形式と呼びます)。
const scene = new g.Scene({
game: g.game,
assetPaths: ["/image/character01.png", "/assets/**/*"]
});
この例でも使っているように、アセットパス形式では glob のサブセット文法(**
, *
, ?
) をサポートしています。
**
はあらゆるファイルや 0 個以上のディレクトリ、サブディレクトリにマッチします。*
は 0 文字以上任意の文字列にマッチします。?
は任意の 1 文字にマッチします。上記サンプルコードの assetPaths
のグロブ指定("/assets/**/*"
)では、assets ディレクトリに下記のようなファイルが存在する場合、全てのファイルが対象となります。
(対応するアセットが game.json に登録されている必要は引き続きあります)
ここまでの文書では、主に scene.asset.getImageById()
などの関数を使い、アセット ID からアセットを取得していました。
シーン生成時の assetPaths
同様、アセットの取得でも ID ではなくパスを利用することができます。
これには scene.asset.getImage()
, scene.asset.getAudio()
などを利用します。
// 画像アセットの取得
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();
またこれも assetPaths
同様、アセットパスにはグロブを利用して複数のアセットを一括で取得することもできます。
これには getAllImages()
, getAllAudios()
などのメソッドを利用します。戻り値は配列になります。
// 複数の画像アセットの取得
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();
}