collision-detection

collision detection - ¿Cómo hicieron los juegos antiguos la detección de colisiones con paredes, pisos y techos?



collision-detection (3)

Aquí hay un artículo que analiza en profundidad la programación de un "juego de plataforma" de Nintendo Entertainment System (NES).

Puede que no haya estado buscando en Google porque no me he topado con este artículo antes.

He estado leyendo sobre la detección de colisiones en juegos en stackoverflow y otros sitios. Muchos de ellos hablan de BSP, elipses de límites, integración, etc. Sin embargo, en la NES, lograron detectar la colisión en el piso y la pared en los juegos y me cuesta creer que hicieron muchos cálculos para detectar colisiones en la pared.

Supongo que mi pregunta es que, dado un nivel compuesto solo por azulejos, ¿cómo detectaron colisiones con paredes y pisos en juegos como Mario y Megaman que tenían poca capacidad de procesamiento?

  • ¿Siguieron el camino del movimiento y determinaron la baldosa de conexión más cercana? (un poco de búsqueda) (a priori)
  • ¿Determinaron una colisión con el piso y luego descubrieron la mejor manera de ajustar el personaje? (posteriori) Esto es riesgoso con pasos de tiempo variables, podría saltar a través de una ficha si fuera lo suficientemente rápido. Aunque supongo que los tiempos de los juegos de NES se sincronizaron con la frecuencia de actualización de la televisión.
  • ¿La gravedad siempre afecta a tu personaje cuando estás en el suelo? ¿O simplemente lo ''apaga'' cuando está decidido a caminar sobre una baldosa? ¿Qué pasa cuando caminas por un borde del acantilado? Necesitarías algún tipo de manera de determinar las fichas debajo de ti, de lo contrario.
  • Si chocó con una ficha, ¿encontraría el borde de esa ficha y movería a su personaje a un lado (dependiendo de la dirección del viaje)?
  • ¿Qué hay de los azulejos inclinados como en super metroid y mario?
  • ¿Qué pasa con las ''plataformas'' donde puedes saltar a través de la parte inferior y aterrizar en la parte superior? ¿Cómo lidiarías con las colisiones con estos azulejos si lo estuvieras haciendo ''posteriori''?

He escrito un código de colisión que es básicamente ''a priori'', ya que busca la primera ficha que golpearás en cierta dirección. Me pregunto si hay una mejor manera. (simplemente utilizando la detección de colisiones después del hecho, tal vez)

por ejemplo, código para verificar colisiones de azulejos para moverse hacia abajo (verifico vert y luego movimiento horizontal):

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


Para juegos como Super Mario World (SNES), el juego almacenó los niveles en un formato de memoria que facilitó tomar la ubicación X / Y de Mario, convertirla en una dirección de mosaico y luego verificar los mosaicos alrededor de esa dirección. Dado que los niveles siempre tenían un ancho fijo (aunque el área que se podía ver variaba), hacía que el direccionamiento fuera más fácil de manejar ya que siempre era un desplazamiento fijo desde la posición de mario, por ejemplo, Dirección + 1 para el mosaico al lado de Mario, Dirección + 0x300 para el Azulejo debajo de él, etc.


Para los tipos de juegos de la era NES de los que estás hablando, todo era 2D. Eso solo simplifica muchas cosas.

Algunas máquinas de esa era (particularmente las que tienen hardware sprites, como el Commodore 64) tenían detección de colisiones de hardware. La mayoría de los juegos que no confiaban en la detección de colisiones de hardware utilizarían un cuadro delimitador o una máscara de éxito (mapa de bits de 1 bit del sprite).

De cualquier manera, la detección de colisiones generalmente se hacía "a posteriori", excepto en casos especiales como los bordes del mundo. Algunos juegos realmente tenían errores donde moverse demasiado rápido cuando golpeas algo podría hacer que pases a través de ellos. (De hecho, las revisiones de los juegos de principios de los 80 solían comentar sobre la precisión de la detección de colisiones).

Para los plataformas, normalmente verificas si el personaje está "conectado a tierra" antes de aplicar la gravedad.

El tema de las plataformas unidireccionales no es demasiado difícil de tratar después del hecho, ya que conoce el vector de velocidad del sprite, por lo que puede usarlo para determinar si la colisión debe registrarse o no.