3 votes

Problème de hitreg de Pymunk

Je veux créer un jeu de flipper mais la balle n'entre pas toujours en collision avec les autres objets. exemple : https://youtu.be/HwSXwJ4-d2w

Voici le code

import pyglet, pymunk
from pymunk.pyglet_util import DrawOptions

win = pyglet.window.Window(1280, 720, resizable=False)
options = DrawOptions()

space = pymunk.Space()
space.gravity = 0, -1000

def Ball(mass, radius, coords):
    circle_moment = pymunk.moment_for_circle(mass, 0, radius)
    circle_body = pymunk.Body(mass, circle_moment)
    circle_shape = pymunk.Circle(circle_body, radius)    
    circle_shape.elasticity = 1.0    
    circle_body.position= coords
    space.add(circle_body, circle_shape)

def BouncyCircle(mass, coords, radius):
    circle_moment = pymunk.moment_for_circle(mass, 0, radius)
    circle_body = pymunk.Body(mass, circle_moment, pymunk.Body.STATIC)
    circle_shape = pymunk.Circle(circle_body, radius)    
    circle_shape.elasticity = 2.0
    circle_body.position= coords
    space.add(circle_body, circle_shape)

def Segment(mass, PointA, PointB, thickness):
    segment_moment = pymunk.moment_for_segment(mass, PointA, PointB, thickness)
    segment_body = pymunk.Body(mass, segment_moment, pymunk.Body.STATIC)
    segment_shape = pymunk.Segment(segment_body, PointA, PointB, thickness)
    segment_shape.elasticity = 0.7
    segment_body.position = 0,0
    space.add(segment_body, segment_shape)

Ball(0.1, 15, (640, 550)) #Falling Ball

BouncyCircle(1, (650,100), 40) #Ball

Segment(10, (105,55), (1195,55), 5) #Border
Segment(10, (100, 50), (100,680), 5)
Segment(10, (105, 675), (1195,675), 5)
Segment(10, (1200, 50), (1200, 680), 5)

@win.event

def on_draw():
    win.clear()
    space.debug_draw(options)

def update(dt):
    space.step(dt)

if __name__ == "__main__":
    pyglet.clock.schedule_interval(update, 1/60)
    pyglet.app.run()

Cela arrive aussi quand il est très lent et parfois il rebondit 10 fois jusqu'à ce qu'il ne fonctionne plus. Quelqu'un sait-il comment le réparer ?

0voto

viblo Points 1577

C'est probablement parce que la balle se déplace trop vite. Si un objet, tel que la balle, se déplace d'un côté à l'autre du mur en une seule étape de simulation (un appel à space.step()), la balle percera le tunnel.

Il existe plusieurs façons d'atténuer ce problème. Parfois, il peut être judicieux d'en utiliser plusieurs.

  1. Veillez à ce que la vitesse des objets ne soit jamais trop élevée. Une façon de le faire est d'utiliser une fonction de vitesse personnalisée avec une limite intégrée sur les corps qui ont tendance à se déplacer trop rapidement :

    def limit_velocity(body, gravity, damping, dt):
        max_velocity = 1000
        pymunk.Body.update_velocity(body, gravity, damping, dt)
        l = body.velocity.length
        if l > max_velocity:
            scale = max_velocity / l
            body.velocity = body.velocity * scale
    
    body_to_limit.velocity_func = limit_velocity
  2. Selon les besoins, il peut être plus judicieux de fixer la vitesse sur plusieurs images. La fonction limite pourrait alors ressembler à ceci :

    def limit_velocity(body, gravity, damping, dt):
        max_velocity = 1000
        pymunk.Body.update_velocity(body, gravity, damping, dt)
        if body.velocity.length > max_velocity:
            body.velocity = body.velocity * 0.99
  3. Utilisez une valeur plus petite pour dt dans l'appel à space.step. Une manière simple est d'appeler space.step plusieurs fois à chaque image dans votre application. Cela contribuera également à rendre la simulation globale plus stable.

Je pense que 1 ou 2 est la meilleure option pour vous.

J'ai mis à jour la documentation de pymunk avec cette explication et un peu plus ici : http://www.pymunk.org/en/latest/overview.html#object-tunneling

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X