ゲムキTOP > ブログTOP

ハルポップの徒然雑記

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

マリオの完コピvol.24 土管ワープ

ハルポップ 2016-06-01 17:59:36 pv:1977


土管に入ると別マップへ移動

これをどう作るか。
作る人によって千差万別のやり方が生まれそうだ。
答えがないところなので一番難しいところでもある。

最初考えた方法はこれ
・透明なスプライトを土管に配置して、しゃがむ事によって反応して土管に入る

これでワープする事は出来たが、以下の短所がある。

短所
・土管以外にも設置できてしまう。土管の配置を変更した場合に透明スプライトも同時に移動しなければいけない。
・土管と別に配置が手間
・BGではなくスプライトとのあたり判定なので処理負荷がかかる

これらを改善すべく次に考えた方法がこちら
・土管自体をワープ土管として区別して配置する。透明スプライトにワープ先の情報を入れる。透明スプライトはワープ土管より手前に設置し、マリオがX座標をこえただけで反応する仕組み。

ただこの方法も結局、スプライトからワープ先を取得するため処理負荷自体はかかる。
配置の手間だけ減らせられる。


そしてオリジナルはどう作っているのか。
風のうわさによると、土管はワープ土管として扱っており、ワープ先は別に取得する。
ワープゾーンは例外として、通常は1画面に2つ以上ワープする土管が存在しない。
4-2の裏技で、豆の木を出して画面スクロールをしてワープ土管を出現させると、土管でワープしたら豆の木のエリアから現れる。これはその処理によるものだと思う。


そういう事でオリジナルと同じく通常土管とワープ土管とで分けて配置する方法を採用した。

マリオの完コピvol.23 処理負荷軽減

ハルポップ 2016-05-26 22:57:40 pv:1760
こちらのvol.19で言っていた負荷について
http://blog.game-kids.net/haruzakki/entry-747.html

オリジナルと同じようにマップを作って実行すると、やたら重くなった。

60だったFPSが30付近に。

なんじゃこりゃー。
ファミコンレベルなのに重くなるのか。
作り方がまずいのか?画像が多すぎる?

そして重くなってる箇所をつきとめる作業に。
これは各処理の部分をコメントアウトして確認する感じで。

すると各スプライトのupdateをするところで重くなっていた。

■該当のコード
auto children = mBgLayer->getChildren();
reverse(children.begin(), children.end());
for (auto obj : children) {
child->update();
}

スプライトといってもクリボーとノコノコしか処理をしているものはない。当たり判定が重いのか?
と思って当たり判定部分を切ったら少し軽くなった。

で、検証したところ
auto children = mBgLayer->getChildren();
reverse(children.begin(), children.end());
こうやって配列を逆順にするところが重かった。

正確に言うと
auto children = mBgLayer->getChildren();
この時点で配列のコピーが生成されているので、元の配列がでかいほど重くなる。

auto &children = mBgLayer->getChildren();
のように&を付けると参照になるので一瞬で処理が通るが、配列を逆順には出来ない。
配列を逆順にする理由は、ループ内で削除をしたいから。

詳しくは
http://qiita.com/AknEp/items/e54e18766ea00c86fca8


で、逆順にせず参照を使い、ループ外で削除するようにコードを変更したら軽くなった。
が、それでもクリボーを大量設置すると重い。
これは仕方ないのか?いや、30年前のファミコンレベルで重いとかありえない。
スーファミのファーストクイーンでも大量のスプライトが動いていたはずだ。


で、よくデバッグをしてみると、
auto &children = mBgLayer->getChildren();

このchildrenの数が全ての設置しているスプライトの数なので、やたら多い。レンガと地面、さらには雲や草原も含めているので500は軽く超える。
そのうち使用するのはクリボーとノコノコ程度なのでほとんどが空処理となる。
当たり判定でもほとんどが空処理になっている。

これが諸悪の根源だったようだ。
毎フレーム500×10(敵キャラ)くらいの空処理があるということ。

それで以下のようにupdateするスプライトだけをリストに入れて実行するようにした。

■リスト版
for (auto itr = mSprList.begin(); itr != mSprList.end(); itr++) {
MySprite* child = dynamic_cast<MySprite*>(*itr);
child->update();
}

こうすると劇的に軽くなった。
試しにクリボー大量設置してもこのように大丈夫。


リストに入れずにスプライトだけを扱ったレイヤーを別に作って、getChildrenで取得する事も検討したが、それだと背景の後ろにスプライトを表示する事が出来なくなるので、やめた。
今だとキノコがブロックの後ろから登場するとこだったり、後にマリオが土管に潜るところで背景の後ろに表示する必要が出てくる。

マリオの完コピvol.22 壁引っかかりバグ

ハルポップ 2016-05-25 19:59:56 pv:2121

忍者マリオ

壁の右からは引っかからないのに左からは引っかかる現象。
修正したら今度は逆に右から引っかかるようになったり。
原因は、マリオの右端の座標をx+16としていたこと。+16にすると右端ではなく、右端の右隣になる。
正しくはx+16-1だ。

この1ピクセルの差や不等号の「<=」か「<」の違いに泣く事がよくある。
「<=」でだめだったらよく考えず「<」にして修正する事もよくある。


修正後

マリオの完コピvol.21 ノコノコ

ハルポップ 2016-05-24 23:19:46 pv:1926


マリオは当初、クリボーがおらずノコノコが最初の敵だったが、1発で倒せる敵を作ろうということで、クリボーが最後に作られたとか。

ノコノコで無限1UPできる裏技も当初は想定していなかったようで、10機をこえたらご褒美で残機に王冠マークを付けるようにしたとか。

マリオの完コピvol.20 下からマリオ

ハルポップ 2016-05-23 23:30:53 pv:1764
下からマリオ サディスティックな奴め


レンガブロックを叩くと上の敵がやっつけられる処理の実装。
最初、ひっくり返ったクリボーに、もう一匹のクリボーがぶつかって反転するという現象があったが、死亡時はスルーする事で解決。