SuperSpaceInvaderTurboApoca.../src/game/display.cpp
2022-01-10 14:27:16 +01:00

169 lines
4.7 KiB
C++

/*!
*
* @file display.cpp
* @author RUBINI Thomas
* @author SIMAILA Djalim
* @date January 2022
* @version 1.0
* @brief game display
*
*/
#include "game.h"
/** Displays the screen once, and returns
* The more important stuff must be drawn last
*/
void Game::displayAll() const {
pm->drawSprite(pm->gameBackground);
for (unsigned i = 0; i < this->grid.size(); ++i){
for (unsigned j = 0; j < this->grid[i].size(); ++j){
Position vec(
basePos.getX() + i * confData.invadersSize + i * confData.invadersDistance,
basePos.getY() + j * confData.invadersSize + j * confData.invadersDistance
);
displayInvader(vec, grid[i][j]);
}
}
for(const missile& miss : missiles){
pm->drawMissile(miss, confData.missilesWidth, confData.missilesColor);
}
for(const Torpedo& tor : torpedos){
pm->drawTorpedo(tor, confData.torpedosWidth, confData.torpedosColor);
}
displayGod();
DEBUG_INSTR(
pm->drawText(Position(pm->getScreenWidth()-200, 20), "FPS : "+to_string(fps), nsGraphics::KWhite, Font::BITMAP_8_BY_13);
)
for(unsigned i=0;i<players.size();++i){
if(!players[i].isEliminated()){
if(players[i].deathAnimCounter%2==0){
pm->drawPlayer(players[i].x, confData.playersWidth, confData.playerDefs[i].color);
}
}
// out of the condition, because we still need to display the falling heart
displayHearts(i);
}
}
void Game::displayHearts(playerID pID) const {
// As said before, the player loop is an illusion, 2 players max
unsigned x;
if(pID==PLAYER1)x = 0;
else x = pm->getScreenWidth()-HEART_LENGTH;
unsigned y = GOD_BENCH_SIZE+5;
for(unsigned i=0;i<players[pID].lives;++i){
pm->drawHeart(Position(x, y));
y+=HEART_LENGTH+5;
}
if(players[pID].hasDeathAnimation()){
pm->drawHeart(Position(x, y+players[pID].deathAnimCounter*5));
}
}
void Game::displayInvader(const Position& pos, InvaderType type) const {
if(type==InvaderType::NONE)return;
const InvaderTypeDef& invDef = confData.invadersDef.at(type);
switch(type){
case InvaderType::TYPEA:{
pm->drawInvaderA(pos, confData.invadersSize, invDef.color);
return;
}
case InvaderType::TYPEB:{
pm->drawInvaderB(pos, confData.invadersSize, invDef.color);
return;
}
case InvaderType::TYPEC:{
pm->drawInvaderC(pos, confData.invadersSize, invDef.color);
return;
}
}
}
void applyBezier(Position& pos, const Position& point, const double percent) {
pos += (point-pos)*percent;
}
void Game::displayGod() const {
switch (god.state) {
case GodState::NONE:
return;
case GodState::AWAKE: {
pm->drawGodBench(god.counter - GOD_BENCH_SIZE);
Position leftHand(GOD_HAND_DISTANCE, god.counter-GOD_BENCH_SIZE);
Position rightHand(pm->getScreenWidth()-GOD_HAND_DISTANCE-GOD_HAND_SIZE, god.counter-GOD_BENCH_SIZE);
pm->drawGodLeftHand(leftHand);
pm->drawGodRightHand(rightHand);
pm->drawGodFace(god.counter - GOD_BENCH_SIZE);
break;
}
case GodState::WAIT:{
pm->drawGodBench(0);
Position leftHand(GOD_HAND_DISTANCE, 0);
Position rightHand(god.getRightHandPos(pm->getScreenWidth()));
pm->drawGodLeftHand(leftHand);
pm->drawGodRightHand(rightHand);
pm->drawGodFace(0);
break;
}
case GodState::RETRIEVE1:
case GodState::RETRIEVE2:{
// Bezier curve
// counter goes [0-100]
pm->drawGodBench(0);
pm->drawGodLeftHand(Position(GOD_HAND_DISTANCE, 0));
pm->drawGodFace(0);
Position pos(god.getRightHandPos(pm->getScreenWidth()));
Position endPos = invIndexToPos(god.thrownInvPosX, god.thrownInvPosY);
applyBezier(pos, god.thrownTransition, god.counter / 100.0);
applyBezier(pos, endPos, god.counter / 100.0);
// pos is now the position we need to draw our hand to
pm->drawGodRightHand(pos);
if(god.thrownInvType!=InvaderType::NONE){
pos+=Position(GOD_HAND_SIZE/2, GOD_HAND_SIZE/2);
pos-=Position(confData.invadersSize/2, confData.invadersSize/2);
displayInvader(pos, god.thrownInvType);
}
break;
}
case GodState::THROW:{
pm->drawGodBench(0);
pm->drawGodLeftHand(Position(GOD_HAND_DISTANCE, 0));
pm->drawGodFace(0);
// compute start position (not sure if we should store it or compute it each time ?)
Position handPos = god.getRightHandPos(pm->getScreenWidth());
Position invaderPos = handPos;
applyTransformation(invaderPos, GOD_HAND_SIZE, confData.invadersSize);
Position a = god.thrownVector * (god.counter / 100.0);
invaderPos = invaderPos + a;
displayInvader(invaderPos, god.thrownInvType);
if(god.counter<30){
// handling hand retraction
unsigned handCounter;
if(god.counter<15)handCounter = god.counter;
else handCounter = 30-god.counter;
handPos = handPos + god.thrownVector * (handCounter / 100.0);
}
pm->drawGodRightHand(handPos);
break;
}
}
}