Returning a polymorphic class - c++

i'm creating a little xbox application and for the beginning it should detect what game is currently running and then bypass and/or launch a program. Since i recently learned polymorphism i thought i could implement it here to gain efficiency. Below is my code (not as efficient as i thought it would be):
DWORD(__cdecl *XamGetCurrentTitleID)() = (DWORD(__cdecl *)())ResolveFunction("xam.xex", 0x1CF); // Resolves current Game ID
typedef enum _XBOX_GAMES : DWORD // Enum that holds Game IDs
{
BOOT_UP = 0x00000000,
DASHBOARD = 0xFFFE07D1,
FREESTYLEDASH = 0xF5D20000,
COD_WORLD_AT_WAR = 0x4156081C,
COD_MODERN_WARFARE = 0x415607E6,
COD_MODERN_WARFARE_2 = 0x41560817,
COD_BLACK_OPS_1 = 0x41560855,
COD_MODERN_WARFARE_3 = 0x415608CB,
COD_BLACK_OPS_2 = 0x415608C3,
COD_GHOSTS = 0x415608fC,
COD_ADVANCED_WARFARE = 0x41560914,
COD_BLACK_OPS_3 = 0x4156091D,
DESTINY = 0x415608F8,
GTAV = 0x545408A7
} XBOX_GAMES;
DWORD GameChecker()
{
DWORD lastID = NULL;
Game *game;
AW aw; BO1 bo1; BO2 bo2; BO3 bo3; Ghosts ghosts; MW2 mw2; MW3 mw3; Dashboard dashboard;
for (;;)
{
if (XamGetCurrentTitleID() != lastID)
{
switch (XamGetCurrentTitleID())
{
case BOOT_UP:
// nothing
break;
case DASHBOARD:
game = &dashboard;
game->Launch();
break;
case COD_MODERN_WARFARE_2:
game = &mw2;
game->Launch();
break;
case COD_MODERN_WARFARE_3:
game = &mw3;
game->Launch();
break;
case COD_GHOSTS:
game = &ghosts;
game->Bypass();
game->Launch();
break;
case COD_BLACK_OPS_1:
game = &bo1;
game->Launch();
break;
case COD_BLACK_OPS_2:
game = &bo2;
game->Bypass();
break;
case COD_BLACK_OPS_3:
game = &bo3;
game->Bypass();
break;
case COD_ADVANCED_WARFARE:
game = &aw;
game->Bypass();
game->Launch();
break;
}
lastID = XamGetCurrentTitleID();
}
}
return 0;
}
As you can see i could've moved the game->Launch() and game->Bypass() outside of the switch statement to have less code and only call it once, but i didn't knew how i could determine when a game needs a bypass and/or launch. This is my GameClass:
class Game
{
public:
virtual void Bypass() { }
virtual void Launch() { }
};
And this is the class of an example game:
// needs bypass and launch called
class AW : public Game
{
public:
void Bypass()
{
// bypass
}
void Launch()
{
Sleep(500);
XNotifyUI(L"AW - Loaded!");
}
};
I would like to know if there is a way to do something like this:
DWORD GameChecker()
{
DWORD lastID = NULL;
Game *game;
for (;;)
{
if (XamGetCurrentTitleID() != lastID)
{
switch (XamGetCurrentTitleID())
{
case BOOT_UP:
// nothing
break;
default:
game = &functionThatReturnsClassBasedOnGame(XamGetCurrentTitleID()); // I don't know how to code such an function
break;
}
if (game->needsBypass)
game->Bypass();
if (game->needsLaunch)
game->Launch();
lastID = XamGetCurrentTitleID();
}
}
return 0;
}
Any help is greatly appreciated! Thanks for your time.

A simple way to accomplish your example is like this:
const int NEEDS_BYPASS = 1;
const int NEEDS_LAUNCH = 2;
class Game
{
public:
virtual ~Game() { }
virtual int getFeatures() const { return 0; }
virtual void Bypass() { }
virtual void Launch() { }
};
class Game_Dashboard : public Game
{
public:
int getFeatures() const { return NEEDS_LAUNCH; }
void Launch() {
Sleep(500);
XNotifyUI(L"Dashboard - Loaded!");
}
};
class Game_ModernWarfare2 : public Game
{
public:
int getFeatures() const { return NEEDS_LAUNCH; }
void Launch() {
Sleep(500);
XNotifyUI(L"MW2 - Loaded!");
}
};
class Game_ModernWarfare3 : public Game
{
public:
int getFeatures() const { return NEEDS_LAUNCH; }
void Launch() {
Sleep(500);
XNotifyUI(L"MW3 - Loaded!");
}
};
class Game_Ghosts : public Game
{
public:
int getFeatures() const { return NEEDS_BYPASS | NEEDS_LAUNCH; }
void Bypass() {
// bypass...
}
void Launch() {
Sleep(500);
XNotifyUI(L"Ghosts - Loaded!");
}
};
class Game_BlackOpts1 : public Game
{
public:
int getFeatures() const { return NEEDS_LAUNCH; }
void Launch() {
Sleep(500);
XNotifyUI(L"BO1 - Loaded!");
}
};
class Game_BlackOpts2 : public Game
{
public:
int getFeatures() const { return NEEDS_BYPASS; }
void Bypass() {
// bypass...
}
};
class Game_BlackOpts3 : public Game
{
public:
int getFeatures() const { return NEEDS_BYPASS; }
void Bypass() {
// bypass...
}
};
class Game_AdvancedWarfare : public Game
{
public:
int getFeatures() const { return NEEDS_BYPASS | NEEDS_LAUNCH; }
void Bypass() {
// bypass
}
void Launch() {
Sleep(500);
XNotifyUI(L"AW - Loaded!");
}
};
Game* getGame(DWORD ID)
{
switch (ID)
{
case DASHBOARD:
return new Game_Dashboard;
case COD_MODERN_WARFARE_2:
return new Game_ModernWarfare2;
case COD_MODERN_WARFARE_3:
return new Game_ModernWarfare3;
case COD_GHOSTS:
return new Game_Ghosts;
case COD_BLACK_OPS_1:
return new Game_BlackOpts1;
case COD_BLACK_OPS_2:
return new Game_BlackOpts2;
case COD_BLACK_OPS_3:
return new Game_BlackOpts3;
case COD_ADVANCED_WARFARE:
return new Game_AdvancedWarfare;
}
return NULL;
}
DWORD GameChecker()
{
DWORD currentID, lastID = 0;
Game *game;
do
{
currentID = XamGetCurrentTitleID();
if (currentID != lastID)
{
lastID = currentID;
game = getGame(currentID);
if (game)
{
if (game->getFeatures() & NEEDS_BYPASS)
game->Bypass();
if (game->getFeatures() & NEEDS_LAUNCH)
game->Launch();
delete game;
}
}
}
while (true);
return 0;
}
However, a better use of polymorphism would to be more like this instead:
class Game
{
public:
virtual ~Game() { }
};
class CanBypass
{
public:
virtual void Bypass() = 0;
};
class CanLaunch
{
public:
virtual void Launch() = 0;
};
class Game_Dashboard : public Game, public CanLaunch
{
public:
void Launch() {
Sleep(500);
XNotifyUI(L"Dashboard - Loaded!");
}
};
class Game_ModernWarfare2 : public Game, public CanLaunch
{
public:
void Launch() {
Sleep(500);
XNotifyUI(L"MW2 - Loaded!");
}
};
class Game_ModernWarfare3 : public Game, public CanLaunch
{
public:
void Launch() {
Sleep(500);
XNotifyUI(L"MW3 - Loaded!");
}
};
class Game_Ghosts : public Game, public CanBypass, public CanLaunch
{
public:
void Bypass() {
// bypass...
}
void Launch() {
Sleep(500);
XNotifyUI(L"Ghosts - Loaded!");
}
};
class Game_BlackOpts1 : public Game, public CanLaunch
{
public:
void Launch() {
Sleep(500);
XNotifyUI(L"BO1 - Loaded!");
}
};
class Game_BlackOpts2 : public Game, public CanBypass
{
public:
void Bypass() {
// bypass...
}
};
class Game_BlackOpts3 : public Game, public CanBypass
{
public:
void Bypass() {
// bypass...
}
};
class Game_AdvancedWarfare : public Game, public CanBypass, public CanLaunch
{
public:
void Bypass() {
// bypass
}
void Launch() {
Sleep(500);
XNotifyUI(L"AW - Loaded!");
}
};
Game* getGame(DWORD ID)
{
switch (ID)
{
case DASHBOARD:
return new Game_Dashboard;
case COD_MODERN_WARFARE_2:
return new Game_ModernWarfare2;
case COD_MODERN_WARFARE_3:
return new Game_ModernWarfare3;
case COD_GHOSTS:
return new Game_Ghosts;
case COD_BLACK_OPS_1:
return new Game_BlackOpts1;
case COD_BLACK_OPS_2:
return new Game_BlackOpts2;
case COD_BLACK_OPS_3:
return new Game_BlackOpts3;
case COD_ADVANCED_WARFARE:
return new Game_AdvancedWarfare;
}
return NULL;
}
DWORD GameChecker()
{
DWORD currentID, lastID = 0;
Game *game;
CanBypass *bypasser;
CanLaunch *launcher;
do
{
currentID = XamGetCurrentTitleID();
if (currentID != lastID)
{
lastID = currentID;
game = getGame(currentID);
if (game)
{
bypasser = dynamic_cast<CanBypass*>(game);
if (bypasser)
bypasser->Bypass();
launcher = dynamic_cast<CanLaunch*>(game);
if (launcher)
launcher->Launch();
delete game;
}
}
}
while (true);
return 0;
}

Related

When apply observer pattern an error occured

I have the following code:
class ISubscriber;
class News {
public:
float getVersion() { return this->version; }
void setVersion(float state) { this->version= state; this->notifyAllSubscribers(); }
void attach(ISubscriber *observer) { this->subscribers.push_back(observer); }
void notifyAllSubscribers() {
for (vector<ISubscriber*>::iterator it = subscribers.begin(); it != subscribers.end(); it++){
(*(*it)).update();
}
}
private:
vector<ISubscriber*> subscribers;
float version;
};
class ISubscriber {
public:
News *news;
virtual void update() = 0;
};
class Subscriber1 : public ISubscriber {
public:
Subscriber1(News *news) { this->news = news; this->news->attach(this); }
void update() override { cout << "Subscriber1: A new version of the newspaper has been launched (v" << this->news->getVersion() << ")" << endl; }
};
class Subscriber2 : public ISubscriber {
public:
Subscriber2(News *news) { this->news = news; this->news->attach(this); }
void update() override { cout << "Subscriber2: A new version of the newspaper has been launched (v" << this->news->getVersion() << ")" << endl; }
};
int main(int argc, char *argv[]) {
News newspaper;
newspaper.setVersion(2.1f);
Subscriber1 sb1(&newspaper);
Subscriber2 sb2(&newspaper);
return 0;
}
But strange errors happened:
The first error points to this code (*(*it)).update(); in news class.
Why that errors happened, what's the reason?
(*(*it)).update(); requires the type ISubscriber to be complete, just the forward declaration is not enough.
You could move the defnition of ISubscriber before the one of News, and give a forward declaration of News before that.
class News;
class ISubscriber {
public:
News *news;
virtual void update() = 0;
};
class News {
public:
float getVersion() { return this->version; }
void setVersion(float state) { this->version= state; this->notifyAllSubscribers(); }
void attach(ISubscriber *observer) { this->subscribers.push_back(observer); }
void notifyAllSubscribers() {
for (vector<ISubscriber*>::iterator it = subscribers.begin(); it != subscribers.end(); it++){
(*(*it)).update();
}
}
private:
vector<ISubscriber*> subscribers;
float version;
};

Accessing a pointer stored in a base class

I have a class called StateMachine, which controls all possible Entity States.
I then have a class called State which is a base class for unique Entity classes, e.g Attack State, Flee State.
When a new unique State is created (within the StateMachine), it passes in a StateMachine pointer, which will then be stored in the State base class, so that each unique State created can access its State Machine.
When I attempt to access the pointers members (using -> operator) it simple doesn't come up with any public methods, and I don't know why.
If anyone has any clue it would be greatly appreciated.
StateMachine.h
using STATE_PTR = std::shared_ptr<State>;
// Class to implement a finite state machine using the state desing pattern
class StateMachine
{
public:
StateMachine();
~StateMachine();
void OnEnter(STATE_NAME sn);
void OnExit();
void OnEvent(STATE_SYMBOL & ss);
void OnTick(float st);
void ChangeState(STATE_NAME const & sn);
void RegisterState(ENTITY_CLASS const & ec);
typedef std::map<STATE_NAME, STATE_PTR> STATE_REGISTRY;
private:
STATE_REGISTRY state_registry;
STATE_NAME current_state;
};
StateMachine.cpp
using namespace::std;
StateMachine::StateMachine()
: state_registry()
{
current_state = STATE_NAME::UNKNOWN;
}
StateMachine::~StateMachine()
{
state_registry.clear();
}
void StateMachine::OnEnter(STATE_NAME sn)
{
current_state = sn;
if (state_registry[current_state] != nullptr)
{
state_registry[current_state]->OnEnter();
}
}
void StateMachine::OnExit()
{
if (state_registry[current_state] != nullptr)
{
state_registry[current_state]->OnExit();
}
}
void StateMachine::OnTick(float st)
{
}
void StateMachine::OnEvent(STATE_SYMBOL & ss)
{
state_registry[current_state]->OnEvent(ss);
}
void StateMachine::RegisterState(ENTITY_CLASS const & ec)
{
switch (ec)
{
case ENTITY_CLASS::PLAYER_TANK :
state_registry.insert(std::make_pair(STATE_NAME::STATE_1, std::make_shared<PlayerTankState1>(this)));
state_registry.insert(std::make_pair(STATE_NAME::STATE_2, std::make_shared<PlayerTankState2>(this)));
break;
case ENTITY_CLASS::ENEMY_TANK :
state_registry.insert(std::make_pair(STATE_NAME::STATE_3, std::make_shared<EnemyTankState1>(this)));
state_registry.insert(std::make_pair(STATE_NAME::STATE_4, std::make_shared<EnemyTankState2>(this)));
state_registry.insert(std::make_pair(STATE_NAME::STATE_5, std::make_shared<EnemyTankState3>(this)));
break;
default:
break;
}
}
void StateMachine::ChangeState(STATE_NAME const & sn)
{
state_registry[current_state]->OnExit();
current_state = sn;
state_registry[current_state]->OnEnter();
}
State.h
class StateMachine; // Forward decloration of the StateMachine class
// Base class for all states of the game system
class State
{
protected:
State(StateMachine * p)
: mp_Owner(p)
{}
public:
virtual ~State() {}
virtual void OnEnter() = 0;
virtual void OnExit() = 0;
virtual void OnTick(float) = 0;
virtual void OnEvent(STATE_SYMBOL) = 0;
StateMachine * mp_Owner;
};
EnemyTankState.cpp (Unique State)
EnemyTankState1::EnemyTankState1(StateMachine * p)
: State(p)
{
}
EnemyTankState1::~EnemyTankState1()
{
}
void EnemyTankState1::OnEnter()
{
cout << "Hi From Enemy Tank: Partolling State" << endl;
}
void EnemyTankState1::OnExit()
{
cout << "Bye From Enemy Enemy Tank: Partolling State" << endl;
}
void EnemyTankState1::OnTick(float dt)
{
}
void EnemyTankState1::OnEvent(STATE_SYMBOL ss)
{
switch (ss)
{
// Takes Enemy Tank to Attacking State
case STATE_SYMBOL::SYMBOL_2 :
mp_Owner->
break;
}
}
Within the code sample above, the line mp_Owner-> is what is giving me grief, as it is not opening up a list of public methods as you would expect when using a class pointer.
Any help would be much appreciated. Sorry for the long chunks of code, I couldn't think of any other way of getting my problem across.

Segmentation fault while trying to change game state

I'm making a state machine for switching game states (playing->menu->setup) in my game engine, but I'm getting a segmentation fault. I can change the game state fine from upper level, but how can I change the game state from within a game state?
Here's a minimal code example:
#include <iostream>
#include <vector>
class GameStateManager;
class GameState {
public:
GameState(GameStateManager* StateManager) {
StateManager = stateManager;
};
virtual ~GameState();
virtual void update() = 0;
GameStateManager* stateManager;
};
class GameStateManager {
public:
GameStateManager();
~GameStateManager();
void changeGameState(GameState* state) {
if(!running) {
running = true;
}
// Cleanup the current state
if(!gameStates.empty()) {
for(unsigned int i = 0; i < gameStates.size(); i++) {
delete gameStates[i];
}
gameStates.clear();
std::cout << "Cleaning up GameState" << std::endl;
}
// Store and initialize the new game state
gameStates.push_back(state);
};
void update() {
if(!gameStates.empty()) {
gameStates.back()->update();
}
};
std::vector<GameState*> gameStates;
bool running;
};
class PlayState : public GameState {
public:
PlayState(GameStateManager* stateManager) : GameState(stateManager) {};
~PlayState();
void update() override {
// On some flag, initiate the next level
nextLevel();
};
void nextLevel() {
stateManager->changeGameState(new PlayState(stateManager));
};
};
int main() {
GameStateManager stateManager;
stateManager.changeGameState(new PlayState(&stateManager));
while(stateManager.running) {
for(unsigned int i = 0; i < 10000; i++) {
std::cout << "Round: " << i << std::endl;
// Segmentation fault here
stateManager.update();
// This works
//stateManager.changeGameState(new PlayState(&stateManager));
}
stateManager.running = false;
}
return 0;
}
for some reason the stateManager is not being set in the GameState constructor.
so try this:
class GameState {
public:
GameState(GameStateManager* StateManager) : stateManager(StateManager)
{
};
virtual ~GameState();
virtual void update() = 0;
GameStateManager* stateManager;
};

Proper usage of std::move

The following code works:
class Handler {
public:
Application* application;
bool handle(sf::Event&);
};
class TestApp {
public:
TestApp();
bool running;
void run();
void attach_handler(Handler*);
std::forward_list<std::unique_ptr<Handler>> handlerFList;
};
TestApp::TestApp() {
}
void Application::run() {
while (running) {
sf::Event event;
while (window->pollEvent(event)) {
for (auto& handler : handlerFList) {
if (handler->handle(event)) {
break;
}
}
}
}
}
void Application::attach_handler(Handler* handler) {
handlerFList.push_front(std::unique_ptr<Handler>(std::move(handler)));
handler->application = this;
}
int main() {
sqt::TestApp app;
sqe::HandlerClose hc;
app.attach_handler(&hc);
app.run();
return 0;
}
But this one does not:
class Handler {
public:
Application* application;
bool handle(sf::Event&);
};
class TestApp {
public:
TestApp();
bool running;
void run();
void attach_handler(Handler*);
std::forward_list<std::unique_ptr<Handler>> handlerFList;
};
TestApp::TestApp() {
sqe::HandlerClose hc;
attach_handler(&hc);
}
void TestApp::run() {
while (running) {
sf::Event event;
while (window->pollEvent(event)) {
for (auto& handler : handlerFList) {
if (handler->handle(event)) { // SEGFAULTS
break;
}
}
}
}
}
void TestApp::attach_handler(Handler* handler) {
handlerFList.push_front(std::unique_ptr<Handler>(std::move(handler)));
handler->application = this;
}
int main() {
sqt::TestApp app;
app.run();
return 0;
}
It segfaults where marked. I can't work out what I'm doing wrong. Isn't std::move supposed to move the base object? What it seems like is happening is that once TestApp's constructor finishes, the object is getting deleted. How can I fix this?

custom CCNode runAction cannot execute in Cocos2d-x?

I have a class that inherits from CCNode. HcharacterDrawnode contains a group of StrokeDrawnode which is another custom CCNode. Now I add (m_HDrawnode)HcharacterDrawnode to a layer and runAction.
CCAction* place = CCMoveTo::create(2.0,ccp(0,0));
m_HDrawnode->runAction(place);
But nothing happened. I have checked some webpage. Someone said it may related to m_bRunning , however I cannot find a place to set this variable.
HcharacterDrawnode.h
class HcharacterDrawnode : public CCNode
{
public:
HcharacterDrawnode();
~HcharacterDrawnode();
CREATE_FUNC(HcharacterDrawnode);
virtual bool init();
virtual void onEnter();
virtual void onExit();
virtual void draw();
void addPoint(CCPoint point);
void addStroke(Stroke s);
void removeLastStroke();
CC_SYNTHESIZE_RETAIN(CCArray*,strokeDrawlist,StrokeDrawnodeList);
private:
};
HcharacterDrawnode.cpp
#include "HcharacterDrawnode.h"
HcharacterDrawnode::HcharacterDrawnode():strokeDrawlist(NULL)
{
}
HcharacterDrawnode::~HcharacterDrawnode()
{
CC_SAFE_RELEASE(strokeDrawlist);
}
void HcharacterDrawnode::onEnter(){
CCNode::onEnter();
}
void HcharacterDrawnode::onExit(){
CCNode::onExit();
}
bool HcharacterDrawnode::init(){
this->setStrokeDrawnodeList(CCArray::create());
return true;
}
void HcharacterDrawnode::draw(){
CCObject* ob;
CCARRAY_FOREACH(strokeDrawlist,ob){
((StrokeDrawnode*)(ob))->draw();
}
}
void HcharacterDrawnode::addPoint(CCPoint point){
StrokeDrawnode* t = (StrokeDrawnode*)(strokeDrawlist->objectAtIndex(strokeDrawlist->count()-1));
t->addPoint(point);
}
void HcharacterDrawnode::addStroke(Stroke s){
strokeDrawlist->addObject(StrokeDrawnode::create(s));
}
void HcharacterDrawnode::removeLastStroke(){
strokeDrawlist->removeLastObject();
}
StrokeDrawnode.h
class StrokeDrawnode : public CCNode
{
public:
StrokeDrawnode();
StrokeDrawnode(Stroke stro);
~StrokeDrawnode();
static StrokeDrawnode* create(Stroke stro);
Stroke stroke;
ccColor4B mcolor;
virtual void onEnter();
virtual void onExit();
virtual void draw();
int visibleIndex;
void addPoint(CCPoint point);
private:
};
StrokeDrawnode.cpp
#include "StrokeDrawnode.h"
StrokeDrawnode::StrokeDrawnode()
{
}
StrokeDrawnode::StrokeDrawnode(Stroke stro){
this->stroke = stro;
}
void StrokeDrawnode::onEnter(){
CCNode::onEnter();
}
void StrokeDrawnode::onExit(){
CCNode::onExit();
}
StrokeDrawnode* StrokeDrawnode::create(Stroke stro){
StrokeDrawnode* pRet = new StrokeDrawnode(stro);
if (pRet && pRet->init())
{
pRet->autorelease();
return pRet;
}else{
delete pRet;
pRet = NULL;
return NULL;
}
}
StrokeDrawnode::~StrokeDrawnode()
{
}
void StrokeDrawnode::draw(){
//CCLog("StrokeDrawnode::draw");
glLineWidth(6.0f);
ccDrawColor4F(0,0,0,1);
// glEnable(GL_LINE_SMOOTH);
CCPoint pre = stroke.pointList[0];
for (int i = 1; i< stroke.pointCount; i++)
{
ccDrawLine(pre,stroke.pointList[i]);
pre = stroke.pointList[i];
}
// glDisable(GL_LINE_SMOOTH);
}
void StrokeDrawnode::addPoint(CCPoint point){
this->stroke.addPoint(point);
}
You draw your StrokeNodes but you forgot to call the CCNode::draw() function for HcharacterDrawnode:
void HcharacterDrawnode::draw(){
CCNode::draw();
CCObject* ob;
CCARRAY_FOREACH(strokeDrawlist,ob){
((StrokeDrawnode*)(ob))->draw();
}
}
Also if you overwrite init() in your class you should call init of your parent:
bool HcharacterDrawnode::init(){
if(!CCNode::init())
return false;
this->setStrokeDrawnodeList(CCArray::create());
return true;
}