2017-11-02 3 views
0

Ich habe ein dynamisches Objekt, auf das ich verschiedene Geschwindigkeitswerte setze. Wenn dieser dynamische Körper jedoch auf einen statischen Körper trifft, überschneidet er sich teilweise mit der statischen Form, bis diese Kollision aufgelöst ist und sich zurückbewegt.Pymunk: verhindere, dass sich dynamische Objekte in statische Objekte bewegen

Gibt es einen Weg in pymunk, den dynamischen Körper genau an den Grenzen des statischen Körpers anzuhalten, selbst wenn die Geschwindigkeit in dieser Richtung angewendet wird? Wenn es Kollisionskonflikte gibt, würde ich sie lieber auf eine andere Weise lösen lassen, als die beiden Formen überlappen zu lassen.

Anwenden Kräfte und Impulse sind nicht wirklich eine Option, da ich eine konstante Geschwindigkeit haben möchte.

(Der Code unten muss zweimal ausgeführt werden, arbeiten.)

import pymunk 
import pyglet 
from PIL import Image 
from PIL import ImageDraw 

# setup of pyglet 

window = pyglet.window.Window() 
main_batch = pyglet.graphics.Batch() 
keys = pyglet.window.key.KeyStateHandler() 
window.push_handlers(keys) 

# setup of pymunk 

space = pymunk.Space() 

"""MOVABLE CIRCLE""" 

# creating pyglet sprite 

circle_img = Image.new('RGBA', (50,50)) 
draw = ImageDraw.Draw(circle_img) 
draw.ellipse((1, 1, 50-1, 50-1), fill=(255,0,0)) 
circle_img.save('circle.png') 
pyglet_circle_img = pyglet.resource.image('circle.png') 
pyglet_circle_img.anchor_x = pyglet_circle_img.width/2 
pyglet_circle_img.anchor_y = pyglet_circle_img.height/2 
circle_sprite = pyglet.sprite.Sprite(pyglet_circle_img, window.width/2, window.height/2, batch=main_batch) 

# creating pymunk body and shape 

mass = 2 
radius = 25 
moment = pymunk.moment_for_circle(mass, 0, radius) 
circle_body = pymunk.Body(mass, moment) 
circle_body.position = circle_sprite.position 
circle_shape = pymunk.Circle(circle_body, 25) 
circle_shape.elasticity = 0.0 
space.add(circle_body, circle_shape) 

"""STATIC SQUARE""" 

# creating pyglet sprite 

square_img = Image.new('RGBA', (70,70)) 
draw = ImageDraw.Draw(square_img) 
draw.rectangle([(0, 0), (70-1, 70-1)], fill=(0,255,0)) 
square_img.save('square.png') 
pyglet_square_img = pyglet.resource.image('square.png') 
pyglet_square_img.anchor_x = pyglet_square_img.width/2 
pyglet_square_img.anchor_y = pyglet_square_img.height/2 
square_sprite = pyglet.sprite.Sprite(pyglet_square_img, 3*window.width/4, window.height/2, batch=main_batch) 

# creating pymunk body and shape 

square_body = pymunk.Body(body_type=pymunk.Body.KINEMATIC) 
square_body.position = square_sprite.position 
square_shape = pymunk.Poly(square_body, [(-35,-35),(-35,35),(35,35),(35,-35)]) 
square_shape.elasticity = 0.0 
space.add(square_body, square_shape) 

def update(dt): 
    space.step(dt) 
    circle_sprite.position = circle_body.position 
    print(circle_body.position) 
    key_pressed = False 
    if keys[pyglet.window.key.LEFT]: 
     circle_body.velocity = (-100,0) 
     key_pressed = True 
    elif keys[pyglet.window.key.RIGHT]: 
     circle_body.velocity = (100, 0) 
     key_pressed = True 
    if keys[pyglet.window.key.UP]: 
     circle_body.velocity = (0, 100) 
     key_pressed = True 
    elif keys[pyglet.window.key.DOWN]: 
     circle_body.velocity = (0, -100) 
     key_pressed = True 
    if not key_pressed: 
     circle_body.velocity = (0,0) 

@window.event 
def on_draw(): 
    window.clear() 
    main_batch.draw() 

pyglet.clock.schedule_interval(update, 1/60.) 

pyglet.app.run() 

Antwort

0

Im Allgemeinen ist die Antwort, dass man seltsame Effekte erwarten sollte, wenn Sie die Position oder Geschwindigkeit manuell einen Körper gesetzt, da dieser es Die Physik-Engine austricksen (genau wie man im echten Leben seltsame Effekte bekommen würde, wenn man etwas teleportiert)

Es ist auch der Fall, dass eine kleine Überlappung zu erwarten ist, wenn Objekte kollidieren, so wird die Kollision gelöst. Es gibt zwei Eigenschaften auf dem Speicherplatz, die Sie verwenden können, um dies ein wenig zu steuern, collision_slop und collision_bias.

Sie können jedoch mit einigen manuellen Korrekturen experimentieren, die Ihnen helfen könnten. Ein Weg wäre, die Objekte wegzubewegen, sobald eine Kollision passiert ist. Sie können dies mit einem Kollisionsrückruf tun.

Hier ist ein kurzes Beispiel Sie kurz vor der Update-Funktion in Ihrem Beispiel die Überlappung verhindern setzen können:

circle_shape.collision_type = 1 
h = space.add_wildcard_collision_handler(circle_shape.collision_type) 
def f(arbiter, space, data): 
    ps = arbiter.contact_point_set 
    arbiter.shapes[0].body.position += ps.normal * ps.points[0].distance 
h.post_solve = f 

(in Ihrem realen Code, den Sie für mehr einige scheitern Safes und berücksichtigen auch hinzufügen müssen als ein Punkt, falls Sie komplexere Formen haben)

Verwandte Themen