Como detectar una "descolision" entre distintos actores [SOLUCIONADO]

Hola, necesito ayuda con mi juego, necesito saber como detectar cuando dos actores descolisionan y no se me ocurre como :frowning:

Gracias por leer.

1 Like

No me sirve para lo que quiero hacer :frowning:

Estoy intentando crear un juego de plataformas, y tengo 2 problemas:

  1. Puedes caminar en el vacio, pero si salta, funciona la gravedad y pierdes, tendria que hacer que cuando el protagonista descolisiona con la plataforma, la gravedad se pondria en true, pero con el post que me pasaste no pude decifrar como hacerlo y creo que con eso no se puede.
  2. Te puedes meter dentro de la plataforma si colisionas con ella desde otro lugar que no sea la superficie.

Link de las texturas:
https://drive.google.com/open?id=1lbXfrzi44wvYvjRJvyK8zLwRDdBkgGen

Codigo:

# coding: utf-8
import pilasengine

pilas = pilasengine.iniciar()

class Heroe(pilasengine.actores.Actor):
    def iniciar(self):
        teclas1 = {pilas.simbolos.IZQUIERDA:'izquierda',pilas.simbolos.ARRIBA:'arriba', pilas.simbolos.ABAJO:'abajo',pilas.simbolos.DERECHA:'derecha', pilas.simbolos.l:'boton'}
        self.controlnave2 = pilas.control.Control(teclas1)
        self.aprender(pilas.habilidades.MoverseConElTeclado, control=self.controlnave2)
        self.imagen = pilas.imagenes.cargar("pla/e.png")
        self.escala = 0.5
        self.grav=True
        self.tu=False
        self.radio_de_colision=24
    def actualizar(self):
        if self.grav:
            self.y -=5.5
        if self.controlnave2.arriba:
            self.y -=4
        if self.controlnave2.abajo:
            self.y +=4
        if self.controlnave2.derecha:
            self.espejado=False
        if self.controlnave2.izquierda:
            self.espejado=True
        
class Plat(pilasengine.actores.Actor):
    def iniciar(self):
        self.imagen = pilas.imagenes.cargar("pla/ee.png")
        self.escala = 0.5
        self.hitbox=pilas.fisica.Rectangulo(0,0,160,40)
        self.figura_de_colision=self.hitbox

class Escena(pilasengine.escenas.Escena):
    def iniciar(self):
        self.fondo = pilas.fondos.Blanco()
        self.heroe = pilas.actores.Heroe()
        self.plat1 = pilas.actores.Plat()
        self.plat1.y = -150
        self.plat2 = pilas.actores.Plat()
        self.plat2.y = -150
        self.plat2.x = -225
        pilas.eventos.pulsa_tecla.conectar(self.al_pulsar_tecla)
        self.pilas.colisiones.agregar('Plat','Heroe',self.asd)
    def asd(self):
        self.heroe.grav=False
    def al_pulsar_tecla(self, tecla):
        if tecla.codigo=="z" and self.heroe.grav==False:
            self.heroe.tu=True
            pilas.tareas.una_vez(0.21, self.asd2)
    def asd2(self):
        self.heroe.grav=True
        self.heroe.tu=False
    def actualizar(self):
        if self.heroe.tu:
            self.heroe.y +=6

pilas.actores.vincular(Heroe)
pilas.actores.vincular(Plat)
pilas.escenas.vincular(Escena)
pilas.escenas.Escena()
pilas.ejecutar()

Principalmente quisiera saber como detectar una descolision entre la plataforma y el protagonista, intentare fijarme en el post que me pasaste denuevo, pero creo que no me sirve o no lo entendi.
Despues me gustaria saber como hacer que la figura de colision no este en el centro, sino un poco mas por encima o a un costado, algo asi (no funciona):

self.hitbox=pilas.fisica.Rectangulo(self.x,self.y+20,250,50)
self.figura_de_colision=self.hitbox

Hola @Pan, es cierto lo que comenta @jordinur, podrías usar ese concepto de “figuras_en_contacto” para detectar en qué momento el actor deja de colisionar con una plataforma. Pero agrego algo más, en los juegos de plataformas muchas veces se construye una segunda figura de colisión tipo sensor para detectar plataformas, algo así:

Me tomé el atrevimiento de modificar un poco tu código para cambiar la lógica de colisiones y e integrar ese sensor. Creo que quedó bastante bien:

# coding: utf-8
import pilasengine

pilas = pilasengine.iniciar()


class Heroe(pilasengine.actores.Actor):
    def iniciar(self):
        teclas1 = {pilas.simbolos.IZQUIERDA:'izquierda',pilas.simbolos.ARRIBA:'arriba', pilas.simbolos.ABAJO:'abajo',pilas.simbolos.DERECHA:'derecha', pilas.simbolos.l:'boton'}
        self.controlnave2 = pilas.control.Control(teclas1)
        self.aprender(pilas.habilidades.MoverseConElTeclado, control=self.controlnave2)
        self.imagen = pilas.imagenes.cargar("pla/e.png")
        self.escala = 0.5
        self.grav=True
        self.tu=False
        self.radio_de_colision=24
        
        
        ## Nuevo: colocamos un sensor para detectar si esta en contacto con una plataforma.
        self.sensor_en_los_pies = pilas.fisica.Rectangulo(self.x, self.y, 20, 5, sensor=True, dinamica=False)
        
    ## Nuevo: creamos un metodo para poder consultar si esta tocando una platafoma o no.
    def esta_pisando_el_suelo(self):
        return len(self.sensor_en_los_pies.figuras_en_contacto) > 0

        
    def actualizar(self):
        if self.grav:
            self.y -=5.5
        if self.controlnave2.arriba:
            self.y -=4
        if self.controlnave2.abajo:
            self.y +=4
        if self.controlnave2.derecha:
            self.espejado=False
        if self.controlnave2.izquierda:
            self.espejado=True
        
        
        ## Nuevo: si esta bajando, intenta consultar si toca una plataforma
        if self.esta_pisando_el_suelo():
            #self.decir("uff, pise suelo firme")
            self.grav = False
        else:
            if not self.grav and not self.tu: # Si esta en reposo, es porque debe empezar a caer
                self.grav = True
                
            
        ## Nuevo: El sensor es un objeto independiente, asi que tenemos que moverlo para que siga al actor
        self.sensor_en_los_pies.x = self.x
        self.sensor_en_los_pies.y = self.y - 30
        
class Plat(pilasengine.actores.Actor):
    def iniciar(self):
        self.imagen = pilas.imagenes.cargar("pla/ee.png")
        self.escala = 0.5
        self.hitbox=pilas.fisica.Rectangulo(0,0,160,40)
        self.figura_de_colision=self.hitbox

class Escena(pilasengine.escenas.Escena):
    def iniciar(self):
        self.fondo = pilas.fondos.Blanco()
        self.heroe = pilas.actores.Heroe()
        self.plat1 = pilas.actores.Plat()
        self.plat1.y = -150
        self.plat2 = pilas.actores.Plat()
        self.plat2.y = -150
        self.plat2.x = -225
        pilas.eventos.pulsa_tecla.conectar(self.al_pulsar_tecla)
        #self.pilas.colisiones.agregar('Plat','Heroe',self.asd)
        # Nuevo:
        self.pilas.fisica.eliminar_suelo()
    #def asd(self):
        #self.heroe.grav=False
    def al_pulsar_tecla(self, tecla):
        if tecla.codigo=="z" and self.heroe.grav==False:
            self.heroe.tu=True
            pilas.tareas.una_vez(0.21, self.asd2)
    def asd2(self):
        self.heroe.grav=True
        self.heroe.tu=False
    def actualizar(self):
        if self.heroe.tu:
            self.heroe.y +=6

pilas.actores.vincular(Heroe)
pilas.actores.vincular(Plat)
pilas.escenas.vincular(Escena)
pilas.escenas.Escena()
pilas.ejecutar()

Por cierto, en los ejemplos de pilas hay un ejemplo llamado plataformas, usa una técnica similar a la que te mencioné aquí, con un sensor, pero además usa el motor de física. Tal vez puedas tomar algo de ahí también.

Saludos!

1 Like

Gracias, me funciono, e hice una plataforma mas para hacer mejor la colision:

# coding: utf-8
import pilasengine

pilas = pilasengine.iniciar()

class Heroe(pilasengine.actores.Actor):
    def iniciar(self):
        teclas1 = {pilas.simbolos.IZQUIERDA:'izquierda',pilas.simbolos.ARRIBA:'arriba', pilas.simbolos.ABAJO:'abajo',pilas.simbolos.DERECHA:'derecha', pilas.simbolos.l:'boton'}
        self.controlnave2 = pilas.control.Control(teclas1)
        self.aprender(pilas.habilidades.MoverseConElTeclado, control=self.controlnave2)
        self.imagen = pilas.imagenes.cargar("pla/e.png")
        self.escala = 0.5
        self.grav=True
        self.tu=False
        self.radio_de_colision=20
        self.sensor_en_los_pies = pilas.fisica.Rectangulo(self.x, self.y, 20, 5, sensor=True, dinamica=False)
    def esta_pisando_el_suelo(self):
        return len(self.sensor_en_los_pies.figuras_en_contacto) > 0
    def actualizar(self):
        if self.grav:
            self.y -=5.5
        if self.controlnave2.arriba:
            self.y -=4
        if self.controlnave2.abajo:
            self.y +=4
        if self.controlnave2.derecha:
            self.espejado=False
        if self.controlnave2.izquierda:
            self.espejado=True
        if self.esta_pisando_el_suelo():
            self.grav = False
        else:
            if not self.grav and not self.tu:
                self.grav = True
        self.sensor_en_los_pies.x = self.x
        self.sensor_en_los_pies.y = self.y - 23
        
class Plat(pilasengine.actores.Actor):
    def iniciar(self):
        self.imagen = pilas.imagenes.cargar("pla/ee.png")
        self.escala = 0.5
            
class Plat2(pilasengine.actores.Actor):
    def iniciar(self):
        self.imagen = pilas.imagenes.cargar("pla/ee.png")
        self.transparencia=100
        self.escala = 0.5
        self.hitbox=pilas.fisica.Rectangulo(0,0,155,5)
        self.figura_de_colision=self.hitbox

class Escena(pilasengine.escenas.Escena):
    def iniciar(self):
        self.fondo = pilas.fondos.Blanco()
        self.heroe = pilas.actores.Heroe()
        self.plat1 = pilas.actores.Plat()
        self.plat1.y = -150
        self.plat2 = pilas.actores.Plat()
        self.plat2.y = -150
        self.plat2.x = -225
        self.plat3 = pilas.actores.Plat()
        self.plat3.y = -150
        self.plat3.x = 250
        self.plat4 = pilas.actores.Plat()
        self.plat4.y = -65
        self.plat4.x = 350
        self.plat12 = pilas.actores.Plat2()
        self.plat22 = pilas.actores.Plat2()
        self.plat32 = pilas.actores.Plat2()
        self.plat42 = pilas.actores.Plat2()
        pilas.eventos.pulsa_tecla.conectar(self.al_pulsar_tecla)
        self.pilas.fisica.eliminar_suelo()
        self.choque=False
    def asd(self):
        self.choque=True
        pilas.avisar("choque")
    def al_pulsar_tecla(self, tecla):
        if tecla.codigo=="z" and self.heroe.grav==False:
            self.heroe.tu=True
            pilas.tareas.una_vez(0.25, self.asd2)
    def asd2(self):
        self.heroe.grav=True
        self.heroe.tu=False
    def actualizar(self):
        self.plat12.y = self.plat1.y + 17
        self.plat22.y = self.plat2.y + 17
        self.plat22.x = self.plat2.x
        self.plat32.y = self.plat3.y + 17
        self.plat32.x = self.plat3.x
        self.plat42.y = self.plat4.y + 17
        self.plat42.x = self.plat4.x
        if self.heroe.tu:
            if not self.choque:
                self.heroe.y +=6

pilas.actores.vincular(Heroe)
pilas.actores.vincular(Plat)
pilas.actores.vincular(Plat2)
pilas.escenas.vincular(Escena)
pilas.escenas.Escena()
pilas.ejecutar()

Gracias por la ayuda @jordinur y @hugoruscitti