티스토리 뷰

728x90

"리듬 게임 분석하기" 글에 이어서 여러 가지 기술적 요소를 살펴보고 있다.

 

리듬 게임은 첫 화면에서 원하는 음악을 선택하고 [Go] 버튼을 누르는 것으로 시작한다. 데모에서는 3가지 트랙을 담고 있는데 개별 트랙을 선택하는 방법은 상단의 사각형을 좌우로 드래그하는 것이다. 각 음악 트랙을 서로 다른 색상의 사각형으로 표시하고 있는데 이때 사용하는 주요 클래스는 Area2D, Sprite, CollisionShape2D 등이다.

 

■ Area2D 클래스

게임 개발에 있어 2D든 3D든 자주 사용하게 되는 것이 두 오브젝트가 겹치거나 닿을 것 같은 상황을 감지하는 충돌 감지와 충돌에 대한 반응을 처리하는 것으로 고도 엔진에서는 물리 몸체(Physics Body)로 Area2D를 비롯하여 StaticBody2D, RigidBody2D, KinematicBody2D를 제공한다. 2D 몸체지만 각각 유사한 형태의 3D 몸체도 제공한다. 지금 다룰 Area2D를 제외하면 나머지 몸체들은 PhysicsBody2D를 상속한다.

 

나머지 몸체를 잠시 소개하면 StaticBody2D는 단어처럼 동적 반응이 필요 없는 정적 요소에 적용한다. 물리 엔진에 의해 움직이지 않고 충돌 감지에만 사용한다. RigidBody2D는 "뻣뻣한"이란 번역이 적절한 몸체로 이에 대한 직접적인 제어 대신에 중력, 충격 등의 힘을 가하면 물리 엔진이 알아서 계산 결과를 만들어 낸다. KinematicBody2D는 "운동학적인"이란 의미이지만 게임 엔진 초보자에게는 친근하지 않은 개념일수 있다. 고도에서는 충돌 감지를 제공하지만 충돌에 대한 움직임이나 반응은 코드로 직접 기술해야 하는 몸체다.

 

Area2D는 2D 영역을 정의하여 오브젝트가 겹치거나, 들어온 것, 나간 것을 감지해서 시그널을 발생시킬 수 있으며 내부의 중력, 감쇠 등의 물리 속성을 재정의할 수도 있다.

 

위의 그림은 Area2D 클래스를 사용한 사례로 공통적으로 자식 노드로 CollisionShape2D를 두고 있음을 확인할 수 있다. CollisionShape2DCollisionPolygon2D 클래스를 활용하여 충돌 감지를 위한 영역을 편집기에서 직접 정의할 수 있다. Area2D와 같은 물리 몸체는 최소한 하나 이상의 Shape2D로 영역을 정의해야 한다.

 

리듬 게임에서는 RectangleShape2D로 사각형 모양의 영역을 정의하고 있다.

 

Area2D 클래스는 위의 그림과 같은 속성들을 가지고 있다. Area2D 클래스의 기본 아이콘과 각 속성들에 대한 설명은 다음과 같다.

monitoring : true면 다른 물리 몸체나 영역이 들어오고 나가는 것을 감지

monitorable : true면 다른 물리 몸체나 영역이 나를 감지할 수 있도록 허용

◇ priority :우선순위로 높은 우선순위를 먼저 처리한다.

▽ Physics Overrides : 물리 옵션을 변경할 때 사용. 사용하려면 space_override 속성을 0(Disabled)이 아닌 값으로 설정.

space_override : 기본값은 0(Disabled) 아래의 값들로 적용 가능.

    Combine : 지금까지 계산된 값에 영역 값을 추가.

    Replace : 물리 옵션을 영역 값으로 대치, 우선순위가 낮은 것들은 무시된다.

    Combine-Replace : 지금까지 계산된 값에 영역 값을 추가하고 우선순위가 낮은 것들은 무시

    Replace-Combine : 지금까지 계산된 중력 및 감쇠 값은 영역 값으로 대치하고 나머지는 유지

◇ gravity_point : 중력점 사용 여부. true면 gravity_vec로 지정한 위치로 모이도록 한다.

◇ gravity_vec : 중력점 위치. 영역의 중심을 기준으로 한 상대 값으로 (0, 0)은 영역의 중심이 기준점이 되게 한다. 

    (0,-1)처럼 지정하면 수직으로 역 중력이 동작하게 된다.

◇ gravity_distance_scale : 중력가속도. 값이 클수록 거리에 따른 빠른 중력 감소를 보인다.

◇ gravity : 중력. gravity_vec와 곱해져서 처리된다.

◇ linear_damp : 이동 속도 감쇠.

◇ angular_damp : 회전 속도 감쇠. 

Audio Bus : 영역에 대한 오디오를 변경할 때 사용. 사용하려면 audio_bus_override를 true로 설정

audio_bus_override : 오디오 변경 여부

audio_bus_name : 오디오 버스 이름

 

위의 그림은 오디오 편집 화면으로 영역 안에 들어왔을 때는 다른 음향 효과를 주도록 기본 버스인 "Master" 외에 Outside와 Reactor 버스를 추가한 것을 볼 수 있다. 특정 영역에서 별도의 음향 효과를 주고 싶다면 오디오 버스를 추가하고 audio_bus_name으로 해당 버스를 지정하면 된다.

 

Point Gravity, Linear Damp, Reverse Gravity

위의 세 가지는 모두 Area2D를 적용하고 CollisionShape2D를 자식 노드로 두어 물리 옵션을 변경한 경우다. 물리 옵션의 차이가 오브젝트에 미치는 영향을 확인하기 위해 임의의 공간을 클릭하면 해당 위치에 RigidBody2D를 가진 씬 인스턴스를 생성하고 오브젝트가 아래로 떨어지도록 설정하면 3가지 Area2D 영역별로 반응이 달라진다. 오브젝트가 각 영역에 들어가면 물리 엔진은 각 영역에서 설정한 값을 기반으로 계산하는데 첫 번째 중력점을 설정한 영역으로 들어가면 영역 중심으로 오브젝트가 빨려 들어가게 된다. 두 번째 영역으로 들어가면 Linear Damp가 적용되어 떨어지는 속도가 급격히 줄어든다. 세 번째 영역으로 들어가면 역 중력이 적용되어 떨어지다 튀어 오르기를 반복한다.

 

위의 그림은 Area2D에 오브젝트가 들어온 경우 area_entered 시그널을 보내도록 설정한 것으로 이외에도 아래와 같은 시그널을 사용할 수 있다.

 

area_entered : 다른 Area2D가 영역에 들어왔을 때 

area_exited : 다른 Area2D가 영역에서 나갔을 때 

area_shape_entered : 다른 Area2D의 자식 Shape2D 중에 현재 영역의 자식 Shape2D 중의 하나에 들어왔을 때

area_shape_exited :  다른 Area2D의 자식 Shape2D 중에 현재 영역의 자식 Shape2D 중의 하나에서 나갔을 때

body_entered : PhysicsBody2D나 TileMap이 영역에 들어왔을 때

body_exited : PhysicsBody2D나 TileMap이 영역에서 나갔을 때 

body_shape_entered : PhysicsBody2D나 TileMap의 Shape2D에 자식 Shape2D 중의 하나에 들어왔을 때

body_shape_exited : PhysicsBody2D나 TileMap의 Shape2D가 자식 Shape2D 중의 하나에서 나갔을 때

 

Area2D와 같은 물리 몸체는 최소한 하나 이상의 Shape2D로 영역을 정의해야 함을 꼭 기억해야 한다. 단일 노드로는 사용하지 않고 반드시 자식 노드로 하나 이상의 Shape2D를 가져야 한다.

 

위의 화면은 Area2D를 사용한 대표적인 게임인 Pong으로 상하좌우 벽도 좌우의 패들 바도 공도 모두 Area2D로 구성되었다. 시그널은 area_entered만 사용해도 충분하다.

 

func _on_area_entered(area):
	if area.name == "Ball":
		area.direction = Vector2(_ball_dir, randf() * 2 - 1).normalized()

위의 코드는 패들에 공이 부딪히면 공의 방향을 바꾸어 주는 스크립트이다.

 

 

■ CollisionShape2D 클래스

물리 몸체의 자식 노드로 배치되어 충돌 영역을 나타내는 클래스다. 주의할 점은 몰리 몸체와 마찬가지로 편집기에서만 보이고 실행 모드에서는 모습이 보이지 않으므로 해당 영역에 통상 Sprite나 AnimatedSprite와 같은 눈에 보이는 요소를 같이 배치한다.

위의 그림은 RigidBody2D 물리 몸체에 캡슐 모양의 CollisionShape2D를 배치한 예제이다.

 

위의 그림은 Area2D(Princess), KinematicBody2D(OneWay1~4, Circle), StaticBody2D(Platform) 물리 몸체에 CollisionShape2D를 배치한 예제이다. 물리 몸체의 자식 노드로 충돌 영역을 정의하기 위한 CollisionShape2D와 함께 눈에 보이는 오브젝트인 Sprite를 배치하고 있는 것을 확인할 수 있다.

 

CollisionShape2D은 위의 그림과 같은 속성을 가진다. 기본 아이콘과 속성은 아래와 같다.

disabled : true면 동작하지 않게 한다.

one_way_collision : true면 위 또는 아래 한 방향으로만 충돌 확인

one_way_collision_margin : 픽셀 단위로 여백 지정. 값을 크게 하면 충돌자의 속도가 빨라도 대응할 수 있다.

shape : 충돌 영역의 모양으로 다음의 그림과 같다.

위의 그림에서는 정형화된 모양을 사용할 때 적용할 수 있다.

 

정형화된 모습이 아닐 때는 위의 예제처럼 CollisionPolygon2D를 사용하여 편집기에서 점들을 직접 조정하여 모양을 지정할 수 있다.

 

func _draw():
	draw_circle($Point.position, $Point/CollisionShape2D.shape.radius,
				Color(1, 1, 1, 0.1))	
	var s = $Antigrav/CollisionShape2D.shape.extents
	draw_rect(Rect2($Antigrav.position-s, s * 2), Color(1, 1, 0, 0.1))
	s = $Slow/CollisionShape2D.shape.extents
	draw_rect(Rect2($Slow.position-s, s * 2), Color(0, 1, 1, 0.1))

끝으로 물리 몸체와 함께 CollisionShape2D는 편집기에서는 그 모양을 확인할 수 있지만 실행 모드에서는 보이지 않으므로(보이지 않더라도 기능은 수행한다) 보통은 Sprite와 같은 오브젝트를 배치하지만 위의 코드는 충돌 영역의 정보를 가져와서 직접 도형을 그리는 방식으로 해당 영역을 표시하고 있다.

 

Sprite 클래스

앞서 살펴본 것처럼 Aread2D와 같은 물리 몸체와 충돌 영역을 나타내는 CollisionShape2D는 편집기에서는 보이지만 실행 모드에서는 보이지 않는다. 이를 위해서 충돌 영역 크기에 맞는 Sprite나 AnimatedSprite 노드를 같이 배치한다.

 

스프라이트는 2D 및 3D에서 사용할 수 있는 텍스처를 표시하는 노드이다.

스프라이트 노드는 위의 그림처럼 인스펙터 창의 텍스처 속성 우측을 클릭하면 하단으로 텍스처의 상세 정보를 확인할 수 있고 [텍스처 영역]이라는 편집 도구도 활용할 수 있다. 위의 그림은 스냅 모드를 "자동 자르기"로 설정할 모습인데 이미지에서 공백을 제외하고 개별 항목들을 자동 추출하여 개발자가 특정 영역을 클릭하면 해당 영역 Region 속성에 해당 정보를 설정해준다. 다양한 캐릭터를 한 이미지에 넣고 골라서 사용하는 경우 편리하게 사용할 수 있다. 픽셀 스냅과 격자 스냅도 사용할 수 있다.

 

Sprite는 위의 그림과 같은 속성을 가지며 기본 아이콘과 속성에 대한 설명은 아래와 같다.

texture : 표시할 오브젝트로 AnimatedTexture, AtlasTexture, CameraTexture, CurveTexture, ExternalTexture, GradientTexture, ImageTexture, LargeTexture, MeshTexture, NoiseTexture, ProxyTexture, StreamTexture, ViewportTexture 등을 적용할 수 있다.

통상 프로젝트 리소스 중에서 불러오기를 하는데 bmp, jpg, jpeg, png, svg, svgz, tga를 비롯한 다양한 비트맵 이미지와 벡터 이미지를 지원하고 스프라이트 시트라고 부르는 아틀라스 텍스처 등도 지원한다.

normal_map : 오브젝트에 깊이를 더해주는 것으로 고도에서는 X+, Y-, Z+ 정보를 받는다.

위의 그림은 단순 텍스처에 노멀 맵을 적용한 결과를 보여준다.

Offset

centered : true면 텍스처를 중앙에 표시

offset : 출력 위치 조정

flip_h : true면 수평 뒤집기

flip_v : true면 수직 뒤집기

Animation - 한 이미지를 동일한 크기의 작은 이미지로 나누어 사용하는 경우에 사용한다.

위의 이미지는 열의 개수는 6, 행의 개수는 1인 스프라이트 시트이다. 아틀라스 텍스처라고도 한다. 리소스 사용 및 관리를 단순화할 수 있다.

hframes : 스프라이트 시트의 열수

vframes : 스프라이트 시트의 행수

 frame : 현재 프레임 인덱스(프레임 인덱스는 0부터 시작)

frame_coords : 스프라이트 시트의 x, y 위치(프레임 인덱스는 0부터 시작)

Region - 텍스처의 일부를 잘라서 사용할 때 사용한다. [텍스처 영역] 편집 도구와 연계해서 사용한다.

region_enabled : true면 지정 영역을 잘라서 사용

region_rect : 자를 영역 정보

region_filter_clip : true면 자른 바깥 부분을 흐리게 처리

 

728x90
댓글
글 보관함
최근에 올라온 글
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31