スクラッチプログラミングに挑戦している皆さん、どうも!スクラッチコーチです。
敵モブをスタック回避させる スタックするというのは動けなくなるとか固まるという意味です。現状では敵モブがシーンに埋もれて動けなくなるバグがあります。 今回はここにタックルしていきます。 リスポーンする まずはシーンに埋もれた時のレスキューとして、最初にスポーンした場所に戻してしまうという方法を実装します。 変数「リスポーンタイマー」を作る 埋もれたらすぐにリスポーンさせるのでは、しょっちゅう敵がリスポーンしてしまい、ゲームが難しくなってしまいます。 そこでリスポーンタイマーという変数を作って、何秒か埋もれた状態が続いていた場合だけリスポーンさせるようにしたいと思います。 ブロック定義「リスポーンする」を作る オプションにチェックを入れます。 右に1座標ズラして障害物に触れているか調べる すぐに座標を戻す 障害物に触れていなければタイマーをリセットする 終わるときはリスポーンタイマーをゼロに戻します。 まだリスポーンタイマーに値を設定する前なので分かりにくいですが、このあとすぐにリスポーンタイマーに値を入れるので、とりあえず処理を止めるときにゼロに戻すという処理を入れておいてください。 処理を止める 障害物に触れていなかったので、リスポーンの必要性はありません。この場合はこれで終わりです。 同じことを左でも繰り返す 座標がプラマイ逆になっただけで、まったく同じ処理です。冗長ですが分かりやすいのでOKです。 左右が障害物に触れていた場合を作る 左右が何かに挟まった状態であると解釈して、タイマーをセットします。このタイマーで一定時間経過したらリスポーンの必要があります。 タイマーという値はブロックパレットの「調べる」にあります。 タイマーをセットしたらいったん処理を止めてOKです。 また、スクショではログを書いておきました。なぜタイマーをセットするのか、その理由を書いておきました。 一定時間たったか様子見をする タイマーをセットした後もなおスタック状態が続いているかを調べます。 ステップ1 タイマーからリスポーンタイマーの値を引いています。 数字で解説します。 タイマーには現在時刻が入っています。 リスポーンタイマーには一瞬前の時刻が入っています。 そして、今の時間から一瞬前の時間を引くと「何秒経ったか」という差分が分かるのです。 ステップ2 差分が3秒よりも大きいかどうかを判断する式です。 3秒はこの段階では適当です。おそらく0.6秒くらいがいいかなと思います。 ステップ3 条件分岐ブロックを追加します。 またログを書いておきました。 このブロック定義は、各条件がNOであるとスクリプトを止める構造なので、ブツブツ切れているような作りになっています。こういう構造はログがないと分かりづらいので、こまめにログを書いてあります。 リスポーン処理をする これがリスポーンの本質的な処理です。変数「初期化済みかどうか」を1から0に戻してから自分のクローンを作り、自分自身は消しています。 こうするとまた最初のスタンバイ状態に戻ります。 ブロック定義全体を確認する 動作確認する 埋もれを修正する(スペースを探す) リスポーンに成功しました。しかし、スタックしたらリスポーンではなく、まずは埋もれた状態を改善できないかどうかを試みたいと思います。 プレイヤーのときに埋もれてしまったプレイヤーをレスキューするロジックを作りました。 https://scratch.coach/lesson/mario5-5/ 敵モブでも同じように埋もれ修正を行います。それでもダメならリスポーンするという流れにします。 作戦としては、敵モブを上下左右に何座標か動かしてみて、一番近くのスペースを探します。そして見つかったスペースに敵モブをワープさせるという感じです。 まずはスペースを探すロジックを作ります。 ブロック定義「埋もれ修正する」を作る オプションにチェックを入れます。 利用する リスポーンの処理を整えておく 埋もれ修正後にリスポーンする部分を少し変更します。 ブロック定義「埋もれ修正する」の直後に、障害物に触れているかどうかを判定します。 触れていなければ埋もれ修正できたということです。 リスポーンタイマーをリセットしてスクリプトを止めます。 また、ログも修正してあります。 ログを追加する リスポーンのところにもログを打っておくと分かりやすいです。 回転方法を自由にする 敵モブを上下左右にずらしていく前提として、処理を効率化するために回転を自由回転にしておきます。 こうすると上を向けたり下を向けたり出来ます。 それがどう効率化につながるのか、予想できますか? 答えはもうすぐです! 90度からスタートする 変数「埋もれ修正値」を作る 初期化する 30回繰り返す 30というのはまだ適当です。何座標まで埋もれ修正を試みるか、適切な数値は微調整しながら見つけてください。 あまり大きな数値にすると、埋もれ修正のレベルを逸脱してしまいます。微調整する際は、そのあたりのバランスを考えながら調整します。 埋もれ修正値を1ずつ増やす 敵モブの位置をずらす 障害物に触れているか調べる 本質的な処理を……後回しにする ここで埋もれを修正する本質的な処理を行うのですが、その前にスペースを探す処理を終わらせてしまいます。 敵モブの位置を戻す ここに処理が来るということは、まだ障害物に触れていたということです。そのため次の位置にチェックを移していきます。 今は90度の向きで1座標ズラしてチェックしましたね。 次のチェックのために、いったん1座標分を戻しておきます。 そして次は180度に向けて1座標ズラしてチェックします。 それでもダメなら次は270度。 それでもダメなら次は360度。 それでもダメなら上下左右の1座標は全て障害物が存在しているということです。 これで諦めずに次は2座標ずつズラしていきます。 これを30座標になるまで続けます。 また、1座標ごとに4つの角度(90, 180, 270, 360)をチェックしていくので、もう1つループを追加していきます。 4回繰り返す 向きを変える 回転方法を左右に戻す 処理が終わったら回転方法を元に戻しておきます。 埋もれ修正する(本質的な処理) TODOとしておいた部分に取り掛かります。ここはスペースが見つかった場合の処理です。 回転方法を元に戻す 向きを元に戻す Y軸に埋もれを修正した場合はこれでもいいのですが、X軸に移動した場合はもうワンステップ必要です。 横向きかどうかを判定する 横向きならX軸に埋もれ解消することを意味します。 変数「移動距離X」に埋もれ修正値を追加する なぜ横向きの場合だけこのような処置が必要なのでしょうか。 Y軸であれば、素直にY座標で指定しているだけなので特に問題はないのですが、X軸への移動には変数「★カメラのX座標」や変数「スポーンするX座標」などを加味した複雑な演算を使っています。 その演算の中で、スポーン地点からどのくらい進んだかという判定に変数「移動距離X」を使っています。 この値を変えないと、せっかく埋もれを修正してスペースにワープさせても、次の瞬間にはまたスポーン地点から変数「移動距離X」分だけ進んでしまい、またまたスタックしてしまいます。 そのため、X軸に埋もれを解消した場合は、変数「移動距離X」の値を変数「埋もれを修正値」の分だけ修正して上げる必要があるのです。 動作確認する 完成です!埋もれてもピョコっと上がってきます。ずっと埋もれてたらリスポーンしてくれます。 プレイヤーを微調整したら土台は完成! 長い道のりでした。 あとはちょっと微調整します。 そうしたらいったん完成です。 その後はマリオらしい敵モブを作ったり、コースを考えたり、ワクワクを盛り込みまくりましょう。スクラッチでマリオのゲームを作る特大レッスン#12 リスポーンさせる
敵モブがスタックしたらリスポーンさせる手順がわかります!
-
スターター
プロジェクト -
リミックス用プロジェクトへ
Scratchデスクトップ用ファイルをダウンロード - サンプル
- 見本のプロジェクトへ
- 難しさ
任意)自分の作業中のスクラッチ作品URLを記録しておこう!再開するときに便利だよ。
LOADING...
※ この記録は今使ってるPCに保存されます。別のPCで作業するときは表示されません。