Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

2D에서 커스텀 그리기

소개

Godot는 스프라이트, 폴리곤, 입자 등을 그리기 위한 노드를 가지고 있습니다. 대부분 경우에 충분하지만 항상 그렇지는 않습니다. 두려움, 불안, 분노 속에 울기 전에 특별한 무언가를 그리는 노드가 존재하지 않기 때문에... 2D 노드( Control 또는 Node2D 기반)가 사용자 지정 명령을 쉽게 그릴 수 있는 것을 알면 좋을 것입니다.

노드에서 수동으로 사용자 임의 그림은 진짜 유용합니다. 여기 왜 그런지 몇 가지 예가 있습니다:

  • 노드에서 처리되지 않는 모양 또는 논리 그리기 (예: 원을 그리는 노드, 이미지 자국, 특별한 종류의 움직이는 폴리곤 등 만들기).

  • 많은 양의 단순 물체 그리기. 사용자 정의 그림을 사용하면 메모리 집약도가 낮아지고 잠재적으로 속도가 빨라져 노드 사용의 오버헤드를 방지할 수 있습니다.

  • 사용자 정의 UI 컨트롤 만들기. 사용 가능한 컨트롤은 많지만, 새롭고 커스텀화된 컨트롤을 만들어야 할 필요성에 부딪치기 쉽습니다.

그리기

CanvasItem 를 상속받는 Control 또는 Node2D 와 같은 노드에 스크립트를 추가하세요. 그런 다음 _draw() 함수를 오버라이드하세요.

extends Node2D

func _draw():
    pass  # Your draw commands here.

그리기 명령은 CanvasItem 클래스 참고에 설명되어 있습니다. 많은 양의 명령이 있습니다.

업데이트 중

_draw() 함수는 단 한 번만 호출하고, 그 다음에는 그리기 명령을 캐싱하여 기억하므로 추가 호출은 불필요합니다.

상태나 다른 것이 변경되어 리드로우가 필요한 경우 간단하게 같은 노드에서 CanvasItem.update() 를 호출하면 새로운 _draw() 호출이 발생합니다.

다음은 언제든지 수정될 수 있는 텍스처 변수가 있고 :ref:`setter<doc_gdscript_basics_setters_getters>`를 사용하여 수정 시 텍스처를 강제로 다시 그리는 조금 더 복잡한 예입니다.

extends Node2D

@export var texture : Texture2D:
    set(value):
        texture = value
        queue_redraw()

func _draw():
    draw_texture(texture, Vector2())

실제로 작동하는 모습을 보려면 FileSystem 탭에서 기본 icon.svg``를 ``Inspector 탭의 Texture 속성으로 드래그 앤 드롭하여 편집기에서 텍스처를 Godot 아이콘으로 설정할 수 있습니다. 이전 스크립트 실행 중 Texture 속성 값을 변경하면 텍스처도 자동으로 변경됩니다.

어떤 경우 모든 프레임을 그리는 것이 바람직할 수 있습니다. 이를 위해 _process() 콜백에서 다음과 같이 update() 를 호출하세요:

extends Node2D

func _draw():
    pass  # Your draw commands here.

func _process(_delta):
    queue_redraw()

좌표 및 선폭 정렬

그리기 API는 CanvasItem의 좌표계를 사용하지만 반드시 픽셀 좌표를 사용할 필요는 없습니다. 이는 ``_draw()``가 CanvasItem의 변환을 적용한 후 생성된 좌표 공간을 사용함을 의미합니다. 또한 draw_set_transform 또는 :ref:`draw_set_transform_matrix<class_CanvasItem_method_draw_set_transform_matrix>`를 사용하여 그 위에 사용자 지정 변환을 적용할 수 있습니다.

:ref:`draw_line <class_CanvasItem_method_draw_line>`을 사용할 때는 선 너비를 고려해야 합니다. 홀수 크기의 너비를 사용하는 경우 아래 그림과 같이 선이 중앙에 유지되도록 ``0.5``로 시작점과 끝점의 위치를 이동해야 합니다.

../../_images/draw_line.png
func _draw():
    draw_line(Vector2(1.5, 1.0), Vector2(1.5, 4.0), Color.GREEN, 1.0)
    draw_line(Vector2(4.0, 1.0), Vector2(4.0, 4.0), Color.GREEN, 2.0)
    draw_line(Vector2(7.5, 1.0), Vector2(7.5, 4.0), Color.GREEN, 3.0)

``filled = false``를 사용하는 draw_lect 메서드에도 동일하게 적용됩니다.

../../_images/draw_rect.png
func _draw():
    draw_rect(Rect2(1.0, 1.0, 3.0, 3.0), Color.GREEN)
    draw_rect(Rect2(5.5, 1.5, 2.0, 2.0), Color.GREEN, false, 1.0)
    draw_rect(Rect2(9.0, 1.0, 5.0, 5.0), Color.GREEN)
    draw_rect(Rect2(16.0, 2.0, 3.0, 3.0), Color.GREEN, false, 2.0)

안티앨리어싱된 그리기

Godot는 안티앨리어싱을 활성화하기 위해 draw_line<class_CanvasItem_method_draw_line>`에 메소드 매개변수를 제공하지만, 모든 사용자 정의 드로잉 메소드가 이 ``antialiased` 매개변수를 제공하는 것은 아닙니다.

antialiased 매개변수를 제공하지 않는 사용자 정의 그리기 방법의 경우 대신 2D MSAA를 활성화할 수 있으며 이는 전체 뷰포트의 렌더링에 영향을 미칩니다. 이는 고품질 앤티앨리어싱을 제공하지만 성능 비용이 더 높고 특정 요소에만 적용됩니다. 자세한 내용은 :ref:`doc_2d_antialiasing`를 참조하세요.

다음은 2D MSAA 2x, 4x 및 8x가 활성화된 antialiased=false, antialiased=trueantialiased=false``로 그린 최소 너비의 선(``width=-1)을 비교한 것입니다.

../../_images/draw_antialiasing_options.webp

편집기에서 실행하는 동안 자신만의 노드를 그리는 것이 바람직할 수도 있습니다. 이는 일부 기능이나 동작을 미리 보거나 시각화하는 데 사용할 수 있습니다.

이렇게 하려면 GDScript와 C# 모두에서 tool annotation 및 :ref:`doc_running_code_in_the_editor`를 참조하세요.

어떻게 작동하는 지의 예제입니다:

이제 Godot 엔진의 사용자 지정 그리기 기능을 사용하여 Godot가 제공하지 않는 기능을 그릴 겁니다. 이것을 수행하려면 함수를 코드화해서 직접 그려야 할 것입니다.

이를 수행하려면 함수를 코딩하고 직접 그려야 합니다.

참고

다음 지침에서는 고해상도 화면(1080p보다 큼)에 비해 너무 작을 수 있는 고정 좌표 집합을 사용합니다. 이러한 경우이고 도면이 너무 작은 경우 프로젝트 설정 :ref:`Display > Window > Stretch > Scale<class_ProjectSettings_property_display/window/stretch/scale>`에서 창 배율을 늘려 프로젝트를 더 높은 해상도로 조정하는 것이 좋습니다(2 또는 4 배율이 잘 작동하는 경향이 있음).

커스텀 노드 생성하기

사용자 정의 다각형을 그리는 전용 노드( Polygon2D)가 있지만 이 경우에는 동일한 노드에서 이를 결합하고 나중에 더 복잡한 모양을 만들 수 있도록 하위 수준 그리기 기능만 사용합니다.

먼저, 모양의 기본을 형성할 점 세트(또는 X 및 Y 좌표)를 정의합니다.

extends Node2D

var coords_head : Array = [
    [ 22.952, 83.271 ],  [ 28.385, 98.623 ],
    [ 53.168, 107.647 ], [ 72.998, 107.647 ],
    [ 99.546, 98.623 ],  [ 105.048, 83.271 ],
    [ 105.029, 55.237 ], [ 110.740, 47.082 ],
    [ 102.364, 36.104 ], [ 94.050, 40.940 ],
    [ 85.189, 34.445 ],  [ 85.963, 24.194 ],
    [ 73.507, 19.930 ],  [ 68.883, 28.936 ],
    [ 59.118, 28.936 ],  [ 54.494, 19.930 ],
    [ 42.039, 24.194 ],  [ 42.814, 34.445 ],
    [ 33.951, 40.940 ],  [ 25.637, 36.104 ],
    [ 17.262, 47.082 ],  [ 22.973, 55.237 ]
]

이 형식은 간결하지만 Godot가 다각형을 그리는 데 이해하는 형식은 아닙니다. 다른 시나리오에서는 파일에서 이러한 좌표를 로드하거나 애플리케이션이 실행되는 동안 위치를 계산해야 할 수 있으므로 일부 변환이 필요할 수 있습니다.

이러한 좌표를 올바른 형식으로 변환하기 위해 새로운 메서드 float_array_to_Vector2Array()``를 만듭니다. 그런 다음 Godot가 실행 시작 해당 좌표를 변수에 로드하기 위해 번만 호출하는 ``_ready() 함수를 재정의합니다:

var head : PackedVector2Array

func float_array_to_Vector2Array(coords : Array) -> PackedVector2Array:
    # Convert the array of floats into a PackedVector2Array.
    var array : PackedVector2Array = []
    for coord in coords:
        array.append(Vector2(coord[0], coord[1]))
    return array

func _ready():
    head = float_array_to_Vector2Array(coords_head);

마지막으로 첫 번째 모양을 그리기 위해 draw_polygon 메서드를 사용하고 다음과 같이 점(Vector2 좌표 배열로)과 해당 색상을 전달합니다.

func _draw():
    # We are going to paint with this color.
    var godot_blue : Color = Color("478cbf")
    # We pass the PackedVector2Array to draw the shape.
    draw_polygon(head, [ godot_blue ])

실행되는 동안 여러분은 이와 비슷한 것이 보여야 합니다.

../../_images/draw_godot_logo_polygon.webp

로고의 아래쪽 부분이 분할되어 있는 것처럼 보입니다. 이는 해당 부분을 정의하는 데 사용된 포인트 수가 적기 때문입니다. 부드러운 곡선을 시뮬레이션하려면 배열에 더 많은 점을 추가하거나 수학 함수를 사용하여 곡선을 보간하고 코드에서 부드러운 모양을 만들 수 있습니다(example 2 참조).

다각형은 닫힌 모양을 갖기 위해 항상 **마지막으로 정의된 점을 첫 번째 점에 연결**합니다.

명명 규칙

다각형을 형성하기 위해 닫히지 않는 일련의 연결된 선을 그리는 것은 이전 방법과 매우 유사합니다. 우리는 연결된 선 세트를 사용하여 Godot의 로고 입을 그릴 것입니다.

먼저 입 모양을 형성하는 좌표 목록을 다음과 같이 정의합니다.

var coords_mouth = [
    [ 22.817, 81.100 ], [ 38.522, 82.740 ],
    [ 39.001, 90.887 ], [ 54.465, 92.204 ],
    [ 55.641, 84.260 ], [ 72.418, 84.177 ],
    [ 73.629, 92.158 ], [ 88.895, 90.923 ],
    [ 89.556, 82.673 ], [ 105.005, 81.100 ]
]

이러한 좌표를 변수에 로드하고 구성 가능한 선 두께로 추가 변수를 정의하겠습니다.

var mouth : PackedVector2Array
var _mouth_width : float = 4.4

func _ready():
    head = float_array_to_Vector2Array(coords_head);
    mouth = float_array_to_Vector2Array(coords_mouth);

마지막으로 draw_polyline 메서드를 사용하여 실제로 다음과 같이 선을 그립니다.

func _draw():
    # We will use white to draw the line.
    var white : Color = Color.WHITE
    var godot_blue : Color = Color("478cbf")

    draw_polygon(head, [ godot_blue ])

    # We draw the while line on top of the previous shape.
    draw_polyline(mouth, white, _mouth_width)

적 씬은 다음 노드들을 사용할 것입니다:

../../_images/draw_godot_logo_polyline.webp

``draw_polygon()``와 달리 폴리라인은 모든 점에 대해 하나의 고유한 색상만 가질 수 있습니다(두 번째 인수). 이 메소드에는 2개의 추가 인수가 있습니다: 선 너비(기본적으로 가능한 한 작음) 및 앤티앨리어싱 활성화 또는 비활성화(기본적으로 비활성화되어 있음).

_draw 호출의 순서가 중요합니다. 트리 계층 구조의 노드 위치와 마찬가지로 다양한 모양이 위에서 아래로 그려지므로 최신 모양이 겹치는 경우 이전 모양이 숨겨집니다. 이 경우에는 입을 머리 위로 그려야 하므로 나중에 배치합니다.

16진수 코드나 미리 정의된 색상 이름을 사용하여 다양한 방법으로 색상을 정의할 수 있는 방법에 주목하세요. 다른 상수와 색상을 정의하는 방법은 Color 클래스를 확인하세요.

그리기

눈을 만들기 위해 다양한 크기, 색상 및 위치로 눈 모양을 그리는 4개의 추가 호출을 추가할 것입니다.

원을 그리려면 draw_circle 메서드를 사용하여 중심을 기준으로 위치를 지정합니다. 첫 번째 매개변수는 중심 좌표가 있는 :ref:`Vector2<class_Vector2>`이고, 두 번째 매개변수는 반경, 세 번째 매개변수는 색상입니다.

func _draw():
    var white : Color = Color.WHITE
    var godot_blue : Color = Color("478cbf")
    var grey : Color = Color("414042")

    draw_polygon(head, [ godot_blue ])
    draw_polyline(mouth, white, _mouth_width)

    # Four circles for the 2 eyes: 2 white, 2 grey.
    draw_circle(Vector2(42.479, 65.4825), 9.3905, white)
    draw_circle(Vector2(85.524, 65.4825), 9.3905, white)
    draw_circle(Vector2(43.423, 65.92), 6.246, grey)
    draw_circle(Vector2(84.626, 66.008), 6.246, grey)

실행되는 동안, 여러분은 이와 비슷한 것이 있어야 합니다:

../../_images/draw_godot_logo_circle.webp

부분적이고 채워지지 않은 호(특정 임의 각도 사이의 원 모양 부분)의 경우 draw_arc 메서드를 사용할 수 있습니다.

그리기

최종 모양(코)을 그리기 위해 선을 사용하여 대략적인 모양을 만듭니다.

:ref:`draw_line <class_CanvasItem_method_draw_line>`은 다음과 같이 시작 및 끝 좌표를 인수로 제공하여 단일 세그먼트를 그리는 데 사용할 수 있습니다.

func _draw():
    var white : Color = Color.WHITE
    var godot_blue : Color = Color("478cbf")
    var grey : Color = Color("414042")

    draw_polygon(head, [ godot_blue ])
    draw_polyline(mouth, white, _mouth_width)
    draw_circle(Vector2(42.479, 65.4825), 9.3905, white)
    draw_circle(Vector2(85.524, 65.4825), 9.3905, white)
    draw_circle(Vector2(43.423, 65.92), 6.246, grey)
    draw_circle(Vector2(84.626, 66.008), 6.246, grey)

    # Draw a short but thick white vertical line for the nose.
    draw_line(Vector2(64.273, 60.564), Vector2(64.273, 74.349), white, 5.8)

이제 화면에서 다음 모양을 볼 수 있습니다.

../../_images/draw_godot_logo_line.webp

연결되지 않은 여러 선을 동시에 그리려는 경우 draw_multiline 메서드를 사용하여 단일 호출로 모든 선을 그리면 추가 성능을 얻을 수 있습니다.

서식(Formatting)

Label 노드를 사용하는 것이 애플리케이션에 텍스트를 추가하는 가장 일반적인 방법이지만, 하위 수준 _draw 함수에는 사용자 정의 노드 도면에 텍스트를 추가하는 기능이 포함되어 있습니다. 로봇 머리 아래에 "GODOT"이라는 이름을 추가하는 데 사용하겠습니다.

이를 수행하기 위해 다음과 같이 draw_string 메서드를 사용합니다.

var default_font : Font = ThemeDB.fallback_font;

func _draw():
    var white : Color = Color.WHITE
    var godot_blue : Color = Color("478cbf")
    var grey : Color = Color("414042")

    draw_polygon(head, [ godot_blue ])
    draw_polyline(mouth, white, _mouth_width)
    draw_circle(Vector2(42.479, 65.4825), 9.3905, white)
    draw_circle(Vector2(85.524, 65.4825), 9.3905, white)
    draw_circle(Vector2(43.423, 65.92), 6.246, grey)
    draw_circle(Vector2(84.626, 66.008), 6.246, grey)
    draw_line(Vector2(64.273, 60.564), Vector2(64.273, 74.349), white, 5.8)

    # Draw GODOT text below the logo with the default font, size 22.
    draw_string(default_font, Vector2(20, 130), "GODOT",
                HORIZONTAL_ALIGNMENT_CENTER, 90, 22)

여기서는 먼저 구성된 기본 테마 글꼴(대신 사용자 정의 글꼴을 설정할 수 있음)을 defaultFont 변수에 로드한 다음 글꼴, 위치, 텍스트, 가로 정렬, 너비 및 글꼴 크기와 같은 매개변수를 전달합니다.

다음 코드를 스크립트에 추가하세요:

../../_images/draw_godot_logo_text.webp

추가 매개변수와 텍스트 및 문자와 관련된 기타 메서드는 CanvasItem 클래스 참조에서 찾을 수 있습니다.

편집하는 동안 그림 표시

지금까지의 코드는 실행 중인 창에 로고를 그릴 수 있지만 편집기의 ``2D view``에는 표시되지 않습니다. 어떤 경우에는 대부분의 다른 노드처럼 사용자 정의 Node2D나 편집기를 편집기에 표시하여 적절하게 배치하고 크기를 조정하고 싶을 수도 있습니다.

로고를 실행하지 않고 편집기에 직접 표시하려면 다음과 같이 @tool 주석을 사용하여 편집 중에도 표시되도록 노드의 사용자 정의 도면을 요청할 수 있습니다.

@tool
extends Node2D

@tool 주석을 처음 추가하거나 제거할 때 2D 보기에서 현재 노드를 새로 고치려면 씬을 저장하고 프로젝트(C#에만 해당)를 다시 빌드한 다음 메뉴 옵션 ``Scene > Reload Saved Scene``에서 현재 씬을 수동으로 다시 로드해야 합니다.

애니메이션

런타임 시 사용자 정의 모양을 변경하려면 실행 시 호출된 메서드나 해당 인수를 수정하거나 변환을 적용하면 됩니다.

예를 들어 방금 디자인한 사용자 정의 모양을 회전시키려면 _ready_process 메서드에 다음 변수와 코드를 추가할 수 있습니다.

extends Node2D

@export var rotation_speed : float = 1  # In radians per second.

func _ready():
    rotation = 0
    ...

func _process(delta: float):
    rotation -= rotation_speed * delta

위 코드의 문제점은 왼쪽 상단 모서리((0, 0) 좌표)에서 시작하여 오른쪽 및 아래쪽으로 확장되는 대략 직사각형에 점을 생성했기 때문에 왼쪽 상단 모서리를 피벗으로 사용하여 회전이 수행되는 것을 볼 수 있다는 것입니다. 노드의 위치 변환 변경은 회전 변환이 먼저 적용되므로 여기서는 도움이 되지 않습니다.

음수 좌표를 포함하여 ``(0, 0)``를 중심으로 모든 점의 좌표를 다시 작성할 수 있지만 이는 많은 작업이 소요됩니다.

이 문제를 해결하는 한 가지 가능한 방법은 낮은 수준의 draw_set_transform 메서드를 사용하여 이 문제를 해결하고 CanvasItem 자체 공간의 모든 지점을 변환한 다음 편집기나 코드에서 다음과 같이 일반 노드 변환을 사용하여 원래 위치로 다시 이동하는 것입니다.

func _ready():
    rotation = 0
    position = Vector2(60, 60)
    ...

func _draw():
    draw_set_transform(Vector2(-60, -60))
    ...

이제 ``(60, 60)``에서 피벗을 중심으로 회전하는 결과는 다음과 같습니다.

../../_images/draw_godot_rotation.webp

애니메이션을 적용하려는 항목이 _draw() 호출 내부의 속성인 경우 ``queue_redraw()``를 호출하여 강제로 새로 고쳐야 한다는 점을 기억해야 합니다. 그렇지 않으면 화면에 업데이트되지 않습니다.

예를 들어, 사인곡선(sin) 곡선을 따라 입선의 너비를 변경하여 로봇이 입을 열고 닫는 것처럼 보이도록 만드는 방법은 다음과 같습니다.

var _mouth_width : float = 4.4
var _max_width : float = 7
var _time : float = 0

func _process(delta : float):
    _time += delta
    _mouth_width = abs(sin(_time) * _max_width)
    queue_redraw()

func _draw():
    ...
    draw_polyline(mouth, white, _mouth_width)
    ...

씬 계층 구조는 다음과 같이 보일 것입니다:

../../_images/draw_godot_mouth_animation.webp

_mouth_width``는 다른 속성과 마찬가지로 사용자 정의 속성이며 그리기 인수로 사용되는 다른 속성은 :ref:`Tween<class_Tween>` 또는 :ref:`AnimationPlayer<class_AnimationPlayer>` 노드와 같은 보다 표준적이고 높은 수준의 방법을 사용하여 애니메이션할 있습니다. 유일한 차이점은 해당 변경 사항을 적용하여 화면에 표시하려면 ``queue_redraw() 호출이 필요하다는 것입니다.

예제: 원호 그리기

이전 예는 사용자 정의 모양과 애니메이션으로 노드를 그리고 수정하는 방법을 배우는 데 유용했습니다. 이는 비트맵 대신 정확한 좌표와 벡터를 사용하여 그리기와 같은 몇 가지 이점을 가질 수 있습니다. 즉, 화면에서 변환할 때 크기가 잘 조정됩니다. 어떤 경우에는 SVG 리소스(벡터로 정의된 이미지이기도 함)를 로드하는 sprites 또는 AnimatedSpritesAnimationPlayer 노드와 같은 노드를 사용하여 더 높은 수준의 기능을 구성하여 유사한 결과를 얻을 수 있습니다.

다른 경우에는 코드를 실행하기 전에 결과 그래픽 표현이 무엇인지 알 수 없기 때문에 불가능합니다. 여기에서는 좌표가 미리 알려지지 않고 사용자 입력의 영향을 받는 동적 선을 그리는 방법을 살펴보겠습니다.

두 점 사이에 직선 그리기

두 점 사이에 직선을 그리려고 한다고 가정해 보겠습니다. 첫 번째 점은 왼쪽 상단 모서리 ``(0, 0)``에 고정되고 두 번째 점은 화면의 커서 위치에 의해 정의됩니다.

다음과 같이 두 점 사이에 동적 선을 그릴 수 있습니다.

extends Node2D

var point1 : Vector2 = Vector2(0, 0)
var width : int = 10
var color : Color = Color.GREEN

var _point2 : Vector2

func _process(_delta):
    var mouse_position = get_viewport().get_mouse_position()
    if mouse_position != _point2:
        _point2 = mouse_position
        queue_redraw()

func _draw():
    draw_line(point1, _point2, color, width)

이 예에서는 get_mouse_position 메서드를 사용하여 모든 프레임마다 기본 뷰포트에서 마우스 위치를 얻습니다. 마지막 그리기 요청 이후 위치가 변경된 경우(매 프레임마다 다시 그리는 것을 피하기 위한 작은 최적화) 다시 그리기를 예약합니다. 우리의 _draw() 메소드에는 왼쪽 상단 모서리와 얻은 위치 사이에 너비가 10픽셀인 녹색 선 그리기를 요청하는 한 줄만 있습니다.

적 씬은 다음 노드들을 사용할 것입니다:

최종 스크립트는 다음과 같아야 합니다:

../../_images/draw_line_between_2_points.webp

두 점 사이에 호 그리기

위의 예는 작동하지만 직선이 아닌 다른 모양이나 기능을 사용하여 두 점을 결합할 수도 있습니다.

이제 두 점 사이에 호(원주의 일부)를 만들어 보겠습니다.

선 시작점, 세그먼트, 너비, 색상 및 앤티앨리어싱을 내보내면 편집기 검사기 패널에서 해당 속성을 매우 쉽게 직접 수정할 수 있습니다.

extends Node2D

@export var point1 : Vector2 = Vector2(0, 0)
@export_range(1, 1000) var segments : int = 100
@export var width : int = 10
@export var color : Color = Color.GREEN
@export var antialiasing : bool = false

var _point2 : Vector2
../../_images/draw_dynamic_exported_properties.webp

호를 그리려면 draw_arc 메소드를 사용할 수 있습니다. 2개의 점을 통과하는 호가 많으므로 이 예에서는 2개의 초기 점 사이의 중간점에 중심이 있는 반원을 선택합니다.

이 호를 계산하는 것은 선의 경우보다 더 복잡합니다.

func _draw():
    # Average points to get center.
    var center : Vector2 = Vector2((_point2.x + point1.x) / 2,
                                   (_point2.y + point1.y) / 2)
    # Calculate the rest of the arc parameters.
    var radius : float = point1.distance_to(_point2) / 2
    var start_angle : float = (_point2 - point1).angle()
    var end_angle : float = (point1 - _point2).angle()
    if end_angle < 0:  # end_angle is likely negative, normalize it.
        end_angle += TAU

    # Finally, draw the arc.
    draw_arc(center, radius, start_angle, end_angle, segments, color,
             width, antialiasing)

반원의 중심은 두 점 사이의 중간점이 됩니다. 반경은 두 지점 사이의 거리의 절반이 됩니다. 시작 각도와 끝 각도는 point1에서 point2로 또는 그 반대로 벡터의 각도가 됩니다. ``end_angle``가 ``start_angle``보다 작으면 호가 시계 반대 방향으로 그려지기 때문에 ``end_angle``를 양수 값으로 정규화해야 했습니다. 이 경우에는 원하지 않습니다(호는 거꾸로 됩니다).

결과는 다음과 같아야 합니다. 호는 아래로 내려가고 점 사이에 있어야 합니다.

../../_images/draw_arc_between_2_points.webp

다양한 결과를 얻기 위해 인스펙터의 매개변수를 자유롭게 사용해 보십시오. 성능을 추가하는 대신 색상, 너비, 앤티앨리어싱을 변경하고 세그먼트 수를 늘려 곡선의 부드러움을 높입니다.