I wrote a simple tron clone in C++ and would appreciate some feedback.The pixelutility.h isn't included on purpose. Feel free to reuse the code where ever you want (It shouldn't be much effort to change from my library to std::vector etc.). My IDE does not support C++11 features so I am not able to use C++11 in general.globals.h:#ifndef GUARD_MANGO_GLOBALS_H#define GUARD_MANGO_GLOBALS_H#include <Gaming\pixelutility.h>//these variables are just convenience, I know it would be better practice to place them as a static member of the game class static const mango::int32 ColourList[12]  = {  ORANGE,   BLUE,   RED,   YELLOW };static const std::string  ColourNames[12] = { ORANGE, BLUE, RED, YELLOW };static const char ControlSets[4][4] = { { 'w','a','s','d' },{ 'i','j','k','l' },{ 't','f','g','h' },{ '8','4','5','6' } };static const graphic::KatCoord startPositions[4] = { graphic::KatCoord(0, 40), graphic::KatCoord(640, 260), graphic::KatCoord(400, 300), graphic::KatCoord(240, 0) };typedef mango::archive::thread_pool worker_thread;#define MANGO_NO_KEY   ' '#define MANGO_EXIT_KEY 'X'#define MANGO_W 'w'#define MANGO_A 'a'#define MANGO_S 's'#define MANGO_D 'd'#define MANGO_I 'i'#define MANGO_J 'j'#define MANGO_K 'k'#define MANGO_L 'l'#endif//GUARD_MANGO_GLOBALS_Hengine.h:#ifndef GUARD_MANGO_ENGINE_H#define GUARD_MANGO_ENGINE_H#include <Gaming/pixelutility.h>#include input.h#include globals.hnamespace engine{    class Game    {    public: //Typedefs        typedef mango::shared_ptr<graphic::GraphicController>       graphics_ptr;        typedef mango::shared_ptr<graphic::Character>               character_ptr;        typedef mango::semimap<std::string, character_ptr>          character_map;        typedef mango::pair<std::string, mango::int32>              animation;        typedef mango::vector<graphic::GraphicController::Simple32> vertex_vector;        typedef graphic::GraphicController::Simple32                Simple32;        typedef graphic::KatCoord                                   resolution;        typedef graphic::KatCoord                                   position;        typedef mango::synchro::boolean                             flag;        typedef mango::shared_ptr<engine::input::Controller>        input_ptr;        typedef mango::semimap<std::string, position>               player_map;        typedef mango::semimap<std::string, mango::int32>           colour_map;        typedef mango::semimap<std::string, input_ptr>              idevice_map;        enum direction        {            right,            left,            up,            down,            dead        };    public: //Functions        Game(graphic::KatCoord resolution = graphic::KatCoord(640, 300));        void init(mango::int32 playerNumber = 4);        void run();        void exit();        void collision();        void logic();        void update();        void draw();        void present();        void loadModel(const graphic::KatCoord& pos, const graphic::KatCoord& resolution, mango::vector<mango::pair<std::string, mango::int32>>& animations, const std::string& name);        void setCurrentBackground(const std::string& name, mango::int32 frames);        void movePlayer(mango::int32 playerNumber);        void playDestructionAnimation();        void reset();        idevice_map getInputDevice();        bool collision(position player);    private:                                                              graphics_ptr              m_GraphicDevice;        idevice_map               m_InputDevices;        character_ptr             m_CurrentBackground;        character_map             m_Characters;        player_map                m_Players;        colour_map                m_PlayerColours;        position                  m_PositionCorrection;        vertex_vector             m_UnboundVertices; //Vertices which are not part of any mesh--> unbound vertex        resolution                m_Resolution;        flag                      m_IsRunning;    };}#endif//GUARD_MANGO_ENGINE_Hengine.cpp#include engine.hengine::Game::Game(graphic::KatCoord resolution)    : m_GraphicDevice(mango::make_threadsafe(new graphic::GraphicController())), m_Resolution(resolution),      m_PositionCorrection(10, 10){}void engine::Game::init(mango::int32 playerNumber){    setCurrentBackground(MISC\\, 25);    mango::int32 dir = 0;    for (mango::int32 current = 0, playerNo = 1; playerNumber > current; ++current, ++playerNo)    {        m_Players.add(Player + mango::to_string(playerNo), startPositions[current]);        m_InputDevices.add(Player + mango::to_string(playerNo), mango::make_threadsafe(new engine::input::Controller(0, 2, 1, 3, current)));        m_PlayerColours.add(Player + mango::to_string(playerNo), ColourList[current]);        mango::vector<animation> animationsPl;        animationsPl.push_back(animation(PLAYER\\ + ColourNames[current] + \\right, 1));        animationsPl.push_back(animation(PLAYER\\ + ColourNames[current] + \\left, 1));        animationsPl.push_back(animation(PLAYER\\ + ColourNames[current] + \\up, 1));        animationsPl.push_back(animation(PLAYER\\ + ColourNames[current] + \\down, 1));        animationsPl.push_back(animation(PLAYER\\Death\\, 4));        position playerModelPos = m_Players.at(current);        playerModelPos.Y -= m_PositionCorrection.Y;        loadModel(playerModelPos, resolution(20, 20), animationsPl, Player + mango::to_string(playerNo));        m_InputDevices.back()->setCurrentDirection((input::Controller::direction)dir);        ++dir;        if (dir >= 4)        {            dir = 0;        }    }}void engine::Game::run(){    m_IsRunning = true;    while (m_IsRunning)    {        logic();        update();        draw();        present();    }}engine::Game::idevice_map engine::Game::getInputDevice(){    return m_InputDevices;}void engine::Game::exit(){    m_IsRunning = false;}bool engine::Game::collision(position player){    for (mango::int32 current = 0; m_UnboundVertices.size() > current; ++current)    {        if (m_UnboundVertices.at(current).m_Position.X == player.X && m_UnboundVertices.at(current).m_Position.Y == player.Y)        {            return true;        }        if (player.X > m_Resolution.X || player.Y > m_Resolution.Y)        {            return true;        }        if (player.X < 0 || player.Y < 0)        {            return true;        }    }    return false;}void engine::Game::collision(){    for (mango::int32 current = 0, playerNo = 1; m_Players.size() > current; ++current, ++playerNo)    {        if (collision(m_Players.at(Player + mango::to_string(playerNo))))        {            m_Characters.at(Player + mango::to_string(playerNo))->SetActiveAnimation(dead);        }    }}void engine::Game::logic(){    static clock_t updateTime = 0;    if (clock() - updateTime > 5)    {        updateTime = clock();        collision();        for (mango::int32 current = 0, playerNo = 1; m_Players.size() > current; ++current, ++playerNo)        {            m_UnboundVertices.push_back(Simple32(m_Players.at(Player + mango::to_string(playerNo)), m_PlayerColours.at(Player + mango::to_string(playerNo))));            movePlayer(playerNo);        }    }}void engine::Game::update(){    static clock_t updateTime = 0;    static clock_t updateTimeBG = 0;    if (clock() - updateTime > 100)    {        updateTime = clock();        lambda((graphic::Character* ptr) { ptr->Update(); return 0; }, 1); //exp1        mango::for_each(&m_Characters.front(), &m_Characters.back(), exp1);    }    if (clock() - updateTimeBG > 200)    {        updateTimeBG = clock();        if (0 != m_CurrentBackground)        {            m_CurrentBackground->Update();        }    }}void engine::Game::draw(){    m_GraphicDevice->ClearBuffer();    if (0 != m_CurrentBackground)    {        m_GraphicDevice->Draw(m_CurrentBackground.get());    }    m_GraphicDevice->SetVertices(m_UnboundVertices);    m_GraphicDevice->Draw(m_Characters);}void engine::Game::present(){    m_GraphicDevice->Present();}void engine::Game::loadModel(const graphic::KatCoord& pos, const graphic::KatCoord& resolution, mango::vector<mango::pair<std::string, mango::int32>>& animations, const std::string& name){    character_ptr tmp(mango::make_threadsafe(new graphic::Character(pos, resolution.X, resolution.Y)));    for (mango::int32 current = 0; animations.size() > current; ++current)    {        tmp->LoadAnimation(current, animations.at(current), animations.at(current));    }    m_Characters.add(name, tmp);}void engine::Game::setCurrentBackground(const std::string& name, mango::int32 frames){    m_CurrentBackground = mango::make_threadsafe(new graphic::Character(graphic::KatCoord(0, 0), m_Resolution.X, m_Resolution.Y));    m_CurrentBackground->LoadAnimation(0, name, frames);}void engine::Game::movePlayer(mango::int32 playerNumber){    std::string playerKey = Player + mango::to_string(playerNumber);    input::Controller::direction plDir = m_InputDevices.at(playerKey)->getCurrentDirection();    if (dead != m_Characters.at(playerKey)->GetActiveAnimation())    {        if (input::Controller::right == plDir)        {            ++m_Players.at(playerKey).X;        }        if (input::Controller::left == plDir)        {            --m_Players.at(playerKey).X;        }        if (input::Controller::down == plDir)        {            ++m_Players.at(playerKey).Y;        }        if (input::Controller::up == plDir)        {            --m_Players.at(playerKey).Y;        }        m_Characters.at(playerKey)->SetActiveAnimation(plDir);        position newModelDir = m_Players.at(playerKey);        newModelDir.Y -= m_PositionCorrection.Y;        newModelDir.X -= m_PositionCorrection.X;        m_Characters.at(playerKey)->SetPosition(newModelDir);    }    mango::int32 deathCount = 0;    for (mango::int32 current = 0; m_Characters.size() > current; ++current)    {        if (dead == m_Characters.at(current)->GetActiveAnimation())        {            ++deathCount;        }    }    if ((m_Players.size() - 1) <= deathCount)    {        playDestructionAnimation();        reset();        return;    }}void engine::Game::playDestructionAnimation(){    clock_t time = clock();    while (clock() - time <= 2000)    {        update();        draw();        present();    }}void engine::Game::reset(){    mango::int32 dir = 0;    m_UnboundVertices.clear();    for (mango::int32 current = 0, playerNo = 1; m_Characters.size() > current; ++current, ++playerNo)    {        m_Players.at(Player + mango::to_string(playerNo)) = startPositions[current];        position playerModelPos = m_Players.at(current);        playerModelPos.Y -= m_PositionCorrection.Y;        m_Characters.at(Player + mango::to_string(playerNo))->SetPosition(playerModelPos);        m_Characters.at(Player + mango::to_string(playerNo))->SetActiveAnimation(dir);        m_InputDevices.at(Player + mango::to_string(playerNo))->setCurrentDirection((input::Controller::direction)dir);        ++dir;        if (dir >= 4) //4 directions--> up, down, left, right--> sets the player directions back to the initial direction        {            dir = 0;        }    }    mango::csleep(500);}input.h:#ifndef GUARD_MANGO_INPUT_H#define GUARD_MANGO_INPUT_H#include <mangoarchive.h>#include globals.hnamespace engine{    namespace input    {        class Controller        {        public:            typedef mango::Byte  Key;            typedef mango::mutex Lock;            enum direction            {                right,                left,                up,                down            };        public:            Controller(Key keyUp, Key keyDown, Key keyLeft, Key keyRight);            Controller(mango::int32 keyUp, mango::int32 keyDown, mango::int32 keyLeft, mango::int32 keyRight, mango::int32 set);            direction getCurrentDirection();            void keyPressed(const Key key);            void setCurrentDirection(direction newDirection);            static Key getCurrentInput();        private:            direction m_CurrentDirection;            Key       m_Up;            Key       m_Down;            Key       m_Left;            Key       m_Right;            Lock      m_InputLock;        };    }}#endif//GUARD_MANGO_INPUT_Hinput.cpp:#include input.hengine::input::Controller::Controller(Key keyUp, Key keyDown, Key keyLeft, Key keyRight)    : m_CurrentDirection(right), m_Up(keyUp), m_Down(keyDown), m_Left(keyLeft), m_Right(keyRight){}engine::input::Controller::Controller(mango::int32 keyUp, mango::int32 keyDown, mango::int32 keyLeft, mango::int32 keyRight, mango::int32 set)    : m_CurrentDirection(right), m_Up(ControlSets[set][keyUp]), m_Down(ControlSets[set][keyDown]), m_Left(ControlSets[set][keyLeft]), m_Right(ControlSets[set][keyRight]){}engine::input::Controller::direction engine::input::Controller::getCurrentDirection(){    mango::lock_guard<Lock> guard(m_InputLock);    direction dir = m_CurrentDirection;    return dir;}void engine::input::Controller::keyPressed(const Key key){    mango::lock_guard<Lock> guard(m_InputLock);    if (key == m_Up && m_CurrentDirection != up && m_CurrentDirection != down)    {        m_CurrentDirection = up;        return;    }    if (key == m_Down && m_CurrentDirection != down && m_CurrentDirection != up)    {        m_CurrentDirection = down;        return;    }    if (key == m_Left && m_CurrentDirection != left && m_CurrentDirection != right)    {        m_CurrentDirection = left;        return;    }    if (key == m_Right && m_CurrentDirection != right && m_CurrentDirection != left)    {        m_CurrentDirection = right;        return;    }}engine::input::Controller::Key engine::input::Controller::getCurrentInput(){    return mango::archive::mgetch();}void engine::input::Controller::setCurrentDirection(direction newDirection){    mango::lock_guard<Lock> guard(m_InputLock);    m_CurrentDirection = newDirection;}main.cpp:#include <trymacro.h>#include engine.h#include input.hmango::int32 main(){    mango::shared_ptr<engine::Game>           game   = mango::make_threadsafe(new engine::Game());    mango::shared_ptr<mango::archive::worker> worker = mango::make_threadsafe(new mango::archive::worker());    mango::int32 playerNumber = 2;    mango::archive::print_t(enter player number (max 4): );    std::cin >> playerNumber;    system(CLS);    game->init(playerNumber);    engine::Game::idevice_map ics = game->getInputDevice();    M_TRY    {        lambda((mango::shared_ptr<engine::Game> game) { game->run(); return 0; }, 1); //exp1        worker->run(exp1, game);        engine::input::Controller::Key input = MANGO_NO_KEY;        while (MANGO_EXIT_KEY != input)        {            input = engine::input::Controller::getCurrentInput();            lambda((engine::Game::input_ptr controller, engine::input::Controller::Key key)             {                controller->keyPressed(key);                 return 0;             }, 2);            mango::for_each(&ics.front(), &ics.back(), exp2, input); //exp2        }        game->exit();    }    M_CATCH(main.txt)}//M_TRY {} M_CATCH(main.txt) --> try catch block to catch //mango::exception:: and critical errors and logging them to main.txt.And a screenshot from the finished game:and for those wo looked over my previous game samples:Tetris as general game exampleAn example for a space arcade 2d shooter in C++this is how I started
A simple tron clone
c++;game