Cómo implementar colisiones

Me pueden ayudar a lograr que las figuras se muevan y colisionen entre ellas, estilo Candy Crush

Hola @Lou, ¿podrías abrir un hilo nuevo?, ¿cómo sería estilo Candy Crush?

Deseo que los actores colisionen entre ellos

No se como abrir nuevo hilo, soy nueva
Mi proyecto de la U es crear un código exactamente al del tema, pero no hemos logrado que las figuras colisionen entre mismo actor y ganar puntos.

Ahí pasé el tema a un hilo nuevo!

Bueno, yo nunca hice un juego estilo candy crush… no se si es muy difícil de hacer, encontré algunos videos que muestran como hacer un juego así y tal vez se puedan adaptar para pilas, pero estoy con muy poquito tiempo disponible estos días, lo paso por si les sirve de referencia:

Ahora, por lo que vi, parece que no usan colisiones, sino que detectan qué bloques hay al lado de cada uno de los bloques para saber si se tienen que borrar o no…

¿Queres pasarnos lo que tienen hasta hora hecho @Lou y qué parte de las colisiones no les funcionan?, tal vez con un código iniciado sea más sencillo para nosotros ayudarles un poco.

Abrazo!

Gracias por responder
Con la ayuda del hilo anterior logramos hacer esto:

import pilasengine

pilas = pilasengine.iniciar()

lista_colisionados = []

class EstrellaAmarilla(pilasengine.actores.Actor):
    def iniciar(self):
        self.imagen = 'media/amarillo1.png'
        self.aprender('arrastrable')
        self.aprender('limitadoabordesdepantalla')
        self.radio_de_colision = 40
        self.colisionado = False

pilas.actores.vincular(EstrellaAmarilla)


def detectar(a, b):
    print('colision')
    if a.colisionado == False:
        a.colisionado = True
        b.colisionado = True
        print('pasando a True')
        lista_colisionados.append(a)
        lista_colisionados.append(b)

    else:
        lista_colisionados.append(b)
        for grupo in lista_colisionados:
            grupo.eliminar()


mono_1 = pilas.actores.EstrellaAmarilla()
mono_1.x = pilas.azar(-300, 300)
mono_1.y = pilas.azar(-300, 300)
mono_2 = pilas.actores.EstrellaAmarilla()
mono_2.x = pilas.azar(-300, 300)
mono_2.y = pilas.azar(-300, 300)
mono_3 = pilas.actores.EstrellaAmarilla()
mono_3.x = pilas.azar(-300, 300)
mono_3.y = pilas.azar(-300, 300)

pilas.colisiones.agregar('EstrellaAmarilla', 'EstrellaAmarilla', detectar)

lista_colisionados1 = []

class EstrellaVerde(pilasengine.actores.Actor):
    def iniciar(self):
        self.imagen = 'media/verde1.png'
        self.aprender('arrastrable')
        self.aprender('limitadoabordesdepantalla')
        self.radio_de_colision = 40
        self.colisionado = False

pilas.actores.vincular(EstrellaVerde)


def detectar1(c, d):
    print('colision')
    if c.colisionado == False:
        c.colisionado = True
        d.colisionado = True
        print('pasando a True')
        lista_colisionados1.append(c)
        lista_colisionados1.append(d)

    else:
        lista_colisionados1.append(d)
        for grupo in lista_colisionados1:
            grupo.eliminar()


verde_1 = pilas.actores.EstrellaVerde()
verde_1.x = pilas.azar(-300, 300)
verde_1.y = pilas.azar(-300, 300)
verde_2 = pilas.actores.EstrellaVerde()
verde_2.x = pilas.azar(-300, 300)
verde_2.y = pilas.azar(-300, 300)
verde_3 = pilas.actores.EstrellaVerde()
verde_3.x = pilas.azar(-300, 300)
verde_3.y = pilas.azar(-300, 300)

pilas.colisiones.agregar('EstrellaVerde', 'EstrellaVerde', detectar1)

lista_colisionados2 = []

class EstrellaRosa(pilasengine.actores.Actor):
    def iniciar(self):
        self.imagen = 'media/rosada1.png'
        self.aprender('arrastrable')
        self.aprender('limitadoabordesdepantalla')
        self.radio_de_colision = 40
        self.colisionado = False

pilas.actores.vincular(EstrellaRosa)


def detectar2(e, f):
    print('colision')
    if e.colisionado == False:
        e.colisionado = True
        f.colisionado = True
        print('pasando a True')
        lista_colisionados2.append(e)
        lista_colisionados2.append(f)

    else:
        lista_colisionados2.append(f)
        for grupo in lista_colisionados2:
            grupo.eliminar()


rosada_1 = pilas.actores.EstrellaRosa()
rosada_1.x = pilas.azar(-300, 300)
rosada_1.y = pilas.azar(-300, 300)
rosada_2 = pilas.actores.EstrellaRosa()
rosada_2.x = pilas.azar(-300, 300)
rosada_2.y = pilas.azar(-300, 300)
rosada_3 = pilas.actores.EstrellaRosa()
rosada_3.x = pilas.azar(-300, 300)
rosada_3.y = pilas.azar(-300, 300)

pilas.colisiones.agregar('EstrellaRosa', 'EstrellaRosa', detectar2)

lista_colisionados3 = []

class EstrellaRoja(pilasengine.actores.Actor):
    def iniciar(self):
        self.imagen = 'media/rojo2.png'
        self.aprender('arrastrable')
        self.aprender('limitadoabordesdepantalla')
        self.radio_de_colision = 40
        self.colisionado = False

pilas.actores.vincular(EstrellaRoja)


def detectar3(g, h):
    print('colision')
    if g.colisionado == False:
        g.colisionado = True
        h.colisionado = True
        print('pasando a True')
        lista_colisionados3.append(g)
        lista_colisionados3.append(h)

    else:
        lista_colisionados3.append(h)
        for grupo in lista_colisionados3:
            grupo.eliminar()


roja_1 = pilas.actores.EstrellaRoja()
roja_1.x = pilas.azar(-300, 300)
roja_1.y = pilas.azar(-300, 300)
roja_2 = pilas.actores.EstrellaRoja()
roja_2.x = pilas.azar(-300, 300)
roja_2.y = pilas.azar(-300, 300)
roja_3 = pilas.actores.EstrellaRoja()
roja_3.x = pilas.azar(-300, 300)
roja_3.y = pilas.azar(-300, 300)

pilas.colisiones.agregar('EstrellaRoja', 'EstrellaRoja', detectar3)

lista_colisionados4 = []

class EstrellaMorada(pilasengine.actores.Actor):
    def iniciar(self):
        self.imagen = 'media/morado1.png'
        self.aprender('arrastrable')
        self.aprender('limitadoabordesdepantalla')
        self.radio_de_colision = 40
        self.colisionado = False

pilas.actores.vincular(EstrellaMorada)


def detectar4(i, j):
    print('colision')
    if i.colisionado == False:
        i.colisionado = True
        j.colisionado = True
        print('pasando a True')
        lista_colisionados4.append(i)
        lista_colisionados4.append(j)

    else:
        lista_colisionados4.append(j)
        for grupo in lista_colisionados4:
            grupo.eliminar()


morada_1 = pilas.actores.EstrellaMorada()
morada_1.x = pilas.azar(-300, 300)
morada_1.y = pilas.azar(-300, 300)
morada_2 = pilas.actores.EstrellaMorada()
morada_2.x = pilas.azar(-300, 300)
morada_2.y = pilas.azar(-300, 300)
morada_3 = pilas.actores.EstrellaMorada()
morada_3.x = pilas.azar(-300, 300)
morada_3.y = pilas.azar(-300, 300)

pilas.colisiones.agregar('EstrellaMorada', 'EstrellaMorada', detectar4)

pilas.ejecutar()

Queremos agregar estas primeras pantallas a al código anterior, pero al hacerlo nos da error

import pilasengine
import sys

pilas = pilasengine.iniciar()

"""Definimos cada una de las clases de nuestro juego"""

class EscenaMenu(pilasengine.escenas.Escena):
    def iniciar(self):
        self.pilas.fondos.Fondo('media/logo.png')
        actor_texto = self.pilas.actores.Actor()
        actor_texto.imagen = "media/Inicio.png"
        actor_texto.y=-200
        actor_texto.escala = [0.5]
        self.pilas.eventos.click_de_mouse.conectar(self._iniciar_el_juego)


    def _iniciar_el_juego(self, evento):
        self.pilas.escenas.EscenaUsuario()

class EscenaUsuario(pilasengine.escenas.Escena):
    def iniciar(self):
        fondo1 = self.pilas.fondos.Fondo('media/img.jpg')
        fondo1.escala = [2]
        texto1 = self.pilas.actores.Texto('Ingresa un nombre:')
        texto1.escala = [1.5]
        texto1.y = 200
        self.valor1 = pilas.interfaz.IngresoDeTexto()
        self.valor1.texto = u''
        botonInicio = pilas.interfaz.Boton('Registrar')
        botonInicio.y = -100
        botonInicio.conectar(self.al_pulsar_el_boton)

    def obtener_valor(self, actor_texto):
        return str(actor_texto.texto)

    def al_pulsar_el_boton(self):
        nombre = self.obtener_valor(self.valor1)

        pilas.escenas.EscenaJuego(nombre)


    def _iniciar(self, evento):
        self.pilas.escenas.EscenaJuego()

class EscenaJuego(pilasengine.escenas.Escena):
    def iniciar(self,nombre):
        fondo2 = self.pilas.fondos.Fondo("media/fondo7.jpg")
        fondo2.escala = [2.9]
        texto_inicio = pilas.actores.Actor()
        texto_inicio.imagen = "media/saludo.png"
        texto_inicio.escala = [0.85]
        texto_inicio.y = 110
        texto_nombre = pilas.actores.Texto(nombre)
        texto_nombre.color = pilas.colores.negro
        texto_nombre.y = -50
        texto_nombre.x = -10

        boton = self.pilas.actores.Actor()
        boton.imagen = "media/boton.png"
        boton.x = 200
        boton.y = -150
        boton.escala = [0.2]
        self.pilas.eventos.click_de_mouse.conectar(self._iniciar_el_juego)

    def al_pulsar_el_boton(self):
        pilas.escenas.NivelEASY()

    def _iniciar_el_juego(self, evento):
        self.pilas.escenas.NivelEASY()

class NivelEASY(pilasengine.escenas.Escena):
    def iniciar(self):
        fondo3 = self.pilas.fondos.Fondo("media/fondo4.jpg")
        fondo3.escala = [1]
        indi = self.pilas.actores.Actor()
        indi.imagen = "media/id.png"
        indi.escala = [0.3]
        indi.y = 40
        indi.x = -150

        play = self.pilas.actores.Actor()
        play.imagen = "media/n1.png"
        play.x = 200
        play.y = -150
        self.pilas.eventos.click_de_mouse.conectar(self._iniciar_el_juego)

    def _iniciar_el_juego(self, evento):
        self.pilas.escenas.NivelUno()

Buenas, @Lou!

Hace tiempo estuve intentando también un juego como el que tú quieres hacer y lo dejé a medias, aunque funcionaba bien el detectar si había 3 ó más fichas iguales.

Mi consejo es el mismo que te da @hugoruscitti, y que no uses colisiones, por que al final todas las fichas están colisionando vertical y horizontalmente. Es mejor asignarles un tipo a las fichas y comprobar si hay 3 o más juntas de ese tipo.

Imaginemos que tenemos una fila de 5 fichas creada al azar a partir de 5 tipos diferentes
A B C D E
Entonces tenemos que hacer una función que determine si la ficha en la posición 0(A) tiene el mismo tipo que la ficha 1(B). Como eso es false, entonces se compara la segunda con la tercera © que en este caso sigue dando false. Si la tercera tampoco coincide con la cuarta (D) ya puedes dejar de comparar por que nunca se van a hacer 3 iguales.
Ahora imaginemos otra fila
A A A E B
en este caso la primera se compara con la segunda y da true, igual que la tercera. En la cuarta (E) ya da false y podemos llamar a la función de cambiar las fichas que sí coinciden.

Y sí, he dicho CAMBIAR por que es mejor cambiarle el atributo a la ficha que eliminarla y crear una nueva.
En pseudocódigo seria mas o menos asi:
Si 0,0 == 0,1 == 0,2 -> cambia_tipo(0.0), cambia_tipo(0.1),cambia_tipo(0.2)
El 0 seria la fila, en este caso la primera (porque seguro que querrás un juego con más de una fila), y 0, 1, y 2 la posición de la ficha en la fila.

Este “cambia_tipo” asigna un tipo de manera aleatoria, con lo que ahora la fila sería por ejemplo
E B A E B
y vuelves otra vez a comparar.

Otra manera que vi en su día de hacerlo es usando “patterns”, es decir especificas las combinaciones que se tienen que “cambiar”, y cuando se detecta una en el tablero se llama a la función de cambiar el tipo a las fichas afectadas. La verdad nunca llegué a implementar eso, pero algo me dice que es la manera más comunmente usada.

No sé si te he ayudado o te he liado aún más :sweat_smile:, pero espero como mínimo haberte marcado un camino fácil de plantear tu juego, o al menos lograr que no pierdas tiempo con el tema de las colisiones.

Un saludo! :wink:

YO estoy tratando de implementar la lógica del candy crush en un juego y me está costando, no es nada fácil…Si la Aprendes es la base para cualquier juego parecido…Saludos