resource.pack

This commit is contained in:
2026-04-15 23:26:43 +02:00
parent c3534ace9c
commit 0faa605ad9
35 changed files with 1537 additions and 1851 deletions

View File

@@ -15,6 +15,7 @@
#include "input.h" // for inputs_e, Input, REPEAT_TRUE, REPEAT_FALSE
#include "item.h" // for Item, ITEM_COFFEE_MACHINE, ITEM_CLOCK
#include "jail_audio.hpp" // for JA_PlaySound, JA_DeleteSound, JA_LoadSound
#include "resource.h"
#include "lang.h" // for Lang
#include "menu.h" // for Menu
#include "movingsprite.h" // for MovingSprite
@@ -98,84 +99,19 @@ Game::~Game() {
options->input[0].deviceType = onePlayerControl;
}
// Elimina todos los objetos contenidos en vectores
// Elimina todos los objetos contenidos en vectores (jugadores, balas, etc.)
deleteAllVectorObjects();
bulletTexture->unload();
delete bulletTexture;
gameBuildingsTexture->unload();
delete gameBuildingsTexture;
gameCloudsTexture->unload();
delete gameCloudsTexture;
gameGrassTexture->unload();
delete gameGrassTexture;
gamePowerMeterTexture->unload();
delete gamePowerMeterTexture;
gameSkyColorsTexture->unload();
delete gameSkyColorsTexture;
gameTextTexture->unload();
delete gameTextTexture;
gameOverTexture->unload();
delete gameOverTexture;
gameOverEndTexture->unload();
delete gameOverEndTexture;
// Animaciones
for (auto animation : playerAnimations) {
delete animation;
}
// Las texturas, animaciones, Text, Menu, sonidos y música son propiedad
// de Resource — no se liberan aquí. Solo limpiamos nuestras vistas.
playerAnimations.clear();
for (auto animation : balloonAnimations) {
delete animation;
}
balloonAnimations.clear();
for (auto animation : itemAnimations) {
delete animation;
}
itemAnimations.clear();
// Texturas
for (auto texture : player1Textures) {
texture->unload();
delete texture;
}
player1Textures.clear();
for (auto texture : player2Textures) {
texture->unload();
delete texture;
}
player2Textures.clear();
for (auto texture : itemTextures) {
texture->unload();
delete texture;
}
itemTextures.clear();
for (auto texture : balloonTextures) {
texture->unload();
delete texture;
}
balloonTextures.clear();
delete text;
delete textBig;
delete textScoreBoard;
delete textNokia2;
delete textNokiaBig2;
delete gameOverMenu;
delete pauseMenu;
delete fade;
delete eventHandler;
delete clouds1A;
@@ -192,24 +128,6 @@ Game::~Game() {
delete powerMeterSprite;
delete gameOverSprite;
delete gameOverEndSprite;
JA_DeleteSound(balloonSound);
JA_DeleteSound(bulletSound);
JA_DeleteSound(playerCollisionSound);
JA_DeleteSound(hiScoreSound);
JA_DeleteSound(itemDropSound);
JA_DeleteSound(itemPickUpSound);
JA_DeleteSound(coffeeOutSound);
JA_DeleteSound(stageChangeSound);
JA_DeleteSound(bubble1Sound);
JA_DeleteSound(bubble2Sound);
JA_DeleteSound(bubble3Sound);
JA_DeleteSound(bubble4Sound);
JA_DeleteSound(clockSound);
JA_DeleteSound(powerBallSound);
JA_DeleteSound(coffeeMachineSound);
JA_DeleteMusic(gameMusic);
}
// Inicializa las variables necesarias para la sección 'Game'
@@ -414,186 +332,106 @@ void Game::loadMedia() {
<< "** LOADING RESOURCES FOR GAME SECTION" << std::endl;
}
// Texturas
bulletTexture = new Texture(renderer, asset->get("bullet.png"));
gameBuildingsTexture = new Texture(renderer, asset->get("game_buildings.png"));
gameCloudsTexture = new Texture(renderer, asset->get("game_clouds.png"));
gameGrassTexture = new Texture(renderer, asset->get("game_grass.png"));
gamePowerMeterTexture = new Texture(renderer, asset->get("game_power_meter.png"));
gameSkyColorsTexture = new Texture(renderer, asset->get("game_sky_colors.png"));
gameTextTexture = new Texture(renderer, asset->get("game_text.png"));
gameOverTexture = new Texture(renderer, asset->get("menu_game_over.png"));
gameOverEndTexture = new Texture(renderer, asset->get("menu_game_over_end.png"));
Resource *R = Resource::get();
// Texturas (handles compartidos — no se liberan aquí)
bulletTexture = R->getTexture("bullet.png");
gameBuildingsTexture = R->getTexture("game_buildings.png");
gameCloudsTexture = R->getTexture("game_clouds.png");
gameGrassTexture = R->getTexture("game_grass.png");
gamePowerMeterTexture = R->getTexture("game_power_meter.png");
gameSkyColorsTexture = R->getTexture("game_sky_colors.png");
gameTextTexture = R->getTexture("game_text.png");
gameOverTexture = R->getTexture("menu_game_over.png");
gameOverEndTexture = R->getTexture("menu_game_over_end.png");
// Texturas - Globos
Texture *balloon1Texture = new Texture(renderer, asset->get("balloon1.png"));
balloonTextures.push_back(balloon1Texture);
Texture *balloon2Texture = new Texture(renderer, asset->get("balloon2.png"));
balloonTextures.push_back(balloon2Texture);
Texture *balloon3Texture = new Texture(renderer, asset->get("balloon3.png"));
balloonTextures.push_back(balloon3Texture);
Texture *balloon4Texture = new Texture(renderer, asset->get("balloon4.png"));
balloonTextures.push_back(balloon4Texture);
balloonTextures.push_back(R->getTexture("balloon1.png"));
balloonTextures.push_back(R->getTexture("balloon2.png"));
balloonTextures.push_back(R->getTexture("balloon3.png"));
balloonTextures.push_back(R->getTexture("balloon4.png"));
// Texturas - Items
Texture *item1 = new Texture(renderer, asset->get("item_points1_disk.png"));
itemTextures.push_back(item1);
Texture *item2 = new Texture(renderer, asset->get("item_points2_gavina.png"));
itemTextures.push_back(item2);
Texture *item3 = new Texture(renderer, asset->get("item_points3_pacmar.png"));
itemTextures.push_back(item3);
Texture *item4 = new Texture(renderer, asset->get("item_clock.png"));
itemTextures.push_back(item4);
Texture *item5 = new Texture(renderer, asset->get("item_coffee.png"));
itemTextures.push_back(item5);
Texture *item6 = new Texture(renderer, asset->get("item_coffee_machine.png"));
itemTextures.push_back(item6);
itemTextures.push_back(R->getTexture("item_points1_disk.png"));
itemTextures.push_back(R->getTexture("item_points2_gavina.png"));
itemTextures.push_back(R->getTexture("item_points3_pacmar.png"));
itemTextures.push_back(R->getTexture("item_clock.png"));
itemTextures.push_back(R->getTexture("item_coffee.png"));
itemTextures.push_back(R->getTexture("item_coffee_machine.png"));
// Texturas - Player1
Texture *player1Head = new Texture(renderer, asset->get("player_bal1_head.png"));
player1Textures.push_back(player1Head);
Texture *player1Body = new Texture(renderer, asset->get("player_bal1_body.png"));
player1Textures.push_back(player1Body);
Texture *player1Legs = new Texture(renderer, asset->get("player_bal1_legs.png"));
player1Textures.push_back(player1Legs);
Texture *player1Death = new Texture(renderer, asset->get("player_bal1_death.png"));
player1Textures.push_back(player1Death);
Texture *player1Fire = new Texture(renderer, asset->get("player_bal1_fire.png"));
player1Textures.push_back(player1Fire);
player1Textures.push_back(R->getTexture("player_bal1_head.png"));
player1Textures.push_back(R->getTexture("player_bal1_body.png"));
player1Textures.push_back(R->getTexture("player_bal1_legs.png"));
player1Textures.push_back(R->getTexture("player_bal1_death.png"));
player1Textures.push_back(R->getTexture("player_bal1_fire.png"));
playerTextures.push_back(player1Textures);
// Texturas - Player2
Texture *player2Head = new Texture(renderer, asset->get("player_arounder_head.png"));
player2Textures.push_back(player2Head);
Texture *player2Body = new Texture(renderer, asset->get("player_arounder_body.png"));
player2Textures.push_back(player2Body);
Texture *player2Legs = new Texture(renderer, asset->get("player_arounder_legs.png"));
player2Textures.push_back(player2Legs);
Texture *player2Death = new Texture(renderer, asset->get("player_arounder_death.png"));
player2Textures.push_back(player2Death);
Texture *player2Fire = new Texture(renderer, asset->get("player_arounder_fire.png"));
player2Textures.push_back(player2Fire);
player2Textures.push_back(R->getTexture("player_arounder_head.png"));
player2Textures.push_back(R->getTexture("player_arounder_body.png"));
player2Textures.push_back(R->getTexture("player_arounder_legs.png"));
player2Textures.push_back(R->getTexture("player_arounder_death.png"));
player2Textures.push_back(R->getTexture("player_arounder_fire.png"));
playerTextures.push_back(player2Textures);
// Animaciones -- Jugador
std::vector<std::string> *playerHeadAnimation = new std::vector<std::string>;
loadAnimations(asset->get("player_head.ani"), playerHeadAnimation);
playerAnimations.push_back(playerHeadAnimation);
// Animaciones (handles a los vectores raw de Resource — no se liberan)
playerAnimations.push_back(&R->getAnimationLines("player_head.ani"));
playerAnimations.push_back(&R->getAnimationLines("player_body.ani"));
playerAnimations.push_back(&R->getAnimationLines("player_legs.ani"));
playerAnimations.push_back(&R->getAnimationLines("player_death.ani"));
playerAnimations.push_back(&R->getAnimationLines("player_fire.ani"));
std::vector<std::string> *playerBodyAnimation = new std::vector<std::string>;
loadAnimations(asset->get("player_body.ani"), playerBodyAnimation);
playerAnimations.push_back(playerBodyAnimation);
balloonAnimations.push_back(&R->getAnimationLines("balloon1.ani"));
balloonAnimations.push_back(&R->getAnimationLines("balloon2.ani"));
balloonAnimations.push_back(&R->getAnimationLines("balloon3.ani"));
balloonAnimations.push_back(&R->getAnimationLines("balloon4.ani"));
std::vector<std::string> *playerLegsAnimation = new std::vector<std::string>;
loadAnimations(asset->get("player_legs.ani"), playerLegsAnimation);
playerAnimations.push_back(playerLegsAnimation);
std::vector<std::string> *playerDeathAnimation = new std::vector<std::string>;
loadAnimations(asset->get("player_death.ani"), playerDeathAnimation);
playerAnimations.push_back(playerDeathAnimation);
std::vector<std::string> *playerFireAnimation = new std::vector<std::string>;
loadAnimations(asset->get("player_fire.ani"), playerFireAnimation);
playerAnimations.push_back(playerFireAnimation);
// Animaciones -- Globos
std::vector<std::string> *balloon1Animation = new std::vector<std::string>;
loadAnimations(asset->get("balloon1.ani"), balloon1Animation);
balloonAnimations.push_back(balloon1Animation);
std::vector<std::string> *balloon2Animation = new std::vector<std::string>;
loadAnimations(asset->get("balloon2.ani"), balloon2Animation);
balloonAnimations.push_back(balloon2Animation);
std::vector<std::string> *balloon3Animation = new std::vector<std::string>;
loadAnimations(asset->get("balloon3.ani"), balloon3Animation);
balloonAnimations.push_back(balloon3Animation);
std::vector<std::string> *balloon4Animation = new std::vector<std::string>;
loadAnimations(asset->get("balloon4.ani"), balloon4Animation);
balloonAnimations.push_back(balloon4Animation);
// Animaciones -- Items
std::vector<std::string> *item1Animation = new std::vector<std::string>;
loadAnimations(asset->get("item_points1_disk.ani"), item1Animation);
itemAnimations.push_back(item1Animation);
std::vector<std::string> *item2Animation = new std::vector<std::string>;
loadAnimations(asset->get("item_points2_gavina.ani"), item2Animation);
itemAnimations.push_back(item2Animation);
std::vector<std::string> *item3Animation = new std::vector<std::string>;
loadAnimations(asset->get("item_points3_pacmar.ani"), item3Animation);
itemAnimations.push_back(item3Animation);
std::vector<std::string> *item4Animation = new std::vector<std::string>;
loadAnimations(asset->get("item_clock.ani"), item4Animation);
itemAnimations.push_back(item4Animation);
std::vector<std::string> *item5Animation = new std::vector<std::string>;
loadAnimations(asset->get("item_coffee.ani"), item5Animation);
itemAnimations.push_back(item5Animation);
std::vector<std::string> *item6Animation = new std::vector<std::string>;
loadAnimations(asset->get("item_coffee_machine.ani"), item6Animation);
itemAnimations.push_back(item6Animation);
itemAnimations.push_back(&R->getAnimationLines("item_points1_disk.ani"));
itemAnimations.push_back(&R->getAnimationLines("item_points2_gavina.ani"));
itemAnimations.push_back(&R->getAnimationLines("item_points3_pacmar.ani"));
itemAnimations.push_back(&R->getAnimationLines("item_clock.ani"));
itemAnimations.push_back(&R->getAnimationLines("item_coffee.ani"));
itemAnimations.push_back(&R->getAnimationLines("item_coffee_machine.ani"));
// Texto
text = new Text(asset->get("smb2.png"), asset->get("smb2.txt"), renderer);
textScoreBoard = new Text(asset->get("8bithud.png"), asset->get("8bithud.txt"), renderer);
textBig = new Text(asset->get("smb2_big.png"), asset->get("smb2_big.txt"), renderer);
textNokia2 = new Text(asset->get("nokia2.png"), asset->get("nokia2.txt"), renderer);
textNokiaBig2 = new Text(asset->get("nokia_big2.png"), asset->get("nokia_big2.txt"), renderer);
text = R->getText("smb2");
textScoreBoard = R->getText("8bithud");
textBig = R->getText("smb2_big");
textNokia2 = R->getText("nokia2");
textNokiaBig2 = R->getText("nokia_big2");
// Menus
gameOverMenu = new Menu(renderer, asset, input, asset->get("gameover.men"));
gameOverMenu = R->getMenu("gameover");
gameOverMenu->setItemCaption(0, lang->getText(48));
gameOverMenu->setItemCaption(1, lang->getText(49));
const int w = text->getCharacterSize() * lang->getText(45).length();
gameOverMenu->setRectSize(w, 0);
gameOverMenu->centerMenuOnX(199);
pauseMenu = new Menu(renderer, asset, input, asset->get("pause.men"));
pauseMenu = R->getMenu("pause");
pauseMenu->setItemCaption(0, lang->getText(41));
pauseMenu->setItemCaption(1, lang->getText(46));
pauseMenu->setItemCaption(2, lang->getText(47));
// Sonidos
balloonSound = JA_LoadSound(asset->get("balloon.wav").c_str());
bubble1Sound = JA_LoadSound(asset->get("bubble1.wav").c_str());
bubble2Sound = JA_LoadSound(asset->get("bubble2.wav").c_str());
bubble3Sound = JA_LoadSound(asset->get("bubble3.wav").c_str());
bubble4Sound = JA_LoadSound(asset->get("bubble4.wav").c_str());
bulletSound = JA_LoadSound(asset->get("bullet.wav").c_str());
clockSound = JA_LoadSound(asset->get("clock.wav").c_str());
coffeeOutSound = JA_LoadSound(asset->get("coffeeout.wav").c_str());
hiScoreSound = JA_LoadSound(asset->get("hiscore.wav").c_str());
itemDropSound = JA_LoadSound(asset->get("itemdrop.wav").c_str());
itemPickUpSound = JA_LoadSound(asset->get("itempickup.wav").c_str());
playerCollisionSound = JA_LoadSound(asset->get("player_collision.wav").c_str());
powerBallSound = JA_LoadSound(asset->get("powerball.wav").c_str());
stageChangeSound = JA_LoadSound(asset->get("stage_change.wav").c_str());
coffeeMachineSound = JA_LoadSound(asset->get("title.wav").c_str());
balloonSound = R->getSound("balloon.wav");
bubble1Sound = R->getSound("bubble1.wav");
bubble2Sound = R->getSound("bubble2.wav");
bubble3Sound = R->getSound("bubble3.wav");
bubble4Sound = R->getSound("bubble4.wav");
bulletSound = R->getSound("bullet.wav");
clockSound = R->getSound("clock.wav");
coffeeOutSound = R->getSound("coffeeout.wav");
hiScoreSound = R->getSound("hiscore.wav");
itemDropSound = R->getSound("itemdrop.wav");
itemPickUpSound = R->getSound("itempickup.wav");
playerCollisionSound = R->getSound("player_collision.wav");
powerBallSound = R->getSound("powerball.wav");
stageChangeSound = R->getSound("stage_change.wav");
coffeeMachineSound = R->getSound("title.wav");
// Musicas
gameMusic = JA_LoadMusic(asset->get("playing.ogg").c_str());
gameMusic = R->getMusic("playing.ogg");
if (options->console) {
std::cout << "** RESOURCES FOR GAME SECTION LOADED" << std::endl
@@ -666,60 +504,32 @@ bool Game::loadScoreFile() {
// Carga el fichero de datos para la demo
bool Game::loadDemoFile() {
// Indicador de éxito en la carga
bool success = true;
const std::string p = asset->get("demo.bin");
const std::string filename = p.substr(p.find_last_of("\\/") + 1);
SDL_IOStream *file = SDL_IOFromFile(p.c_str(), "r+b");
// El fichero no existe
if (file == nullptr) {
if (options->console) {
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
// Lee los datos de la demo desde Resource (precargados al arrancar).
const auto &bytes = Resource::get()->getDemoBytes();
const size_t expected = sizeof(demoKeys_t) * TOTAL_DEMO_DATA;
if (bytes.size() >= expected) {
for (int i = 0; i < TOTAL_DEMO_DATA; ++i) {
memcpy(&demo.dataFile[i], bytes.data() + i * sizeof(demoKeys_t), sizeof(demoKeys_t));
}
// Creamos el fichero para escritura
file = SDL_IOFromFile(p.c_str(), "w+b");
if (file != nullptr) {
if (options->console) {
std::cout << "New file (" << filename.c_str() << ") created!" << std::endl;
}
// Inicializamos los datos
for (int i = 0; i < TOTAL_DEMO_DATA; ++i) {
demo.keys.left = 0;
demo.keys.right = 0;
demo.keys.noInput = 0;
demo.keys.fire = 0;
demo.keys.fireLeft = 0;
demo.keys.fireRight = 0;
demo.dataFile[i] = demo.keys;
SDL_WriteIO(file, &demo.dataFile[i], sizeof(demoKeys_t));
}
// Cerramos el fichero
SDL_CloseIO(file);
} else {
if (options->console) {
std::cout << "Error: Unable to create file " << filename.c_str() << std::endl;
}
success = false;
if (options->console) {
std::cout << "Demo data loaded (" << bytes.size() << " bytes)" << std::endl;
}
} else {
// Si no hay datos (bytes vacíos o tamaño inválido), inicializamos a cero.
if (options->console) {
std::cout << "Warning: demo data missing or too small, initializing to zero" << std::endl;
}
for (int i = 0; i < TOTAL_DEMO_DATA; ++i) {
demo.keys.left = 0;
demo.keys.right = 0;
demo.keys.noInput = 0;
demo.keys.fire = 0;
demo.keys.fireLeft = 0;
demo.keys.fireRight = 0;
demo.dataFile[i] = demo.keys;
}
}
// El fichero existe
else {
// Cargamos los datos
if (options->console) {
std::cout << "Reading file " << filename.c_str() << std::endl;
}
for (int i = 0; i < TOTAL_DEMO_DATA; ++i)
SDL_ReadIO(file, &demo.dataFile[i], sizeof(demoKeys_t));
// Cierra el fichero
SDL_CloseIO(file);
}
return success;
return true;
}
// Guarda el fichero de puntos
@@ -1690,9 +1500,11 @@ void Game::updateDeath() {
if ((deathCounter == 250) || (deathCounter == 200) || (deathCounter == 180) || (deathCounter == 120) || (deathCounter == 60)) {
// Hace sonar aleatoriamente uno de los 4 sonidos de burbujas
const Uint8 index = rand() % 4;
JA_Sound_t *sound[4] = {bubble1Sound, bubble2Sound, bubble3Sound, bubble4Sound};
JA_PlaySound(sound[index], 0);
if (!demo.enabled) {
const Uint8 index = rand() % 4;
JA_Sound_t *sound[4] = {bubble1Sound, bubble2Sound, bubble3Sound, bubble4Sound};
JA_PlaySound(sound[index], 0);
}
}
} else {
section->subsection = SUBSECTION_GAME_GAMEOVER;
@@ -2373,11 +2185,15 @@ void Game::killPlayer(Player *player) {
if (player->hasExtraHit()) {
player->removeExtraHit();
throwCoffee(player->getPosX() + (player->getWidth() / 2), player->getPosY() + (player->getHeight() / 2));
JA_PlaySound(coffeeOutSound);
if (!demo.enabled) {
JA_PlaySound(coffeeOutSound);
}
} else if (deathSequence.phase == DeathPhase::None) {
JA_PauseMusic();
if (!demo.enabled) {
JA_PauseMusic();
JA_PlaySound(playerCollisionSound);
}
stopAllBalloons(10);
JA_PlaySound(playerCollisionSound);
shakeScreen();
deathSequence.phase = DeathPhase::Shaking;
deathSequence.phaseStartTicks = SDL_GetTicks();
@@ -2404,13 +2220,15 @@ void Game::updateDeathSequence() {
case DeathPhase::Waiting:
// Espera 500ms antes de completar la muerte
if (SDL_GetTicks() - deathSequence.phaseStartTicks >= 500) {
JA_PlaySound(coffeeOutSound);
deathSequence.player->setAlive(false);
if (allPlayersAreDead()) {
JA_StopMusic();
} else {
JA_ResumeMusic();
if (!demo.enabled) {
JA_PlaySound(coffeeOutSound);
if (allPlayersAreDead()) {
JA_StopMusic();
} else {
JA_ResumeMusic();
}
}
deathSequence.player->setAlive(false);
deathSequence.phase = DeathPhase::Done;
deathSequence.player = nullptr;
}
@@ -2981,8 +2799,8 @@ void Game::iterate() {
// Si la música no está sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) {
// Reproduce la música
if (!gameCompleted) {
// Reproduce la música (nunca en modo demo: deja sonar la del título)
if (!gameCompleted && !demo.enabled) {
if (players[0]->isAlive()) {
JA_PlayMusic(gameMusic);
}
@@ -3445,22 +3263,6 @@ void Game::checkEvents() {
}
}
// Carga las animaciones
void Game::loadAnimations(std::string filePath, std::vector<std::string> *buffer) {
std::ifstream file(filePath);
std::string line;
if (file) {
if (options->console) {
std::cout << "Animation loaded: " << filePath.substr(filePath.find_last_of("\\/") + 1).c_str() << std::endl;
}
while (std::getline(file, line)) {
buffer->push_back(line);
}
file.close();
}
}
// Elimina todos los objetos contenidos en vectores
void Game::deleteAllVectorObjects() {
for (auto player : players) {