Colision mientras pilas.fisica.rectangulo rota

Buenas!

Se me ha metido en mente la idea de crear un “Pinball”, pero me estoy encontrando con varios problemas. El principal es que la pelota no colisiona con el “pin” si está en movimiento (rotando). Habría otra forma de realizar ese movimiento que SI permitiera la colision? :cold_sweat:

Adjunto código de prueba, verán que incluso he intentado con un ciclo “for in” para ver si pasando por cada una de las posiciones si se daba la colisión, pero ni así :tired_face:

Un saludo :wink:

# coding: utf-8
import pilasengine
pilas = pilasengine.iniciar()

recta = pilas.fisica.Rectangulo(0,-160,200,25, plataforma= True)
recta.rotacion = 27

palo1 = pilas.actores.Actor()
palo1.imagen="palo.png"
palo1.imitar(recta)

pelota= pilas.actores.Pelota(y=100)
pelota.aprender('arrastrable')

def al_pulsar_m(tecla):
    if tecla.codigo == "m":
        for i in range(27,-27,-1):
            recta.rotacion=i
        
def al_soltar_m(tecla):
    if tecla.codigo == "m":
        recta.rotacion = 27
    
pilas.eventos.pulsa_tecla.conectar(al_pulsar_m)
pilas.eventos.suelta_tecla.conectar(al_soltar_m)

pilas.ejecutar()

Hola @jordinur !!!

Estuve investigando un poco y logré algo bastante parecido a una paleta de pinball. Resulta que en box2d lo que que se necesita es crear una articulación que al moverse aplique un impulso que represente el movimiento de rotación:

Aun no comprendo muy bien el concepto, pero entiendo que aplicar un cambio de rotación no produce el efecto esperado porque se pierde esa “inercia” del movimiento que podría empujar la pelota.

Te dejo el código, ojalá te sirva!

# coding: utf-8
import pilasengine

pilas = pilasengine.iniciar()

recta = pilas.fisica.Rectangulo(0,0, 200, 25, densidad=0.25)
soporte = pilas.fisica.Circulo(100, 0, 10)
soporte.angle = 0
  
palo1 = pilas.actores.Actor()
palo1.imagen="palo.png"
palo1.imitar(recta)

VELOCIDAD = 40000
PI = 3.1415


soporte._cuerpo.type=0

pelota= pilas.actores.Pelota(x=50, y=100)
pelota.aprender('arrastrable')


articulacion = pilas.fisica.mundo.CreateRevoluteJoint(
    bodyB=recta._cuerpo, 
    bodyA=soporte._cuerpo, 
    anchor=soporte._cuerpo.worldCenter,
    
    lowerAngle = 0.23,
    upperAngle = 0.75 ** 3.14,
    enableLimit = True,
    maxMotorTorque = 8000.0,

    motorSpeed = 5.0,
    enableMotor = True,
)
    

def al_pulsar_m(tecla):
    if tecla.codigo == "m":
        articulacion.motorSpeed = -VELOCIDAD
        
def al_soltar_m(tecla):
    if tecla.codigo == "m":
        articulacion.motorSpeed = VELOCIDAD
    
pilas.eventos.pulsa_tecla.conectar(al_pulsar_m)
pilas.eventos.suelta_tecla.conectar(al_soltar_m)

pilas.ejecutar()

Ah, por cierto, acá hay algunos links que me sirvieron para hacer el ejemplo:

¡Abrazo!

Buenas, Hugo!

Ante todo gracias por tomarte tanta molestia, me doy cuenta de que es un tema que aunque a priori me parecía muy fácil de resolver es en realidad bastante complejo.

Aún ando tratando de entender a fondo ese código… me hubiera gustado que el ángulo de “mando pulsado” fuera un poco más alto para poder retener la bola, pero en todas las pruebas y combinaciones que he realizado el mando se pone a girar como un molino :joy:

De nuevo muchas gracias y un abrazo. Seguiré informando si consigo algún progreso. :wink:

Parece ser que este “problema” de que se sobrepase el “lowerAngle” se ha dado en más casos… Creo entender que la solución seria “rotar” bodyA y bodyB al mismo tiempo? Y como conseguir eso? :cold_sweat:

http://www.box2d.org/forum/viewtopic.php?t=9333

Mmmmm, es cierto… ahí revisé un poco el código y encontré que estabamos multiplicando el angulo por ** 3.14 y debería haber sido simplemente * 3.14, es decir, con un solo signo *

Quedó mucho mejor, igual, con algunos valores muy grandes de velocidad se sale del límite de angulos, no logro entender muy bien por qué.

Fijate si así mejora:

# coding: utf-8
import pilasengine

pilas = pilasengine.iniciar()

ANGULO = -0.0 * 3.1415
VELOCIDAD = 340000
PI = 3.1415


recta = pilas.fisica.Rectangulo(100, 0, 200, 20, densidad=1.0)
recta._cuerpo.bullet = True

soporte = pilas.fisica.Circulo(0, 0, 10, densidad=1.0)
soporte.angle = 0

recta._cuerpo.angle = ANGULO
soporte._cuerpo.angle = ANGULO

palo1 = pilas.actores.Actor()
palo1.imagen="palo.png"
palo1.imitar(recta)




soporte._cuerpo.type=0
#recta._cuerpo.type=0

pelota= pilas.actores.Pelota(x=50, y=100)
pelota.aprender('arrastrable')


articulacion = pilas.fisica.mundo.CreateRevoluteJoint(
    bodyB=recta._cuerpo, 
    bodyA=soporte._cuerpo, 
    anchor=soporte._cuerpo.worldCenter,
    
    lowerAngle = 0.8 * PI,
    upperAngle = 1.15 * PI,
    enableLimit = True,
    maxMotorTorque = 14000.0,

    motorSpeed = VELOCIDAD,
    enableMotor = True,
)
    

def al_pulsar_m(tecla):
    if tecla.codigo == "m":
        articulacion.motorSpeed = -VELOCIDAD
        
def al_soltar_m(tecla):
    if tecla.codigo == "m":
        articulacion.motorSpeed = 0.15 * VELOCIDAD
    
pilas.eventos.pulsa_tecla.conectar(al_pulsar_m)
pilas.eventos.suelta_tecla.conectar(al_soltar_m)


pilas.ejecutar()

Buenas!

Genial!

Yo he estado como 4 horas haciendo todo tipo de pruebas, sin éxito. Al final opté por poner unos “topes” y setear el enableLimit a False, con una tarea en las def pulsa_tecla para volver el mando a su posición original. Pero esta versión que acabas de hacer es infinitamente mejor!

No entiendo que haya mucho de diferente entre este código y el anterior, y sin embargo este funciona y el otro “hacía molino” cuando el mando pasaba por el grado 0 de la rotación. El que hubiera ** no era el motivo, ya que yo he probado de cien maneras diferentes, incluso bajándome ejemplos de Google. Es un misterio, por tanto :disappointed_relieved:

Da risa ver que definiste [quote=“hugoruscitti, post:5, topic:1315”]
ANGULO = -0.0 * 3.1415
[/quote]
y que dando ese valor de ángulo a las dos figuras parece solucionarse el problema :smile:

Tambien veo que has seteado todas las densidades a 1 (que es algo que yo también había probado sin éxito), y que has subido el torque y la velocidad (en mis pruebas sólo se me ocurrió bajarlas).

De nuevo gracias, gracias, y mil gracias.

Un abrazo. :wink: