From ddb70c8c85a7792f170a5f51e099ed01704789a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Valor=20Mart=C3=ADnez?= Date: Tue, 4 Oct 2022 07:09:28 +0200 Subject: [PATCH] Fallo parcial en la carga de animaciones desde streams --- source/animatedsprite.cpp | 158 ++++++++++++++++++++++++++++++++++++-- source/animatedsprite.h | 9 ++- source/balloon.cpp | 4 +- source/balloon.h | 21 ++--- source/game.cpp | 124 +++++++++++++----------------- source/game.h | 14 +++- 6 files changed, 237 insertions(+), 93 deletions(-) diff --git a/source/animatedsprite.cpp b/source/animatedsprite.cpp index 68ce500..76008aa 100644 --- a/source/animatedsprite.cpp +++ b/source/animatedsprite.cpp @@ -1,8 +1,7 @@ - #include "animatedsprite.h" // Constructor -AnimatedSprite::AnimatedSprite(LTexture *texture, SDL_Renderer *renderer, std::string file) +AnimatedSprite::AnimatedSprite(LTexture *texture, SDL_Renderer *renderer, std::string file, std::stringstream *stream) { // Copia los punteros setTexture(texture); @@ -11,7 +10,12 @@ AnimatedSprite::AnimatedSprite(LTexture *texture, SDL_Renderer *renderer, std::s // Carga las animaciones if (file != "") { - load(file); + loadFromFile(file); + } + + else if (stream) + { + loadFromStream(stream); } // Inicializa variables @@ -161,7 +165,7 @@ SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF) } // Carga la animación desde un fichero -bool AnimatedSprite::load(std::string filePath) +bool AnimatedSprite::loadFromFile(std::string filePath) { int framesPerRow = 0; int frameWidth = 0; @@ -204,14 +208,17 @@ bool AnimatedSprite::load(std::string filePath) { buffer.name = line.substr(pos + 1, line.length()); } + else if (line.substr(0, pos) == "speed") { buffer.speed = std::stoi(line.substr(pos + 1, line.length())); } + else if (line.substr(0, pos) == "loop") { buffer.loop = std::stoi(line.substr(pos + 1, line.length())); } + else if (line.substr(0, pos) == "frames") { // Se introducen los valores separados por comas en un vector @@ -221,12 +228,13 @@ bool AnimatedSprite::load(std::string filePath) while (getline(ss, tmp, ',')) { // Comprueba que el tile no sea mayor que el maximo indice permitido - const int numTile = std::stoi(tmp) > maxTiles ? 0 : std::stoi(tmp); + const int numTile = std::stoi(tmp) > maxTiles ? 0 : std::stoi(tmp); rect.x = (numTile % framesPerRow) * frameWidth; rect.y = (numTile / framesPerRow) * frameHeight; buffer.frames.push_back(rect); } } + else { printf("Warning: file %s, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str()); @@ -302,6 +310,146 @@ bool AnimatedSprite::load(std::string filePath) return success; } +// Carga la animación desde un stream +bool AnimatedSprite::loadFromStream(std::stringstream *stream) +{ + int framesPerRow = 0; + int frameWidth = 0; + int frameHeight = 0; + int maxTiles = 0; + + static int number = 0; + number++; + std::cout << "Reading stream #" << number << std::endl; + + // Indicador de éxito en la carga + bool success = true; + + std::string line; + + while (std::getline(*stream, line)) + { + std::cout << "***: "< maxTiles ? 0 : std::stoi(tmp); + rect.x = (numTile % framesPerRow) * frameWidth; + rect.y = (numTile / framesPerRow) * frameHeight; + buffer.frames.push_back(rect); + } + } + + else + { + std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl; + success = false; + } + } + } while (line != "[/animation]"); + + // Añade la animación al vector de animaciones + animation.push_back(buffer); + } + + // En caso contrario se parsea el fichero para buscar las variables y los valores + else + { + // Encuentra la posición del caracter '=' + int pos = line.find("="); + + // Procesa las dos subcadenas + if (pos != (int)line.npos) + { + if (line.substr(0, pos) == "framesPerRow") + { + framesPerRow = std::stoi(line.substr(pos + 1, line.length())); + } + + else if (line.substr(0, pos) == "frameWidth") + { + frameWidth = std::stoi(line.substr(pos + 1, line.length())); + } + + else if (line.substr(0, pos) == "frameHeight") + { + frameHeight = std::stoi(line.substr(pos + 1, line.length())); + } + + else + { + std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl; + success = false; + } + + // Normaliza valores + if (framesPerRow == 0 && frameWidth > 0) + { + framesPerRow = texture->getWidth() / frameWidth; + } + + if (maxTiles == 0 && frameWidth > 0 && frameHeight > 0) + { + const int w = texture->getWidth() / frameWidth; + const int h = texture->getHeight() / frameHeight; + maxTiles = w * h; + } + } + } + } + + // Pone un valor por defecto + setPos({0, 0, frameWidth, frameHeight}); + + std::cout << "Closing stream #" << number << std::endl; + + return success; +} + // Establece la animacion actual void AnimatedSprite::setCurrentAnimation(std::string name) { diff --git a/source/animatedsprite.h b/source/animatedsprite.h index 4776b65..2b49ec3 100644 --- a/source/animatedsprite.h +++ b/source/animatedsprite.h @@ -6,6 +6,8 @@ #include #include #include +#include + #ifndef ANIMATEDSPRITE_H #define ANIMATEDSPRITE_H @@ -29,7 +31,7 @@ private: public: // Constructor - AnimatedSprite(LTexture *texture = nullptr, SDL_Renderer *renderer = nullptr, std::string file = ""); + AnimatedSprite(LTexture *texture = nullptr, SDL_Renderer *renderer = nullptr, std::string file = "", std::stringstream *stream = nullptr); // Destructor ~AnimatedSprite(); @@ -66,7 +68,10 @@ public: int getIndex(std::string name); // Carga la animación desde un fichero - bool load(std::string filePath); + bool loadFromFile(std::string filePath); + + // Carga la animación desde un stream + bool loadFromStream(std::stringstream *stream); // Establece la animacion actual void setCurrentAnimation(std::string name = "default"); diff --git a/source/balloon.cpp b/source/balloon.cpp index 4142eb2..13fe97a 100644 --- a/source/balloon.cpp +++ b/source/balloon.cpp @@ -2,9 +2,9 @@ #include "balloon.h" // Constructor -Balloon::Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, LTexture *texture, std::string file, SDL_Renderer *renderer) +Balloon::Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, LTexture *texture, std::stringstream *stream, SDL_Renderer *renderer) { - mSprite = new AnimatedSprite(texture, renderer, file); + mSprite = new AnimatedSprite(texture, renderer, "", stream); disable(); mEnabled = true; diff --git a/source/balloon.h b/source/balloon.h index 4401f89..3cbda11 100644 --- a/source/balloon.h +++ b/source/balloon.h @@ -4,6 +4,7 @@ #include "utils.h" #include "animatedsprite.h" #include +#include #ifndef BALLOON_H #define BALLOON_H @@ -107,15 +108,15 @@ private: Uint16 mCreationCounterIni; // Valor inicial para el temporizador para controlar el estado "creandose" Uint16 mScore; // Puntos que da el globo al ser destruido Uint16 mStoppedCounter; // Contador para controlar el estado "parado" - //Uint16 mTimeToLive; // Indica el tiempo de vida que le queda al globo - Uint8 mKind; // Tipo de globo - Uint8 mMenace; // Cantidad de amenaza que genera el globo - Uint32 mCounter; // Contador interno - float mTravelY; // Distancia que ha de recorrer el globo en el eje Y antes de que se le aplique la gravedad - float mSpeed; // Velocidad a la que se mueven los globos - Uint8 mSize; // Tamaño del globo - Uint8 mPower; // Cantidad de poder que alberga el globo - bouncing mBouncing; // Contiene las variables para el efecto de rebote + // Uint16 mTimeToLive; // Indica el tiempo de vida que le queda al globo + Uint8 mKind; // Tipo de globo + Uint8 mMenace; // Cantidad de amenaza que genera el globo + Uint32 mCounter; // Contador interno + float mTravelY; // Distancia que ha de recorrer el globo en el eje Y antes de que se le aplique la gravedad + float mSpeed; // Velocidad a la que se mueven los globos + Uint8 mSize; // Tamaño del globo + Uint8 mPower; // Cantidad de poder que alberga el globo + bouncing mBouncing; // Contiene las variables para el efecto de rebote // Alinea el circulo de colisión con la posición del objeto globo void updateColliders(); @@ -140,7 +141,7 @@ private: public: // Constructor - Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, LTexture *texture, std::string file, SDL_Renderer *renderer); + Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, LTexture *texture, std::stringstream *stream, SDL_Renderer *renderer); // Destructor ~Balloon(); diff --git a/source/game.cpp b/source/game.cpp index 754c78e..287d40e 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -48,6 +48,16 @@ Game::Game(int numPlayers, int currentStage, SDL_Renderer *renderer, Screen *scr mTextureGameText = new LTexture(mRenderer, mAsset->get("game_text.png")); mTextureItems = new LTexture(mRenderer, mAsset->get("items.png")); + balloon1Animation = new std::stringstream; + balloon2Animation = new std::stringstream; + balloon3Animation = new std::stringstream; + balloon4Animation = new std::stringstream; + + loadAnimations(mAsset->get("balloon1.ani"), balloon1Animation); + loadAnimations(mAsset->get("balloon2.ani"), balloon2Animation); + loadAnimations(mAsset->get("balloon3.ani"), balloon3Animation); + loadAnimations(mAsset->get("balloon4.ani"), balloon4Animation); + mText = new Text(mAsset->get("smb2.png"), mAsset->get("smb2.txt"), mRenderer); mTextScoreBoard = new Text(mAsset->get("8bithud.png"), mAsset->get("8bithud.txt"), mRenderer); mTextBig = new Text(mAsset->get("smb2_big.png"), mAsset->get("smb2_big.txt"), mRenderer); @@ -84,12 +94,6 @@ Game::~Game() mOptions->input[0].deviceType = mOnePlayerControl; - mRenderer = nullptr; - mScreen = nullptr; - mAsset = nullptr; - mLang = nullptr; - mInput = nullptr; - for (auto player : players) { delete player; @@ -127,87 +131,45 @@ Game::~Game() balloon4Texture->unload(); delete balloon4Texture; + delete balloon1Animation; + delete balloon2Animation; + delete balloon3Animation; + delete balloon4Animation; + mTextureBullet->unload(); delete mTextureBullet; - mTextureBullet = nullptr; mTextureGameBG->unload(); delete mTextureGameBG; - mTextureGameBG = nullptr; mTextureGameText->unload(); delete mTextureGameText; - mTextureGameText = nullptr; mTextureItems->unload(); delete mTextureItems; - mTextureItems = nullptr; delete mText; - mText = nullptr; - delete mTextBig; - mTextBig = nullptr; - delete mTextScoreBoard; - mTextScoreBoard = nullptr; - delete mTextNokia2; - mTextNokia2 = nullptr; - delete mTextNokiaBig2; - mTextNokiaBig2 = nullptr; - delete mMenuGameOver; - mMenuGameOver = nullptr; - delete mMenuPause; - mMenuPause = nullptr; - delete mFade; - mFade = nullptr; - delete mEventHandler; - mEventHandler = nullptr; - delete mClouds1a; - mClouds1a = nullptr; - delete mClouds1b; - mClouds1b = nullptr; - delete mClouds2a; - mClouds2a = nullptr; - delete mClouds2b; - mClouds2b = nullptr; - delete m1000Bitmap; - m1000Bitmap = nullptr; - delete m2500Bitmap; - m2500Bitmap = nullptr; - delete m5000Bitmap; - m5000Bitmap = nullptr; - delete mSpriteBackground; - mSpriteBackground = nullptr; - delete mSpriteGetReady; - mSpriteGetReady = nullptr; - delete mSpriteGradient; - mSpriteGradient = nullptr; - delete mSpriteGrass; - mSpriteGrass = nullptr; - delete mSpritePowerMeter; - mSpritePowerMeter = nullptr; - delete mSpriteScoreBoard; - mSpriteScoreBoard = nullptr; JA_DeleteSound(mSoundBalloon); JA_DeleteSound(mSoundBullet); @@ -1400,12 +1362,12 @@ void Game::deployEnemyFormation() const Uint8 numEnemies = mStage[mCurrentStage].enemyPool->set[set]->numberOfEnemies; for (int i = 0; i < numEnemies; ++i) { - createNewBalloon(mStage[mCurrentStage].enemyPool->set[set]->init[i].x, - mStage[mCurrentStage].enemyPool->set[set]->init[i].y, - mStage[mCurrentStage].enemyPool->set[set]->init[i].kind, - mStage[mCurrentStage].enemyPool->set[set]->init[i].velX, - mEnemySpeed, - mStage[mCurrentStage].enemyPool->set[set]->init[i].creationCounter); + createBalloon(mStage[mCurrentStage].enemyPool->set[set]->init[i].x, + mStage[mCurrentStage].enemyPool->set[set]->init[i].y, + mStage[mCurrentStage].enemyPool->set[set]->init[i].kind, + mStage[mCurrentStage].enemyPool->set[set]->init[i].velX, + mEnemySpeed, + mStage[mCurrentStage].enemyPool->set[set]->init[i].creationCounter); } mEnemyDeployCounter = 300; @@ -1766,10 +1728,9 @@ void Game::renderBalloons() } // Crea un globo nuevo en el vector de globos -Uint8 Game::createNewBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 creationtimer) +Uint8 Game::createBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 creationtimer) { - const std::string file = balloonAnimation(kind); - Balloon *b = new Balloon(x, y, kind, velx, speed, creationtimer, balloonTexture(kind), file, mRenderer); + Balloon *b = new Balloon(x, y, kind, velx, speed, creationtimer, balloonTexture(kind), balloonStreamAnimation(kind), mRenderer); balloons.push_back(b); return (Uint8)(balloons.size() - 1); } @@ -1786,7 +1747,7 @@ void Game::createPowerBall() const int x[3] = {left, center, right}; const int posX = x[rand() % 3]; - Balloon *b = new Balloon(posX, posY, POWER_BALL, BALLOON_VELX_POSITIVE * (((rand() % 2) * 2) - 1), mEnemySpeed, 100, balloon4Texture, mAsset->get("balloon4.ani"), mRenderer); + Balloon *b = new Balloon(posX, posY, POWER_BALL, BALLOON_VELX_POSITIVE * (((rand() % 2) * 2) - 1), mEnemySpeed, 100, balloon4Texture, balloon4Animation, mRenderer); balloons.push_back(b); mPowerBallEnabled = true; @@ -1911,7 +1872,7 @@ void Game::popBalloon(Balloon *balloon) // En cualquier otro caso, crea dos globos de un tipo inferior default: // Balloon *b1 = new Balloon(0, balloon->getPosY(), balloon->getKind() - 1, BALLOON_VELX_NEGATIVE, mEnemySpeed, 0, mRenderer); - const int index = createNewBalloon(0, balloon->getPosY(), balloon->getKind() - 1, BALLOON_VELX_NEGATIVE, mEnemySpeed, 0); + const int index = createBalloon(0, balloon->getPosY(), balloon->getKind() - 1, BALLOON_VELX_NEGATIVE, mEnemySpeed, 0); balloons.at(index)->allignTo(balloon->getPosX() + (balloon->getWidth() / 2)); if (balloons.at(index)->getClass() == BALLOON_CLASS) { @@ -1922,7 +1883,7 @@ void Game::popBalloon(Balloon *balloon) balloons.at(index)->setVelY(BALLOON_VELX_NEGATIVE); } - const int index2 = createNewBalloon(0, balloon->getPosY(), balloon->getKind() - 1, BALLOON_VELX_POSITIVE, mEnemySpeed, 0); + const int index2 = createBalloon(0, balloon->getPosY(), balloon->getKind() - 1, BALLOON_VELX_POSITIVE, mEnemySpeed, 0); balloons.at(index2)->allignTo(balloon->getPosX() + (balloon->getWidth() / 2)); if (balloons.at(index2)->getClass() == BALLOON_CLASS) { @@ -2074,6 +2035,8 @@ Uint8 Game::countBalloons() // Obtiene la textura correspondiente en funcion del tipo LTexture *Game::balloonTexture(int kind) { + std::cout << " ********** kind: " << kind << std::endl; + if (kind == 1 || kind == 5) { return balloon1Texture; @@ -2098,29 +2061,29 @@ LTexture *Game::balloonTexture(int kind) } // Obtiene la animacion correspondiente en funcion del tipo -std::string Game::balloonAnimation(int kind) +std::stringstream *Game::balloonStreamAnimation(int kind) { if (kind == 1 || kind == 5) { - return mAsset->get("balloon1.ani"); + return balloon1Animation; } else if (kind == 2 || kind == 6) { - return mAsset->get("balloon2.ani"); + return balloon2Animation; } else if (kind == 3 || kind == 7) { - return mAsset->get("balloon3.ani"); + return balloon3Animation; } else if (kind == 4 || kind == 8 || kind == 9) { - return mAsset->get("balloon4.ani"); + return balloon4Animation; } - return mAsset->get("balloon1.ani"); + return balloon1Animation; } // Vacia el vector de globos @@ -3657,4 +3620,23 @@ void Game::checkEventHandler() } } } +} + +// Carga las animaciones +void Game::loadAnimations(std::string filePath, std::stringstream *buffer) +{ + std::ifstream file(filePath); + + if (file) + { + std::cout << "Animation loaded: " << filePath.substr(filePath.find_last_of("\\/") + 1).c_str() << std::endl; + *buffer << file.rdbuf(); + file.close(); + } + + // std::string line; + // while (std::getline(*buffer, line)) + //{ + // std::cout << line << std::endl; + // } } \ No newline at end of file diff --git a/source/game.h b/source/game.h index e68199d..23035ab 100644 --- a/source/game.h +++ b/source/game.h @@ -18,6 +18,7 @@ #include "text.h" #include "utils.h" #include "writer.h" +#include "iostream" #ifndef GAME_H #define GAME_H @@ -150,6 +151,11 @@ private: LTexture *mTextureGameText; // Textura para los sprites con textos LTexture *mTextureItems; // Textura para los items + std::stringstream *balloon1Animation; // Información para la animación de los globos + std::stringstream *balloon2Animation; // Información para la animación de los globos + std::stringstream *balloon3Animation; // Información para la animación de los globos + std::stringstream *balloon4Animation; // Información para la animación de los globos + Text *mText; // Fuente para los textos del juego Text *mTextBig; // Fuente de texto grande Text *mTextScoreBoard; // Fuente para el marcador del juego @@ -315,7 +321,7 @@ private: void renderBalloons(); // Crea un globo nuevo en el vector de globos - Uint8 createNewBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 stoppedcounter); + Uint8 createBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 stoppedcounter); // Crea una PowerBall void createPowerBall(); @@ -357,7 +363,7 @@ private: LTexture *balloonTexture(int kind); // Obtiene la animacion correspondiente en funcion del tipo - std::string balloonAnimation(int kind); + std::stringstream *balloonStreamAnimation(int kind); // Vacia el vector de globos void freeBalloons(); @@ -461,7 +467,6 @@ private: // Dibuja el fondo void renderBackground(); - // Gestiona la entrada durante el juego void checkGameInput(); @@ -504,6 +509,9 @@ private: // Comprueba si todos los jugadores han muerto bool allPlayersAreDead(); + // Carga las animaciones + void loadAnimations(std::string filePath, std::stringstream *buffer); + public: // Constructor Game(int numPlayers, int currentStage, SDL_Renderer *renderer, Screen *screen, Asset *mAsset, Lang *lang, Input *input, bool demo, options_t *options);