212 lines
5.9 KiB
C++
212 lines
5.9 KiB
C++
/*!
|
|
*
|
|
* @file gameBasics.cpp
|
|
* @author RUBINI Thomas
|
|
* @date January 2022
|
|
* @version 1.0
|
|
* @brief game basic mechanisms
|
|
*
|
|
*/
|
|
|
|
#include "game.h"
|
|
|
|
#define ISPRESSED(ID, X) window.isPressed({confData.playerDefs[ID].keys.X, false})
|
|
void Game::manageOnePlayer(playerID pID){
|
|
Player& p = players[pID];
|
|
if(p.isEliminated())return;
|
|
|
|
if (ISPRESSED(pID, left)){
|
|
if(p.x < confData.playersSpeed) p.x = 0;
|
|
else p.x -= confData.playersSpeed;
|
|
}
|
|
if (ISPRESSED(pID, right)){
|
|
if(p.x + confData.playersWidth + confData.playersSpeed >= pm.getScreenWidth()) p.x = pm.getScreenWidth() - confData.playersWidth - 1;
|
|
else p.x += confData.playersSpeed;
|
|
}
|
|
|
|
|
|
if(p.hasDeathAnimation()) {
|
|
++p.deathAnimCounter;
|
|
if (p.deathAnimCounter == 75) {
|
|
p.deathAnimCounter = 0;
|
|
}
|
|
}else{
|
|
if(p.isEliminated())return;
|
|
|
|
if(p.fireCooldown==0) {
|
|
if (ISPRESSED(pID, shoot)) {
|
|
torpedos.emplace_back(p.x + confData.playersWidth / 2, pm.getScreenHeight() - PLAYER_HEIGHT, pID);
|
|
p.fireCooldown = confData.playersFireCooldown;
|
|
}
|
|
}else --p.fireCooldown;
|
|
}
|
|
}
|
|
|
|
void Game::managePlayers(){
|
|
for(unsigned i=0;i<players.size();++i)manageOnePlayer(i);
|
|
}
|
|
|
|
bool Game::manageInvaders(){
|
|
if(!areThereInvadersLeft())return false; // If there are no more invaders we don't need to manage them
|
|
|
|
// shoot
|
|
if(fireCooldown==0) {
|
|
fireCooldown = confData.invadersFireCooldown + rand() % 25;
|
|
|
|
unsigned rdCol = grid.randomValidCol();
|
|
// 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;
|
|
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
void 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(p.isPlaying()){
|
|
if(areLinesColliding(
|
|
miss_ite->getX(), miss_ite->getX() + confData.missilesWidth,
|
|
p.x, p.x + confData.playersWidth)){
|
|
wasColliding = true;
|
|
p.damage();
|
|
// do not break, the second player also deserves to be hit
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(wasColliding)missiles.erase(miss_ite);
|
|
else ++miss_ite;
|
|
}
|
|
}
|
|
|
|
bool Game::checkTorpedosAndInvaders() {
|
|
auto tor_ite = torpedos.begin();
|
|
while(tor_ite!=torpedos.end()){
|
|
unsigned i=0;
|
|
for(;i<grid.size();++i){
|
|
|
|
unsigned alienIndex = grid[i].getOutterInvader();
|
|
if(alienIndex==grid[i].size())continue;
|
|
// 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][alienIndex];
|
|
players[tor_ite->owner].score += confData.invadersDef.at(invType).points;
|
|
torpedos.erase(tor_ite);
|
|
|
|
grid[i][alienIndex] = InvaderType::NONE;
|
|
|
|
if(!areThereInvadersLeft()) return true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(i==grid.size()) ++tor_ite;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Game::invadersTouchPlayer() const {
|
|
return any_of(grid.begin(), grid.end(), [this](const InvadersColumn& line) -> bool {
|
|
unsigned outter = line.getOutterInvader();
|
|
return this->basePos.getY()+confData.invadersSize*(outter+1)
|
|
+confData.invadersDistance*outter
|
|
>= pm.getScreenHeight() - PLAYER_HEIGHT;
|
|
});
|
|
}
|