旧游戏如何检测墙壁,地板和天花板的碰撞? [英] How did older games do collision detection with walls, floors and ceilings?

查看:112
本文介绍了旧游戏如何检测墙壁,地板和天花板的碰撞?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在阅读关于stackoverflow和其他网站上的游戏中的碰撞检测的信息。他们中很多谈论BSP,边界椭圆,集成等。但是,在NES上,他们设法在游戏中进行地板和墙壁碰撞检测,我很难相信他们做了很多计算以检测墙壁碰撞。 p>

我想我的问题是,鉴于仅由瓷砖组成的关卡,它们如何检测像Mario和Megaman这样游戏中处理能力差的墙壁和地板的碰撞? / p>


  • 它们是否遵循运动路径并确定最近的连接图块? (稍作搜索)(先验)

  • 他们是否确定与地板发生碰撞,然后找出调整角色的最佳方法? (posteriori)这是有风险的,因为时间步长可变,如果足够快的话,您可能会跳过瓷砖。尽管我假设NES游戏的时步与电视的刷新率保持同步。

  • 在地面上时,重力是否总是会影响角色?还是确定要在瓷砖上行走时只是关闭它?当您走下悬崖的边缘怎么办?您需要某种方法来确定下方的瓷砖。

  • 如果您与瓷砖发生碰撞,您是否会找到瓷砖的边缘并将角色移动到

  • 像超级银河战士和马里奥中那样倾斜的瓷砖呢?

  • 平台怎么样?您可以从底部跳到顶部。如果您在进行 posteriori操作,如何处理这些图块的碰撞?



我已经编写了一些基本上是碰撞代码 priori,因为它会搜索您将沿特定方向命中的第一个图块。我只是想知道是否有更好的方法。 (可能只是使用事后碰撞检测而已)



例如,用于检查向下移动的瓷砖碰撞的代码(我先检查vert然后再水平移动):

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

#t_是平铺坐标
#必须是int ..,因为我们要添加它。
t_upper_edge_y = int(math.ceil((char.y + char.h)/ self.tile_height))#最低边
而(t_upper_edge_y * self.tile_height)< (char.y + char.h + y_off):#最低边+偏移量

t_upper_edge_x = int(math.floor(char.x / self.tile_width))
而(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):
字符。 y = t_y * self.tile_height-char.h
char.vert_speed = 0.0
char.on_ground =真
返回

t_upper_edge_x + = 1
t_upper_edge_y + = 1

char.y + = y_off


解决方案

对于您正在谈论的NES时代的游戏类型,一切都是2D的。



那个时代的某些机器(特别是带有硬件精灵的机器,例如Commodore 64)具有硬件冲突检测功能。大多数不依赖硬件冲突检测的游戏都将使用边界框或命中遮罩(精灵的1位位图)。



无论哪种方式,冲突除特殊情况(例如世界边缘)外,检测通常是后验的。实际上,有些游戏确实存在一些错误,当您碰到某些东西时,它们过快移动可能会导致您通过错误。 (实际上,对80年代早期游戏的评论经常会评论碰撞检测的精确度。)



对于平台游戏者,通常需要检查角色是否在施加重力之前先接地。



单向平台的事情在事实发生之后并不太难处理,因为您知道了精灵的速度矢量,因此您可以以此来确定是否应该记录冲突。


I have been reading about collision detection in games on stackoverflow and other sites. A lot of them talk about BSPs, bounding elipses, integration etc. However, on the NES, they managed to do floor and wall collision detection in games and I find it hard to believe that they did many calculations to detect wall collisions.

I guess my question is, given a level made up of just tiles, how did they detect collisions with walls and floors in games like Mario and Megaman which had little processing power?

  • Did they follow the path of motion and determine the closest connecting tile? (a bit of searching) (priori)
  • Did they determine a collision with the floor and then figure out the best way of adjusting the character? (posteriori) This is risky with variable timesteps, you could jump through a tile if you were fast enough. Although I assume NES games timesteps were synced with the tv's refresh rate.
  • Is gravity always affecting your character when you're on the ground? Or do you just 'turn it off' when you're determined to be walking on a tile? What about when you walk off an edge of the cliff? You'd need some sort of way of determining tiles underneath you otherwise.
  • If you've collided with a tile, would you just find the edge of that tile and move your character to the side of it (depending on the direction of travel)?
  • what about sloping tiles like in super metroid and mario?
  • What about 'platforms' where you can jump through the bottom and land on top. How would you deal with collisions with these tiles if you were doing it 'posteriori'?

I have written some collision code that is basically 'priori' as it searches for the first tile you will hit in a certain direction. I'm just wondering if there's a better way. (just using after-the-fact collision detection instead maybe)

eg, code to check for tile collisions for moving downward (I check vert then horizontal movement):

  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

解决方案

For the types of NES-era games you're talking about, everything was 2D. That alone simplifies many things.

Some machines of that era (particularly ones with hardware sprites, like the Commodore 64) had hardware collision detection. Most games that weren't relying on hardware collision detection would either use a bounding box or a hit mask (1-bit bitmap of the sprite).

Either way, collision detection was usually done "a posteriori", except for special cases like the edges of the world. Some games actually did have bugs where moving too fast when you hit something could cause you to pass through it. (In fact, reviews of early 80's games would often comment on how precise the collision detection was.)

For platformers, you'd typically check to see if the character is "grounded" before applying gravity.

The one-way platforms thing isn't too hard to deal with after the fact since you know the sprite's velocity vector, so you can use that to determine whether or not the collision should register.

这篇关于旧游戏如何检测墙壁,地板和天花板的碰撞?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆