1145 lines
31 KiB
C++
1145 lines
31 KiB
C++
#include "common/utils.h"
|
|
#include "const.h"
|
|
#include "director.h"
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
#ifndef _WIN32
|
|
#include <pwd.h>
|
|
#endif
|
|
|
|
// Constructor
|
|
Director::Director(int argc, char *argv[])
|
|
{
|
|
// Inicializa variables
|
|
section = new section_t();
|
|
#ifdef RECORDING
|
|
section->name = SECTION_PROG_GAME;
|
|
section->subsection = SUBSECTION_GAME_PLAY_1P;
|
|
#else
|
|
section->name = SECTION_PROG_LOGO;
|
|
#endif
|
|
|
|
// Comprueba los parametros del programa
|
|
checkProgramArguments(argc, argv);
|
|
|
|
// Crea la carpeta del sistema donde guardar datos
|
|
createSystemFolder("jailgames");
|
|
createSystemFolder("jailgames/coffee_crisis_arcade_edition");
|
|
|
|
// Inicializa las opciones del programa
|
|
initOptions();
|
|
|
|
// Crea el objeto que controla los ficheros de recursos
|
|
asset = new Asset(executablePath);
|
|
asset->setVerbose(options->console);
|
|
|
|
// Si falta algún fichero no inicia el programa
|
|
if (!setFileList())
|
|
{
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
// Carga los parametros para configurar el juego
|
|
loadParams();
|
|
|
|
// Carga el fichero de configuración
|
|
loadConfigFile();
|
|
|
|
// Inicializa SDL
|
|
initSDL();
|
|
|
|
// Inicializa JailAudio
|
|
initJailAudio();
|
|
|
|
// Crea los objetos
|
|
lang = new Lang(asset);
|
|
lang->setLang(options->game.language);
|
|
|
|
input = new Input(asset->get("gamecontrollerdb.txt"));
|
|
initInput();
|
|
|
|
screen = new Screen(window, renderer, asset, input, options);
|
|
|
|
// Carga los sonidos del juego
|
|
loadSounds();
|
|
|
|
// Carga las musicas del juego
|
|
loadMusics();
|
|
}
|
|
|
|
Director::~Director()
|
|
{
|
|
saveConfigFile();
|
|
|
|
delete asset;
|
|
delete input;
|
|
delete screen;
|
|
delete lang;
|
|
delete options;
|
|
delete param;
|
|
delete section;
|
|
|
|
deleteSounds();
|
|
deleteMusics();
|
|
|
|
SDL_DestroyRenderer(renderer);
|
|
SDL_DestroyWindow(window);
|
|
|
|
SDL_Quit();
|
|
}
|
|
|
|
// Inicializa el objeto input
|
|
void Director::initInput()
|
|
{
|
|
// Establece si ha de mostrar mensajes
|
|
#ifdef VERBOSE
|
|
input->setVerbose(true);
|
|
#else
|
|
input->setVerbose(options->console);
|
|
#endif
|
|
// Busca si hay mandos conectados
|
|
input->discoverGameControllers();
|
|
|
|
// Teclado - Movimiento del jugador
|
|
input->bindKey(input_up, SDL_SCANCODE_UP);
|
|
input->bindKey(input_down, SDL_SCANCODE_DOWN);
|
|
input->bindKey(input_left, SDL_SCANCODE_LEFT);
|
|
input->bindKey(input_right, SDL_SCANCODE_RIGHT);
|
|
input->bindKey(input_fire_left, SDL_SCANCODE_Q);
|
|
input->bindKey(input_fire_center, SDL_SCANCODE_W);
|
|
input->bindKey(input_fire_right, SDL_SCANCODE_E);
|
|
input->bindKey(input_start, SDL_SCANCODE_RETURN);
|
|
|
|
// Teclado - Otros
|
|
input->bindKey(input_accept, SDL_SCANCODE_RETURN);
|
|
input->bindKey(input_cancel, SDL_SCANCODE_ESCAPE);
|
|
input->bindKey(input_pause, SDL_SCANCODE_P);
|
|
input->bindKey(input_exit, SDL_SCANCODE_ESCAPE);
|
|
input->bindKey(input_window_dec_size, SDL_SCANCODE_F1);
|
|
input->bindKey(input_window_inc_size, SDL_SCANCODE_F2);
|
|
input->bindKey(input_window_fullscreen, SDL_SCANCODE_F3);
|
|
input->bindKey(input_video_shaders, SDL_SCANCODE_F4);
|
|
input->bindKey(input_mute, SDL_SCANCODE_F5);
|
|
input->bindKey(input_reset, SDL_SCANCODE_F10);
|
|
|
|
const int numGamePads = input->getNumControllers();
|
|
for (int i = 0; i < numGamePads; ++i)
|
|
{
|
|
// Mando - Movimiento del jugador
|
|
input->bindGameControllerButton(i, input_up, SDL_CONTROLLER_BUTTON_DPAD_UP);
|
|
input->bindGameControllerButton(i, input_down, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
|
|
input->bindGameControllerButton(i, input_left, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
|
|
input->bindGameControllerButton(i, input_right, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
|
|
input->bindGameControllerButton(i, input_fire_left, SDL_CONTROLLER_BUTTON_X);
|
|
input->bindGameControllerButton(i, input_fire_center, SDL_CONTROLLER_BUTTON_Y);
|
|
input->bindGameControllerButton(i, input_fire_right, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
|
|
input->bindGameControllerButton(i, input_start, SDL_CONTROLLER_BUTTON_START);
|
|
|
|
// Mando - Otros
|
|
input->bindGameControllerButton(i, input_accept, SDL_CONTROLLER_BUTTON_START);
|
|
input->bindGameControllerButton(i, input_cancel, SDL_CONTROLLER_BUTTON_A);
|
|
input->bindGameControllerButton(i, input_pause, SDL_CONTROLLER_BUTTON_B);
|
|
input->bindGameControllerButton(i, input_exit, SDL_CONTROLLER_BUTTON_BACK);
|
|
}
|
|
|
|
// Comprueba si ha de modificar las asignaciones por las que hay en las opciones en caso de coincidir el nombre del mando
|
|
for (int i = 0; i < numGamePads; ++i)
|
|
for (int index = 0; index < (int)options->controller.size(); ++index)
|
|
if (input->getControllerName(i) == options->controller[index].name)
|
|
for (int j = 0; j < (int)options->controller[index].inputs.size(); ++j)
|
|
{
|
|
input->bindGameControllerButton(i, options->controller[index].inputs[j], options->controller[index].buttons[j]);
|
|
}
|
|
|
|
// Modifica las opciones para colocar los valores asignados
|
|
for (int index = 0; index < numGamePads; ++index)
|
|
{
|
|
options->controller[index].name = input->getControllerName(index);
|
|
for (int j = 0; j < (int)options->controller[index].inputs.size(); ++j)
|
|
{
|
|
options->controller[index].buttons[j] = input->getControllerBinding(index, options->controller[index].inputs[j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Inicializa JailAudio
|
|
void Director::initJailAudio()
|
|
{
|
|
JA_Init(48000, AUDIO_S16, 2);
|
|
JA_EnableMusic(options->audio.music.enabled);
|
|
JA_EnableSound(options->audio.sound.enabled);
|
|
JA_SetMusicVolume(options->audio.music.volume);
|
|
JA_SetSoundVolume(options->audio.sound.volume);
|
|
}
|
|
|
|
// Arranca SDL y crea la ventana
|
|
bool Director::initSDL()
|
|
{
|
|
// Indicador de éxito
|
|
bool success = true;
|
|
|
|
// Inicializa SDL
|
|
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
|
|
{
|
|
if (options->console)
|
|
{
|
|
std::cout << "SDL could not initialize!\nSDL Error: " << SDL_GetError() << std::endl;
|
|
}
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
// Inicia el generador de numeros aleatorios
|
|
std::srand(static_cast<unsigned int>(SDL_GetTicks()));
|
|
|
|
// Establece el filtro de la textura
|
|
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(options->video.filter).c_str()))
|
|
{
|
|
if (options->console)
|
|
{
|
|
std::cout << "Warning: texture filtering not enabled!\n";
|
|
}
|
|
}
|
|
#ifndef NO_SHADERS
|
|
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"))
|
|
{
|
|
if (options->console)
|
|
{
|
|
std::cout << "Warning: opengl not enabled!\n";
|
|
}
|
|
}
|
|
#endif
|
|
// Crea la ventana
|
|
int incW = 0;
|
|
int incH = 0;
|
|
if (options->video.border.enabled)
|
|
{
|
|
incW = options->video.border.width * 2;
|
|
incH = options->video.border.height * 2;
|
|
}
|
|
window = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (param->gameWidth + incW) * options->video.window.size, (param->gameHeight + incH) * options->video.window.size, SDL_WINDOW_HIDDEN);
|
|
if (window == nullptr)
|
|
{
|
|
if (options->console)
|
|
{
|
|
std::cout << "Window could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
|
}
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
// Crea un renderizador para la ventana. El vsync se activa en funcion de las opciones
|
|
Uint32 flags = 0;
|
|
if (options->video.vSync)
|
|
{
|
|
flags = flags | SDL_RENDERER_PRESENTVSYNC;
|
|
}
|
|
#ifndef NO_SHADERS
|
|
// La aceleración se activa según el define
|
|
flags = flags | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
|
|
#endif
|
|
renderer = SDL_CreateRenderer(window, -1, flags);
|
|
|
|
if (renderer == nullptr)
|
|
{
|
|
if (options->console)
|
|
{
|
|
std::cout << "Renderer could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
|
}
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
// Inicializa el color de renderizado
|
|
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
|
|
|
|
// Establece el tamaño del buffer de renderizado
|
|
SDL_RenderSetLogicalSize(renderer, param->gameWidth, param->gameHeight);
|
|
|
|
// Establece el modo de mezcla
|
|
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (options->console)
|
|
{
|
|
std::cout << std::endl;
|
|
}
|
|
return success;
|
|
}
|
|
|
|
// Crea el indice de ficheros
|
|
bool Director::setFileList()
|
|
{
|
|
#ifdef MACOS_BUNDLE
|
|
const std::string prefix = "/../Resources";
|
|
#else
|
|
const std::string prefix = "";
|
|
#endif
|
|
|
|
// Ficheros de configuración
|
|
asset->add(systemFolder + "/config.txt", t_data, false, true);
|
|
asset->add(systemFolder + "/score.bin", t_data, false, true);
|
|
asset->add(prefix + "/data/config/param.txt", t_data);
|
|
asset->add(prefix + "/data/config/demo1.bin", t_data);
|
|
asset->add(prefix + "/data/config/demo2.bin", t_data);
|
|
asset->add(prefix + "/data/config/gamecontrollerdb.txt", t_data);
|
|
|
|
// Notificaciones
|
|
asset->add(prefix + "/data/notification/notify.png", t_bitmap);
|
|
|
|
// Musicas
|
|
asset->add(prefix + "/data/music/intro.ogg", t_music);
|
|
asset->add(prefix + "/data/music/playing.ogg", t_music);
|
|
asset->add(prefix + "/data/music/title.ogg", t_music);
|
|
|
|
// Sonidos
|
|
asset->add(prefix + "/data/sound/balloon.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/bubble1.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/bubble2.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/bubble3.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/bubble4.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/bullet.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/coffeeout.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/hiscore.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/itemdrop.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/itempickup.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/player_collision.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/stage_change.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/title.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/clock.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/powerball.wav", t_sound);
|
|
asset->add(prefix + "/data/sound/notify.wav", t_sound);
|
|
|
|
// Shaders
|
|
asset->add(prefix + "/data/shaders/crtpi.glsl", t_data);
|
|
|
|
// Texturas
|
|
asset->add(prefix + "/data/gfx/balloon1.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/balloon1.ani", t_animation);
|
|
asset->add(prefix + "/data/gfx/balloon2.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/balloon2.ani", t_animation);
|
|
asset->add(prefix + "/data/gfx/balloon3.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/balloon3.ani", t_animation);
|
|
asset->add(prefix + "/data/gfx/balloon4.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/balloon4.ani", t_animation);
|
|
|
|
asset->add(prefix + "/data/gfx/explosion1.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/explosion1.ani", t_animation);
|
|
asset->add(prefix + "/data/gfx/explosion2.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/explosion2.ani", t_animation);
|
|
asset->add(prefix + "/data/gfx/explosion3.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/explosion3.ani", t_animation);
|
|
asset->add(prefix + "/data/gfx/explosion4.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/explosion4.ani", t_animation);
|
|
|
|
asset->add(prefix + "/data/gfx/powerball.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/powerball.ani", t_animation);
|
|
|
|
asset->add(prefix + "/data/gfx/bullet.png", t_bitmap);
|
|
|
|
asset->add(prefix + "/data/gfx/game_buildings.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/game_clouds1.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/game_clouds2.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/game_grass.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/game_power_meter.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/game_sky_colors.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/game_text.png", t_bitmap);
|
|
|
|
asset->add(prefix + "/data/gfx/intro.png", t_bitmap);
|
|
|
|
asset->add(prefix + "/data/gfx/logo_jailgames.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/logo_jailgames_mini.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/logo_since_1998.png", t_bitmap);
|
|
|
|
asset->add(prefix + "/data/gfx/item_points1_disk.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/item_points1_disk.ani", t_animation);
|
|
asset->add(prefix + "/data/gfx/item_points2_gavina.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/item_points2_gavina.ani", t_animation);
|
|
asset->add(prefix + "/data/gfx/item_points3_pacmar.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/item_points3_pacmar.ani", t_animation);
|
|
asset->add(prefix + "/data/gfx/item_clock.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/item_clock.ani", t_animation);
|
|
asset->add(prefix + "/data/gfx/item_coffee.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/item_coffee.ani", t_animation);
|
|
asset->add(prefix + "/data/gfx/item_coffee_machine.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/item_coffee_machine.ani", t_animation);
|
|
|
|
asset->add(prefix + "/data/gfx/title_bg_tile.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/title_coffee.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/title_crisis.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/title_arcade_edition.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/title_dust.png", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/title_dust.ani", t_animation);
|
|
|
|
asset->add(prefix + "/data/gfx/player1.gif", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/player1_pal1.gif", t_palette);
|
|
asset->add(prefix + "/data/gfx/player1_pal2.gif", t_palette);
|
|
asset->add(prefix + "/data/gfx/player1_pal3.gif", t_palette);
|
|
|
|
asset->add(prefix + "/data/gfx/player2.gif", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/player2_pal1.gif", t_palette);
|
|
asset->add(prefix + "/data/gfx/player2_pal2.gif", t_palette);
|
|
asset->add(prefix + "/data/gfx/player2_pal3.gif", t_palette);
|
|
|
|
asset->add(prefix + "/data/gfx/player.ani", t_animation);
|
|
|
|
asset->add(prefix + "/data/gfx/player_power.gif", t_bitmap);
|
|
asset->add(prefix + "/data/gfx/player_power_pal.gif", t_palette);
|
|
asset->add(prefix + "/data/gfx/player_power.ani", t_animation);
|
|
|
|
// Fuentes de texto
|
|
asset->add(prefix + "/data/font/8bithud.png", t_font);
|
|
asset->add(prefix + "/data/font/8bithud.txt", t_font);
|
|
asset->add(prefix + "/data/font/nokia.png", t_font);
|
|
asset->add(prefix + "/data/font/nokia_big2.png", t_font);
|
|
asset->add(prefix + "/data/font/nokia.txt", t_font);
|
|
asset->add(prefix + "/data/font/nokia2.png", t_font);
|
|
asset->add(prefix + "/data/font/nokia2.txt", t_font);
|
|
asset->add(prefix + "/data/font/nokia_big2.txt", t_font);
|
|
asset->add(prefix + "/data/font/smb2_big.png", t_font);
|
|
asset->add(prefix + "/data/font/smb2_big.txt", t_font);
|
|
asset->add(prefix + "/data/font/smb2.gif", t_font);
|
|
asset->add(prefix + "/data/font/smb2_pal1.gif", t_palette);
|
|
asset->add(prefix + "/data/font/smb2.txt", t_font);
|
|
|
|
// Textos
|
|
asset->add(prefix + "/data/lang/es_ES.txt", t_lang);
|
|
asset->add(prefix + "/data/lang/en_UK.txt", t_lang);
|
|
asset->add(prefix + "/data/lang/ba_BA.txt", t_lang);
|
|
|
|
return asset->check();
|
|
}
|
|
|
|
// Carga los parametros para configurar el juego
|
|
void Director::loadParams()
|
|
{
|
|
param = new param_t;
|
|
|
|
loadParam(param, asset->get("param.txt"));
|
|
|
|
// Modifica las opciones desde el fichero de parametros
|
|
options->game.autofire = param->autofire;
|
|
options->video.window.width = options->video.window.size * param->gameWidth;
|
|
options->video.window.height = options->video.window.size * param->gameHeight;
|
|
options->video.gameWidth = param->gameWidth;
|
|
options->video.gameHeight = param->gameHeight;
|
|
}
|
|
|
|
// Inicializa las opciones del programa
|
|
void Director::initOptions()
|
|
{
|
|
// Crea el puntero a la estructura de opciones
|
|
options = new options_t;
|
|
|
|
// Pone unos valores por defecto para las opciones
|
|
|
|
// Opciones varias
|
|
#ifdef VERBOSE
|
|
options->console = true;
|
|
#else
|
|
options->console = false;
|
|
#endif
|
|
|
|
// Opciones de video
|
|
options->video.mode = 0;
|
|
options->video.window.size = 3;
|
|
options->video.filter = FILTER_NEAREST;
|
|
options->video.vSync = true;
|
|
options->video.integerScale = true;
|
|
options->video.keepAspect = true;
|
|
options->video.border.width = 0;
|
|
options->video.border.height = 0;
|
|
options->video.border.enabled = false;
|
|
options->video.shaders = true;
|
|
|
|
// Opciones de las notificaciones
|
|
options->notification.posV = pos_top;
|
|
options->notification.posH = pos_left;
|
|
options->notification.sound = true;
|
|
options->notification.color = {48, 48, 48};
|
|
|
|
// Opciones de audio
|
|
options->audio.music.enabled = true;
|
|
options->audio.music.volume = 128;
|
|
options->audio.sound.enabled = true;
|
|
options->audio.sound.volume = 64;
|
|
|
|
// Opciones de juego
|
|
options->game.difficulty = DIFFICULTY_NORMAL;
|
|
options->game.language = ba_BA;
|
|
ManageHiScoreTable *m = new ManageHiScoreTable(&options->game.hiScoreTable);
|
|
m->clear();
|
|
delete m;
|
|
|
|
// Opciones de control
|
|
options->controller.clear();
|
|
op_controller_t c;
|
|
|
|
const int numPlayers = 2;
|
|
for (int index = 0; index < numPlayers; ++index)
|
|
{
|
|
c.index = index;
|
|
c.deviceType = INPUT_USE_GAMECONTROLLER;
|
|
c.name = "NO NAME";
|
|
|
|
c.inputs.clear();
|
|
c.inputs.push_back(input_fire_left);
|
|
c.inputs.push_back(input_fire_center);
|
|
c.inputs.push_back(input_fire_right);
|
|
c.inputs.push_back(input_start);
|
|
c.inputs.push_back(input_exit);
|
|
|
|
c.buttons.clear();
|
|
c.buttons.push_back(SDL_CONTROLLER_BUTTON_X);
|
|
c.buttons.push_back(SDL_CONTROLLER_BUTTON_Y);
|
|
c.buttons.push_back(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
|
|
c.buttons.push_back(SDL_CONTROLLER_BUTTON_START);
|
|
c.buttons.push_back(SDL_CONTROLLER_BUTTON_BACK);
|
|
|
|
options->controller.push_back(c);
|
|
}
|
|
options->controller[0].deviceType = INPUT_USE_ANY; // El primer jugador puede usar tanto el teclado como el primer mando
|
|
}
|
|
|
|
// Comprueba los parametros del programa
|
|
void Director::checkProgramArguments(int argc, char *argv[])
|
|
{
|
|
// Establece la ruta del programa
|
|
executablePath = argv[0];
|
|
|
|
// Comprueba el resto de parametros
|
|
for (int i = 1; i < argc; ++i)
|
|
{
|
|
if (strcmp(argv[i], "--console") == 0)
|
|
{
|
|
options->console = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Crea la carpeta del sistema donde guardar datos
|
|
void Director::createSystemFolder(std::string folder)
|
|
{
|
|
#ifdef _WIN32
|
|
systemFolder = std::string(getenv("APPDATA")) + "/" + folder;
|
|
#elif __APPLE__
|
|
struct passwd *pw = getpwuid(getuid());
|
|
const char *homedir = pw->pw_dir;
|
|
systemFolder = std::string(homedir) + "/Library/Application Support" + "/" + folder;
|
|
#elif __linux__
|
|
struct passwd *pw = getpwuid(getuid());
|
|
const char *homedir = pw->pw_dir;
|
|
systemFolder = std::string(homedir) + "/." + folder;
|
|
#endif
|
|
|
|
struct stat st = {0};
|
|
if (stat(systemFolder.c_str(), &st) == -1)
|
|
{
|
|
errno = 0;
|
|
#ifdef _WIN32
|
|
int ret = mkdir(systemFolder.c_str());
|
|
#else
|
|
int ret = mkdir(systemFolder.c_str(), S_IRWXU);
|
|
#endif
|
|
|
|
if (ret == -1)
|
|
{
|
|
switch (errno)
|
|
{
|
|
case EACCES:
|
|
printf("the parent directory does not allow write");
|
|
exit(EXIT_FAILURE);
|
|
|
|
case EEXIST:
|
|
printf("pathname already exists");
|
|
exit(EXIT_FAILURE);
|
|
|
|
case ENAMETOOLONG:
|
|
printf("pathname is too long");
|
|
exit(EXIT_FAILURE);
|
|
|
|
default:
|
|
perror("mkdir");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Carga el fichero de configuración
|
|
bool Director::loadConfigFile()
|
|
{
|
|
// Indicador de éxito en la carga
|
|
bool success = true;
|
|
|
|
// Variables para manejar el fichero
|
|
const std::string filePath = "config.txt";
|
|
std::string line;
|
|
std::ifstream file(asset->get(filePath));
|
|
|
|
// Si el fichero se puede abrir
|
|
if (file.good())
|
|
{
|
|
// Procesa el fichero linea a linea
|
|
if (options->console)
|
|
{
|
|
std::cout << "Reading file " << filePath << std::endl;
|
|
}
|
|
while (std::getline(file, line))
|
|
{
|
|
// Comprueba que la linea no sea un comentario
|
|
if (line.substr(0, 1) != "#")
|
|
{
|
|
// Encuentra la posición del caracter '='
|
|
int pos = line.find("=");
|
|
// Procesa las dos subcadenas
|
|
if (!setOptions(options, line.substr(0, pos), line.substr(pos + 1, line.length())))
|
|
{
|
|
if (options->console)
|
|
{
|
|
std::cout << "Warning: file " << filePath << std::endl;
|
|
std::cout << "Unknown parameter " << line.substr(0, pos).c_str() << std::endl;
|
|
}
|
|
success = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cierra el fichero
|
|
if (options->console)
|
|
{
|
|
std::cout << "Closing file " << filePath << std::endl;
|
|
}
|
|
file.close();
|
|
}
|
|
|
|
// El fichero no existe
|
|
else
|
|
{ // Crea el fichero con los valores por defecto
|
|
saveConfigFile();
|
|
}
|
|
|
|
// Normaliza los valores
|
|
const bool a = options->video.mode == 0;
|
|
const bool b = options->video.mode == SDL_WINDOW_FULLSCREEN;
|
|
const bool c = options->video.mode == SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
if (!(a || b || c))
|
|
{
|
|
options->video.mode = 0;
|
|
}
|
|
|
|
if (options->video.window.size < 1 || options->video.window.size > 4)
|
|
{
|
|
options->video.window.size = 3;
|
|
}
|
|
|
|
if (options->game.language < 0 || options->game.language > MAX_LANGUAGES)
|
|
{
|
|
options->game.language = en_UK;
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Guarda el fichero de configuración
|
|
bool Director::saveConfigFile()
|
|
{
|
|
bool success = true;
|
|
|
|
// Crea y abre el fichero de texto
|
|
std::ofstream file(asset->get("config.txt"));
|
|
|
|
if (file.good())
|
|
{
|
|
if (options->console)
|
|
{
|
|
std::cout << asset->get("config.txt") << " open for writing" << std::endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (options->console)
|
|
{
|
|
std::cout << asset->get("config.txt") << " can't be opened" << std::endl;
|
|
}
|
|
}
|
|
|
|
// Opciones de video
|
|
file << "## VIDEO\n";
|
|
file << "## video.mode [0: window, 1: full screen]\n";
|
|
file << "## video.filter [0: nearest, 1: lineal]\n";
|
|
file << "\n";
|
|
|
|
if (options->video.mode == VIDEO_MODE_WINDOW)
|
|
{
|
|
file << "video.mode=0\n";
|
|
}
|
|
|
|
else if (options->video.mode == VIDEO_MODE_FULLSCREEN)
|
|
{
|
|
file << "video.mode=1\n";
|
|
}
|
|
|
|
file << "video.window.size=" + std::to_string(options->video.window.size) + "\n";
|
|
|
|
options->video.filter == FILTER_NEAREST ? file << "video.filter=0\n" : file << "video.filter=1\n";
|
|
|
|
file << "video.shaders=" + boolToString(options->video.shaders) + "\n";
|
|
file << "video.vSync=" + boolToString(options->video.vSync) + "\n";
|
|
file << "video.integerScale=" + boolToString(options->video.integerScale) + "\n";
|
|
file << "video.keepAspect=" + boolToString(options->video.keepAspect) + "\n";
|
|
file << "video.border.enabled=" + boolToString(options->video.border.enabled) + "\n";
|
|
file << "video.border.width=" + std::to_string(options->video.border.width) + "\n";
|
|
file << "video.border.height=" + std::to_string(options->video.border.height) + "\n";
|
|
|
|
// Opciones de notificaciones
|
|
file << "\n\n## NOTIFICATION\n";
|
|
file << "## notification.posV [pos_top | pos_bottom]\n";
|
|
file << "## notification.posH [pos_left | pos_middle | pos_right]\n";
|
|
file << "\n";
|
|
|
|
if (options->notification.posV == pos_top)
|
|
{
|
|
file << "notification.posV=pos_top\n";
|
|
}
|
|
|
|
else
|
|
{
|
|
file << "notification.posV=pos_bottom\n";
|
|
}
|
|
|
|
if (options->notification.posH == pos_left)
|
|
{
|
|
file << "notification.posH=pos_left\n";
|
|
}
|
|
|
|
else if (options->notification.posH == pos_middle)
|
|
{
|
|
file << "notification.posH=pos_middle\n";
|
|
}
|
|
|
|
else
|
|
{
|
|
file << "notification.posH=pos_right\n";
|
|
}
|
|
|
|
file << "notification.sound=" + boolToString(options->notification.sound) + "\n";
|
|
|
|
// Opciones de audio
|
|
file << "\n\n## AUDIO\n";
|
|
file << "## volume [0 .. 128]\n";
|
|
file << "\n";
|
|
|
|
file << "audio.music.enabled=" + boolToString(options->audio.music.enabled) + "\n";
|
|
file << "audio.music.volume=" + std::to_string(options->audio.music.volume) + "\n";
|
|
file << "audio.sound.enabled=" + boolToString(options->audio.sound.enabled) + "\n";
|
|
file << "audio.sound.volume=" + std::to_string(options->audio.sound.volume) + "\n";
|
|
|
|
// Opciones del juego
|
|
file << "\n\n## GAME\n";
|
|
file << "## game.language [0: spanish, 1: valencian, 2: english]\n";
|
|
file << "## game.difficulty [0: easy, 1: normal, 2: hard]\n";
|
|
file << "\n";
|
|
|
|
file << "game.language=" + std::to_string(options->game.language) + "\n";
|
|
file << "game.difficulty=" + std::to_string(options->game.difficulty) + "\n";
|
|
|
|
// Opciones de mandos
|
|
file << "\n\n## CONTROLLERS\n";
|
|
file << "\n";
|
|
|
|
const int numPlayers = 2;
|
|
for (int index = 0; index < numPlayers; ++index)
|
|
{
|
|
const std::string joyIndex = std::to_string(index + 1);
|
|
file << "controller" + joyIndex + ".name=" + options->controller[index].name + "\n";
|
|
file << "controller" + joyIndex + ".inputs.fire_left=" + std::to_string((int)options->controller[index].buttons[0]) + "\n";
|
|
file << "controller" + joyIndex + ".inputs.fire_center=" + std::to_string((int)options->controller[index].buttons[1]) + "\n";
|
|
file << "controller" + joyIndex + ".inputs.fire_right=" + std::to_string((int)options->controller[index].buttons[2]) + "\n";
|
|
file << "controller" + joyIndex + ".inputs.fire_start=" + std::to_string((int)options->controller[index].buttons[3]) + "\n";
|
|
file << "controller" + joyIndex + ".inputs.fire_exit=" + std::to_string((int)options->controller[index].buttons[4]) + "\n";
|
|
|
|
if (index < numPlayers - 1)
|
|
{
|
|
file << "\n";
|
|
}
|
|
}
|
|
|
|
// Cierra el fichero
|
|
file.close();
|
|
|
|
return success;
|
|
}
|
|
|
|
// Carga los sonidos del juego
|
|
void Director::loadSounds()
|
|
{
|
|
// Obtiene la lista con las rutas a los ficheros de sonidos
|
|
std::vector<std::string> list = asset->getListByType(t_sound);
|
|
sounds.clear();
|
|
|
|
for (auto l : list)
|
|
{
|
|
const size_t lastIndex = l.find_last_of("/") + 1;
|
|
const std::string name = l.substr(lastIndex, std::string::npos);
|
|
sound_file_t temp;
|
|
temp.name = name; // Añade el nombre del fichero
|
|
temp.file = JA_LoadSound(l.c_str()); // Carga el fichero de audio
|
|
sounds.push_back(temp);
|
|
}
|
|
}
|
|
|
|
// Carga las musicas del juego
|
|
void Director::loadMusics()
|
|
{
|
|
// Obtiene la lista con las rutas a los ficheros musicales
|
|
std::vector<std::string> list = asset->getListByType(t_music);
|
|
musics.clear();
|
|
|
|
for (auto l : list)
|
|
{
|
|
const size_t lastIndex = l.find_last_of("/") + 1;
|
|
const std::string name = l.substr(lastIndex, std::string::npos);
|
|
music_file_t temp;
|
|
temp.name = name; // Añade el nombre del fichero
|
|
temp.file = JA_LoadMusic(l.c_str()); // Carga el fichero de audio
|
|
musics.push_back(temp);
|
|
}
|
|
}
|
|
|
|
// Descarga los sonidos del juego
|
|
void Director::deleteSounds()
|
|
{
|
|
for (auto s : sounds)
|
|
{
|
|
JA_DeleteSound(s.file);
|
|
}
|
|
sounds.clear();
|
|
}
|
|
|
|
// Descarga las músicas del juego
|
|
void Director::deleteMusics()
|
|
{
|
|
for (auto m : musics)
|
|
{
|
|
JA_DeleteMusic(m.file);
|
|
}
|
|
musics.clear();
|
|
}
|
|
|
|
// Ejecuta la seccion de juego con el logo
|
|
void Director::runLogo()
|
|
{
|
|
logo = new Logo(renderer, screen, asset, input, param, section);
|
|
logo->run();
|
|
delete logo;
|
|
}
|
|
|
|
// Ejecuta la seccion de juego de la introducción
|
|
void Director::runIntro()
|
|
{
|
|
intro = new Intro(renderer, screen, asset, input, lang, param, section, getMusic(musics, "intro.ogg"));
|
|
intro->run();
|
|
delete intro;
|
|
}
|
|
|
|
// Ejecuta la seccion de juego con el titulo y los menus
|
|
void Director::runTitle()
|
|
{
|
|
title = new Title(renderer, screen, input, asset, options, lang, param, section, getMusic(musics, "title.ogg"));
|
|
title->run();
|
|
delete title;
|
|
}
|
|
|
|
// Ejecuta la seccion de juego donde se juega
|
|
void Director::runGame()
|
|
{
|
|
const int playerID = section->subsection == SUBSECTION_GAME_PLAY_1P ? 1 : 2;
|
|
game = new Game(playerID, 0, renderer, screen, asset, lang, input, false, param, options, section, getMusic(musics, "playing.ogg"));
|
|
game->run();
|
|
delete game;
|
|
}
|
|
|
|
// Ejecuta la parte donde se muestra la tabla de puntuaciones
|
|
void Director::runHiScoreTable()
|
|
{
|
|
hiScoreTable = new HiScoreTable(renderer, screen, asset, input, lang, param, options, section);
|
|
hiScoreTable->run();
|
|
delete hiScoreTable;
|
|
}
|
|
|
|
// Ejecuta la parte donde se muestran las instrucciones
|
|
void Director::runInstructions()
|
|
{
|
|
instructions = new Instructions(renderer, screen, asset, input, lang, param, section);
|
|
instructions->run();
|
|
delete instructions;
|
|
}
|
|
|
|
// Ejecuta el juego en modo demo
|
|
void Director::runDemoGame()
|
|
{
|
|
const int playerID = (rand() % 2) + 1;
|
|
demoGame = new Game(playerID, 0, renderer, screen, asset, lang, input, true, param, options, section, nullptr);
|
|
demoGame->run();
|
|
delete demoGame;
|
|
}
|
|
|
|
void Director::run()
|
|
{
|
|
// Bucle principal
|
|
while (section->name != SECTION_PROG_QUIT)
|
|
{
|
|
switch (section->name)
|
|
{
|
|
case SECTION_PROG_LOGO:
|
|
runLogo();
|
|
break;
|
|
|
|
case SECTION_PROG_INTRO:
|
|
runIntro();
|
|
break;
|
|
|
|
case SECTION_PROG_TITLE:
|
|
runTitle();
|
|
break;
|
|
|
|
case SECTION_PROG_GAME:
|
|
runGame();
|
|
break;
|
|
|
|
case SECTION_PROG_HI_SCORE_TABLE:
|
|
runHiScoreTable();
|
|
break;
|
|
|
|
case SECTION_PROG_GAME_DEMO:
|
|
runDemoGame();
|
|
break;
|
|
|
|
case SECTION_PROG_INSTRUCTIONS:
|
|
runInstructions();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Asigna variables a partir de dos cadenas
|
|
bool Director::setOptions(options_t *options, std::string var, std::string value)
|
|
{
|
|
// Indicador de éxito en la asignación
|
|
bool success = true;
|
|
|
|
// Opciones de video
|
|
if (var == "video.mode")
|
|
{
|
|
if (value == "0")
|
|
{
|
|
options->video.mode = VIDEO_MODE_WINDOW;
|
|
}
|
|
else
|
|
{
|
|
options->video.mode = VIDEO_MODE_FULLSCREEN;
|
|
}
|
|
}
|
|
|
|
else if (var == "video.window.size")
|
|
{
|
|
options->video.window.size = std::stoi(value);
|
|
if ((options->video.window.size < 1) || (options->video.window.size > 4))
|
|
{
|
|
options->video.window.size = 3;
|
|
}
|
|
}
|
|
|
|
else if (var == "video.filter")
|
|
{
|
|
if (value == "0")
|
|
{
|
|
options->video.filter = FILTER_NEAREST;
|
|
}
|
|
else
|
|
{
|
|
options->video.filter = FILTER_LINEAL;
|
|
}
|
|
}
|
|
|
|
else if (var == "video.shaders")
|
|
{
|
|
options->video.shaders = stringToBool(value);
|
|
}
|
|
|
|
else if (var == "video.vSync")
|
|
{
|
|
options->video.vSync = stringToBool(value);
|
|
}
|
|
|
|
else if (var == "video.integerScale")
|
|
{
|
|
options->video.integerScale = stringToBool(value);
|
|
}
|
|
|
|
else if (var == "video.keepAspect")
|
|
{
|
|
options->video.keepAspect = stringToBool(value);
|
|
}
|
|
|
|
else if (var == "video.border.enabled")
|
|
{
|
|
options->video.border.enabled = stringToBool(value);
|
|
}
|
|
|
|
else if (var == "video.border.width")
|
|
{
|
|
options->video.border.width = std::stoi(value);
|
|
}
|
|
|
|
else if (var == "video.border.height")
|
|
{
|
|
options->video.border.height = std::stoi(value);
|
|
}
|
|
|
|
// Opciones de notificaciones
|
|
else if (var == "notification.posH")
|
|
{
|
|
if (value == "pos_left")
|
|
{
|
|
options->notification.posH = pos_left;
|
|
}
|
|
else if (value == "pos_middle")
|
|
{
|
|
options->notification.posH = pos_middle;
|
|
}
|
|
else
|
|
{
|
|
options->notification.posH = pos_right;
|
|
}
|
|
}
|
|
|
|
else if (var == "notification.posV")
|
|
{
|
|
if (value == "pos_top")
|
|
{
|
|
options->notification.posV = pos_top;
|
|
}
|
|
else
|
|
{
|
|
options->notification.posV = pos_bottom;
|
|
}
|
|
}
|
|
|
|
else if (var == "notification.sound")
|
|
{
|
|
options->notification.sound = stringToBool(value);
|
|
}
|
|
|
|
// Opciones de audio
|
|
else if (var == "audio.music.enabled")
|
|
{
|
|
options->audio.music.enabled = stringToBool(value);
|
|
}
|
|
|
|
else if (var == "audio.music.volume")
|
|
{
|
|
options->audio.music.volume = std::stoi(value);
|
|
}
|
|
|
|
else if (var == "audio.sound.enabled")
|
|
{
|
|
options->audio.sound.enabled = stringToBool(value);
|
|
}
|
|
|
|
else if (var == "audio.sound.volume")
|
|
{
|
|
options->audio.sound.volume = std::stoi(value);
|
|
}
|
|
|
|
// Opciones de juego
|
|
else if (var == "game.language")
|
|
{
|
|
options->game.language = std::stoi(value);
|
|
}
|
|
|
|
else if (var == "game.difficulty")
|
|
{
|
|
options->game.difficulty = std::stoi(value);
|
|
}
|
|
|
|
// Opciones de mandos
|
|
else if (var == "controller1.name")
|
|
{
|
|
options->controller[0].name = value;
|
|
}
|
|
|
|
else if (var == "controller1.inputs.fire_left")
|
|
{
|
|
options->controller[0].buttons[0] = (SDL_GameControllerButton)std::stoi(value);
|
|
}
|
|
|
|
else if (var == "controller1.inputs.fire_center")
|
|
{
|
|
options->controller[0].buttons[1] = (SDL_GameControllerButton)std::stoi(value);
|
|
}
|
|
|
|
else if (var == "controller1.inputs.fire_right")
|
|
{
|
|
options->controller[0].buttons[2] = (SDL_GameControllerButton)std::stoi(value);
|
|
}
|
|
|
|
else if (var == "controller1.inputs.fire_start")
|
|
{
|
|
options->controller[0].buttons[3] = (SDL_GameControllerButton)std::stoi(value);
|
|
}
|
|
|
|
else if (var == "controller1.inputs.fire_exit")
|
|
{
|
|
options->controller[0].buttons[4] = (SDL_GameControllerButton)std::stoi(value);
|
|
}
|
|
|
|
else if (var == "controller2.name")
|
|
{
|
|
options->controller[1].name = value;
|
|
}
|
|
|
|
else if (var == "controller2.inputs.fire_left")
|
|
{
|
|
options->controller[1].buttons[0] = (SDL_GameControllerButton)std::stoi(value);
|
|
}
|
|
|
|
else if (var == "controller2.inputs.fire_center")
|
|
{
|
|
options->controller[1].buttons[1] = (SDL_GameControllerButton)std::stoi(value);
|
|
}
|
|
|
|
else if (var == "controller2.inputs.fire_right")
|
|
{
|
|
options->controller[1].buttons[2] = (SDL_GameControllerButton)std::stoi(value);
|
|
}
|
|
|
|
else if (var == "controller2.inputs.fire_start")
|
|
{
|
|
options->controller[1].buttons[3] = (SDL_GameControllerButton)std::stoi(value);
|
|
}
|
|
|
|
else if (var == "controller2.inputs.fire_exit")
|
|
{
|
|
options->controller[1].buttons[4] = (SDL_GameControllerButton)std::stoi(value);
|
|
}
|
|
|
|
// Lineas vacias o que empiezan por comentario
|
|
else if (var == "" || var.substr(0, 1) == "#")
|
|
{
|
|
}
|
|
|
|
else
|
|
{
|
|
success = false;
|
|
}
|
|
|
|
return success;
|
|
} |