24

stackoverflow や他のサイトでゲームの衝突検出について読んでいます。彼らの多くは、BSP、境界楕円、統合などについて語っています。しかし、NES では、ゲームで床と壁の衝突検出を行うことができました。壁の衝突を検出するために多くの計算を行ったとは信じがたいと思います。

私の質問は、タイルだけで構成されたレベルを考えると、処理能力がほとんどないマリオやロックマンのようなゲームで壁や床との衝突をどのように検出したのでしょうか?

  • 彼らは動きの経路をたどり、最も近い接続タイルを特定しましたか? (少し調べて)(アプリオリ)
  • 彼らは床との衝突を判断してから、キャラクターを調整する最善の方法を見つけましたか? (事後) これは可変タイムステップでは危険です。十分に速ければ、タイルを飛び越えることができます。NES ゲームのタイムステップはテレビのリフレッシュ レートと同期していると思いますが。
  • 地面にいるとき、重力は常にキャラクターに影響を与えていますか? それとも、タイルの上を歩いていると決めたときに「オフ」にしますか? 崖の端から歩いて降りるときはどうですか?それ以外の場合は、下にあるタイルを特定する何らかの方法が必要になります。
  • タイルに衝突した場合、そのタイルの端を見つけて、キャラクターをその側に移動しますか (進行方向によって異なります)。
  • スーパーメトロイドやマリオのような傾斜したタイルはどうですか?
  • 下をジャンプして上に着地できる「プラットフォーム」はどうでしょうか。「事後」に行う場合、これらのタイルとの衝突にどのように対処しますか?

特定の方向にヒットする最初のタイルを検索するため、基本的に「アプリオリ」な衝突コードをいくつか作成しました。何か良い方法はないかと考えているところです。(代わりに事後衝突検出を使用するだけかもしれません)

たとえば、下に移動するためのタイルの衝突をチェックするコード (私は垂直方向の動きをチェックしてから水平方向の動きをチェックします):

  def tile_search_down(self, char, level):
        y_off = char.vert_speed
        assert y_off > 0

        # t_ are tile coordintes
        # must be int.. since we're adding to it.
        t_upper_edge_y = int( math.ceil((char.y+char.h) / self.tile_height ) ) #lowest edge
        while (t_upper_edge_y*self.tile_height) < (char.y+char.h+y_off): # lowest edge + offset

            t_upper_edge_x = int( math.floor(char.x/self.tile_width) )
            while (t_upper_edge_x*self.tile_width) < (char.x+char.w):

                t_x = t_upper_edge_x
                t_y = t_upper_edge_y 
                if self.is_tile_top_solid(t_x, t_y, plane):
                    char.y = t_y*self.tile_height - char.h
                    char.vert_speed = 0.0
                    char.on_ground = True
                    return

                t_upper_edge_x += 1
            t_upper_edge_y += 1

        char.y += y_off
4

4 に答える 4

18

あなたが話しているNES時代のゲームの種類については、すべてが2Dでした。それだけで多くのことが簡単になります。

その時代のいくつかのマシン(特にコモドール64のようなハードウェアスプライトを備えたマシン)には、ハードウェアの衝突検出機能がありました。ハードウェアの衝突検出に依存していなかったほとんどのゲームは、バウンディングボックスまたはヒットマスク(スプライトの1ビットビットマップ)のいずれかを使用します。

いずれにせよ、衝突検出は、世界の端のような特別な場合を除いて、通常「事後」に行われました。一部のゲームには実際にバグがあり、何かにぶつかったときに動きが速すぎると、それを通過する可能性があります。(実際、80年代初頭のゲームのレビューでは、衝突検出がどれほど正確であったかについてコメントすることがよくありました。)

プラットフォーマーの場合、通常、重力を適用する前に、キャラクターが「接地」されているかどうかを確認します。

スプライトの速度ベクトルがわかっているので、一方向プラットフォームのことは事後に対処するのはそれほど難しくありません。したがって、それを使用して、衝突を登録する必要があるかどうかを判断できます。

于 2009-07-15T06:05:15.307 に答える
14

Nintendo Entertainment System (NES) の「プラットフォーム ゲーム」のプログラミングについて詳しく説明している記事がここにあります。

以前にこの記事に出くわしたことがなかったので、私は正しくグーグルしていなかったかもしれません.

于 2009-07-17T00:46:13.340 に答える
13

スーパー マリオ ワールド (SNES) などのゲームでは、マリオの X/Y 位置を取得してタイル アドレスに変換し、そのアドレスのすぐ近くにあるタイルを簡単に確認できるメモリ形式でレベルを保存しました。レベルは常に固定幅だったので (表示できる領域はさまざまでした)、アドレッシングが管理しやすくなりました。これは、マリオの位置からのオフセットが常に固定されているためです。たとえば、マリオの横のタイルはアドレス + 1、タイルはアドレス + 0x300 です。彼の下のタイルなど

于 2009-07-15T06:09:06.063 に答える