投稿記事

ティラノスクリプトの記事 (5)

大寒ソフト 2022/08/10 12:00

【Tyranoscript】Pixi.jsを呼び出す

はじめに

Tyranoscriptでゲームを作っているけど、一部複雑なミニゲームをPixi.jsで作ってはめ込みたいという場合の導入方法。

Pixi.js本体

Pixi.jsの本体をDLしてきて「data/others/js/」あたりに置く。

GitHubには複数のjsファイルがあるけど、コードの中身を見る必要がなければProduction Buildのpixi.min.jsで良い。

シナリオファイルの設定

シナリオファイル上では、まずloadjsタグでjsファイルを読み込んで、htmlタグで描画領域を確保する。その直後に描画開始の関数initGame()(※後述)を呼び出しておく。
勝ち負けのラベル直後のcmタグはhtmlタグで描画したものをクリアするためのもの。

@loadjs storage="js/pixi.min.js"
@loadjs storage="js/mini_game.js"

[html]
  <div id="pixiApp"></div>
  <script>
    initGame();
  </script>
[endhtml]
[s]

*win
; 勝った後の処理
[cm]
勝ち[p]
@jump target="*common"

*lose
; 負けた後の処理
[cm]
負け[p]
@jump target="*common"

*common
; 後続処理

jsファイルの記述

Pixi.jsの後に読み込んでいるmini_game.jsの中身はこんな感じ。

{
  let app;

  let player;
  let enemy;

  let elapsed = 0;

  // 初期化
  function initGame() {
    app = new PIXI.Application({ width: 1280, height: 720 });
    app.ticker.maxFPS = 60;
    app.stage.interactive = true;
    document.getElementById("pixiApp").appendChild(app.view);

    // 画像ファイルの読み込み
    app.loader.add("player", "data/image/game/player.png");
    app.loader.add("enemy", "data/image/game/enemy.png");
    app.loader.load(setup);
  }

  // すべての画像ファイルが読み込まれたら
  function setup(loader, resources) {
    player = new PIXI.Sprite(resources.player.texture);
    player.anchor.set(0.5, 0.5);
    player.x = 200;
    player.y = 300;
    app.stage.addChild(player);

    enemy = new PIXI.Sprite(resources.enemy.texture);
    enemy.anchor.set(0.5, 0.5);
    enemy.x = 1280 - 200;
    enemy.y = 300;
    app.stage.addChild(enemy);

    // ゲームループを開始する
    app.ticker.add(gameLoop);
  }

  // ゲームループ
  // 引数のdeltaは60fps前提で前回のループから何フレーム経過したかを渡してくれる。
  // たとえば60fpsで回せていれば1が入って来るし、30fpsに落ちると2が入って来る。
  // 小数で来る場合もあるのでカウンター的に使う場合は注意が必要。
  function gameLoop(delta) {
    elapsed += delta;

    updatePlayer(delta);

    updateEnemy(delta);
    
    // 1秒後くらいに勝って終了させる
    if (elapsed >= 60) {
      endGame(true);
    }
  }

  function updatePlayer(delta) {
    // プレイヤーの更新処理
    
    // 右に進む
    player.x += 1;
  }

  function updateEnemy(delta) {
    // 敵の更新処理
    
    // 左に進む
    enemy.x -= 1;
  }

  // Pixi.jsの破棄処理
  function destroy() {
    app.destroy();
    app = null;

    player.destroy(true);
    player = null;

    enemy.destroy(true);
    enemy = null;
  }

  // ゲームを終了する
  // 引数で勝敗を渡してシナリオのそれぞれのラベルへジャンプする。
  function endGame(isWin) {
    destroy();

    const target = isWin ? "win" : "lose";
    tyrano.plugin.kag.stat.is_stop = false;  // シナリオが止まっているので動かす。ちゃんとした方法があるかも
    tyrano.plugin.kag.ftag.startTag("jump", {
      storage: "呼び出し元のシナリオファイル.ks",
      target: target,
    });
  }

  // 外部から初期化関数を呼べるようにする。
  window.initGame = initGame;
}

動作確認

上記を合わせると以下のような感じになる。
あとはプレイヤーと敵の動きとか、衝突判定とかをゴリゴリ足していく感じ。

あ、ゲーム中に抜けられるとたぶんバグるので、メニューボタンやキーコンフィグは切っておいたほうが良いです。

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

大寒ソフト 2022/08/08 12:00

【Tyranoscript】出力したexeの詳細情報を編集する

TyranoStudioで出力したexeファイルのプロパティから詳細情報を見ると以下のようになっている。

著作権表示がGitHubになっているのでなんだか気持ちが悪い。

調べてみると、この辺の情報を編集するElectronの公式ツールがあった。

https://github.com/electron/rcedit

Releasesから「rcedit-x64.exe」を落としてきて、パスの通っているところに置く。
変更したいexeのあるフォルダーをコマンドプロンプトで開いて、rceditを実行する。

rcedit-x64 "PrincessKnightFine.exe" --set-version-string "LegalCopyright" "© 2022 大寒ソフト"

変更できた。

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

大寒ソフト 2022/08/07 12:00

【Tyranoscript】タイトルに戻る際のちらつきを消す

メニューのタイトルに戻るボタンを押すと、htmlがリロードされて最初から表示される。
このとき一瞬だけど背景が白くなって画面がちらつくように見える。

おそらくElectronの背景が露出していると思われるので、背景色を変更してみる。
対象ファイルは以下。

TyranoStudio_win_std_v110d\resources\app\src\system\main.js

mainWindow = new BrowserWindow({
    "width": width, 
    "height": height,
    "resizable":resize,
    "useContentSize": true,
    "show":false,
    webPreferences: {
      nodeIntegration: true
    },
    backgroundColor: "#000000"  // この設定を追加
});

ちらつきが消えた。

ただ不思議なんだけど、backgroundColorを何色にしても黒にしかならない。

※検証環境 TyranoStudio ver0.1.1 standard

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

大寒ソフト 2022/08/06 14:49

【Tyranoscript】最初に考慮しておくこと

今回の反省とこれから制作を始める方への転ばぬ先の杖。

時間の指定は変数で行う

waitやchara_showなどのtime指定は数字を直打ちではなく、sfなどの変数経由で行った方がよい。
その方が全体の統一ができるし、あとでタイミングを微調整をする際にかなり楽になる。

waitやanimなどをラップしておく

waitやanim、chara_moveなど時間指定を伴うタグは自前のマクロでラップしておいた方が良い。
なぜかというと、スキップをした際にテキストは高速で流れるのに、演出がそのままということが発生してしまうから。
以下のようにスキップ中はtimeを短くするか、そもそもタグの呼び出し自体をしないようなマクロにしておくと、スキップ中のストレスが減る。

[macro name="wait2"]
  [iscript]
    tf.is_skip = TG.stat.is_skip == true;
    if (tf.is_skip) {
      mp.time = Math.min(100, Number(mp.time));
    }
  [endscript]
  [wait *]
[endmacro]

現在実行中のシナリオファイル名を保持しておく

あるマクロ内で現在実行中のシナリオファイルに応じて処理を変える必要が生じた。
パラメーターでファイル名を渡しても良いのだけど、量が多いのでできれば手間は省きたい。
検索してみると、以下の方法でファイル名を取得できるという情報を発見。

var storage = tyrano.plugin.kag.stat.stack.macro[0].storage;

しばらくは問題なく動いていたのだが、何かの拍子にmacro[0]が取得できなくなってjsの処理が止まることがあった。
仕方ないので、各ファイルの冒頭でf変数にファイル名を保持するようにした。
(シナリオファイルの途中にジャンプしまくるような作りだとこの方法は無理です。)

シナリオのテンプレの作り方

以下のようなシナリオのテンプレを作って、それを元に開発をしていた。

------------------
■初期化処理
------------------
会話
------------------
■背景切り替え
------------------
イベント
------------------
■終了処理
------------------

■の部分はほとんど共通なのだが、このファイルをコピペ増殖してシナリオを量産してしまい、後になって■の部分の修正が発生したときに非常に面倒だった。
共通になる部分はマクロかサブルーチンにまとめるべきだろう。

Tyranoscript本体への変更

割とゴリゴリ変更を入れてしまったが、そうすると本体の重要なバグフィックス等があってもアップデートができなくなるので、別のjsファイルを作って修正したい関数を上書きするのが良いのだと思う。(最近のバージョンはパフォーマンスが上がっているらしいぜ!…とほほ)

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

大寒ソフト 2022/08/05 22:21

【Tyranoscript】大量のglinkを一気に表示したい

Tyranoscriptでglinkを大量に生成するケース(「姫騎士フィーネの受難」だと街の移動先選択とか)があるとする。

以下のような感じでjumpタグで無理くりループを作って生成すると、結構バラバラ出て来てしまう。

*loop

[iscript]
tf.x = 155 * Math.floor(tf.num / 10);
tf.y = 62 * (tf.num % 10);
[endscript]

[glink  color="blue"  storage="scene1.ks"  size="28"  x="&tf.x"  width="40"  y="&tf.y" height="30"  text="&tf.num"  target="*selectinterest"  ]

[if exp="tf.num < 79"]
@eval exp="tf.num++"
@jump target="*loop"
[endif]

[s]

Tyranoscriptのソースにconsole.log()でタイムスタンプを仕込んで何に時間を食っているのか見てみると、「iscript」や「eval」の実行に10ms弱かかっている。
内部的にjsのeval()を実行していると思うので、まぁそりゃそうかという感じだ。
なのでこいつを取っ払う。

*loop

[glink  color="blue"  storage="scene1.ks"  size="28"  x="&(155 * Math.floor(tf.num / 10))"  width="40"  y="&(62 * (tf.num % 10))" height="30"  text="&tf.num"  target="*selectinterest"  ]

[if exp="tf.num++ < 79"]
@jump target="*loop"
[endif]

[s]

前よりは早くなったが、順番に出てくる感じは消えない。
これは「iscript」や「eval」以外のタグもわずかに時間がかかっているためだろう。
とういうことは、全部のボタンを一気に出したければ、タグを一つにするしかない。

Tyranoscriptのタグをjsから呼び出せる「tyrano.plugin.kag.ftag.startTag」を使って以下のように「iscript」だけに書き換える。

[iscript]
for (let i = 0; i < 80; i++) {
  let x = 155 * Math.floor(i / 10);
  let y = 62 * (i % 10);

  tyrano.plugin.kag.ftag.startTag("glink",
  {
    color: "blue",
    storage: "scene1.ks",
    size: 28,
    x: x,
    width: 40,
    y: y,
    height: 30,
    text: i,
    target: "*selectinterest"
  }
  );
}
[endscript]
[s]

おぉ、できた。
一度に多くの処理を行いたい場合は、無理にタグで頑張らずjsに寄せてしまった方が良さそうだ。
(ゲームの方は次回のアップデートで直そう…)

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

記事のタグから探す

月別アーカイブ

限定特典から探す

記事を検索