ニコ生ゲームを作ろうと思ったらすぐ作ろう その5

第5回は画像を用意していきます。

見た目が変われば結構印象も変わるので、サンプルゲームの改造だとばれないといいですね。

■目次

改造内容】

  • 画像を用意する
  • 画像を差し替える
  • 画像を追加する
  • チュートリアルと終了の画像を表示する
  • 制限時間を設定する

 


 

【改造内容】画像を用意する

それではplayershotを差し替えていきます。

画像を用意しますが、背景が透過されたPNG画像がいいですね。
サイズはタイルと同じ90x90ピクセルでいいでしょう。

画像編集は慣れてる人も多いと思うので、特に詳しくもない私からわざわざ説明することもないのですが、photoshopgimpを使ったことがない人にgoogle図形描画を紹介しておきます。普通に絵を描ける人はどうぞ好きなように描いてください。


Googleのアカウントが必要ですが、ドライブの新規作成のところからGoogle図形描画を選択することができます。

  



自動でgoogleドライブに保存してくれて、透過PNGも出力しやすいです。

新規作成したら、まずページ設定を変えましょう。


  

カスタムピクセルを選んで数字を入力します。

  


適当に図形を配置します。ホイップクリームを出すやつのゼリー版のイメージで・・・

  


描いたらダウンロードからPNGで保存します。
ダウンロード?と思わなくもないですが、クラウド保存ではなくてローカルにダウンロードする、ということなんでしょう。

  



飛んでいくゼリーも曲線を使って書きます。線を太くすると曲線の汚さをごまかせます。
ちなみに光沢部分は極限まで薄くしたアーチの線を太くしたものです。

  


実際に書いている現場がこちらです。
画像ファイルを実際に使う場合は こちら。後で使う画像もあります。

【改造内容】画像を差し替える
それではダウンロードしたファイルの名前を「player」「shot」にします。
そして「kaizou」の「image」フォルダの中に入れて、差し替えます。

それではakashic-sandboxのページを更新しましょう。


  

はい。うまく行っていませんね。
playerの画像が切れてしまっていて、shotは映りもしません。

これは、画像のサイズが変わったことが反映されていないためです。
画像のサイズを更新するためには、コマンドプロンプトで以下の呪文を唱えます。
一度 Ctrl+C でakashic-sandboxを終了してから入力しましょう。

  akashic scan asset

  


再度akashic-sandboxを起動して更新しましょう。


  


ちゃんと表示されました。
ついでに、左上の残弾表示がかぶるのでちょっと左に寄せておきます。

画像のサイズが変わったときは、akashic scan assetが必要ですが、逆にサイズが変わらない微修正であればやる必要はありません



【改造内容】画像を追加する

タイルの方も画像に変えていこうと思います。

タイルは86x86にしてしまったので、図形描画でサイズ変更してから保存します。

  


画像に「tile」の名前をつけて、imageフォルダに入れ、akashic scan assetを実行します。


var shotのところの真似をして下のようにタイルの書き方を変えます。

var tiless = ;
for (var j = 0; j < 12; j++) {
  var tiles =
;
  for (var i = 0; i < 7; i++) {
    var tile = new g.Sprite({
      scene: scene, src: scene.assets["tile"], parent: scene,
      x: g.game.width - 100 - 90 * j, y: 90 * i + 47,
      width: 86, height: 86, opacity: 1, tag: {row: i, column: j,},
    });
    tiles[i] = tile;
  }
  tiless[j] = tiles;
}

これで起動してみると、
  
このようなエラーが出るはずです。

これは新しく追加した画像がプログラム上で登録されていないためです。
登録する場所はゲームの準備のところにあります。
scene.onLoaded.add(function () {の更に上です。


var scene = new g.Scene({
  game: g.game,
  // このシーンで利用するアセットのIDを列挙し、シーンに通知します
  assetIds: ["player", "shot", "se"]
});
var time = 60; // 制限時間
if (param.sessionParameter.totalTimeLimit) {
  time = param.sessionParameter.totalTimeLimit; // セッションパラメータで制限時間が指定されたらその値を使用します
}
// 市場コンテンツのランキングモードでは、g.game.vars.gameState.score の値をスコアとして扱います
g.game.vars.gameState = { score: 0 };

scene.onLoaded.add(function () {


あとから追加しやすいように改行を入れて、"tile"を入れます。

assetIds: [
  "player",
  "shot",
  "tile",
  "se"
]


  

このように表示されるはずです。


【改造内容】チュートリアルと終了の画像を追加する
チュートリアル画像はサイズを1280x720にして、図形描画上で位置を調整してしまいます。

  

この画像を開始7秒間だけ表示して、その間は操作も制限します。
残り時間が53秒より大きければ表示して、それ以外は透明にします。

var tutorial = new g.Sprite({
  scene: scene,
  src: scene.assets["tutorial"], parent: scene,
});
scene.onUpdate.add(function () {
  if (time > 53) {
    tutorial.opacity = 1;
  } else {
    tutorial.opacity = 0;
  }
  tutorial.modified();
});

このvar tutorialは追加する場所を気をつけないと、チュートリアル画像の上にタイル画像が重なってしまいます。

プログラムは記載してある順に表示するので、チュートリアルはできる限り下の方の、scene.onPointDownCapture.add(function () {の前に追加しましょう。

ゲームへの画像の登録と、akashic scan asset ももちろんやります。


操作の制限はすでに bullet > 0 という条件が追加されているところに条件を追加します。

// 画面をタッチしたとき、SEを鳴らします
scene.onPointDownCapture.add(function () {

if (bullet > 0 && time < 53) {
bullet = bullet - 1;


&&は条件の追加で、「bullet > 0」かつ「time < 53」という意味になります。


終了も同じように追加します。場所も同じでいいでしょう。
ついでにブロマガの宣伝を載せます。
終了と同時にスコアも大きく表示したいところですが、今回は省略します。

ここで黒い文字を表示させようとしていますが、背景が真っ黒の場合黒い文字は全く見えなくなってしまいます。周りを白で縁取りするなどして、見やすくするのが良いでしょう。  

残念ながらGoogle図形描画では縁取りは難しいのでGIMPや他の方法を探してください。
[22/1/27追記]Googleスライドのワードアートで縁取りできることがわかりました。
たまに変更しても見た目が更新しないときがありますが、背景を透明にして複数のワードアートを重ねれば多重縁取りもできます。
  

var finish = new g.Sprite({
  scene: scene,
  src: scene.assets["finish"], parent: scene,
});
scene.update.add(function () {
  if (time < 0) {
    finish.opacity = 1;
  } else {
    finish.opacity = 0;
  }
  finish.modified();
});



【改造内容】制限時間を設定する

さて、このへんでおかしなことが起きているかもしれません。
ゲームの準備のところでvar time = 60; // 制限時間としているのに、
akashic-sandboxは85秒から始まっているかもしれません。

これはakashix-sandboxの設定によって変わり、sandboxの右上のギアボタンを押して、「Niconico」のタブ「セッションパラメータを送る」にチェックが入っていて、「game.jsonの~」のチェックも入っていると起きます。逆にそうでないならば、60秒から始まっているはずです。

  



唐突に複雑な設定について話し始めましたが、重要なことなので説明をしていきます。
そもそも、ランキング形式のニコ生ゲームの制限時間には2種類あります。

  • ゲームをプレイできなくなるまでの時間 (60秒)
  • ゲームが終了してランキング表示が始まるまでの時間 (70秒)

終了待ちは自分のゲームの終了が表示され、ランキングが始まるのを待っている状態です。
この終了待ちの状態が用意されていないゲームは、有名ゲームでも割とよくあるのですが若干問題があります。

生放送の場合、プレイヤーによってロードにかかる時間が異なり、開始するタイミングが数秒ずれます。

 

この場合、たとえゲームの時間が残っていたとしても強制的にランキング表示に移行します。

時間が残っているのにゲームが終わってしまった経験はないでしょうか。これは競技性の面でも少し不公平になります。

また、ゲーム終了時に得点を計算するプログラムにしている場合、得点計算をせずに終了して0点になってしまうこともあります。得点は常に更新するようにしたほうがいいですね。

これまでの経験から10秒あれば一部の人を除いてほぼ、ロード時間の違いを吸収できます。
ランキング表示が始まるまでの時間を70秒に設定していきます。


main.jsのなかで制限時間はどのように設定されているかというと、60に設定したあとに、param.sessionParameter.totalTimeLimitに設定し直されています。

var time = 60; // 制限時間
if (param.sessionParameter.totalTimeLimit) {
  time = param.sessionParameter.totalTimeLimit; // セッションパラメータで制限時間が指定されたらその値を使用します
}

このparam.sessionParameter.totalTimeLimitというのが、ランキング表示が始まるまでの時間なのですが、このままだと60秒と70秒というように分けることができません。var time = 60; // 制限時間のみ残してあとは消します。


そして、param.sessionParameter.totalTimeLimitはどこで設定するのかというと、これまで編集してきたmain.jsではなく、kaizouフォルダに有るgame.jsonです。

どこかに85という数字が書いてるかというと・・・
どこにもありません。85はデフォルトの数字であって、書き換えるというやり方ではだめなので、game.jsonの一番下に次のように記載を追加してください。

"moduleMainScripts": {},

"environment": {

"sandbox-runtime": "3",
"niconico": {

"supportedModes": [

"ranking"

],

"preferredSessionParameters": {

"totalTimeLimit": 70

}

}

}

}


途中の カンマ ,  も忘れないようにしてください。
あと、このgame.jsonの方は全角のスペースはダメみたいなので気をつけてください。
game.jsonを保存してsandboxを更新してみましょう。

  

「game.jsonのpreferredSessionParameters~」の右端が70秒になっていればOKです。
その下の「時間経過後にゲームを停止」のチェックも入れておくと、実際にどのタイミングでランキング表示に移行するかわかりやすくなります。


また、制限時間がどれくらいがいいかというと、60~70秒が一般的です。短期決戦のゲームだと40~50秒もありです。

ゆったりしたゲームだと90秒ぐらいでもありですが、単調なゲームで90秒あると結構不評が出てきます。

もちろん、じっくりと攻略する要素がある場合は2分以上でも大丈夫です。ランキングモードの場合、確か180秒が最大だったと思います。





終了

はい5回はここまで。

見た目を変えると言いながら、制限時間の話に脱線しました。

最終コードはこちら
game.jsonはこちら
画像ファイルは こちら

次はフォントと音の追加をやります。