God is no longer drunk (rightly chose invs)
+ some refactoring
This commit is contained in:
parent
af8476c4ba
commit
6b24924b95
@ -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)
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "utils.h"
|
||||
#include "playerDef.h"
|
||||
#include "invaderDef.h"
|
||||
#include "invadersGrid.h"
|
||||
|
||||
typedef string configKey;
|
||||
|
||||
|
@ -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
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define GUARD_GOD_H
|
||||
|
||||
#include "utils.h"
|
||||
#include "invadersGrid.h"
|
||||
|
||||
enum class GodState{
|
||||
NONE,
|
||||
|
26
headers/invadersGrid.h
Normal file
26
headers/invadersGrid.h
Normal 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
|
@ -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
|
||||
|
@ -1,6 +1,6 @@
|
||||
560753531201765499
|
||||
10912949710723305374
|
||||
Thomas,2000
|
||||
Thomas,1000
|
||||
Thomas,300
|
||||
Thomas,0
|
||||
Thomas,0
|
||||
Thomas,0
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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){
|
||||
unsigned rdCol = grid.randomValid();
|
||||
// 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)
|
||||
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)
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}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,
|
||||
|
@ -18,30 +18,43 @@ void Game::manageGod() {
|
||||
break;
|
||||
}
|
||||
case GodState::WAIT: {
|
||||
if (god.counter == 100) {
|
||||
if (god.counter < 100) {
|
||||
++god.counter;
|
||||
break;
|
||||
}
|
||||
// init throw
|
||||
god.counter = 0;
|
||||
god.state = GodState::RETRIEVE1;
|
||||
god.thrownInvPosX = rand() % grid.size();
|
||||
god.thrownInvPosY = rand() % grid[0].size();
|
||||
|
||||
god.thrownInvType = grid[god.thrownInvPosX][god.thrownInvPosY];
|
||||
god.thrownInvPosX = grid.randomValid();
|
||||
god.thrownInvPosY = grid[god.thrownInvPosX].randomValid();
|
||||
god.thrownInvType = InvaderType::NONE;
|
||||
|
||||
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) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
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;
|
||||
|
||||
// compute the launch vector
|
||||
@ -60,7 +73,6 @@ void Game::manageGod() {
|
||||
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: {
|
||||
|
57
src/invaderGrids.cpp
Normal file
57
src/invaderGrids.cpp
Normal 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");
|
||||
}
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user