God is no longer drunk (rightly chose invs)

+ some refactoring
This commit is contained in:
Thomas 2022-01-06 15:07:42 +01:00
parent af8476c4ba
commit 6b24924b95
No known key found for this signature in database
GPG Key ID: E538821A6CDFDAD7
13 changed files with 146 additions and 81 deletions

View File

@ -5,6 +5,7 @@
#include "utils.h" #include "utils.h"
#include "playerDef.h" #include "playerDef.h"
#include "invaderDef.h" #include "invaderDef.h"
#include "invadersGrid.h"
typedef string configKey; typedef string configKey;

View File

@ -11,6 +11,7 @@
#include "projectiles.h" #include "projectiles.h"
#include "scoresManager.h" #include "scoresManager.h"
#include "god.h" #include "god.h"
#include "invadersGrid.h"
using namespace std; using namespace std;
@ -62,7 +63,6 @@ private:
// god things // god things
void awakeGod(); void awakeGod();
void manageGod(); void manageGod();
void _manageGod_retrieve(bool back);
public: public:
// in case someone wants to mess with the code, here's a minimal API, costs nothing to us // in case someone wants to mess with the code, here's a minimal API, costs nothing to us

View File

@ -2,6 +2,7 @@
#define GUARD_GOD_H #define GUARD_GOD_H
#include "utils.h" #include "utils.h"
#include "invadersGrid.h"
enum class GodState{ enum class GodState{
NONE, NONE,

26
headers/invadersGrid.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef GUARD_INVADERSGRID_H
#define GUARD_INVADERSGRID_H
#include<vector>
using namespace std;
enum class InvaderType {
TYPEA,
TYPEB,
TYPEC,
NONE,
};
class InvadersColumn : public vector<InvaderType>{
public:
// idk why CLion says this is not implemented, but it is
bool hasNoValid() const;
unsigned getOutterInvader() const;
unsigned randomValid() const;
};
class InvadersGrid : public vector<InvadersColumn>{
public:
unsigned randomValid() const;
};
#endif

View File

@ -22,19 +22,9 @@ enum class WinValue{
INVADERS, INVADERS,
}; };
enum class InvaderType {
TYPEA, typedef nsGraphics::Vec2D IndexPair;
TYPEB, typedef nsGraphics::Vec2D Position;
TYPEC,
NONE,
};
class InvadersColumn : public vector<InvaderType>{
public:
// idk why CLion says this is not implemented, but it is
size_t getOutterInvader() const;
};
typedef vector<InvadersColumn> InvadersGrid;
typedef nsGraphics::Vec2D Position; // TODO replace with Vec2D ?
typedef unsigned playerID; // 0 for player 1, 1 for player 2 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 // didn't want to use Position because of the semantic with x and y

View File

@ -1,6 +1,6 @@
560753531201765499 10912949710723305374
Thomas,2000
Thomas,1000 Thomas,1000
Thomas,300 Thomas,300
Thomas,0 Thomas,0
Thomas,0 Thomas,0
Thomas,0

View File

@ -96,7 +96,7 @@ void Game::displayGod() const {
// pos is now the position we need to draw our hand to // pos is now the position we need to draw our hand to
pm.drawGodRightHand(pos); pm.drawGodRightHand(pos);
// TODO remove "closed" arg // TODO remove "closed" arg
if(god.state==GodState::RETRIEVE2){ if(god.thrownInvType!=InvaderType::NONE){
pos+=Position(GOD_HAND_SIZE/2, GOD_HAND_SIZE/2); pos+=Position(GOD_HAND_SIZE/2, GOD_HAND_SIZE/2);
pos-=Position(confData.invadersSize/2, confData.invadersSize/2); pos-=Position(confData.invadersSize/2, confData.invadersSize/2);

View File

@ -14,12 +14,12 @@ Game::Game() : WININIT, pm(window) {
} }
void Game::updateColumns(){ void Game::updateColumns(){
while(grid.at(0).getOutterInvader()==grid.at(0).size()){ while(grid.at(0).hasNoValid()){
grid.erase(grid.begin()); grid.erase(grid.begin());
basePos+=confData.invadersSize+confData.invadersDistance; basePos+=confData.invadersSize+confData.invadersDistance;
} }
while(grid.at(grid.size()-1).getOutterInvader()==grid.at(grid.size()-1).size()){ while(grid.at(grid.size() - 1).hasNoValid()){
grid.erase(grid.end()-1); grid.erase(grid.end()-1);
} }
} }
@ -134,6 +134,7 @@ WinValue Game::playGame(){ // returns when game is finished
this_thread::sleep_until(startTime+maxFrameTime); this_thread::sleep_until(startTime+maxFrameTime);
} }
return WinValue::NOBODY; return WinValue::NOBODY;
} }

View File

@ -37,26 +37,12 @@ bool Game::manageInvaders(){
if(fireCooldown==0) { if(fireCooldown==0) {
fireCooldown = confData.invadersFireCooldown + rand() % 60; fireCooldown = confData.invadersFireCooldown + rand() % 60;
// compute the number of valid columns for firing, so rand() can't pick an empty column to fire unsigned rdCol = grid.randomValid();
unsigned counter=0;
for(InvadersColumn& col : grid){
if(!col.empty())++counter;
}
unsigned rd = (rand()%counter)+1;
counter = 0;
for(size_t i=0;i<grid.size();++i){
if(!grid[i].empty())++counter;
if(counter==rd){
// fire ! // fire !
missiles.push_back(basePos + Position( missiles.push_back(basePos + Position(
confData.invadersSize*i+confData.invadersDistance*(i+0.5), confData.invadersSize * rdCol + confData.invadersDistance * (rdCol + 0.5),
confData.invadersSize*(grid[i].size()-1)+confData.invadersDistance*(grid[i].size()-1) confData.invadersSize * (grid[rdCol].size() - 1) + confData.invadersDistance * (grid[rdCol].size() - 1)
)); ));
break;
}
}
}else --fireCooldown; }else --fireCooldown;
// moving // moving
@ -171,7 +157,7 @@ bool Game::checkTorpedosAndInvaders() {
size_t i=0; size_t i=0;
for(;i<grid.size();++i){ for(;i<grid.size();++i){
size_t alienIndex = grid[i].getOutterInvader(); unsigned alienIndex = grid[i].getOutterInvader();
// calculate top-left Position of invader // calculate top-left Position of invader
Position pos = basePos + Position( Position pos = basePos + Position(
confData.invadersSize*i+confData.invadersDistance*i, confData.invadersSize*i+confData.invadersDistance*i,

View File

@ -18,30 +18,43 @@ void Game::manageGod() {
break; break;
} }
case GodState::WAIT: { case GodState::WAIT: {
if (god.counter == 100) { if (god.counter < 100) {
++god.counter;
break;
}
// init throw // init throw
god.counter = 0; god.counter = 0;
god.state = GodState::RETRIEVE1; god.state = GodState::RETRIEVE1;
god.thrownInvPosX = rand() % grid.size(); god.thrownInvPosX = grid.randomValid();
god.thrownInvPosY = rand() % grid[0].size(); god.thrownInvPosY = grid[god.thrownInvPosX].randomValid();
god.thrownInvType = InvaderType::NONE;
god.thrownInvType = grid[god.thrownInvPosX][god.thrownInvPosY];
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)); god.thrownTransition.setY(basePos.getY() + INV_GET_POS(god.thrownInvPosY));
} else ++god.counter;
break; break;
} }
case GodState::RETRIEVE1: { case GodState::RETRIEVE1: {
if (god.counter == 100) { if (god.counter < 100) {
god.counter += 2;
break;
}
if (grid.size() > god.thrownInvPosY && grid[god.thrownInvPosX][god.thrownInvPosY] != InvaderType::NONE) {
god.thrownInvType = grid[god.thrownInvPosX][god.thrownInvPosY];
grid[god.thrownInvPosX][god.thrownInvPosY] = InvaderType::NONE; grid[god.thrownInvPosX][god.thrownInvPosY] = InvaderType::NONE;
updateColumns(); updateColumns();
}
god.state = GodState::RETRIEVE2; god.state = GodState::RETRIEVE2;
} else god.counter += 2;
break; break;
} }
case GodState::RETRIEVE2: { case GodState::RETRIEVE2: {
if (god.counter == 0) { if (god.counter > 0) {
god.counter -= 2;
break;
}
if(god.thrownInvType==InvaderType::NONE){
god.state = GodState::WAIT;
break;
}
god.state = GodState::THROW; god.state = GodState::THROW;
// compute the launch vector // compute the launch vector
@ -60,7 +73,6 @@ void Game::manageGod() {
god.thrownVector = god.thrownVector / (god.thrownVector.computeMagnitude() / 1000.0); 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 // let's normalize it, but keep it's length big so x and y and non-zero
// We will divide it in display // We will divide it in display
} else god.counter -= 2;
break; break;
} }
case GodState::THROW: { case GodState::THROW: {

57
src/invaderGrids.cpp Normal file
View File

@ -0,0 +1,57 @@
#include<invadersGrid.h>
#include<iostream>
bool InvadersColumn::hasNoValid() const {
return getOutterInvader()==size();
}
unsigned InvadersColumn::getOutterInvader() const {
unsigned i=size();
while(i>0){
--i;
if(at(i)!=InvaderType::NONE)return i;
}
return size();
}
// these are used to invoke rand() as less as possible
unsigned InvadersColumn::randomValid() const {
unsigned validTotal = 0;
for(InvaderType ite : *this){
if(ite!=InvaderType::NONE)++validTotal;
}
unsigned rd = rand() % validTotal;
unsigned validIndex = 0;
for(unsigned i=0;i<size();++i){
if(at(i)!=InvaderType::NONE){
if(validIndex==rd)return i;
++validIndex;
}
}
throw runtime_error("SHOULD NOT HAPPEN");
}
unsigned InvadersGrid::randomValid() const {
unsigned validTotal = 0;
for(const InvadersColumn& i : *this){
if(!i.hasNoValid())++validTotal;
}
unsigned rd = rand() % validTotal;
unsigned validIndex = 0;
for(unsigned i=0;i<size();++i){
if(!at(i).hasNoValid()){
if(validIndex==rd)return i;
++validIndex;
}
}
throw runtime_error("SHOULD NOT HAPPEN");
}

View File

@ -8,15 +8,6 @@ bool areLinesColliding(unsigned start1, unsigned end1, unsigned start2, unsigned
// if it returns true, lines are colliding. I like truth tables // if it returns true, lines are colliding. I like truth tables
} }
size_t InvadersColumn::getOutterInvader() const {
size_t i=size();
while(i>0){
--i;
if(at(i)!=InvaderType::NONE)return i;
}
return size();
}
void applyTransformation(Position& pos, unsigned sizeFrom, unsigned sizeTo){ void applyTransformation(Position& pos, unsigned sizeFrom, unsigned sizeTo){
pos += Position(sizeFrom/2, sizeFrom/2); pos += Position(sizeFrom/2, sizeFrom/2);
pos -= Position(sizeTo/2, sizeTo/2); pos -= Position(sizeTo/2, sizeTo/2);