반응형

Godot엔진에 대해 알아보겠습니다. 이름(...이라기보다는 발음)에 대한 논란이 지속적으로 발생하여 새로운 이름에 대해 커뮤니티를 중심으로 끊이지 않자, 최근 새로운 이름 Godette로 변경하였습니다. 아울러 마스코트도 이상한 톱니머리 얼굴이 아닌 예쁘장한 여학생 캐릭터를 만들었는데요. 머리에 뿔은 이 엔진의 동질성일까요? 계속 동일한 뿔모양을 가져가는 모습입니다. 본 포스팅에서는 기존부터 익숙히 알고 있던 이름인 관계로 Godot라는 명칭을 사용하겠습니다.

 

아르헨티나에 본사를 둔 OKAM이라는 회사에서 인하우스 툴로 사용하던 게임엔진로 이를 MIT 라이센스하에 오픈소스로 배포한 것이라고 합니다. 주요 특징으로는

 

1. 완전 무료

MIT 라이센스 하에 배포되다보니 다른 제한사항도 없고 사용은 물론 수정하여 배포하는 것, 상용으로 사용하는 것까지도 완전 무료인 게임엔진입니다. 그리고 앞으로도 항구적 무료를 유지하기 위해 이를 비영리 자선기관인 Software Freedom Conservancy(소프트웨어 자유 보호단)가 법적으로 대리하고 있다고 합니다. 

 

2. 크로스플랫폼 지원

Godot 엔진은 주요 데스크톱 플랫폼(Linux, macOS, Windows)은 물론 모바일(Android, iOS) 및 웹 기반(HTML5) 플랫폼까지 지원하는 특징을 갖고 있습니다. 

 

3. 작은 용량

Windows용 Standard 64bit버전은 27.4MB, C#을 지원하는 Mono 64bit 버전은 57.9BM에 불과할 정도로 매우 작은 용량입니다. 단, 게임을 배포하려면 템플릿을 추가로 받아야 하는데, 이게 약 200MB정도로 꽤 큽니다. 그럼에도 불구하고 코드편집기, 애니메이션 편집기, 타일맵 편집기, 셰이더 편집기, 디버거 등이 포함되어 있습니다.

 

4. 지원언어

Godot엔진은 GDScript라는 자체 스크립트 언어를 사용하고 있습니다. 기존에는 Lua를 사용했고, Python으로도 구현해보려고 하였으나, 여러가지 사유로 결국 자체 스크립트 언어를 만들게 되었다고 합니다. 그 외에도 C#, C++을 지원하고 있으며, 순수 Python을 사용할 수도 있는데, Addon과 C컴파일러를 별도로 설치해야 하는 등의 불편이 좀 있습니다. 그리고 VisualScript를 지원합니다. Visual Script는 일일이 코딩하는 방식이 아니라 블럭을 연결하는 방식으로, 비프로그래머에게 어필하기 위한 스크립팅 방식입니다. 그리고 Community에 의해 구축된 진짜 Python, Rust, Lua 지원 라이브러리도 있습니다. 

 

5. Godot의 핵심 개념

엔진 내에서 대부분의 게임 요소는 트리 구조의 씬(Scene)으로 만들어집니다. 장면, 게임오브젝트, 캐릭터 등이 하나의 씬, 또는 여러개의 씬을 트리로 만들어 작동합니다. 씬은 노드(Node)가 모여 이루어지며, 노드는 다시 리소스(Resource)가 모여 이루어집니다. 게임에 필요한 기능 대부분은 이 노드를 이용하여 만듭니다. 예를 들어 버튼을 만들기 위한 'Button' 노드가 있고 타일맵을 만들기 위한 'TileSet'노드와 이를 사용하는 'TileMap' 노드가 있다. 씬도 다른 씬의 하위 멤버로 추가하여(인스턴싱) 다른 씬의 노드가 될 수도 있습니다. 이렇게 여러 노드와 씬이 중첩되어서 캐릭터가 되고, 아이템이 되고 노드끼리 시그널을 주고 받으면서 게임을 만드는 것이 Godot의 컨셉입니다.
 

(1) Scene(장면, 씬)

Godot에서의 게임은 재사용 씬을 모아 구성됩니다. 캐릭터, 무기, 사용자 인터페이스의 메뉴, 집 한채, 레벨 전체 등 생각할 수 있는 모든 것이 씬으로 구성될 수 있습니다. 유니티 엔진에서의 프리팹과 씬의 역할을 모두 수행합니다.

씬의 하위에 다른 씬을 배치할 수도 있습니다. 예를 들어 Player씬을 Level씬에 드래그앤 드랍으로 끌어다가 하위에 배치할 수 있습니다.

 

(2) 노드(Node)

씬은 하나 이상의 노드로 구성 됩니다 . 노드는 씬 트리를 구성하는 가장 기본이되는 요소입니다. 아래는 Character 씬의 노드 구성 예입니다. 물론 노드 내부는 수많은 Resource들로 구성되어있지만, 각 노드는 하나의 역할을 하도록 구성되어 있어, Godot에서의 게임 제작은 노드를 기준으로 생각하는 것이 적절합니다.

KinematicBody2D노드를 이용하여 "Character"노드를 만들고, 하위 구성으로는 이미지를 담당하는 Sprite2D노드, 카메라를 담당하는 Camera2D노드, 충돌을 감지하는 CollisionShape2D노드가 모여 구성됩니다. 이 씬(Character)을 다른 씬의 하위로 다시 불러오게 되면 하위 노드들(Camera2D 등)은 나타나지 않고 Character 노드 하나만 나타납니다. 모두 나타나게 하기 위해서는 '편집할 수 있는 자식' 기능을 체크해서 편집을 계속 할 수도 있습니다.

Godot는 다양한 기능을 수행할 수 있는 기능 라이브러리를 제공합니다. 2D, 3D작업 및 사용자 인터페이스 구성에서 대부분의 작업을 이 노드 리스트들을 사용하여 수행합니다.

 

 

(3) 씬 트리

최종 게임은 여러 씬들이 모여 씬 트리 형태로 표시됩니다. 각각의 씬도 결국 노드들의 트리지만, 하위 씬을 추가했을 때에는 기본적으로 씬도 단일 노드로 표시됩니다. 캐릭터, 무기, 문 또는 사용자 인터페이스를 나타낼 수 있는 씬의 관점에서 게임을 생각하는 것이 더 게임 제작 및 관리 입장에서 좀 더 효율적일 수 있습니다. 단, '편집할 수 있는 자식' 기능을 체크할 경우 자식노드도 표시하여 편집을 계속할 수 있습니다.

 

(4) 시그널

노드들 간에 통신을 할 수 있는 시그널의 개념이 있습니다. 예를 들면 CollisionShape 에 적이 충돌하면 죽거나, 키보드 클릭했을 시 움직임 등을 처리할 수 있게 되는거죠.

 

 

 

 

반응형
반응형

- stage_menu.tscn에서 새 스크립트를 추가

- game.gd로 저장

<game.gd>

- Project Settings > Autoload 에 game.gd파일 추가

- hud에 최고기록을 표시하는 라벨 추가

- stage_game.tscn > tex_score 노드 추가

- 노드 이름을 tex_bestscore로 변경

- 스크립트를 clear해주고, 다시 builtin script 추가

- 스크립트 이름을 tex_bestscore로 지정

- stage_game.tscn씬 > tex_score노드 > tex_score스크립트 수정

 

...길다....

 

- 끝 -

반응형
반응형

- 새로운 씬 생성

- 빈 Node 추가 후 audio_player로 이름 변경, audio_player.tscn으로 저장

 

- Music 추가하기

- AudioStreamPlayer노드 2개 추가

- 하나는 배경음악 설정을 위한 노드 (background로 이름 변경), Sound에 music.ogg설정

- 다른하나는 효과음 설정을 위한 노드 (effect로 이름 변경)

- Autoplay에 체크하여 시작 후 계속 플레이되도록 설정

 

- audio_player.gd 스크립트 추가

extends Node

func _ready():
	pass
	
func play(sample_name):
	#get_node("AudioStreamPlayer").play(sample_name)
	get_node("effect").stream = load(sample_name)
	get_node("effect").play()
	pass

기존 예제에 존재하던 sample_player노드가 사라짐에 따라, 직접 AudioStreamPlayer에 파일을 읽어주는 방식으로 변경함.

 

- audio_player씬을 autoload에 등록.

   프로젝트 어디에서든 실행코드 불러와 사용 가능. 또한 게임 시작 시 자동으로 최초 입력한 배경음악파일(music.ogg)을 실행함.

 

<스크립트 추가>

- ship.gd

- enemy.gd

- laser_ship.gd

- laser_enemy.gd

- powerup_armor.gd

- powerup_laser.gd

- explosion.gd

- 게임 시작 후 enemy 출현까지 약간의 시간간격을 줌

반응형
반응형

<powerup>

- 새로운 씬 생성 후, Area2D노드 추가

- 이름을 powerup으로 변경 후 powerup.tscn으로 저장

- Sprite노드 추가 후 이름을 sprite로 변경

- CollisionShape2D노드 추가 후 이름을 shape으로 변경

- New RectangleShape2D 지정

 

- Extends: (7,7)로 변경

- powerup노드에 powerup.gd스크립트 추가

<powerup_armor>

- 상속씬으로부터 만들기 > powerup.tscn선택

- 이름을 powerup_armor로 변경하고 powerup_armor.tscn으로 저장

- 기존의 스크립트를 제거

- powerup_armor.gd스크립트 새로 추가

 

<ship.gd> 스크립트 수정

- 새로운 상속씬 생성

- powerup.tscn을 상속하여 powerup_laser.tscn생성 후 저장

- sprite > Texture에 powerup_laser.png 지정

- 스크립트 제거 후 새로 생성

- powerup_laser.gd 로 저장

 

<powerup을 무작위로 생성해주는 spawner 시스템>

- spawner enemy.tscn을 상속하여 새로운 씬 생성

- 상속 클리어

- 이름을 spawner_powerup으로 변경

- 스크립트를 고유하게 변경

- 스크립트를 spawner_powerup.gd로 저장

<spawner_powerup.gd>

- stage_game.tscn에 하위씬으로 추가한 후,

- spawner_enemy보다 위쪽에 위치시킴

반응형
반응형

- ship.gd스크립트 수정

- armor_changed 시그널 추가

- set_armor함수에 emit_signal 추가

- Canvas2D노드 추가 후 hud로 이름 변경

- 하위에 sprite노드 추가 후 spr_armor로 이름 변경

- Sprite Texture에 armor.png파일 지정

- Centered는 해제하고,

- 총 수평방향으로 5개의 프레임이 존재(Hframes:5) 인식

- 현재 프레임은 4번째 프레임을(Frame: 4)인식시켜준다.

- spr_armor노드에 스크립트 추가 (Built-In-Script형태로 추가해준다.)

<Score시스템>

- TextureFrame TextureRect노드를 추가 후 tex_score로 이름 변경

- Texture에 score.png 파일 추가

- 노드 사이즈를 적절히 조정 후 Pos (123, 10) 으로 위치 지정

- tex_score하위에 label노드 추가하여 이름을 label로 변경

- Text: 0, Align: Right, Pos:(3,1), Size:(41,14) 지정

- 다이나믹 폰트 지정

- tex_score에 built-in-sciprt 추가

- Name: tex_score 지정

-  새로운 값이 들어오면 텍스트를 새 값으로 변경해줌

- 새 값을 전달해주는 함수는 enemy.gd에서 수정

 

<main메뉴 만들기>

- 빈 Node를 추가하여 이름을 main으로 바꾸고

- stage_menu.tscn으로 저장

- CanvasLayer2D노드 추가 후 hud로 이름 변경

- TextureButton 노드 추가 후 btn_start로 이름 변경

- Texture에서 각 경우에 맞게 텍스쳐 이미지 지정

    Normal: button_normal.png

    Pressed: button_pressed.png

    Hover: button_hover.png

- 위치 조정 (67, 134)

- 하위에 라벨 노드를 추가하고, Text: Start, Align:Center 지정

- 노드 사이즈를 이미지에 맞게 조정

- 폰트를 HUD의 다이나믹 폰트에서 복사/붙여넣기 한다.

<Quit버튼 만들기>

- btn_start를 복제하여 만들기

- 위치를 67,155로 변경

- Text: QUIT 로 변경하고 위치 미세조정

- btn_start에서 스크립트 추가(Attach Script)

- 이름을 btn_start로 지정 후 스크립트 생성

- btn_quit노드에도 built-in-script추가

- Name: btn_quit 지정

- btn_start의 스크립트를 복사 후, _on_pressed()함수에서 작동하는 부분만 수정

- Project Settings에서 시작씬으로 stage_menu.tscn을 지정

< 죽었을 때 메뉴버튼 나타내기>

- stage_game.tscn > hud노드에 Merge from Scene

- stage_menu.tscn > btn_start 버튼을 가져온다.

- 버튼 이름을 btn_menu로 변경하고,

- label노드의 Text: MENU로 변경한 뒤 노드 사이즈를 미세조정한다.

- 시작시에 이 버튼은 나타나지 않도록 숨겨줌

- 스크립트는 고유하게 변경해줌

- 스크립트 편집

시그널 " exit_tree" -> " tree_exited" 로 변경

 

반응형
반응형

<폭발 시 카마레 진동 효과>

- world씬에 camera2D노드 추가

- 카메라 스크립트 추가

<camera.gd>

<laser_ship.gd> 수정

<laser_enemy.gd>수정

<explosion.gd>수정

<붉은 화면 깜빡이기>

- 새로운 씬 생성하고 sprite노드를 추가하여 flash라고 이름을 바꿔 flash.tscn으로 저장한다.

- Texture에 rectangle.png파일을 지정하고

- Centered를 해제한 뒤, 화면 사이즈보다 약간 크게 확장한다.

- Modulate에 빨간색을 지정한다. 

- Z값을 15로 지정한다.

- 하위노드로 Merge from Scene > flare.tscn > anim노드를 추가한다.

- Make Sub-Resources Unique로 고유하게 변경한다.

- 재생 길이를 0.3으로 변경하고 마지막 프레임도 0.3 위치에 놓는다.

- 다시 0프레임에 위치시킨 후 스크립트를 추가한다.

 <flash.gd>

- 적용을 위해 ship.gd파일 수정

<ship.gd>

- flash.tscn을 미리 불러오기

- 아머가 하나씩 줄 때마다 flash씬을 실행(자식노드로 추가)

반응형
반응형

<폭발>

 

- 새로운 씬 생성

- sprite노드 추가 후 explosion 으로 변경

- Texture 지정

- Z 값을 5 정도로 상향 조정

- explosion에 하위노드로 Particles2D 노드 추가

- 이름을 p_smoke로 변경

- 각종 파라미터 적절히 변경

- Texture 를 클릭하여 smoke.png를 할당

 

- 추가 설정

- 추가 설정

- 추가 설정

- emmiting 기능으로 애니메이션 확인

- p_smoke 노드를 복사하여 p_flare노드 생성

- Texture에 flare.png파일을 할당하여 애니메이션 확인

- 노드 추가 > Merge from scene > flare.tscn 선택

- anim노드 선택

- 애니메이션이 영향받지 않도록 유니크하게 만들기

- length를 0.7초로 변경하고,

- 마지막 프레임을 0.7초 위치로 변경시킨다.

- explosion노드에 explosion.gd 스크립트를 추가

<ship.gd>에서 폭발 애니메이션 스크립트 추가 

<enemy.gd>스크립트 수정 (enemy.tscn)

- 소스코드는 ship.gd의 함수와 동일

- 충돌 시 폭발하는 부분도 동일하게 추가하는 것 주의

- ship에서 발사되는 레이저가 2개인 관계로, enemy와 충돌할 시 폭발이 2번 발생하는 오류가 있음

- 따라서 enemy가 폭발중일 때에는 처리하지 않도록 문구 추가 필요

반응형
반응형

<ship.gd> 수정

- 스크립트에 체력(armor) 변수를 설정

- "ship"그룹에 추가

- 체력이 0 이하로 가면 삭제되는 set_armor함수 추가

<enemy.gd> 수정

- 스크립트에 체력(armor) 변수를 설정

- "enemy"그룹에 추가

- 체력이 0 이하로 가면 삭제되는 set_armor함수 추가

- enemy_kamikaze.tscn의 Armor값은 2로 설정

- enemy_clever.tscn의 Armor값은 6으로 설정

<laser 수정>

- laser_ship.tscn을 불러와서 기존의 laser.gd스크립트를 제거

- 새로운 스크립트 laser_ship.gd 생성

- 속도를 -350으로 설정

<laser_ship.gd>

- "area_enter"이벤트 발생 시 "_on_area_enter"함수와 연결

- 접촉한 외부물체가 "enemy"이면 Armor를 -1 차감

- 플레어 생성

- 레이저 자체는 삭제됨(queue_free())

- 아직 enemy가 죽지 않음. laser_ship.tscn의 상위인 laser.tscn의 shape에 아무것도 지정되지 않음

- laser.tscn > shape에 RectangleShape2D 설정

<laser_enemy.gd>

- laser_enemy.tscn에서 기존의 스크립트 laser.gd 제거

- 새로운 스크립트 laser_enemy.gd 생성

- 기존의 laser_ship.gd의 내용을 복사해옴

- 충돌 감지 대상만 "enemy" -> "ship"으로 변경

- laser_enemy의 속도는 150으로 재설정

 

- 마지막으로 enemy.tscn에서

- enemy와 충돌했을 때에 ship의 armor를 -1 차감하고

- 충돌한 enemy는 사라지는 함수(_on_area_enter) 구현

반응형

+ Recent posts