[Python] pyBox2D 사용 예제 - 4. pyGame + Box2D 기본 예제 (1)


pyGame에 pyBox2D를 결합한 첫번째 예제 코드입니다.
import pygame
from pygame.locals import *
from Box2D import *
from Box2D.b2 import *

SCREEN_WD = 400
SCREEN_HT = 400
TARGET_FPS = 60
PPM = 20.0

screen = pygame.display.set_mode((SCREEN_WD, SCREEN_HT), 0, 32)
pygame.display.set_caption("PyBox2D_Example")
clock = pygame.time.Clock()

world = b2World(gravity = (0, -10), doSleep = True)

ground1BodyDef = b2BodyDef()
ground1BodyDef.position.Set(0, 1)
ground1Body = world.CreateBody(ground1BodyDef)
ground1Shape = b2PolygonShape()
ground1Shape.SetAsBox(50, 5)
ground1Body.CreateFixture(shape = ground1Shape)

box1BodyDef = b2BodyDef()
box1BodyDef.type = b2_dynamicBody
box1BodyDef.position.Set(10, 15)
box1Body = world.CreateBody(box1BodyDef)
box1Shape = b2PolygonShape()
box1Shape.SetAsBox(2, 1)
box1FixtureDef = b2FixtureDef()
box1FixtureDef.shape = box1Shape
box1FixtureDef.density = 1
box1FixtureDef.friction = 0.3
box1Body.CreateFixture(box1FixtureDef)

timeStep = 1.0 / 60
velIters = 10
posIters = 10

colors = {
    staticBody  : (255,255,255,255),
    dynamicBody : (127,127,127,255),
}

running = True
while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
            continue
        if event.type == KEYDOWN and event.key == K_ESCAPE:
            running = False
            continue

    screen.fill((0, 0, 0, 0))

    for body in (ground1Body, box1Body):
        for fixture in body.fixtures:
            shape = fixture.shape
            vertices = [(body.transform * v) * PPM for v in shape.vertices]
            vertices = [(v[0], (SCREEN_HT - v[1])) for v in vertices]
            pygame.draw.polygon(screen, colors[body.type], vertices)
                     
    world.Step(timeStep, velIters, posIters)
    pygame.display.flip()
    clock.tick(TARGET_FPS)

pygame.quit()
print("done")
전반적으로는 앞서 두개의 예제가 합쳐진 것이라고 볼 때 크게 다르지 않습니다.


주의할 부분은 Box2d의 객체들을 화면으로 그려주는 부분인데,


생성된 지면과 박스의 body 객체 각각에 대해 처리하도록 하면서,
    for body in (ground1Body, box1Body):
body 객체에 연결된 모든 fixture 객체에 대해 처리하도록 합니다.
    for fixture in body.fixtures:
fixture 객체에 연결된 shape 객체를 가져옵니다.
    shape = fixture.shape
Shape 객체 내의 정점 집합에 대해 body 객체 자체의 확대 배율(body.transform)과 미터당 포인트 비율(Point Per Meter, PPM)을 곱하여(Box2D 내부의 좌표 체계는 미터로 되어있음), 결과 또한 집합으로 얻습니다.
    vertices = [(body.transform * v) * PPM for v in shape.vertices]
Box2D 좌표계 상의 Y좌표는 위로 갈수록 커지고, pyGame 좌표계 상의 Y좌표는 아래로 갈수록 커지므로 이를 보정해줍니다. (v[0] : X 좌표, v[1] : Y좌표)
    vertices = [(v[0], (SCREEN_HT - v[1])) for v in vertices]
마지막으로 최종적으로 구해진 좌표 집합으로 polygon을 그리는데, 타입이 static이냐 dynamic이냐에 따라 다른 색으로 그려줍니다.
    pygame.draw.polygon(screen, colors[body.type], vertices)
,