[Godot] Breakout(Arkanoid) 벽돌깨기
Godot 2026. 9. 29. 22:38 |반응형
벽돌깨기 게임의 움직임을 간단히 구현해 보자.

구슬은 CharacterBody2D로, 사방을 둘러싼 4개의 벽은 StaticBody2D로 구현한다.
CharacterBody2D - Sprite2D는 아래와 같이 설정한다.

Gradient의 흰색 바 같은 부분을 살짝 변경해 보면 아래와 같으며, 바깥 부분을 담당하는 슬라이드를 클릭해 색깔 선택 창에서 Alpha값을 0으로 조절한 것이다.

CharacterBody2D의 스크립트는 아래와 같이 작성한다.
using Godot;
public partial class Ball : CharacterBody2D
{
public const float Speed = 400.0f;
// 공이 날아가는 방향 (처음에는 대각선 오른쪽 위로 쏘아 올림)
private Vector2 _direction = new Vector2(1, -1).Normalized();
public override void _PhysicsProcess(double delta)
{
// 공을 이동시킨다. MoveAndCollide는 부딪힌 물체의 정보를 반환한다.
// delta를 곱해서 프레임과 상관없이 일정한 속도로 이동하게 만든다.
KinematicCollision2D collision = MoveAndCollide(_direction * Speed * (float)delta);
if (collision != null) // 만약 어딘가에 부딪혔다면?
{
_direction = _direction.Bounce(collision.GetNormal());
// collision.GetNormal()은 부딪힌 벽면이 바라보는 수직 방향(법선 벡터)을 알려준다.
// _direction.Bounce() 는 벽면의 법선 벡터를 이용해서 입사각과 반사각을 계산해 새로운 방향 벡터를 반환한다.
// (옵션) 부딪힌 물체가 벽돌이라면 삭제하는 코드
Node2D collider = (Node2D)collision.GetCollider();
if (collider.IsInGroup("Brick"))
{
collider.QueueFree(); // 벽돌 파괴
}
}
}
}
게임을 실행한다.

처음 시작시 스페이스바를 눌러 마우스 위치로 공을 발사해 보자.
using Godot;
public partial class Ball : CharacterBody2D
{
public const float Speed = 400.0f;
// 처음에는 방향이 없는 상태(정지)로 둔다.
private Vector2 _direction = Vector2.Zero;
// 게임이 시작되었는지 확인하는 변수
private bool _isStarted = false;
public override void _PhysicsProcess(double delta)
{
// 아직 발사 전이라면?
if (!_isStarted)
{
// 스페이스바(엔진 기본 입력키인 ui_accept 사용)를 눌렀을 때
if (Input.IsActionJustPressed("ui_accept"))
{
_isStarted = true; // 발사 시작
// 마우스의 전역 좌표에서 내 좌표를 빼면 나로부터 마우스를 향하는 방향이다.
// Normalized()를 계산해 화살표의 길이를 딱 '1'로 맞춰주어야 속도가 일정해진다.
_direction = (GetGlobalMousePosition() - GlobalPosition).Normalized();
}
// 아직 스페이스바를 안 눌렀다면 여기서 함수를 끝내서 움직이지 않게 한다.
return;
}
// 발사된 공을 이동시킨다. MoveAndCollide는 부딪힌 물체의 정보를 반환한다.
// delta를 곱해서 프레임과 상관없이 일정한 속도로 이동하게 만든다.
KinematicCollision2D collision = MoveAndCollide(_direction * Speed * (float)delta);
if (collision != null) // 만약 어딘가에 부딪혔다면?
{
_direction = _direction.Bounce(collision.GetNormal());
// collision.GetNormal()은 부딪힌 벽면이 바라보는 수직 방향(법선 벡터)을 알려준다.
// _direction.Bounce() 는 벽면의 법선 벡터를 이용해서 입사각과 반사각을 계산해 새로운 방향 벡터를 반환한다.
// (옵션) 부딪힌 물체가 벽돌이라면 삭제하는 코드
Node2D collider = (Node2D)collision.GetCollider();
if (collider.IsInGroup("Brick"))
{
collider.QueueFree(); // 벽돌 파괴
}
}
}
}

공과 마우스 위치를 직선(점선)으로 이어보자. 공 발사는 마우스 왼쪽 버튼릭으로 바꾼다.
using Godot;
public partial class Ball : CharacterBody2D
{
public const float Speed = 400.0f;
// 처음에는 방향이 없는 상태(정지)로 둔다.
private Vector2 _direction = Vector2.Zero;
// 게임이 시작되었는지 확인하는 변수
private bool _isStarted = false;
// 화면에 직접 도형이나 선을 그리는 전용 함수
public override void _Draw()
{
if (!_isStarted)
{
// 내 위치(로컬 좌표계의 중심점인 Vector2.Zero)부터 마우스의 로컬 위치까지
// 노란색(Colors.Yellow)으로 두께 2.0f의 선을 그린다.
//DrawLine(Vector2.Zero, GetLocalMousePosition(), Colors.Yellow, 2.0f); // 직선
DrawDashedLine(Vector2.Zero, GetLocalMousePosition(), Colors.Yellow, 2.0f, 10.0f); // 점선
// 그리기 함수는 화면 전체(Global)가 아니라 내 캐릭터를 중심으로 한 지역(Local) 좌표를 기준으로
// 작동한다. 그래서 시작점을 내 위치인 Vector2.Zero(0, 0)로 두고, 끝점을 내 기준에서의 마우스
// 위치로 연결하면 완벽한 조준선이 된다.
}
}
// 매 프레임마다 화면 갱신을 요청.
public override void _Process(double delta)
{
if (!_isStarted)
{
// 발사 전일 때는 마우스가 움직일 때마다 선을 새로 그려야 하므로
// 엔진에게 다시 그리라고(Redraw) 지속적으로 요청한다.
QueueRedraw();
}
}
public override void _PhysicsProcess(double delta)
{
// 아직 발사 전이라면?
if (!_isStarted)
{
// 마우스 왼쪽 버튼을 눌렀을때
if (Input.IsMouseButtonPressed(MouseButton.Left))
{
_isStarted = true; // 발사 시작
// 마우스의 전역 좌표에서 내 좌표를 빼면 나로부터 마우스를 향하는 방향이다.
// Normalized()를 계산해 화살표의 길이를 딱 '1'로 맞춰주어야 속도가 일정해진다.
_direction = (GetGlobalMousePosition() - GlobalPosition).Normalized();
// 발사되는 순간, 더 이상 선을 그리지 않도록 마지막으로 한 번 더 갱신 요청을 해서 선을 지운다.
QueueRedraw();
}
// 아직 스페이스바를 안 눌렀다면 여기서 함수를 끝내서 움직이지 않게 한다.
return;
}
// 발사된 공을 이동시킨다. MoveAndCollide는 부딪힌 물체의 정보를 반환한다.
// delta를 곱해서 프레임과 상관없이 일정한 속도로 이동하게 만든다.
KinematicCollision2D collision = MoveAndCollide(_direction * Speed * (float)delta);
if (collision != null) // 만약 어딘가에 부딪혔다면?
{
_direction = _direction.Bounce(collision.GetNormal());
// collision.GetNormal()은 부딪힌 벽면이 바라보는 수직 방향(법선 벡터)을 알려준다.
// _direction.Bounce() 는 벽면의 법선 벡터를 이용해서 입사각과 반사각을 계산해 새로운 방향 벡터를 반환한다.
// (옵션) 부딪힌 물체가 벽돌이라면 삭제하는 코드
Node2D collider = (Node2D)collision.GetCollider();
if (collider.IsInGroup("Brick"))
{
collider.QueueFree(); // 벽돌 파괴
}
}
}
}

반응형
'Godot' 카테고리의 다른 글
| [Godot] Game Manager (Singleton) 게임 메니저 (0) | 2026.09.28 |
|---|---|
| [Godot] Flickering Candles 바람에 흔들리는 촛불 (0) | 2026.09.22 |
| [Godot] Network Multi Play - Character Animation 네트워크 멀티 플레이 - 캐릭터 애니메이션 (0) | 2026.09.20 |
| [Godot] Physics 물리 (0) | 2026.09.19 |
| [Godot] RPG Top-Down View Character 탑다운 뷰 캐릭터 2 (0) | 2026.09.17 |