This is was an exercise utilizing the component base system from Pong, the hash-map implementation from Missile Command and implementing a Finite State Machine to control the behaviour of the weapon you use to destroy the aliens (if you can call aliens the green circles at the bottom).
/*
* Carlos Adan Cortes De la Fuente
* All rights reserved. Copyright (c)
* Email: dev@carlosadan.com
*/
class COGFSM : public Component
{
private:
FSMState* mCurrent;
FSMState* mNext;
public:
static std::vector<COGFSM*> mFSMComponents;
COGFSM(GameObject* pGO) : Component(pGO), mCurrent(nullptr), mNext(nullptr) {}
~COGFSM()
{
// Makes sure the states are cleaned
delete mNext;
delete mCurrent;
}
// Component funcitons
virtual ComponentType GetType() const { return ComponentType::FSM; }
virtual void Initialize() override { AddToComponentVector(mFSMComponents); }
virtual void Destroy() override { RemoveFromComponentVector(mFSMComponents); }
// Manages the state changes
void Initialize(FSMState* pState)
{
assert(mCurrent == nullptr); // Terminate the program if the state machine has an initial state before we stablish one
mCurrent = pState;
}
// Assigns the next state to the FSM
void Next(FSMState* pState)
{
if (mCurrent != nullptr)
{
delete mNext;
}
mNext = pState;
}
// Runs through the game loop for that state machine
void Update(float fDeltaT)
{
// Means we have a new state to transition to
if (mNext != nullptr)
{
mCurrent->OnExit(); // Runs the exit state code
delete mCurrent;
mCurrent = mNext;
mCurrent->OnEnter(); // Runs the on enter code
mNext = nullptr;
}
mCurrent->OnUpdate(fDeltaT);
}
// Creates a New State depending on the type
template<class T>
T* Create()
{
return new T(this);
}
};
std::vector<COGFSM*> COGFSM::mFSMComponents; // inits the fsm components
/*
* Carlos Adan Cortes De la Fuente
* All rights reserved. Copyright (c)
* Email: dev@carlosadan.com
*/
class FSMState
{
protected:
COGFSM* mFSM;
public:
FSMState(COGFSM* pFSM) : mFSM(fFSM) {}
~FSMState() {}
virtual void OnEnter() {} // Gets called when the state is entered for the first time
virtual void OnExit() {} // Gets called when the state is ending
virtual void OnUpdate(float fDeltaT) {}; // gets called every frame that the state is active
};
/*
* Carlos Adan Cortes De la Fuente
* All rights reserved. Copyright (c)
* Email: dev@carlosadan.com
*/
#define PI 3.14159265f
#define Deg2Rad PI / 180.0f
#define Rad2Deg 180.0f / PI
class FSMStateFire : public FSMState
{
public:
FSMStateFire(COGFSM* pFSM) {}
~FSMStateFire() {}
virtual void OnUpdate(float fDeltaT) override
{
// Shoot
if (InputManager::GetInstance()->mMouseLeft && InputManager::GetInstance()->mMouseLeft != InputManager::GetInstance()->mMouseLeftPreviousState)
{
for (IShootEvent* pIShootEventListener : World::mShootEventListeners)
{
exColor color;
color.mColor[0] = 252;
color.mColor[1] = 115;
color.mColor[2] = 17;
color.mColor[3] = 255;
// We get the main angle and add and substract degrees
exVector2 mousePos = InputManager::GetInstance()->mMousePosition;
exVector2 origin = mFSM->GetGameObject()->FindComponent<COGLineShape>(ComponentType::LineShape)->GetOrigin();
exVector2 dir = Vector2::GetDirectionVector(origin, mousePos);
exVector2 normalizedDir = Vector2::Normalized(dir);
// We get the angle for the other two vector
float angle = std::atan2(dir.y, dir.x);
float spread = 25.0f;
exVector2 bulletDown = { std::cos(angle + spread * Deg2Rad), std::sin(angle + spread * Deg2Rad) };
exVector2 bulletUp = { std::cos(angle - spread * Deg2Rad), std::sin(angle - spread * Deg2Rad) };
// Spawns 3 bullets
pIShootEventListener->OnBulletSpawn(normalizedDir, color); // Center Bullet
pIShootEventListener->OnBulletSpawn(bulletUp, color); // Bullet going up
pIShootEventListener->OnBulletSpawn(bulletDown, color); // Bullet going down
}
}
// Cache Input
InputManager::GetInstance()->CacheInput();
}
};