#include "game.h" // Constructor Game::Game(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, Debug *debug) { // Copia punteros this->renderer = renderer; this->asset = asset; this->screen = screen; this->input = input; this->debug = debug; this->debug->setEnabled(true); // Reserva memoria para los objetos scoreboard = new ScoreBoard(renderer, asset, input, &board); eventHandler = new SDL_Event(); itemTracker = new ItemTracker(); map = new Map(asset->get("01.map"), renderer, asset, itemTracker); player = new Player(renderer, asset, input, map, debug, &board.diamonds); enemyEngine = new EnemyEngine(renderer, asset, player, map, asset->get(map->getEnemyFile())); music = JA_LoadMusic(asset->get("music_surface.ogg").c_str()); // Crea la textura para dibujar los sprites spriteLayer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, PLAY_AREA_WIDTH, PLAY_AREA_HEIGHT); if (spriteLayer == nullptr) printf("Error: map_layer0 could not be created!\nSDL Error: %s\n", SDL_GetError()); SDL_SetTextureBlendMode(spriteLayer, SDL_BLENDMODE_BLEND); // Inicializa variables ticks = 0; ticksSpeed = 15; section.name = SECTION_PROG_GAME; section.subsection = SUBSECTION_GAME_PLAY; musicEnabled = !debug->getEnabled(); board.diamonds = 0; board.lives = 5; } // Destructor Game::~Game() { SDL_DestroyTexture(spriteLayer); delete scoreboard; delete eventHandler; delete itemTracker; delete map; delete player; delete enemyEngine; JA_DeleteMusic(music); } // Bucle para el juego section_t Game::run() { JA_PlayMusic(music); if (!musicEnabled) { JA_PauseMusic(); } while (section.name == SECTION_PROG_GAME) { // Sección juego jugando if (section.subsection == SUBSECTION_GAME_PLAY) { update(); render(); } } JA_StopMusic(); return section; } // Actualiza el juego, las variables, comprueba la entrada, etc. void Game::update() { // Comprueba que la diferencia de ticks sea mayor a la velocidad del juego if (SDL_GetTicks() - ticks > ticksSpeed) { // Actualiza el contador de ticks ticks = SDL_GetTicks(); // Comprueba los eventos de la cola checkEventHandler(); // Actualiza los objetos debug->clear(); scoreboard->update(); map->update(); enemyEngine->update(); player->update(); if (enemyEngine->checkEnemyCollision(player->getCollider())) { debug->add("COLLISION"); } checkScreenBorders(); updateDebugInfo(); } } // Pinta los objetos en pantalla void Game::render() { // Rellena las texturas fillSpriteTexture(); scoreboard->fillTexture(); // Prepara para dibujar el frame screen->start(); screen->clean(); // Dibuja la capa 0 map->renderLayer0(); // Dibuja la capa 1 map->renderLayer1(); // Dibuja la capa de sprites renderSprites(); // Dibuja el marcador scoreboard->render(); // Dibuja la información de debug renderDebugInfo(); // Actualiza la pantalla screen->blit(); } // Dibuja los sprites en la textura void Game::fillSpriteTexture() { // Cambia el puntero del renderizador a la textura y la limpia SDL_SetRenderTarget(renderer, spriteLayer); SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00); SDL_RenderClear(renderer); // Dibuja los sprites en la textura map->renderActors(); enemyEngine->render(); player->render(); // Vuelve a colocar el renderizador apuntando a la pantalla SDL_SetRenderTarget(renderer, nullptr); } // Dibuja los sprites void Game::renderSprites() { // Copia la textura al renderizador SDL_Rect rect = {PLAY_AREA_X, PLAY_AREA_Y, PLAY_AREA_WIDTH, PLAY_AREA_HEIGHT}; SDL_RenderCopy(renderer, spriteLayer, NULL, &rect); } // Comprueba los eventos de la cola void Game::checkEventHandler() { // 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) { section.name = SECTION_PROG_QUIT; break; } else if ((eventHandler->type == SDL_KEYDOWN) and (eventHandler->key.repeat == 0)) { switch (eventHandler->key.keysym.scancode) { case SDL_SCANCODE_ESCAPE: section.name = SECTION_PROG_QUIT; break; case SDL_SCANCODE_D: debug->switchEnabled(); musicEnabled = !debug->getEnabled(); musicEnabled ? JA_ResumeMusic() : JA_PauseMusic(); break; case SDL_SCANCODE_M: musicEnabled = !musicEnabled; musicEnabled ? JA_ResumeMusic() : JA_PauseMusic(); break; case SDL_SCANCODE_R: delete map; map = new Map(asset->get("01.map"), renderer, asset, itemTracker); delete player; player = new Player(renderer, asset, input, map, debug, &board.diamonds); break; case SDL_SCANCODE_F: screen->switchVideoMode(); reLoadTextures(); break; case SDL_SCANCODE_F1: screen->setWindowSize(1); reLoadTextures(); break; case SDL_SCANCODE_F2: screen->setWindowSize(2); reLoadTextures(); break; case SDL_SCANCODE_F3: screen->setWindowSize(3); reLoadTextures(); break; case SDL_SCANCODE_F4: screen->setWindowSize(4); reLoadTextures(); break; default: break; } } } } // Pasa la información de debug void Game::updateDebugInfo() { debug->add("R - Reload player and map"); debug->add("D - Toggle debug mode"); } // Pone la información de debug en pantalla void Game::renderDebugInfo() { if (!debug->getEnabled()) { return; } // Pinta la rejilla SDL_SetRenderDrawColor(renderer, 0, 0, 0, 16); for (int i = 0; i < 240; i += 8) { SDL_RenderDrawLine(renderer, 0, i, 320, i); } for (int i = 0; i < 320; i += 8) { SDL_RenderDrawLine(renderer, i, 0, i, 240); } // Pinta mascaras SDL_SetRenderDrawColor(renderer, 0, 255, 0, 192); SDL_Rect rect = player->getRect(); SDL_RenderFillRect(renderer, &rect); // Pinta el texto debug->setPos({1, 1}); debug->render(); } // Cambia el mapa bool Game::changeMap(std::string file) { bool success = false; // En las habitaciones los limites tienen la cadena del fichero o un 0 en caso de no limitar con nada if (file != "0") { // Verifica que exista el fichero que se va a cargar if (asset->get(file) != "") { // Elimina la habitación actual y crea un objeto nuevo a partir del fichero delete map; map = new Map(asset->get(file), renderer, asset, itemTracker); // Elimina el gestor de enemigos y crea uno nuevo a partir de un fichero delete enemyEngine; enemyEngine = new EnemyEngine(renderer, asset, player, map, asset->get(map->getEnemyFile())); success = true; } } return success; } // Comprueba si el jugador está en el borde y se ha de cambiar el mapa void Game::checkScreenBorders() { if (player->isOnScreenBorder()) { if (changeMap(map->getRoomFileName(player->getBorder()))) { player->setMap(map); player->switchBorders(); } } } // Recarga las texturas void Game::reLoadTextures() { map->reLoadTextures(); player->reLoadTextures(); scoreboard->reLoadTexture(); }