pyBox2D - Polygone zeichnen

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Benutzeravatar
Don Polettone
User
Beiträge: 115
Registriert: Dienstag 23. November 2010, 20:26
Wohnort: Schweiz

Hi,

Ich spiele mit pyBox2D rum zurzeit. Bälle und Boxen hab ich am Start und die funktionieren wie sie sollen. Ich habe eine kleine Sequenz gecodet, bei der an der Mauscursorposition eine zufälliger Körper erstellt wird wenn man klickt. Um die Körper zu erstellen, habe ich Klassen gecodet wie folgt:

Code: Alles auswählen

import random
from Box2D import b2World, b2_dynamicBody, b2CircleShape, b2PolygonShape
from colours import colour_x

VER = 1.0

###############################################################################
#                                                                             #
#              --- RECENT CHANGES ---                                         #
#                                                                             #
#                                                                             #
#                                                                             #
###############################################################################

###############################################################################
#                                                                             #
#              --- TO DOs ---                                                 #
#                                                                             #
#                                                                             #
#                                                                             #
###############################################################################

######## SETTING THINGS UP #########

def init(resolution, pixels_per_meter, ):
    _set_PPM(pixels_per_meter)
    _set_RES(resolution)

def init_world(g=(0, -10), sleep=True):
    global world
    world = b2World(gravity=g, doSleep=sleep)
    return world
    
def _set_PPM(pixels_per_meter):
    global PPM
    PPM = pixels_per_meter

def _set_RES(resolution):
    global RES
    RES = resolution

def _set_b2world(world):
    global b2world
    b2world = world

####################################

def get_x(b2x):
    x = int(round(b2x * PPM, 3))
    return x

def get_y(b2y):
    y = RES[1] - b2y * PPM
    return int(round(y, 3))

def get_pos(b2pos):
    pos = (get_x(b2pos[0]), get_y(b2pos[1]))
    return pos

def get_b2x(x):
    return x / PPM

def get_b2y(y):
    return (RES[1] - y) / PPM

def get_b2pos(pos):
    return (get_b2x(pos[0]), get_b2y(pos[1]))

class Static_Box():

    def __init__(self, width, height, centerpos, colour=(0, 0, 0)):

        b2_centerpos = get_b2pos(centerpos)
        b2w, b2h = width / PPM / 2.0, height / PPM / 2.0
        
        self.body = world.CreateStaticBody(position=b2_centerpos)
        self.body.CreatePolygonFixture(box=(b2w, b2h))
        self.colour = colour

class Dynamic_Box():                                    

    def __init__(self, width, height, centerpos, colour=None,
                 dens=1, frict=0.5, rest=0.25):

        b2_centerpos = get_b2pos(centerpos)
        b2w, b2h = width / PPM / 2.0, height / PPM / 2.0
        
        self.body = world.CreateDynamicBody(position=b2_centerpos)
        self.body.CreatePolygonFixture(box=(b2w, b2h), density=dens, friction=frict, restitution=rest)
        if not colour:
            self.colour = colour_x(gamma_min=150)
        else:
            self.colour = colour

class Dynamic_Ball():

    def __init__(self, radius, centerpos, colour=None,
                 dens=1, frict=0.5, rest=0.25):

        b2_centerpos = get_b2pos(centerpos)
        
        r = radius / PPM
        self.body = world.CreateDynamicBody(position=b2_centerpos)
        
        circle = b2CircleShape(pos=(0, 0), radius=r)
        ball = self.body.CreateFixture(shape=circle, density=dens, friction=frict, restitution=rest)
        if not colour:
            self.colour = colour_x(gamma_min=150)
        else:
            self.colour = colour

class Dynamic_Polygon():

    def __init__(self, poslist, centerpos, colour=None,
                 dens=1, frict=0.5, rest=0.25):

        b2_centerpos = get_b2pos(centerpos)
        
        self.body = world.CreateDynamicBody(position=b2_centerpos)
        vert = []
        for pos in poslist:
            vert.append(get_b2pos(pos))
        polygon_shape = b2PolygonShape(pos=(0, 0), vertices=vert)
        self.body.CreateFixture(shape=polygon_shape, density=dens, friction=frict, restitution=rest)
        if not colour:
            self.colour = colour_x(gamma_min=150)
        else:
            self.colour = colour

class Revolute_Joint():

    def __init__(self, body_a, body_b, pos):

        b2pos = get_b2pos(pos)
        world.CreateRevoluteJoint(bodyA=body_a, bodyB=body_b, anchor=b2pos)
        
Dies ist soweit meine eigene Extension für Pygame und pyBox2D, damit ich einfach Positionen umrechnen kann etc. Der Code, welcher im Hauptscript die Körper erstellt, sieht wie folgt aus:

Code: Alles auswählen

    def update_bodies(self):

        obj_type = random.randint(0, 2)
        if obj_type == 0:
            method = self.make_box
        elif obj_type == 1:
            method = self.make_ball
        else:
            method = self.make_car

        if RIGHT_BUTTON in self.mouse.pressed:
            method()
            return
        if MID_BUTTON in self.mouse.pressed:
            self.mouse.ready = False
            self.del_all_bodies()
            return
        if self.mouse.ready and LEFT_BUTTON in self.mouse.pressed:
            self.mouse.ready = False
            method()

Code: Alles auswählen

    def make_ball(self):

        r = random.randint(10, 35)
        self.b2objects.append(Dynamic_Ball(r, self.mouse.pos, rest=0.8))

    def make_box(self):

        w_min = h_min = 10
        w_max = h_max = 50
        w = random.randint(w_min, w_max)
        h = random.randint(h_min, h_max)
        self.b2objects.append(Dynamic_Box(w, h, self.mouse.pos))

    def make_polygon(self):

        poslist = ((0, 0), (0, 20), (73, 20), (73, 13), (66, 8), (36, 0))
        self.b2objects.append(Dynamic_Polygon(poslist, self.mouse.pos))
Wenn es einen Ball oder eine Box erstellt, werden diese an der Mauscursorposition initiiert, wie vorgesehen. Wenn aber ein Polygon erstellt wird, sehe ich erstmal nichts, dann irgendwann fällt das Polygon ins Bild von oben. Die y pos stimmt also schon mal nicht. auch x stimmt nicht genau; das Polygon ist linksbündig mit dem Mauscursor; es sollte aber mittig erstellt werden? Ich verstehe nicht, wieso das so ist, da ich ja immer dasselbe mache eigentlich.

Jemand eine Idee?

Vielen Dank und Gruss,


Henry
Ich code, also bin ich.
Benutzeravatar
Don Polettone
User
Beiträge: 115
Registriert: Dienstag 23. November 2010, 20:26
Wohnort: Schweiz

habs rausgefunden. Zum einen hab ich die vertices falsch umgerechnet für die shape (da sind die Koordinaten ja nicht abhängig vom Bildschirmrand!), zum anderen hatte ich nicht bedacht, dass shapes ja abhängig von der Bodyposition erstellt werden (man muss immer von der Mitte ausgehen). Ein kleines Dreieck zum Beispiel mittig zum Body könnte so aussehen:

Code: Alles auswählen

    def make_triangle(self):

        poslist = ((-1, -5), (-6, 5), (5, 5))
        self.b2objects.append(Dynamic_Polygon(poslist, self.mouse.pos))
eben vom Nullpunkt aus her gesehen; drum auch teils mit negativen Koordinaten.

Code: Alles auswählen

class Dynamic_Polygon():

    def __init__(self, poslist, centerpos, colour=None,
                 dens=1, frict=0.5, rest=0.25):

        b2_centerpos = get_b2pos(centerpos)
        self.body = world.CreateDynamicBody(position=b2_centerpos)
        vert = [(v[0] / PPM, v[1] / PPM) for v in poslist]
        polygon_shape = b2PolygonShape(vertices=vert)
        self.body.CreateFixture(shape=polygon_shape, density=dens, friction=frict, restitution=rest)
        if not colour:
            self.colour = colour_x(gamma_min=150)
        else:
            self.colour = colour
Evtl hilft dies ja jemand auf die Sprünge der dasselbe Problem hat? Ich bin jetzt auf jeden happy mal. Cheers

Henry
Ich code, also bin ich.
Antworten