diff --git a/QUESTIONS.md b/QUESTIONS.md index 7f847e1..324831f 100644 --- a/QUESTIONS.md +++ b/QUESTIONS.md @@ -6,13 +6,11 @@ Questions que je (Thomas Rubini) voudrais poser - Est-ce mon implémentation du multithreading est bonne ? - Est-on obligé d'utiliser size_t quand on sait que la taille du vecteur ne dépassera jamais concrètement la taille d'un int (cas précis : taille de 100 maximum, est-on obligé d'utiliser size_t de 8 bytes ?) -* +* Non - Que pensez-vous de la sémantique de déplacement, plutot que la référence constante ? * on peut utiliser la sémantique de déplacement au besoin - Est-ce qu'on doit forcément utiliser const pour des valeurs primitives (int, float...) qu'on ne touche pas en paramètres de fonction ? * c'est mieux -- Est-ce que vouloir faire des structures optimisées (pas de redondance de mémoire) est une bonne chose, ou pas important ? -* - Pour import MinGL, il vaut mieux utiliser "" ou <> ? * <> tout le temps, "" à éviter - copier ou ref constante pour Position (Vec2D) ? diff --git a/assets/hand_closed.si2 b/assets/hand_closed.si2 index 275c3d3..f6d2d30 100644 Binary files a/assets/hand_closed.si2 and b/assets/hand_closed.si2 differ diff --git a/assets/hand_open.si2 b/assets/hand_open.si2 index 275c3d3..f6d2d30 100644 Binary files a/assets/hand_open.si2 and b/assets/hand_open.si2 differ diff --git a/config.yml b/config.yml index 52a856c..71971f9 100644 --- a/config.yml +++ b/config.yml @@ -20,7 +20,7 @@ players: # Enemies config invaders: fireCooldown: 0 - size: 50 + size: 40 speed: 10 distance: 10 # distance in pixels between invaders @@ -47,6 +47,6 @@ projectiles: width: 10 grid: - - " AAAAAAAA" - - "B BBBBBBBB" - - " CCCCCCCC" + - "AAAAAAAA" +# - "B BBBBBBBB" +# - " CCCCCCCC" diff --git a/headers/game.h b/headers/game.h index 6df452c..f26279d 100644 --- a/headers/game.h +++ b/headers/game.h @@ -38,6 +38,7 @@ private: // basic methods void updateColumns(); void handleScoreSaving(); + Position invIndexToPos(unsigned x, unsigned y) const; // drawing methods void display(unsigned fps) const; diff --git a/headers/god.h b/headers/god.h index 8ff3539..d4e0a85 100644 --- a/headers/god.h +++ b/headers/god.h @@ -27,7 +27,10 @@ public: GodState state; unsigned counter; - Position throwedInvPos; + + // we do not use a Position because it is used for pixel X and Y + unsigned throwedInvPosX; + unsigned throwedInvPosY; InvaderType thrownInvType; Position thrownVector; Position thrownTransition; diff --git a/headers/pixelManager.h b/headers/pixelManager.h index c6c17f7..3c6cc4e 100644 --- a/headers/pixelManager.h +++ b/headers/pixelManager.h @@ -14,6 +14,8 @@ using namespace std; +#define MIRROR(SP) mirrorData((SP).getPixelData(), (SP).getRowSize()), (SP).getRowSize() + class PixelManager{ public: MinGL& window; @@ -22,10 +24,16 @@ public: * 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) */ - nsGui::Sprite background = nsGui::Sprite("./assets/bg.si2"); - nsGui::Sprite handOpen = nsGui::Sprite("./assets/hand_open.si2"); - nsGui::Sprite handClosed = nsGui::Sprite("./assets/hand_closed.si2"); + nsGui::Sprite background{"assets/bg.si2"}; + nsGui::Sprite rightHandOpen{"assets/hand_open.si2"}; + nsGui::Sprite rightHandClosed{"assets/hand_closed.si2"}; + + nsGui::Sprite leftHandOpen{MIRROR(rightHandOpen)}; + nsGui::Sprite leftHandClosed{MIRROR(rightHandClosed)}; explicit PixelManager(MinGL&); @@ -36,7 +44,7 @@ public: void drawPlayer(unsigned x, unsigned width, const nsGraphics::RGBAcolor& color) const; void drawMissile(const Position& baseVector, unsigned width, const nsGraphics::RGBAcolor& color) const; void drawTorpedo(const Position& baseVector, unsigned width, const nsGraphics::RGBAcolor& color) const; - void drawSprite(nsGui::Sprite& sprite, const Position& pos) const; + void drawSprite(const nsGui::Sprite& sprite, const Position& pos) const; void drawBackground() const; void drawFPS(unsigned fps) const; @@ -53,8 +61,13 @@ public: // y will be negative sometimes, so not unsigned void displayGodBench(int y) const; - void displayGodRightHand(const Position& pos) const; - void displayGodLeftHand(const Position& pos) const; + void displayGodRightHand(const Position& pos, bool closed=false) const; + void displayGodLeftHand(const Position& pos, bool closed=false) const; + +private: + // Explanation for choices : + // non reference output : I don't think we have another choice than a std::move() here + vector mirrorData(const vector& inPixels, unsigned rowSize); }; diff --git a/headers/utils.h b/headers/utils.h index 002b372..875cc16 100644 --- a/headers/utils.h +++ b/headers/utils.h @@ -8,8 +8,8 @@ #define PLAYER_HEIGHT 100 #define PROJ_LENGTH_FACTOR 2 // TODO utiliser ca de partout -// ou alors faire une method dans Game ? -#define INV_POS(i) confData.invadersSize*(i)+confData.invadersDistance*(i) + +#define INV_GET_POS(i) confData.invadersSize*(i)+confData.invadersDistance*(i) using namespace std; diff --git a/src/game/display.cpp b/src/game/display.cpp index 31300e2..342cf4d 100644 --- a/src/game/display.cpp +++ b/src/game/display.cpp @@ -57,59 +57,50 @@ void applyBezier(Position& pos, const Position& point, const double percent) { pos += (point-pos)*percent; } +#include void Game::displayGod() const { switch (god.state) { case GodState::NONE: return; case GodState::AWAKE: { - pm.displayGodBench(god.counter - GOD_BENCH_SIZE); + unsigned dividedCounter = god.counter/1; + pm.displayGodBench(dividedCounter - GOD_BENCH_SIZE); - Position leftHand = Position(pm.getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE, god.counter - GOD_BENCH_SIZE); - Position rightHand = Position(GOD_HAND_DISTANCE, god.counter - GOD_BENCH_SIZE); + Position leftHand(pm.getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE, dividedCounter-GOD_BENCH_SIZE); + Position rightHand(GOD_HAND_DISTANCE, dividedCounter-GOD_BENCH_SIZE); pm.displayGodLeftHand(leftHand); pm.displayGodRightHand(rightHand); + break; } case GodState::WAIT:{ pm.displayGodBench(0); - Position leftHand(GOD_HAND_DISTANCE, 0); - Position rightHand(pm.getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE, 0); + Position leftHand(pm.getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE, 0); + Position rightHand(GOD_HAND_DISTANCE, 0); pm.displayGodLeftHand(leftHand); pm.displayGodRightHand(rightHand); break; } - case GodState::RETRIEVE1:{ + case GodState::RETRIEVE1: + case GodState::RETRIEVE2:{ // Bezier curve // counter goes [0-100] + pm.displayGodBench(0); - Position startPos(GOD_HAND_DISTANCE, 0); - Position endPos = basePos+Position(INV_POS(god.throwedInvPos.getX()), INV_POS(god.throwedInvPos.getY())); + Position pos(pm.getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE, 0); + Position endPos = invIndexToPos(god.throwedInvPosX, god.throwedInvPosY); - applyBezier(startPos, god.thrownTransition, god.counter/100); - applyBezier(startPos, endPos, god.counter/100); + applyBezier(pos, god.thrownTransition, god.counter / 100.0); + applyBezier(pos, endPos, god.counter / 100.0); + cout << pos << endl; - // startPos is now the position we need to draw our hand to - pm.displayGodRightHand(startPos); + // pos is now the position we need to draw our hand to pm.displayGodLeftHand(Position(GOD_HAND_DISTANCE, 0)); - - break; - } - case GodState::RETRIEVE2:{ - // similar with RETRIEVE1 - Position pos(GOD_HAND_DISTANCE, 0); - Position endPos = basePos+Position(INV_POS(god.throwedInvPos.getX()), INV_POS(god.throwedInvPos.getY())); - - applyBezier(pos, god.thrownTransition, 1 - (god.counter / 100)); - applyBezier(pos, endPos, 1 - (god.counter / 100)); - pm.displayGodRightHand(pos); - pm.displayGodLeftHand(Position(GOD_HAND_DISTANCE, 0)); - - // TODO maybe a little transition to pos to better reflect the invader's position ? - -// but now, you come with me you invader ! - displayInvader(pos, god.thrownInvType); - break; + if(god.state==GodState::RETRIEVE2){ + // TODO maybe a little transition to pos to better reflect the invader's position ? + displayInvader(pos, god.thrownInvType); + } } case GodState::THROW:{ break; diff --git a/src/gameBasics.cpp b/src/game/gameBasics.cpp similarity index 90% rename from src/gameBasics.cpp rename to src/game/gameBasics.cpp index c5a5b14..d12a74f 100644 --- a/src/gameBasics.cpp +++ b/src/game/gameBasics.cpp @@ -68,7 +68,8 @@ void Game::managedGames() { WinValue Game::playGame(){ // returns when game is finished // INIT // we assume the game has been played before, and so we need to clean used members - grid = confData.grid; // will copy the vector + grid = confData.grid; // will copy the grid + updateColumns(); // Would have liked to to that in the "config grid", but.. I'm lazy if(playMode==PlayMode::SINGLE){ @@ -97,12 +98,13 @@ WinValue Game::playGame(){ // returns when game is finished if(manageInvaders()) { // if they went down if (invadersTouchPlayer())return WinValue::INVADERS; // TODO abstract this ? - if (basePos.getY() > 200 /*lambda value*/ && god.state==GodState::NONE) { - cout << "hey" << endl; + if (basePos.getY() > 100 /*lambda value*/ && god.state==GodState::NONE) { awakeGod(); } } + manageGod(); + moveMissiles(); remCollidingProjectiles(); moveTorpedos(); @@ -131,3 +133,7 @@ WinValue Game::playGame(){ // returns when game is finished } return WinValue::NOBODY; } + +Position Game::invIndexToPos(unsigned x, unsigned y) const { + return basePos+Position(INV_GET_POS(x), INV_GET_POS(y)); +} diff --git a/src/gameManagers.cpp b/src/game/gameManagers.cpp similarity index 100% rename from src/gameManagers.cpp rename to src/game/gameManagers.cpp diff --git a/src/game/godThings.cpp b/src/game/godThings.cpp new file mode 100644 index 0000000..b93ffad --- /dev/null +++ b/src/game/godThings.cpp @@ -0,0 +1,55 @@ +#include "game.h" + +void Game::awakeGod() { + god.counter = 0; + god.state = GodState::AWAKE; +} + +void Game::manageGod(){ + switch(god.state){ + case GodState::NONE:{ + break; + } + case GodState::AWAKE:{ + if(god.counter==GOD_BENCH_SIZE*1){ + god.counter = 0; + god.state = GodState::WAIT; + }else ++god.counter; + break; + } + case GodState::WAIT: { + if (god.counter == 50) { + cout << "init throw" << endl; + // init throw + god.counter = 0; + god.state = GodState::RETRIEVE1; + god.throwedInvPosX = rand() % grid.size(); + god.throwedInvPosY = rand() % grid[0].size(); + + god.thrownInvType = grid[god.throwedInvPosX][god.throwedInvPosY]; + + god.thrownTransition.setX(pm.getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE); + god.thrownTransition.setY(basePos.getY()+INV_GET_POS(god.throwedInvPosY)); + } else ++god.counter; + break; + } + case GodState::RETRIEVE1:{ + if(god.counter==100){ + grid[god.throwedInvPosX][god.throwedInvPosY] = InvaderType::NONE; + updateColumns(); + god.state = GodState::RETRIEVE2; + }else ++god.counter; + break; + } + case GodState::RETRIEVE2:{ + if(god.counter==0){ + god.state = GodState::THROW; + }else --god.counter; + break; + } + case GodState::THROW:{ + cout << "FROM NOW ON ANYTHING CAN HAPPEN" << endl; + break; + } + } +} diff --git a/src/godThings.cpp b/src/godThings.cpp deleted file mode 100644 index b2cc587..0000000 --- a/src/godThings.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "game.h" - -void Game::awakeGod() { - god.counter = 0; - god.state = GodState::AWAKE; -} - -void Game::manageGod(){ - switch(god.state){ - case GodState::NONE:{ - return; - } - case GodState::AWAKE:{ - if(god.counter==GOD_BENCH_SIZE){ - god.counter = 0; - god.state = GodState::WAIT; - }else ++god.counter; - return; - } - case GodState::WAIT: { - if (god.counter == 1000) { - // init throw - god.counter = 0; - god.state = GodState::RETRIEVE1; - unsigned rx = rand() % grid.size(); - unsigned ry = rand() % grid[0].size(); - god.throwedInvPos.setX(rx); - god.throwedInvPos.setY(ry); - - god.thrownInvType = grid[rx][ry]; - - god.thrownTransition.setX(GOD_HAND_SIZE); - god.thrownTransition.setY(rx); - } else ++god.counter; - return; - } - } -} diff --git a/src/pixelManager.cpp b/src/pixelManager.cpp index 0a4fdbb..07ceb11 100644 --- a/src/pixelManager.cpp +++ b/src/pixelManager.cpp @@ -62,13 +62,9 @@ void PixelManager::drawTorpedo(const Position& baseVector, unsigned width, const window << Rectangle(baseVector, baseVector + Position(width, width * PROJ_LENGTH_FACTOR), color); } -void PixelManager::drawSprite(nsGui::Sprite& sprite, const Position& pos) const { - /* - * no idea why the const qualifier is authorized since we modify object data with setPosition(), - * but since this modification isn't even "real" (see pixelManager.h), it's actually nice, I guess - */ - sprite.setPosition(pos); - +void PixelManager::drawSprite(const nsGui::Sprite& sprite, const Position& pos) const { + // see pixelManager.h for the explanation of this hack + const_cast(sprite).setPosition(pos); sprite.draw(window); } @@ -101,17 +97,38 @@ void PixelManager::endFrame() const { } void PixelManager::displayGodBench(int y) const { - window << Rectangle(Position(0, y), Position(0, y+GOD_BENCH_SIZE), nsGraphics::KBlack); + window << Rectangle(Position(0, y), Position(getScreenWidth(), y+GOD_BENCH_SIZE), nsGraphics::KGray); } -void PixelManager::displayGodRightHand(const Position& pos) const { - +void PixelManager::displayGodRightHand(const Position& pos, bool closed) const { + if(closed){ + drawSprite(rightHandClosed, pos); + }else{ + drawSprite(rightHandOpen, pos); + } } -void PixelManager::displayGodLeftHand(const Position& pos) const { - +void PixelManager::displayGodLeftHand(const Position& pos, bool closed) const { + if(closed){ + drawSprite(leftHandClosed, pos); + }else{ + drawSprite(leftHandOpen, pos); + } } void PixelManager::drawFPS(unsigned fps) const { window << nsGui::Text(Position(getScreenWidth()-100, 10), "FPS : "+ to_string(fps), nsGraphics::KWhite); } + +vector +PixelManager::mirrorData(const vector& inPixels, unsigned rowSize) { + vector outPixels; + outPixels.reserve(inPixels.size()); + + for(unsigned i=0;i