diff --git a/source/credits.cpp b/source/credits.cpp index e903cd8..dcc5aef 100644 --- a/source/credits.cpp +++ b/source/credits.cpp @@ -9,14 +9,14 @@ #include // Para runtime_error #include // Para basic_string, string #include // Para vector -#include // Para vector +#include // Para vector #include "balloon_manager.h" // Para BalloonManager #include "fade.h" // Para Fade, FadeType, FadeMode #include "global_inputs.h" // Para check, update #include "input.h" // Para Input #include "jail_audio.h" // Para JA_GetMusicState, JA_SetMusicVolume #include "lang.h" // Para getText -#include "global_events.h" // Para handleEvent +#include "global_events.h" // Para handleEvent #include "param.h" // Para Param, ParamGame, param #include "player.h" // Para Player, PlayerState #include "resource.h" // Para Resource @@ -57,6 +57,9 @@ Credits::Credits() fade_out_->setType(FadeType::FULLSCREEN); fade_out_->setPostDuration(400); + updateRedRect(); + tiled_bg_->setColor(Color(255, 96, 96)); + initPlayers(); SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND); fillTextTexture(); @@ -94,6 +97,7 @@ void Credits::update() for (int i = 0; i < REPEAT; ++i) { tiled_bg_->update(); + cycleColors(); balloon_manager_->update(); updateTextureDstRects(); throwBalloons(); @@ -104,7 +108,7 @@ void Credits::update() updateAllFades(); ++counter_; } - + Screen::get()->update(); globalInputs::update(); @@ -128,23 +132,25 @@ void Credits::render() // Comprueba el manejador de eventos void Credits::checkEvents() { - SDL_Event event; - while (SDL_PollEvent(&event)) - { - globalEvents::check(event); - } + SDL_Event event; + while (SDL_PollEvent(&event)) + { + globalEvents::check(event); + } } // Comprueba las entradas void Credits::checkInput() { // Comprueba si se ha pulsado cualquier botón (de los usados para jugar) - if (Input::get()->checkAnyButtonPressed()) + if (Input::get()->checkAnyButtonPressed(INPUT_ALLOW_REPEAT)) + { if (mini_logo_on_position_) { // Si el mini_logo ha llegado a su posición final, al pulsar cualquier tecla se activa el fundido fading_ = true; + want_to_pass_ = true; } else { @@ -152,6 +158,10 @@ void Credits::checkInput() want_to_pass_ = true; } } + else + { + want_to_pass_ = false; + } // Comprueba los inputs que se pueden introducir en cualquier sección del juego globalInputs::check(); @@ -268,12 +278,16 @@ void Credits::fillCanvas() SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_); // Dibuja los rectangulos negros - SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 255); + SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 0xFF); SDL_RenderFillRect(Screen::get()->getRenderer(), &top_black_rect_); SDL_RenderFillRect(Screen::get()->getRenderer(), &bottom_black_rect_); SDL_RenderFillRect(Screen::get()->getRenderer(), &left_black_rect_); SDL_RenderFillRect(Screen::get()->getRenderer(), &right_black_rect_); + // Dibuja el rectangulo rojo + SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0xFF, 0, 0, 0xFF); + SDL_RenderDrawRect(Screen::get()->getRenderer(), &red_rect); + // Si el mini_logo está en su destino, lo dibuja encima de lo anterior if (mini_logo_on_position_) { @@ -419,13 +433,14 @@ void Credits::updateBlackRects() // Si los rectangulos superior e inferior han llegado al centro if (left_black_rect_.w != param.game.game_area.center_x && right_black_rect_.x != param.game.game_area.center_x) { + constexpr int SPEED = 2; // Si los rectangulos izquierdo y derecho no han llegado al centro // Incrementa la anchura del rectangulo situado a la izquierda - left_black_rect_.w = std::min(left_black_rect_.w + 4, param.game.game_area.center_x); + left_black_rect_.w = std::min(left_black_rect_.w + SPEED, param.game.game_area.center_x); // Incrementa la anchura y modifica la posición del rectangulo situado a la derecha - right_black_rect_.w += 4; - right_black_rect_.x = std::max(right_black_rect_.x - 4, param.game.game_area.center_x); + right_black_rect_.w += SPEED; + right_black_rect_.x = std::max(right_black_rect_.x - SPEED, param.game.game_area.center_x); --current_step; setVolume(static_cast(initial_volume_ * current_step / steps_)); @@ -447,12 +462,22 @@ void Credits::updateBlackRects() } } +// Actualiza el rectangulo rojo +void Credits::updateRedRect() +{ + red_rect.x = left_black_rect_.x + left_black_rect_.w; + red_rect.y = top_black_rect_.y + top_black_rect_.h - 1; + red_rect.w = right_black_rect_.x - red_rect.x; + red_rect.h = bottom_black_rect_.y - red_rect.y + 1; +} + // Actualiza el estado de fade void Credits::updateAllFades() { if (fading_) { updateBlackRects(); + updateRedRect(); } fade_in_->update(); @@ -483,4 +508,42 @@ void Credits::resetVolume() { options.audio.music.volume = initial_volume_; JA_SetMusicVolume(to_JA_volume(options.audio.music.volume)); -} \ No newline at end of file +} + +// Cambia el color del fondo +void Credits::cycleColors() +{ + constexpr int UPPER_LIMIT = 255; // Límite superior + constexpr int LOWER_LIMIT = 80; // Límite inferior + + static float r = static_cast(UPPER_LIMIT); + static float g = static_cast(LOWER_LIMIT); + static float b = static_cast(LOWER_LIMIT); + static float stepR = -0.5f; // Paso flotante para transiciones suaves + static float stepG = 0.3f; + static float stepB = 0.7f; + + // Ajustar valores de R + r += stepR; + if (r >= UPPER_LIMIT || r <= LOWER_LIMIT) + { + stepR = -stepR; // Cambia de dirección al alcanzar los límites + } + + // Ajustar valores de G + g += stepG; + if (g >= UPPER_LIMIT || g <= LOWER_LIMIT) + { + stepG = -stepG; // Cambia de dirección al alcanzar los límites + } + + // Ajustar valores de B + b += stepB; + if (b >= UPPER_LIMIT || b <= LOWER_LIMIT) + { + stepB = -stepB; // Cambia de dirección al alcanzar los límites + } + + // Aplicar el color, redondeando a enteros antes de usar + tiled_bg_->setColor(Color(static_cast(r), static_cast(g), static_cast(b))); +} diff --git a/source/credits.h b/source/credits.h index 7ca2125..3121af4 100644 --- a/source/credits.h +++ b/source/credits.h @@ -54,6 +54,7 @@ private: SDL_Rect bottom_black_rect_ = {play_area_.x, param.game.game_area.rect.h - black_bars_size_, play_area_.w, black_bars_size_}; // Rectangulo negro inferior SDL_Rect left_black_rect_ = {play_area_.x, param.game.game_area.center_y - 1, 0, 2}; // Rectangulo negro situado a la izquierda SDL_Rect right_black_rect_ = {play_area_.x + play_area_.w, param.game.game_area.center_y - 1, 0, 2}; // Rectangulo negro situado a la derecha + SDL_Rect red_rect = play_area_; // Rectangulo rojo para delimitar la ventana // Actualiza las variables void update(); @@ -85,6 +86,9 @@ private: // Actualiza los rectangulos negros void updateBlackRects(); + // Actualiza el rectangulo rojo + void updateRedRect(); + // Actualiza el estado de fade void updateAllFades(); @@ -94,6 +98,9 @@ private: // Reestablece el nivel de volumen void resetVolume(); + // Cambia el color del fondo + void cycleColors(); + public: // Constructor Credits(); diff --git a/source/director.cpp b/source/director.cpp index d82fc3f..875bd39 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -55,7 +55,7 @@ Director::Director(int argc, const char *argv[]) section::name = section::Name::GAME; section::options = section::Options::GAME_PLAY_1P; #elif DEBUG - section::name = section::Name::LOGO; + section::name = section::Name::CREDITS; #else // NORMAL GAME section::name = section::Name::LOGO; section::options = section::Options::NONE; diff --git a/source/game.cpp b/source/game.cpp index bac582b..2752a60 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -346,8 +346,8 @@ void Game::updateGameStateGameOver() { // La partida ha terminado con la derrota de los jugadores section::name = section::Name::HI_SCORE_TABLE; - section::options = section::Options::HI_SCORE_AFTER_GAME_OVER; } + section::options = section::Options::HI_SCORE_AFTER_PLAYING; if (options.audio.enabled) { JA_StopChannel(-1); diff --git a/source/hiscore_table.cpp b/source/hiscore_table.cpp index b3f3763..51ceae7 100644 --- a/source/hiscore_table.cpp +++ b/source/hiscore_table.cpp @@ -176,7 +176,7 @@ void HiScoreTable::updateFade() if (fade_->hasEnded() && fade_mode_ == FadeMode::OUT) { - section::name = (section::options == section::Options::HI_SCORE_AFTER_GAME_OVER) + section::name = (section::options == section::Options::HI_SCORE_AFTER_PLAYING) ? section::Name::TITLE : section::Name::INSTRUCTIONS; section::options = section::Options::NONE; diff --git a/source/intro.cpp b/source/intro.cpp index 3ff8e86..36cda11 100644 --- a/source/intro.cpp +++ b/source/intro.cpp @@ -313,7 +313,7 @@ void Intro::initSprites() const int X_DEST = param.game.game_area.center_x - SPRITE_WIDTH / 2; const int Y_DEST = param.game.game_area.first_quarter_y - (SPRITE_HEIGHT / 4); - // Inicializa los sprites de la intro + // Inicializa los sprites con las imagenes constexpr int TOTAL_SPRITES = 6; for (int i = 0; i < TOTAL_SPRITES; ++i) { @@ -339,7 +339,7 @@ void Intro::initSprites() const int S_X_DEST = X_DEST - BORDER / 2; const int S_Y_DEST = Y_DEST - BORDER / 2; - // Crea las texturas para las sombras + // Crea las texturas para las imágenes traseras std::vector> shadow_textures; for (int i = 0; i < TOTAL_SPRITES; ++i) diff --git a/source/jail_shader.cpp b/source/jail_shader.cpp index e6e8f52..ecaa7bf 100644 --- a/source/jail_shader.cpp +++ b/source/jail_shader.cpp @@ -10,12 +10,12 @@ #if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 #include -#else +#else // NOT ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 #include -#endif //! ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 -#else +#endif // ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 +#else // NOT __APPLE__ #include -#endif +#endif // __APPLE__ namespace shader { @@ -73,10 +73,13 @@ namespace shader { // Create ID for shader GLuint result = glCreateShader(shaderType); + // Add define depending on shader type const char *sources[2] = {shaderType == GL_VERTEX_SHADER ? "#define VERTEX\n" : "#define FRAGMENT\n", source}; + // Define shader text - glShaderSource(result, 2, sources, NULL); + glShaderSource(result, 2, sources, nullptr); + // Compile shader glCompileShader(result); @@ -97,8 +100,6 @@ namespace shader } glDeleteShader(result); result = 0; - // } else { - // std::cout << "Shader compilado correctamente. Id = " << result << std::endl; } return result; } @@ -127,6 +128,7 @@ namespace shader if (logLen > 0) { char *log = (char *)malloc(logLen * sizeof(char)); + // Show any errors as appropriate glGetProgramInfoLog(programId, logLen, &logLen, log); std::cout << "Prog Info Log: " << std::endl @@ -152,11 +154,10 @@ namespace shader shader::backBuffer = backBuffer; SDL_GetWindowSize(win, &win_size.x, &win_size.y); int access; - SDL_QueryTexture(backBuffer, NULL, &access, &tex_size.x, &tex_size.y); + SDL_QueryTexture(backBuffer, nullptr, &access, &tex_size.x, &tex_size.y); if (access != SDL_TEXTUREACCESS_TARGET) { - std::cout << "ERROR FATAL: La textura per al render ha de tindre SDL_TEXTUREACCESS_TARGET definit." << std::endl; - exit(1); + throw std::runtime_error("ERROR FATAL: La textura debe tener SDL_TEXTUREACCESS_TARGET definido."); } SDL_RendererInfo rendererInfo; @@ -164,7 +165,6 @@ namespace shader if (!strncmp(rendererInfo.name, "opengl", 6)) { - // std::cout << "Es OpenGL!" << std::endl; #ifndef __APPLE__ if (!initGLExtensions()) { @@ -175,7 +175,6 @@ namespace shader #endif // Compilar el shader y dejarlo listo para usar. programId = compileProgram(vertexShader, fragmentShader); - // std::cout << "programId = " << programId << std::endl; } else { @@ -190,48 +189,75 @@ namespace shader void render() { GLint oldProgramId; - // Guarrada para obtener el textureid (en driverdata->texture) - // Detach the texture + // Establece el color de fondo SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - - SDL_SetRenderTarget(renderer, NULL); + SDL_SetRenderTarget(renderer, nullptr); SDL_RenderClear(renderer); if (usingOpenGL) { - SDL_GL_BindTexture(backBuffer, NULL, NULL); + SDL_GL_BindTexture(backBuffer, nullptr, nullptr); if (programId != 0) { glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgramId); glUseProgram(programId); } - GLfloat minx, miny, maxx, maxy; - GLfloat minu, maxu, minv, maxv; + // Recupera el tamaño lógico configurado con SDL_RenderSetLogicalSize + int logicalW, logicalH; + SDL_RenderGetLogicalSize(renderer, &logicalW, &logicalH); + if (logicalW == 0 || logicalH == 0) + { + logicalW = win_size.x; + logicalH = win_size.y; + } - // Coordenadas de la ventana donde pintar. - minx = 0.0f; - miny = 0.0f; - maxx = tex_size.x; - maxy = tex_size.y; + // Calcula el viewport para preservar la relación de aspecto (letterboxing) + float windowAspect = static_cast(win_size.x) / win_size.y; + float logicalAspect = static_cast(logicalW) / logicalH; + int viewportX = 0, viewportY = 0, viewportW = win_size.x, viewportH = win_size.y; - minu = 0.0f; - maxu = 1.0f; - minv = 0.0f; - maxv = 1.0f; + if (windowAspect > logicalAspect) + { + // La ventana es más ancha que el espacio lógico: + viewportW = static_cast(logicalAspect * win_size.y); + viewportX = (win_size.x - viewportW) / 2; + } + else + { + // La ventana es más alta que el espacio lógico: + viewportH = static_cast(win_size.x / logicalAspect); + viewportY = (win_size.y - viewportH) / 2; + } + glViewport(viewportX, viewportY, viewportW, viewportH); - glViewport(0, 0, win_size.x, win_size.y); + // Configura la proyección ortográfica usando el espacio lógico + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + // Se usa glOrtho para definir el espacio lógico: + // el 0 está en la esquina superior izquierda y logicalH en la inferior. + glOrtho(0, static_cast(logicalW), static_cast(logicalH), 0, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // Dibuja el quad usando las nuevas coordenadas de textura: + // Se corrigen la inversión vertical y la espejada horizontal. glBegin(GL_TRIANGLE_STRIP); - glTexCoord2f(minu, minv); - glVertex2f(minx, miny); - glTexCoord2f(maxu, minv); - glVertex2f(maxx, miny); - glTexCoord2f(minu, maxv); - glVertex2f(minx, maxy); - glTexCoord2f(maxu, maxv); - glVertex2f(maxx, maxy); + // Vértice superior izquierdo: posición (0, 0) + glTexCoord2f(0.0f, 1.0f); + glVertex2f(0.0f, 0.0f); + // Vértice superior derecho: posición (logicalW, 0) + glTexCoord2f(1.0f, 1.0f); + glVertex2f(static_cast(logicalW), 0.0f); + // Vértice inferior izquierdo: posición (0, logicalH) + glTexCoord2f(0.0f, 0.0f); + glVertex2f(0.0f, static_cast(logicalH)); + // Vértice inferior derecho: posición (logicalW, logicalH) + glTexCoord2f(1.0f, 0.0f); + glVertex2f(static_cast(logicalW), static_cast(logicalH)); glEnd(); + SDL_GL_SwapWindow(win); if (programId != 0) @@ -241,7 +267,7 @@ namespace shader } else { - SDL_RenderCopy(renderer, backBuffer, NULL, NULL); + SDL_RenderCopy(renderer, backBuffer, nullptr, nullptr); SDL_RenderPresent(renderer); } } diff --git a/source/section.h b/source/section.h index 0b07c38..2e16ac1 100644 --- a/source/section.h +++ b/source/section.h @@ -29,7 +29,7 @@ namespace section QUIT_WITH_CONTROLLER, QUIT_FROM_EVENT, RELOAD, - HI_SCORE_AFTER_GAME_OVER, + HI_SCORE_AFTER_PLAYING, NONE, };