464 lines
10 KiB
C++
464 lines
10 KiB
C++
#include "const.h"
|
|
#include "director.h"
|
|
#include <iostream>
|
|
|
|
const Uint8 *keystates;
|
|
|
|
// Constructor
|
|
Director::Director(std::string path)
|
|
{
|
|
// Arranca SDL y crea la ventana
|
|
initSDL();
|
|
|
|
// Crea todos los objetos del juego
|
|
eventHandler = new SDL_Event();
|
|
screen = new Screen(window, renderer);
|
|
asset = new Asset(path.substr(0, path.find_last_of("\\/")));
|
|
setFileList();
|
|
|
|
// Inicializa todas las variables
|
|
section = NONE;
|
|
gameControllerFound = false;
|
|
for (int i = 0; i < 360; i++)
|
|
sen[i] = sin(i * 3.14 / 180);
|
|
for (int i = 0; i < TOTAL_SCORE_DATA; i++)
|
|
scoreData[i] = 0;
|
|
|
|
initOptions();
|
|
initGame();
|
|
quit = false;
|
|
}
|
|
|
|
Director::~Director()
|
|
{
|
|
|
|
quitGame();
|
|
|
|
// Borra todos los objetos del juego
|
|
delete eventHandler;
|
|
eventHandler = nullptr;
|
|
|
|
// delete text.white;
|
|
// text.white = nullptr;
|
|
|
|
delete screen;
|
|
screen = nullptr;
|
|
|
|
delete asset;
|
|
asset = nullptr;
|
|
|
|
// Destruye la ventana
|
|
SDL_DestroyRenderer(renderer);
|
|
SDL_DestroyTexture(backbuffer);
|
|
SDL_DestroyWindow(window);
|
|
backbuffer = nullptr;
|
|
renderer = nullptr;
|
|
window = nullptr;
|
|
|
|
// Sal del subsistema SDL
|
|
SDL_Quit();
|
|
}
|
|
|
|
// Inicializa las variables de las opciones
|
|
void Director::initOptions()
|
|
{
|
|
options.fullScreenMode = 0;
|
|
options.fullScreenModePrevious = 0;
|
|
options.windowSize = 0;
|
|
options.windowSizePrevious = 0;
|
|
}
|
|
|
|
// Inicializa las variables y crea los objetos del juego
|
|
void Director::initGame()
|
|
{
|
|
// Variables
|
|
game.score = 0;
|
|
game.section = 0;
|
|
game.paused = false;
|
|
game.ticks = 0;
|
|
game.ticksSpeed = GAME_SPEED;
|
|
game.counter = 0;
|
|
|
|
// Player
|
|
player = new Player(renderer, asset);
|
|
|
|
// Map
|
|
map = new Map(renderer, asset->get("volcano.map"), asset);
|
|
}
|
|
|
|
// Destruye los objetos del juego
|
|
void Director::quitGame()
|
|
{
|
|
// Player
|
|
delete player;
|
|
player = nullptr;
|
|
|
|
// Map
|
|
delete map;
|
|
map = nullptr;
|
|
}
|
|
|
|
// Arranca SDL y crea la ventana
|
|
bool Director::initSDL()
|
|
{
|
|
// Indicador de inicialización
|
|
bool success = true;
|
|
|
|
// Inicializa SDL
|
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_HAPTIC) < 0)
|
|
{
|
|
printf("SDL could not initialize!\nSDL Error: %s\n", SDL_GetError());
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
// Establece el filtro de la textura a nearest
|
|
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"))
|
|
{
|
|
printf("Warning: Nearest texture filtering not enabled!\n");
|
|
}
|
|
|
|
// Inicializa jail_audio
|
|
JA_Init(48000, AUDIO_S16, 2);
|
|
|
|
// Comprueba si hay algun mando conectado
|
|
if (SDL_NumJoysticks() < 1)
|
|
{
|
|
printf("Warning: No joysticks connected!\n");
|
|
gameControllerFound = false;
|
|
}
|
|
else
|
|
{
|
|
// Carga el mando
|
|
gameController = SDL_JoystickOpen(0);
|
|
gameControllerFound = true;
|
|
|
|
if (gameController == NULL)
|
|
{
|
|
printf("Warning: Unable to open game controller!\nSDL Error: %s\n", SDL_GetError());
|
|
gameControllerFound = false;
|
|
}
|
|
else
|
|
{
|
|
printf("%i joysticks were found.\n", SDL_NumJoysticks());
|
|
std::cout << SDL_JoystickNumButtons(gameController) << " buttons\n";
|
|
|
|
// Get controller haptic device
|
|
controllerHaptic = SDL_HapticOpenFromJoystick(gameController);
|
|
if (controllerHaptic == NULL)
|
|
{
|
|
printf("Warning: Controller does not support haptics!\nSDL Error: %s\n", SDL_GetError());
|
|
}
|
|
else
|
|
{
|
|
printf("Haptics detected\n");
|
|
|
|
// Get initialize rumble
|
|
if (SDL_HapticRumbleInit(controllerHaptic) < 0)
|
|
{
|
|
printf("Warning: Unable to initialize rumble!\nSDL Error: %s\n", SDL_GetError());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Crea la ventana
|
|
window = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, VIEW_WIDTH, VIEW_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
|
|
if (window == NULL)
|
|
{
|
|
printf("Window could not be created!\nSDL Error: %s\n", SDL_GetError());
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
// Crea un renderizador para la ventana con vsync
|
|
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
|
if (renderer == NULL)
|
|
{
|
|
printf("Renderer could not be created!\nSDL Error: %s\n", SDL_GetError());
|
|
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, SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
|
|
// Establece el modo de mezcla
|
|
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
|
}
|
|
|
|
// Crea un backbuffer para el renderizador
|
|
backbuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
if (backbuffer == NULL)
|
|
{
|
|
printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError());
|
|
success = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
printf("\n");
|
|
return success;
|
|
}
|
|
|
|
// Crea el indice de ficheros de recursos
|
|
bool Director::setFileList()
|
|
{
|
|
// Ficheros binarios
|
|
asset->add("/data/volcano.map", data);
|
|
asset->add("/data/config.bin", data, false);
|
|
|
|
// Texturas
|
|
asset->add("/media/gfx/actors.png", bitmap);
|
|
asset->add("/media/gfx/bg_surface.png", bitmap);
|
|
asset->add("/media/gfx/filter.png", bitmap);
|
|
asset->add("/media/gfx/hud.png", bitmap);
|
|
asset->add("/media/gfx/menu_animation.png", bitmap);
|
|
asset->add("/media/gfx/menu.png", bitmap);
|
|
asset->add("/media/gfx/player.png", bitmap);
|
|
asset->add("/media/gfx/tiles_surface.png", bitmap);
|
|
asset->add("/media/gfx/tiles_volcano.png", bitmap);
|
|
|
|
// Sonidos
|
|
asset->add("/media/sound/sound_player_coin.wav", sound);
|
|
asset->add("/media/sound/sound_player_death.wav", sound);
|
|
asset->add("/media/sound/sound_drop_enemy.wav", sound);
|
|
asset->add("/media/sound/sound_drop_splat.wav", sound);
|
|
asset->add("/media/sound/sound_player_jump.wav", sound);
|
|
asset->add("/media/sound/sound_menu_logo.wav", sound);
|
|
asset->add("/media/sound/sound_menu_start.wav", sound);
|
|
|
|
// Musicas
|
|
asset->add("/media/music/music_menu.ogg", music);
|
|
asset->add("/media/music/music_surface.ogg", music);
|
|
asset->add("/media/music/music_volcano.ogg", music);
|
|
|
|
return asset->check();
|
|
}
|
|
|
|
// Carga el fichero de configuración
|
|
bool Director::loadConfig()
|
|
{
|
|
// Indicador de éxito en la carga
|
|
bool success = true;
|
|
const std::string p = asset->get("config.bin").c_str();
|
|
const std::string filename = p.substr(p.find_last_of("\\/") + 1);
|
|
|
|
// Abre el fichero con la configuracion de las opciones para leer en binario
|
|
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b");
|
|
|
|
// El fichero no existe
|
|
if (file == NULL)
|
|
{
|
|
printf("Warning: Unable to open %s file\n", filename.c_str());
|
|
|
|
// Crea el fichero para escribir
|
|
file = SDL_RWFromFile(p.c_str(), "w+b");
|
|
if (file != NULL)
|
|
{
|
|
printf("New file (%s) created!\n", filename.c_str());
|
|
|
|
// Inicializa los datos
|
|
options.fullScreenMode = 0;
|
|
SDL_RWwrite(file, &options.fullScreenMode, sizeof(options.fullScreenMode), 1);
|
|
|
|
options.windowSize = 3;
|
|
SDL_RWwrite(file, &options.windowSize, sizeof(options.windowSize), 1);
|
|
|
|
// Cierra el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
else
|
|
{
|
|
printf("Error: Unable to create file %s\n", filename.c_str());
|
|
success = false;
|
|
}
|
|
}
|
|
// El fichero existe
|
|
else
|
|
{
|
|
// Carga los datos
|
|
printf("Reading file %s\n", filename.c_str());
|
|
SDL_RWread(file, &options.fullScreenMode, sizeof(options.fullScreenMode), 1);
|
|
SDL_SetWindowFullscreen(window, options.fullScreenMode);
|
|
SDL_RWread(file, &options.windowSize, sizeof(options.windowSize), 1);
|
|
SDL_SetWindowSize(window, SCREEN_WIDTH * options.windowSize, SCREEN_HEIGHT * options.windowSize);
|
|
|
|
// Cierra el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
printf("\n");
|
|
|
|
return success;
|
|
}
|
|
|
|
// Guarda el fichero de configuración
|
|
bool Director::saveConfig()
|
|
{
|
|
// Indicador de éxito en la carga
|
|
bool success = true;
|
|
const std::string p = asset->get("config.bin");
|
|
const std::string filename = p.substr(p.find_last_of("\\/") + 1);
|
|
|
|
// Abre el fichero de puntuación para escribir
|
|
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "w+b");
|
|
|
|
if (file != NULL)
|
|
{
|
|
// Guardamos los datos
|
|
SDL_RWwrite(file, &options.fullScreenMode, sizeof(Uint32), 1);
|
|
SDL_RWwrite(file, &options.windowSize, sizeof(Uint8), 1);
|
|
|
|
printf("Writing file %s\n", filename.c_str());
|
|
|
|
// Cerramos el fichero
|
|
SDL_RWclose(file);
|
|
}
|
|
else
|
|
{
|
|
printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError());
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Obtiene el valor de la variable
|
|
Uint8 Director::getGameSection()
|
|
{
|
|
return game.section;
|
|
}
|
|
|
|
// Establece el valor de la variable
|
|
void Director::changeGameSection(_section sectionPrevious, _section sectionNext)
|
|
{
|
|
switch (sectionPrevious)
|
|
{
|
|
case GAME:
|
|
quitGame();
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch (sectionNext)
|
|
{
|
|
case GAME:
|
|
initGame();
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
game.section = sectionNext;
|
|
}
|
|
|
|
// Cambia el valor de la variable de modo de pantalla completa
|
|
void Director::changeFullScreenMode()
|
|
{
|
|
switch (options.fullScreenMode)
|
|
{
|
|
case 0:
|
|
options.fullScreenMode = SDL_WINDOW_FULLSCREEN;
|
|
break;
|
|
case SDL_WINDOW_FULLSCREEN:
|
|
options.fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
break;
|
|
case SDL_WINDOW_FULLSCREEN_DESKTOP:
|
|
options.fullScreenMode = 0;
|
|
break;
|
|
|
|
default:
|
|
options.fullScreenMode = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Comprueba si hay que salir
|
|
bool Director::isRunning()
|
|
{
|
|
return !quit;
|
|
}
|
|
|
|
// Bucle para el logo del juego
|
|
void Director::runLogo()
|
|
{
|
|
}
|
|
|
|
// Bucle para la intro del juego
|
|
void Director::runIntro()
|
|
{
|
|
}
|
|
|
|
// Bucle para el titulo del juego
|
|
void Director::runTitle()
|
|
{
|
|
}
|
|
|
|
// Bucle para el juego
|
|
void Director::runGame()
|
|
{
|
|
// Actualiza la lógica del juego
|
|
updateGame();
|
|
|
|
// Pinta la sección de juego
|
|
renderGame();
|
|
}
|
|
|
|
// Actualiza la lógica del juego
|
|
void Director::updateGame()
|
|
{
|
|
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
|
if (SDL_GetTicks() - game.ticks > game.ticksSpeed)
|
|
{
|
|
// Actualiza el contador de ticks
|
|
game.ticks = SDL_GetTicks();
|
|
|
|
// Comprueba los eventos que hay en la cola
|
|
while (SDL_PollEvent(eventHandler) != 0)
|
|
{
|
|
// Evento de salida de la aplicación
|
|
if (eventHandler->type == SDL_QUIT)
|
|
{
|
|
quit = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
game.counter++;
|
|
map->update();
|
|
player->update();
|
|
}
|
|
}
|
|
|
|
// Pinta la sección de juego
|
|
void Director::renderGame()
|
|
{
|
|
// Prepara para empezar a dibujar el frame
|
|
screen->start();
|
|
|
|
// Limpia la pantalla
|
|
screen->clean();
|
|
|
|
// Dibuja los objetos
|
|
map->render();
|
|
player->render();
|
|
|
|
// Vuelca el contenido del renderizador en pantalla
|
|
screen->blit();
|
|
}
|
|
|
|
// Bucle principal
|
|
void Director::run()
|
|
{
|
|
while (isRunning())
|
|
{
|
|
runGame();
|
|
}
|
|
} |