충돌과 게임 상태
규칙과 승리 조건을 추가해 보세요.
충돌과 게임 상태은(는) CoddyKit의 무료 Learn Rust Coding 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Learn Rust Coding 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Learn Rust Coding 강의에는 총 4개의 강의가 포함되어 있습니다.
AABB 충돌 기초
가장 간단한 충돌 검사는 축에 정렬된 경계 상자(AABB)의 겹침을 확인하는 것입니다. 두 사각형이 x축과 y축 모두에서 겹치면 충돌한 것입니다.
스프라이트의 경우 전체 물리 엔진을 사용하기 전에 많은 2D 게임에서 충분히 빠르고 적절한 방법입니다.
fn overlaps(a_pos: Vec2, a_size: Vec2, b_pos: Vec2, b_size: Vec2) -> bool {
(a_pos.x - b_pos.x).abs() < (a_size.x + b_size.x) * 0.5
&& (a_pos.y - b_pos.y).abs() < (a_size.y + b_size.y) * 0.5
}Collider 컴포넌트
각 엔터티에 반쪽 크기 또는 전체 크기를 저장하는 Collider 컴포넌트를 추가합니다. 그러면 시스템이 변환값과 콜라이더를 함께 읽어 겹침을 검사합니다.
크기를 별도의 컴포넌트에 보관하면 서로 다른 엔터티가 동일한 충돌 시스템을 공유할 수 있습니다.
#[derive(Component)]
struct Collider {
size: Vec2,
}시스템에서 충돌 감지하기
플레이어를 여러 장애물과 비교하려면 플레이어는 한 번 쿼리하고 장애물들을 순회합니다. 서로 다른 두 쿼리를 사용하면 같은 데이터를 두 번 빌리는 일을 피할 수 있습니다.
겹침이 발생하면 Commands를 사용하거나 컴포넌트를 변경하여 피해를 주거나, 튕겨 내거나, 제거하는 등의 반응을 수행합니다.
fn detect(
player: Query<(&Transform, &Collider), With<Player>>,
walls: Query<(&Transform, &Collider), With<Wall>>,
) {
let (pt, pc) = player.single().unwrap();
for (wt, wc) in &walls {
if overlaps(pt.translation.truncate(), pc.size, wt.translation.truncate(), wc.size) {
info!("hit a wall");
}
}
}이벤트로 반응하기
결과를 감지 과정 안에서 바로 처리하는 대신 사용자 지정 Event를 보냅니다. 한 시스템이 충돌을 감지하고 이벤트를 발생시키면 다른 시스템이 이벤트를 읽어 효과를 적용합니다.
이렇게 하면 감지와 반응이 분리되어 각 시스템을 작게 유지할 수 있습니다.
#[derive(Event)]
struct CollisionEvent { entity: Entity }
fn emit(mut writer: EventWriter<CollisionEvent>, e: Entity) {
writer.send(CollisionEvent { entity: e });
}이벤트 읽기
리더 시스템은 EventReader로 대기 중인 이벤트를 가져와 각각 처리합니다. 이벤트는 두 프레임 동안 유지되므로 모든 리더가 이벤트를 확인할 수 있습니다.
이 발행-구독 방식은 결합도를 높이지 않고도 여러 생산자와 여러 소비자로 확장할 수 있습니다.
fn on_hit(mut reader: EventReader<CollisionEvent>, mut commands: Commands) {
for ev in reader.read() {
commands.entity(ev.entity).despawn();
}
}점수 업데이트하기
플레이어가 아이템을 획득하면 ResMut을 사용해 전역 Score 리소스를 변경합니다.
리소스는 하나만 존재하므로 어떤 시스템에서든 점수를 직접 전달하지 않고 읽거나 업데이트할 수 있습니다.
fn collect(mut score: ResMut<Score>, mut reader: EventReader<PickupEvent>) {
for _ in reader.read() {
score.0 += 10;
}
}상태: 전체 그림
게임은 메뉴, 플레이 중, 일시 정지, 게임 오버와 같은 모드 사이를 이동합니다. Bevy에서는 init_state로 등록한 States 열거형으로 이러한 모드를 모델링합니다.
한 번에 하나의 상태만 활성화되며, 시스템이 특정 상태에서만 실행되도록 제한할 수 있습니다.
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
enum GameState {
#[default]
Menu,
Playing,
GameOver,
}상태 등록하기
init_state를 사용해 앱에 상태를 추가합니다. 그러면 Bevy가 현재 값을 추적하고 State 및 NextState 리소스를 제공합니다.
시스템에서 현재 모드를 알아야 할 때는 Res<State<GameState>>로 현재 상태를 읽습니다.
App::new()
.add_plugins(DefaultPlugins)
.init_state::<GameState>()
.run();상태에서 시스템 실행하기
run_if 조건과 in_state를 사용해 시스템을 특정 상태로 제한합니다. 이동과 충돌은 Playing 상태일 때만 실행됩니다.
이것이 일시 정지가 작동하는 방식입니다. Playing 상태를 벗어나 게임플레이 시스템을 멈추면 해당 시스템은 실행되지 않습니다.
app.add_systems(
Update,
(drive, detect).run_if(in_state(GameState::Playing)),
);상태 전환하기
상태를 변경하려면 어떤 시스템에서든 NextState를 설정합니다. Bevy는 다음 프레임 경계에서 전환을 적용합니다.
OnEnter 및 OnExit 일정을 사용하면 상태에 진입할 때 UI를 생성하거나 상태를 벗어날 때 정리 작업을 수행할 수 있습니다.
fn lose(mut next: ResMut<NextState<GameState>>, health: Res<Health>) {
if health.0 == 0 {
next.set(GameState::GameOver);
}
}종료 시 정리하기
Playing을 벗어날 때 게임플레이 엔터티를 제거하면 다음 라운드를 깨끗한 상태로 시작할 수 있습니다. 엔터티에 표시용 태그를 붙인 다음 해당 태그가 있는 모든 엔터티를 제거합니다.
정리 작업을 OnExit(GameState::Playing)에 등록하면 전환마다 정확히 한 번 실행됩니다.
fn cleanup(mut commands: Commands, q: Query<Entity, With<GameEntity>>) {
for e in &q {
commands.entity(e).despawn();
}
}
// app.add_systems(OnExit(GameState::Playing), cleanup);빠른 확인
게임플레이를 깔끔하게 일시 정지하는 방법을 생각해 보세요.
복습: 충돌과 게임 상태
AABB 검사와 Collider 컴포넌트로 겹침을 감지하고, 이벤트로 감지와 반응을 분리하며, Score 리소스로 진행 상황을 추적합니다. run_if, NextState, OnEnter/OnExit를 사용하는 States 시스템은 메뉴, 플레이, 게임 오버를 체계적으로 구성합니다.
이제 생성하고, 조작하고, 충돌하고, 전환하는 전체 흐름을 갖추었습니다. 이 구성 요소들을 활용해 완전한 Bevy 게임을 만들어 보세요.
자주 묻는 질문
“충돌과 게임 상태” 강의는 무료인가요?
네 — “충돌과 게임 상태” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Learn Rust Coding 강의 전체를 잠금 해제할 수 있습니다. Learn Rust Coding 강의에는 총 4개의 강의가 포함되어 있습니다.
“충돌과 게임 상태”에서 뭘 배우나요?
규칙과 승리 조건을 추가해 보세요. 브라우저에서 직접 실행하는 실습 코드로 Learn Rust Coding을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Learn Rust Coding을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Learn Rust Coding은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“충돌과 게임 상태” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Learn Rust Coding 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Learn Rust Coding 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- ECS 사고방식
- 엔터티 생성하고 이동하기
- 입력과 시간 처리하기
- 충돌과 게임 상태