game.json の仕様

# これは

Akashic のゲームにおいてメタ情報などを取り扱う設定ファイル、game.json の仕様をまとめます。対象バージョンは akashic-engine@1.11.2 以降です。

# game.json とは

game.json は、Akashic のゲームのメタ情報などを取り扱う JSON 形式の設定ファイルです。主に以下のような情報を取り扱います。

  • ゲーム画面のサイズ
  • ゲームの FPS
  • ゲーム内で利用する各種素材のファイルパスや ID

これらに加えて、画像素材のサイズのような補助的な情報も取り扱います。

各種素材(アセット)のファイルパスや画像のサイズなどは、手動で記述・維持しにくいので、 game.json を生成・管理するツールとして akashic-cli が提供されています。 akashic-cli の詳細は akashic-cli 利用ガイド を参照してください。

# 形式

妥当な game.json の内容は一つのオブジェクトです。それは以下の名前のプロパティと、対応する値を持ちます。

  • width (必須)
    • 数値
    • 画面の幅 (ピクセル)
  • height (必須)
    • 数値
    • 画面の高さ (ピクセル)
  • fps (必須)
    • 数値
    • ゲームの FPS (秒間フレーム数)
  • assets (必須)
    • オブジェクト (詳細は後述)
    • ゲーム内で利用するアセットの定義
  • main (指定推奨)
    • 文字列
    • エントリポイントのスクリプトへのパス
  • globalScripts
    • 配列 (詳細は後述)
    • ゲーム内で利用するスクリプトアセット定義の短縮表記
  • renderers
    • 配列(詳細は後述)
    • ゲームが利用するレンダラーを定義
  • defaultLoadingScene
    • 文字列 (詳細は後述)
    • デフォルトのローディングシーンを定義
  • environment
    • オブジェクト (詳細は後述)
    • このゲームの実行環境に要求する条件
  • maxPoints
    • 数値
    • ゲーム内での最大同時タップ数を指定

次の JSON は、妥当な game.json の一例です:

{
  "width": 320,
  "height": 240,
  "fps": 30,
  "assets": {
    "main": {
      "type": "script",
      "path": "script/main.js",
      "global": true
    }
  },
  "main": "./script/main.js"
}

この game.json は、画面サイズが 320x240 で FPS が 30 の、 "script/main.js" というゲームスクリプト一つだけを使うゲームであること、またエントリポイントはその "./script/main.js" であることを定義しています。

assets (アセット定義)

game.json のオブジェクト中、 assets の値は、オブジェクトでなければなりません。そのオブジェクトの各キーはアセット ID、値はその ID のアセット定義です。

アセット ID は、ゲーム開発者が任意に設定できる文字列です。アセット ID は「半角英数字、アンダースコア "_"、ドル記号 "$"」のみで構成され、かつ「英字で始まっている」必要があります。あるシーンで読み込んだアセットは g.Scene#assets オブジェクトから参照できます。アセット ID はこのオブジェクトのキーとして利用されます。すなわち、アセット ID が "foo" のアセットは、scene.assets["foo"] のような形で参照することができます。

アセット定義 は、オブジェクトであり、少なくとも以下の値を持つことができます:

  • type (必須)
    • 次の文字列のいずれか: "image", "audio", "text", "script", "vector-image", "binary"
    • アセットの種類
  • path (必須)
    • 文字列
    • game.json のあるディレクトリからの相対パス (スラッシュ区切り)
    • アセットを表すファイル
  • global
    • 真理値
    • グローバルアセットであるか否か (省略された場合、偽)

global の値が真に設定されたアセットは、グローバルアセット になります。通常のアセットは、シーン単位で管理されます。アセットを利用する場合、g.Scene のコンストラクタでそのアセット ID を指定する必要があります。しかしグローバルアセットは、シーン単位ではなく、ゲーム内において常に利用可能なアセットになります。通常のアセットが g.Scene#assets から参照できるのに対して、グローバルアセットは g.Game#assets から参照できます。

(なお Akashic Engine v3 以降では、より柔軟な API を提供する g.Scene#asset (s がないことに注意) 経由でもアセットを参照できます)

type の値によっては、アセット定義にさらに追加の制約や必須プロパティが存在します。

  • "image"
    • プロパティ: width (必須)
      • 数値
      • 画像の幅(ピクセル)
    • プロパティ: height (必須)
      • 数値
      • 画像の高さ(ピクセル)
    • プロパティ: slice
      • オプジェクト
      • 切り出す領域。"{x: 数値、 y: 数値, width: 数値, height: 数値}" 指定された場合、画像ファイルのこの領域だけを画像アセットとして使う
        • 数値配列で [x, y, width, height] でも指定できる
    • 制約: path の拡張子は ".png"、".jpg" または ".jpeg" でなければならない
  • "audio"
    • プロパティ: systemId (必須)
      • 文字列
      • このアセットの system (本文書では詳細割愛)
      • 省略された場合、 g.Game#defaultAudioSystemId の値 (defaultAudioSystemId の初期値は "sound")
    • プロパティ: duration (必須)
      • 数値
      • 再生時間。単位はミリ秒
    • プロパティ: loop
      • 真理値
      • ループ再生を行うか。省略された場合、systemId が "music" の場合は真、"sound" の場合は偽となるため、ゲーム開発者はこの値を変更する必要はない
    • プロパティ: hint
      • オブジェクト
      • プロパティ: streaming
        • 真理値
        • ストリーミング再生が適しているアセットであるか否か
      • プロパティ: extensions
        • 配列
        • ファイルの拡張子の配列
          • 省略された場合は [".ogg", ".aac"] となる
          • ".aac" の代わりに ".m4a" を利用する場合はここで指定する必要がある
    • プロパティ: offset
      • 数値
      • 再生開始位置。単位はミリ秒
    • 制約: path はファイルのパス文字列から拡張子を取り除いたものでなければならない
    • 制約: 対応するファイルの拡張子は ".ogg", ".m4a" または ".aac" でなければならない
  • "script"
    • プロパティ: preload
      • 真理値
      • 他のアセットよりも優先して読み込むかどうか。真であるアセットは、エントリポイントよりも先行して読み込まれる
    • プロパティ: exports
      • 配列
      • このアセットが公開する変数名の配列。指定された場合、 module.exports の一部を上書きする
    • 制約: path の拡張子は ".js" でなければならない
  • "vector-image”
    • プロパティ: width (必須)
      • 数値
      • 画像の幅(ピクセル)
    • プロパティ: height (必須)
      • 数値
      • 画像の高さ(ピクセル)

オーディオアセット (type が "audio" であるアセット) は他と異なり、ファイルパスに拡張子を書かないことに気をつけて下さい。音素材に関して、拡張子以外の部分が同名のファイル (e.g. "audio/foo.ogg" と "audio/foo.m4a" など) は、それぞれ同じ内容であることが期待されます。これらはエンジンが、ゲームの各実行環境で再生可能な形式のファイルを自動的に選択して再生するためです。

main

akashic-engine@1.2.0 で導入。

main は、ゲームのエントリポイントとなるスクリプト( main スクリプト )を指定する値です。

指定されたスクリプトは、アセット定義 (assets) でグローバルなスクリプトアセットとして定義されていなければなりません。エンジンはグローバルアセットの読み込み後、この値で require() を呼び出し、その戻り値をエントリポイントとみなして実行します。 (require() する関係上、アセット定義の path と異なり、相対パスは "./" で始める必要がある点に気をつけて下さい。)

main スクリプトは、次の仕様を満たす関数をエクスポートする必要があります。

  • 引数 param: g.GameMainParameterObject を受け取り、値を返さない ((param: g.GameMainParameterObject) => void)
  • 呼び出された時、 g.Game#pushScene() によるシーンの追加など、ゲームの初期化処理を行う

akashic-engine@1.1.2 以前では、このフィールドは存在しませんでした。エンジンは後方互換性のため、 main が指定されていない場合には、以下のような内容の main スクリプトが与えられたかのように振る舞います。

module.exports = function(param) {
  if (!param.snapshot) {
    var mainSceneFun = require("mainScene");
    g.game.pushScene(mainSceneFun());
  } else {
    var snapshotLoader = require("snapshotLoader");
    snapshotLoader(param.snapshot);
  }
};

この場合、assets は少なくとも "mainScene" という名前のキーを持つ必要があります。アセット ID "mainScene" を持つアセットは、type が "script" で global は true、すなわちグローバルなスクリプトアセットでなければなりません。

(上の例では require()にアセット ID を渡していることに気をつけてください。 akashic-engine の提供する require()は、Node.js などのそれと異なり、game.json に存在するアセット ID を(優先的に)解決します。これは歴史的経緯によるものです。上の例では説明のために使っていますが、この動作の利用は非推奨です。)

globalScripts

akashic-engine@0.1.0 で導入。

globalScripts は、スクリプトアセットの短縮記法です。これは akashic install/uninstall のために用意された値です。通常ゲーム開発者が編集する必要はありません。

存在する場合、globalScripts はファイルパスの配列でなければなりません。ファイルパスは game.json のあるディレクトリからの相対パスで、拡張子が ".js" または ".json" である必要があります。

ここに書かれたファイルパスは、アセット ID を持たないグローバルなスクリプトアセット (".js" の場合) またはテキストアセット (".json" の場合) として読み込まれます。 (アセット ID を持たないアセットは通常、定義も利用もできませんが、スクリプトアセットおよび JSON であるテキストアセットに限っては require() によってファイルパスで参照することができます)

renderers

akashic-engine@1.0.3 で導入。

renderers は、ゲームで利用するレンダラーを指定するためのリストであり、レンダラーを識別する文字列であるレンダラー識別子の配列である必要があります。

レンダラー識別子はサービスや実行環境により異なります。

Akashic エンジンは、レンダラー識別子に該当するレンダラーをリストの先頭から順に探索します。利用可能なレンダラーが見つかると、そのレンダラーを利用して描画を行います。

例えば、 canvaswebgl という 2 つのレンダラー識別子が利用可能な環境において、 webgl を優先して使いたい場合は、"renderers": ["webgl", "canvas"] と記述します。

レンダラー識別子として"auto" を指定した場合は、Akashic エンジンが自動的にレンダラーを決定します。また、game.json に renderers を定義しなかった場合の挙動は "renderers": ["auto"] を指定した場合と等価になります。

# defaultLoadingScene

defaultLoadingScene は、グローバルアセット読み込み中のローディングシーンなど、デフォルトのローディングシーンについての設定です。 akashic-engine@1.11.2 では "default" または "none" を指定できます。 "default" を指定または省略時はエンジンに用意されているデフォルトのローディングシーンを表示します。 "none" を指定するとそれらのローディングシーンを非表示にできます。

akashic-engine@3.0.0 で "compact" が導入されました。 "compact" を指定すると背景が透過になり、プログレスバーが画面中央ではなく右下の方に小さく表示されます。

# defaultSkippingScene

defaultSkippingScene は、早送り中の描画についての設定です。 akashic-engine@3.4.0 では "fast-forward", "indicator", "none" を指定できます。 "fast-forward" を指定、または省略した場合は早送り中のゲーム状態をそのまま描画します。 "indicator" を指定すると早送り中はエンジンに用意されている専用のスキッピングシーンを描画します。 "none" を指定すると早送り中の描画を非表示にできます。

environment

akashic-engine@2.0.0 で導入。

environment は、ゲームを実行する環境やエンジンに対する要求を指定するためのオブジェクトです。オブジェクトのキーは要求の種類、値は要求内容です(必要なバージョンなど)。

次の値が利用できます。

キー 説明
"sandbox-runtime" "1", "2" または "3" (文字列) akashic-sandbox でゲームを実行する際、実行するエンジンのバージョンを決定するために利用されます。
Akashic Engine v3 系で作成しているゲームの場合、 "3" を指定してください。
v2 系で作成しているゲームの場合、 "2" を指定してください。
省略された場合、 "1" として解釈されます。
"nicolive" オブジェクト ニコ生ゲームとして登録する場合に参照される設定。詳細は ニコニコ生放送上で遊べるゲームの作成 を参照してください。
"niconico" オブジェクト 非推奨。ニコ生ゲームとして登録する場合の情報としては、 `"nicolive"` を利用してください。この値は後方互換性のために残されていますが、非推奨です。 `"nicolive"` と両方指定されている場合、無視されます。
"external" オブジェクト プラグイン等の外部 API を利用する場合に記述します。詳細はsandbox.config.js の仕様を参照してください。
  "environment": {
    "sandbox-runtime": "3"
  }

"sandbox-runtime" の値は、 akashic export html でエンジンをバンドルした HTML を出力する際にも参照されます。

# maxPoints

akashic-engine@3.9.3 で導入。

ゲーム内での最大同時タップ数を指定します。 タッチデバイス等でのマルチタップに対して制限を加えられ、マルチタップに依る想定外の挙動を回避することができます。

# game.json の例

妥当な game.json の一例を示します。

{
  "width": 320,
  "height": 320,
  "fps": 30,
  "main": "./script/main.js",
  "assets": {
    "main": {
      "type": "script",
      "path": "script/main.js",
      "global": true
    },
    "character": {
      "type": "image",
      "path": "image/character.png",
      "width": 32,
      "height": 32
    },
    "background": {
      "type": "image",
      "path": "image/background.jpg",
      "width": 320,
      "height": 320
    },
    "bgm": {
      "type": "audio",
      "path": "audio/bgm",
      "systemId": "sound",
      "duration": 1500,
      "hint": {
        "extensions": [".aac", ".ogg"]
      }
    }
  },
  "globalScripts": [
    "node_modules/@akashic-extension/akashic-timeline/lib/Easing.js",
    "node_modules/@akashic-extension/akashic-timeline/lib/Timeline.js",
    "node_modules/@akashic-extension/akashic-timeline/lib/Tween.js",
    "node_modules/@akashic-extension/akashic-timeline/lib/index.js",
    "node_modules/@akashic-extension/akashic-timeline/package.json"
  ],
  "environment": {
    "sandbox-runtime": "3"
  }
}