Buenisimo @jetspydragon, lo que se me ocurre que te podría servir es usar el atributo “figuras_en_contacto” que tienen las figuras físicas. El atributo “figuras_en_contacto” es una lista que se carga automáticamente cada vez que una figura colisiona con otra.
Por ejemplo, mirando tu código se me ocurrió esto: en el método actualizar el actor se mueve incrementando las posiciones x e y, lo que se podría hacer ahí es revertir el movimiento si el actor ingresa en una colisión con un obstáculo:
import pilasengine
pilas = pilasengine.iniciar()
pilas.fondos.Color(pilas.colores.negro)
class Room(pilasengine.actores.Actor):
def iniciar(self):
#self.imagen = 'assets/room.png'
self.escala = .45
self.etiquetas.agregar("obstaculo")
self.figura_de_colision = None
self.limites = {
"arriba": self.pilas.fisica.Rectangulo(0, 0, 600, 20, sensor = True, dinamica = False),
"abajo": self.pilas.fisica.Rectangulo(0, 0, 600, 20, sensor = True, dinamica = False),
"derecha": self.pilas.fisica.Rectangulo(0, 0, 20, 300, sensor = True, dinamica = False),
"izquierda": self.pilas.fisica.Rectangulo(0, 0, 20, 300, sensor = True, dinamica = False)
}
self.limites["arriba"].etiquetas.agregar("obstaculo")
self.limites["abajo"].etiquetas.agregar("obstaculo")
self.limites["derecha"].etiquetas.agregar("obstaculo")
self.limites["izquierda"].etiquetas.agregar("obstaculo")
def actualizar(self):
self.limites["arriba"].y = 160
self.limites["abajo"].y = -160
self.limites["derecha"].x = 300
self.limites["izquierda"].x = -300
class Isaac(pilasengine.actores.Actor):
def iniciar(self):
self.velocidadx = 0
self.velocidady = 0
#self.imagen = 'assets/Isaac.png'
self.imagen = "mono.png"
self.escala = .25
self.etiquetas.agregar('jugador')
self.figura_de_colision = None
self.figura_de_colision_pie = pilas.fisica.Rectangulo(0, 0, 30, 10, sensor = True, dinamica = False)
self.figura_de_colision_pie.etiquetas.agregar("jugador")
self.pilas.eventos.pulsa_tecla.conectar(self.al_pulsar_tecla)
self.pilas.eventos.suelta_tecla.conectar(self.al_soltar_tecla)
#self.pilas.colisiones.agregar("jugador", "obstaculo", self.al_tocar_obstaculo)
def actualizar(self):
# Posicion
self.x += self.velocidadx
self.y += self.velocidady
# Figura de colision
self.figura_de_colision_pie.x = self.x
self.figura_de_colision_pie.y = self.y - 16
## Si colisiona con alguna figura
if self.figura_de_colision_pie.figuras_en_contacto:
primer_figura = self.figura_de_colision_pie.figuras_en_contacto[0]
es_obstaculo = 'obstaculo' in primer_figura.etiquetas.lista
if es_obstaculo:
self.y -= self.velocidady
self.x -= self.velocidadx
def al_pulsar_tecla(self, evento):
if evento.codigo == pilas.simbolos.DERECHA:
self.velocidadx = 2
elif evento.codigo == pilas.simbolos.IZQUIERDA:
self.velocidadx = -2
if evento.codigo == pilas.simbolos.ARRIBA:
self.velocidady = 2
elif evento.codigo == pilas.simbolos.ABAJO:
self.velocidady = -2
def al_soltar_tecla(self, evento):
if evento.codigo == pilas.simbolos.DERECHA:
self.velocidadx = 0
elif evento.codigo == pilas.simbolos.IZQUIERDA:
self.velocidadx = 0
if evento.codigo == pilas.simbolos.ARRIBA:
self.velocidady = 0
elif evento.codigo == pilas.simbolos.ABAJO:
self.velocidady = 0
#def al_tocar_obstaculo(self, jugador, obstaculo):
# print("colision")
# jugador.velocidadx = 0
# jugador.velocidady = 0
pilas.actores.vincular(Room)
pilas.actores.vincular(Isaac)
pilas.actores.Room()
pilas.actores.Isaac()
pilas.ejecutar()
Lo único malo de este enfoque es que el actor queda “bloqueado” al hacer una diagonal. Bah, la colisión le impide ir en diagonal.
Para corregir una opción es separar los obstáculos verticales de los horizontales usando etiquetas, y al momento de detectar una colisión con el obstáculo solo revertir el eje que corresponda.
Mirá esta otra versión, es mucho más interesante el movimiento que hace el personaje cuando entra en contacto con la pared en diagonal:
import pilasengine
pilas = pilasengine.iniciar()
pilas.fondos.Color(pilas.colores.gris)
class Room(pilasengine.actores.Actor):
def iniciar(self):
#self.imagen = 'assets/room.png'
self.escala = .45
self.etiquetas.agregar("obstaculo")
self.figura_de_colision = None
self.limites = {
"arriba": self.pilas.fisica.Rectangulo(0, 0, 600, 20, sensor = True, dinamica = False),
"abajo": self.pilas.fisica.Rectangulo(0, 0, 600, 20, sensor = True, dinamica = False),
"derecha": self.pilas.fisica.Rectangulo(0, 0, 20, 300, sensor = True, dinamica = False),
"izquierda": self.pilas.fisica.Rectangulo(0, 0, 20, 300, sensor = True, dinamica = False)
}
self.limites["arriba"].etiquetas.agregar("obstaculo")
self.limites["abajo"].etiquetas.agregar("obstaculo")
self.limites["derecha"].etiquetas.agregar("obstaculo")
self.limites["izquierda"].etiquetas.agregar("obstaculo")
self.limites["arriba"].etiquetas.agregar("horizontal")
self.limites["abajo"].etiquetas.agregar("horizontal")
self.limites["derecha"].etiquetas.agregar("vertical")
self.limites["izquierda"].etiquetas.agregar("vertical")
def actualizar(self):
self.limites["arriba"].y = 160
self.limites["abajo"].y = -160
self.limites["derecha"].x = 300
self.limites["izquierda"].x = -300
class Isaac(pilasengine.actores.Actor):
def iniciar(self):
self.velocidadx = 0
self.velocidady = 0
#self.imagen = 'assets/Isaac.png'
self.imagen = "mono.png"
self.escala = .25
self.etiquetas.agregar('jugador')
self.figura_de_colision = None
self.figura_de_colision_pie = pilas.fisica.Rectangulo(0, 0, 30, 10, sensor = True, dinamica = False)
self.figura_de_colision_pie.etiquetas.agregar("jugador")
self.pilas.eventos.pulsa_tecla.conectar(self.al_pulsar_tecla)
self.pilas.eventos.suelta_tecla.conectar(self.al_soltar_tecla)
#self.pilas.colisiones.agregar("jugador", "obstaculo", self.al_tocar_obstaculo)
def actualizar(self):
# Posicion
self.x += self.velocidadx
self.y += self.velocidady
# Figura de colision
self.figura_de_colision_pie.x = self.x
self.figura_de_colision_pie.y = self.y - 16
## Si colisiona con alguna figura
if self.figura_de_colision_pie.figuras_en_contacto:
primer_figura = self.figura_de_colision_pie.figuras_en_contacto[0]
es_obstaculo = 'obstaculo' in primer_figura.etiquetas.lista
es_vertical = 'vertical' in primer_figura.etiquetas.lista
es_horizontal = 'horizontal' in primer_figura.etiquetas.lista
if es_obstaculo:
if es_horizontal:
self.y -= self.velocidady
if es_vertical:
self.x -= self.velocidadx
def al_pulsar_tecla(self, evento):
if evento.codigo == pilas.simbolos.DERECHA:
self.velocidadx = 2
elif evento.codigo == pilas.simbolos.IZQUIERDA:
self.velocidadx = -2
if evento.codigo == pilas.simbolos.ARRIBA:
self.velocidady = 2
elif evento.codigo == pilas.simbolos.ABAJO:
self.velocidady = -2
def al_soltar_tecla(self, evento):
if evento.codigo == pilas.simbolos.DERECHA:
self.velocidadx = 0
elif evento.codigo == pilas.simbolos.IZQUIERDA:
self.velocidadx = 0
if evento.codigo == pilas.simbolos.ARRIBA:
self.velocidady = 0
elif evento.codigo == pilas.simbolos.ABAJO:
self.velocidady = 0
#def al_tocar_obstaculo(self, jugador, obstaculo):
# print("colision")
# jugador.velocidadx = 0
# jugador.velocidady = 0
pilas.actores.vincular(Room)
pilas.actores.vincular(Isaac)
pilas.actores.Room()
pilas.actores.Isaac()
pilas.ejecutar()
Por último, las zonas en donde se forman esquinas horizontales se produce un efecto raro… porque en ese instante el protagonista va a estar colisionando con dos obstáculos al mismo tiempo. Lo ideal es chequear todas las colisiones juntas, probá con un método actualizar como este si llega a ser un caso para tu juego:
def actualizar(self):
# Posicion
self.x += self.velocidadx
self.y += self.velocidady
# Figura de colision
self.figura_de_colision_pie.x = self.x
self.figura_de_colision_pie.y = self.y - 16
## Si colisiona con alguna figura
if self.figura_de_colision_pie.figuras_en_contacto:
for figura in self.figura_de_colision_pie.figuras_en_contacto:
es_obstaculo = 'obstaculo' in figura.etiquetas.lista
es_vertical = 'vertical' in figura.etiquetas.lista
es_horizontal = 'horizontal' in figura.etiquetas.lista
if es_obstaculo:
if es_horizontal:
self.y -= self.velocidady
if es_vertical:
self.x -= self.velocidadx
Abrazo!!!
PD: como no tenía las imágenes del juego no me quedó otra que volver a poner al actor del monito de nuevo…
PD 2: Ah, por cierto, seguramente te va a servir agregarle una figura de colisión adicional al actor, por si colisiona con otro tipo de objetos. Mirá el ejemplo de plataformas de pilas, es un buen ejemplo de un actor con figuras de colisión mixtas: