Skip to content

ランキングゲームテンプレート

Akashic 関連ツール akashic init で、ランキングゲーム向けのテンプレートからゲームを生成できます。 ランキングゲームの作成には、このテンプレートを利用することを推奨します。

インストール

akashic init コマンドを利用するには akashic-cli ツールが必要です。 インストール のページを参考にインストールを行ってください。

ランキングゲームテンプレートからのゲーム生成

akashic-cli をインストールすると、 CUI ツールで akashic コマンドが利用できるようになっています。 ランキングゲームテンプレートからゲームを生成するには、以下のコマンドを実行してください。

sh
akashic init -t javascript-shin-ichiba-ranking
akashic init -t javascript-shin-ichiba-ranking

TIP

ここでは解説しませんが、 -t typescript-shin-ichiba-ranking とすると、JavaScript ではなく TypeScript 向けテンプレートが利用できます。

(補足) 詳細な手順

CUI ツールを起動します。適当な作業場所のフォルダに cd コマンドで移ってください。仮に c:\akashic というところに移るものとします。以下のようなコマンドになります。

sh
c:
cd \akashic
c:
cd \akashic

ここに、今回のゲーム用のフォルダを用意したいと思います。以下のコマンドを実行してください。

sh
mkdir game
cd game
mkdir game
cd game

mkdirgame というフォルダを作り、 cd で作業場所フォルダを今作成した新しいフォルダにしたので、このフォルダで Akashic ゲームを生成したいと思います。

以下のコマンドを実行してください。

sh
akashic init -t javascript-shin-ichiba-ranking
akashic init -t javascript-shin-ichiba-ranking

akashic init は、「現在の作業フォルダに Akashic ゲームを生成する」コマンドです。 -t javascript-shin-ichiba-ranking の部分は、「JavaScript 向け・ランキングゲーム用のテンプレートを使う」という意味の akashic init コマンドのオプションです。 これにより、いくつかランキングゲームの作成に必要な処理が最初から組み込まれたゲームが生成されます。

このコマンドを実行すると、対話型のインターフェースでゲーム画面の幅・高さなどの指定を求められます。 お好みの値を入力して Enter キーを押してください。 何も入力せずに Enter キーを押すと、画面サイズ 1280x720 で 30fps になります。

TIP

ニコニコ生放送上で実行した時、上下左右に余白を作らないためには、画面サイズが 16:9 である必要があります。 FPS は 30 または 60 を推奨します。

テンプレートから生成されたゲーム

テンプレートから生成されたゲームは、次のように画面中央でキャラクタが浮かんでいるだけのゲームになっています。

画面サイズ 640x480 を指定して生成されたゲーム画面

これは akashic-sandbox を実行し、 http://localhost:3000 にアクセスすると確認できます。

sh
akashic-sandbox
akashic-sandbox

このゲームは次の要素で構成されています:

  • 画面内をクリックすると弾を発射するキャラクタ
  • 弾を発射すると増えていく右上の得点 (SCORE)
  • 画面右上の残り時間 (TIME)

これ自体は、画像表示や音声再生など、よく使われる機能のサンプルコードとしての意味あいが強く、ゲーム性はほぼありません。 しかし最低限ランキングゲームとしての形を満たしています (画面の連打回数を競うだけのゲーム) 。 また以下で紹介するように、ランキングゲームに必要な設定や処理が含まれています。

ここから不要なコードを削除して、オリジナルのランキングゲームを作成してください。

参考

supportedModes の指定

ランキングゲームテンプレートの game.json では、supportedModes の指定 が最初から行われています。

json
{
  // ... その他の記述 ...

  "environment": {
    "nicolive": {
      "supportedModes": ["ranking"] // [!code hilight]
    }
  }
}
{
  // ... その他の記述 ...

  "environment": {
    "nicolive": {
      "supportedModes": ["ranking"] // [!code hilight]
    }
  }
}

制限時間の申告

ランキングゲームテンプレートの game.json では、制限時間の申告 が最初から行われています。

json
{
  // ... その他の記述 ...

  "environment": {
    "nicolive": {
      "supportedModes": ["ranking"],
      "preferredSessionParameters": {
        "totalTimeLimit": 82
      }
    }
  }
}
{
  // ... その他の記述 ...

  "environment": {
    "nicolive": {
      "supportedModes": ["ranking"],
      "preferredSessionParameters": {
        "totalTimeLimit": 82
      }
    }
  }
}

totalTimeLimit には 20 以上 200 以下の整数を指定できます。

制限時間の参照

ランキングゲームテンプレートの main.js では、 main() の引数 param から制限時間を取得しています。次の箇所がそれです。

javascript
let time = 60; // 制限時間
if (param.sessionParameter.totalTimeLimit) {
  time = param.sessionParameter.totalTimeLimit;
}
let time = 60; // 制限時間
if (param.sessionParameter.totalTimeLimit) {
  time = param.sessionParameter.totalTimeLimit;
}

この値を使って、次のように scene.update で 1 フレームごとにカウントダウンしていき、ラベル timeLabel で画面に表示しています。

javascript
const updateHandler = () => {
  if (time <= 0) {
    // (中略)
    scene.update.remove(updateHandler); // このハンドラを削除=カウントダウンを停止
  }
  // カウントダウン処理
  time -= 1 / g.game.fps;
  timeLabel.text = "TIME: " + Math.ceil(time);
  timeLabel.invalidate();
};
scene.update.add(updateHandler);
const updateHandler = () => {
  if (time <= 0) {
    // (中略)
    scene.update.remove(updateHandler); // このハンドラを削除=カウントダウンを停止
  }
  // カウントダウン処理
  time -= 1 / g.game.fps;
  timeLabel.text = "TIME: " + Math.ceil(time);
  timeLabel.invalidate();
};
scene.update.add(updateHandler);

厳密には、ゲーム内で制限時間を扱う必要はありません。ランキングゲームは制限時間に応じて自動的に・強制的に終了されるためです。 しかし現実には、「残り時間をゲーム画面に表示したい」といったことはよくあるでしょう。 残り時間が短くなったら結果発表演出を行いたい、ということも考えられます。 そのような場合に param.sessionParameter.totalTimeLimit を利用してください。

IMPORTANT

制限時間は「ゲーム起動から終了までの全ての時間」であることに注意してください。 これには「ゲームリソースのダウンロード時間」なども含まれます。 そのため、制限時間のギリギリで行う演出は、回線状況によって途切れてしまう可能性があります。 終了前に結果発表演出などを挟む場合は、念のため 制限時間の 10 秒程度前までに演出を完了させることを推奨します

INFO

制限時間は、game.json での指定の有無に関わらず param.sessionParameter から取得してください。 game.json での指定はあくまで "希望値の申告" であるためです。 将来的に、何らかの理由でニコニコ生放送が独自に制限時間を設定する場合があり得ます。

スコアの処理

テンプレートの main.js では、ランキングゲームの要件である スコアの代入 も行っています。

実行開始時、次のコードで最初にスコアを 0 点にセットしています。

javascript
g.game.vars.gameState = { score: 0 };
g.game.vars.gameState = { score: 0 };

テンプレートのゲームは、単に画面がクリックされたら 1 点加算するというものです。 これは次の記述で実現されています。

javascript
scene.onPointDownCapture.add(() => {
  // 制限時間以内であればタッチ1回ごとにSCOREに+1します
  if (time > 0) {
    g.game.vars.gameState.score++;
    scoreLabel.text = "SCORE: " + g.game.vars.gameState.score;
    scoreLabel.invalidate();
  }

  // ... その他、弾の発射や効果音再生処理
});
scene.onPointDownCapture.add(() => {
  // 制限時間以内であればタッチ1回ごとにSCOREに+1します
  if (time > 0) {
    g.game.vars.gameState.score++;
    scoreLabel.text = "SCORE: " + g.game.vars.gameState.score;
    scoreLabel.invalidate();
  }

  // ... その他、弾の発射や効果音再生処理
});

++score を 1 加算し、それをラベル scoreLabel で画面に表示しています。 実際のゲームでは「アイテムを取得した時」「敵を倒した時」「一定時間生き残った時」などお好みの条件でスコアを追加してください。

スコアは 0 以上の整数である必要があります。上限は今のところありませんが、現実的に表示が崩れてしまうので、10 万未満 (5 桁以内) を推奨します。

共通乱数生成器

ランキングゲームテンプレートは、プレイヤー間で共通の乱数生成器 (共通乱数生成器) を提供しています。 テンプレートの main.js 内、 main() の引数が param の時、共通乱数生成器は param.random で取得できます。

typescript
function main(param) {
  const random = param.random; // 共通乱数生成器
  const r = random.generate(); // プレイヤー間で共通の乱数値を生成
}
function main(param) {
  const random = param.random; // 共通乱数生成器
  const r = random.generate(); // プレイヤー間で共通の乱数値を生成
}

ランダム性を持たせつつ、全プレイヤーが等しい条件で競うようなゲームを作成する場合は、この共通乱数生成器を利用してください。 プレイヤーごとにランダムに異なる状態を作りたいゲームでは、 単に g.game.random (か g.game.localRandom) を利用してください。

INFO

共通乱数生成器は ランキングゲームテンプレートにしか存在しない ことに注意してください。

マルチプレイゲームの場合、エンジンが乱数シードを揃えるため g.game.random の結果がプレイヤー間で一致します。 逆にマルチプレイゲームにおいて「プレイヤー間で独立な乱数」を生成するには g.game.localRandom を使う必要があります。

これはランキングゲームが、放送者・各視聴者の手元で個別に実行されるシングルプレイのゲームであるためです。 最後に集計される得点以外は独立しているので、g.game.randomg.game.localRandom もプレイヤーごとにばらばらになります。

ランキングゲームマルチプレイゲーム
g.game.randomプレイヤー間で独立プレイヤー間で共通
g.game.localRandomプレイヤー間で独立プレイヤー間で独立
共通乱数生成器プレイヤー間で共通N/A