Last active
February 20, 2021 08:43
-
-
Save copyrat90/45f2e8bc79650ea2c98b064f1f624e93 to your computer and use it in GitHub Desktop.
std::function callback example (video game)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
class Character | |
{ | |
public: | |
Character(int maxHP) : m_maxHP(maxHP), m_currentHP(maxHP) {}; | |
void Update() | |
{ | |
if (m_isPoisoned) | |
{ | |
std::cout << "독으로 70의 데미지를 입었다!\n"; | |
m_currentHP -= 70; | |
} | |
else | |
{ | |
std::cout << "아무 일도 일어나지 않았다.\n"; | |
} | |
m_currentHP = (m_currentHP < 0) ? 0 : m_currentHP; | |
std::cout << "HP : " << m_currentHP << " / " << m_maxHP << "\n"; | |
// 체력이 다 떨어지면 gm.GameOver() 를 호출하고 싶다. (Callback) | |
// gm 객체의 멤버함수를 호출해야하는데, gm 에 접근을 못하는 게 문제. | |
if (m_currentHP <= 0) | |
; // 어떻게 해야 할까? | |
} | |
void SetPlayerPoison(bool isPoisoned) | |
{ | |
m_isPoisoned = isPoisoned; | |
std::cout << "3턴이 돼서 독에 걸렸다!\n"; | |
} | |
bool GetPlayerPoison() const { return m_isPoisoned; } | |
private: | |
const int m_maxHP; | |
int m_currentHP; | |
bool m_isPoisoned = false; | |
}; | |
class GameManager | |
{ | |
public: | |
GameManager() : m_player(100) {} | |
void Update() | |
{ | |
++m_turn; | |
std::cout << "==== 제 " << m_turn << "턴 ====\n"; | |
if (m_turn >= 3 && !m_player.GetPlayerPoison()) | |
m_player.SetPlayerPoison(true); | |
m_player.Update(); | |
} | |
bool GetGameOverStatus() const { return m_isGameOver; } | |
private: | |
Character m_player {100}; | |
int m_turn = 0; | |
bool m_isGameOver = false; | |
void GameOver(bool isPoisonDeath) | |
{ | |
m_isGameOver = true; | |
if (isPoisonDeath) | |
std::cout << "독으로 인한 사망! 게임 오버!\n"; | |
else | |
std::cout << "타격으로 인한 사망! 게임 오버!\n"; | |
} | |
}; | |
int main() | |
{ | |
GameManager gm; | |
while (!gm.GetGameOverStatus()) | |
gm.Update(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
// std::function 을 위해 functional 헤더를 포함한다. | |
#include <functional> | |
class Character | |
{ | |
public: | |
Character(int maxHP) : m_maxHP(maxHP), m_currentHP(maxHP) {}; | |
void Update() | |
{ | |
if (m_isPoisoned) | |
{ | |
std::cout << "독으로 70의 데미지를 입었다!\n"; | |
m_currentHP -= 70; | |
} | |
else | |
{ | |
std::cout << "아무 일도 일어나지 않았다.\n"; | |
} | |
m_currentHP = (m_currentHP < 0) ? 0 : m_currentHP; | |
std::cout << "HP : " << m_currentHP << " / " << m_maxHP << "\n"; | |
// 체력이 다 떨어지면 gm.GameOver() 를 호출한다. (Callback) | |
if (m_currentHP <= 0) | |
c_onPlayerDeath(true); | |
} | |
void SetPlayerPoison(bool isPoisoned) | |
{ | |
m_isPoisoned = isPoisoned; | |
std::cout << "3턴이 돼서 독에 걸렸다!\n"; | |
} | |
bool GetPlayerPoison() const { return m_isPoisoned; } | |
// 플레이어 사망시 호출될 GameManager 쪽 멤버함수를 넣어준다. | |
void Set_OnPlayerDeath(std::function<void(bool)> onPlayerDeath) | |
{ | |
// 매개변수는 어차피 없어질 스택변수니 복사보단 이동시키는 게 나을 듯. | |
c_onPlayerDeath = std::move(onPlayerDeath); | |
} | |
private: | |
const int m_maxHP; | |
int m_currentHP; | |
bool m_isPoisoned = false; | |
// Event Handler 를 받을 함수 객체 선언 | |
std::function<void(bool)> c_onPlayerDeath; | |
}; | |
class GameManager | |
{ | |
public: | |
GameManager() : m_player(100) | |
{ | |
// 플레이어 사망시 호출될 GameOver(bool) 멤버함수를 넣어준다. | |
// m_player 의 체력이 0이 되면, | |
// Character 쪽에서 gm.GameOver(bool) 를 되호출한다. (Callback) | |
// 이 때, 멤버함수는 std::bind(...) 로 아래 형식으로 전달해줘야 함. | |
// std::bind(전달할 멤버함수의 포인터, 대상 객체의 포인터, 함수 인자) | |
// 함수 인자는 std::placeholders::_N 으로, N은 1~30 사이이다. | |
m_player.Set_OnPlayerDeath( | |
std::bind(&GameManager::GameOver, this, std::placeholders::_1) | |
); | |
} | |
void Update() | |
{ | |
++m_turn; | |
std::cout << "==== 제 " << m_turn << "턴 ====\n"; | |
if (m_turn >= 3 && !m_player.GetPlayerPoison()) | |
m_player.SetPlayerPoison(true); | |
m_player.Update(); | |
} | |
bool GetGameOverStatus() const { return m_isGameOver; } | |
private: | |
Character m_player; | |
int m_turn = 0; | |
bool m_isGameOver = false; | |
void GameOver(bool isPoisonDeath) | |
{ | |
m_isGameOver = true; | |
if (isPoisonDeath) | |
std::cout << "독으로 인한 사망! 게임 오버!\n"; | |
else | |
std::cout << "타격으로 인한 사망! 게임 오버!\n"; | |
} | |
}; | |
int main() | |
{ | |
GameManager gm; | |
while (!gm.GetGameOverStatus()) | |
gm.Update(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment