도형

Rect, Triangle, Circle, Line, Polyline은 도형 컴포넌트입니다. 엔티티를 생성할 때 하나를 건네주면, 그 엔티티는 파괴될 때까지 매 프레임 그 도형을 그립니다.

from pyxen import *

def start():
    world.spawn(x=110, y=90, shape=Rect(48, 32, fill=(0.4, 0.7, 1.0, 1.0)))
    world.spawn(x=210, y=90, shape=Circle(24, stroke=(1.0, 0.6, 0.3, 1.0), stroke_width=2))

도형은 진짜 엔티티이므로 엔티티가 할 수 있는 모든 것이 그대로 적용됩니다. entity.x와 entity.y로 움직이고, entity.rotation으로 돌리고, 부모를 지정하고, 트윈으로 움직이고, 레이어에 올리고, entity.visible로 숨길 수 있습니다.


도형과 draw 중 무엇을 쓸까

Pyxen은 같은 다섯 가지 기본 도형을 두 가지 방식으로 제공합니다. 화면에서는 똑같아 보이고 차이는 수명뿐입니다. 다른 한쪽은 draw를 참고하세요.

도형 컴포넌트draw
수명엔티티를 파괴할 때까지 유지한 프레임
위치엔티티의 위치·회전·크기직접 전달한 월드 좌표
비용완전한 엔티티(transform, 레이어, 컴포넌트 저장소)프레임 버퍼의 쿼드 몇 개
적합한 용도우주선·벽·고정 UI 같은 게임 객체절차적 도형, 디버그 표시, HUD 막대, 잔상

그것이 게임 속 존재라면 도형 컴포넌트를, 이미 직접 관리하는 값을 그림으로만 표현한다면 draw를 쓰세요.


자주 걸리는 세 가지

도형은 생성할 때 정해지며 이후에는 바꿀 수 없습니다. entity.shape는 존재하지 않고, 읽으려 하면 ValueError: component schema does not exist가 발생합니다. 대입이 가능한 sprite나 text와는 다릅니다. 도형을 바꾸려면 엔티티를 파괴하고 새로 생성하세요.

entity.color로는 도형에 색을 입힐 수 없습니다. 스프라이트에는 적용되지만, 도형은 자신의 fill과 stroke로 그려지며 이를 무시합니다. 색은 도형 자체에 지정하세요.

외곽선 두께 인자의 이름이 두 가지입니다. Rect, Triangle, Circle은 stroke_width를, Line과 Polyline은 width를 받습니다. 의미는 같습니다.


색

모든 색 인자는 각 성분이 0.0~1.0인 (r, g, b, a) 튜플 또는 Color를 받습니다.

Rect(40, 20, fill=(1, 0, 0, 1))        # 불투명한 빨강
Rect(40, 20, fill=(1, 0, 0, 0.35))     # 35% 빨강

fill도 stroke도 없는 도형은 아무것도 그리지 않습니다. 둘 다 완전히 투명한 상태로 시작하므로 Rect(40, 40)은 유효하지만 보이지 않는 엔티티입니다. 여기서 가장 흔한 함정입니다. 둘 다 넘기면 외곽선이 있는 채워진 도형이 됩니다.


타입

Rect(width, height, fill=None, stroke=None, stroke_width=1, pivot=None)

직사각형.

인자타입설명
width, heightfloat크기(픽셀).
fill튜플내부 색. 생략하면 채우지 않습니다.
stroke튜플외곽선 색. 생략하면 그리지 않습니다.
stroke_widthfloat외곽선 두께. 기본값은 1.
pivot튜플엔티티 위치가 가리키는 지점을 도형 내부 픽셀로 지정합니다. 기본값은 모서리이며 (width/2, height/2)면 가운데가 됩니다.

pivot을 가진 도형은 Rect뿐이며, 회전의 중심이기도 합니다.

def start():
    world.spawn(x=110, y=90, shape=Rect(48, 32, fill=(0.4, 0.7, 1.0, 1.0)))
    # 자기 위치를 중심으로 하므로 제자리에서 회전합니다.
    world.spawn(name="spinner", x=210, y=90,
                shape=Rect(48, 32, stroke=(1.0, 0.6, 0.3, 1.0), stroke_width=2,
                           pivot=(24, 16)))

def update():
    world.get(name="spinner").rotation += 0.02

Triangle(x1, y1, x2, y2, x3, y3, fill=None, stroke=None, stroke_width=1)

엔티티 위치를 기준으로 한 세 점을 지나는 삼각형.

인자타입설명
x1, y1, x2, y2, x3, y3float세 꼭짓점. 엔티티로부터의 상대 위치.
fill튜플내부 색. 생략하면 채우지 않습니다.
stroke튜플외곽선 색. 생략하면 그리지 않습니다.
stroke_widthfloat외곽선 두께.
world.spawn(x=160, y=90, shape=Triangle(0, -20, 18, 14, -18, 14, fill=(1, 1, 0.3, 1)))

Circle(radius, fill=None, stroke=None, stroke_width=1, segments=12)

엔티티를 중심으로 하는 원.

인자타입설명
radiusfloat반지름(픽셀).
fill튜플내부 색. 생략하면 채우지 않습니다.
stroke튜플외곽선 색. 생략하면 그리지 않습니다.
stroke_widthfloat외곽선 두께.
segmentsint곡선을 근사하는 직선 분할 수. 기본값은 12.

원은 사실 다각형입니다. 작은 크기에서는 12분할이면 둥글게 보입니다. 큰 원에서는 값을 올리고, 일부러 다각형처럼 보이고 싶다면 낮추세요. segments=6이면 육각형입니다.

world.spawn(x=110, y=90, shape=Circle(28, fill=(0.5, 1.0, 0.7, 1.0), segments=6))
world.spawn(x=210, y=90, shape=Circle(28, fill=(1.0, 0.5, 0.7, 1.0), segments=32))

Line(x1, y1, x2, y2, stroke=None, width=1)

엔티티를 기준으로 한 두 점을 잇는 직선.

인자타입설명
x1, y1float시작점. 엔티티로부터의 상대 위치.
x2, y2float끝점.
stroke튜플선 색.
widthfloat선 두께. stroke_width가 아니라 width입니다.
world.spawn(x=60, y=90, shape=Line(0, 0, 80, -40, stroke=(0.3, 1, 0.5, 1), width=2))

Polyline(points, stroke=None, width=1, closed=False, fill=None)

이어진 선분들의 나열.

인자타입설명
points튜플 또는 FloatBuffer(x1, y1, x2, y2, …) 형태의 평탄한 나열. 좌표 쌍의 목록이 아닙니다.
stroke튜플선 색.
widthfloat선 두께. stroke_width가 아니라 width입니다.
closedboolTrue면 마지막 점을 첫 점과 잇습니다.
fill튜플둘러싸인 영역을 채웁니다. closed=True와 함께 쓸 때 특히 유용합니다.

평탄한 나열인 것은 의도된 설계입니다. FloatBuffer가 이미 이 형태이므로, 한 번 계산한 경로를 다시 만들지 않고 그대로 Polyline에 넘길 수 있습니다.

world.spawn(x=250, y=90,
            shape=Polyline((0, 0, 30, -25, 60, 0), stroke=(1, 0.9, 0.2, 1), width=3))