본문 바로가기
Programming/Godot

Godot 시작하기#1 - 프로젝트 설정 및 Player Scene

by Wilkyway 2021. 12. 22.
반응형

1. 프로젝트 설정

프로젝트 > 프로젝트 설정을 클릭한 후, display > window메뉴로 가서 width480, height720으로 설정해줍니다.

그리고, Stretch로 내려가서 Mode: 2d, Aspect: keep으로 변경해줍니다.

2. Resource 폴더 추가

dodge_assets 파일은 링크 에서 다운받을 수 있습니다. Godot엔진 홈페이지의 Your First Game 챕터에서 찾을 수도 있습니다. 압축을 풀어서 생성된 프로젝트 폴더에 집어넣으면 아래와 같이 자동으로 프로젝트에 폴더가 추가됩니다.

3. Player 씬 추가

왼쪽 씬 탐색기에서 다른노드 > Area2D검색 >Area2D 를 선택합니다.

노드를 더블클릭하여 이름을 Player로 바꿔줍니다. 그리고 Player.tscn으로 저장합니다.

 

그리고 자물쇠 아이콘 옆의 아이콘을 클릭해줍니다. 추후 자식 노드들이 추가될텐데, 자식노드들만 따로 선택되는 것을 방지해주는 기능이라고 합니다.

Player 노드 하위에 AnimatedSprite를 검색하여 추가합니다.

AnimatedSprite노드가 추가되면 우측의 Frames속성이 아직 [비었음] 상태입니다. [비었음]을 클릭하여 새 SpriteFrames를 선택합니다.

그리고 선택된 SpriteFrame를 한번 더 눌러주면 아래의 애니메이션 패널이 나타납니다.

4. 애니메이션 프레임 추가

Default를 walk라고 이름을 바꾸고, 새 애니메이션 추가 버튼을 클릭하여 up으로 이름으로 만들어줍니다. 아까 추가한 dodge_assets 폴더로 가보면 art라는 하위폴더가 있는데, 여기에서 PlayerGrey_walk1, 2는 walk프레임에, PlayerGrey_up1, 2는 up프레임에 드래그앤드랍으로 추가해줍니다.

다시 AnimationSprite노드를 클릭하고, 인스펙터 창에서 Node2D > Scale에서 x와 y를 각각 0.5로 입력하여 사이즈를 반으로 줄여줍니다.

5. 충돌감지노드 추가

Player노드에서 우클릭하여 새 노드를 추가합니다.검색창에 CollisionShape2D를 검색하여 추가해줍니다.

이 노드는 현재의 노드가 장애물(Mob)과 충돌을 감지할 수 있는 영역을 만들수 있게 해 줍니다. 즉, 이 노드만으로는 안되고, 실제 감지되는 영역을 지정해줘야합니다. 인스펙터 창에서 Shape > [비었음] 클릭 > 새 CapsuleShape2D 를 클릭하여 추가해줍니다.

그러면 캐릭터에 캡슐형 감지영역이 나타나게 됩니다.  감지영역의 핸들을 조정하여 적당히 커버될 수 있도록 조정합니다. 약간 이미지보다 작게 나타나도록 설정하는 것을 추천합니다.


6. Player 방향키 설정

적당히 진행하며 저장해주시고, 이제 Player의 움직임을 설정해줘야합니다. 여기서부터 코딩이 들어갑니다. Attach Script 버튼을 클릭합니다.

우선 필요한 변수를 선언합니다. (speed, screen_size)

export 키워드는 작업을 굉장히 편리하게 해 줍니다. 변수 앞에 export를 붙여주면 inpector 창에서 나타나게 됩니다. 그럼 inpector에서 값을 직접 설정하여, 테스트할 때 일일이 코드를 보지 않고도 테스트할 수 있도록 도와줍니다. 물론 스크립트에 설정된 기본값은 무시됩니다.

 

처음 게임이 시작되면 _ready()함수를 실행하게 되는데, 게임 창의 크기값을 가져와 screen_size라는 변수에 지정하도록 하겠습니다. 이 값은 나중에 활용할 계획입니다. 기존에 있던 pass 부분은 지워줍니다. 아무것도 안하는 함수일 때 필요한 지시어입니다.

func _ready():
    screen_size = get_viewport_rect().size

이제 진짜 움직임을 코딩합니다.

func _process(delta):
    var velocity = Vector2()  # The player's movement vector.
    if Input.is_action_pressed("ui_right"):
        velocity.x += 1
    if Input.is_action_pressed("ui_left"):
        velocity.x -= 1
    if Input.is_action_pressed("ui_down"):
        velocity.y += 1
    if Input.is_action_pressed("ui_up"):
        velocity.y -= 1
    if velocity.length() > 0:
        velocity = velocity.normalized() * speed
        $AnimatedSprite.play()
    else:
        $AnimatedSprite.stop()

우선 $AnimatedSprite.play() 의$는 get_node()의 단축 표기형입니다. get_node("AnimatedSprite").play()와 동일합니다. 위 코드는 아직 오류가 있는 것이 상하키와 좌우키를 동시에 누르면 1+1=2의 속도로 원래 움직임보다 더 빠르게 움직입니다.
다음으로 화면 밖으로 나가는 것을 방지하기 위해 clamp()함수로 영역을 지정해줍니다. func _process(delta)함수 하부에 이어서 아래 코드를 추가해줍니다.

position += velocity * delta
position.x = clamp(position.x, 0, screen_size.x)
position.y = clamp(position.y, 0, screen_size.y)

이제 "재생 장면" (F6)을 클릭하여 확인해봅니다.

이렇게 좌상단 구석에 우리 캐릭터가 위치하고 있습니다. 방향키를 눌러보면 움직이는 것이 보일 것입니다. 좀더 세부적인 동작은 아래에서 계속 하겠습니다.


7. 애니메이션 지정

Player가 상하로 움직일 때, 좌우로 움직일 때 각각 다른 애니메이션이 나오도록 지정을 해줘야 합니다. 방향을 역전시키는 것은 flip_v / flip_h 속성으로 간단히 만들 수 있습니다.

if velocity.x != 0:
    $AnimatedSprite.animation = "walk"
    $AnimatedSprite.flip_v = false
    $AnimatedSprite.flip_h = velocity.x < 0
elif velocity.y != 0:
    $AnimatedSprite.animation = "up"
    $AnimatedSprite.flip_v = velocity.y > 0

그리고, _ready() 함수에 아래 코드를 추가하여  게임 시작시 Player를 숨김상태로 시작하게 합니다.

hide()


8. 충돌 감지

이제 signal 기능을 이용하여 장애물과의 충돌을 인식시키도록 할 차례입니다. 스크립트 최상단 - extends Area2D 아래 - 에 아래 코드를 추가합니다.

signal hit

이렇게 하면 사용자가 정의하는 signal을 지정하게 됩니다. Player가 방출할 수 있는 signal의 종류는 Inspector창 옆의 Node탭에 보면 나타나게 됩니다. 방금 지정한 hit 시그널도 확인되는 것을 볼 수 있습니다.

본 게임에서의 장애물(Mob)은 RigidBody2D이고 body_entered(body: Node) 시그널이 발생하도록 할 계획입니다. 즉,

body_entered(body: Node)시그널 -> Player 사라짐

body_entered(body: Node)시그널 -> hit 시그널 -> 게임오버 진행 (Main.tscn에서 작성)

으로 구성할 예정입니다. 하단의 "연결" 또는 마우스 우클릭 후 "연결"을 클릭하고, 자동 생성된 함수명으로 "연결"을 클릭합니다.

그리고 연결되었다는 의미로 해당 함수 앞에 초록색 아이콘이 생성됩니다. 생성된 함수 내부에 아래와 같이 코딩합니다.

func _on_Player_body_entered(body):
    hide()  # 부닫히면 Player를 사라지게..
    emit_signal("hit")
    $CollisionShape2D.set_deferred("disabled", true)


이제 Mob이 Player와 충돌할 때마다 Signal이 방출되게 됩니다.

9. 초기화

마지막으로 새 게임 시작시 Player를 초기화하는 코드를 추가해줍니다.

func start(pos):
    position = pos
    show()
    $CollisionShape2D.disabled = false

 

<전체 코드:Player.gd>

extends Area2D

signal hit
export var speed = 400
var screen_size

# Called when the node enters the scene tree for the first time.
func _ready():
	screen_size = get_viewport_rect().size
	hide()


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	var velocity = Vector2()  # The player's movement vector.
	if Input.is_action_pressed("ui_right"):
		velocity.x += 1
	if Input.is_action_pressed("ui_left"):
		velocity.x -= 1
	if Input.is_action_pressed("ui_down"):
		velocity.y += 1
	if Input.is_action_pressed("ui_up"):
		velocity.y -= 1
	if velocity.length() > 0:
		velocity = velocity.normalized() * speed
		$AnimatedSprite.play()
	else:
		$AnimatedSprite.stop()
		
	# position
	position += velocity * delta
	position.x = clamp(position.x, 0, screen_size.x)
	position.y = clamp(position.y, 0, screen_size.y)
	
	# 방향 역전
	if velocity.x != 0:
		$AnimatedSprite.animation = "walk"
		$AnimatedSprite.flip_v = false
		$AnimatedSprite.flip_h = velocity.x < 0
	elif velocity.y != 0:
		$AnimatedSprite.animation = "up"
		$AnimatedSprite.flip_v = velocity.y > 0

func start(pos):
	position = pos
	show()
	$CollisionShape2D.disabled = false

func _on_Player_body_entered(body):
	hide()  # Player disappears after being hit.
	emit_signal("hit")
	$CollisionShape2D.set_deferred("disabled", true)

 

- Player Scene 끝 -

반응형

댓글