아래는 Godot 4.3에서 작성된 RigidBody2D
를 확장한 코드에 대한 상세한 분석입니다. 이 코드는 주로 물리적 객체의 상태 관리, 사용자 입력 처리, 발사체 생성, 물리적 움직임 등을 포함합니다. 이를 블로그 스타일로 디자인 서식을 포함하여 설명하겠습니다.
Godot 4.3: RigidBody2D 기반 플레이어 컨트롤 분석
코드 개요
이 코드는 RigidBody2D
를 확장하여 사용자 입력에 따라 회전, 이동, 발사 등의 기능을 구현합니다. 상태 관리, 화면 경계 래핑(wrapping), 발사체 관리 등 다양한 게임플레이 요소를 포함합니다.
코드 분석
1. 변수 선언
@export var bullet_scene : PackedScene
@export var fire_rate = 0.25
@export var engie_power = 500
@export var spin_power = 8000
bullet_scene
: 발사체의 장면(PackedScene
)을 저장합니다. 이 값은 에디터에서 설정됩니다.fire_rate
: 발사 주기(초 단위). 0.25초마다 발사가 가능합니다.engie_power
: 추진력의 크기. 플레이어가 앞으로 나아갈 때 적용됩니다.spin_power
: 회전력의 크기. 좌우 회전의 민첩성을 조정합니다.
enum {INIT, ALIVE, INVULNERABLE, DEAD}
var state = INIT
enum
: 객체 상태를 정의합니다.INIT
: 초기 상태.ALIVE
: 활성 상태.INVULNERABLE
: 무적 상태.DEAD
: 죽은 상태.
state
: 현재 상태를 저장하는 변수로 기본값은INIT
입니다.
2. Godot 기본 함수
_ready()
func _ready() -> void:
change_state(ALIVE)
screensize = get_viewport_rect().size
$GunCooldown.wait_time = fire_rate
change_state(ALIVE)
: 초기 상태를 활성 상태로 변경합니다.get_viewport_rect().size
: 화면의 크기를 가져옵니다.$GunCooldown.wait_time
: 발사 대기 시간을 설정합니다.
_process(delta)
func _process(delta: float) -> void:
get_input()
_process(delta)
: 매 프레임 호출됩니다.get_input()
: 사용자 입력을 처리합니다.
_physics_process(delta)
func _physics_process(delta: float) -> void:
constant_force = thrust
constant_torque = rotation_dir * spin_power
_physics_process(delta)
: 물리 프레임마다 호출됩니다.constant_force
: 객체에 적용되는 지속적인 힘입니다.constant_torque
: 객체에 적용되는 지속적인 회전력입니다.
🔗 Godot Docs: _physics_process()
_integrate_forces()
func _integrate_forces(physics_state: PhysicsDirectBodyState2D) -> void:
var xform = physics_state.transform
xform.origin.x = wrapf(xform.origin.x, 0, screensize.x)
xform.origin.y = wrapf(xform.origin.y, 0, screensize.y)
physics_state.transform = xform
wrapf(value, min, max)
:value
를min
과max
사이로 순환합니다.- 목적: 화면 밖으로 나가는 객체를 반대편으로 래핑합니다.
🔗 Godot Docs: _integrate_forces()
3. 사용자 입력 처리
get_input()
func get_input():
thrust = Vector2.ZERO
if state in [DEAD, INIT]:
return
if Input.is_action_pressed("thrust"):
thrust = transform.x * engie_power
rotation_dir = Input.get_axis("rotate_left", "rotate_right")
if Input.is_action_pressed("shoot") and can_shoot:
shoot()
Input.is_action_pressed()
: 사용자가 특정 액션(예: “thrust”)을 누르고 있는지 확인합니다.Input.get_axis()
: 회전 입력(왼쪽/오른쪽)을 계산합니다.shoot()
: 발사 기능 호출.
4. 발사체 생성
shoot()
func shoot():
if state == INVULNERABLE:
return
can_shoot = false
$GunCooldown.start()
var b = bullet_scene.instantiate()
get_tree().root.add_child(b)
b.start($Muzzle.global_transform)
$GunCooldown.start()
: 발사 쿨다운 타이머 시작.bullet_scene.instantiate()
: 새 발사체 인스턴스 생성.get_tree().root.add_child(b)
: 발사체를 씬 트리에 추가.b.start()
: 발사체 초기화.
🔗 Godot Docs: Scenes and Nodes
5. 상태 관리
change_state(new_state)
func change_state(new_state):
match new_state:
INIT:
$CollisionShape2D.set_deferred("disabled", true)
ALIVE:
$CollisionShape2D.set_deferred("disabled", false)
INVULNERABLE:
$CollisionShape2D.set_deferred("disabled", true)
DEAD:
$CollisionShape2D.set_deferred("disabled", true)
state = new_state
match
: 상태 전환을 처리합니다.set_deferred()
: 물리 엔진과의 충돌 상태를 비동기적으로 설정합니다.
결론
이 코드는 2D 슈팅 게임에서 플레이어의 이동, 회전, 발사 등의 동작을 제어하는 기본적인 기능을 제공합니다. RigidBody2D
를 확장하여 물리적인 움직임과 사용자 입력을 효과적으로 결합했으며, 상태 관리와 발사체 구현이 주요 특징입니다.
추천 참고 자료
이 코드는 프로젝트의 특정 요구사항에 따라 확장할 수 있으며, 발사체나 화면 경계 래핑과 같은 기능을 게임의 다른 요소에 적용할 수도 있습니다.