Created
September 19, 2016 11:58
-
-
Save voidproc/29fa09a7a38bba7b827c45bdd4f39596 to your computer and use it in GitHub Desktop.
Simple game object container
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> | |
#include <algorithm> | |
#include <memory> | |
#include <string> | |
#include <vector> | |
#include <list> | |
#include <unordered_map> | |
using namespace std; | |
/* ---------------------------------------- | |
Shared data | |
---------------------------------------- */ | |
struct Data | |
{ | |
int val = 0; | |
}; | |
/* ---------------------------------------- | |
Entity | |
---------------------------------------- */ | |
class Entity | |
{ | |
public: | |
Entity() = default; | |
virtual ~Entity() = default; | |
virtual void update() {} | |
static Data data; | |
}; | |
Data Entity::data; | |
/* ---------------------------------------- | |
Actor | |
---------------------------------------- */ | |
class Actor : public Entity | |
{ | |
public: | |
Actor() : Entity() | |
{ | |
} | |
virtual ~Actor() = default; | |
virtual void update() override {} | |
virtual const bool collidable() { return false; } | |
virtual void collide(Actor* e) {} | |
int pos = 0; | |
string name = ""; | |
}; | |
/* ---------------------------------------- | |
Global entity container | |
---------------------------------------- */ | |
class EntityList | |
{ | |
public: | |
template <class T, class ... Args> | |
static void push_back(const string& tag, Args && ... args) | |
{ | |
instance().e_[tag].emplace_back(new T(std::forward<Args>(args) ...)); | |
} | |
static void pop_back(const string& tag) | |
{ | |
instance().e_[tag].pop_back(); | |
} | |
static shared_ptr<Entity> back(const string& tag) | |
{ | |
return instance().e_[tag].back(); | |
} | |
static const bool empty(const string& tag) | |
{ | |
return instance().e_[tag].empty(); | |
} | |
static void update(const string& tag) | |
{ | |
for (auto& e : instance().e_[tag]) | |
{ | |
e->update(); | |
} | |
} | |
static void checkCollision(const string& tag1, const string& tag2) | |
{ | |
// CAUTION: 'tag1' and 'tag2' groups must be derived from Actor. | |
for (auto& e1 : instance().e_[tag1]) | |
{ | |
Actor* a1 = dynamic_cast<Actor*>(e1.get()); | |
if (!a1->collidable()) { continue; } | |
for (auto& e2 : instance().e_[tag2]) | |
{ | |
Actor* a2 = dynamic_cast<Actor*>(e2.get()); | |
if (!a2->collidable()) { continue; } | |
if (a1->pos == a2->pos) | |
{ | |
a1->collide(a2); | |
a2->collide(a1); | |
} | |
} | |
} | |
} | |
private: | |
static EntityList& instance() | |
{ | |
static EntityList instance; | |
return instance; | |
} | |
unordered_map<string, list<shared_ptr<Entity>>> e_; | |
}; | |
/* ---------------------------------------- | |
Entities derived | |
---------------------------------------- */ | |
class Player : public Actor | |
{ | |
public: | |
Player(const int pos) : Actor() | |
{ | |
this->pos = pos; | |
name = "player"; | |
} | |
virtual ~Player() = default; | |
virtual void update() override | |
{ | |
data.val += 1; // shared data | |
cout << "Player updated [" << data.val << "]\n"; | |
} | |
virtual const bool collidable() override { return true; } | |
virtual void collide(Actor* e) override | |
{ | |
cout << "Player collide: " << e->name << "\n"; | |
} | |
}; | |
class Enemy : public Actor | |
{ | |
public: | |
Enemy(const string& name, const int pos) : Actor() | |
{ | |
this->pos = pos; | |
this->name = name; | |
} | |
virtual ~Enemy() = default; | |
virtual void update() override | |
{ | |
data.val += 5; // shared data | |
cout << name << " updated [" << data.val << "]\n"; | |
} | |
virtual const bool collidable() override { return true; } | |
virtual void collide(Actor* e) override | |
{ | |
cout << name << " collide: " << e->name << "\n"; | |
} | |
}; | |
class Fx : public Actor | |
{ | |
public: | |
Fx(const string& name, const int pos) : Actor() | |
{ | |
this->pos = pos; | |
this->name = name; | |
} | |
virtual ~Fx() = default; | |
virtual void update() override | |
{ | |
cout << name << " updated\n"; | |
} | |
}; | |
class Init : public Entity | |
{ | |
public: | |
Init() : Entity() | |
{ | |
data.val = 100000; | |
} | |
virtual ~Init() = default; | |
}; | |
/* ---------------------------------------- | |
Scenes | |
---------------------------------------- */ | |
class SceneEnd; | |
class SceneMain : public Entity | |
{ | |
public: | |
SceneMain() : Entity() | |
{ | |
} | |
virtual ~SceneMain() = default; | |
virtual void update() override | |
{ | |
cout << "Scene 'Main'\n"; | |
// Generate actors | |
EntityList::push_back<Player>("player", 10); | |
EntityList::push_back<Enemy>("enemy", "enemy1", 10); // collide this | |
EntityList::push_back<Enemy>("enemy", "enemy2", 20); | |
EntityList::push_back<Enemy>("enemy", "enemy3", 30); | |
EntityList::push_back<Enemy>("enemy", "enemy4", 10); // collide this | |
EntityList::push_back<Fx>("effect", "fx1", 10); | |
EntityList::push_back<Fx>("effect", "fx2", 20); | |
EntityList::push_back<Fx>("effect", "fx3", 30); | |
// Update actors | |
EntityList::update("player"); | |
EntityList::update("enemy"); | |
EntityList::update("effect"); | |
EntityList::checkCollision("player", "enemy"); | |
// Change scene | |
EntityList::pop_back("scene"); | |
EntityList::push_back<SceneEnd>("scene"); | |
} | |
}; | |
class SceneEnd : public Entity | |
{ | |
public: | |
SceneEnd() : Entity() | |
{ | |
} | |
virtual ~SceneEnd() = default; | |
virtual void update() override | |
{ | |
cout << "Scene 'End'\n"; | |
// Quit app | |
EntityList::pop_back("scene"); | |
} | |
}; | |
/* ---------------------------------------- | |
Main | |
---------------------------------------- */ | |
int main() | |
{ | |
Init(); | |
// Start | |
EntityList::push_back<SceneMain>("scene"); | |
while (!EntityList::empty("scene")) | |
{ | |
EntityList::back("scene")->update(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment