You are currently viewing “Godot 4.3에서 RigidBody2D를 활용한 플레이어 컨트롤 구현: 물리와 게임플레이의 조화”

“Godot 4.3에서 RigidBody2D를 활용한 플레이어 컨트롤 구현: 물리와 게임플레이의 조화”

아래는 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: 발사 대기 시간을 설정합니다.

🔗 Godot Docs: _ready()


_process(delta)

func _process(delta: float) -> void:
    get_input()
  • _process(delta): 매 프레임 호출됩니다.
  • get_input(): 사용자 입력을 처리합니다.

🔗 Godot Docs: _process()


_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): valueminmax 사이로 순환합니다.
  • 목적: 화면 밖으로 나가는 객체를 반대편으로 래핑합니다.

🔗 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(): 발사 기능 호출.

🔗 Godot Docs: Input


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를 확장하여 물리적인 움직임과 사용자 입력을 효과적으로 결합했으며, 상태 관리와 발사체 구현이 주요 특징입니다.


추천 참고 자료

이 코드는 프로젝트의 특정 요구사항에 따라 확장할 수 있으며, 발사체나 화면 경계 래핑과 같은 기능을 게임의 다른 요소에 적용할 수도 있습니다.

답글 남기기