diff --git a/CMakeLists.txt b/CMakeLists.txt index bb58a89..8176ff3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,3 +17,4 @@ target_link_libraries(Space mingl) target_link_libraries(Space GL) target_link_libraries(Space GLU) target_link_libraries(Space glut) +target_link_libraries(Space pthread) diff --git a/assets/game_background.si2 b/assets/game_background.si2 deleted file mode 100644 index a0a63e3..0000000 Binary files a/assets/game_background.si2 and /dev/null differ diff --git a/assets/hand_closed.si2 b/assets/hand_closed.si2 deleted file mode 100644 index f6d2d30..0000000 Binary files a/assets/hand_closed.si2 and /dev/null differ diff --git a/assets/hand_open.si2 b/assets/hand_open.si2 deleted file mode 100644 index f6d2d30..0000000 Binary files a/assets/hand_open.si2 and /dev/null differ diff --git a/assets/menu_background.si2 b/assets/menu_background.si2 deleted file mode 100644 index 763c1c7..0000000 Binary files a/assets/menu_background.si2 and /dev/null differ diff --git a/config.yml b/config.yml index ce9638b..d9e75bb 100644 --- a/config.yml +++ b/config.yml @@ -1,6 +1,7 @@ # General configuration general: maxFPS: 90 + theme: bad # Players config players: diff --git a/headers/configData.h b/headers/configData.h index a5e8cc3..39763cd 100644 --- a/headers/configData.h +++ b/headers/configData.h @@ -25,7 +25,12 @@ typedef string configKey; * @brief this struct stores all relevant data from the configuration file */ struct ConfigData { - + + /*! + * @brief theme to use. Valid values : good,bad + */ + string theme; + /*! * @brief maximum framerate at which the game will run */ diff --git a/headers/game.h b/headers/game.h index 153081a..b55d2fb 100644 --- a/headers/game.h +++ b/headers/game.h @@ -14,7 +14,7 @@ #define GUARD_GAME_H #include #include "mingl/mingl.h" -#include "pixelManager.h" +#include "pixelManager/pixelManager.h" #include "utils.h" #include "playerDef.h" #include "player.h" @@ -41,8 +41,9 @@ private: /*! * @brief PixelManager : Class that contains and draws all the data that will be drawn on screen + * This is a pointer because the object is allocated at runtime, following the configuration */ - PixelManager pm; + unique_ptr pm; /*! * @brief ConfigData : Struct that stores all the relevant data read from the configuration file @@ -65,7 +66,7 @@ private: Position basePos; /*! - * @brief Invader posision and type matrix + * @brief Invader position and type matrix */ InvadersGrid grid; @@ -97,9 +98,9 @@ private: // invaders related variables /*! - * @brief cooldown between two invader shot in milliseconds + * @brief cooldown until the invaders can shoot again */ - unsigned fireCooldown=120; + unsigned fireCooldown=0; // basic methods diff --git a/headers/mySprite.h b/headers/mySprite.h new file mode 100644 index 0000000..028c16c --- /dev/null +++ b/headers/mySprite.h @@ -0,0 +1,16 @@ +#ifndef GUARD_MYSPRITE_H +#define GUARD_MYSPRITE_H + +#include +#include "mingl/gui/sprite.h" + +using namespace std; + +class MySprite{ +public: + unique_ptr ptr; + future asyncLoad(const string& fname); + void mirror(MySprite& msp); +}; + +#endif diff --git a/headers/pixelManager/goodPixelManager.h b/headers/pixelManager/goodPixelManager.h new file mode 100644 index 0000000..b086d17 --- /dev/null +++ b/headers/pixelManager/goodPixelManager.h @@ -0,0 +1,21 @@ +#ifndef GUARD_GOODPIXELMANAGER_H +#define GUARD_GOODPIXELMANAGER_H + +#include "pixelManager/pixelManager.h" + +class GoodPixelManager : public PixelManager{ + + void loadSprites(SpriteTasks& tasks) override; + + MySprite player; + MySprite invaderA; + MySprite invaderB; + MySprite invaderC; + MySprite missile; + MySprite torpedo; +public: + GoodPixelManager(MinGL& win); +}; + + +#endif diff --git a/headers/pixelManager.h b/headers/pixelManager/pixelManager.h similarity index 88% rename from headers/pixelManager.h rename to headers/pixelManager/pixelManager.h index 94d2e45..6658037 100644 --- a/headers/pixelManager.h +++ b/headers/pixelManager/pixelManager.h @@ -24,54 +24,64 @@ #include "utils.h" #include "playMode.h" #include "menu.h" +#include "mySprite.h" using namespace std; -#define MIRROR(SP) mirrorData((SP).getPixelData(), (SP).getRowSize()), (SP).getRowSize() - typedef nsGui::GlutFont::GlutFonts Font; /*! * @class PixelManager * @brief main display function, clear the window and calls sub display functions */ + +/* + * It's MinGL's fault. This is all I have to say + */ + +// The convention seems to just add a number to the macro name +#define ADD_TASK(X) ADD_TASK2(X, X) +#define ADD_TASK2(X, Y) tasks.push_back((X).asyncLoad("assets/"#Y".si2")); + +typedef vector> SpriteTasks; + + class PixelManager{ public: MinGL& window; - /* - * Sprites are not const because for some reason the texture is associated with coordinates, - * and we have no way to dissociate them... - * So the objects are constantly updated with new coordinates as they need to be drawn - * We used {} insead of () for the constructor because the () makes the compiler think we declare methods - * - * (We could copy them every time, but I feel like copying image data every frame isn't great) - */ - + /*! + * @brief loads sprites in parallel using multiple threads + * @param[in] vec : We take his ownership, so + * @fn void loadSprites(); + */ + virtual void loadSprites(SpriteTasks& tasks); + + /*! * @brief sprite of the logo of the game */ - nsGui::Sprite logo{"assets/logo.si2"}; - - /*! - * @brief sprite of the background during gameplay - */ - nsGui::Sprite gameBackground{"assets/game_background.si2"}; - + MySprite logo; + /*! * @brief sprite of the background during menu */ - nsGui::Sprite menuBackground{"assets/menu_background.si2"}; - + MySprite menuBackground; + + /*! + * @brief sprite of the background during gameplay + */ + MySprite gameBackground; + /*! * @brief sprite of the right hand of god */ - nsGui::Sprite rightHand{"assets/hand_open.si2"}; + MySprite rightHand; /*! * @brief sprite of the left hand of god */ - nsGui::Sprite leftHand{MIRROR(rightHand)}; + MySprite leftHand; /*! * @brief constructor the pixel manager class @@ -145,11 +155,11 @@ public: /*! * @brief display a sprite on screen - * @param[in] sprite : sprite to draw + * @param[in] msp : sprite to draw * @param[in] pos : pixel coordinates to draw the sprite - * @fn void drawSprite(const nsGui::Sprite& sprite, const Position& pos = Position(0, 0)) const; + * @fn void drawSprite(const MySprite& msp, const Position& pos = Position(0, 0)) const; */ - void drawSprite(const nsGui::Sprite& sprite, const Position& pos = Position(0, 0)) const; + void drawSprite(const MySprite& msp, const Position& pos = Position(0, 0)) const; /*! * @brief display a menu button on screen diff --git a/src/configManagement.cpp b/src/configManagement.cpp index 22bf164..469f08b 100644 --- a/src/configManagement.cpp +++ b/src/configManagement.cpp @@ -153,6 +153,7 @@ void ConfigBuilder::readInvaderType(const configKey& baseKey, InvaderTypeDef& in void ConfigBuilder::readConfig() { + collectedData.theme = getString("general.theme"); collectedData.maxFPS = getInt("general.maxFPS"); readGrid("grid"); diff --git a/src/game/display.cpp b/src/game/display.cpp index 88477d6..bbf173f 100644 --- a/src/game/display.cpp +++ b/src/game/display.cpp @@ -16,7 +16,7 @@ * The more important stuff must be drawn last */ void Game::displayAll() const { - pm.drawSprite(pm.gameBackground); + pm->drawSprite(pm->gameBackground); for (unsigned i = 0; i < this->grid.size(); ++i){ for (unsigned j = 0; j < this->grid[i].size(); ++j){ Position vec( @@ -28,23 +28,23 @@ void Game::displayAll() const { } for(const missile& miss : missiles){ - pm.drawMissile(miss, confData.missilesWidth, confData.missilesColor); + pm->drawMissile(miss, confData.missilesWidth, confData.missilesColor); } for(const Torpedo& tor : torpedos){ - pm.drawTorpedo(tor, confData.torpedosWidth, confData.torpedosColor); + pm->drawTorpedo(tor, confData.torpedosWidth, confData.torpedosColor); } displayGod(); DEBUG_INSTR( - pm.drawText(Position(pm.getScreenWidth()-200, 20), "FPS : "+to_string(fps), nsGraphics::KWhite, Font::BITMAP_8_BY_13); + pm->drawText(Position(pm->getScreenWidth()-200, 20), "FPS : "+to_string(fps), nsGraphics::KWhite, Font::BITMAP_8_BY_13); ) for(unsigned i=0;idrawPlayer(players[i].x, confData.playersWidth, confData.playerDefs[i].color); } } // out of the condition, because we still need to display the falling heart @@ -57,15 +57,15 @@ void Game::displayHearts(playerID pID) const { // As said before, the player loop is an illusion, 2 players max unsigned x; if(pID==PLAYER1)x = 0; - else x = pm.getScreenWidth()-HEART_LENGTH; + else x = pm->getScreenWidth()-HEART_LENGTH; unsigned y = GOD_BENCH_SIZE+5; for(unsigned i=0;idrawHeart(Position(x, y)); y+=HEART_LENGTH+5; } if(players[pID].hasDeathAnimation()){ - pm.drawHeart(Position(x, y+players[pID].deathAnimCounter*5)); + pm->drawHeart(Position(x, y+players[pID].deathAnimCounter*5)); } } @@ -74,15 +74,15 @@ void Game::displayInvader(const Position& pos, InvaderType type) const { const InvaderTypeDef& invDef = confData.invadersDef.at(type); switch(type){ case InvaderType::TYPEA:{ - pm.drawInvaderA(pos, confData.invadersSize, invDef.color); + pm->drawInvaderA(pos, confData.invadersSize, invDef.color); return; } case InvaderType::TYPEB:{ - pm.drawInvaderB(pos, confData.invadersSize, invDef.color); + pm->drawInvaderB(pos, confData.invadersSize, invDef.color); return; } case InvaderType::TYPEC:{ - pm.drawInvaderC(pos, confData.invadersSize, invDef.color); + pm->drawInvaderC(pos, confData.invadersSize, invDef.color); return; } } @@ -97,40 +97,40 @@ void Game::displayGod() const { case GodState::NONE: return; case GodState::AWAKE: { - pm.drawGodBench(god.counter - GOD_BENCH_SIZE); + pm->drawGodBench(god.counter - GOD_BENCH_SIZE); Position leftHand(GOD_HAND_DISTANCE, god.counter-GOD_BENCH_SIZE); - Position rightHand(pm.getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE, god.counter-GOD_BENCH_SIZE); - pm.drawGodLeftHand(leftHand); - pm.drawGodRightHand(rightHand); - pm.drawGodFace(god.counter - GOD_BENCH_SIZE); + Position rightHand(pm->getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE, god.counter-GOD_BENCH_SIZE); + pm->drawGodLeftHand(leftHand); + pm->drawGodRightHand(rightHand); + pm->drawGodFace(god.counter - GOD_BENCH_SIZE); break; } case GodState::WAIT:{ - pm.drawGodBench(0); + pm->drawGodBench(0); Position leftHand(GOD_HAND_DISTANCE, 0); - Position rightHand(god.getRightHandPos(pm.getScreenWidth())); - pm.drawGodLeftHand(leftHand); - pm.drawGodRightHand(rightHand); - pm.drawGodFace(0); + Position rightHand(god.getRightHandPos(pm->getScreenWidth())); + pm->drawGodLeftHand(leftHand); + pm->drawGodRightHand(rightHand); + pm->drawGodFace(0); break; } case GodState::RETRIEVE1: case GodState::RETRIEVE2:{ // Bezier curve // counter goes [0-100] - pm.drawGodBench(0); - pm.drawGodLeftHand(Position(GOD_HAND_DISTANCE, 0)); - pm.drawGodFace(0); + pm->drawGodBench(0); + pm->drawGodLeftHand(Position(GOD_HAND_DISTANCE, 0)); + pm->drawGodFace(0); - Position pos(god.getRightHandPos(pm.getScreenWidth())); + Position pos(god.getRightHandPos(pm->getScreenWidth())); Position endPos = invIndexToPos(god.thrownInvPosX, god.thrownInvPosY); applyBezier(pos, god.thrownTransition, god.counter / 100.0); applyBezier(pos, endPos, god.counter / 100.0); // pos is now the position we need to draw our hand to - pm.drawGodRightHand(pos); + pm->drawGodRightHand(pos); if(god.thrownInvType!=InvaderType::NONE){ pos+=Position(GOD_HAND_SIZE/2, GOD_HAND_SIZE/2); @@ -140,12 +140,12 @@ void Game::displayGod() const { break; } case GodState::THROW:{ - pm.drawGodBench(0); - pm.drawGodLeftHand(Position(GOD_HAND_DISTANCE, 0)); - pm.drawGodFace(0); + pm->drawGodBench(0); + pm->drawGodLeftHand(Position(GOD_HAND_DISTANCE, 0)); + pm->drawGodFace(0); // compute start position (not sure if we should store it or compute it each time ?) - Position handPos = god.getRightHandPos(pm.getScreenWidth()); + Position handPos = god.getRightHandPos(pm->getScreenWidth()); Position invaderPos = handPos; applyTransformation(invaderPos, GOD_HAND_SIZE, confData.invadersSize); @@ -160,7 +160,7 @@ void Game::displayGod() const { else handCounter = 30-god.counter; handPos = handPos + god.thrownVector * (handCounter / 100.0); } - pm.drawGodRightHand(handPos); + pm->drawGodRightHand(handPos); break; } diff --git a/src/game/gameBasics.cpp b/src/game/gameBasics.cpp index bdcf93b..322d0db 100644 --- a/src/game/gameBasics.cpp +++ b/src/game/gameBasics.cpp @@ -10,17 +10,42 @@ */ #include +#include #include #include "game.h" #include "playMode.h" +#include "pixelManager/goodPixelManager.h" #define WININIT window("SUPER Space Invader : Turbo Apocalypse DX - VS GOD", Position(1280, 720), Position(128, 128), nsGraphics::KBlack) -Game::Game() : WININIT, pm(window) { - if(!reloadConfig()){ +Game::Game() : WININIT { + + if(!reloadConfig()){ // Config throw runtime_error("Initial config loading failed. Please check the error above and fix the configuration"); } - sm.readFile(); + + // Pixel Manager + if(confData.theme=="good"){ + pm = std::make_unique(window); + }else if(confData.theme=="bad"){ + pm = std::make_unique(window); + }else throw runtime_error("Invalid theme value : "+confData.theme+ + "\nValid values are : good,bad"); + + cout << "Loading sprites..." << endl; + SpriteTasks tasks; + chrono::high_resolution_clock::time_point start = chrono::high_resolution_clock::now(); + + pm->loadSprites(tasks); + for(future& f : tasks)f.wait(); + + // We just do that for one sprite, so I didn't bother creating an 'API' for that + pm->leftHand.mirror(pm->rightHand); + + chrono::high_resolution_clock::duration elapsed = chrono::high_resolution_clock::now()-start; + cout << "Done ! Time : " << chrono::duration_cast(elapsed).count() << "ms" << endl; + + sm.readFile(); // Score manager } bool Game::areThereInvadersLeft(){ @@ -30,7 +55,7 @@ bool Game::areThereInvadersLeft(){ void Game::handleScoreSaving(){ for(unsigned i=0;iaskPlayerNameMenu(i, players[i].score, pName); sm.inputScore(move(pName), players[i].score); } sm.writeFile(); @@ -42,13 +67,13 @@ void Game::managedGames() { while(playMode!=PlayMode::EXIT){ if(playMode==PlayMode::NONE){ - playMode = pm.showInitialMenu(); + playMode = pm->showInitialMenu(); }else{ initGame(); enterGameLoop(); // will read the playMode handleScoreSaving(); cout << "END OF GAME" << endl; - if(!pm.showDeathMenu())playMode = PlayMode::NONE; + if(!pm->showDeathMenu())playMode = PlayMode::NONE; } } } @@ -69,7 +94,7 @@ void Game::initGame(){ }else{ players.resize(2); // mirror the start X Position for the other - players[1].x = pm.getScreenWidth() - confData.startXPosition - confData.playersWidth; + players[1].x = pm->getScreenWidth() - confData.startXPosition - confData.playersWidth; } players[0].x = confData.startXPosition; @@ -103,7 +128,7 @@ WinValue Game::enterGameLoop(){ // returns when game is finished fpsStartTime = startTime; } - pm.startFrame(); + pm->startFrame(); managePlayers(); if(manageInvaders()) { // if they went down @@ -126,7 +151,7 @@ WinValue Game::enterGameLoop(){ // returns when game is finished displayAll(); - pm.endFrame(); + pm->endFrame(); MyTimePoint endTime = chrono::high_resolution_clock::now(); diff --git a/src/game/gameManagers.cpp b/src/game/gameManagers.cpp index 9dd17c4..ee1cf05 100644 --- a/src/game/gameManagers.cpp +++ b/src/game/gameManagers.cpp @@ -20,7 +20,7 @@ void Game::manageOnePlayer(playerID pID){ else p.x -= confData.playersSpeed; } if (ISPRESSED(pID, right)){ - if(p.x + confData.playersWidth + confData.playersSpeed >= pm.getScreenWidth()) p.x = pm.getScreenWidth() - confData.playersWidth - 1; + if(p.x + confData.playersWidth + confData.playersSpeed >= pm->getScreenWidth()) p.x = pm->getScreenWidth() - confData.playersWidth - 1; else p.x += confData.playersSpeed; } @@ -35,7 +35,7 @@ void Game::manageOnePlayer(playerID pID){ if(p.fireCooldown==0) { if (ISPRESSED(pID, shoot)) { - torpedos.emplace_back(p.x + confData.playersWidth / 2, pm.getScreenHeight() - PLAYER_HEIGHT, pID); + torpedos.emplace_back(p.x + confData.playersWidth / 2, pm->getScreenHeight() - PLAYER_HEIGHT, pID); p.fireCooldown = confData.playersFireCooldown; } }else --p.fireCooldown; @@ -69,7 +69,7 @@ bool Game::manageInvaders(){ // you got the end position of the invader crowd ! - if(end + confData.invadersSpeed < pm.getScreenWidth()){ + if(end + confData.invadersSpeed < pm->getScreenWidth()){ basePos.setX(basePos.getX() + confData.invadersSpeed); }else{ basePos.setY(basePos.getY() + confData.invadersSize + confData.invadersDistance); @@ -121,7 +121,7 @@ void Game::remCollidingProjectiles(){ void Game::moveMissiles() { auto miss = missiles.begin(); while (miss != missiles.end()) { - if (miss->getY() >= pm.getScreenHeight())missiles.erase(miss); + if (miss->getY() >= pm->getScreenHeight())missiles.erase(miss); else { miss->setY(miss->getY()+confData.missilesSpeed); ++miss; @@ -144,7 +144,7 @@ void Game::checkMissilesAndPlayers() { auto miss_ite = missiles.begin(); while(miss_ite!=missiles.end()){ bool wasColliding = false; - if(miss_ite->getY()>=pm.getScreenHeight()-PLAYER_HEIGHT){ // check collision on Y + if(miss_ite->getY()>=pm->getScreenHeight()-PLAYER_HEIGHT){ // check collision on Y // now check collision on X (with both players) for(Player& p : players){ if(p.isPlaying()){ @@ -206,6 +206,6 @@ bool Game::invadersTouchPlayer() const { unsigned outter = line.getOutterInvader(); return this->basePos.getY()+confData.invadersSize*(outter+1) +confData.invadersDistance*outter - >= pm.getScreenHeight() - PLAYER_HEIGHT; + >= pm->getScreenHeight() - PLAYER_HEIGHT; }); } diff --git a/src/game/godManager.cpp b/src/game/godManager.cpp index 15ef8a8..cfd3d1a 100644 --- a/src/game/godManager.cpp +++ b/src/game/godManager.cpp @@ -48,7 +48,7 @@ bool Game::manageGod() { god.thrownInvPosY = grid[god.thrownInvPosX].randomValidInv(); god.thrownInvType = InvaderType::NONE; - god.thrownTransition.setX(pm.getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE); + god.thrownTransition.setX(pm->getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE); god.thrownTransition.setY(basePos.getY() + INV_GET_POS(god.thrownInvPosY)); return false; } @@ -79,7 +79,7 @@ bool Game::manageGod() { // compute the launch vector - Position invaderMiddlePos(pm.getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE / 2, + Position invaderMiddlePos(pm->getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE / 2, GOD_HAND_SIZE / 2); @@ -90,7 +90,7 @@ bool Game::manageGod() { * honestly at this point I want to re-code the whole game engine to allow a better handling of cases like this...*/ Position playerMiddlePos(players[target].x + confData.playersWidth / 2, - pm.getScreenHeight() - PLAYER_HEIGHT / 2); + pm->getScreenHeight() - PLAYER_HEIGHT / 2); god.thrownVector = playerMiddlePos - invaderMiddlePos; god.thrownVector = god.thrownVector / (god.thrownVector.computeMagnitude() / 1000.0); @@ -101,7 +101,7 @@ bool Game::manageGod() { case GodState::THROW: { ++god.counter; - Position invaderPos = god.getRightHandPos(pm.getScreenWidth()); + Position invaderPos = god.getRightHandPos(pm->getScreenWidth()); applyTransformation(invaderPos, GOD_HAND_SIZE, confData.invadersSize); Position a = god.thrownVector * (god.counter / 100.0); invaderPos = invaderPos + a; @@ -109,8 +109,8 @@ bool Game::manageGod() { bool touched = false; // check if OOB (Out Of Bounds) - if (invaderPos.getY() + confData.invadersSize >= pm.getScreenWidth() || - (invaderPos.getX() < 0 || invaderPos.getX() + confData.invadersSize >= pm.getScreenWidth())) { + if (invaderPos.getY() + confData.invadersSize >= pm->getScreenWidth() || + (invaderPos.getX() < 0 || invaderPos.getX() + confData.invadersSize >= pm->getScreenWidth())) { touched = true; /* there are no invaders in the grid anymore, and the one thrown just went out of bound @@ -118,7 +118,7 @@ bool Game::manageGod() { if(!areThereInvadersLeft())return true; // check player collision - } else if (invaderPos.getY() + confData.invadersSize >= pm.getScreenHeight() - PLAYER_HEIGHT) { + } else if (invaderPos.getY() + confData.invadersSize >= pm->getScreenHeight() - PLAYER_HEIGHT) { for (Player &p: players) { if(p.isPlaying()){ if (areLinesColliding( diff --git a/src/mySprite.cpp b/src/mySprite.cpp new file mode 100644 index 0000000..c34b921 --- /dev/null +++ b/src/mySprite.cpp @@ -0,0 +1,26 @@ +#include "utils.h" +#include "mySprite.h" + +future MySprite::asyncLoad(const string& fname){ + return std::async(std::launch::async, [fname, this]() -> void { + ptr = std::make_unique(fname); + }); +} + +void MySprite::mirror(MySprite& msp) { + const vector& inPixels = msp.ptr->getPixelData(); + unsigned rowSize = msp.ptr->getRowSize(); + + vector outPixels; + // we reserve size so the vector doesn't dynamically grows + outPixels.reserve(inPixels.size()); + //for each line of pixel + for(unsigned rowOffset=0; rowOffset < inPixels.size(); rowOffset+=rowSize){ + // for each pixel of that line + for(unsigned j=0;j(outPixels, rowSize); +} diff --git a/src/drawEntity.cpp b/src/pixelManager/drawEntities.cpp similarity index 82% rename from src/drawEntity.cpp rename to src/pixelManager/drawEntities.cpp index a4fc9ea..b159ab4 100644 --- a/src/drawEntity.cpp +++ b/src/pixelManager/drawEntities.cpp @@ -11,7 +11,7 @@ */ #include "mingl/gui/text.h" -#include "pixelManager.h" +#include "pixelManager/pixelManager.h" #include "utils.h" #include "god.h" @@ -76,26 +76,10 @@ void PixelManager::drawTorpedo(const Position& baseVector, unsigned width, const window << Rectangle(baseVector, baseVector + Position(width, width * PROJ_LENGTH_FACTOR), color); } -void PixelManager::drawSprite(const Sprite& sprite, const Position& pos) const { - // see pixelManager.h for the explanation of this hack - const_cast(sprite).setPosition(pos); - sprite.draw(window); -} - -unsigned PixelManager::getScreenHeight() const { - return window.getWindowSize().getY(); -} - -unsigned PixelManager::getScreenWidth() const { - return window.getWindowSize().getX(); -} - -void PixelManager::startFrame() const { - window.clearScreen(); -} - -void PixelManager::endFrame() const { - window.finishFrame(); +void PixelManager::drawSprite(const MySprite& msp, const Position& pos) const { + // The sprite is associated with a Vec2D for whatever reason, so yeah, we modify it each time we draw it + msp.ptr->setPosition(pos); + msp.ptr->draw(window); } void PixelManager::drawGodBench(int y) const { @@ -128,19 +112,3 @@ void PixelManager::drawGodFace(int y, bool angry) const { void PixelManager::drawText(const Position& pos, const string& text, const nsGraphics::RGBAcolor& color, Font font) const { window << Text(pos, text, color, font); } - -vector -PixelManager::mirrorData(const vector& inPixels, unsigned rowSize) { - vector outPixels; - // we reserve size so the vector doesn't dynamically grows - outPixels.reserve(inPixels.size()); - //for each line of pixel - for(unsigned rowOffset=0; rowOffset < inPixels.size(); rowOffset+=rowSize){ - // for each pixel of that line - for(unsigned j=0;j #include "mingl/shape/rectangle.h" #include "playMode.h" -#include "pixelManager.h" +#include "pixelManager/pixelManager.h" #include "utils.h" using namespace nsShape; using namespace nsGraphics; -void PixelManager::displayButton(const Position& baseVector,const string& text,nsGraphics::RGBAcolor& color){ +void PixelManager::displayButton(const Position& baseVector, const string& text, nsGraphics::RGBAcolor& color){ window << Rectangle(baseVector, Position(180, 40)+baseVector, KGray); window << Rectangle(baseVector+Position(2,2), Position(178, 38)+baseVector, KBlack); window << nsGui::Text(baseVector+Position(10,22), text, color); diff --git a/src/pixelManager/goodPixelManager.cpp b/src/pixelManager/goodPixelManager.cpp new file mode 100644 index 0000000..f9fa430 --- /dev/null +++ b/src/pixelManager/goodPixelManager.cpp @@ -0,0 +1,15 @@ +#include "pixelManager/goodPixelManager.h" + +void GoodPixelManager::loadSprites(SpriteTasks& tasks) { + PixelManager::loadSprites(tasks); + ADD_TASK(player) + ADD_TASK(invaderA) + ADD_TASK(invaderB) + ADD_TASK(invaderC) + ADD_TASK(missile) + ADD_TASK(torpedo) +} + +GoodPixelManager::GoodPixelManager(MinGL& win) : PixelManager(win) { + +} diff --git a/src/pixelManager/pixelManager.cpp b/src/pixelManager/pixelManager.cpp new file mode 100644 index 0000000..f1afd5c --- /dev/null +++ b/src/pixelManager/pixelManager.cpp @@ -0,0 +1,41 @@ +#include "pixelManager/pixelManager.h" + + +void PixelManager::loadSprites(SpriteTasks& tasks){ + ADD_TASK(logo) + ADD_TASK(menuBackground) + ADD_TASK(gameBackground) + ADD_TASK2(rightHand, hand) +} + +void PixelManager::startFrame() const { + window.clearScreen(); +} + +void PixelManager::endFrame() const { + window.finishFrame(); +} + +unsigned PixelManager::getScreenHeight() const { + return window.getWindowSize().getY(); +} + +unsigned PixelManager::getScreenWidth() const { + return window.getWindowSize().getX(); +} + +vector +PixelManager::mirrorData(const vector& inPixels, unsigned rowSize) { + vector outPixels; + // we reserve size so the vector doesn't dynamically grows + outPixels.reserve(inPixels.size()); + //for each line of pixel + for(unsigned rowOffset=0; rowOffset < inPixels.size(); rowOffset+=rowSize){ + // for each pixel of that line + for(unsigned j=0;j