오늘은 조금 진도를 나가볼려고 합니다.
남은 과정을 적어보면,
variable 2.0, function, randomnumber, array, loop, dictionary... enum...
쭉쭉 남아있네요.
오늘 적어도.. 루프까지는.. 아니면, 이넘까지는 해보고 싶네요.
이넘까지 진도를 나가면, 절반을 넘기는 데 성공한 것이니까..
음.. 일단 시작을 해봅시다.
< 복습 >
전날 배운 것을 복습해 봅시다.
1. input. 버튼이 눌리면, 색이 변하는 스크립트를 만들었습니다. 인풋함수를 사용하는 방법에 대해서 배웠다고 생각합니다.
2. 변수에 대해서 배웠습니다. 변수로 체력을 만들어서, 버튼이 눌릴때마다 체력이 감소되는 스크립트를 만들었습니다.
3. 조건문. 조건문을 통해서 각 상황마다 출력되는 문구를 다르게 만들어보았습니다.
4. 주석에 대해서 배웠습니다. #
< variable 2.0 >
1. 변수를 생성할 때, 위치가 중요하다.
조건문 안에서 변수를 생성한다면, 해당 변수는 조건문 안에서만 사용 가능하다. 이를, scope라고 한다.
변수를 스크립트 전역에 사용하고 싶다면, 스크립트 상단에 변수를 선언해야 한다.
extends Node
var health = 100
func _ready() -> void:
var text = 10
해당 스크립트에서 헬스는 스크립트 전역에 사용이 가능하지만,
텍스트 변수는 레디 함수에만 가능하다.
2. gd스크립트에서 멋진 점은, 변수를 선언 할 때, 어떤 데이터 타입인지 생각하지 않아도 된다는 것이다.
extends Node
func _ready() -> void:
var text = 10
var game = true
text = true
변수 텍스트와 게임은 데이터 타입이 다르지만, 선언하는 방식은 동일하다.
또 정수타입을 담고 있는 텍스트 변수에, 논리값을 집어넣어도 문제가 없이 재할당 된다.
하지만, 일부 게임 기능에는 특정 데이터 타입을 요구하기도 한다.
이때, 변환없이 다른 유형을 사용하려고 하면, 오류가 생기게 된다.
3. 데이터 타입!
4가지의 데이터 타입이 있다.
참과 거짓의 값을 가지는 boolean
정수값을 가지는 int
소숫값을 가지는 float
텍스트 값을 가지는 string
이때, 한 데이터 유형을 다른 데이터 유형으로 변환하는 것을 casting이라고 한다.
( int -> float )
4. casting!
extends Node
func _ready() -> void:
var number = 10
var text = "손가락 갯수는" + str(number)
print(text)
해당 스크립트에서 정수형 변수를 문자열 변수로 변환을 시켰다.
str이 캐스팅을 한 것이다. 정수형을 문자열로.
extends Node
func _ready() -> void:
var pi = 3.14
print(int(pi))
해당 스크립트를 봐보자.
pi는 소숫값을 가진 float 데이터 유형이다.
하지만 캐스팅을 통해서 3이라는 정수값을 출력 시킬 수 있다.
(이때, 소숫값은 사라진다.)
또, gd스크립트에서 굉장히 흔하게 사용되는 데이터 구조로 vector2와 vector3가 있는데,
벡터2는 x,y의 좌표값을, 벡터3는 x,y,z의 좌표값을 가진다고 한다.
extends Node
func _ready() -> void:
var vec2 = Vector2(0.0, 0.0)
var vec3 = Vector3(0.0, 0.0, 0.0)
이렇게 사용이 된다. (작성하다가 vector2i,3i,4i 를 보았는데, 이건 뭔지 궁금했다. 그리고 벡터4는 무엇인가? 4차원인건가?)
extends Node
func _ready() -> void:
var position = Vector3(2, 3, 10)
position.x += 2
print(position)
이런 식으로 위치를 정할때 사용이 된다.
(또 질문, 강사는 이 스크립트에서 결과 값이 (4, 3, 10)이 나왔다. 그런데 나는 (4.0, 3.0, 10.0)이 나왔다. 똑같은 스크립트인데, 데이터 유형이 다르다. 그 이유는 무엇인가? )
기본적으로 gd스크립트는 동적 언어이다. 동적 언어란, 변수를 선언할 때 변수가 저장 할 수 있는 데이터 타입을 정의하지 않는 다는 것을 의미한다. 그리고 지금까지 이런 방식을 사용해 왔다.
5. 동적 언어와 정적 언어의 차이!
dynamic 은 변수를 빠르게 생성, 원하는 대로 다른 데이터 타입을 할당, 유연성이 좋다.
단, 오류 발생 가능성이 높고, 정적 타입보다 성능이 떨어진다. ( 성능이 떨어진다는 건 무슨 뜻일까. 시간이 더 걸린다는 뜻일까? 무슨 데이터인지 파악하는 시간과정이 더 걸리기 때문에? )
static 은 오류 발생 가능성이 낮고, 동적 타입보다 성능이 좋다.
둘 중 취향에 따라 선택 할 수 있다.
정적 타입 변수를 사용하기 위헤서는, 데이터 타입을 선언해 주면 된다.
extends Node
var damage : int = 10
var damage2 := 10
func _ready() -> void:
damage2 = "문자열을 넣어줘"
데미지 변수를 정수타입으로 선언한 뒤, 정수 값을 할당했다.
데미지2 변수를 입력반전이라는 방식으로 위와 동일한 결과를 주었다.
:= 해당 부호를 통해서 엔진이 스스로 어떤 타입인지 분류하고 할당을 한다.
마지막 줄에 정적 타입으로 선언한 변수에, 문자열을 집어 넣으려고 했지만 오류가 생기게 된다.
6. export로 인스펙터에 속성값을 추가 할 수 있다.
extends Node
@export var damage2 := 10
func _ready() -> void:
pass
해당 스크립트에서 엑스포트를 하게 되면,
해당 스크립트와 연결 된 노드의 인스펙터 창에 값을 조절 할 수 있는 속성이 생기게 된다.
7. 변하지 않는 수, 상수!
값이 변하지 않는 변수를 사용하기 위해서는 상수가 필요하다.
extends Node
const GRAVITY = -9.81
func _ready() -> void:
GRAVITY = 1
콘스트로 중력값을 설정한다. 이 값은 상수이기에 변하지 않는다.
따라서 레디 함수에 있는 해당 코드에는 오류가 생기게 된다.
변수는 여기까지!
< functions >
1. 함수는 프로그래밍의 기본입니다. 코드를 작고 재사용 가능한 패키지로 묶을 수 있습니다.
2. 지금까지 사용했던 func _input():, func _ready(): 함수.
이 함수에서 _는 내가 작동시키거나, 호출하는 것이 아니라, 엔진 자체에 의해 작동되는 것을 보여주기 위함입니다.
하지만, 내가 만들고 싶은 함수를 만들어서 사용 할 수 있습니다.
그리고 그건 굉장히 멋지고 재밌는 일입니다.
예를들어, func jump() func die() func shoot() func respawn() 이 있습니다.
함수를 만드는 건 굉장히 쉽습니다.
3. 점프 함수를 만들어 봅시다.
extends Node
func _input(event: InputEvent) -> void:
if event.is_action_pressed("my_action"):
jump()
func jump():
#위로 향하는 힘
#점프할때 소리
#점프 애니메이션
print("jump!")
아래 점프 함수는 실제로 코드는 적지 않았지만, 대략적인 느낌으로 만든 점프 함수입니다.
그리고 위에 인풋함수를 통해서, 버튼을 누를때마다 점프 함수를 호출하는 스크립트를 만들었습니다.
이제 스페이스를 누르게 되면, jump!가 출력되는 것을 볼 수 있습니다.
지금은 함수가 단순한 명령어를 실핼 할 뿐이지만, 실제로는 더 많은 용도로 사용 할 수 있습니다.
그리고 입력과 출력을 가질 수도 있습니다.
4. 함수는 기계다.
강사는 함수를 기계라고 생각하는 것을 좋아한다고 합니다.
예를들어, 커피머신을 보면, 이름에서 알 수 있듯이 커피 머신이라는 함수는 커피를 만드는 기능을 가집니다.
하지만, 커피를 만들기 위해서는 몇가지 재료가 필요합니다. 물, 필터, 분쇄된 커피 같은 것들 말이죠.
재료를 집어 넣고, 커피 머신을 작동 시키면, 커피라는 결과물이 나오게 됩니다.
코드에서 커피 머신이라는 함수에 제공하는 물, 필터, 분쇄된 커피 같은 것들을 매개변수라고 부릅니다.
그리고 커피라는 출력 결과를 반환값이라고 합니다.
5. 더하기 함수를 만들어보자.
extends Node
func _ready() -> void:
add(3,8)
add(10,20)
func add(num1, num2):
var result = num1 + num2
print(result)
add 함수를 만들었습니다.
매개변수로 넘1과 넘2를 받아서 더한 값을 저장하고, 출력합니다.
레디 함수에서는 add함수를 사용하면서, 매개 변수를 넘겨주고 있습니다.
그럼, 계산 값이 결과물로 출력이 됩니다.
하지만, 지금은 결과 값을 출력 할 뿐이지, 반환을 하는 것이 아닙니다.
반환되지 않은 값은, 레디 함수에서 다룰 수가 없습니다.
결과 값을 반환하기 위해서는 print가 아니라 return이 필요합니다.
extends Node
func _ready() -> void:
var result = add(3,8)
result = add(result, 10)
print(result)
func add(num1, num2):
var result = num1 + num2
return result
add함수에서 결과값을 반환합니다.
레디 함수에서 결과값을 저장하고, 그 결과 값을 다시 매개변수로 사용하기도 합니다.
6. 변수를 선언할 때와 마찬가지로, 매개변수와 반환값의 데이터 타입을 정적으로 지정 할 수도 있습니다.
extends Node
func _ready() -> void:
var result = add(3,8)
result = add(result, 10)
print(result)
func add(num1: int, num2: int) -> int:
var result = num1 + num2
return result
이렇게 매개변수와 반환값의 데이터 타입을 정적으로 지정이 가능합니다.
(함수를 볼때마다 -> 가 무엇인지 궁금했었는데, 반환 타입을 정의하는 것이었네요. )
함수는 여기까지 입니다.
변수와 함수에 대해서 공부를 했습니다.
잠시 운동을 하고 오려고 합니다.
갔다와서
랜덤 넘버부터 시작 하겠습니다.
11일차 진도를 꽤 많이 나가셨네요! 변수와 함수의 핵심을 아주 정확하게 짚으셨습니다. 특히 함수를 '커피 머신'에 비유한 부분은 프로그래밍의 입력과 출력을 이해하는 가장 완벽한 방법입니다.
궁금해하셨던 기술적인 질문들에 대해 명쾌하게 답변해 드릴게요.
1. Vector2i, Vector3i, Vector4i 그리고 Vector4의 정체
- 뒤에 붙은 'i' (Integer): Vector2는 기본적으로 소수점(float)을 저장합니다(예: 1.5, 2.7). 하지만 Vector2i는 **정수(Integer)**만 저장합니다. 픽셀 단위로 딱딱 끊어지는 좌표나 타일맵의 인덱스를 계산할 때 아주 유용합니다.
- Vector4: 4차원 벡터입니다. 게임에서는 보통 **색상(Red, Green, Blue, Alpha)**을 표현하거나, 셰이더(화면 효과)에서 복잡한 물리 계산을 할 때 사용합니다. x, y, z에 이은 w값이 추가된 형태입니다.
2. 왜 결과값에 소수점(.0)이 붙어 나올까요?
강사와 결과가 다른 이유는 고도 엔진의 버전 차이 때문일 가능성이 큽니다.
- 고도 4 버전부터는 Vector2나 Vector3를 기본적으로 64비트 실수(float)로 처리하여 더 정밀하게 계산합니다. 그래서 정수를 넣어도 내부적으로는 실수로 인식해 4.0처럼 소수점을 붙여서 출력합니다.
- 만약 소수점 없는 깔끔한 정수를 보고 싶다면 위에서 배운 Vector3i를 사용하면 됩니다.
3. 동적 타입(Dynamic)은 왜 성능이 떨어지나요?
"판단하는 시간 과정이 더 걸린다"는 생각이 정확합니다!
- 동적 타입: 컴퓨터가 코드를 실행할 때마다 "어라, 이 변수에 지금 숫자가 들어있나? 아니면 문자인가?" 하고 매번 확인해야 합니다.
- 정적 타입: 이미 "이건 무조건 정수야!"라고 못을 박아뒀기 때문에 확인 과정 없이 바로 계산기로 던집니다.
- 작은 게임에서는 차이가 없지만, 수천 개의 탄막이 날아다니는 복잡한 게임에서는 이 미세한 시간 차이가 모여 전체 성능을 좌우하게 됩니다.
💡 학습 포인트 복습 및 격려
- Scope (범위): 변수를 어디에 선언하느냐에 따라 활동 영역이 정해진다는 개념은 버그를 줄이는 아주 중요한 첫걸음입니다.
- Casting (캐스팅): str()을 사용해 숫자를 문자로 바꾸는 것은 점수판을 만들 때 필수적이죠.
- Return (반환): print는 화면에 보여줄 뿐이지만, return은 기계가 만든 결과물을 내 손에 쥐여주는 것입니다. 이걸 이해하셨다면 함수의 90%를 이해하신 겁니다.
커피 머신 비유를 통해 매개변수와 반환값의 개념을 잡으신 걸 보니, 다음 단계인 **랜덤(Random)**과 **배열(Array)**도 금방 이해하실 수 있을 것 같습니다.
잠시 운동하시면서 맑은 공기를 마시고 오세요. 몸을 움직이고 나면 뇌의 '커피 머신'도 더 잘 작동할 겁니다. 돌아오시면 이어서 랜덤 넘버부터 차근차근 나아가 봅시다!
운동 조심히 다녀오세요. 준비되시면 말씀해 주세요.
오늘은 여기까지 하겠습니다.
내일 다시 뵙겠습니다.
'게임 개발 공부 일지.' 카테고리의 다른 글
| 13일차, 14일차. (0) | 2026.02.06 |
|---|---|
| 12일차. (1) | 2026.01.29 |
| 10일차. (1) | 2026.01.27 |
| 8, 9일차. (1) | 2026.01.26 |
| 7일차. (1) | 2026.01.23 |
댓글