Async sprites loading
This commit is contained in:
parent
3dcdcadff3
commit
36d6b21613
@ -17,3 +17,4 @@ target_link_libraries(Space mingl)
|
||||
target_link_libraries(Space GL)
|
||||
target_link_libraries(Space GLU)
|
||||
target_link_libraries(Space glut)
|
||||
target_link_libraries(Space pthread)
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,6 +1,7 @@
|
||||
# General configuration
|
||||
general:
|
||||
maxFPS: 90
|
||||
theme: bad
|
||||
|
||||
# Players config
|
||||
players:
|
||||
|
@ -25,7 +25,12 @@ typedef string configKey;
|
||||
* @brief this struct stores all relevant data from the configuration file
|
||||
*/
|
||||
struct ConfigData {
|
||||
|
||||
|
||||
/*!
|
||||
* @brief theme to use. Valid values : good,bad
|
||||
*/
|
||||
string theme;
|
||||
|
||||
/*!
|
||||
* @brief maximum framerate at which the game will run
|
||||
*/
|
||||
|
@ -14,7 +14,7 @@
|
||||
#define GUARD_GAME_H
|
||||
#include <vector>
|
||||
#include "mingl/mingl.h"
|
||||
#include "pixelManager.h"
|
||||
#include "pixelManager/pixelManager.h"
|
||||
#include "utils.h"
|
||||
#include "playerDef.h"
|
||||
#include "player.h"
|
||||
@ -41,8 +41,9 @@ private:
|
||||
|
||||
/*!
|
||||
* @brief PixelManager : Class that contains and draws all the data that will be drawn on screen
|
||||
* This is a pointer because the object is allocated at runtime, following the configuration
|
||||
*/
|
||||
PixelManager pm;
|
||||
unique_ptr<PixelManager> pm;
|
||||
|
||||
/*!
|
||||
* @brief ConfigData : Struct that stores all the relevant data read from the configuration file
|
||||
@ -65,7 +66,7 @@ private:
|
||||
Position basePos;
|
||||
|
||||
/*!
|
||||
* @brief Invader posision and type matrix
|
||||
* @brief Invader position and type matrix
|
||||
*/
|
||||
InvadersGrid grid;
|
||||
|
||||
@ -97,9 +98,9 @@ private:
|
||||
// invaders related variables
|
||||
|
||||
/*!
|
||||
* @brief cooldown between two invader shot in milliseconds
|
||||
* @brief cooldown until the invaders can shoot again
|
||||
*/
|
||||
unsigned fireCooldown=120;
|
||||
unsigned fireCooldown=0;
|
||||
|
||||
// basic methods
|
||||
|
||||
|
16
headers/mySprite.h
Normal file
16
headers/mySprite.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef GUARD_MYSPRITE_H
|
||||
#define GUARD_MYSPRITE_H
|
||||
|
||||
#include <future>
|
||||
#include "mingl/gui/sprite.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class MySprite{
|
||||
public:
|
||||
unique_ptr<nsGui::Sprite> ptr;
|
||||
future<void> asyncLoad(const string& fname);
|
||||
void mirror(MySprite& msp);
|
||||
};
|
||||
|
||||
#endif
|
21
headers/pixelManager/goodPixelManager.h
Normal file
21
headers/pixelManager/goodPixelManager.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef GUARD_GOODPIXELMANAGER_H
|
||||
#define GUARD_GOODPIXELMANAGER_H
|
||||
|
||||
#include "pixelManager/pixelManager.h"
|
||||
|
||||
class GoodPixelManager : public PixelManager{
|
||||
|
||||
void loadSprites(SpriteTasks& tasks) override;
|
||||
|
||||
MySprite player;
|
||||
MySprite invaderA;
|
||||
MySprite invaderB;
|
||||
MySprite invaderC;
|
||||
MySprite missile;
|
||||
MySprite torpedo;
|
||||
public:
|
||||
GoodPixelManager(MinGL& win);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -24,54 +24,64 @@
|
||||
#include "utils.h"
|
||||
#include "playMode.h"
|
||||
#include "menu.h"
|
||||
#include "mySprite.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define MIRROR(SP) mirrorData((SP).getPixelData(), (SP).getRowSize()), (SP).getRowSize()
|
||||
|
||||
typedef nsGui::GlutFont::GlutFonts Font;
|
||||
|
||||
/*!
|
||||
* @class PixelManager
|
||||
* @brief main display function, clear the window and calls sub display functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* It's MinGL's fault. This is all I have to say
|
||||
*/
|
||||
|
||||
// The convention seems to just add a number to the macro name
|
||||
#define ADD_TASK(X) ADD_TASK2(X, X)
|
||||
#define ADD_TASK2(X, Y) tasks.push_back((X).asyncLoad("assets/"#Y".si2"));
|
||||
|
||||
typedef vector<future<void>> SpriteTasks;
|
||||
|
||||
|
||||
class PixelManager{
|
||||
public:
|
||||
MinGL& window;
|
||||
|
||||
/*
|
||||
* Sprites are not const because for some reason the texture is associated with coordinates,
|
||||
* and we have no way to dissociate them...
|
||||
* So the objects are constantly updated with new coordinates as they need to be drawn
|
||||
* We used {} insead of () for the constructor because the () makes the compiler think we declare methods
|
||||
*
|
||||
* (We could copy them every time, but I feel like copying image data every frame isn't great)
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief loads sprites in parallel using multiple threads
|
||||
* @param[in] vec : We take his ownership, so
|
||||
* @fn void loadSprites();
|
||||
*/
|
||||
virtual void loadSprites(SpriteTasks& tasks);
|
||||
|
||||
|
||||
/*!
|
||||
* @brief sprite of the logo of the game
|
||||
*/
|
||||
nsGui::Sprite logo{"assets/logo.si2"};
|
||||
|
||||
/*!
|
||||
* @brief sprite of the background during gameplay
|
||||
*/
|
||||
nsGui::Sprite gameBackground{"assets/game_background.si2"};
|
||||
|
||||
MySprite logo;
|
||||
|
||||
/*!
|
||||
* @brief sprite of the background during menu
|
||||
*/
|
||||
nsGui::Sprite menuBackground{"assets/menu_background.si2"};
|
||||
|
||||
MySprite menuBackground;
|
||||
|
||||
/*!
|
||||
* @brief sprite of the background during gameplay
|
||||
*/
|
||||
MySprite gameBackground;
|
||||
|
||||
/*!
|
||||
* @brief sprite of the right hand of god
|
||||
*/
|
||||
nsGui::Sprite rightHand{"assets/hand_open.si2"};
|
||||
MySprite rightHand;
|
||||
|
||||
/*!
|
||||
* @brief sprite of the left hand of god
|
||||
*/
|
||||
nsGui::Sprite leftHand{MIRROR(rightHand)};
|
||||
MySprite leftHand;
|
||||
|
||||
/*!
|
||||
* @brief constructor the pixel manager class
|
||||
@ -145,11 +155,11 @@ public:
|
||||
|
||||
/*!
|
||||
* @brief display a sprite on screen
|
||||
* @param[in] sprite : sprite to draw
|
||||
* @param[in] msp : sprite to draw
|
||||
* @param[in] pos : pixel coordinates to draw the sprite
|
||||
* @fn void drawSprite(const nsGui::Sprite& sprite, const Position& pos = Position(0, 0)) const;
|
||||
* @fn void drawSprite(const MySprite& msp, const Position& pos = Position(0, 0)) const;
|
||||
*/
|
||||
void drawSprite(const nsGui::Sprite& sprite, const Position& pos = Position(0, 0)) const;
|
||||
void drawSprite(const MySprite& msp, const Position& pos = Position(0, 0)) const;
|
||||
|
||||
/*!
|
||||
* @brief display a menu button on screen
|
@ -153,6 +153,7 @@ void ConfigBuilder::readInvaderType(const configKey& baseKey, InvaderTypeDef& in
|
||||
|
||||
void ConfigBuilder::readConfig() {
|
||||
|
||||
collectedData.theme = getString("general.theme");
|
||||
collectedData.maxFPS = getInt("general.maxFPS");
|
||||
|
||||
readGrid("grid");
|
||||
|
@ -16,7 +16,7 @@
|
||||
* The more important stuff must be drawn last
|
||||
*/
|
||||
void Game::displayAll() const {
|
||||
pm.drawSprite(pm.gameBackground);
|
||||
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(
|
||||
@ -28,23 +28,23 @@ void Game::displayAll() const {
|
||||
}
|
||||
|
||||
for(const missile& miss : missiles){
|
||||
pm.drawMissile(miss, confData.missilesWidth, confData.missilesColor);
|
||||
pm->drawMissile(miss, confData.missilesWidth, confData.missilesColor);
|
||||
}
|
||||
for(const Torpedo& tor : torpedos){
|
||||
pm.drawTorpedo(tor, confData.torpedosWidth, confData.torpedosColor);
|
||||
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);
|
||||
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);
|
||||
pm->drawPlayer(players[i].x, confData.playersWidth, confData.playerDefs[i].color);
|
||||
}
|
||||
}
|
||||
// out of the condition, because we still need to display the falling heart
|
||||
@ -57,15 +57,15 @@ 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;
|
||||
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));
|
||||
pm->drawHeart(Position(x, y));
|
||||
y+=HEART_LENGTH+5;
|
||||
}
|
||||
if(players[pID].hasDeathAnimation()){
|
||||
pm.drawHeart(Position(x, y+players[pID].deathAnimCounter*5));
|
||||
pm->drawHeart(Position(x, y+players[pID].deathAnimCounter*5));
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,15 +74,15 @@ void Game::displayInvader(const Position& pos, InvaderType type) const {
|
||||
const InvaderTypeDef& invDef = confData.invadersDef.at(type);
|
||||
switch(type){
|
||||
case InvaderType::TYPEA:{
|
||||
pm.drawInvaderA(pos, confData.invadersSize, invDef.color);
|
||||
pm->drawInvaderA(pos, confData.invadersSize, invDef.color);
|
||||
return;
|
||||
}
|
||||
case InvaderType::TYPEB:{
|
||||
pm.drawInvaderB(pos, confData.invadersSize, invDef.color);
|
||||
pm->drawInvaderB(pos, confData.invadersSize, invDef.color);
|
||||
return;
|
||||
}
|
||||
case InvaderType::TYPEC:{
|
||||
pm.drawInvaderC(pos, confData.invadersSize, invDef.color);
|
||||
pm->drawInvaderC(pos, confData.invadersSize, invDef.color);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -97,40 +97,40 @@ void Game::displayGod() const {
|
||||
case GodState::NONE:
|
||||
return;
|
||||
case GodState::AWAKE: {
|
||||
pm.drawGodBench(god.counter - GOD_BENCH_SIZE);
|
||||
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);
|
||||
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);
|
||||
pm->drawGodBench(0);
|
||||
Position leftHand(GOD_HAND_DISTANCE, 0);
|
||||
Position rightHand(god.getRightHandPos(pm.getScreenWidth()));
|
||||
pm.drawGodLeftHand(leftHand);
|
||||
pm.drawGodRightHand(rightHand);
|
||||
pm.drawGodFace(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);
|
||||
pm->drawGodBench(0);
|
||||
pm->drawGodLeftHand(Position(GOD_HAND_DISTANCE, 0));
|
||||
pm->drawGodFace(0);
|
||||
|
||||
Position pos(god.getRightHandPos(pm.getScreenWidth()));
|
||||
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);
|
||||
pm->drawGodRightHand(pos);
|
||||
if(god.thrownInvType!=InvaderType::NONE){
|
||||
|
||||
pos+=Position(GOD_HAND_SIZE/2, GOD_HAND_SIZE/2);
|
||||
@ -140,12 +140,12 @@ void Game::displayGod() const {
|
||||
break;
|
||||
}
|
||||
case GodState::THROW:{
|
||||
pm.drawGodBench(0);
|
||||
pm.drawGodLeftHand(Position(GOD_HAND_DISTANCE, 0));
|
||||
pm.drawGodFace(0);
|
||||
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 handPos = god.getRightHandPos(pm->getScreenWidth());
|
||||
|
||||
Position invaderPos = handPos;
|
||||
applyTransformation(invaderPos, GOD_HAND_SIZE, confData.invadersSize);
|
||||
@ -160,7 +160,7 @@ void Game::displayGod() const {
|
||||
else handCounter = 30-god.counter;
|
||||
handPos = handPos + god.thrownVector * (handCounter / 100.0);
|
||||
}
|
||||
pm.drawGodRightHand(handPos);
|
||||
pm->drawGodRightHand(handPos);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -10,17 +10,42 @@
|
||||
*/
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include "game.h"
|
||||
#include "playMode.h"
|
||||
#include "pixelManager/goodPixelManager.h"
|
||||
|
||||
#define WININIT window("SUPER Space Invader : Turbo Apocalypse DX - VS GOD", Position(1280, 720), Position(128, 128), nsGraphics::KBlack)
|
||||
|
||||
Game::Game() : WININIT, pm(window) {
|
||||
if(!reloadConfig()){
|
||||
Game::Game() : WININIT {
|
||||
|
||||
if(!reloadConfig()){ // Config
|
||||
throw runtime_error("Initial config loading failed. Please check the error above and fix the configuration");
|
||||
}
|
||||
sm.readFile();
|
||||
|
||||
// Pixel Manager
|
||||
if(confData.theme=="good"){
|
||||
pm = std::make_unique<GoodPixelManager>(window);
|
||||
}else if(confData.theme=="bad"){
|
||||
pm = std::make_unique<PixelManager>(window);
|
||||
}else throw runtime_error("Invalid theme value : "+confData.theme+
|
||||
"\nValid values are : good,bad");
|
||||
|
||||
cout << "Loading sprites..." << endl;
|
||||
SpriteTasks tasks;
|
||||
chrono::high_resolution_clock::time_point start = chrono::high_resolution_clock::now();
|
||||
|
||||
pm->loadSprites(tasks);
|
||||
for(future<void>& f : tasks)f.wait();
|
||||
|
||||
// We just do that for one sprite, so I didn't bother creating an 'API' for that
|
||||
pm->leftHand.mirror(pm->rightHand);
|
||||
|
||||
chrono::high_resolution_clock::duration elapsed = chrono::high_resolution_clock::now()-start;
|
||||
cout << "Done ! Time : " << chrono::duration_cast<chrono::milliseconds>(elapsed).count() << "ms" << endl;
|
||||
|
||||
sm.readFile(); // Score manager
|
||||
}
|
||||
|
||||
bool Game::areThereInvadersLeft(){
|
||||
@ -30,7 +55,7 @@ bool Game::areThereInvadersLeft(){
|
||||
void Game::handleScoreSaving(){
|
||||
for(unsigned i=0;i<players.size();++i){
|
||||
string pName;
|
||||
pm.askPlayerNameMenu(i, players[i].score, pName);
|
||||
pm->askPlayerNameMenu(i, players[i].score, pName);
|
||||
sm.inputScore(move(pName), players[i].score);
|
||||
}
|
||||
sm.writeFile();
|
||||
@ -42,13 +67,13 @@ void Game::managedGames() {
|
||||
|
||||
while(playMode!=PlayMode::EXIT){
|
||||
if(playMode==PlayMode::NONE){
|
||||
playMode = pm.showInitialMenu();
|
||||
playMode = pm->showInitialMenu();
|
||||
}else{
|
||||
initGame();
|
||||
enterGameLoop(); // will read the playMode
|
||||
handleScoreSaving();
|
||||
cout << "END OF GAME" << endl;
|
||||
if(!pm.showDeathMenu())playMode = PlayMode::NONE;
|
||||
if(!pm->showDeathMenu())playMode = PlayMode::NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,7 +94,7 @@ void Game::initGame(){
|
||||
}else{
|
||||
players.resize(2);
|
||||
// mirror the start X Position for the other
|
||||
players[1].x = pm.getScreenWidth() - confData.startXPosition - confData.playersWidth;
|
||||
players[1].x = pm->getScreenWidth() - confData.startXPosition - confData.playersWidth;
|
||||
}
|
||||
players[0].x = confData.startXPosition;
|
||||
|
||||
@ -103,7 +128,7 @@ WinValue Game::enterGameLoop(){ // returns when game is finished
|
||||
fpsStartTime = startTime;
|
||||
}
|
||||
|
||||
pm.startFrame();
|
||||
pm->startFrame();
|
||||
|
||||
managePlayers();
|
||||
if(manageInvaders()) { // if they went down
|
||||
@ -126,7 +151,7 @@ WinValue Game::enterGameLoop(){ // returns when game is finished
|
||||
|
||||
displayAll();
|
||||
|
||||
pm.endFrame();
|
||||
pm->endFrame();
|
||||
|
||||
MyTimePoint endTime = chrono::high_resolution_clock::now();
|
||||
|
||||
|
@ -20,7 +20,7 @@ void Game::manageOnePlayer(playerID pID){
|
||||
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;
|
||||
if(p.x + confData.playersWidth + confData.playersSpeed >= pm->getScreenWidth()) p.x = pm->getScreenWidth() - confData.playersWidth - 1;
|
||||
else p.x += confData.playersSpeed;
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ void Game::manageOnePlayer(playerID pID){
|
||||
|
||||
if(p.fireCooldown==0) {
|
||||
if (ISPRESSED(pID, shoot)) {
|
||||
torpedos.emplace_back(p.x + confData.playersWidth / 2, pm.getScreenHeight() - PLAYER_HEIGHT, pID);
|
||||
torpedos.emplace_back(p.x + confData.playersWidth / 2, pm->getScreenHeight() - PLAYER_HEIGHT, pID);
|
||||
p.fireCooldown = confData.playersFireCooldown;
|
||||
}
|
||||
}else --p.fireCooldown;
|
||||
@ -69,7 +69,7 @@ bool Game::manageInvaders(){
|
||||
|
||||
// you got the end position of the invader crowd !
|
||||
|
||||
if(end + confData.invadersSpeed < pm.getScreenWidth()){
|
||||
if(end + confData.invadersSpeed < pm->getScreenWidth()){
|
||||
basePos.setX(basePos.getX() + confData.invadersSpeed);
|
||||
}else{
|
||||
basePos.setY(basePos.getY() + confData.invadersSize + confData.invadersDistance);
|
||||
@ -121,7 +121,7 @@ void Game::remCollidingProjectiles(){
|
||||
void Game::moveMissiles() {
|
||||
auto miss = missiles.begin();
|
||||
while (miss != missiles.end()) {
|
||||
if (miss->getY() >= pm.getScreenHeight())missiles.erase(miss);
|
||||
if (miss->getY() >= pm->getScreenHeight())missiles.erase(miss);
|
||||
else {
|
||||
miss->setY(miss->getY()+confData.missilesSpeed);
|
||||
++miss;
|
||||
@ -144,7 +144,7 @@ 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
|
||||
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()){
|
||||
@ -206,6 +206,6 @@ bool Game::invadersTouchPlayer() const {
|
||||
unsigned outter = line.getOutterInvader();
|
||||
return this->basePos.getY()+confData.invadersSize*(outter+1)
|
||||
+confData.invadersDistance*outter
|
||||
>= pm.getScreenHeight() - PLAYER_HEIGHT;
|
||||
>= pm->getScreenHeight() - PLAYER_HEIGHT;
|
||||
});
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ bool Game::manageGod() {
|
||||
god.thrownInvPosY = grid[god.thrownInvPosX].randomValidInv();
|
||||
god.thrownInvType = InvaderType::NONE;
|
||||
|
||||
god.thrownTransition.setX(pm.getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE);
|
||||
god.thrownTransition.setX(pm->getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE);
|
||||
god.thrownTransition.setY(basePos.getY() + INV_GET_POS(god.thrownInvPosY));
|
||||
return false;
|
||||
}
|
||||
@ -79,7 +79,7 @@ bool Game::manageGod() {
|
||||
|
||||
// compute the launch vector
|
||||
|
||||
Position invaderMiddlePos(pm.getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE / 2,
|
||||
Position invaderMiddlePos(pm->getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE / 2,
|
||||
GOD_HAND_SIZE / 2);
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@ bool Game::manageGod() {
|
||||
* honestly at this point I want to re-code the whole game engine to allow a better handling of cases like this...*/
|
||||
|
||||
Position playerMiddlePos(players[target].x + confData.playersWidth / 2,
|
||||
pm.getScreenHeight() - PLAYER_HEIGHT / 2);
|
||||
pm->getScreenHeight() - PLAYER_HEIGHT / 2);
|
||||
|
||||
god.thrownVector = playerMiddlePos - invaderMiddlePos;
|
||||
god.thrownVector = god.thrownVector / (god.thrownVector.computeMagnitude() / 1000.0);
|
||||
@ -101,7 +101,7 @@ bool Game::manageGod() {
|
||||
case GodState::THROW: {
|
||||
++god.counter;
|
||||
|
||||
Position invaderPos = god.getRightHandPos(pm.getScreenWidth());
|
||||
Position invaderPos = god.getRightHandPos(pm->getScreenWidth());
|
||||
applyTransformation(invaderPos, GOD_HAND_SIZE, confData.invadersSize);
|
||||
Position a = god.thrownVector * (god.counter / 100.0);
|
||||
invaderPos = invaderPos + a;
|
||||
@ -109,8 +109,8 @@ bool Game::manageGod() {
|
||||
bool touched = false;
|
||||
|
||||
// check if OOB (Out Of Bounds)
|
||||
if (invaderPos.getY() + confData.invadersSize >= pm.getScreenWidth() ||
|
||||
(invaderPos.getX() < 0 || invaderPos.getX() + confData.invadersSize >= pm.getScreenWidth())) {
|
||||
if (invaderPos.getY() + confData.invadersSize >= pm->getScreenWidth() ||
|
||||
(invaderPos.getX() < 0 || invaderPos.getX() + confData.invadersSize >= pm->getScreenWidth())) {
|
||||
touched = true;
|
||||
|
||||
/* there are no invaders in the grid anymore, and the one thrown just went out of bound
|
||||
@ -118,7 +118,7 @@ bool Game::manageGod() {
|
||||
if(!areThereInvadersLeft())return true;
|
||||
|
||||
// check player collision
|
||||
} else if (invaderPos.getY() + confData.invadersSize >= pm.getScreenHeight() - PLAYER_HEIGHT) {
|
||||
} else if (invaderPos.getY() + confData.invadersSize >= pm->getScreenHeight() - PLAYER_HEIGHT) {
|
||||
for (Player &p: players) {
|
||||
if(p.isPlaying()){
|
||||
if (areLinesColliding(
|
||||
|
26
src/mySprite.cpp
Normal file
26
src/mySprite.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "utils.h"
|
||||
#include "mySprite.h"
|
||||
|
||||
future<void> MySprite::asyncLoad(const string& fname){
|
||||
return std::async(std::launch::async, [fname, this]() -> void {
|
||||
ptr = std::make_unique<nsGui::Sprite>(fname);
|
||||
});
|
||||
}
|
||||
|
||||
void MySprite::mirror(MySprite& msp) {
|
||||
const vector<RGBAcolor>& inPixels = msp.ptr->getPixelData();
|
||||
unsigned rowSize = msp.ptr->getRowSize();
|
||||
|
||||
vector<RGBAcolor> outPixels;
|
||||
// we reserve size so the vector doesn't dynamically grows
|
||||
outPixels.reserve(inPixels.size());
|
||||
//for each line of pixel
|
||||
for(unsigned rowOffset=0; rowOffset < inPixels.size(); rowOffset+=rowSize){
|
||||
// for each pixel of that line
|
||||
for(unsigned j=0;j<rowSize;++j) {
|
||||
// push back the pixel opposed to this one (still in the same line)
|
||||
outPixels.push_back(inPixels[rowOffset + rowSize - j - 1]);
|
||||
}
|
||||
}
|
||||
ptr = std::make_unique<nsGui::Sprite>(outPixels, rowSize);
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
#include "mingl/gui/text.h"
|
||||
#include "pixelManager.h"
|
||||
#include "pixelManager/pixelManager.h"
|
||||
#include "utils.h"
|
||||
#include "god.h"
|
||||
|
||||
@ -76,26 +76,10 @@ void PixelManager::drawTorpedo(const Position& baseVector, unsigned width, const
|
||||
window << Rectangle(baseVector, baseVector + Position(width, width * PROJ_LENGTH_FACTOR), color);
|
||||
}
|
||||
|
||||
void PixelManager::drawSprite(const Sprite& sprite, const Position& pos) const {
|
||||
// see pixelManager.h for the explanation of this hack
|
||||
const_cast<Sprite&>(sprite).setPosition(pos);
|
||||
sprite.draw(window);
|
||||
}
|
||||
|
||||
unsigned PixelManager::getScreenHeight() const {
|
||||
return window.getWindowSize().getY();
|
||||
}
|
||||
|
||||
unsigned PixelManager::getScreenWidth() const {
|
||||
return window.getWindowSize().getX();
|
||||
}
|
||||
|
||||
void PixelManager::startFrame() const {
|
||||
window.clearScreen();
|
||||
}
|
||||
|
||||
void PixelManager::endFrame() const {
|
||||
window.finishFrame();
|
||||
void PixelManager::drawSprite(const MySprite& msp, const Position& pos) const {
|
||||
// The sprite is associated with a Vec2D for whatever reason, so yeah, we modify it each time we draw it
|
||||
msp.ptr->setPosition(pos);
|
||||
msp.ptr->draw(window);
|
||||
}
|
||||
|
||||
void PixelManager::drawGodBench(int y) const {
|
||||
@ -128,19 +112,3 @@ void PixelManager::drawGodFace(int y, bool angry) const {
|
||||
void PixelManager::drawText(const Position& pos, const string& text, const nsGraphics::RGBAcolor& color, Font font) const {
|
||||
window << Text(pos, text, color, font);
|
||||
}
|
||||
|
||||
vector<RGBAcolor>
|
||||
PixelManager::mirrorData(const vector<nsGraphics::RGBAcolor>& inPixels, unsigned rowSize) {
|
||||
vector<RGBAcolor> outPixels;
|
||||
// we reserve size so the vector doesn't dynamically grows
|
||||
outPixels.reserve(inPixels.size());
|
||||
//for each line of pixel
|
||||
for(unsigned rowOffset=0; rowOffset < inPixels.size(); rowOffset+=rowSize){
|
||||
// for each pixel of that line
|
||||
for(unsigned j=0;j<rowSize;++j) {
|
||||
// push back the pixel opposed to this one (still in the same line)
|
||||
outPixels.push_back(inPixels[rowOffset + rowSize - j - 1]);
|
||||
}
|
||||
}
|
||||
return std::move(outPixels);
|
||||
}
|
@ -13,13 +13,13 @@
|
||||
#include <thread>
|
||||
#include "mingl/shape/rectangle.h"
|
||||
#include "playMode.h"
|
||||
#include "pixelManager.h"
|
||||
#include "pixelManager/pixelManager.h"
|
||||
#include "utils.h"
|
||||
|
||||
using namespace nsShape;
|
||||
using namespace nsGraphics;
|
||||
|
||||
void PixelManager::displayButton(const Position& baseVector,const string& text,nsGraphics::RGBAcolor& color){
|
||||
void PixelManager::displayButton(const Position& baseVector, const string& text, nsGraphics::RGBAcolor& color){
|
||||
window << Rectangle(baseVector, Position(180, 40)+baseVector, KGray);
|
||||
window << Rectangle(baseVector+Position(2,2), Position(178, 38)+baseVector, KBlack);
|
||||
window << nsGui::Text(baseVector+Position(10,22), text, color);
|
15
src/pixelManager/goodPixelManager.cpp
Normal file
15
src/pixelManager/goodPixelManager.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "pixelManager/goodPixelManager.h"
|
||||
|
||||
void GoodPixelManager::loadSprites(SpriteTasks& tasks) {
|
||||
PixelManager::loadSprites(tasks);
|
||||
ADD_TASK(player)
|
||||
ADD_TASK(invaderA)
|
||||
ADD_TASK(invaderB)
|
||||
ADD_TASK(invaderC)
|
||||
ADD_TASK(missile)
|
||||
ADD_TASK(torpedo)
|
||||
}
|
||||
|
||||
GoodPixelManager::GoodPixelManager(MinGL& win) : PixelManager(win) {
|
||||
|
||||
}
|
41
src/pixelManager/pixelManager.cpp
Normal file
41
src/pixelManager/pixelManager.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include "pixelManager/pixelManager.h"
|
||||
|
||||
|
||||
void PixelManager::loadSprites(SpriteTasks& tasks){
|
||||
ADD_TASK(logo)
|
||||
ADD_TASK(menuBackground)
|
||||
ADD_TASK(gameBackground)
|
||||
ADD_TASK2(rightHand, hand)
|
||||
}
|
||||
|
||||
void PixelManager::startFrame() const {
|
||||
window.clearScreen();
|
||||
}
|
||||
|
||||
void PixelManager::endFrame() const {
|
||||
window.finishFrame();
|
||||
}
|
||||
|
||||
unsigned PixelManager::getScreenHeight() const {
|
||||
return window.getWindowSize().getY();
|
||||
}
|
||||
|
||||
unsigned PixelManager::getScreenWidth() const {
|
||||
return window.getWindowSize().getX();
|
||||
}
|
||||
|
||||
vector<RGBAcolor>
|
||||
PixelManager::mirrorData(const vector<nsGraphics::RGBAcolor>& inPixels, unsigned rowSize) {
|
||||
vector<RGBAcolor> outPixels;
|
||||
// we reserve size so the vector doesn't dynamically grows
|
||||
outPixels.reserve(inPixels.size());
|
||||
//for each line of pixel
|
||||
for(unsigned rowOffset=0; rowOffset < inPixels.size(); rowOffset+=rowSize){
|
||||
// for each pixel of that line
|
||||
for(unsigned j=0;j<rowSize;++j) {
|
||||
// push back the pixel opposed to this one (still in the same line)
|
||||
outPixels.push_back(inPixels[rowOffset + rowSize - j - 1]);
|
||||
}
|
||||
}
|
||||
return std::move(outPixels);
|
||||
}
|
Loading…
Reference in New Issue
Block a user