RPGツクールと数学のブログ

RPGツクールと数学についてのブログです。

ピクチャ主体のゲーム作成ツール(基礎編5/6)(RPGツクールMZ)

サンプルゲームの簡易版を完成させる

前回までの記事で、ハネを打ち返すサンプルゲームを作成できました。今回はゲームの要素を諸々追加して、サンプルゲームの作成を終えようかと思います。

ハネの発生位置や速度をランダムにする

ハネが現状、発生位置も速度も固定なので、同じところで構えていれば、ずっと打ち続けてしまい、ゲームになりません。それらがランダムに変わるようにしてみましょう。ランダムな値は、次のようにして生成できます。

rnd(【最小値】, 【最大値】)

生成されるのは整数の値です。例えば、rnd(4, 7)とすると、4, 5, 6, 7のどれかの値がランダムで選ばれます。

まずはハネの位置yを、固定値からrnd(0, 300)に置き換えましょう。ゲーム進行役2ページの以下スクリプトを修正します。

if (this.t % 60 == 0) {

    this.list.push(new ハネ(0, rnd(0, 300)));

}

これで出現位置の高さがランダムに変わるようになりました。でもまだ速度が同一なので、イマイチです。次に、ハネの速度もランダムで変えられるようにしましょう。

ハネの1ページ目をこのように変えます。まず、注釈に引数speedを追加します。

(x, y, speed)

次に、スクリプトで速度の計算をするところから、let speedを削除します。

// 角度

let angle = 60;

 

// 速度

this.vx = speed * Math.cos(angle * Math.PI / 180);

this.vy = -speed * Math.sin(angle * Math.PI / 180);

今までは5固定としていましたが、初期化の引数にしてあげることで、ハネを生成するときの初期値として与えられるようになりました。*1

ゲーム進行役2ページのスクリプトを、次のようにしましょう。さっき追加したspeedの部分として、rnd(3, 10)を追加しました。

if (this.t % 60 == 0) {

    this.list.push(new ハネ(0, rnd(0, 300), rnd(3, 10)));

}

テストプレイしてみると、いろんなところにハネが落ちるようになりました。

制限時間を追加する

制限時間を追加して、制限時間を過ぎたらハネが出現しないようにしてみましょう。新しく「制限時間」というイベントを配置して、ゲーム進行役に集約させます。

制限時間の1ページ目はこうします。注釈は

(s)

として、設定する制限時間を「秒」の単位で与えられるようにします。これをsとします。スクリプトは、以下です。

this.s = s; // 秒

this.f = 60; // フレーム

 

// 変数11番の値を表示するような文字列ピクチャを生成

createStringPicture.call(this, "\\V[11]", 1, 408, 60, 100, 100, 72, 255, [0, 0, 0, 0], 8, global.mainLayer);

 

// 変数11番に「秒」の値を代入

$gameVariables.setValue(11, this.s);

ここで、画面に制限時間の値を表示するのですが、文字列は文字列ピクチャとして生成することになります。文字列の内容を変動できるようにするためには、RPGツクールMZで標準サポートされている「変数」を使用する必要があります。ここでは、変数11番を制限時間(秒)として扱います。

// 変数11番の値を表示するような文字列ピクチャを生成

createStringPicture.call(this, "\\V[11]", 1, 408, 60, 100, 100, 72, 255, [0, 0, 0, 0], 8, global.mainLayer);

これは次のような文法です。

createStringPicture.call(this, 【表示する文字列】, 【origin】, 【x】, 【y】, 【scaleX】, 【scaleY】, 【フォントサイズ】, 【opacity】, [【赤】, 【緑】, 【青】, 【グレー】], 【太さ】, 【pictureManager】);

表示する文字列の部分は、例えば「あいうえお」だったら、"あいうえお" と書きます。この場合は変数11番を表示するので"\V[11]"と書きたいところですが、スクリプトの中では「\」のことを「\\」と書かなければならない決まりがあるので、"\\V[11]" と書きます。

そして、変数11番に、設定した秒の値を代入します。ただしイベント命令は使えずスクリプトしか使えないので、スクリプト

// 変数11番に「秒」の値を代入

$gameVariables.setValue(11, this.s);

と書きます。これは、変数11番にthis.sを代入するという意味です。

制限時間の2ページ目は以下です。スクリプトは以下です。

this.f--;

if (this.f <= 0) {

    this.f = 60;

    this.s--;

    $gameVariables.setValue(11, this.s);

}

if (this.s <= 0) {

    this.cleared = true;

}

「this.f--;」とは、「this.f -= 1;」と同じ意味です。this.fの値を1減算するという意味です。逆に1加算するときは「this.f++;」と書きます。

60フレームで1秒なことを利用して、まずthis.fを1ずつ減らしていき、0以下になったら、this.sを1減らします(ちょうど一秒経過したという意味)。そしてthis.fを60フレームに戻して繰り返し、となります。this.fは定義済みですが、「this.f = 60;」と書けば、this.fの値を60に戻すことができます。これを代入といいます。this.sが減ったら表示文字列も更新されるので、変数11番にthis.sを代入しています。

最後、this.sが0以下になったらタイマーストップですので、「this.cleared = true;」として自身を消滅させます。

あとはゲーム進行役に制限時間イベントを持たせます。1ページ目のスクリプトを次のようにします。30秒の制限時間という意味です。

this.list.push(new 背景());

this.list.push(this.baysuke = new ベイ助());

this.list.push(this.limitTime = new 制限時間(30));

制限時間は2ページ目でも使うので、this.limitTimeとして定義しておきました。2ページ目は以下です。

if (this.t % 60 == 0 && !this.limitTime.cleared) {

    this.list.push(new ハネ(0, rnd(0, 300), rnd(3, 10)));

}

条件に、「!this.limitTime.cleared」を追加しました。先頭に!が付いているので、これは「this.limitTime.cleared == false」と同じ意味です。つまり、「制限時間が消滅していなければ」という意味です。制限時間が消滅していなければハネを生成します。

これで設定完了です。テストプレイしてみると、画面上部に制限時間が追加されています。0になると、ハネが出てこなくなります。

得点表示を追加する

制限時間と似た要領で、得点表示を追加します。得点表示イベントを同様に、ゲーム進行役へ集約させます。

得点表示イベントの中身は、制限時間よりはシンプルです。1ページ目は以下です。注釈は()です。スクリプトは以下です。

createStringPicture.call(this, "\\V[13]点", 0, 20, 20, 100, 100, 48, 255, [0, 0, 0, 0], 8, global.mainLayer);

 

// スコア初期値

global.score = 0;

今度は得点を変数13番に設定して表示するようにしてみます。後にニコ生ゲーム化もしますが、ニコ生ゲームの得点は変数13番と決めていますので、最終的な得点は変数13番に代入されるようにしてください。

また、得点値は「this.score」ではなく「global.score」として定義していることに注意です。「this.score」とすると得点表示イベントが持つスコアという意味になりますが、スコアはすべてのイベントが使ったり参照したりできるので、得点表示だけのものではなく、みんなのものとして共有させてあげる必要があります。そこで、「global.score」と書くと、これはすべてのイベントが使えるようになります。これをグローバル変数といいます。

2ページ目は以下です。スクリプトは以下です。

// 得点表示の値を実際の得点変数に反映する

$gameVariables.setValue(13, global.score);

これはそのまま、得点を変数13番に代入しているだけですね。ニコ生ゲームでも得点はglobal.scoreのものが使われるのではなく、変数13番の値が使われるので、表示用という目的以外に、得点を反映させるためにも、このスクリプトは必要になります。

あとはゲーム進行役に得点表示を持たせて、さらにハネを打ったときに得点が増えるようにしておけば完成です。

1ページ目は以下です。

this.list.push(new 背景());

this.list.push(this.baysuke = new ベイ助());

this.list.push(this.limitTime = new 制限時間(30));

this.list.push(new 得点表示());

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);

        global.score += 10; // ★追加

    }

});

ハネを打ったときに得点が10加算されるようにしました。

テストプレイすると、以下のように得点が画面表示され、ハネを打つたびに得点が10加算されていると思います。

BGM/効果音を追加する

最後に、BGMと効果音を追加しましょう。ただ、サンプルでは音楽素材を入れていないので、各自何らかの素材を用意してください。ここでは設定方法だけ説明します。

まず、ゲーム開始時にBGMを鳴らします。ゲーム進行役1ページ目に追加します。

AudioManager.playBgm({"name":"hiyokonokakekko","volume":100,"pitch":100,"pan":0});

これは、BGMを再生するコードです。文法は以下です。

AudioManager.playBgm({"name":【ファイル名】,"volume":【音量】,"pitch":【ピッチ】,"pan":【位相】});

ファイル名は "hiyokonokakekko" のように、""で囲んでください。

次に、ハネを打ったときに効果音を鳴らします。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) {

        AudioManager.playSe({"name":"Blow1","volume":100,"pitch":100,"pan":0}); // ★追加した

        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);

        global.score += 10;

    }

});

効果音再生の文法は以下です。BGMとほぼ同じです。

AudioManager.playSe({"name":【ファイル名】,"volume":【音量】,"pitch":【ピッチ】,"pan":【位相】});

これでテストプレイしてみると、BGMや効果音が鳴るようになったと思います。

これで簡易版サンプルゲームが完成しました。なんとかゲームっぽくはなったのではないでしょうか。最低限、この記事までに説明してきた内容を使っていけば、色々ゲームが作れると思います。

次回の記事では、ニコ生ゲーム化する方法を説明して、基礎編を終了しようと思います。

 

次の記事へ

前の記事へ

TOPに戻る

*1:今回は常にランダムな値とするので別に引数化する必要はないのですが、このように引数化しておくと柔軟さが出るので便利です。