SuperSpaceInvaderTurboApoca.../src/game/gameManagers.cpp
2022-01-06 15:07:42 +01:00

198 lines
5.8 KiB
C++

#include "game.h"
#define ISPRESSED(ID, X) window.isPressed({confData.playerDefs[ID].keys.X, false})
void Game::manageOnePlayer(playerID pID){
if (ISPRESSED(pID, left)){
if(players[pID].x < confData.playersSpeed) players[pID].x = 0;
else players[pID].x -= confData.playersSpeed;
}
if (ISPRESSED(pID, right)){
if(players[pID].x + confData.playersWidth + confData.playersSpeed >= pm.getScreenWidth()) players[pID].x = pm.getScreenWidth() - confData.playersWidth - 1;
else players[pID].x += confData.playersSpeed;
}
if(players[pID].fireCooldown==0) {
if (ISPRESSED(pID, shoot)) {
torpedos.emplace_back(players[pID].x + confData.playersWidth / 2, pm.getScreenHeight() - PLAYER_HEIGHT, pID);
players[pID].fireCooldown = confData.playersFireCooldown;
}
}else --players[pID].fireCooldown;
}
/** Makes the players play once
*/
void Game::managePlayers(){
manageOnePlayer(0);
if(playMode==PlayMode::TWO_LOCAL)manageOnePlayer(1);
else if(playMode==PlayMode::TWO_TCPIP){
// TODO TCPIP
}
}
/** Makes the invaders play once, and check lower bounds
*
* @return true if the invaders went down from one line (and we should check lower boundary), else false
*/
bool Game::manageInvaders(){
// shoot
if(fireCooldown==0) {
fireCooldown = confData.invadersFireCooldown + rand() % 60;
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
if(direction){ // go to the right
int end = basePos.getX(); // start Position
end+= grid.size() * confData.invadersSize; // add the invaders
end+= (grid.size()-1) * confData.invadersDistance; // add the invadersDistance between invaders
// you got the end position of the invader crowd !
if(end + confData.invadersSpeed < pm.getScreenWidth()){
basePos.setX(basePos.getX() + confData.invadersSpeed);
}else{
basePos.setY(basePos.getY() + confData.invadersSize + confData.invadersDistance);
direction = !direction;
return true;
}
}else{
if(basePos.getX() >= confData.invadersSpeed){
basePos.setX(basePos.getX() - confData.invadersSpeed);
}else{
basePos.setY(basePos.getY() + confData.invadersSize + confData.invadersDistance);
direction = !direction;
return true;
}
}
return false;
}
/** makes projectiles move, and manage collisions between them and everything
*
* @return 1 if the invaders are all dead, 2 if the player is dead, else 0
*/
void Game::remCollidingProjectiles(){
auto miss = missiles.begin();
auto tor = torpedos.begin();
while(miss != missiles.end()){
bool wasColliding = false;
while(tor != torpedos.end()){
// missiles can't be right under torpedos, so that must means they are colliding in Y
if(miss->getY() + confData.missilesLength < tor->getY()){
}
if(areLinesColliding( // now check if they collide in X
miss->getX(), miss->getX() + confData.missilesWidth,
tor->getX(), tor->getX() + confData.torpedosWidth)){
missiles.erase(miss);
torpedos.erase(tor);
wasColliding = true;
break;
}
++tor;
}
/* if it was colling, it was removed and his Position is now replaced by the next.
* else, go to the next
*/
if(!wasColliding)++miss;
}
}
void Game::moveMissiles() {
auto miss = missiles.begin();
while (miss != missiles.end()) {
if (miss->getY() >= pm.getScreenHeight())missiles.erase(miss);
else {
miss->setY(miss->getY()+confData.missilesSpeed);
++miss;
}
}
}
void Game::moveTorpedos() {
auto tor = torpedos.begin();
while (tor != torpedos.end()) {
if (tor->getY()+confData.torpedosLength <= 0)torpedos.erase(tor);
else{
tor->setY(tor->getY()-confData.torpedosSpeed);
++tor;
}
}
}
bool Game::checkMissilesAndPlayers() {
auto miss_ite = missiles.begin();
while(miss_ite!=missiles.end()){
bool wasColliding = false;
if(miss_ite->getY()>=pm.getScreenHeight()-PLAYER_HEIGHT){ // check collision on Y
// now check collision on X (with both players)
for(Player& p : players){
if(areLinesColliding(
miss_ite->getX(), miss_ite->getX() + confData.missilesWidth,
p.x, p.x + confData.playersWidth)){
wasColliding = true;
if(p.deathAnimCounter)p.deathAnimCounter = 1;
// do not break, the second player also deserves to be hit
}
}
}
if(wasColliding)missiles.erase(miss_ite);
else ++miss_ite;
}
return false; // TODO manage death animation
}
bool Game::checkTorpedosAndInvaders() {
auto tor_ite = torpedos.begin();
while(tor_ite!=torpedos.end()){
size_t i=0;
for(;i<grid.size();++i){
unsigned alienIndex = grid[i].getOutterInvader();
// calculate top-left Position of invader
Position pos = basePos + Position(
confData.invadersSize*i+confData.invadersDistance*i,
confData.invadersSize*alienIndex+confData.invadersDistance*alienIndex
);
// check collision on Y (invaders can actually be "under" torpedos, so we check both lower and upper bounds
if(pos.getY()+confData.invadersSize>=tor_ite->getY() &&
pos.getY()<=tor_ite->getY()+confData.torpedosLength){
// now check collision on X
if(areLinesColliding( // now check collision on X
tor_ite->getX(), tor_ite->getX() + confData.torpedosWidth,
pos.getX(), pos.getX() + confData.invadersSize)){
InvaderType invType = grid[i][grid[i].size()];
players[tor_ite->owner].score += confData.invadersDef[invType].points;
torpedos.erase(tor_ite);
grid[i][alienIndex] = InvaderType::NONE;
updateColumns();
break;
}
}
}
if(i==grid.size()) ++tor_ite;
}
return false;
}
bool Game::invadersTouchPlayer() const {
for(const InvadersColumn& line : grid){
if(basePos.getY() + line.size() * confData.invadersSize >= pm.getScreenHeight() - PLAYER_HEIGHT){
return true;
}
}
return false;
}