ゲムキTOP > ブログTOP

ハルポップの徒然雑記

ためになる話、どうでもいい話など

マリオの完コピvol.29 Bダッシュで1マスの穴越え

ハルポップ 2016-06-12 22:54:05 pv:2485


最初はどうしてダッシュで穴を越えれるのかが分からなかった。
1フレームで当たり判定分以上のピクセルを移動しているのか、それとも本来は落ちるはずなのに特別処理で落ちないようにしているのか。
オリジナルの動きをよく見るとトリックが分かった。
Bダッシュじゃなく歩行時の最大速度でも1マスの穴は越えられるのだが、その時に一瞬穴に数ピクセル落ちていたのだ。その後、ブロックの上に補正されていた。

その補正処理が穴を越えるトリック。
前の「ブロックずらし」という記事で書いた処理のX軸バージョンっぽい。
http://blog.game-kids.net/haruzakki/entry-744.html

これを実装してみるとBダッシュで1マスの穴を越えるのが実現出来た。

マリオの完コピvol.28 ジャンプの解析と修正

ハルポップ 2016-06-11 14:20:21 pv:12882
ジャンプの挙動と値を修正する事にした。
オリジナルのジャンプを1フレームずつ撮影し、その時のマリオの帽子の高さよりY座標を求め、それをエクセルに入力してグラフにしてみた。
すると新たな発見があった。Aボタン押しっぱなしの時とAボタンを途中で離した時でグラフの形が変わっていたのだ。

■Aボタンを押しっぱなしのグラフ


■Aボタンを途中で離した時のグラフ


Aボタンを押しっぱなしのほうは、左右対称の放物線ではないので上昇時と落下時で加速度が違う事が分かる。
Aボタンを途中で離した時は、左右対称の放物線っぽく見えるが、値が少しずれているため、ボタンを離すまでは↑の上昇時と同じ加速度がかかり、離した時から違う加速度がかかっていると想像する。

また別に、ジャンプではなく落下時だけのデータも取得してグラフにしてみた。


こちらは途中まで加速し、そこから一定速度になっている事が分かる。これにより落下の最大速度が設定されている事が分かる。



次にジャンプ上昇時の起点と終点の数値より、物理の方程式を使って加速度と初速を求めてみた。
Δx = v0 * t + 1/2 * a * t^2
v = v0 + a * t

この2つの式を使って連立方程式を解けばいける。
中3か高1くらいの分野と思うが、現役を離れて忘れていたので、この本を引っ張り出してみた。



そして計算した結果
加速度は-0.126953125ピクセル/フレーム^2
初速は4.0624ピクセル/フレーム
となった。


導いた式を使って実際の値を比べてみると、ほぼ一致していたので、等加速度運動になっている感じだ。
↓Aの列がオリジナルの値で、Iの列が計算結果の値


以上より仕様をまとめると
・上昇時と下降時で重力が違う。
・等加速度運動である。
・落下時は最大速度がある。


そこで以前に書いたジャンプ実装の記事が間違っていた事が分かる。
http://blog.game-kids.net/haruzakki/page-6.html
こちらの記事では、ジャンプで必要そうなパラメータは以下の4つを挙げていた。
1.ジャンプした瞬間の力
2.加速度(重力)
3.ボタンを押す時間の最大フレーム数
4.落下時の最大速度

このうち、2は細分化され、上昇時と下降時とで分かれる。
3は不要である。

次に、オリジナルの完コピを目指しているため、正確な値を入力してみたい。
で、風の噂でオリジナルの値を知る事が出来た。

まず、マリオの停止低速時、低速ダッシュ時、高速ダッシュ時の3パターンに分かれている。
低速時においては、上昇重力は0x20、下降重力は0x70、入力値は0xFC、抑制力は0x00であるようだ。

何のこっちゃよく分からないが、入力値の0xFCは10進数にすると252であり、256から引くと4となる。
上昇重力の0x20は10進数で32であり、その値を256で割ると0.125である。
この2つの数値は先ほど求めた
・初速は4.0624ピクセル/フレーム
・加速度は-0.126953125ピクセル/フレーム^2
の値に限りなく近い。

そしてこの値を使ってやってみた結果、ほぼオリジナルと同じ動きを再現する事ができた。
ダッシュジャンプの最高点の高さも一致している。


再現できた時には中々感動した。

ジャンプについてはいろいろググって調べてみたが、サンプルはどれもマリオのジャンプとは違っていた。
これとか
http://aidiary.hatenablog.com/entry/20050613/1255785116
これとか
http://d.hatena.ne.jp/Gemma/20080517/1211010942
http://www.geocities.jp/teruakigemma/jsmario/jsmario.html

2つ目の記事ではVerlet法というのを使ってやってて、この方法じゃないと出来ないのかと思ったけど、別に速度と加速度を使っても同じように出来るので騙されるところだった。

マリオのジャンプの肝は『上昇時と下降時で重力を分ける』。これに尽きる。
ボタン押し続けている間は上昇時の重力がかかるので、ボタンを押す時間によってジャンプ力が変わるというのも再現できるということだ。
重力が同じなら、ボタンを押し続けている間のフレーム数をカウントして、いろいろ処理しないといけない。
↑の最後のサンプルはそれに引っかかって5フレーム分のカウントをとるようにしていた。


物理法則には従わないこの方法を考えた人は天才だ。
初速と重力2つ。これでボタンを押す長さによって高さが変わるジャンプが再現できる。素晴らしい。

マリオの完コピvol.27 マップスクロールの負荷軽減

ハルポップ 2016-06-10 22:56:47 pv:2132
Androidの実機で確認すると、マップスクロール時に処理落ちしていた。
いろいろ検証テストしてみた結果、設置したスプライトの数が少ない時は処理落ちしなかった。
どうやらスプライトを大量に配置してスクロールさせると処理落ちするようだ。

そこで、画面外のスプライトは配置しないようにして、マリオが近づいて画面内に迫ってくると配置するように変更した。
これで実機でも処理落ちしなくなった。


↑分かりやすいように仕掛けを画面内に見えるようにしてみた。

マリオの完コピvol.26 中間ポイント

ハルポップ 2016-06-09 20:50:18 pv:1654

ステージの後半で死んだら、中間から開始される。

マップのカスタムプロパティで、中間の座標を設定し、それを越えたところで死んだらそこから始まるように。
中間から再開する時は、中間より前の敵は設置しないようにする。
ついでに初期座標もマップのプロパティで定義するようにした。

マリオの完コピvol.25 ゴールの旗

ハルポップ 2016-06-02 23:42:44 pv:2152


旗はスプライト
ポールはBG
城はBG
城の旗はスプライト

問題はマリオの動作の制御。
ポールから下るのは重力が関係ないので固定の動作。
ポールから飛び降りるところは重力込みの自然動作。
城に向かって歩いていくのも自然動作。

問題は城の入口をどう認識するか。
旗から城までの距離を固定にするなら簡単だが、もし城の位置を変えた時に対応できないので良くない。

で、マリオ2の攻略本を思い出した。
ポールを越えた後、城の入り口の隣に透明のブロックがあるという記事があったことを。
この透明のブロックの意味が20年以上の時を越えて繋がった。
この透明ブロックがトリガーとなっているのだ。ブロックに当たる事によって城に入ると。

分かりやすく色をつけてみた。