반응형

캐릭터가 도구를 사용하도록 처리해 보자.

아래 링크를 참고해 곡괭이를 사용할 수 있게 만든다.

2026.09.07 - [Godot] - [Godot] RPG Top-Down View Character 탑다운 뷰 캐릭터 1

 

 

전체적인 화면 구성은 위와 같이 한다.

 

 

전 예제에서는 실제 사용하지는 않았던 CharacterBody2D - Area2D - CollisionShape2D의 크기를 곡괭이에 적당히 맞추고 AnimationPlayer의 각 곡괭이질 애니메이션에 disabled, position 속성을 추가 세팅한다.

● disabled - 곡괭이질 애니메이션이 시작되는 순간 false로, 곡괭이질 애니메이션이 끝나는 순간 true로 세팅.

● position - 각 애니메이션 곡괭이 목표 지점에 적당히 배치해서 세팅

 

 

필요하다면 CharacterBody2D - CanvasItem - Ordering - Z Index를 높여 다른 오브젝트 위에 그려지도록 한다.

 

 

사이즈가 일정하지 않은 스프라이트 시트는 Region을 체크하고 직접 Rect를 지정하거나 Edit Region 버튼을 클릭해 원하는 스프라이트를 간단히 지정할 수 있다.

 

Basic Grass Biom things 1.png
0.01MB

 

 

 

 

 

StaticBody2D(해바라기)의 그룹은 Flowers, StaticBody2D(바위)의 그룹은 Rocks로 세팅한다.

 

CharacterBody2D의 스크립트는 아래와 같이 작성한다.

 

using Godot;

public partial class CharacBody : CharacterBody2D
{
    public const float Speed = 100.0f;

    private AnimationTree _animationTree;
    private AnimationNodeStateMachinePlayback _stateMachine;

    public override void _Ready()
    {
        // StateMachine을 가져온다
        _animationTree = GetNode<AnimationTree>("AnimationTree");
        _stateMachine = (AnimationNodeStateMachinePlayback)_animationTree.Get("parameters/playback");

        // 게임 시작 시 기본 방향을 아래쪽(0, 1)으로 강제 설정.
        // Y축이 아래쪽으로 향하는 2D 좌표계에서, (0, 1)은 아래쪽을 의미.
        Vector2 startingDirection = new Vector2(0, 1);

        _animationTree.Set("parameters/Idle/blend_position", startingDirection);
        _animationTree.Set("parameters/Walk/blend_position", startingDirection);

        // Area2D 노드의 BodyEntered 시그널에 이벤트 핸들러를 연결한다.
        Area2D area2D = GetNode<Area2D>("Area2D");
        area2D.BodyEntered += OnBodyEntered;
    }

    private void OnBodyEntered(Node body)
    {
        if (body.IsInGroup("Flowers"))
            // 꽃 그룹에 속한 Body가 Area2D에 들어왔을 때 처리할 로직을 여기에 작성한다.
            GD.Print("Body entered: " + body.GetGroups()[0].ToString());
        else if (body.IsInGroup("Rocks"))
            // 바위 그룹에 속한 Body가 Area2D에 들어왔을 때 처리할 로직을 여기에 작성한다.
            GD.Print("Body entered: " + body.GetGroups()[0].ToString());
    }
    
    /* OnBodyEntered()를 아래와 같이 작성할 수도 있다.
     * 그런데 Flowers, Rocks 외 _root_canvas3685081939968 같은 이름의 그룹 하나가 항상 더 감지 되는데
     * 이 그룹은 Godot이 자동으로 생성하는 그룹으로 실제 게임 로직에서는 필요하지 않다.
    private void OnBodyEntered(Node body)
    {
        Godot.Collections.Array<StringName> groups = body.GetGroups();

        if (groups != null && groups.Count > 0)
        {
            foreach (StringName group in groups)
            {                
                switch (group)
                {
                    case "Flowers":
                        GD.Print("Flower entered");
                         break;
                    case "Rocks":
                        GD.Print("Rock entered");
                        break;
                    default:
                        GD.Print("Other group entered: " + group.ToString());
                        break;
                }
            }
        }
    }
    */

    public override void _PhysicsProcess(double delta)
    {
        // IsActionJustPressed는 계속 누르고 있어도 클릭하는 순간 1번만 true를 반환한다.
        // Plow 액션은 Input Map에서 마우스 왼쪽 버튼으로 설정되어 있다.        
        if (Input.IsActionJustPressed("Plow"))
        {
            Vector2 rawDirection = GetGlobalMousePosition() - GlobalPosition;
            Vector2 plowDirection = Vector2.Zero;

            if (Mathf.Abs(rawDirection.X) > Mathf.Abs(rawDirection.Y))
                plowDirection = rawDirection.X > 0 ? Vector2.Right : Vector2.Left;
            else
                plowDirection = rawDirection.Y > 0 ? Vector2.Down : Vector2.Up;

            // Plow 애니메이션을 재생하기 위해, 애니메이션 트리의 blend_position을 설정한다.
            _animationTree.Set("parameters/Plow/blend_position", plowDirection);
            // Walk과 Idle 애니메이션도 같은 방향으로 바라보도록 blend_position을 설정한다.
            _animationTree.Set("parameters/Idle/blend_position", plowDirection);
            _animationTree.Set("parameters/Walk/blend_position", plowDirection);

            _stateMachine.Travel("Plow");

            // Plow 명령을 내렸으니 return으로 함수를 끝내서 아래에 있는 Idle(대기) 상태가 되는것을 차단한다.
            return;
        }

        // WASD 또는 방향키 입력을 Vector2로 받아온다.
        // 예: 오른쪽 위 대각선 이동 시 (1, -1) 반환
        Vector2 direction = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");

        if (direction != Vector2.Zero)
        {
            // 이동 방향을 애니메이션 트리에 전달.
            _animationTree.Set("parameters/Idle/blend_position", direction);
            _animationTree.Set("parameters/Walk/blend_position", direction);

            // 상태를 '걷기'로 바꾼다.
            _stateMachine.Travel("Walk");
        }
        else
        {
            // 입력이 없으면 상태를 '대기'로 바꾼다. 
            // (마지막으로 바라보던 방향의 idle 애니메이션이 자동으로 재생)
            _stateMachine.Travel("Idle");
        }

        // 입력된 방향에 속도를 곱해서 바로 Velocity(속력)로 설정한다.
        Velocity = direction * Speed;

        // 엔진이 알아서 벽 충돌을 계산하며 이동시킨다.
        MoveAndSlide();
    }
}

 

게임을 실행하고 곡괙이질을 해 보자.

 

 

반응형
Posted by J-sean
: