STEP02.高さの表示を自動化しよう

ミニゲーム作成チュートリアルの2回目です。

前回は高さを取得して表示まで行いました。 毎回チャットコマンドを入力するのは面倒なので、この表示を自動化しましょう。

Tickイベントを使って、表示コマンドをティックごとに自動で実行する

TickEventはティックごとに自動で実行されるイベントです。 1ティック、つまり1秒間に20回、目的のプログラムを実行します。 この機能を使い、目的のコマンドを定期的に実行することで、表示を自動化します。

コマンドを使うには、どの次元 (dimension)で使っているのか、あるいはどのプレイヤー (player)が使ってるのかをはっきりさせる必要があります。

例えば/tpを使うときに、オーバーワールドで使った場合と、ネザーで使った場合では移動する場所が違いますね。 移動先の座標の数字は同じでも、オーバーワールドとネザーでは別のワールドだからです。

また、誰が使うのかをはっきりさせれば、そのプレイヤーがどの次元にいるのかを判断できます。 そのため、コマンドを使うには「次元」か「プレイヤー」の情報が必要になります。

今回使用するTickEventで取得できる内容だけではコマンドを実行できないので、オーバーワールドの次元情報を事前に取得しておきます。 この情報からrunCommand()を実行することにします。

前回書いたコードは削除して、次の内容で上書きしてください。

scripts/main.ts
import * as mc from 'mojang-minecraft';

// 最初にオーバーワールドの次元情報を取得しておく
// 今回の使い方では毎回取得する必要がないので、グローバル変数に入れる
const overworld = mc.world.getDimension('overworld');

mc.world.events.tick.subscribe((event) => {
  // 次元情報からコマンドを実行
  overworld.runCommand(`say ${event.currentTick}`)
});

ワールドにいる全プレイヤーを取得する

次にプレイヤー情報を取得する処理を加えます。

開発時には自分ひとりしかいませんが、マルチプレイのことも考えて、プレイヤー全員に対して処理を行うようにしておきます。

プレイヤーの情報は、次元情報から取得できます。 上で取得したオーバーワールドの次元情報を今回も使用します。

まずはプレイヤー情報を取得できていることを確かめるために、名前だけを表示してみましょう。 すべての処理を一気に描くのではなく、ひとつずつ進めていきます。

scripts/main.ts
import * as mc from 'mojang-minecraft';

const overworld = mc.world.getDimension('overworld');

mc.world.events.tick.subscribe((event) => {
  // オーバーワールドにいるプレイヤーを取得する
  const players = overworld.getPlayers();
  // プレイヤーごとに繰り返し
  for (const player of players) {
    // そのプレイヤーの名前を表示
    overworld.runCommand(`say ${player.nameTag}`)
  }
});

プレイヤーの取得は変数に入れずに、直接for文の中に書くこともできます。 上では、途中の処理をわかりやすくするため、分けて書きましたが、この場合は直接for文の中に書いても良いでしょう。

for (const player of overworld.getPlayers()) {
  // ...
}

高さをアクションバーに表示する

オーバーワールドにいるプレイヤー全員分の名前が表示されたら成功です。 しかし、本当に表示したいのは、それぞれのプレイヤーのいる「高さ」でした。 次はこれを表示するようにしましょう。

高さを取得する処理は前回と同じです。 今回は各プレイヤーが自分の情報だけを知れれば良いので、共通のチャット画面ではなく、そのプレイヤーのアクションバーに表示させます。 アクションバーに表示させるのは/titleコマンドです。

また、今回のrunCommand()メソッドはプレイヤーから使用します。 この場合、コマンド文の@sは、このメソッドを実行したプレイヤーのことになります。 次元情報からrunCommand()を使用した場合、@sは無効になるので注意してください。

scripts/main.ts
import * as mc from 'mojang-minecraft';

const overworld = mc.world.getDimension('overworld');

mc.world.events.tick.subscribe((event) => {
  for (const player of overworld.getPlayers()) {
    const height = Math.floor(player.location.y);
    const text = `現在の高さは ${height} です。`;
    // titleコマンドでアクションバーに表示する
    player.runCommand(`title @s actionbar ${text}`);
  }
});

実行回数を制限する

上の方法では1秒間に20回、表示コマンドが実行されます。 今回の目的では、ここまで何度も書き換える必要はないので、回数を制限しましょう。

event.currentTickで現在の総ティック数を取得できるので、これを使用します。

また、%演算子を使うと、割った余りを求めることができます。 この場合の記号に元の百分率(パーセント)の意味はありません。

下の例の場合はティック数を10で割った余りが0のときにだけ実行できます。 つまり、ティック数が10の倍数のときだけ、条件式の判定が真になり、目的のコマンドを実行します。

scripts/main.ts
import * as mc from 'mojang-minecraft';

const overworld = mc.world.getDimension('overworld');

mc.world.events.tick.subscribe((event) => {
  // 10ティック(0.5秒)ごとに1回実行する
  if (event.currentTick % 10 === 0) {
    for (const player of overworld.getPlayers()) {
      const height = Math.floor(player.location.y);
      const text = `現在の高さは ${height} です。`;
      // titleコマンドでアクションバーに表示する
      player.runCommand(`title @s actionbar ${text}`);
    }
  }
});

この例では10ティックごとに目的のコマンドを実行しています。 つまり、それぞれのプレイヤーの高さ情報を0.5秒ごとに更新しています。

もし更新が遅いと感じたら、数字を調整してみましょう。 更新が多すぎると、ゲームが重くなってしまうので、処理内容に合わせてうまく制限してください。 (毎ティック実行した方が良い場合もあります)

コードを整理する

最後にコードの整理を行います。

ここまでのコード自体は間違っていません。 しかし、このままひとつの関数に処理を加え続けると、コードが読みづらくなっていきます。 これを避けるために、処理のまとまりを関数に置き換えて分離します。

理想的な関数の書き方はありますが、まずは意味のまとまりで切り出す、というところから始めてください。

次の場合は、アクションバーに表示する処理を切り出しています。

scripts/main.ts
import * as mc from 'mojang-minecraft';

const overworld = mc.world.getDimension('overworld');

mc.world.events.tick.subscribe((event) => {
  if (event.currentTick % 10 === 0) {
    for (const player of overworld.getPlayers()) {
      // 関数を呼び出し
      showActionBar(player);
    }
  }
});

// 自分の高さ(y座標)をアクションバーに表示する
function showActionBar(player: mc.Player) {
  const height = Math.floor(player.location.y);
  const text = `現在の高さは ${height} です。`;
  player.runCommand(`title @s actionbar ${text}`);
}

このように関数に切り出すことで、コードが読みやすくなります。 この場合は「プレイヤーごとにアクションバーを表示させる」という意図がはっきりします。

次のページへ
STEP03. 高さを変数に保存しよう