반응형
간단한 AI 기초 (상태 머신)
게임 개발에서 인공지능(AI)은 NPC(Non-Player Character)나 적 캐릭터의 행동을 제어하는 중요한 요소입니다. 상태 머신(State Machine)은 AI를 구현하는 데 사용되는 일반적인 방법입니다. 상태 머신은 객체가 여러 상태 중 하나에 있을 수 있고, 특정 이벤트나 조건에 따라 상태가 전환되는 모델입니다.
상태 머신 기초
상태 머신은 다음과 같은 구성 요소로 이루어집니다:
- 상태(State): 객체가 가질 수 있는 다양한 상태를 나타냅니다.
- 전환(Transition): 한 상태에서 다른 상태로의 변화입니다.
- 이벤트(Event): 상태 전환을 트리거하는 조건이나 사건입니다.
간단한 AI 상태 머신 구현
다음 예제에서는 NPC가 정지, 이동, 공격의 세 가지 상태를 가질 수 있는 간단한 AI 상태 머신을 구현합니다.
상태 인터페이스 정의
class AIState {
public:
virtual ~AIState() {}
virtual void enter() = 0;
virtual void handleEvent(sf::Event& event) = 0;
virtual void update(float deltaTime) = 0;
virtual void render(sf::RenderWindow& window) = 0;
};
NPC 클래스 정의
NPC 클래스는 현재 상태를 보관하고, 상태 전환을 처리합니다.
class NPC {
public:
NPC() : currentState(nullptr) {}
void changeState(AIState* state) {
if (currentState != nullptr) {
currentState->exit();
}
currentState = state;
currentState->enter();
}
void handleEvent(sf::Event& event) {
if (currentState != nullptr) {
currentState->handleEvent(event);
}
}
void update(float deltaTime) {
if (currentState != nullptr) {
currentState->update(deltaTime);
}
}
void render(sf::RenderWindow& window) {
if (currentState != nullptr) {
currentState->render(window);
}
}
private:
AIState* currentState;
};
구체적인 상태 클래스 정의
다음으로, NPC의 구체적인 상태 클래스를 정의합니다. 여기서는 정지 상태, 이동 상태, 공격 상태를 구현합니다.
class IdleState : public AIState {
public:
void enter() override {
std::cout << "Entering Idle State" << std::endl;
}
void handleEvent(sf::Event& event) override {}
void update(float deltaTime) override {
// 정지 상태에서는 아무 것도 하지 않음
}
void render(sf::RenderWindow& window) override {}
void exit() override {
std::cout << "Exiting Idle State" << std::endl;
}
};
class MoveState : public AIState {
public:
void enter() override {
std::cout << "Entering Move State" << std::endl;
}
void handleEvent(sf::Event& event) override {}
void update(float deltaTime) override {
// 이동 로직 구현
std::cout << "Moving..." << std::endl;
}
void render(sf::RenderWindow& window) override {}
void exit() override {
std::cout << "Exiting Move State" << std::endl;
}
};
class AttackState : public AIState {
public:
void enter() override {
std::cout << "Entering Attack State" << std::endl;
}
void handleEvent(sf::Event& event) override {}
void update(float deltaTime) override {
// 공격 로직 구현
std::cout << "Attacking..." << std::endl;
}
void render(sf::RenderWindow& window) override {}
void exit() override {
std::cout << "Exiting Attack State" << std::endl;
}
};
전체 코드
다음은 전체 코드입니다. 이 코드는 NPC가 상태 머신을 사용하여 상태 전환을 처리하는 예제입니다.
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <iostream>
class AIState {
public:
virtual ~AIState() {}
virtual void enter() = 0;
virtual void handleEvent(sf::Event& event) = 0;
virtual void update(float deltaTime) = 0;
virtual void render(sf::RenderWindow& window) = 0;
virtual void exit() = 0;
};
class IdleState : public AIState {
public:
void enter() override {
std::cout << "Entering Idle State" << std::endl;
}
void handleEvent(sf::Event& event) override {}
void update(float deltaTime) override {
// 정지 상태에서는 아무 것도 하지 않음
}
void render(sf::RenderWindow& window) override {}
void exit() override {
std::cout << "Exiting Idle State" << std::endl;
}
};
class MoveState : public AIState {
public:
void enter() override {
std::cout << "Entering Move State" << std::endl;
}
void handleEvent(sf::Event& event) override {}
void update(float deltaTime) override {
// 이동 로직 구현
std::cout << "Moving..." << std::endl;
}
void render(sf::RenderWindow& window) override {}
void exit() override {
std::cout << "Exiting Move State" << std::endl;
}
};
class AttackState : public AIState {
public:
void enter() override {
std::cout << "Entering Attack State" << std::endl;
}
void handleEvent(sf::Event& event) override {}
void update(float deltaTime) override {
// 공격 로직 구현
std::cout << "Attacking..." << std::endl;
}
void render(sf::RenderWindow& window) override {}
void exit() override {
std::cout << "Exiting Attack State" << std::endl;
}
};
class NPC {
public:
NPC() : currentState(nullptr) {}
void changeState(AIState* state) {
if (currentState != nullptr) {
currentState->exit();
}
currentState = state;
currentState->enter();
}
void handleEvent(sf::Event& event) {
if (currentState != nullptr) {
currentState->handleEvent(event);
}
}
void update(float deltaTime) {
if (currentState != nullptr) {
currentState->update(deltaTime);
}
}
void render(sf::RenderWindow& window) {
if (currentState != nullptr) {
currentState->render(window);
}
}
private:
AIState* currentState;
};
int main() {
// SFML 창 생성
sf::RenderWindow window(sf::VideoMode(800, 600), "AI State Machine Example");
NPC npc;
IdleState idleState;
MoveState moveState;
AttackState attackState;
npc.changeState(&idleState);
// 게임 루프
sf::Clock clock;
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
npc.handleEvent(event);
// 상태 전환을 위한 임시 로직
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::I) {
npc.changeState(&idleState);
} else if (event.key.code == sf::Keyboard::M) {
npc.changeState(&moveState);
} else if (event.key.code == sf::Keyboard::A) {
npc.changeState(&attackState);
}
}
}
float deltaTime = clock.restart().asSeconds();
npc.update(deltaTime);
// 화면 지우기
window.clear();
// NPC 렌더링
npc.render(window);
// 화면에 그리기
window.display();
}
return 0;
}
결론
오늘은 상태 머신을 사용하여 간단한 AI를 구현하는 방법을 학습했습니다. 상태 머신은 AI의 상태 전환을 관리하는 데 유용한 패턴입니다. 이를 통해 게임에서 NPC나 적 캐릭터의 다양한 행동을 제어할 수 있습니다. 질문이나 추가적인 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "Day 19: 경로 찾기 알고리즘 (A* 알고리즘)"에 대해 학습하겠습니다.
반응형
'-----ETC----- > C++ 게임 개발 시리즈' 카테고리의 다른 글
[C++ 게임 개발 시리즈] Day 19: 경로 찾기 알고리즘 (A* 알고리즘) (0) | 2024.08.01 |
---|---|
[C++ 게임 개발 시리즈] Day 20: AI 행동 트리 (0) | 2024.08.01 |
[C++ 게임 개발 시리즈] Day 16: 플레이어 입력 처리 (0) | 2024.08.01 |
[C++ 게임 개발 시리즈] Day 17: 게임 상태 관리 (0) | 2024.08.01 |
[C++ 게임 개발 시리즈] Day 14: 화면 전환과 UI 요소 (0) | 2024.08.01 |