From 1af32bafd87bed905f9cca81eb53a4fe58a746e1 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 6 Jan 2022 09:58:06 +0100 Subject: [PATCH] God beta (quite cool) --- TODO_LUCAS.txt | 2 +- config.yml | 16 ++++--- headers/god.h | 6 ++- headers/pixelManager.h | 6 +-- headers/utils.h | 5 ++- src/game/display.cpp | 50 +++++++++++++++------ src/game/gameBasics.cpp | 3 +- src/game/godThings.cpp | 98 ++++++++++++++++++++++++++++++++--------- src/pixelManager.cpp | 6 +-- src/utils.cpp | 5 +++ 10 files changed, 143 insertions(+), 54 deletions(-) diff --git a/TODO_LUCAS.txt b/TODO_LUCAS.txt index c9ffcca..231d360 100644 --- a/TODO_LUCAS.txt +++ b/TODO_LUCAS.txt @@ -1,4 +1,4 @@ -nom du joueur ecran 100*100 sans efacé le reste +nom du joueur ecran 100*100 sans effacer le reste le joueur est gros basevector a change en variable x projectile style fusée diff --git a/config.yml b/config.yml index 71971f9..2b78f92 100644 --- a/config.yml +++ b/config.yml @@ -19,9 +19,9 @@ players: # Enemies config invaders: - fireCooldown: 0 - size: 40 - speed: 10 + fireCooldown: 20 + size: 25 + speed: 2 distance: 10 # distance in pixels between invaders typeA: @@ -39,14 +39,16 @@ invaders: projectiles: missiles: color: yellow - speed: 100 + speed: 10 width: 10 torpedos: color: green speed: 10 width: 10 +# Grid definition +# You can add more rows, make rows longer and add spaces grid: - - "AAAAAAAA" -# - "B BBBBBBBB" -# - " CCCCCCCC" + - "AAAAAAAAAAAA" + - "BBBBBBBBBBBB" + - "CCCCCCCCCCCC" diff --git a/headers/god.h b/headers/god.h index d4e0a85..7661cd2 100644 --- a/headers/god.h +++ b/headers/god.h @@ -29,12 +29,14 @@ public: // we do not use a Position because it is used for pixel X and Y - unsigned throwedInvPosX; - unsigned throwedInvPosY; + unsigned thrownInvPosX; + unsigned thrownInvPosY; InvaderType thrownInvType; Position thrownVector; Position thrownTransition; + Position getLeftHandPos(unsigned screenWidth) const; + }; #endif diff --git a/headers/pixelManager.h b/headers/pixelManager.h index 3c6cc4e..1591b53 100644 --- a/headers/pixelManager.h +++ b/headers/pixelManager.h @@ -59,10 +59,10 @@ public: void askPlayerNameMenu(playerID pID, string& name) const; // y will be negative sometimes, so not unsigned - void displayGodBench(int y) const; + void drawGodBench(int y) const; - void displayGodRightHand(const Position& pos, bool closed=false) const; - void displayGodLeftHand(const Position& pos, bool closed=false) const; + void drawGodRightHand(const Position& pos, bool closed= false) const; + void drawGodLeftHand(const Position& pos, bool closed= false) const; private: // Explanation for choices : diff --git a/headers/utils.h b/headers/utils.h index 875cc16..e74cf97 100644 --- a/headers/utils.h +++ b/headers/utils.h @@ -34,10 +34,13 @@ public: size_t getOutterInvader() const; }; typedef vector InvadersGrid; -typedef nsGraphics::Vec2D Position; // in case we need to ad dmore methods, we defined our own type +typedef nsGraphics::Vec2D Position; // TODO replace with Vec2D ? typedef unsigned playerID; // 0 for player 1, 1 for player 2 // didn't want to use Position because of the semantic with x and y bool areLinesColliding(unsigned start1, unsigned end1, unsigned start2, unsigned end2); +// change draw position for a specified size (keeps the same center) +void applyTransformation(Position& pos, unsigned sizeFrom, unsigned sizeTo); + #endif \ No newline at end of file diff --git a/src/game/display.cpp b/src/game/display.cpp index 342cf4d..e94b53f 100644 --- a/src/game/display.cpp +++ b/src/game/display.cpp @@ -64,45 +64,67 @@ void Game::displayGod() const { return; case GodState::AWAKE: { unsigned dividedCounter = god.counter/1; - pm.displayGodBench(dividedCounter - GOD_BENCH_SIZE); + pm.drawGodBench(dividedCounter - 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); + pm.drawGodLeftHand(leftHand); + pm.drawGodRightHand(rightHand); break; } case GodState::WAIT:{ - pm.displayGodBench(0); + pm.drawGodBench(0); - Position leftHand(pm.getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE, 0); - Position rightHand(GOD_HAND_DISTANCE, 0); - pm.displayGodLeftHand(leftHand); - pm.displayGodRightHand(rightHand); + Position leftHand(GOD_HAND_DISTANCE, 0); + Position rightHand(pm.getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE, 0); + pm.drawGodLeftHand(leftHand); + pm.drawGodRightHand(rightHand); break; } case GodState::RETRIEVE1: case GodState::RETRIEVE2:{ // Bezier curve // counter goes [0-100] - pm.displayGodBench(0); + pm.drawGodBench(0); + pm.drawGodLeftHand(Position(GOD_HAND_DISTANCE, 0)); Position pos(pm.getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE, 0); - Position endPos = invIndexToPos(god.throwedInvPosX, god.throwedInvPosY); + Position endPos = invIndexToPos(god.thrownInvPosX, god.thrownInvPosY); applyBezier(pos, god.thrownTransition, god.counter / 100.0); applyBezier(pos, endPos, god.counter / 100.0); - cout << pos << endl; // pos is now the position we need to draw our hand to - pm.displayGodLeftHand(Position(GOD_HAND_DISTANCE, 0)); - pm.displayGodRightHand(pos); + pm.drawGodRightHand(pos); + // TODO remove "closed" arg if(god.state==GodState::RETRIEVE2){ - // TODO maybe a little transition to pos to better reflect the invader's position ? + pos+=Position(GOD_HAND_SIZE/2, GOD_HAND_SIZE/2); + pos-=Position(confData.invadersSize/2, confData.invadersSize/2); displayInvader(pos, god.thrownInvType); } + break; } case GodState::THROW:{ + pm.drawGodBench(0); + pm.drawGodLeftHand(Position(GOD_HAND_DISTANCE, 0)); + + // compute start position (not sure if we should store it or compute it each time ?) + Position handPos = god.getLeftHandPos(pm.getScreenWidth()); + + Position invaderPos = handPos; + applyTransformation(invaderPos, GOD_HAND_SIZE, confData.invadersSize); + Position a = god.thrownVector * (god.counter / 100.0); + invaderPos = invaderPos + a; + + displayInvader(invaderPos, god.thrownInvType); + if(god.counter>60){ + // handling hand retraction + unsigned handCounter; + if(god.counter>30)handCounter = 30-god.counter; + else handCounter = god.counter; + handPos = handPos + god.thrownVector * (handCounter / 100.0); + pm.drawGodRightHand(handPos); + } break; } } diff --git a/src/game/gameBasics.cpp b/src/game/gameBasics.cpp index d12a74f..c8a2d86 100644 --- a/src/game/gameBasics.cpp +++ b/src/game/gameBasics.cpp @@ -84,12 +84,13 @@ WinValue Game::playGame(){ // returns when game is finished basePos = Position(200, 0); // GAMELOOP -#define MAX_FPS 60 + const int MAX_FPS = 60; chrono::milliseconds fpsTime; unsigned tmpFps = 0; unsigned fps = 0; while(window.isOpen()){ + chrono::time_point startTime = chrono::high_resolution_clock::now(); pm.startFrame(); diff --git a/src/game/godThings.cpp b/src/game/godThings.cpp index b93ffad..c587d95 100644 --- a/src/game/godThings.cpp +++ b/src/game/godThings.cpp @@ -5,51 +5,105 @@ void Game::awakeGod() { god.state = GodState::AWAKE; } -void Game::manageGod(){ - switch(god.state){ - case GodState::NONE:{ +void Game::manageGod() { + switch (god.state) { + case GodState::NONE: { break; } - case GodState::AWAKE:{ - if(god.counter==GOD_BENCH_SIZE*1){ + case GodState::AWAKE: { + if (god.counter == GOD_BENCH_SIZE) { god.counter = 0; god.state = GodState::WAIT; - }else ++god.counter; + } 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.thrownInvPosX = rand() % grid.size(); + god.thrownInvPosY = rand() % grid[0].size(); - god.thrownInvType = grid[god.throwedInvPosX][god.throwedInvPosY]; + god.thrownInvType = grid[god.thrownInvPosX][god.thrownInvPosY]; - god.thrownTransition.setX(pm.getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE); - god.thrownTransition.setY(basePos.getY()+INV_GET_POS(god.throwedInvPosY)); + god.thrownTransition.setX(pm.getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE); + god.thrownTransition.setY(basePos.getY() + INV_GET_POS(god.thrownInvPosY)); } else ++god.counter; break; } - case GodState::RETRIEVE1:{ - if(god.counter==100){ - grid[god.throwedInvPosX][god.throwedInvPosY] = InvaderType::NONE; + case GodState::RETRIEVE1: { + if (god.counter == 100) { + grid[god.thrownInvPosX][god.thrownInvPosY] = InvaderType::NONE; updateColumns(); god.state = GodState::RETRIEVE2; - }else ++god.counter; + } else god.counter += 2; break; } - case GodState::RETRIEVE2:{ - if(god.counter==0){ + case GodState::RETRIEVE2: { + if (god.counter == 0) { god.state = GodState::THROW; - }else --god.counter; + god.counter = 0; + + // compute the launch vector + + Position invaderMiddlePos(pm.getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE / 2, + GOD_HAND_SIZE / 2); + + playerID target; + if (players.size() == 1)target = 0; // don't want to use random if not needed + else target = rand() % players.size(); + Position playerMiddlePos(players[target].x + confData.playersWidth / 2, + pm.getScreenWidth() - PLAYER_HEIGHT / 2); + + god.thrownVector = playerMiddlePos - invaderMiddlePos; + god.thrownVector = god.thrownVector / (god.thrownVector.computeMagnitude() / 1000.0); + // let's normalize it, but keep it's length big so x and y and non-zero + // We will divide it in display + } else god.counter -= 2; break; } - case GodState::THROW:{ - cout << "FROM NOW ON ANYTHING CAN HAPPEN" << endl; - break; + case GodState::THROW: { + ++god.counter; + + + Position invaderPos = god.getLeftHandPos(pm.getScreenWidth()); + applyTransformation(invaderPos, GOD_HAND_SIZE, confData.invadersSize); + Position a = god.thrownVector * (god.counter / 100.0); + invaderPos = invaderPos + a; + + bool touched = false; + + // check if OOB (Out Of Bounds) + if (invaderPos.getY() >= pm.getScreenWidth() && + (invaderPos.getX() < 0 || invaderPos.getX() + confData.invadersSize >= pm.getScreenWidth())) { + touched = true; + // check player collision + } else if (invaderPos.getY() + confData.invadersSize >= pm.getScreenWidth() - PLAYER_HEIGHT) { + for (Player &p: players) { + if (areLinesColliding( + p.x, p.x + confData.playersWidth, + invaderPos.getX(), invaderPos.getX() + confData.invadersSize + )) { + // TODO manage player death + touched = true; + // do not break, the other player also deserves to be hit + } + } + } + if (touched){ + god.state = GodState::WAIT; + god.counter = 0; + } + /* + * we do not need to reset other members, they'll be treated as non-initialized + * When we cycle back between states + */ } + break; } } + +Position God::getLeftHandPos(unsigned screenWidth) const { + return Position(screenWidth - GOD_HAND_DISTANCE - GOD_HAND_SIZE, GOD_HAND_SIZE); +} \ No newline at end of file diff --git a/src/pixelManager.cpp b/src/pixelManager.cpp index 07ceb11..1f102ba 100644 --- a/src/pixelManager.cpp +++ b/src/pixelManager.cpp @@ -96,11 +96,11 @@ void PixelManager::endFrame() const { window.finishFrame(); } -void PixelManager::displayGodBench(int y) const { +void PixelManager::drawGodBench(int y) const { window << Rectangle(Position(0, y), Position(getScreenWidth(), y+GOD_BENCH_SIZE), nsGraphics::KGray); } -void PixelManager::displayGodRightHand(const Position& pos, bool closed) const { +void PixelManager::drawGodRightHand(const Position& pos, bool closed) const { if(closed){ drawSprite(rightHandClosed, pos); }else{ @@ -108,7 +108,7 @@ void PixelManager::displayGodRightHand(const Position& pos, bool closed) const { } } -void PixelManager::displayGodLeftHand(const Position& pos, bool closed) const { +void PixelManager::drawGodLeftHand(const Position& pos, bool closed) const { if(closed){ drawSprite(leftHandClosed, pos); }else{ diff --git a/src/utils.cpp b/src/utils.cpp index 54382da..e8666b6 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -16,3 +16,8 @@ size_t InvadersColumn::getOutterInvader() const { } return size(); } + +void applyTransformation(Position& pos, unsigned sizeFrom, unsigned sizeTo){ + pos += Position(sizeFrom/2, sizeFrom/2); + pos -= Position(sizeTo/2, sizeTo/2); +} \ No newline at end of file