스프라이트 및 렌더링

Pyxen은 Metal 기반 2D 렌더러를 사용하여 게임을 렌더링합니다. 화면에 보이는 모든 것은 Sprite 컴포넌트를 가진 엔티티입니다.

스프라이트

스프라이트는 엔진에 엔티티를 위해 무엇을 그릴지 알려줍니다. 프로젝트의 이미지를 참조하여 생성합니다:

player = world.spawn(sprite=Sprite("hero"))

문자열 "hero"는 프로젝트 에셋에 있는 hero라는 이미지를 참조합니다.

타일 시트

대부분의 게임은 타일 시트 — 그리드에 배열된 여러 프레임이나 타일을 포함하는 단일 이미지 — 를 사용합니다. tile 매개변수로 이미지의 영역을 선택합니다:

Sprite("characters", tile=(0, 0, 16, 16))    # 첫 번째 타일
Sprite("characters", tile=(16, 0, 16, 16))   # 두 번째 타일
Sprite("characters", tile=(0, 16, 16, 16))   # 두 번째 행의 타일

네 값은 이미지의 좌상단에서 측정한 (x, y, width, height) 픽셀 단위입니다.

스프라이트 애니메이션

스프라이트 에디터에서 이름 있는 애니메이션을 만들면 직접 재생할 수 있습니다:

player = world.spawn(
    sprite=Sprite("hero", animation="walk"),
    x=100, y=50
)

엔진이 스프라이트 메타데이터에서 애니메이션의 프레임 시퀀스와 FPS를 읽고 프레임을 자동으로 진행합니다. 애니메이션을 전환하려면 새 스프라이트를 할당합니다:

player.sprite = Sprite("hero", animation="jump")

한 번만 재생되는 애니메이션(공격이나 사망 등)은 loop=False로 설정하고 완료를 확인합니다:

player.sprite = Sprite("hero", animation="attack", loop=False)

def update():
    if player.animation and player.animation.finished:
        player.sprite = Sprite("hero", animation="idle")

e.animation 컴포넌트를 통해 현재 상태에 읽기 전용으로 접근할 수 있습니다: .name, .frame, .playing, .finished. 자세한 내용은 Entity 레퍼런스를 참조하세요.

매 프레임 타일을 변경하여 수동으로 애니메이션할 수도 있습니다:

def update():
    frame = time.frame % 4
    player.sprite = Sprite("hero", tile=(frame * 16, 0, 16, 16))

피벗 포인트

기본적으로 스프라이트는 좌상단 모서리에서 그려집니다. 피벗 포인트를 변경하여 스프라이트가 고정되는 위치를 제어할 수 있습니다:

Sprite("hero", tile=(0, 0, 16, 16), pivot=(8, 8))

이렇게 하면 스프라이트가 엔티티 위치의 중심에 배치됩니다. 피벗은 타일에 상대적인 픽셀 좌표입니다. 타일의 중심에 피벗을 설정하는 것이 가장 일반적인 선택입니다 — 회전과 스케일링이 직관적으로 동작합니다.

색상 틴팅

엔티티의 스프라이트에 색상을 설정하여 틴팅할 수 있습니다:

player.color = (1.0, 0.5, 0.5, 1.0)  # 붉은 틴트

색상은 0.0에서 1.0 사이의 RGBA 튜플입니다. 흰색 (1, 1, 1, 1)은 틴팅 없음을 의미합니다. 알파 채널로 투명도를 사용할 수 있습니다:

ghost.color = (1, 1, 1, 0.5)  # 50% 투명

트윈을 사용하여 색상과 알파를 부드럽게 애니메이션할 수도 있습니다:

ghost.tween("alpha", to=0, duration=0.5, ease="out_quad")  # 페이드 아웃

펄스나 깜빡임 같은 지속적인 효과에는 애니메이션을 사용합니다:

ghost.animate("alpha", by=0.3, center=0.7, speed=4.0)  # 깜빡임

카메라

카메라는 월드의 어느 부분이 보이는지를 제어합니다. Camera 컴포넌트를 가진 엔티티를 생성하여 만듭니다:

cam = world.spawn(camera=Camera(), x=160, y=90)

플레이어를 따라가도록 카메라를 이동합니다:

def update():
    cam.x = player.x
    cam.y = player.y

카메라는 줌을 지원합니다:

cam.camera.zoom = 2.0  # 2배 확대

트윈으로 줌을 부드럽게 애니메이션할 수 있습니다:

cam.tween("zoom", to=2.0, duration=0.5, ease="out_quad")

해상도

Pyxen 게임은 기본 해상도 320x180 픽셀로 실행됩니다. 이는 의도적인 선택입니다 — 낮은 해상도는 픽셀 아트를 선명하게 보이게 하고 렌더링을 빠르게 유지합니다. 엔진이 출력을 화면에 맞게 스케일링합니다.

텍스트

Text 컴포넌트는 비트맵 텍스트를 렌더링합니다. 텍스트 엔티티는 다음과 같이 만듭니다:

label = world.spawn(text=Text("Hello, world!"))

기본적으로 텍스트는 내장 픽셀 폰트를 사용합니다. 폰트 에디터로 만든 커스텀 폰트를 사용하려면:

title = world.spawn(text=Text("Game Over", font="myfont"))

런타임에 text 속성을 수정하여 텍스트를 업데이트합니다:

def update():
    score_label.text = Text(f"Score: {score}")

전체 API는 Text 레퍼런스를 참조하세요.

그리기 순서

엔티티는 다음 순서로 그려집니다:

  1. 레이어 — 낮은 레이어가 먼저 그려짐 (레이어 0이 레이어 1 뒤에)
  2. 깊이 — 레이어 내에서, 씬 그래프 위치에 의해 결정
  3. 스프라이트가 없는 엔티티는 그려지지 않지만 월드에는 존재

레이어와 깊이에 대한 자세한 내용은 씬 그래프를 참조하세요.

전체 Sprite API는 SpriteCamera를 참조하세요.