Skip to content

v2.2.0 새로운 기능

v2.2는 게임 루프 보일러플레이트를 라이브러리 안으로 흡수합니다 — 입력, 카메라, 캐릭터 이동이 이제 한 줄로 처리됩니다. 모든 변경 사항은 완전한 하위 호환을 유지합니다.


새로운 기능

Input.axis() — 간결한 이동 입력

# 이전
move_x = float(inp.key_held(f3d.Key.D)) - float(inp.key_held(f3d.Key.A))

# 이후
move_x = inp.axis(f3d.Key.A, f3d.Key.D)   # → [-1, 1] float
move_y = inp.axis(f3d.Key.S, f3d.Key.W)

ScriptedInput에도 동일하게 추가되어 결정론적 테스트에 사용 가능합니다.

OrbitCamera.handle_input() — 카메라를 한 줄로

# 이전 (프레임별 이벤트 파싱)
dx, dy = inp.mouse_delta()
if inp.mouse_button(1):
    cam.rotate(d_azimuth=dx * 0.5, d_elevation=-dy * 0.5)
cam.zoom(-inp.scroll_delta() * 0.5)

# 이후
cam.handle_input(inp, dt)   # 드래그 + Q/E 회전 + 스크롤 줌, 모두 내장

CharacterController.move_camera_relative() — 카메라 공간 이동

# 이전 — 수동 yaw 계산
import math
yaw = math.atan2(cam_dir[1], cam_dir[0])
fx = math.cos(yaw) * move_x + ...

# 이후
cc.move_camera_relative(inp, cam, speed=5.5, dt=dt)

Viewer.show_grid — 공개 프로퍼티

viewer = f3d.Viewer(world, show_grid=True)   # 생성자 파라미터
viewer.show_grid = False                      # 또는 런타임에서 토글

내부 접근 viewer._renderer._show_grid를 공개 API로 대체합니다.

Viewer.draw_text — 앵커 기반 레이아웃

viewer.draw_text("점수: 100",  anchor="topcenter",    margin=10)
viewer.draw_text("목숨: 3",    anchor="topleft",       margin=10)
viewer.draw_text("게임 오버",  anchor="bottomcenter",  margin=40)
viewer.draw_text("ENTER 누르기", anchor="bottomright", margin=10)

xy는 픽셀 정밀 배치에 여전히 사용 가능하며, 생략 시 anchor를 사용합니다.

App 생성자에서 렌더 파라미터 설정

app = f3d.App(
    "내 게임",
    width=1920, height=1080,
    substeps=4,
    shadow_resolution=2048,
    sky_color=(0.1, 0.15, 0.25),
    show_grid=False,
    max_dt=1/30,
)

버그 수정

Sentry 호버 떠오름 버그 (apps/game/enemies.py)

호버 raycast에 layer_mask가 없어 sentry가 자신의 몸통을 감지하고 위로 떠오르는 버그 수정:

hit = world.raycast(origin, (0, 0, -1), max_dist=2.0,
                    layer_mask=CollisionLayer.DEFAULT | CollisionLayer.TERRAIN)

마이그레이션

Breaking change 없음. 기존 코드는 수정 없이 동작합니다.

이전 패턴 v2.2 대안
float(inp.key_held(D)) - float(inp.key_held(A)) inp.axis(A, D)
프레임별 카메라 이벤트 파싱 cam.handle_input(inp, dt)
수동 yaw + cc.move(...) cc.move_camera_relative(inp, cam, speed, dt)
viewer._renderer._show_grid = True viewer.show_grid = True
draw_text(text, x=640, y=10, ...) draw_text(text, anchor="topcenter", margin=10)