ピクチャ主体のゲーム作成ツール(基礎編4/6)(RPGツクールMZ)
サンプルゲームの簡易版 ハネを打ち返す
前回の記事ではサンプルゲームの簡易版として、ハネが飛んでくる処理を実装しました。今回は、ハネを打ち返す処理を実装します。
ハネを打ち返すためには、ベイ助とハネが衝突していることを判定しなければなりません。このことを当たり判定といいます。当たり判定用の便利機能は実装しているのですが、今回の例ではベイ助とハネの当たり判定ぐらいですので、そのままスクリプトで実装してしまいましょう。
当たり判定をするのは、ゲーム進行役です。そのために、まずはゲーム進行役がベイ助の座標を知ることができる状態にしなければなりません。
1ページ目のスクリプトを以下のように修正してください。
this.list.push(new 背景());
this.list.push(this.baysuke = new ベイ助());
今までnew ベイ助()としていたところを、this.baysuke = new ベイ助()に修正しました。以前の復習ですが、
this.【属性名】 = 【値】;
で、自身に新しい属性を定義して保持することができると記載しましたよね。それと同じ意味の書き方がここでも出来るのです(「;」は無いことに注意)。
「new ベイ助()」は、ベイ助のピクチャ実体です。これをなんとゲーム進行役の属性「baysuke」として保持してやろうという意味です。こうしておくことで、ゲーム進行役は「this.baysuke」と書くことで、ベイ助の座標やら何やらにアクセスできるようになります。
ゲーム進行役の2ページ目に次のスクリプトを追加します。
// 当たり判定
this.list.filter(obj => obj instanceof ハネ).forEach(obj => {
let x = this.baysuke.x + 78;
let y = this.baysuke.y - 88 + 80;
if (get_dist_sqr(x, y, obj.x, obj.y) < 30000) {
let angle = 135;
obj.vx = 20 * Math.cos(angle * Math.PI / 180);
obj.vy = -20 * Math.sin(angle * Math.PI / 180);
}
});
スクリプトの内容を詳しく見ていきます。
まず、以下はこういう文法だと思ってコピペして使ってください。これは、色々ある管理対象のうち、特定のイベントだけを対象に、かっこの中の処理を一つ一つしていくというものです。
this.list.filter(obj => obj instanceof 【イベント名】).forEach(obj => {
【処理】;
});
ゲーム進行役は「背景」「ベイ助」「ハネ」の3種類のイベントを持っていますが、「ハネ」だけを対象に一つずつ当たり判定をしたいので、このように書いています。図のイメージは以下です。図のように、ハネのイベントだけを取り出して、ハネ一つ一つに対して当たり判定していくイメージです。
この処理の中では、ハネ一つ分のイベントは「obj」と書いて参照することができます。obj.x, obj.yで、ハネのx座標、y座標です。また、「this.baysuke」でベイ助のイベントを参照できたのですから、this.baysuke.x, this.baysuke.yで、ベイ助のx座標、y座標です。ベイ助の座標とはベイ助の画像の中心(胸のあたり)になってしまいますから、羽子板の座標になるよう位置を調整しています。それが、
let x = this.baysuke.x + 78;
let y = this.baysuke.y - 88 + 80;
の部分です。ベイ助の位置から少しずれた位置x, yを羽子板の座標としています。それを、計算式を使って表現しています。
次のif文で、当たり判定をしています。x, y座標(羽子板)と、obj.x, obj.y座標(ハネ)が当たっているかどうかを判定します。
if (get_dist_sqr(x, y, obj.x, obj.y) < 【当たり判定の大きさ】) {
【当たったときの処理】;}
当たり判定の大きさの値は、小さくすると、ぴったり重なるぐらいまで当たってないと、当たったと判定しないというものになります。
当たった場合の処理は、以下のように書いています。ハネの角度を変更して、それに合わせて速度を変更している、というものです。この計算のことは割愛します。
let angle = 135;
obj.vx = 20 * Math.cos(angle * Math.PI / 180);
obj.vy = -20 * Math.sin(angle * Math.PI / 180);
これで当たり判定に基づいてハネが打ち返せるようになりました。テストプレイすると、羽子板とハネが当たったときにハネがはじかれる様子が確認できると思います。
ハネが羽子板に当たったら、ベイ助に羽子板を振るアニメーションをさせるようにしてみましょう。
まず、ベイ助の1ページ目にスクリプトを一行追加します。新たに「shot」という属性を追加します。
this.shot = false;
これは、打ち返していない状態を「false」、打ち返した状態を「true」という2通りの値になるようにする属性として扱います。falseはスイッチOFF、trueはスイッチON、と同じような意味を持ちます。
2ページ目には以下のスクリプトを追加します。打ち返す状態になったらアニメーションするというものです。
if (this.shot) {
if (this.t == 0) {
this.cellX = 1;
}
if (this.t == 4) {
this.cellX = 2;
}
if (this.t == 26) {
this.cellX = 1;
}
if (this.t == 30) {
this.cellX = 0;
this.shot = false;
}
}
if文の条件に「this.shot」とありますが、これは「this.shot == true」と同じ意味です。このように、true/falseの値の場合はif文の条件をそのように省略したような書き方ができます。逆に「this.shot == false」の場合は「!this.shot」のように、先頭に「!」を付ける書き方ができます。
その後、this.tの値に応じてthis.cellXを1, 2, 1, 0と順に変化させて、最後にthis.shot = falseとして処理終了していますね。this.cellXとは、分割画像の何枚目かを表すものです。
このベイ助の画像は初期化のときにthis.divX = 3と指定しているとおり、画像を横方向に3分割しているのです。this.cellXを0, 1, 2とすれば、それぞれ対応する画像が表示されることになります。1, 2, 1, 0と順に変化させれば、羽子板を振っているように見えますね。
このように、画像をアニメーションさせるには、分割を想定した大きな画像を用意すれば良いのですが、Android等の一部の端末では、画像の横サイズか縦サイズが4096を超えると表示されないことがあると報告されていますので、それ以下になるよう注意してください。
そして、ゲーム進行役でハネが当たった処理を実装した部分で、以下の2行を追加します。
// 当たり判定
this.list.filter(obj => obj instanceof ハネ).forEach(obj => {
let x = this.baysuke.x + 78;
let y = this.baysuke.y - 88 + 80;
if (get_dist_sqr(x, y, obj.x, obj.y) < 30000) {
this.baysuke.shot = true; // ★追加した部分
this.baysuke.t = 0; // ★追加した部分
let angle = 135;
obj.vx = 20 * Math.cos(angle * Math.PI / 180);
obj.vy = -20 * Math.sin(angle * Math.PI / 180);
}
});
ハネが当たったら、
this.baysuke.shot = true;
とすることでベイ助の羽子板アニメーションを開始させ、
this.baysuke.t = 0;
とすることで、アニメーションの時間を0からにすることができます。
テストプレイしてみると、羽子板に当たったときにちゃんとアニメーションしてくれるようになっていますね。
これでハネを打ち返せるようになりました。
次回は最後に制限時間と得点表示を作って、サンプルゲームの作成は完了とします。