2D 이동 개요

소개

Every beginner has been there: "How do I move my character?" Depending on the style of game you're making, you may have special requirements, but in general the movement in most 2D games is based on a small number of designs.

우리는 이번 예제에 KinematicBody2D 를 사용할 겁니다. 하지만 원리는 다른 노드 유형(Area2D, RiqidBody2D)에도 적용할 수 있습니다.

Setup

아래의 각 예제는 동일한 씬 설정을 사용합니다. KinematicBody2D 와 자손 노드로 SpriteCollisionShape2D 로 시작합니다. 당신은 스프라이트 텍스처로 Godot 아이콘("icon.png")을 사용하거나 가지고 있는 다른 2D 이미지를 사용할 수 있습니다.

프로젝트 -> 프로젝트 설정 을 열고 "입력 설정" 탭을 선택합니다. 다음의 입력 액션들을 추가하세요 (see InputEvent for details):

../../_images/movement_inputs.png

8 방향 이동

이 시나리오에서는 사용자가 4 방향의 키들(위/왼쪽/아래/오른쪽 또는 W/A/S/D)을 누르고 선택된 방향으로 움직였으면 합니다. "8 방향 이동" 명칭은 동시에 두 키를 눌러서 플레이어가 대각선으로 움직이게 되는 것에서 유래합니다.

../../_images/movement_8way.gif

kinematic body에 스크립트를 추가하고 다음과 같은 코드를 추가합니다:

extends KinematicBody2D

export (int) var speed = 200

var velocity = Vector2()

func get_input():
    velocity = Vector2()
    if Input.is_action_pressed("right"):
        velocity.x += 1
    if Input.is_action_pressed("left"):
        velocity.x -= 1
    if Input.is_action_pressed("down"):
        velocity.y += 1
    if Input.is_action_pressed("up"):
        velocity.y -= 1
    velocity = velocity.normalized() * speed

func _physics_process(delta):
    get_input()
    velocity = move_and_slide(velocity)

In the get_input() function, we check for the four key events and sum them up to get the velocity vector. This has the benefit of making two opposite keys cancel each other out, but will also result in diagonal movement being faster due to the two directions being added together.

이런 현상은 속도를 *정규화*해서 방지할 수 있습니다. 즉, *길이*를 ``1``로 만든 뒤 원하는 속력 값을 곱해주면 되겠죠.

벡터 수학을 사용해 본 적이 없거나 재교육이 필요한 경우 벡터 에서 Godot 내 벡터 사용에 대한 설명을 볼 수 있습니다.

참고

If the code above does nothing when you press the keys, double-check that you've set up input actions correctly as described in the Setup part of this tutorial.

회전 + 이동

이러한 이동의 유형은 때때로 "Asteroids-style"이라 불립니다. 왜냐하면 고전 아케이드 게임 Asteroids 작동 방식과 닮았기 때문입니다. 왼쪽 또는 오른쪽을 누르면 캐릭터가 회전합니다. 반면에 위 또는 아래를 누르면 보고 있는 방향에 대햐여 전진 하거나 후진합니다.

../../_images/movement_rotate1.gif
extends KinematicBody2D

export (int) var speed = 200
export (float) var rotation_speed = 1.5

var velocity = Vector2()
var rotation_dir = 0

func get_input():
    rotation_dir = 0
    velocity = Vector2()
    if Input.is_action_pressed("right"):
        rotation_dir += 1
    if Input.is_action_pressed("left"):
        rotation_dir -= 1
    if Input.is_action_pressed("down"):
        velocity = Vector2(-speed, 0).rotated(rotation)
    if Input.is_action_pressed("up"):
        velocity = Vector2(speed, 0).rotated(rotation)

func _physics_process(delta):
    get_input()
    rotation += rotation_dir * rotation_speed * delta
    velocity = move_and_slide(velocity)

여기에 회전 방향과 속도를 추적하기 위한 새로운 변수 두 개를 추가했습니다. 다시 두 키를 동시에 누르면 취소되고 회전하지 않습니다. 이 회전은 바디의 rotation 속성에 직접 적용됩니다.

속도를 설정하기 위해 우리는 Vector2.rotated() 메서드를 사용해 바디와 같은 방향을 가리키도록 합니다. ``rotated``는 삼각함수를 적용해야 하는 여러 가지 상황에서 사용할 수 있는 유용한 벡터 함수입니다.

회전 + 이동 (마우스)

이번 동작 방식은 이전 동작의 변형입니다. 이번에는 키보드 대신 마우스 위치에 의해 방향이 정해집니다. 캐릭터는 항상 마우스 포인터를 봅니다("look at"). 그러나 전방/후진 입력은 동일하게 유지됩니다.

../../_images/movement_rotate2.gif
extends KinematicBody2D

export (int) var speed = 200

var velocity = Vector2()

func get_input():
    look_at(get_global_mouse_position())
    velocity = Vector2()
    if Input.is_action_pressed("down"):
        velocity = Vector2(-speed, 0).rotated(rotation)
    if Input.is_action_pressed("up"):
        velocity = Vector2(speed, 0).rotated(rotation)

func _physics_process(delta):
    get_input()
    velocity = move_and_slide(velocity)

여기서 우리는 플레이어를 주어진 포지션으로 향하도록 하기 위해 Node2Dlook_at() 메서드를 사용하고 있습니다. 이 함수가 없으면 각도를 다음과 같이 설정하여 동일한 효과를 얻을 수 있습니다:

rotation = get_global_mouse_position().angle_to_point(position)

클릭과 이동

이번 마지막 예제는 마우스만 사용하여 캐릭터를 제어합니다. 화면을 클릭하면 플레이어는 지정 위치로 움직입니다.

../../_images/movement_click.gif
extends KinematicBody2D

export (int) var speed = 200

onready var target = position
var velocity = Vector2()

func _input(event):
    if event.is_action_pressed("click"):
        target = get_global_mouse_position()

func _physics_process(delta):
    velocity = position.direction_to(target) * speed
    # look_at(target)
    if position.distance_to(target) > 5:
        velocity = move_and_slide(velocity)

Note the distance_to() check we make prior to movement. Without this test, the body would "jitter" upon reaching the target position, as it moves slightly past the position and tries to move back, only to move too far and repeat.

Uncommenting the look_at() line will also turn the body to point in its direction of motion if you prefer.

This technique can also be used as the basis of a "following" character. The target position can be that of any object you want to move to.

요약

당신은 이 코드 샘플들이 자신의 프로젝트 시작점으로서 유용하다는 것을 알게 될 것입니다. 자유롭게 그것들을 사용해서 무엇을 만들 수 있을 지 실험해보세요.

여기에서 이 샘플 프로젝트를 다운할 수 있습닌다: 2D_movement_demo.zip