Compare commits

12 Commits

29 changed files with 626 additions and 156 deletions

View File

@@ -28,6 +28,10 @@ Les tecles son les següents:
- **Tecla F4**: Activa o desactiva els shaders - **Tecla F4**: Activa o desactiva els shaders
- **Tecla F5**: Activa o desactiva l'audio
- **Tecla F6**: Canvia el idioma del joc i reinicia
- **Tecla F10**: Reset - **Tecla F10**: Reset
<p align="center"> <p align="center">

View File

@@ -360,3 +360,15 @@ Temps!
## 120 - SCOREBOARD ## 120 - SCOREBOARD
Puntuacio Puntuacio
## 121 - CREDITS
PROGRAMAT I DISSENYAT PER
## 122 - CREDITS
GRAFICS DIBUIXATS PER
## 123 - CREDITS
MUSICA COMPOSADA PER
## 124 - CREDITS
EFECTES DE SO

View File

@@ -360,3 +360,15 @@ Stop!
## 120 - SCOREBOARD ## 120 - SCOREBOARD
Score Score
## 121 - CREDITS
PROGRAMMED AND DESIGNED BY
## 122 - CREDITS
PIXELART DRAWN BY
## 123 - CREDITS
MUSIC COMPOSED BY
## 124 - CREDITS
SOUND EFFECTS

View File

@@ -360,3 +360,15 @@ Tiempo!
## 120 - SCOREBOARD ## 120 - SCOREBOARD
Puntuacion Puntuacion
## 121 - CREDITS
PROGRAMADO Y DISE{ADO POR
## 122 - CREDITS
GRAFICOS DIBUJADOS POR
## 123 - CREDITS
MUSICA COMPUESTA POR
## 124 - CREDITS
EFECTOS DE SONIDO

234
data/shaders/crtpi_240.glsl Normal file
View File

@@ -0,0 +1,234 @@
/*
crt-pi - A Raspberry Pi friendly CRT shader.
Copyright (C) 2015-2016 davej
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
Notes:
This shader is designed to work well on Raspberry Pi GPUs (i.e. 1080P @ 60Hz on a game with a 4:3 aspect ratio). It pushes the Pi's GPU hard and enabling some features will slow it down so that it is no longer able to match 1080P @ 60Hz. You will need to overclock your Pi to the fastest setting in raspi-config to get the best results from this shader: 'Pi2' for Pi2 and 'Turbo' for original Pi and Pi Zero. Note: Pi2s are slower at running the shader than other Pis, this seems to be down to Pi2s lower maximum memory speed. Pi2s don't quite manage 1080P @ 60Hz - they drop about 1 in 1000 frames. You probably won't notice this, but if you do, try enabling FAKE_GAMMA.
SCANLINES enables scanlines. You'll almost certainly want to use it with MULTISAMPLE to reduce moire effects. SCANLINE_WEIGHT defines how wide scanlines are (it is an inverse value so a higher number = thinner lines). SCANLINE_GAP_BRIGHTNESS defines how dark the gaps between the scan lines are. Darker gaps between scan lines make moire effects more likely.
GAMMA enables gamma correction using the values in INPUT_GAMMA and OUTPUT_GAMMA. FAKE_GAMMA causes it to ignore the values in INPUT_GAMMA and OUTPUT_GAMMA and approximate gamma correction in a way which is faster than true gamma whilst still looking better than having none. You must have GAMMA defined to enable FAKE_GAMMA.
CURVATURE distorts the screen by CURVATURE_X and CURVATURE_Y. Curvature slows things down a lot.
By default the shader uses linear blending horizontally. If you find this too blury, enable SHARPER.
BLOOM_FACTOR controls the increase in width for bright scanlines.
MASK_TYPE defines what, if any, shadow mask to use. MASK_BRIGHTNESS defines how much the mask type darkens the screen.
*/
#pragma parameter CURVATURE_X "Screen curvature - horizontal" 0.10 0.0 1.0 0.01
#pragma parameter CURVATURE_Y "Screen curvature - vertical" 0.15 0.0 1.0 0.01
#pragma parameter MASK_BRIGHTNESS "Mask brightness" 0.70 0.0 1.0 0.01
#pragma parameter SCANLINE_WEIGHT "Scanline weight" 6.0 0.0 15.0 0.1
#pragma parameter SCANLINE_GAP_BRIGHTNESS "Scanline gap brightness" 0.12 0.0 1.0 0.01
#pragma parameter BLOOM_FACTOR "Bloom factor" 1.5 0.0 5.0 0.01
#pragma parameter INPUT_GAMMA "Input gamma" 2.4 0.0 5.0 0.01
#pragma parameter OUTPUT_GAMMA "Output gamma" 2.2 0.0 5.0 0.01
// Haven't put these as parameters as it would slow the code down.
#define SCANLINES
#define MULTISAMPLE
#define GAMMA
//#define FAKE_GAMMA
//#define CURVATURE
//#define SHARPER
// MASK_TYPE: 0 = none, 1 = green/magenta, 2 = trinitron(ish)
#define MASK_TYPE 2
#ifdef GL_ES
#define COMPAT_PRECISION mediump
precision mediump float;
#else
#define COMPAT_PRECISION
#endif
#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float CURVATURE_X;
uniform COMPAT_PRECISION float CURVATURE_Y;
uniform COMPAT_PRECISION float MASK_BRIGHTNESS;
uniform COMPAT_PRECISION float SCANLINE_WEIGHT;
uniform COMPAT_PRECISION float SCANLINE_GAP_BRIGHTNESS;
uniform COMPAT_PRECISION float BLOOM_FACTOR;
uniform COMPAT_PRECISION float INPUT_GAMMA;
uniform COMPAT_PRECISION float OUTPUT_GAMMA;
#else
#define CURVATURE_X 0.05
#define CURVATURE_Y 0.1
#define MASK_BRIGHTNESS 0.80
#define SCANLINE_WEIGHT 6.0
#define SCANLINE_GAP_BRIGHTNESS 0.12
#define BLOOM_FACTOR 3.5
#define INPUT_GAMMA 2.4
#define OUTPUT_GAMMA 2.2
#endif
/* COMPATIBILITY
- GLSL compilers
*/
//uniform vec2 TextureSize;
#if defined(CURVATURE)
varying vec2 screenScale;
#endif
varying vec2 TEX0;
varying float filterWidth;
#if defined(VERTEX)
//uniform mat4 MVPMatrix;
//attribute vec4 VertexCoord;
//attribute vec2 TexCoord;
//uniform vec2 InputSize;
//uniform vec2 OutputSize;
void main()
{
#if defined(CURVATURE)
screenScale = vec2(1.0, 1.0); //TextureSize / InputSize;
#endif
filterWidth = (768.0 / 240.0) / 3.0;
TEX0 = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
#elif defined(FRAGMENT)
uniform sampler2D Texture;
#if defined(CURVATURE)
vec2 Distort(vec2 coord)
{
vec2 CURVATURE_DISTORTION = vec2(CURVATURE_X, CURVATURE_Y);
// Barrel distortion shrinks the display area a bit, this will allow us to counteract that.
vec2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION);
coord *= screenScale;
coord -= vec2(0.5);
float rsq = coord.x * coord.x + coord.y * coord.y;
coord += coord * (CURVATURE_DISTORTION * rsq);
coord *= barrelScale;
if (abs(coord.x) >= 0.5 || abs(coord.y) >= 0.5)
coord = vec2(-1.0); // If out of bounds, return an invalid value.
else
{
coord += vec2(0.5);
coord /= screenScale;
}
return coord;
}
#endif
float CalcScanLineWeight(float dist)
{
return max(1.0-dist*dist*SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS);
}
float CalcScanLine(float dy)
{
float scanLineWeight = CalcScanLineWeight(dy);
#if defined(MULTISAMPLE)
scanLineWeight += CalcScanLineWeight(dy-filterWidth);
scanLineWeight += CalcScanLineWeight(dy+filterWidth);
scanLineWeight *= 0.3333333;
#endif
return scanLineWeight;
}
void main()
{
vec2 TextureSize = vec2(320.0, 240.0);
#if defined(CURVATURE)
vec2 texcoord = Distort(TEX0);
if (texcoord.x < 0.0)
gl_FragColor = vec4(0.0);
else
#else
vec2 texcoord = TEX0;
#endif
{
vec2 texcoordInPixels = texcoord * TextureSize;
#if defined(SHARPER)
vec2 tempCoord = floor(texcoordInPixels) + 0.5;
vec2 coord = tempCoord / TextureSize;
vec2 deltas = texcoordInPixels - tempCoord;
float scanLineWeight = CalcScanLine(deltas.y);
vec2 signs = sign(deltas);
deltas.x *= 2.0;
deltas = deltas * deltas;
deltas.y = deltas.y * deltas.y;
deltas.x *= 0.5;
deltas.y *= 8.0;
deltas /= TextureSize;
deltas *= signs;
vec2 tc = coord + deltas;
#else
float tempY = floor(texcoordInPixels.y) + 0.5;
float yCoord = tempY / TextureSize.y;
float dy = texcoordInPixels.y - tempY;
float scanLineWeight = CalcScanLine(dy);
float signY = sign(dy);
dy = dy * dy;
dy = dy * dy;
dy *= 8.0;
dy /= TextureSize.y;
dy *= signY;
vec2 tc = vec2(texcoord.x, yCoord + dy);
#endif
vec3 colour = texture2D(Texture, tc).rgb;
#if defined(SCANLINES)
#if defined(GAMMA)
#if defined(FAKE_GAMMA)
colour = colour * colour;
#else
colour = pow(colour, vec3(INPUT_GAMMA));
#endif
#endif
scanLineWeight *= BLOOM_FACTOR;
colour *= scanLineWeight;
#if defined(GAMMA)
#if defined(FAKE_GAMMA)
colour = sqrt(colour);
#else
colour = pow(colour, vec3(1.0/OUTPUT_GAMMA));
#endif
#endif
#endif
#if MASK_TYPE == 0
gl_FragColor = vec4(colour, 1.0);
#else
#if MASK_TYPE == 1
float whichMask = fract((gl_FragCoord.x*1.0001) * 0.5);
vec3 mask;
if (whichMask < 0.5)
mask = vec3(MASK_BRIGHTNESS, 1.0, MASK_BRIGHTNESS);
else
mask = vec3(1.0, MASK_BRIGHTNESS, 1.0);
#elif MASK_TYPE == 2
float whichMask = fract((gl_FragCoord.x*1.0001) * 0.3333333);
vec3 mask = vec3(MASK_BRIGHTNESS, MASK_BRIGHTNESS, MASK_BRIGHTNESS);
if (whichMask < 0.3333333)
mask.x = 1.0;
else if (whichMask < 0.6666666)
mask.y = 1.0;
else
mask.z = 1.0;
#endif
gl_FragColor = vec4(colour * mask, 1.0);
#endif
}
}
#endif

View File

@@ -97,7 +97,6 @@ void main()
#if defined(CURVATURE) #if defined(CURVATURE)
screenScale = vec2(1.0, 1.0); //TextureSize / InputSize; screenScale = vec2(1.0, 1.0); //TextureSize / InputSize;
#endif #endif
//filterWidth = (768.0 / 240.0) / 3.0;
filterWidth = (768.0 / 256.0) / 3.0; filterWidth = (768.0 / 256.0) / 3.0;
TEX0 = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001; TEX0 = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

BIN
data/sound/logo.wav Normal file

Binary file not shown.

View File

@@ -303,7 +303,7 @@ int BalloonManager::destroyAllBalloons()
balloon_deploy_counter_ = 300; balloon_deploy_counter_ = 300;
JA_PlaySound(Resource::get()->getSound("powerball.wav")); JA_PlaySound(Resource::get()->getSound("powerball.wav"));
Screen::get()->flash(flash_color, 100); Screen::get()->flash(flash_color, 3);
Screen::get()->shake(); Screen::get()->shake();
return score; return score;

View File

@@ -1,27 +1,27 @@
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include "credits.h" #include "credits.h"
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT #include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_rect.h> // Para SDL_Rect #include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks #include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <string> // Para basic_string, string #include <algorithm>
#include <vector> // Para vector #include <cstdlib>
#include "balloon_manager.h" // Para BalloonManager #include <string> // Para basic_string, string
#include "global_inputs.h" // Para check #include <vector> // Para vector
#include "input.h" // Para Input #include "balloon_manager.h" // Para BalloonManager
#include "jail_audio.h" // Para JA_PlayMusic, JA_StopMusic #include "global_inputs.h" // Para check
#include "param.h" // Para Param, ParamGame, param #include "input.h" // Para Input
#include "resource.h" // Para Resource #include "jail_audio.h" // Para JA_PlayMusic, JA_StopMusic
#include "screen.h" // Para Screen #include "param.h" // Para Param, ParamGame, param
#include "section.h" // Para Name, name, Options, options #include "resource.h" // Para Resource
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW #include "screen.h" // Para Screen
#include "tiled_bg.h" // Para TiledBG, TiledBGMode #include "section.h" // Para Name, name, Options, options
#include "utils.h" // Para Color, no_color, shdw_txt_color, Zone #include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
#include "utils.h" // Para Color, no_color, shdw_txt_color, Zone
#include "player.h" #include "player.h"
#include "fade.h" #include "fade.h"
#include "lang.h"
// Textos // Textos
constexpr const char TEXT_COPYRIGHT[] = "@2020,2024 JailDesigner"; constexpr const char TEXT_COPYRIGHT[] = "@2020,2024 JailDesigner";
@@ -34,22 +34,28 @@ Credits::Credits()
fade_in_(std::make_unique<Fade>()), fade_in_(std::make_unique<Fade>()),
fade_out_(std::make_unique<Fade>()) fade_out_(std::make_unique<Fade>())
{ {
if (!text_texture_)
{
throw std::runtime_error("Failed to create SDL texture for text.");
}
section::name = section::Name::CREDITS; section::name = section::Name::CREDITS;
top_black_rect_ = {play_area_.x, 0, play_area_.w, black_bars_size_}; //top_black_rect_ = {play_area_.x, 0, play_area_.w, black_bars_size_};
bottom_black_rect_ = {play_area_.x, param.game.game_area.rect.h - black_bars_size_, play_area_.w, black_bars_size_}; //bottom_black_rect_ = {play_area_.x, param.game.game_area.rect.h - black_bars_size_, play_area_.w, black_bars_size_};
balloon_manager_->setPlayArea(play_area_); balloon_manager_->setPlayArea(play_area_);
fade_in_->setColor(fade_color.r, fade_color.g, fade_color.b); fade_in_->setColor(fade_color.r, fade_color.g, fade_color.b);
fade_in_->setType(FadeType::FULLSCREEN); fade_in_->setType(FadeType::FULLSCREEN);
fade_in_->setPost(50); fade_in_->setPost(50);
fade_in_->setMode(FadeMode::IN); fade_in_->setMode(FadeMode::IN);
fade_in_->activate(); fade_in_->activate();
fade_out_->setColor(0, 0, 0); fade_out_->setColor(0, 0, 0);
fade_out_->setType(FadeType::FULLSCREEN); fade_out_->setType(FadeType::FULLSCREEN);
fade_out_->setPost(400); fade_out_->setPost(400);
initPlayers(); initPlayers();
SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND);
fillTextTexture(); fillTextTexture();
// JA_PlayMusic(Resource::get()->getMusic("credits.ogg"));
steps_ = std::abs((top_black_rect_.h - param.game.game_area.center_y - 1) + ((left_black_rect_.w - param.game.game_area.center_x) / 4)); steps_ = std::abs((top_black_rect_.h - param.game.game_area.center_y - 1) + ((left_black_rect_.w - param.game.game_area.center_x) / 4));
} }
@@ -88,6 +94,7 @@ void Credits::update()
} }
updateAllFades(); updateAllFades();
Screen::get()->update(); Screen::get()->update();
globalInputs::update();
++counter_; ++counter_;
} }
} }
@@ -116,20 +123,19 @@ void Credits::render()
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_); SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_);
// Dibuja los rectangulos negros // Dibuja los rectangulos negros
// SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0x27, 0x27, 0x36, 255);
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 255); SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 255);
SDL_RenderFillRect(Screen::get()->getRenderer(), &top_black_rect_); SDL_RenderFillRect(Screen::get()->getRenderer(), &top_black_rect_);
SDL_RenderFillRect(Screen::get()->getRenderer(), &bottom_black_rect_); SDL_RenderFillRect(Screen::get()->getRenderer(), &bottom_black_rect_);
SDL_RenderFillRect(Screen::get()->getRenderer(), &left_black_rect_); SDL_RenderFillRect(Screen::get()->getRenderer(), &left_black_rect_);
SDL_RenderFillRect(Screen::get()->getRenderer(), &right_black_rect_); SDL_RenderFillRect(Screen::get()->getRenderer(), &right_black_rect_);
// Si el mini_logo está en su destino, lo dibuja encima del resto // Si el mini_logo está en su destino, lo dibuja encima de lo anterior
if (mini_logo_on_position_) if (mini_logo_on_position_)
{ {
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_); SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_);
} }
// Dibuja el fade sobre el resto // Dibuja el fade sobre el resto de elementos
fade_in_->render(); fade_in_->render();
fade_out_->render(); fade_out_->render();
@@ -170,7 +176,7 @@ void Credits::checkInput()
{ {
// Si todavía estan los creditos en marcha, se pasan solos a toda pastilla // Si todavía estan los creditos en marcha, se pasan solos a toda pastilla
want_to_pass_ = true; want_to_pass_ = true;
ticks_speed_ = 3; ticks_speed_ = 1;
} }
} }
@@ -188,10 +194,10 @@ void Credits::fillTextTexture()
SDL_RenderClear(Screen::get()->getRenderer()); SDL_RenderClear(Screen::get()->getRenderer());
std::vector<std::string> texts = { std::vector<std::string> texts = {
"PROGRAMACIO I DISSENY", lang::getText(121),
"GRAFICS", lang::getText(122),
"MUSICA", lang::getText(123),
"SONS", lang::getText(124),
"JAILDESIGNER", "JAILDESIGNER",
"JAILDOCTOR (INTRO)", "JAILDOCTOR (INTRO)",
"ERIC MATYAS (SOUNDIMAGE.ORG)", "ERIC MATYAS (SOUNDIMAGE.ORG)",
@@ -257,10 +263,11 @@ void Credits::fillTextTexture()
y += mini_logo_sprite->getHeight() + 3; y += mini_logo_sprite->getHeight() + 3;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXT_COPYRIGHT, 1, no_color, 1, shdw_txt_color); text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXT_COPYRIGHT, 1, no_color, 1, shdw_txt_color);
mini_logo_rect_dst_.h = mini_logo_rect_src_.h = mini_logo_sprite->getHeight() + 3 + text->getCharacterSize(); // Resetea el renderizador
SDL_SetRenderTarget(Screen::get()->getRenderer(), nullptr); SDL_SetRenderTarget(Screen::get()->getRenderer(), nullptr);
// Actualiza las variables
mini_logo_rect_dst_.h = mini_logo_rect_src_.h = mini_logo_sprite->getHeight() + 3 + text->getCharacterSize();
credits_rect_dst_.y = param.game.game_area.rect.h; credits_rect_dst_.y = param.game.game_area.rect.h;
mini_logo_rect_dst_.y = credits_rect_dst_.y + credits_rect_dst_.h + 30; mini_logo_rect_dst_.y = credits_rect_dst_.y + credits_rect_dst_.h + 30;
mini_logo_final_pos_ = param.game.game_area.center_y - mini_logo_rect_src_.h / 2; mini_logo_final_pos_ = param.game.game_area.center_y - mini_logo_rect_src_.h / 2;
@@ -312,7 +319,9 @@ void Credits::throwBalloons()
const std::vector<int> sets = {0, 63, 25, 67, 17, 75, 13, 50}; const std::vector<int> sets = {0, 63, 25, 67, 17, 75, 13, 50};
if (counter_ > ((sets.size() - 1) * speed) * 3) if (counter_ > ((sets.size() - 1) * speed) * 3)
{
return; return;
}
if (counter_ % speed == 0) if (counter_ % speed == 0)
{ {

View File

@@ -10,6 +10,8 @@ class TiledBG;
class Player; class Player;
class Fade; class Fade;
constexpr int PLAY_AREA_HEIGHT = 200;
class Credits class Credits
{ {
private: private:
@@ -22,18 +24,18 @@ private:
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
// Variables // Variables
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticks_speed_ = 15; // Velocidad del bucle update Uint32 ticks_speed_ = 15; // Velocidad del bucle update
Uint32 counter_ = 0; // Contador para la lógica de la clase Uint32 counter_ = 0; // Contador para la lógica de la clase
Uint32 counter_pre_fade_ = 0; // Contador para activar el fundido final Uint32 counter_pre_fade_ = 0; // Contador para activar el fundido final
Uint32 counter_prevent_endless_ = 0; // Contador para evitar que el juego se quede para siempre en los creditos Uint32 counter_prevent_endless_ = 0; // Contador para evitar que el juego se quede para siempre en los creditos
int black_bars_size_ = 28; // Tamaño de las barras negras int black_bars_size_ = (param.game.game_area.rect.h - PLAY_AREA_HEIGHT) / 2; // Tamaño de las barras negras
int mini_logo_final_pos_ = 0; // Ubicación donde se detiene el minilogo int mini_logo_final_pos_ = 0; // Ubicación donde se detiene el minilogo
bool fading_ = false; // Indica si se está realizando el fade final bool fading_ = false; // Indica si se está realizando el fade final
bool want_to_pass_ = false; // Indica si el jugador quiere saltarse los titulos de crédito bool want_to_pass_ = false; // Indica si el jugador quiere saltarse los titulos de crédito
bool mini_logo_on_position_ = false; // Indica si el minilogo ya se ha quedado en su posición bool mini_logo_on_position_ = false; // Indica si el minilogo ya se ha quedado en su posición
int initial_volume_ = options.audio.music.volume; // Volumen actual al crear el objeto int initial_volume_ = options.audio.music.volume; // Volumen actual al crear el objeto
int steps_ = 0; // Cantidad de pasos a dar para ir reduciendo el audio int steps_ = 0; // Cantidad de pasos a dar para ir reduciendo el audio
// Rectangulos // Rectangulos
SDL_Rect credits_rect_src_ = param.game.game_area.rect; // Rectangulo con el texto de los créditos (origen) SDL_Rect credits_rect_src_ = param.game.game_area.rect; // Rectangulo con el texto de los créditos (origen)
@@ -44,7 +46,7 @@ private:
param.game.game_area.rect.x, param.game.game_area.rect.x,
param.game.game_area.rect.y + black_bars_size_, param.game.game_area.rect.y + black_bars_size_,
param.game.game_area.rect.w, param.game.game_area.rect.w,
param.game.game_area.rect.h - black_bars_size_}; // Area visible para los creditos PLAY_AREA_HEIGHT}; // Area visible para los creditos
SDL_Rect top_black_rect_ = {play_area_.x, 0, play_area_.w, black_bars_size_}; // Rectangulo negro superior SDL_Rect top_black_rect_ = {play_area_.x, 0, play_area_.w, black_bars_size_}; // Rectangulo negro superior
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 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 left_black_rect_ = {play_area_.x, param.game.game_area.center_y - 1, 0, 2}; // Rectangulo negro situado a la izquierda

View File

@@ -1,3 +1,4 @@
// IWYU pragma: no_include <bits/chrono.h>
#include "director.h" #include "director.h"
#include <SDL2/SDL.h> // Para SDL_Init, SDL_Quit, SDL_INIT_EV... #include <SDL2/SDL.h> // Para SDL_Init, SDL_Quit, SDL_INIT_EV...
#include <SDL2/SDL_audio.h> // Para AUDIO_S16 #include <SDL2/SDL_audio.h> // Para AUDIO_S16
@@ -7,7 +8,7 @@
#include <SDL2/SDL_hints.h> // Para SDL_SetHint, SDL_HINT_RENDER_DR... #include <SDL2/SDL_hints.h> // Para SDL_SetHint, SDL_HINT_RENDER_DR...
#include <SDL2/SDL_scancode.h> // Para SDL_SCANCODE_0, SDL_SCANCODE_DOWN #include <SDL2/SDL_scancode.h> // Para SDL_SCANCODE_0, SDL_SCANCODE_DOWN
#include <SDL2/SDL_stdinc.h> // Para SDL_bool, Uint32 #include <SDL2/SDL_stdinc.h> // Para SDL_bool, Uint32
#include <bits/chrono.h> // Para duration, system_clock #include <chrono> // Para duration, system_clock
#include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO... #include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO...
#include <stdio.h> // Para printf, perror #include <stdio.h> // Para printf, perror
#include <sys/stat.h> // Para mkdir, stat, S_IRWXU #include <sys/stat.h> // Para mkdir, stat, S_IRWXU
@@ -20,7 +21,7 @@
#include <string> // Para operator+, char_traits, allocator #include <string> // Para operator+, char_traits, allocator
#include <vector> // Para vector #include <vector> // Para vector
#include "asset.h" // Para Asset, AssetType #include "asset.h" // Para Asset, AssetType
#include "credits.h" #include "credits.h" // Para Credits
#include "dbgtxt.h" // Para dbg_init #include "dbgtxt.h" // Para dbg_init
#include "game.h" // Para Game, GAME_MODE_DEMO_OFF, GAME_... #include "game.h" // Para Game, GAME_MODE_DEMO_OFF, GAME_...
#include "global_inputs.h" // Para init #include "global_inputs.h" // Para init
@@ -46,13 +47,6 @@
#include <pwd.h> // para getpwuid, passwd #include <pwd.h> // para getpwuid, passwd
#endif #endif
// Inicia la semilla aleatoria
void initRand()
{
unsigned int seed = static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count());
std::srand(seed);
}
// Constructor // Constructor
Director::Director(int argc, const char *argv[]) Director::Director(int argc, const char *argv[])
{ {
@@ -60,7 +54,7 @@ Director::Director(int argc, const char *argv[])
section::name = section::Name::GAME; section::name = section::Name::GAME;
section::options = section::Options::GAME_PLAY_1P; section::options = section::Options::GAME_PLAY_1P;
#elif DEBUG #elif DEBUG
section::name = section::Name::LOGO; section::name = section::Name::CREDITS;
#else // NORMAL GAME #else // NORMAL GAME
section::name = section::Name::LOGO; section::name = section::Name::LOGO;
section::attract_mode = section::AttractMode::TITLE_TO_DEMO; section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
@@ -74,42 +68,36 @@ Director::Director(int argc, const char *argv[])
std::cout << "Game start" << std::endl; std::cout << "Game start" << std::endl;
initRand(); // Inicia la semilla aleatoria
unsigned int seed = static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count());
std::srand(seed);
// Comprueba los parametros del programa // Comprueba los parametros del programa
checkProgramArguments(argc, argv); checkProgramArguments(argc, argv);
// Crea la carpeta del sistema donde guardar datos // Crea la carpeta del sistema donde guardar los datos persistentes
createSystemFolder("jailgames"); createSystemFolder("jailgames");
createSystemFolder("jailgames/coffee_crisis_arcade_edition"); createSystemFolder("jailgames/coffee_crisis_arcade_edition");
// Crea el objeto que controla los ficheros de recursos init();
Asset::init(executable_path_); }
// Crea el indice de ficheros Director::~Director()
setFileList(); {
close();
std::cout << "\nBye!" << std::endl;
}
// Carga el fichero de configuración // Inicializa todo
loadOptionsFile(Asset::get()->get("config.txt")); void Director::init()
{
Asset::init(executable_path_); // Crea el objeto que controla los ficheros de recursos
setFileList(); // Crea el indice de ficheros
loadOptionsFile(Asset::get()->get("config.txt")); // Carga el fichero de configuración
loadParams(); // Carga los parametros
loadScoreFile(); // Carga el fichero de puntuaciones
// Carga los parametros para configurar el juego // Inicializa y crea el resto de objetos
#ifdef ANBERNIC
const std::string paramFilePath = asset->get("param_320x240.txt");
#else
const std::string paramFilePath = overrides.param_file == "--320x240" ? Asset::get()->get("param_320x240.txt") : Asset::get()->get("param_320x256.txt");
#endif
loadParamsFromFile(paramFilePath);
// Carga el fichero de puntuaciones
{
auto manager = std::make_unique<ManageHiScoreTable>(options.game.hi_score_table);
if (overrides.clear_hi_score_table)
manager->clear();
else
manager->loadFromFile(Asset::get()->get("score.bin"));
}
// Inicializa todo
initSDL(); initSDL();
initJailAudio(); initJailAudio();
dbg_init(renderer_); dbg_init(renderer_);
@@ -118,12 +106,12 @@ Director::Director(int argc, const char *argv[])
Resource::init(); Resource::init();
Input::init(Asset::get()->get("gamecontrollerdb.txt")); Input::init(Asset::get()->get("gamecontrollerdb.txt"));
bindInputs(); bindInputs();
Notifier::init(std::string(), Resource::get()->getText("8bithud"), Asset::get()->get("notify.wav")); Notifier::init(std::string(), Resource::get()->getText("8bithud"));
OnScreenHelp::init(); OnScreenHelp::init();
globalInputs::init();
} }
Director::~Director() // Cierra todo
void Director::close()
{ {
saveOptionsFile(Asset::get()->get("config.txt")); saveOptionsFile(Asset::get()->get("config.txt"));
@@ -134,12 +122,38 @@ Director::~Director()
Notifier::destroy(); Notifier::destroy();
OnScreenHelp::destroy(); OnScreenHelp::destroy();
JA_Quit();
SDL_DestroyRenderer(renderer_); SDL_DestroyRenderer(renderer_);
SDL_DestroyWindow(window_); SDL_DestroyWindow(window_);
SDL_Quit(); SDL_Quit();
}
std::cout << "\nBye!" << std::endl; // Carga los parametros
void Director::loadParams()
{
// Carga los parametros para configurar el juego
#ifdef ANBERNIC
const std::string paramFilePath = asset->get("param_320x240.txt");
#else
const std::string paramFilePath = overrides.param_file == "--320x240" ? Asset::get()->get("param_320x240.txt") : Asset::get()->get("param_320x256.txt");
#endif
loadParamsFromFile(paramFilePath);
}
// Carga el fichero de puntuaciones
void Director::loadScoreFile()
{
auto manager = std::make_unique<ManageHiScoreTable>(options.game.hi_score_table);
if (overrides.clear_hi_score_table)
{
manager->clear();
}
else
{
manager->loadFromFile(Asset::get()->get("score.bin"));
}
} }
// Asigna los botones y teclas al objeto Input // Asigna los botones y teclas al objeto Input
@@ -166,7 +180,8 @@ void Director::bindInputs()
Input::get()->bindKey(InputType::WINDOW_FULLSCREEN, SDL_SCANCODE_F3); Input::get()->bindKey(InputType::WINDOW_FULLSCREEN, SDL_SCANCODE_F3);
Input::get()->bindKey(InputType::VIDEO_SHADERS, SDL_SCANCODE_F4); Input::get()->bindKey(InputType::VIDEO_SHADERS, SDL_SCANCODE_F4);
Input::get()->bindKey(InputType::MUTE, SDL_SCANCODE_F5); Input::get()->bindKey(InputType::MUTE, SDL_SCANCODE_F5);
Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F6); Input::get()->bindKey(InputType::CHANGE_LANG, SDL_SCANCODE_F6);
Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F7);
Input::get()->bindKey(InputType::RESET, SDL_SCANCODE_F10); Input::get()->bindKey(InputType::RESET, SDL_SCANCODE_F10);
// Asigna botones a inputs // Asigna botones a inputs
@@ -381,9 +396,11 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/sound/clock.wav", AssetType::SOUND); Asset::get()->add(prefix + "/data/sound/clock.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/powerball.wav", AssetType::SOUND); Asset::get()->add(prefix + "/data/sound/powerball.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/notify.wav", AssetType::SOUND); Asset::get()->add(prefix + "/data/sound/notify.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/logo.wav", AssetType::SOUND);
// Shaders // Shaders
Asset::get()->add(prefix + "/data/shaders/crtpi.glsl", AssetType::DATA); Asset::get()->add(prefix + "/data/shaders/crtpi_256.glsl", AssetType::DATA);
Asset::get()->add(prefix + "/data/shaders/crtpi_240.glsl", AssetType::DATA);
// Texturas // Texturas
@@ -663,6 +680,7 @@ int Director::run()
switch (section::name) switch (section::name)
{ {
case section::Name::INIT: case section::Name::INIT:
Resource::get()->reload();
section::name = section::Name::LOGO; section::name = section::Name::LOGO;
break; break;
case section::Name::LOGO: case section::Name::LOGO:

View File

@@ -74,6 +74,18 @@ private:
void shutdownSystem(); void shutdownSystem();
#endif #endif
// Inicializa todo
void init();
// Cierra todo
void close();
// Carga los parametros
void loadParams();
// Carga el fichero de puntuaciones
void loadScoreFile();
public: public:
// Constructor // Constructor
Director(int argc, const char *argv[]); Director(int argc, const char *argv[]);

View File

@@ -253,7 +253,7 @@ void Game::updateStage()
++Stage::number; ++Stage::number;
JA_PlaySound(Resource::get()->getSound("stage_change.wav")); JA_PlaySound(Resource::get()->getSound("stage_change.wav"));
balloon_manager_->resetBalloonSpeed(); balloon_manager_->resetBalloonSpeed();
screen_->flash(flash_color, 100); screen_->flash(flash_color, 3);
screen_->shake(); screen_->shake();
// Escribe el texto por pantalla // Escribe el texto por pantalla
@@ -869,6 +869,7 @@ void Game::update()
checkMusicStatus(); checkMusicStatus();
screen_->update(); screen_->update();
globalInputs::update();
fillCanvas(); fillCanvas();
} }
} }
@@ -1169,7 +1170,7 @@ void Game::checkEvents()
} }
case SDLK_7: // Flash case SDLK_7: // Flash
{ {
screen_->flash(flash_color, 100); screen_->flash(flash_color, 3);
break; break;
} }
case SDLK_8: case SDLK_8:

View File

@@ -1,6 +1,7 @@
#include "global_inputs.h" #include "global_inputs.h"
#include <string> // Para operator+, string #include <string> // Para operator+, string
#include "input.h" // Para Input, InputType, INPUT_DO_NOT_ALLOW_REPEAT #include "input.h" // Para Input, InputType, INPUT_DO_NOT_ALLOW_REPEAT
#include "asset.h"
#include "jail_audio.h" // Para JA_EnableMusic, JA_EnableSound #include "jail_audio.h" // Para JA_EnableMusic, JA_EnableSound
#include "lang.h" // Para getText #include "lang.h" // Para getText
#include "notifier.h" // Para Notifier #include "notifier.h" // Para Notifier
@@ -13,18 +14,8 @@
namespace globalInputs namespace globalInputs
{ {
// Variables // Variables
std::vector<int> service_pressed_counter; int service_pressed_counter = 0;
bool service_pressed = false;
// Inicializa variables
void init()
{
const auto num_inputs = Input::get()->getNumControllers() + 1;
service_pressed_counter.reserve(num_inputs);
for (int i = 0; i < num_inputs; ++i)
{
service_pressed_counter.push_back(0);
}
}
// Termina // Termina
void quit(section::Options code) void quit(section::Options code)
@@ -33,11 +24,13 @@ namespace globalInputs
auto code_found = stringInVector(Notifier::get()->getCodes(), exit_code); auto code_found = stringInVector(Notifier::get()->getCodes(), exit_code);
if (code_found) if (code_found)
{ {
// Si la notificación de salir está activa, cambia de sección
section::name = section::Name::QUIT; section::name = section::Name::QUIT;
section::options = code; section::options = code;
} }
else else
{ {
// Si la notificación de salir no está activa, muestra la notificación
#ifdef ARCADE #ifdef ARCADE
const int index = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94; const int index = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94;
Notifier::get()->showText({lang::getText(index), std::string()}, -1, exit_code); Notifier::get()->showText({lang::getText(index), std::string()}, -1, exit_code);
@@ -71,6 +64,49 @@ namespace globalInputs
Notifier::get()->showText({"Audio " + boolToOnOff(options.audio.enabled)}); Notifier::get()->showText({"Audio " + boolToOnOff(options.audio.enabled)});
} }
// Obtiene una fichero a partir de un lang::Code
std::string getLangFile(lang::Code code)
{
switch (code)
{
case lang::Code::ba_BA:
return Asset::get()->get("ba_BA.txt");
break;
case lang::Code::es_ES:
return Asset::get()->get("es_ES.txt");
break;
default:
return Asset::get()->get("en_UK.txt");
break;
}
}
// Obtiene una cadena a partir de un lang::Code
std::string getLangName(lang::Code code)
{
switch (code)
{
case lang::Code::ba_BA:
return "ba_BA";
break;
case lang::Code::es_ES:
return "es_ES";
break;
default:
return "en_UK";
break;
}
}
// Cambia el idioma
void changeLang()
{
options.game.language = lang::change(options.game.language);
lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language)));
section::name = section::Name::INIT;
Notifier::get()->showText({getLangName(options.game.language)});
}
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
void check() void check()
{ {
@@ -125,6 +161,13 @@ namespace globalInputs
return; return;
} }
// Idioma
if (Input::get()->checkInput(InputType::CHANGE_LANG, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
changeLang();
return;
}
// Shaders // Shaders
if (Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD)) if (Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{ {
@@ -143,17 +186,9 @@ namespace globalInputs
// OnScreenHelp // OnScreenHelp
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD)) if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{ {
service_pressed_counter[0]++; service_pressed = true;
if (service_pressed_counter[0] >= 3000)
{
OnScreenHelp::get()->toggleState();
service_pressed_counter[0] = 0;
}
return; return;
} }
service_pressed_counter[0] = 0;
} }
// Mandos // Mandos
@@ -203,18 +238,30 @@ namespace globalInputs
// OnScreenHelp // OnScreenHelp
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i)) if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{ {
service_pressed_counter[i + 1]++; service_pressed = true;
if (service_pressed_counter[i + 1] >= 3000)
{
OnScreenHelp::get()->toggleState();
service_pressed_counter[i + 1] = 0;
}
return; return;
} }
service_pressed_counter[i + 1] = 0;
} }
} }
} }
// Actualiza variables
void update()
{
if (service_pressed)
{
++service_pressed_counter;
if (service_pressed_counter >= 200)
{
OnScreenHelp::get()->toggleState();
service_pressed_counter = 0;
}
}
else
{
service_pressed_counter = 0;
}
service_pressed = false;
}
} }

View File

@@ -1,11 +1,12 @@
#include <vector> #include <vector>
namespace globalInputs namespace globalInputs
{ {
extern std::vector<int> service_pressed_counter; extern int service_pressed_counter;
extern bool service_pressed;
// Inicializa variables
void init();
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
void check(); void check();
// Actualiza variables
void update();
} }

View File

@@ -77,6 +77,9 @@ void HiScoreTable::update()
// Actualiza el objeto screen // Actualiza el objeto screen
Screen::get()->update(); Screen::get()->update();
// Actualiza las variables de globalInputs
globalInputs::update();
// Actualiza el fondo // Actualiza el fondo
background_->update(); background_->update();

View File

@@ -40,6 +40,7 @@ enum class InputType : int
VIDEO_SHADERS, VIDEO_SHADERS,
RESET, RESET,
MUTE, MUTE,
CHANGE_LANG,
SHOWINFO, SHOWINFO,
CONFIG, CONFIG,
SWAP_CONTROLLERS, SWAP_CONTROLLERS,

View File

@@ -216,6 +216,9 @@ void Instructions::update()
// Actualiza el objeto screen // Actualiza el objeto screen
Screen::get()->update(); Screen::get()->update();
// Actualiza las variables de globalInputs
globalInputs::update();
// Incrementa el contador // Incrementa el contador
counter_++; counter_++;

View File

@@ -382,6 +382,9 @@ void Intro::update()
// Actualiza las escenas de la intro // Actualiza las escenas de la intro
updateScenes(); updateScenes();
// Actualiza las variables de globalInputs
globalInputs::update();
} }
} }

View File

@@ -40,4 +40,12 @@ namespace lang
{ {
return texts.at(index); return texts.at(index);
} }
// Cambia el idioma seleccionado al siguiente idioma disponible
Code change(Code current_lang)
{
auto index = static_cast<int>(current_lang);
index = (index + 1) % 3;
return static_cast<Code>(index);
}
} }

View File

@@ -16,4 +16,7 @@ namespace lang
// Obtiene la cadena de texto del indice // Obtiene la cadena de texto del indice
std::string getText(int index); std::string getText(int index);
// Cambia el idioma seleccionado al siguiente idioma disponible
Code change(Code current_lang);
} }

View File

@@ -59,6 +59,7 @@ Logo::~Logo()
{ {
jail_texture_->setColor(255, 255, 255); jail_texture_->setColor(255, 255, 255);
since_texture_->setColor(255, 255, 255); since_texture_->setColor(255, 255, 255);
JA_PauseChannel(-1);
} }
// Recarga todas las texturas // Recarga todas las texturas
@@ -113,6 +114,11 @@ void Logo::checkInput()
// Gestiona el logo de JAILGAME // Gestiona el logo de JAILGAME
void Logo::updateJAILGAMES() void Logo::updateJAILGAMES()
{ {
if (counter_ == 30)
{
JA_PlaySound(Resource::get()->getSound("logo.wav"));
}
if (counter_ > 30) if (counter_ > 30)
{ {
for (int i = 0; i < (int)jail_sprite_.size(); ++i) for (int i = 0; i < (int)jail_sprite_.size(); ++i)
@@ -195,6 +201,9 @@ void Logo::update()
{ {
section::name = section::Name::INTRO; section::name = section::Name::INTRO;
} }
// Actualiza las variables de globalInputs
globalInputs::update();
} }
} }

View File

@@ -10,14 +10,15 @@
#include "sprite.h" // Para Sprite #include "sprite.h" // Para Sprite
#include "text.h" // Para Text #include "text.h" // Para Text
#include "texture.h" // Para Texture #include "texture.h" // Para Texture
#include "resource.h"
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Notifier *Notifier::notifier_ = nullptr; Notifier *Notifier::notifier_ = nullptr;
// [SINGLETON] Crearemos el objeto screen con esta función estática // [SINGLETON] Crearemos el objeto screen con esta función estática
void Notifier::init(const std::string &icon_file, std::shared_ptr<Text> text, const std::string &sound_file) void Notifier::init(const std::string &icon_file, std::shared_ptr<Text> text)
{ {
Notifier::notifier_ = new Notifier(icon_file, text, sound_file); Notifier::notifier_ = new Notifier(icon_file, text);
} }
// [SINGLETON] Destruiremos el objeto screen con esta función estática // [SINGLETON] Destruiremos el objeto screen con esta función estática
@@ -33,21 +34,14 @@ Notifier *Notifier::get()
} }
// Constructor // Constructor
Notifier::Notifier(std::string icon_file, std::shared_ptr<Text> text, const std::string &sound_file) Notifier::Notifier(std::string icon_file, std::shared_ptr<Text> text)
: renderer_(Screen::get()->getRenderer()), : renderer_(Screen::get()->getRenderer()),
icon_texture_(!icon_file.empty() ? std::make_unique<Texture>(renderer_, icon_file) : nullptr), icon_texture_(!icon_file.empty() ? std::make_unique<Texture>(renderer_, icon_file) : nullptr),
text_(text), text_(text),
bg_color_(param.notification.color), bg_color_(param.notification.color),
wait_time_(150), wait_time_(150),
stack_(false), stack_(false),
has_icons_(!icon_file.empty()), has_icons_(!icon_file.empty()) {}
sound_(JA_LoadSound(sound_file.c_str())) {}
// Destructor
Notifier::~Notifier()
{
JA_DeleteSound(sound_);
}
// Dibuja las notificaciones por pantalla // Dibuja las notificaciones por pantalla
void Notifier::render() void Notifier::render()
@@ -80,8 +74,9 @@ void Notifier::update()
if (param.notification.sound) if (param.notification.sound)
{ {
if (notifications_[i].status == NotificationStatus::RISING) if (notifications_[i].status == NotificationStatus::RISING)
{ // Reproduce el sonido de la notificación {
JA_PlaySound(sound_); // Reproduce el sonido de la notificación
JA_PlaySound(Resource::get()->getSound("notify.wav"));
} }
} }
} }

View File

@@ -62,7 +62,6 @@ private:
std::vector<Notification> notifications_; // La lista de notificaciones activas std::vector<Notification> notifications_; // La lista de notificaciones activas
bool stack_; // Indica si las notificaciones se apilan bool stack_; // Indica si las notificaciones se apilan
bool has_icons_; // Indica si el notificador tiene textura para iconos bool has_icons_; // Indica si el notificador tiene textura para iconos
JA_Sound_t *sound_; // Sonido a reproducir cuando suena la notificación
// Elimina las notificaciones finalizadas // Elimina las notificaciones finalizadas
void clearFinishedNotifications(); void clearFinishedNotifications();
@@ -73,14 +72,14 @@ private:
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos notifier desde fuera // [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos notifier desde fuera
// Constructor // Constructor
Notifier(std::string icon_file, std::shared_ptr<Text> text, const std::string &sound_file); Notifier(std::string icon_file, std::shared_ptr<Text> text);
// Destructor // Destructor
~Notifier(); ~Notifier() = default;
public: public:
// [SINGLETON] Crearemos el objeto notifier con esta función estática // [SINGLETON] Crearemos el objeto notifier con esta función estática
static void init(const std::string &icon_file, std::shared_ptr<Text> text, const std::string &sound_file); static void init(const std::string &icon_file, std::shared_ptr<Text> text);
// [SINGLETON] Destruiremos el objeto notifier con esta función estática // [SINGLETON] Destruiremos el objeto notifier con esta función estática
static void destroy(); static void destroy();

View File

@@ -34,6 +34,24 @@ Resource *Resource::get()
// Constructor // Constructor
Resource::Resource() Resource::Resource()
{
load();
}
// Vacia todos los vectores de recursos
void Resource::clear()
{
clearSounds();
clearMusics();
textures_.clear();
text_files_.clear();
texts_.clear();
animations_.clear();
demos_.clear();
}
// Carga todos los recursos
void Resource::load()
{ {
std::cout << "** LOADING RESOURCES" << std::endl; std::cout << "** LOADING RESOURCES" << std::endl;
loadSounds(); loadSounds();
@@ -48,6 +66,13 @@ Resource::Resource()
std::cout << "\n** RESOURCES LOADED" << std::endl; std::cout << "\n** RESOURCES LOADED" << std::endl;
} }
// Recarga todos los recursos
void Resource::reload()
{
clear();
load();
}
// Obtiene el sonido a partir de un nombre // Obtiene el sonido a partir de un nombre
JA_Sound_t *Resource::getSound(const std::string &name) JA_Sound_t *Resource::getSound(const std::string &name)
{ {
@@ -307,3 +332,33 @@ void Resource::createText()
printWithDots("Text : ", resource.first, "[ DONE ]"); printWithDots("Text : ", resource.first, "[ DONE ]");
} }
} }
// Vacía el vector de sonidos
void Resource::clearSounds()
{
// Itera sobre el vector y libera los recursos asociados a cada JA_Sound_t
for (auto &sound : sounds_)
{
if (sound.sound)
{
JA_DeleteSound(sound.sound);
sound.sound = nullptr;
}
}
sounds_.clear(); // Limpia el vector después de liberar todos los recursos
}
// Vacía el vector de musicas
void Resource::clearMusics()
{
// Itera sobre el vector y libera los recursos asociados a cada JA_Music_t
for (auto &music : musics_)
{
if (music.music)
{
JA_DeleteMusic(music.music);
music.music = nullptr;
}
}
musics_.clear(); // Limpia el vector después de liberar todos los recursos
}

View File

@@ -117,6 +117,18 @@ private:
// Crea los objetos de texto // Crea los objetos de texto
void createText(); void createText();
// Vacia todos los vectores de recursos
void clear();
// Carga todos los recursos
void load();
// Vacía el vector de sonidos
void clearSounds();
// Vacía el vector de musicas
void clearMusics();
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos resource desde fuera // [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos resource desde fuera
// Constructor // Constructor
@@ -155,4 +167,7 @@ public:
// Obtiene el fichero con los datos para el modo demostración a partir de un çindice // Obtiene el fichero con los datos para el modo demostración a partir de un çindice
DemoData &getDemoData(int index); DemoData &getDemoData(int index);
// Recarga todos los recursos
void reload();
}; };

View File

@@ -88,10 +88,10 @@ void Screen::blit()
fps_counter_++; fps_counter_++;
// Actualiza y dibuja el efecto de flash en la pantalla // Actualiza y dibuja el efecto de flash en la pantalla
doFlash(); renderFlash();
// Atenua la pantalla // Atenua la pantalla
doAttenuate(); renderAttenuate();
// Muestra la ayuda por pantalla // Muestra la ayuda por pantalla
OnScreenHelp::get()->render(); OnScreenHelp::get()->render();
@@ -200,7 +200,8 @@ void Screen::setVideoMode(ScreenVideoMode videoMode)
if (options.video.shaders) if (options.video.shaders)
{ {
#ifndef NO_SHADERS #ifndef NO_SHADERS
std::ifstream f(Asset::get()->get("crtpi.glsl").c_str()); const std::string glsl_file = param.game.game_area.rect.h == 256 ? "crtpi_256.glsl" : "crtpi_240.glsl";
std::ifstream f(Asset::get()->get(glsl_file).c_str());
std::string source((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); std::string source((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
shader::init(window_, shader_canvas_, source.c_str()); shader::init(window_, shader_canvas_, source.c_str());
@@ -254,6 +255,7 @@ void Screen::setBlendMode(SDL_BlendMode blendMode)
void Screen::update() void Screen::update()
{ {
updateShakeEffect(); updateShakeEffect();
updateFlash();
Notifier::get()->update(); Notifier::get()->update();
updateFPS(); updateFPS();
OnScreenHelp::get()->update(); OnScreenHelp::get()->update();
@@ -312,21 +314,26 @@ void Screen::flash(Color color, int lenght)
} }
// Actualiza y dibuja el efecto de flash en la pantalla // Actualiza y dibuja el efecto de flash en la pantalla
void Screen::doFlash() void Screen::renderFlash()
{ {
if (flash_effect_.enabled) if (flash_effect_.enabled)
{ {
// Dibuja el color del flash en la textura
SDL_SetRenderDrawColor(renderer_, flash_effect_.color.r, flash_effect_.color.g, flash_effect_.color.b, 0xFF); SDL_SetRenderDrawColor(renderer_, flash_effect_.color.r, flash_effect_.color.g, flash_effect_.color.b, 0xFF);
SDL_RenderClear(renderer_); SDL_RenderClear(renderer_);
}
}
// Actualiza la lógica del efecto // Actualiza el efecto de flash
void Screen::updateFlash()
{
if (flash_effect_.enabled)
{
flash_effect_.counter > 0 ? flash_effect_.counter-- : flash_effect_.enabled = false; flash_effect_.counter > 0 ? flash_effect_.counter-- : flash_effect_.enabled = false;
} }
} }
// Atenua la pantalla // Atenua la pantalla
void Screen::doAttenuate() void Screen::renderAttenuate()
{ {
if (attenuate_effect_) if (attenuate_effect_)
{ {
@@ -386,7 +393,7 @@ void Screen::renderInfo()
dbg_print(0, 0, info_resolution_.c_str(), 255, 255, 0); dbg_print(0, 0, info_resolution_.c_str(), 255, 255, 0);
// Contador de service_pressed_counter // Contador de service_pressed_counter
if (const int counter = globalInputs::service_pressed_counter[0]; counter > 0) if (const int counter = globalInputs::service_pressed_counter; counter > 0)
dbg_print(0, 8, std::to_string(counter).c_str(), 255, 0, 255); dbg_print(0, 8, std::to_string(counter).c_str(), 255, 0, 255);
} }
} }

View File

@@ -82,11 +82,14 @@ private:
// Actualiza la logica para agitar la pantalla // Actualiza la logica para agitar la pantalla
void updateShakeEffect(); void updateShakeEffect();
// Actualiza y dibuja el efecto de flash en la pantalla // Dibuja el efecto de flash en la pantalla
void doFlash(); void renderFlash();
// Actualiza el efecto de flash
void updateFlash();
// Atenua la pantalla // Atenua la pantalla
void doAttenuate(); void renderAttenuate();
// Calcula los frames por segundo // Calcula los frames por segundo
void updateFPS(); void updateFPS();

View File

@@ -69,7 +69,10 @@ void Title::update()
// Actualiza el objeto screen // Actualiza el objeto screen
Screen::get()->update(); Screen::get()->update();
// Comprueba el fade_ y si se ha acabado // Actualiza las variables de globalInputs
globalInputs::update();
// Comprueba el fundido y si se ha acabado
fade_->update(); fade_->update();
if (fade_->hasEnded()) if (fade_->hasEnded())
{ {