엔티티 및 컴포넌트

Pyxen은 엔티티-컴포넌트 시스템 (ECS)을 사용합니다. Player가 Character를 상속하고 Character가 GameObject를 상속하는 클래스 계층 구조를 사용하는 게임 엔진과는 다릅니다. Pyxen에는 상속이 없습니다. 모든 것이 조합(composition)입니다.

엔티티

엔티티는 게임 오브젝트입니다. 플레이어, 벽, 총알, 파티클 등 무엇이든 될 수 있습니다. 내부적으로 엔티티는 단순한 ID입니다. 자체적으로 데이터를 보유하지 않으며, 대신 컴포넌트를 붙입니다.

player = world.spawn(name="player", x=100, y=50)

이 코드는 위치 (100, 50)에 이름을 가진 엔티티를 생성합니다. 엔티티는 월드에 존재하며 스프라이트가 있으면 렌더링됩니다.

컴포넌트

컴포넌트는 엔티티에 첨부된 데이터 조각입니다. Pyxen에는 두 종류가 있습니다:

내장 컴포넌트

엔진에서 제공하는 컴포넌트입니다:

컴포넌트용도
Transform위치 (x, y), 회전, 스케일
Sprite시각적 외관 — 이미지, 타일, 피벗, 색상
Camera줌이 있는 뷰포트
GridBody그리드 위의 충돌 바디
GridMap행, 열, 타일 데이터가 있는 타일맵
Sound효과음 재생
Music음악 스트림 재생
Name조회용 문자열 식별자
Layer렌더링 레이어 (0–255)
Parent / Children씬 계층 구조

내장 컴포넌트는 엔티티 속성이나 생성 시점에 설정합니다:

e = world.spawn(
    x=50, y=80,
    sprite=Sprite("hero"),
    name="player"
)

# 나중에
e.x = 100
e.sprite = Sprite("hero", tile=(16, 0, 16, 16))

커스텀 컴포넌트

어떤 엔티티에든 자신만의 컴포넌트를 붙일 수 있습니다. 커스텀 컴포넌트는 타입이 있는 필드를 가진 딕셔너리입니다:

player.health = {"value": 100, "max": 100}
player.speed = {"value": 2.5}

붙인 뒤에는 필드에 직접 접근할 수 있습니다:

player.health.value -= 10

마커 컴포넌트 — 데이터 없이 태그 역할을 하는 컴포넌트 — 도 사용할 수 있습니다:

player.alive = True
enemy.boss = True

이는 쿼리에 유용합니다: 특정 마커를 가진 모든 엔티티를 찾을 수 있습니다.

필드 타입

컴포넌트 필드는 다음이 될 수 있습니다:

타입예시비고
int4232비트 정수
float3.1432비트 부동소수점
boolTrue불리언
str"hello"최대 31자
Entityplayer다른 엔티티에 대한 참조

이러한 제약은 컴포넌트가 C++ 엔진 내부에서 컴팩트하고 캐시 친화적인 레이아웃에 저장되기 때문입니다. 이것이 쿼리를 빠르게 만듭니다.

엔티티 쿼리

world를 통해 컴포넌트로 엔티티를 찾을 수 있습니다:

# "health" 컴포넌트가 있는 모든 엔티티
for e in world.all("health"):
    if e.health.value <= 0:
        world.destroy(e)

# 조합: "enemy"가 있고, "dead"가 없는 엔티티
for e in world.all("enemy", without=("dead",)):
    e.x += e.speed.value

"sprite", "body", "camera", "sound", "music", "map" 같은 내장 컴포넌트로도 쿼리할 수 있습니다:

# 스프라이트가 있는 모든 엔티티
for e in world.all("sprite"):
    e.color = (1, 1, 1, 1)

# 스프라이트와 "enemy" 커스텀 컴포넌트가 모두 있는 엔티티
for e in world.all("sprite", "enemy"):
    e.color = (1, 0, 0, 1)

쿼리는 Pyxen에서 게임 로직을 작성하는 주요 방법입니다. 각 오브젝트가 스스로를 업데이트하는 대신, 특정 컴포넌트를 가진 엔티티를 순회하는 시스템을 작성합니다.

전체 API 보기: world.all(), Entity

왜 ECS인가?

객체지향 게임 코드에 익숙하다면, ECS가 처음에는 낯설게 느껴질 수 있습니다. 장점은 다음과 같습니다: