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

@ -9,7 +9,7 @@ file(GLOB_RECURSE HEADERS headers/*)
add_executable(Space ${LIB_HEADERS} ${HEADERS} ${SRC})
target_link_directories(Space PUBLIC .)
target_link_directories(Space PUBLIC .)
target_include_directories(Space PUBLIC headers)
target_include_directories(Space PUBLIC lib_headers)

View File

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

View File

@ -11,6 +11,7 @@
#include "projectiles.h"
#include "scoresManager.h"
#include "god.h"
#include "invadersGrid.h"
using namespace std;
@ -62,7 +63,6 @@ private:
// god things
void awakeGod();
void manageGod();
void _manageGod_retrieve(bool back);
public:
// 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
#include "utils.h"
#include "invadersGrid.h"
enum class GodState{
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,
};
enum class InvaderType {
TYPEA,
TYPEB,
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 nsGraphics::Vec2D IndexPair;
typedef nsGraphics::Vec2D Position;
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

View File

@ -1,6 +1,6 @@
560753531201765499
10912949710723305374
Thomas,2000
Thomas,1000
Thomas,300
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
pm.drawGodRightHand(pos);
// 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(confData.invadersSize/2, confData.invadersSize/2);

View File

@ -14,12 +14,12 @@ Game::Game() : WININIT, pm(window) {
}
void Game::updateColumns(){
while(grid.at(0).getOutterInvader()==grid.at(0).size()){
while(grid.at(0).hasNoValid()){
grid.erase(grid.begin());
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);
}
}
@ -134,6 +134,7 @@ WinValue Game::playGame(){ // returns when game is finished
this_thread::sleep_until(startTime+maxFrameTime);
}
return WinValue::NOBODY;
}

View File

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

View File

@ -18,49 +18,61 @@ void Game::manageGod() {
break;
}
case GodState::WAIT: {
if (god.counter == 100) {
// init throw
god.counter = 0;
god.state = GodState::RETRIEVE1;
god.thrownInvPosX = rand() % grid.size();
god.thrownInvPosY = rand() % grid[0].size();
if (god.counter < 100) {
++god.counter;
break;
}
// init throw
god.counter = 0;
god.state = GodState::RETRIEVE1;
god.thrownInvPosX = grid.randomValid();
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.setY(basePos.getY() + INV_GET_POS(god.thrownInvPosY));
} else ++god.counter;
god.thrownTransition.setX(pm.getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE);
god.thrownTransition.setY(basePos.getY() + INV_GET_POS(god.thrownInvPosY));
break;
}
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;
updateColumns();
god.state = GodState::RETRIEVE2;
} else god.counter += 2;
}
god.state = GodState::RETRIEVE2;
break;
}
case GodState::RETRIEVE2: {
if (god.counter == 0) {
god.state = GodState::THROW;
if (god.counter > 0) {
god.counter -= 2;
break;
}
if(god.thrownInvType==InvaderType::NONE){
god.state = GodState::WAIT;
break;
}
god.state = GodState::THROW;
// compute the launch vector
// compute the launch vector
Position invaderMiddlePos(pm.getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE / 2,
GOD_HAND_SIZE / 2);
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.getScreenHeight() - PLAYER_HEIGHT / 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.getScreenHeight() - 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;
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
break;
}
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
}
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){
pos += Position(sizeFrom/2, sizeFrom/2);
pos -= Position(sizeTo/2, sizeTo/2);