#include "game.h" // Constructor Game::Game(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, Debug *debug) { // Inicia algunas variables board.iniClock = SDL_GetTicks(); currentRoom = "01.room"; spawnPoint = {16, 96, 0, 0, 0, s_standing, SDL_FLIP_NONE}; // Copia los punteros this->renderer = renderer; this->asset = asset; this->screen = screen; this->input = input; this->debug = debug; // this->debug->setEnabled(true); // currentRoom = "06.room"; // spawnPoint = {240, 96, 0, 0, 0, s_standing, SDL_FLIP_HORIZONTAL}; // Crea los objetos scoreboard = new ScoreBoard(renderer, asset, &board); itemTracker = new ItemTracker(); roomTracker = new RoomTracker(); room = new Room(asset->get(currentRoom), renderer, screen, asset, itemTracker, &board.items, debug); player = new Player(spawnPoint, asset->get("player.png"), asset->get("player.ani"), renderer, asset, input, room, debug); eventHandler = new SDL_Event(); text = new Text(asset->get("smb2.png"), asset->get("smb2.txt"), renderer); music = JA_LoadMusic(asset->get("game.ogg").c_str()); deathSound = JA_LoadSound(asset->get("death.wav").c_str()); test = new Test(renderer, screen, asset, debug); // Inicializa el resto de variables ticks = 0; ticksSpeed = 15; board.lives = 9; board.items = 0; board.rooms = 1; board.color = room->getBorderColor(); roomTracker->addRoom(currentRoom); player->setInvincible(debug->getEnabled()); board.music = !debug->getEnabled(); section.name = SECTION_PROG_GAME; section.subsection = SUBSECTION_GAME_PLAY; } Game::~Game() { // Borra las referencias a los punteros renderer = nullptr; asset = nullptr; input = nullptr; // Libera la memoria de los objetos delete scoreboard; delete itemTracker; delete roomTracker; delete room; delete player; delete eventHandler; delete text; JA_DeleteMusic(music); JA_DeleteSound(deathSound); delete test; } // 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; screen->setBorderColor(stringToColor("black")); 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_TITLE; break; case SDL_SCANCODE_D: debug->switchEnabled(); player->setInvincible(debug->getEnabled()); board.music = !debug->getEnabled(); board.music ? JA_ResumeMusic() : JA_PauseMusic(); break; case SDL_SCANCODE_M: board.music = !board.music; board.music ? JA_ResumeMusic() : JA_PauseMusic(); break; case SDL_SCANCODE_B: screen->switchBorder(); reLoadTextures(); 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; } } } } // Bucle para el juego section_t Game::run() { JA_PlayMusic(music); if (!board.music) { 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(); room->update(); player->update(); checkPlayerOnBorder(); checkPlayerAndItems(); checkPlayerAndEnemies(); scoreboard->update(); updateDebugInfo(); } } // Pinta los objetos en pantalla void Game::render() { // Prepara para dibujar el frame screen->start(); screen->clean(room->getBGColor()); room->renderMap(); room->renderEnemies(); room->renderItems(); player->render(); renderRoomName(); scoreboard->render(); // Debug info renderDebugInfo(); // test->render(); // Actualiza la pantalla screen->blit(); } // Pasa la información de debug void Game::updateDebugInfo() { debug->add("X = " + std::to_string((int)player->x) + ", Y = " + std::to_string((int)player->y)); debug->add("VX = " + std::to_string(player->vx).substr(0, 4) + ", VY = " + std::to_string(player->vy).substr(0, 4)); debug->add("STATE = " + std::to_string(player->state)); } // Pone la información de debug en pantalla void Game::renderDebugInfo() { if (!debug->getEnabled()) { return; } // Borra el marcador SDL_Rect rect = {0, 18 * BLOCK, PLAY_AREA_WIDTH, GAMECANVAS_HEIGHT - PLAY_AREA_HEIGHT}; SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderFillRect(renderer, &rect); // Pinta la rejilla /*SDL_SetRenderDrawColor(renderer, 255, 255, 255, 32); for (int i = 0; i < PLAY_AREA_BOTTOM; i += 8) { // Lineas horizontales SDL_RenderDrawLine(renderer, 0, i, PLAY_AREA_RIGHT, i); } for (int i = 0; i < PLAY_AREA_RIGHT; i += 8) { // Lineas verticales SDL_RenderDrawLine(renderer, i, 0, i, PLAY_AREA_BOTTOM - 1); }*/ // Pinta el texto debug->setPos({1, 18 * 8}); debug->render(); } // Escribe el nombre de la pantalla void Game::renderRoomName() { // Texto en el centro de la pantalla SDL_Rect rect = {0, 16 * BLOCK, PLAY_AREA_WIDTH, BLOCK * 2}; color_t color = stringToColor("white"); SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 0xFF); SDL_RenderFillRect(renderer, &rect); text->writeDX(TXT_CENTER | TXT_COLOR, GAMECANVAS_CENTER_X, 16 * 8 + 4, room->getName(), 1, room->getBGColor()); } // Cambia de habitación bool Game::changeRoom(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 delete room; room = nullptr; // Crea un objeto habitación nuevo a partir del fichero room = new Room(asset->get(file), renderer, screen, asset, itemTracker, &board.items, debug); // Actualiza el marcador const color_t c = room->getBorderColor(); // Pon el color del marcador board.color = (c.r + c.g + c.b == 0) ? stringToColor("white") : c; // Si el color es negrom cambialo a blanco if (roomTracker->addRoom(file)) { // Incrementa el contador de habitaciones visitadas board.rooms++; } // Pasa la nueva habitación al jugador player->setRoom(room); success = true; } return success; } // Comprueba si el jugador esta en el borde de la pantalla void Game::checkPlayerOnBorder() { if (player->getOnBorder()) { const std::string room_name = room->getRoom(player->getBorder()); if (changeRoom(room_name)) { player->switchBorders(); currentRoom = room_name; spawnPoint = player->getSpawnParams(); } } } // Comprueba las colisiones del jugador con los enemigos bool Game::checkPlayerAndEnemies() { const bool death = room->enemyCollision(player->getCollider()); if (death) { killPlayer(); } return death; } // Comprueba las colisiones del jugador con los objetos void Game::checkPlayerAndItems() { room->itemCollision(player->getCollider()); } // Mata al jugador void Game::killPlayer() { if (player->getInvincible()) { return; } board.lives--; // Destruye la habitacion y el jugador delete room; delete player; // Sonido JA_PlaySound(deathSound); // Crea la nueva habitación y el nuevo jugador room = new Room(asset->get(currentRoom), renderer, screen, asset, itemTracker, &board.items, debug); player = new Player(spawnPoint, asset->get("player.png"), asset->get("player.ani"), renderer, asset, input, room, debug); } // Recarga todas las texturas void Game::reLoadTextures() { player->reLoadTexture(); room->reLoadTexture(); scoreboard->reLoadTexture(); text->reLoadTexture(); }