スクラッチに挑戦している皆さん、どうも!スクラッチコーチです。
準備
このレッスンは前回「横スクロールを制覇せよ!」の続きです!今回はジャンプを作っていきます。
スクラッチでマリオのゲームを作る特大レッスン#01 横スクロールを制覇せよ
スクラッチでマリオのゲームを作る方法が分かります!今回は横スクロール!「スクラッチでマリオ」シリーズの最終ゴールをチェック
最後までレッスンを進めるとこのようなマリオゲームの土台となるプロジェクトが完成する予定です。
「レッスン#02 ジャンプ」のゴール確認
このように滑らかにジャンプするところがゴールです。空中ジャンプを禁止して、地面の着地方法も面白い計算を使っています。
プロジェクトをコピーする
前回のレッスンを作っている人は、ファイル>コピーを保存を選んで、プロジェクト名を「マリオプロジェクト002」に変えるところからスタートです。
ジャンプを作る
マリオといえばジャンプして敵を踏んで倒すというのが定番ですよね。ブロックを壊すときもジャンプしますね。つまりジャンプはスーパーマリオで最も大事な動きの1つと言えます。
ここからはジャンプをやっていきましょう。
今まではX軸の動きでしたが、ここからY軸の動きに着手するので、動きがますます複雑になっていきます。1つずつ丁寧に解説していくので、一緒にがんばりましょう!
上キーを感知する
とりあえず上キーを押したらY座標を10ずつ変えるブロックを追加して、動きを確かめましょう。もちろん動くと思いますが、儀式的な感じです。
変数「スピードY」を作る
X軸のときと同じように変数でスピードを管理していきます。スピードYという変数を作ってください。
上を押したら変数「スピードY」に加算する
上キーを押したらスピードYを一定の数値にセットします。ひとまず10にしておきます。
Y座標に変数「スピードY」を加算し続けます
X軸のときと同じように、Y座標にもスピードYを加算し続ける仕様にします。旗を押したらにある「ずっと」ループ内にブロックを追加してください。
変数「★重力」を追加する
これだけでは上を押したらプレイヤーがずっと上に浮いている状態が続いてしまうので、プレイヤーを下に落下させる処理を追加します。
ここでは重力という変数を作り、常にプレイヤーを下に引っ張る力を加えます。
この変数はすべてのスプライト用に作るので、接頭語に★をつけておいてください。
初期化する
マイナス1になるように初期化してください。
プレイヤーを重力で落とし続ける
変数「スピードY」を変数「★重力」で変え続けます。こうすることでプレイヤーは常に重力の影響を受けることになります。
プレイヤーの初期位置を初期化する
いちいちプレイヤーの位置を戻すのは手間なので、少し高いところに初期位置を設定します。
着地できるようにする
動かしてみると、プレイヤーが画面の下まで落ちてしまいましたね。ずっと重力の影響を受けているので、際限なく下に移動してしまうのです。
そこで、「もし」ブロックを使ってプレイヤーが着地できるようにしましょう。
これには調べるブロックの1つである「○に触れた」ブロックが有効です。ステージスプライトに触れたら変数「スピードY」をゼロにして、これ以上の落下を止めます。
しかし、こうすると動かなくなってしまいますよね。
また、ときどきプレイヤーがステージに埋まってしまったり、少しだけ空中に浮いてしまったりする現象も起きているのではないでしょうか。
着地判定に条件をつける
まずは動かなくなってしまう問題にタックルします。
動かなくなった原因は、ステージに触れている間はずっと変数「スピードY」がゼロに固定されてしまうので、落下したタイミングだけではなく、そのあともずっと変数「スピードY」がゼロから変わらなくなってしまうからです。
そこで、さらに条件を追加します。
変数「スピードY」がゼロよりも大きいときだけ、この着地判定が行われるようにします。こうすることで、着地したあとにまた上キーを押せば、変数「スピードY」は10に戻ることができます。
ブロック定義に処理を移す
すこしループ内が混雑してきたので、このタイミングで今までのY軸の移動処理をブロック定義に変えておきます。
ブロック定義に移し終わったら、動作確認をしてとりあえずここまでの動きが壊れていないか確認しましょう。
地面に触れているかどうかを1座標ずつ調べる
ここからは、着地時にプレイヤーが地面に埋まってしまう、または地面から少し浮いている問題にタックルしていきます。
様々な方法がありますが、プレイヤーが次に移動する位置にステージがあるかどうかを1座標ずつチェックしていく作戦でいきます。
分かりづらい部分なので、何度か読み返してマスターしてください。マリオだけではなく、シューティングゲームやイラストアニメーションのような別プロジェクトでも応用可能な処理です。必ず役に立ちます。
Y座標を−1ずつ変えるように微調整する
まずはブロック定義「Y軸に移動する」内の処理を少しだけ変えます。一番下にあった「y座標をスピードYずつ変える」ブロックを外して、少し上に移動します。また、値を-1に変えます。
文字だと分かりづらい部分なので画像をご覧ください。
変数「直前のY座標」を作る
Y座標を-1してプレイヤーがステージに触れているか調べて、触れていたら移動を中断するために直前のY座標に戻したいと思います。そこで、チェック前のY座標を変数「直前のY座標」に預けておきます。
変数「直前のY座標」のおかげで、Y座標を-1する処理を何回繰り返しても、カンタンにY座標を元に戻せます。
変数「直前のY座標」を初期化する
処理の直前にY座標の値で初期化します。
ステージに触れたら元に戻す
ステージに触れたタイミングで、直前のY座標に戻します。こうすることで地面に触れた瞬間に落下が止まります。
しかし、これだと再びジャンプができなくなってしまいます。
なぜなら、「もし」ブロックのせいで変数「スピードY」がゼロより大きくなる前にプレイヤーのY座標を-1してステージに触れたか判定するので、必ずステージに触れている判定になってしまうからです。
これを改善するには2ステップ必要です。見ていきましょう。
変数「スピードY」がゼロなら、という条件をやめる
原因の1つである「もし」ブロックを除去します。
進行方向の1つ先にある座標をチェックするよう変える
いまは「Y座標を-1ずつ変える」と直接入力しているので、これでは必ず下方向しかチェックしません。しかしジャンプするときは上方向に向かっているので、下をチェックする必要はなく、むしろ邪魔です。
そこで上に向かうときはY座標をプラス1して、下に向かうときはY座標をマイナス1したいと思います。
それには絶対値が有効です。
この式はどうなっているのでしょうか。
たとえば変数「スピードY」の値が10だったとします。これは上に向かっているときの値ですね。プラス10の絶対値は10なので、このときの式は「10 ÷ 10」つまり1です。
そして変数「スピードY」の値が-5だったとします。これは下に向かっているときの値です。マイナス5の絶対値は5なので、このときの式は「-5 ÷ 5」つまりマイナス1となります。
これにより上に向かうときはプラス1、下に向かうときはマイナス1という要件を実現できました。
しかし、動きを試してみるとジャンプが小さくなってしまっていませんか?それに上キーをずっと押していたらやっぱり空中浮遊してしまいます。どうやらまだまだ改善しないといけないようですね。
判定処理を繰り返す
ジャンプが小さくなっている理由は、スピードYの値が10であろうと100であろうと、絶対値で割って1にしてしまっているので、Y座標が1ずつしか変わらないという点です。
そこで、この処理を変数「スピードY」の絶対値の分だけ繰り返します。
これでジャンプは予定通り10座標分動くようになりました。
しかし、なんだか動きが「もっさり」していませんか?ずいぶんゆっくりなジャンプになってしまっていると思います。この理由は、Y座標を1変える度に判定処理が行われているので、1座標ずつカクカクして見えているからです。
ブロック定義を再描画させずに行う
今回のカクカク現象は、1座標ずつ変える度に判定処理が行われてしまっていることが原因でした。
そこで、変数「スピードY」が10なら、10回の判定処理が終わってからプレイヤーを動かすように変更できればOKです。
ブロック定義には「画面を再描画せずに実行する」というオプションがあることをご存知ですか?
このオプションこそが今回の鍵です。
ブロック定義を右クリックしてオプションにチェックを入れてからOKを押してください。
動きはどうですか?しっかり10座標分のジャンプができるようになっているのではないでしょうか。
上手く動かないひとは「○回繰り返す」ブロックに変数「スピードY」の絶対値が入っているかチェックしてください。
この「再描画せずに実行する」オプションは、ある意味で未来予想ができるものです。一瞬で処理をしているから、人間の感覚ではとらえきれないためです。色々な場面で役に立つので、このオプションの使い方の1つとしてマスターしていくと良いでしょう。
空中ジャンプをできなくする
さて、ジャンプはいい感じになってきましたが、ジャンプ中に上キーを押すと好きなだけ空中ジャンプができてしまうのが現状です。
これはこれで面白い発想に繋がりそうですが、ここでは空中ジャンプは禁止したい思います。
考え方としては、空中にいるかどうかを判定して、空中にいたら上キーを押しても効かなくするという感じです。
変数「滞空時間」を作る
空中にいるかどうかを判定するために、滞空時間という変数を作ります。
加算し続ける
滞空時間に1を加算し続けるようにします。
上キーの条件に滞空時間を使う
滞空時間が3未満のときだけ変数「スピードY」が10になるように調整します。
この3という数値は感覚的なものですから、自分で動きを確かめながらどのくらいの数値が良いか見定めてもOKです。
これで空中ジャンプも行われなくなり、マリオの横スクロールの基本的な動作が完成しました。歩く、ジャンプ、横スクロール、この3つが完成したことは大きな進歩です。
マリオの土台ができたと言っても過言ではありません。
壁・坂の処理に挑戦していこう!
次にタックルするのは、ステージが起伏に富んでいる際に生じる問題です。すなわち「壁に当たったら止まる」「でも坂なら登る・降りる」です。
壁に当たったら止まると言っても、今回はプレイヤーのX座標を動かさずに★カメラのX座標を使って移動を実現していますよね。こういう場合はどうコーディングしていけばよいのでしょうか。
また、坂も厄介です。壁と坂の違いをプログラム上どのように見分ければ良いでしょうか。
これらも厄介な実装が必要ですが、引き続き丁寧に解説していきますので、一緒にトライしていきましょう!
数日以内に更新する予定です!この記事からも新しいレッスンに行けるリンクを張っておくので、ブックマークよろしくおねがいします〜!次のレッスンを公開しました!
スクラッチでマリオのゲームを作る特大レッスン#03 壁・坂を攻略せよ
本家マリオと同じように壁なら止まり、坂なら登る処理が書けるようになります。- ① 横スクロールを制覇せよ
- ② ジャンプせよ (いまここ)
- ③ 壁・坂を攻略せよ
- ④ ゴールして次へ
- ⑤ ブロックを壊せ
- ⑥ スタックを回避せよ (バグ修正の回)
- ⑦ コインをゲットせよ
- ⑧ 敵モブを召喚せよ1 (クローン化、スポーン、横移動など)
- ⑨ 敵モブを召喚せよ2 (方向転換や重力)
- ⑩ 敵モブを召喚せよ3 (アニメーション)
- ⑪ バトル開始1 (ダメージを受ける・与える)
- ⑫ バトル開始2 (ダメージのアニメーション、フィードバック)
- ⑬ 敵モブをリスポーンさせる
- ⑭ iPadに対応する
- ⑮ 迫りくるパタパタ (敵モブに新しい動きを追加する手順が分かる)
- ⑯ パタパタのバグ修正 (ジャンプのバグを直す)
- ⑰ 壁に埋もれるバグ修正 (バグがバグを呼ぶ、でも諦めない)