Compare commits
23 Commits
2024-12-05
...
2024-12-31
| Author | SHA1 | Date | |
|---|---|---|---|
| 40dfc32e84 | |||
| 4cd1d91560 | |||
| e43badd703 | |||
| 71dcf9cf87 | |||
| 3a8521a1da | |||
| 74d9c9a2b9 | |||
| 9532caace8 | |||
| 0bbd14067a | |||
| cfaa143c44 | |||
| e61daeb92e | |||
| d57cc15aee | |||
| de3b18a407 | |||
| 7f444fef33 | |||
| ca18baefd7 | |||
| b8dca0a46f | |||
| ca2c48ea17 | |||
| fb4d0d12db | |||
| fb31445731 | |||
| cf4f0459b3 | |||
| fe0900a686 | |||
| 3367b70cd5 | |||
| 7016849587 | |||
| 301c059a26 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -15,4 +15,5 @@ thumbs.db
|
||||
*score.bin
|
||||
coffee_crisis*
|
||||
debug.txt
|
||||
cppcheck-result*
|
||||
cppcheck-result*
|
||||
desktop.ini
|
||||
|
||||
156
Makefile
156
Makefile
@@ -1,59 +1,63 @@
|
||||
# Directorios
|
||||
DIR_ROOT := $(dir $(abspath $(MAKEFILE_LIST)))
|
||||
DIR_SOURCES:= $(addsuffix /, $(DIR_ROOT)source)
|
||||
DIR_BIN := $(addsuffix /, $(DIR_ROOT))
|
||||
DIR_BUILD := $(addsuffix /, $(DIR_ROOT)build)
|
||||
DIR_ROOT := $(dir $(abspath $(MAKEFILE_LIST)))
|
||||
DIR_SOURCES := $(addsuffix /, $(DIR_ROOT)source)
|
||||
DIR_BIN := $(addsuffix /, $(DIR_ROOT))
|
||||
DIR_BUILD := $(addsuffix /, $(DIR_ROOT)build)
|
||||
|
||||
# Variables
|
||||
TARGET_NAME := coffee_crisis_arcade_edition
|
||||
TARGET_FILE := $(DIR_BIN)$(TARGET_NAME)
|
||||
APP_NAME := Coffee Crisis Arcade Edition
|
||||
RELEASE_FOLDER:= ccae_release
|
||||
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
|
||||
VERSION := v0.01
|
||||
TARGET_NAME := coffee_crisis_arcade_edition
|
||||
TARGET_FILE := $(DIR_BIN)$(TARGET_NAME)
|
||||
APP_NAME := Coffee Crisis Arcade Edition
|
||||
RELEASE_FOLDER := ccae_release
|
||||
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
|
||||
RESOURCE_FILE := release/coffee.res
|
||||
VERSION := 2024-12-31
|
||||
|
||||
# Nombres para los ficheros de lanzamiento
|
||||
WINDOWS_RELEASE := $(TARGET_FILE)-$(VERSION)-win32-x64.zip
|
||||
MACOS_INTEL_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-intel.dmg
|
||||
MACOS_APPLE_SILICON_RELEASE:= $(TARGET_FILE)-$(VERSION)-macos-apple-silicon.dmg
|
||||
LINUX_RELEASE := $(TARGET_FILE)-$(VERSION)-linux.tar.gz
|
||||
WINDOWS_RELEASE := $(TARGET_NAME)-$(VERSION)-win32-x64.zip
|
||||
MACOS_INTEL_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-intel.dmg
|
||||
MACOS_APPLE_SILICON_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-apple-silicon.dmg
|
||||
LINUX_RELEASE := $(TARGET_FILE)-$(VERSION)-linux.tar.gz
|
||||
RASPI_RELEASE := $(TARGET_FILE)-$(VERSION)-raspberry.tar.gz
|
||||
|
||||
# Includes
|
||||
INCLUDES:= -I$(DIR_SOURCES)
|
||||
INCLUDES := -I$(DIR_SOURCES)
|
||||
|
||||
# Variables según el sistema operativo
|
||||
ifeq ($(OS),Windows_NT)
|
||||
FixPath = $(subst /,\,$1)
|
||||
SOURCES := source/*.cpp
|
||||
CXXFLAGS:= -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows
|
||||
CXXFLAGS_DEBUG:= -std=c++20 -Wall -g
|
||||
LDFLAGS := -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32
|
||||
RM = del /Q
|
||||
MKD:= mkdir
|
||||
FixPath = $(subst /,\\,$1)
|
||||
SOURCES := source/*.cpp
|
||||
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows
|
||||
CXXFLAGS_DEBUG := -std=c++20 -Wall -g
|
||||
LDFLAGS := -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32
|
||||
RM := del /Q
|
||||
MKDIR := mkdir
|
||||
else
|
||||
FixPath = $1
|
||||
SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp')
|
||||
SOURCES := source/*.cpp
|
||||
CXXFLAGS:= -std=c++20 -Wall -Os -ffunction-sections -fdata-sections
|
||||
CXXFLAGS_DEBUG:= -std=c++20 -Wall -g
|
||||
LDFLAGS := -lSDL2
|
||||
RM = rm -f
|
||||
MKD:= mkdir -p
|
||||
UNAME_S := $(shell uname -s)
|
||||
FixPath = $1
|
||||
SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp')
|
||||
SOURCES := source/*.cpp
|
||||
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections
|
||||
CXXFLAGS_DEBUG := -std=c++20 -Wall -g
|
||||
LDFLAGS := -lSDL2
|
||||
RMFILE := rm -f
|
||||
RMDIR := rm -rdf
|
||||
MKDIR := mkdir -p
|
||||
UNAME_S := $(shell uname -s)
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
LDFLAGS += -lGL
|
||||
LDFLAGS += -lGL
|
||||
endif
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
CXXFLAGS += -Wno-deprecated
|
||||
CXXFLAGS_DEBUG += -Wno-deprecated
|
||||
LDFLAGS += -framework OpenGL
|
||||
CXXFLAGS += -Wno-deprecated
|
||||
CXXFLAGS_DEBUG += -Wno-deprecated
|
||||
LDFLAGS += -framework OpenGL
|
||||
endif
|
||||
endif
|
||||
|
||||
# Rules
|
||||
# Reglas para compilación
|
||||
windows:
|
||||
@echo off
|
||||
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE).exe"
|
||||
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
|
||||
$(CXX) $(SOURCES) $(RESOURCE_FILE) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE).exe"
|
||||
strip -s -R .comment -R .gnu.version "$(TARGET_FILE).exe" --strip-unneeded
|
||||
|
||||
windows_rec:
|
||||
@@ -80,12 +84,13 @@ windows_release:
|
||||
powershell Copy-Item "release\*.dll" -Destination "$(RELEASE_FOLDER)"
|
||||
|
||||
# Compila
|
||||
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE).exe"
|
||||
strip -s -R .comment -R .gnu.version "$(RELEASE_FOLDER)/$(TARGET_FILE).exe" --strip-unneeded
|
||||
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
|
||||
$(CXX) $(SOURCES) $(RESOURCE_FILE) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE).exe"
|
||||
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE).exe" --strip-unneeded
|
||||
|
||||
# Crea el fichero .zip
|
||||
powershell if (Test-Path $(WINDOWS_RELEASE)) {Remove-Item $(WINDOWS_RELEASE)}
|
||||
powershell Compress-Archive -Path "$(RELEASE_FOLDER)"/* -DestinationPath $(WINDOWS_RELEASE)
|
||||
powershell if (Test-Path "$(WINDOWS_RELEASE)") {Remove-Item "$(WINDOWS_RELEASE)"}
|
||||
powershell Compress-Archive -Path "$(RELEASE_FOLDER)"/* -DestinationPath "$(WINDOWS_RELEASE)"
|
||||
|
||||
# Elimina la carpeta temporal 'RELEASE_FOLDER'
|
||||
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
|
||||
@@ -98,17 +103,17 @@ macos_debug:
|
||||
|
||||
macos_release:
|
||||
# Elimina datos de compilaciones anteriores
|
||||
rm -rdf "$(RELEASE_FOLDER)"
|
||||
rm -rdf Frameworks
|
||||
rm -f tmp.dmg
|
||||
rm -f "$(MACOS_INTEL_RELEASE)"
|
||||
rm -f "$(MACOS_APPLE_SILICON_RELEASE)"
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
$(RMDIR) Frameworks
|
||||
$(RMFILE) tmp.dmg
|
||||
$(RMFILE) "$(MACOS_INTEL_RELEASE)"
|
||||
$(RMFILE) "$(MACOS_APPLE_SILICON_RELEASE)"
|
||||
|
||||
# Crea la carpeta temporal para hacer el trabajo y las carpetas obligatorias para crear una app de macos
|
||||
mkdir -p "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
|
||||
mkdir -p "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
|
||||
mkdir -p "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||
mkdir -p Frameworks
|
||||
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
|
||||
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
|
||||
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||
$(MKDIR) Frameworks
|
||||
|
||||
# Copia carpetas y ficheros
|
||||
cp -R data "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||
@@ -123,24 +128,24 @@ macos_release:
|
||||
ln -s /Applications "$(RELEASE_FOLDER)"/Applications
|
||||
|
||||
# Compila la versión para procesadores Intel
|
||||
$(CXX) $(SOURCES) -D MACOS_BUNDLE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_FILE)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.12
|
||||
$(CXX) $(SOURCES) -D MACOS_BUNDLE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.12
|
||||
|
||||
# Empaqueta el .dmg de la versión Intel
|
||||
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
|
||||
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_INTEL_RELEASE)"
|
||||
rm -f tmp.dmg
|
||||
$(RMFILE) tmp.dmg
|
||||
|
||||
# Compila la versión para procesadores Apple Silicon
|
||||
$(CXX) $(SOURCES) -D MACOS_BUNDLE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_FILE)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11
|
||||
$(CXX) $(SOURCES) -D MACOS_BUNDLE -D SDL_DISABLE_IMMINTRIN_H $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11
|
||||
|
||||
# Empaqueta el .dmg de la versión Apple Silicon
|
||||
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
|
||||
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_APPLE_SILICON_RELEASE)"
|
||||
rm -f tmp.dmg
|
||||
$(RMFILE) tmp.dmg
|
||||
|
||||
# Elimina las carpetas temporales
|
||||
$(RM) Frameworks
|
||||
$(RM) "$(RELEASE_FOLDER)"
|
||||
$(RMDIR) Frameworks
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
linux:
|
||||
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
|
||||
@@ -151,10 +156,10 @@ linux_debug:
|
||||
|
||||
linux_release:
|
||||
# Elimina carpetas previas
|
||||
$(RM) "$(RELEASE_FOLDER)"
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
# Crea la carpeta temporal para realizar el lanzamiento
|
||||
mkdir -p "$(RELEASE_FOLDER)"
|
||||
$(MKDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
# Copia ficheros
|
||||
cp -R data "$(RELEASE_FOLDER)"
|
||||
@@ -166,11 +171,11 @@ linux_release:
|
||||
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
|
||||
|
||||
# Empaqueta ficheros
|
||||
$(RM) "$(LINUX_RELEASE)"
|
||||
cd "$(RELEASE_FOLDER)" && tar -czvf "../$(LINUX_RELEASE)" *
|
||||
$(RMFILE) "$(LINUX_RELEASE)"
|
||||
cd "$(RELEASE_FOLDER)" && tar -czvf "$(LINUX_RELEASE)" *
|
||||
|
||||
# Elimina la carpeta temporal
|
||||
$(RM) "$(RELEASE_FOLDER)"
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
raspi:
|
||||
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE)
|
||||
@@ -179,12 +184,35 @@ raspi:
|
||||
raspi_debug:
|
||||
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE -D DEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
||||
|
||||
anbernic:
|
||||
raspi_release:
|
||||
# Elimina carpetas previas
|
||||
$(RM) "$(RELEASE_FOLDER)"_anbernic
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
# Crea la carpeta temporal para realizar el lanzamiento
|
||||
mkdir -p "$(RELEASE_FOLDER)"_anbernic
|
||||
$(MKDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
# Copia ficheros
|
||||
cp -R data "$(RELEASE_FOLDER)"
|
||||
cp LICENSE "$(RELEASE_FOLDER)"
|
||||
cp README.md "$(RELEASE_FOLDER)"
|
||||
|
||||
# Complia
|
||||
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
|
||||
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
|
||||
|
||||
# Empaqueta ficheros
|
||||
$(RMFILE) "$(LINUX_RELEASE)"
|
||||
cd "$(RELEASE_FOLDER)" && tar -czvf "$(RASPI_RELEASE)" *
|
||||
|
||||
# Elimina la carpeta temporal
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
anbernic:
|
||||
# Elimina carpetas previas
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"_anbernic
|
||||
|
||||
# Crea la carpeta temporal para realizar el lanzamiento
|
||||
$(MKDIR) "$(RELEASE_FOLDER)"_anbernic
|
||||
|
||||
# Copia ficheros
|
||||
cp -R data "$(RELEASE_FOLDER)"_anbernic
|
||||
|
||||
@@ -30,7 +30,9 @@ Les tecles son les següents:
|
||||
|
||||
- **Tecla F5**: Activa o desactiva l'audio
|
||||
|
||||
- **Tecla F6**: Canvia el idioma del joc i reinicia
|
||||
- **Tecla F6**: Activa o desactiva el dispar automàtic
|
||||
|
||||
- **Tecla F7**: Canvia el idioma del joc i reinicia
|
||||
|
||||
- **Tecla F10**: Reset
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ fade.num_squares_height 120
|
||||
fade.random_squares_delay 1
|
||||
fade.random_squares_mult 500
|
||||
fade.post_duration 80
|
||||
fade.venetian_size 16
|
||||
fade.venetian_size 12
|
||||
|
||||
## SCOREBOARD
|
||||
scoreboard.x 0
|
||||
|
||||
@@ -14,7 +14,7 @@ fade.num_squares_height 128
|
||||
fade.random_squares_delay 1
|
||||
fade.random_squares_mult 500
|
||||
fade.post_duration 80
|
||||
fade.venetian_size 16
|
||||
fade.venetian_size 12
|
||||
|
||||
## SCOREBOARD
|
||||
scoreboard.x 0
|
||||
|
||||
9
data/gfx/tabe/tabe.ani
Normal file
9
data/gfx/tabe/tabe.ani
Normal file
@@ -0,0 +1,9 @@
|
||||
frame_width=32
|
||||
frame_height=32
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=2
|
||||
loop=0
|
||||
frames=0,1
|
||||
[/animation]
|
||||
BIN
data/gfx/tabe/tabe.png
Normal file
BIN
data/gfx/tabe/tabe.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
data/sound/game_start.wav
Normal file
BIN
data/sound/game_start.wav
Normal file
Binary file not shown.
BIN
data/sound/tabe.wav
Normal file
BIN
data/sound/tabe.wav
Normal file
Binary file not shown.
BIN
data/sound/voice_coffee.wav
Normal file
BIN
data/sound/voice_coffee.wav
Normal file
Binary file not shown.
BIN
data/sound/voice_get_ready.wav
Normal file
BIN
data/sound/voice_get_ready.wav
Normal file
Binary file not shown.
BIN
data/sound/voice_no.wav
Normal file
BIN
data/sound/voice_no.wav
Normal file
Binary file not shown.
BIN
data/sound/voice_power_up.wav
Normal file
BIN
data/sound/voice_power_up.wav
Normal file
Binary file not shown.
2
release/coffee.rc
Normal file
2
release/coffee.rc
Normal file
@@ -0,0 +1,2 @@
|
||||
// coffee.rc
|
||||
IDI_ICON1 ICON "icon.ico"
|
||||
BIN
release/coffee.res
Normal file
BIN
release/coffee.res
Normal file
Binary file not shown.
BIN
release/icon.ico
Normal file
BIN
release/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
@@ -5,6 +5,8 @@
|
||||
#include "param.h" // Para Param, param, ParamBalloon, ParamGame
|
||||
#include "sprite.h" // Para Sprite
|
||||
#include "texture.h" // Para Texture
|
||||
#include "resource.h"
|
||||
#include "jail_audio.h"
|
||||
|
||||
// Constructor
|
||||
Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, SDL_Rect play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
|
||||
@@ -36,6 +38,7 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
|
||||
power_ = BALLOON_POWER[index];
|
||||
menace_ = BALLOON_MENACE[index];
|
||||
score_ = BALLOON_SCORE[index];
|
||||
sound_ = BALLOON_SOUND[index];
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -50,14 +53,16 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
|
||||
power_ = BALLOON_POWER[index];
|
||||
menace_ = BALLOON_MENACE[index];
|
||||
score_ = BALLOON_SCORE[index];
|
||||
sound_ = BALLOON_SOUND[index];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BalloonType::POWERBALL:
|
||||
{
|
||||
const int index = 3;
|
||||
constexpr int index = 3;
|
||||
h_ = w_ = BALLOON_SIZE[4];
|
||||
sound_ = BALLOON_SOUND[3];
|
||||
power_ = score_ = menace_ = 0;
|
||||
|
||||
vy_ = 0;
|
||||
@@ -145,6 +150,7 @@ void Balloon::move()
|
||||
const float max_x = play_area_.x + play_area_.w - w_ + clip;
|
||||
if (x_ < min_x || x_ > max_x)
|
||||
{
|
||||
playSound();
|
||||
x_ = std::clamp(x_, min_x, max_x);
|
||||
vx_ = -vx_;
|
||||
// Activa el efecto de rebote o invierte la rotación
|
||||
@@ -179,6 +185,7 @@ void Balloon::move()
|
||||
const int min_y = play_area_.y;
|
||||
if (y_ < min_y)
|
||||
{
|
||||
playSound();
|
||||
y_ = min_y;
|
||||
vy_ = -vy_;
|
||||
enableBounce();
|
||||
@@ -189,6 +196,7 @@ void Balloon::move()
|
||||
const int max_y = play_area_.y + play_area_.h - h_;
|
||||
if (y_ > max_y)
|
||||
{
|
||||
playSound();
|
||||
y_ = max_y;
|
||||
vy_ = -default_vy_;
|
||||
if (type_ != BalloonType::POWERBALL)
|
||||
@@ -401,4 +409,13 @@ void Balloon::useNormalColor()
|
||||
{
|
||||
use_reversed_colors_ = false;
|
||||
setAnimation();
|
||||
}
|
||||
|
||||
// Reproduce el sonido al rebotar
|
||||
void Balloon::playSound()
|
||||
{
|
||||
if (sound_enabled_)
|
||||
{
|
||||
JA_PlaySound(Resource::get()->getSound(sound_));
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ constexpr int BALLOON_SCORE[] = {50, 100, 200, 400};
|
||||
constexpr int BALLOON_POWER[] = {1, 3, 7, 15};
|
||||
constexpr int BALLOON_MENACE[] = {1, 2, 4, 8};
|
||||
constexpr int BALLOON_SIZE[] = {10, 16, 26, 48, 49};
|
||||
const std::string BALLOON_SOUND[] = {"bubble1.wav", "bubble2.wav", "bubble3.wav", "bubble4.wav"};
|
||||
|
||||
// Tamaños de globo
|
||||
enum class BalloonSize : Uint8
|
||||
@@ -113,6 +114,8 @@ private:
|
||||
float speed_; // Velocidad a la que se mueven los globos
|
||||
Uint8 power_; // Cantidad de poder que alberga el globo
|
||||
SDL_Rect play_area_; // Zona por donde se puede mover el globo
|
||||
std::string sound_; // Archivo de sonido que hace el globo al rebotar
|
||||
bool sound_enabled_ = false; // Indica si ha de sonar el sonido del globo al rebotar
|
||||
|
||||
// Alinea el circulo de colisión con la posición del objeto globo
|
||||
void shiftColliders();
|
||||
@@ -138,6 +141,9 @@ private:
|
||||
// Establece la animación correspondiente
|
||||
void setAnimation();
|
||||
|
||||
// Reproduce el sonido al rebotar
|
||||
void playSound();
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Balloon(
|
||||
@@ -208,4 +214,5 @@ public:
|
||||
void setVelY(float vel_y) { vy_ = vel_y; }
|
||||
void setSpeed(float speed) { speed_ = speed; }
|
||||
void setInvulnerable(bool value) { invulnerable_ = value; }
|
||||
void setSound(bool value) { sound_enabled_ = value; }
|
||||
};
|
||||
@@ -371,4 +371,13 @@ int BalloonManager::getMenace()
|
||||
{
|
||||
return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon)
|
||||
{ return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); });
|
||||
}
|
||||
|
||||
// Establece el sonido de los globos
|
||||
void BalloonManager::setSounds(bool value)
|
||||
{
|
||||
for (auto &balloon : balloons_)
|
||||
{
|
||||
balloon->setSound(value);
|
||||
}
|
||||
}
|
||||
@@ -111,6 +111,9 @@ public:
|
||||
// Obtiene el nivel de ameza actual generado por los globos
|
||||
int getMenace();
|
||||
|
||||
// Establece el sonido de los globos
|
||||
void setSounds(bool value);
|
||||
|
||||
// Getters
|
||||
float getBalloonSpeed() const { return balloon_speed_; }
|
||||
Balloons &getBalloons() { return balloons_; }
|
||||
|
||||
@@ -180,8 +180,9 @@ void Director::bindInputs()
|
||||
Input::get()->bindKey(InputType::WINDOW_FULLSCREEN, SDL_SCANCODE_F3);
|
||||
Input::get()->bindKey(InputType::VIDEO_SHADERS, SDL_SCANCODE_F4);
|
||||
Input::get()->bindKey(InputType::MUTE, SDL_SCANCODE_F5);
|
||||
Input::get()->bindKey(InputType::CHANGE_LANG, SDL_SCANCODE_F6);
|
||||
Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F7);
|
||||
Input::get()->bindKey(InputType::AUTO_FIRE, SDL_SCANCODE_F6);
|
||||
Input::get()->bindKey(InputType::CHANGE_LANG, SDL_SCANCODE_F7);
|
||||
Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F8);
|
||||
Input::get()->bindKey(InputType::RESET, SDL_SCANCODE_F10);
|
||||
|
||||
// Asigna botones a inputs
|
||||
@@ -295,8 +296,15 @@ bool Director::initSDL()
|
||||
}
|
||||
*/
|
||||
|
||||
// Obtiene información sobre la pantalla
|
||||
SDL_DisplayMode DM;
|
||||
SDL_GetCurrentDisplayMode(0, &DM);
|
||||
|
||||
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla
|
||||
options.video.window.max_size = std::min(DM.w / param.game.width, DM.h / param.game.height);
|
||||
options.video.window.size = std::min(options.video.window.size, options.video.window.max_size);
|
||||
|
||||
// Muestra información sobre el tamaño de la pantalla y de la ventana de juego
|
||||
std::cout << "\nCurrent display mode: " << DM.w << "x" << DM.h << " @ " << DM.refresh_rate << "Hz" << std::endl;
|
||||
std::cout << "Window resolution : " << param.game.width << "x" << param.game.height << " x" << options.video.window.size << std::endl;
|
||||
|
||||
@@ -380,6 +388,7 @@ void Director::setFileList()
|
||||
Asset::get()->add(prefix + "/data/music/credits.ogg", AssetType::MUSIC);
|
||||
|
||||
// Sonidos
|
||||
Asset::get()->add(prefix + "/data/sound/game_start.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/balloon.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/bubble1.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/bubble2.wav", AssetType::SOUND);
|
||||
@@ -397,6 +406,11 @@ void Director::setFileList()
|
||||
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/logo.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/voice_coffee.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/voice_power_up.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/voice_no.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/voice_get_ready.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/tabe.wav", AssetType::SOUND);
|
||||
|
||||
// Shaders
|
||||
Asset::get()->add(prefix + "/data/shaders/crtpi_256.glsl", AssetType::DATA);
|
||||
@@ -439,6 +453,11 @@ void Director::setFileList()
|
||||
Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP);
|
||||
}
|
||||
|
||||
{ // Tabe
|
||||
Asset::get()->add(prefix + "/data/gfx/tabe/tabe.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/tabe/tabe.ani", AssetType::ANIMATION);
|
||||
}
|
||||
|
||||
{ // Juego
|
||||
Asset::get()->add(prefix + "/data/gfx/game/game_buildings.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/game/game_clouds1.png", AssetType::BITMAP);
|
||||
|
||||
@@ -100,6 +100,8 @@ void Fade::update()
|
||||
|
||||
SDL_RenderFillRect(renderer_, &rect1_);
|
||||
SDL_RenderFillRect(renderer_, &rect2_);
|
||||
|
||||
value_ = calculateValue(0, counter_, i);
|
||||
}
|
||||
|
||||
// Deja el renderizador como estaba
|
||||
@@ -121,7 +123,6 @@ void Fade::update()
|
||||
// Dibuja sobre el backbuffer_
|
||||
auto temp = SDL_GetRenderTarget(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
||||
|
||||
@@ -133,12 +134,12 @@ void Fade::update()
|
||||
SDL_RenderFillRect(renderer_, &square_[index2]);
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
|
||||
|
||||
// Deja el renderizador como estaba
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
}
|
||||
|
||||
value_ = calculateValue(0, static_cast<int>(num_squares_width_ * num_squares_height_), static_cast<int>(counter_ * fade_random_squares_mult_ / fade_random_squares_delay_));
|
||||
|
||||
// Comprueba si ha terminado
|
||||
if (counter_ * fade_random_squares_mult_ / fade_random_squares_delay_ >= num_squares_width_ * num_squares_height_)
|
||||
{
|
||||
@@ -156,9 +157,11 @@ void Fade::update()
|
||||
// Dibuja sobre el backbuffer_
|
||||
auto temp = SDL_GetRenderTarget(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
||||
for (auto rect : square_)
|
||||
|
||||
// Dibuja el cuadrado correspondiente
|
||||
for (const auto rect : square_)
|
||||
{
|
||||
SDL_RenderFillRect(renderer_, &rect);
|
||||
}
|
||||
@@ -166,11 +169,12 @@ void Fade::update()
|
||||
// Deja el renderizador como estaba
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
|
||||
const auto h = counter_ / 3;
|
||||
for (int i = 0; i < (int)square_.size(); ++i)
|
||||
// Modifica el tamaño de los rectangulos
|
||||
const auto h = counter_ / 2;
|
||||
for (size_t i = 0; i < square_.size(); ++i)
|
||||
{
|
||||
// A partir del segundo rectangulo se pinta en función del anterior
|
||||
square_[i].h = i == 0 ? h : std::max(square_[i - 1].h - 3, 0);
|
||||
square_.at(i).h = i == 0 ? h : std::max(square_.at(i - 1).h - 2, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -251,12 +255,8 @@ void Fade::activate()
|
||||
}
|
||||
|
||||
// Limpia la textura
|
||||
auto temp = SDL_GetRenderTarget(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||
a_ = mode_ == FadeMode::OUT ? 0 : 255;
|
||||
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
||||
SDL_RenderClear(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
cleanBackbuffer(r_, g_, b_, a_);
|
||||
|
||||
// Deja el color listo para usar
|
||||
a_ = mode_ == FadeMode::OUT ? 255 : 0;
|
||||
@@ -266,12 +266,16 @@ void Fade::activate()
|
||||
|
||||
case FadeType::VENETIAN:
|
||||
{
|
||||
cleanBackbuffer(0, 0, 0, 0);
|
||||
rect1_ = {0, 0, param.game.width, 0};
|
||||
square_.clear();
|
||||
a_ = 255;
|
||||
// Limpia la textura
|
||||
a_ = mode_ == FadeMode::OUT ? 0 : 255;
|
||||
cleanBackbuffer(r_, g_, b_, a_);
|
||||
|
||||
// Deja el color listo para usar
|
||||
a_ = mode_ == FadeMode::OUT ? 255 : 0;
|
||||
|
||||
// Añade los cuadrados al vector
|
||||
square_.clear();
|
||||
rect1_ = {0, 0, param.game.width, 0};
|
||||
const int max = param.game.height / param.fade.venetian_size;
|
||||
|
||||
for (int i = 0; i < max; ++i)
|
||||
@@ -285,31 +289,6 @@ void Fade::activate()
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba si está activo
|
||||
bool Fade::isEnabled() const
|
||||
{
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
// Comprueba si ha terminado la transicion
|
||||
bool Fade::hasEnded() const
|
||||
{
|
||||
// Ha terminado cuando ha finalizado la transición y se ha deshabilitado
|
||||
return !enabled_ && finished_;
|
||||
}
|
||||
|
||||
// Establece el tipo de fade
|
||||
void Fade::setType(FadeType type)
|
||||
{
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
// Establece el modo de fade
|
||||
void Fade::setMode(FadeMode mode)
|
||||
{
|
||||
mode_ = mode;
|
||||
}
|
||||
|
||||
// Establece el color del fade
|
||||
void Fade::setColor(Uint8 r, Uint8 g, Uint8 b)
|
||||
{
|
||||
@@ -318,12 +297,6 @@ void Fade::setColor(Uint8 r, Uint8 g, Uint8 b)
|
||||
b_ = b;
|
||||
}
|
||||
|
||||
// Establece la duración posterior
|
||||
void Fade::setPost(int value)
|
||||
{
|
||||
post_duration_ = value;
|
||||
}
|
||||
|
||||
// Limpia el backbuffer
|
||||
void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
|
||||
{
|
||||
@@ -337,4 +310,14 @@ void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
|
||||
|
||||
// Vuelve a dejar el renderizador como estaba
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
}
|
||||
|
||||
// Calcula el valor del estado del fade
|
||||
int Fade::calculateValue(int min, int max, int current)
|
||||
{
|
||||
if (max == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return std::clamp(current * 100 / max, 0, 100);
|
||||
}
|
||||
@@ -45,6 +45,7 @@ private:
|
||||
int fade_random_squares_mult_; // Cantidad de cuadrados que se pintaran cada vez
|
||||
int post_duration_; // Duración posterior del fade tras finalizar
|
||||
int post_counter_; // Contador para la duración posterior
|
||||
int value_ = 0; // Estado actual del fade entre 0 y 100
|
||||
|
||||
// Inicializa las variables
|
||||
void init();
|
||||
@@ -52,6 +53,9 @@ private:
|
||||
// Limpia el backbuffer
|
||||
void cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
||||
|
||||
// Calcula el valor del estado del fade
|
||||
int calculateValue(int min, int max, int current);
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Fade();
|
||||
@@ -71,21 +75,16 @@ public:
|
||||
// Activa el fade
|
||||
void activate();
|
||||
|
||||
// Comprueba si ha terminado la transicion
|
||||
bool hasEnded() const;
|
||||
|
||||
// Comprueba si está activo
|
||||
bool isEnabled() const;
|
||||
|
||||
// Establece el tipo de fade
|
||||
void setType(FadeType type);
|
||||
|
||||
// Establece el modo de fade
|
||||
void setMode(FadeMode mode);
|
||||
|
||||
// Establece el color del fade
|
||||
void setColor(Uint8 r, Uint8 g, Uint8 b);
|
||||
|
||||
// Establece la duración posterior
|
||||
void setPost(int value);
|
||||
// Getters
|
||||
int getValue() const { return value_; }
|
||||
bool isEnabled() const { return enabled_; }
|
||||
bool hasEnded() const { return !enabled_ && finished_; }
|
||||
|
||||
// Setters
|
||||
void setType(FadeType type) { type_ = type; }
|
||||
void setMode(FadeMode mode) { mode_ = mode; }
|
||||
void setPost(int value) { post_duration_ = value; }
|
||||
};
|
||||
188
source/game.cpp
188
source/game.cpp
@@ -32,6 +32,7 @@
|
||||
#include "section.h" // Para Name, name, Options, options
|
||||
#include "smart_sprite.h" // Para SmartSprite
|
||||
#include "stage.h" // Para number, get, Stage, power, total_p...
|
||||
#include "tabe.h" // Para Tabe
|
||||
#include "text.h" // Para Text
|
||||
#include "texture.h" // Para Texture
|
||||
struct JA_Sound_t; // lines 37-37
|
||||
@@ -44,8 +45,10 @@ Game::Game(int player_id, int current_stage, bool demo)
|
||||
input_(Input::get()),
|
||||
background_(std::make_unique<Background>()),
|
||||
canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.play_area.rect.w, param.game.play_area.rect.h)),
|
||||
fade_(std::make_unique<Fade>()),
|
||||
balloon_manager_(std::make_unique<BalloonManager>())
|
||||
fade_in_(std::make_unique<Fade>()),
|
||||
fade_out_(std::make_unique<Fade>()),
|
||||
balloon_manager_(std::make_unique<BalloonManager>()),
|
||||
tabe_(std::make_unique<Tabe>())
|
||||
{
|
||||
// Pasa variables
|
||||
demo_.enabled = demo;
|
||||
@@ -63,9 +66,15 @@ Game::Game(int player_id, int current_stage, bool demo)
|
||||
Scoreboard::init();
|
||||
scoreboard_ = Scoreboard::get();
|
||||
|
||||
fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
|
||||
fade_->setPost(param.fade.post_duration);
|
||||
fade_->setType(FadeType::VENETIAN);
|
||||
fade_in_->setColor(fade_color.r, fade_color.g, fade_color.b);
|
||||
fade_in_->setPost(0);
|
||||
fade_in_->setType(FadeType::RANDOM_SQUARE);
|
||||
fade_in_->setMode(FadeMode::IN);
|
||||
fade_in_->activate();
|
||||
|
||||
fade_out_->setColor(fade_color.r, fade_color.g, fade_color.b);
|
||||
fade_out_->setPost(param.fade.post_duration);
|
||||
fade_out_->setType(FadeType::VENETIAN);
|
||||
|
||||
background_->setPos(param.game.play_area.rect);
|
||||
|
||||
@@ -87,24 +96,25 @@ Game::Game(int player_id, int current_stage, bool demo)
|
||||
Stage::total_power += Stage::get(i).power_to_complete;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Crea los primeros globos y el mensaje de inicio
|
||||
if (!demo_.enabled)
|
||||
{
|
||||
balloon_manager_->createTwoBigBalloons();
|
||||
evaluateAndSetMenace();
|
||||
createMessage({paths_.at(0), paths_.at(1)}, Resource::get()->getTexture("get_ready"));
|
||||
}
|
||||
}
|
||||
|
||||
Game::~Game()
|
||||
{
|
||||
// Guarda las puntuaciones en un fichero
|
||||
if (!demo_.enabled)
|
||||
// MODO DEMO
|
||||
if (demo_.enabled)
|
||||
{
|
||||
// Habilita los sonidos
|
||||
JA_EnableSound(true);
|
||||
}
|
||||
// MODO JUEGO
|
||||
else
|
||||
{
|
||||
// Guarda las puntuaciones en un fichero
|
||||
auto manager = std::make_unique<ManageHiScoreTable>(options.game.hi_score_table);
|
||||
manager->saveToFile(asset_->get("score.bin"));
|
||||
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
|
||||
}
|
||||
|
||||
#ifdef RECORDING
|
||||
saveDemoFile(Asset::get()->get("demo1.bin"), demo_.data.at(0));
|
||||
#endif
|
||||
@@ -213,8 +223,8 @@ void Game::updatePlayers()
|
||||
|
||||
if (demo_.enabled && allPlayersAreNotPlaying())
|
||||
{
|
||||
fade_->setType(FadeType::RANDOM_SQUARE);
|
||||
fade_->activate();
|
||||
fade_out_->setType(FadeType::RANDOM_SQUARE);
|
||||
fade_out_->activate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +272,7 @@ void Game::updateStage()
|
||||
std::vector<Path> paths = {paths_.at(2), paths_.at(3)};
|
||||
if (Stage::number == 9)
|
||||
{
|
||||
createMessage(paths, Resource::get()->getTexture("last_stage"));
|
||||
createMessage(paths, Resource::get()->getTexture("game_text_last_stage"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -275,6 +285,27 @@ void Game::updateStage()
|
||||
}
|
||||
}
|
||||
|
||||
// Actualiza el estado de fade in
|
||||
void Game::updateFadeInState()
|
||||
{
|
||||
if (state_ == GameState::FADE_IN)
|
||||
{
|
||||
if (fade_in_->hasEnded())
|
||||
{
|
||||
state_ = GameState::PLAYING;
|
||||
|
||||
// Crea los primeros globos y el mensaje de inicio
|
||||
if (!demo_.enabled)
|
||||
{
|
||||
balloon_manager_->createTwoBigBalloons();
|
||||
evaluateAndSetMenace();
|
||||
createMessage({paths_.at(0), paths_.at(1)}, Resource::get()->getTexture("game_text_get_ready"));
|
||||
JA_PlaySound(Resource::get()->getSound("voice_get_ready.wav"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Actualiza el estado de fin de la partida
|
||||
void Game::updateGameOverState()
|
||||
{
|
||||
@@ -283,25 +314,21 @@ void Game::updateGameOverState()
|
||||
if (game_over_counter_ > 0)
|
||||
{
|
||||
if (game_over_counter_ == GAME_OVER_COUNTER_)
|
||||
createMessage({paths_.at(2), paths_.at(3)}, Resource::get()->getTexture("game_over"));
|
||||
{
|
||||
createMessage({paths_.at(2), paths_.at(3)}, Resource::get()->getTexture("game_text_game_over"));
|
||||
JA_FadeOutMusic(1000);
|
||||
balloon_manager_->setSounds(true);
|
||||
}
|
||||
|
||||
game_over_counter_--;
|
||||
|
||||
if ((game_over_counter_ == 250) || (game_over_counter_ == 200) || (game_over_counter_ == 180) || (game_over_counter_ == 120) || (game_over_counter_ == 60))
|
||||
{
|
||||
// Hace sonar aleatoriamente uno de los 4 sonidos de burbujas
|
||||
const auto index = rand() % 4;
|
||||
JA_Sound_t *sound[4] = {Resource::get()->getSound("bubble1.wav"), Resource::get()->getSound("bubble2.wav"), Resource::get()->getSound("bubble3.wav"), Resource::get()->getSound("bubble4.wav")};
|
||||
JA_PlaySound(sound[index], 0);
|
||||
}
|
||||
|
||||
if (game_over_counter_ == 150)
|
||||
{
|
||||
fade_->activate();
|
||||
fade_out_->activate();
|
||||
}
|
||||
}
|
||||
|
||||
if (fade_->hasEnded())
|
||||
if (fade_out_->hasEnded())
|
||||
{
|
||||
if (game_completed_counter_ > 0)
|
||||
{
|
||||
@@ -336,8 +363,8 @@ void Game::updateCompletedState()
|
||||
// Muestra el mensaje de felicitación y da los puntos a los jugadores
|
||||
if (game_completed_counter_ == 200)
|
||||
{
|
||||
createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("congratulations"));
|
||||
createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("1000000_points"));
|
||||
createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("game_text_congratulations"));
|
||||
createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("game_text_1000000_points"));
|
||||
|
||||
for (auto &player : players_)
|
||||
if (player->isPlaying())
|
||||
@@ -474,6 +501,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
|
||||
(item->getWidth() - game_text_textures_[4]->getWidth()) / 2;
|
||||
createItemText(x, game_text_textures_[4]);
|
||||
}
|
||||
JA_PlaySound(Resource::get()->getSound("voice_coffee.wav"));
|
||||
break;
|
||||
}
|
||||
case ItemType::COFFEE_MACHINE:
|
||||
@@ -484,6 +512,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
|
||||
item->getPosX() +
|
||||
(item->getWidth() - game_text_textures_[3]->getWidth()) / 2;
|
||||
createItemText(x, game_text_textures_[3]);
|
||||
JA_PlaySound(Resource::get()->getSound("voice_power_up.wav"));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -722,7 +751,9 @@ void Game::createMessage(const std::vector<Path> &paths, std::shared_ptr<Texture
|
||||
|
||||
// Inicializa
|
||||
for (const auto &path : paths)
|
||||
{
|
||||
path_sprites_.back()->addPath(path, true);
|
||||
}
|
||||
path_sprites_.back()->enable();
|
||||
}
|
||||
|
||||
@@ -815,13 +846,12 @@ void Game::killPlayer(std::shared_ptr<Player> &player)
|
||||
else
|
||||
{
|
||||
// Si no tiene cafes, muere
|
||||
pauseMusic();
|
||||
// pauseMusic();
|
||||
balloon_manager_->stopAllBalloons();
|
||||
JA_PlaySound(Resource::get()->getSound("player_collision.wav"));
|
||||
screen_->shake();
|
||||
JA_PlaySound(Resource::get()->getSound("coffeeout.wav"));
|
||||
JA_PlaySound(Resource::get()->getSound("voice_no.wav"));
|
||||
player->setPlayingState(PlayerState::DYING);
|
||||
allPlayersAreNotPlaying() ? stopMusic() : resumeMusic();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -869,7 +899,7 @@ void Game::update()
|
||||
|
||||
checkMusicStatus();
|
||||
screen_->update();
|
||||
globalInputs::update();
|
||||
globalInputs::update();
|
||||
fillCanvas();
|
||||
}
|
||||
}
|
||||
@@ -912,11 +942,10 @@ void Game::fillCanvas()
|
||||
renderItems();
|
||||
renderSmartSprites();
|
||||
balloon_manager_->render();
|
||||
tabe_->render();
|
||||
renderBullets();
|
||||
renderPathSprites();
|
||||
renderPlayers();
|
||||
// dbg_print(0, 40, std::to_string(menace_current_).c_str(), 255, 0, 0);
|
||||
// dbg_print(0, 50, std::to_string(menace_threshold_).c_str(), 255, 0, 0);
|
||||
|
||||
// Deja el renderizador apuntando donde estaba
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
@@ -935,7 +964,8 @@ void Game::render()
|
||||
scoreboard_->render();
|
||||
|
||||
// Dibuja el fade
|
||||
fade_->render();
|
||||
fade_in_->render();
|
||||
fade_out_->render();
|
||||
|
||||
// Vuelca el contenido del renderizador en pantalla
|
||||
screen_->blit();
|
||||
@@ -960,10 +990,11 @@ void Game::disableTimeStopItem()
|
||||
// Comprueba si la música ha de estar sonando
|
||||
void Game::checkMusicStatus()
|
||||
{
|
||||
// Si la música no está sonando
|
||||
if (JA_GetMusicState() == JA_MUSIC_INVALID || JA_GetMusicState() == JA_MUSIC_STOPPED)
|
||||
// Si se ha completado el juego o los jugadores han terminado, detiene la música
|
||||
state_ == GameState::COMPLETED || allPlayersAreGameOver() ? JA_StopMusic() : JA_PlayMusic(Resource::get()->getMusic("playing.ogg"));
|
||||
// Si se ha completado el juego o los jugadores han terminado, detiene la música
|
||||
if (state_ != GameState::COMPLETED && !allPlayersAreGameOver())
|
||||
{
|
||||
playMusic();
|
||||
}
|
||||
}
|
||||
|
||||
// Bucle para el juego
|
||||
@@ -988,7 +1019,7 @@ void Game::initPaths()
|
||||
{
|
||||
// Recorrido para el texto de "Get Ready!" (0,1)
|
||||
{
|
||||
const auto &texture = Resource::get()->getTexture("get_ready");
|
||||
const auto &texture = Resource::get()->getTexture("game_text_get_ready");
|
||||
const auto w = texture->getWidth();
|
||||
const int x0 = -w;
|
||||
const int x1 = param.game.play_area.center_x - w / 2;
|
||||
@@ -998,10 +1029,9 @@ void Game::initPaths()
|
||||
paths_.emplace_back(Path(createPath(x1, x2, PathType::HORIZONTAL, y, 80, easeInQuint), 0));
|
||||
}
|
||||
|
||||
// Recorrido para el texto de "Last Stage!" o de "X stages left" o "Game Over"
|
||||
// (2,3)
|
||||
// Recorrido para el texto de "Last Stage!" o de "X stages left" o "Game Over" (2,3)
|
||||
{
|
||||
const auto &texture = Resource::get()->getTexture("last_stage");
|
||||
const auto &texture = Resource::get()->getTexture("game_text_last_stage");
|
||||
const auto h = texture->getHeight();
|
||||
const int y0 = param.game.play_area.rect.h - h;
|
||||
const int y1 = param.game.play_area.center_y - h / 2;
|
||||
@@ -1013,7 +1043,7 @@ void Game::initPaths()
|
||||
|
||||
// Recorrido para el texto de "Congratulations!!" (3,4)
|
||||
{
|
||||
const auto &texture = Resource::get()->getTexture("congratulations");
|
||||
const auto &texture = Resource::get()->getTexture("game_text_congratulations");
|
||||
const auto w = texture->getWidth();
|
||||
const auto h = texture->getHeight();
|
||||
const int x0 = -w;
|
||||
@@ -1026,7 +1056,7 @@ void Game::initPaths()
|
||||
|
||||
// Recorrido para el texto de "1.000.000 points!" (5,6)
|
||||
{
|
||||
const auto &texture = Resource::get()->getTexture("1000000_points");
|
||||
const auto &texture = Resource::get()->getTexture("game_text_1000000_points");
|
||||
const auto w = texture->getWidth();
|
||||
const auto h = texture->getHeight();
|
||||
const int x0 = param.game.play_area.rect.w;
|
||||
@@ -1164,8 +1194,7 @@ void Game::checkEvents()
|
||||
}
|
||||
case SDLK_6: // Crea un mensaje
|
||||
{
|
||||
createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("congratulations"));
|
||||
createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("1000000_points"));
|
||||
createMessage({paths_.at(2), paths_.at(3)}, Resource::get()->getTexture("game_text_congratulations"));
|
||||
break;
|
||||
}
|
||||
case SDLK_7: // Flash
|
||||
@@ -1176,6 +1205,12 @@ void Game::checkEvents()
|
||||
case SDLK_8:
|
||||
{
|
||||
players_.at(0)->setPlayingState(PlayerState::LEAVING_SCREEN);
|
||||
break;
|
||||
}
|
||||
case SDLK_9:
|
||||
{
|
||||
tabe_->enable();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
@@ -1342,7 +1377,8 @@ void Game::handleDemoMode()
|
||||
|
||||
if (input_->checkAnyButtonPressed())
|
||||
{
|
||||
section::name = section::Name::TITLE; // Salir del modo demo y regresar al menú principal.
|
||||
section::name = section::Name::TITLE; // Salir del modo demo y regresar al menú principal.
|
||||
section::attract_mode = section::AttractMode::TITLE_TO_DEMO; // El juego volverá a mostrar la demo
|
||||
return;
|
||||
}
|
||||
++index;
|
||||
@@ -1691,6 +1727,16 @@ void Game::resumeMusic()
|
||||
}
|
||||
}
|
||||
|
||||
// Hace sonar la música
|
||||
void Game::playMusic()
|
||||
{
|
||||
// Si la música no está sonando
|
||||
if (JA_GetMusicState() == JA_MUSIC_INVALID || JA_GetMusicState() == JA_MUSIC_STOPPED)
|
||||
{
|
||||
JA_PlayMusic(Resource::get()->getMusic("playing.ogg"));
|
||||
}
|
||||
}
|
||||
|
||||
// Detiene la música
|
||||
void Game::stopMusic()
|
||||
{
|
||||
@@ -1712,12 +1758,12 @@ void Game::updateDemo()
|
||||
// Activa el fundido antes de acabar con los datos de la demo
|
||||
if (demo_.counter == TOTAL_DEMO_DATA - 200)
|
||||
{
|
||||
fade_->setType(FadeType::RANDOM_SQUARE);
|
||||
fade_->activate();
|
||||
fade_out_->setType(FadeType::RANDOM_SQUARE);
|
||||
fade_out_->activate();
|
||||
}
|
||||
|
||||
// Si ha terminado el fundido, cambia de sección
|
||||
if (fade_->hasEnded())
|
||||
if (fade_out_->hasEnded())
|
||||
{
|
||||
section::name = section::Name::HI_SCORE_TABLE;
|
||||
return;
|
||||
@@ -1756,15 +1802,18 @@ void Game::updateGame()
|
||||
Stage::addPower(5);
|
||||
}
|
||||
#endif
|
||||
fade_->update();
|
||||
fade_in_->update();
|
||||
fade_out_->update();
|
||||
updatePlayers();
|
||||
checkPlayersStatusPlaying();
|
||||
updateScoreboard();
|
||||
updateBackground();
|
||||
balloon_manager_->update();
|
||||
tabe_->update();
|
||||
moveBullets();
|
||||
updateItems();
|
||||
updateStage();
|
||||
updateFadeInState();
|
||||
updateGameOverState();
|
||||
updateCompletedState();
|
||||
updateSmartSprites();
|
||||
@@ -1792,21 +1841,24 @@ void Game::cleanVectors()
|
||||
// Gestiona el nivel de amenaza
|
||||
void Game::updateMenace()
|
||||
{
|
||||
const auto stage = Stage::get(Stage::number);
|
||||
const float percent = Stage::power / stage.power_to_complete;
|
||||
const int difference = stage.max_menace - stage.min_menace;
|
||||
|
||||
// Aumenta el nivel de amenaza en función de la puntuación
|
||||
menace_threshold_ = stage.min_menace + (difference * percent);
|
||||
|
||||
// Si el nivel de amenza es inferior al umbral
|
||||
if (menace_current_ < menace_threshold_)
|
||||
if (state_ == GameState::PLAYING)
|
||||
{
|
||||
// Crea una formación de enemigos
|
||||
balloon_manager_->deployBalloonFormation(Stage::number);
|
||||
const auto stage = Stage::get(Stage::number);
|
||||
const float percent = Stage::power / stage.power_to_complete;
|
||||
const int difference = stage.max_menace - stage.min_menace;
|
||||
|
||||
// Recalcula el nivel de amenaza con el nuevo globo
|
||||
evaluateAndSetMenace();
|
||||
// Aumenta el nivel de amenaza en función de la puntuación
|
||||
menace_threshold_ = stage.min_menace + (difference * percent);
|
||||
|
||||
// Si el nivel de amenza es inferior al umbral
|
||||
if (menace_current_ < menace_threshold_)
|
||||
{
|
||||
// Crea una formación de enemigos
|
||||
balloon_manager_->deployBalloonFormation(Stage::number);
|
||||
|
||||
// Recalcula el nivel de amenaza con el nuevo globo
|
||||
evaluateAndSetMenace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
class Asset; // lines 13-13
|
||||
class Background; // lines 14-14
|
||||
class BalloonManager;
|
||||
class Tabe;
|
||||
class Bullet; // lines 15-15
|
||||
class Fade; // lines 16-16
|
||||
class Input; // lines 17-17
|
||||
@@ -65,6 +66,7 @@ private:
|
||||
// Enum
|
||||
enum class GameState
|
||||
{
|
||||
FADE_IN,
|
||||
PLAYING,
|
||||
COMPLETED,
|
||||
GAME_OVER,
|
||||
@@ -140,8 +142,10 @@ private:
|
||||
std::vector<std::vector<std::string>> item_animations_; // Vector con las animaciones de los items
|
||||
std::vector<std::vector<std::string>> player_animations_; // Vector con las animaciones del jugador
|
||||
|
||||
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
|
||||
std::unique_ptr<Fade> fade_in_; // Objeto para renderizar fades
|
||||
std::unique_ptr<Fade> fade_out_; // Objeto para renderizar fades
|
||||
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
|
||||
std::unique_ptr<Tabe> tabe_; // Objeto para gestionar el Tabe Volaor
|
||||
std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados
|
||||
|
||||
// Variables
|
||||
@@ -164,7 +168,7 @@ private:
|
||||
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
|
||||
int menace_current_ = 0; // Nivel de amenaza actual
|
||||
int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
|
||||
GameState state_ = GameState::PLAYING; // Estado
|
||||
GameState state_ = GameState::FADE_IN; // Estado
|
||||
#ifdef DEBUG
|
||||
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
|
||||
#endif
|
||||
@@ -193,6 +197,9 @@ private:
|
||||
// Comprueba si hay cambio de fase y actualiza las variables
|
||||
void updateStage();
|
||||
|
||||
// Actualiza el estado de fade in
|
||||
void updateFadeInState();
|
||||
|
||||
// Actualiza el estado de fin de la partida
|
||||
void updateGameOverState();
|
||||
|
||||
@@ -373,6 +380,9 @@ private:
|
||||
// Reanuda la música
|
||||
void resumeMusic();
|
||||
|
||||
// Hace sonar la música
|
||||
void playMusic();
|
||||
|
||||
// Detiene la música
|
||||
void stopMusic();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "game_logo.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_render.h> // Para SDL_FLIP_HORIZONTAL
|
||||
#include <algorithm> // Para max
|
||||
#include "animated_sprite.h" // Para AnimatedSprite
|
||||
@@ -8,6 +9,11 @@
|
||||
#include "smart_sprite.h" // Para SmartSprite
|
||||
#include "sprite.h" // Para Sprite
|
||||
#include "texture.h" // Para Texture
|
||||
#include "screen.h"
|
||||
|
||||
constexpr int ZOOM_FACTOR = 5;
|
||||
constexpr int FLASH_DELAY = 3;
|
||||
constexpr int FLASH_LENGHT = FLASH_DELAY + 3;
|
||||
|
||||
// Constructor
|
||||
GameLogo::GameLogo(int x, int y)
|
||||
@@ -21,7 +27,7 @@ GameLogo::GameLogo(int x, int y)
|
||||
crisis_sprite_(std::make_unique<SmartSprite>(crisis_texture_)),
|
||||
arcade_edition_sprite_(std::make_unique<Sprite>(arcade_edition_texture_, (param.game.width - arcade_edition_texture_->getWidth()) / 2, param.title.arcade_edition_position, arcade_edition_texture_->getWidth(), arcade_edition_texture_->getHeight())),
|
||||
x_(x),
|
||||
y_(y) { }
|
||||
y_(y) {}
|
||||
|
||||
// Inicializa las variables
|
||||
void GameLogo::init()
|
||||
@@ -32,15 +38,8 @@ void GameLogo::init()
|
||||
// Variables
|
||||
coffee_crisis_status_ = Status::DISABLED;
|
||||
arcade_edition_status_ = Status::DISABLED;
|
||||
|
||||
shake_.desp = 1;
|
||||
shake_.delay = 2;
|
||||
shake_.lenght = 8;
|
||||
shake_.remaining = shake_.lenght;
|
||||
shake_.counter = shake_.delay;
|
||||
shake_.origin = xp;
|
||||
|
||||
zoom_ = 3.0f;
|
||||
shake_.init(1, 2, 8, xp);
|
||||
zoom_ = 3.0f * ZOOM_FACTOR;
|
||||
|
||||
// Inicializa el bitmap de 'Coffee'
|
||||
coffee_sprite_->setPosX(xp);
|
||||
@@ -122,10 +121,11 @@ void GameLogo::update()
|
||||
if (coffee_sprite_->hasFinished() && crisis_sprite_->hasFinished())
|
||||
{
|
||||
coffee_crisis_status_ = Status::SHAKING;
|
||||
arcade_edition_status_ = Status::MOVING;
|
||||
|
||||
// Reproduce el efecto sonoro
|
||||
JA_PlaySound(Resource::get()->getSound("title.wav"));
|
||||
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
|
||||
Screen::get()->shake();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -133,7 +133,7 @@ void GameLogo::update()
|
||||
|
||||
case Status::SHAKING:
|
||||
{
|
||||
// Agita el logo
|
||||
// Agita "COFFEE CRISIS"
|
||||
if (shake_.remaining > 0)
|
||||
{
|
||||
if (shake_.counter > 0)
|
||||
@@ -154,6 +154,7 @@ void GameLogo::update()
|
||||
coffee_sprite_->setPosX(shake_.origin);
|
||||
crisis_sprite_->setPosX(shake_.origin + 15);
|
||||
coffee_crisis_status_ = Status::FINISHED;
|
||||
arcade_edition_status_ = Status::MOVING;
|
||||
}
|
||||
|
||||
dust_right_sprite_->update();
|
||||
@@ -178,12 +179,42 @@ void GameLogo::update()
|
||||
{
|
||||
case Status::MOVING:
|
||||
{
|
||||
zoom_ -= 0.1f;
|
||||
zoom_ -= 0.1f * ZOOM_FACTOR;
|
||||
arcade_edition_sprite_->setZoom(zoom_);
|
||||
if (zoom_ <= 1.0f)
|
||||
{
|
||||
arcade_edition_status_ = Status::FINISHED;
|
||||
arcade_edition_status_ = Status::SHAKING;
|
||||
zoom_ = 1.0f;
|
||||
arcade_edition_sprite_->setZoom(zoom_);
|
||||
shake_.init(1, 2, 8, arcade_edition_sprite_->getX());
|
||||
JA_PlaySound(Resource::get()->getSound("title.wav"));
|
||||
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
|
||||
Screen::get()->shake();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Status::SHAKING:
|
||||
{
|
||||
// Agita "ARCADE EDITION"
|
||||
if (shake_.remaining > 0)
|
||||
{
|
||||
if (shake_.counter > 0)
|
||||
{
|
||||
shake_.counter--;
|
||||
}
|
||||
else
|
||||
{
|
||||
shake_.counter = shake_.delay;
|
||||
const auto desp = shake_.remaining % 2 == 0 ? shake_.desp * (-1) : shake_.desp;
|
||||
arcade_edition_sprite_->setX(shake_.origin + desp);
|
||||
shake_.remaining--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
arcade_edition_sprite_->setX(shake_.origin);
|
||||
arcade_edition_status_ = Status::FINISHED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -191,6 +222,13 @@ void GameLogo::update()
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (coffee_crisis_status_ == Status::FINISHED &&
|
||||
arcade_edition_status_ == Status::FINISHED &&
|
||||
post_finished_counter_ > 0)
|
||||
{
|
||||
--post_finished_counter_;
|
||||
}
|
||||
}
|
||||
|
||||
// Activa la clase
|
||||
@@ -203,7 +241,7 @@ void GameLogo::enable()
|
||||
// Indica si ha terminado la animación
|
||||
bool GameLogo::hasFinished() const
|
||||
{
|
||||
return coffee_crisis_status_ == Status::FINISHED && arcade_edition_status_ == Status::FINISHED;
|
||||
return post_finished_counter_ == 0;
|
||||
}
|
||||
|
||||
// Recarga las texturas
|
||||
|
||||
@@ -20,12 +20,30 @@ private:
|
||||
|
||||
struct Shake
|
||||
{
|
||||
int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x
|
||||
int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse
|
||||
int counter; // Contador para el retraso
|
||||
int lenght; // Cantidad de desplazamientos a realizar
|
||||
int remaining; // Cantidad de desplazamientos pendientes a realizar
|
||||
int origin; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
|
||||
int desp = 1; // Pixels de desplazamiento para agitar la pantalla en el eje x
|
||||
int delay = 2; // Retraso entre cada desplazamiento de la pantalla al agitarse
|
||||
int lenght = 8; // Cantidad de desplazamientos a realizar
|
||||
int remaining = lenght; // Cantidad de desplazamientos pendientes a realizar
|
||||
int counter = delay; // Contador para el retraso
|
||||
int origin; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
|
||||
|
||||
// Constructor por defect
|
||||
Shake() = default;
|
||||
|
||||
// Constructor
|
||||
Shake(int d, int de, int l, int o)
|
||||
: desp(d), delay(de), lenght(l), remaining(l), counter(de), origin(o) {}
|
||||
|
||||
// Inicializa los miembros
|
||||
void init(int d, int de, int l, int o)
|
||||
{
|
||||
desp = d;
|
||||
delay = de;
|
||||
lenght = l;
|
||||
remaining = l;
|
||||
counter = de;
|
||||
origin = o;
|
||||
}
|
||||
};
|
||||
|
||||
// Objetos y punteros
|
||||
@@ -43,9 +61,10 @@ private:
|
||||
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite con los graficos de "Arcade Edition"
|
||||
|
||||
// Variables
|
||||
int x_; // Posición donde dibujar el logo
|
||||
int y_; // Posición donde dibujar el logo
|
||||
float zoom_; // Zoom aplicado al texto "ARCADE EDITION"
|
||||
int x_; // Posición donde dibujar el logo
|
||||
int y_; // Posición donde dibujar el logo
|
||||
float zoom_; // Zoom aplicado al texto "ARCADE EDITION"
|
||||
int post_finished_counter_ = 1; // Contador final una vez terminada las animaciones de los logos
|
||||
|
||||
Status coffee_crisis_status_ = Status::DISABLED; // Estado en el que se encuentra el texto "COFFEE CRISIS"
|
||||
Status arcade_edition_status_ = Status::DISABLED; // Estado en el que se encuentra el texto "ARCADE_EDITION"
|
||||
|
||||
@@ -108,6 +108,13 @@ namespace globalInputs
|
||||
Notifier::get()->showText({getLangName(options.game.language)});
|
||||
}
|
||||
|
||||
// Cambia el modo de disparo
|
||||
void toggleFireMode()
|
||||
{
|
||||
options.game.autofire = !options.game.autofire;
|
||||
Notifier::get()->showText({"Autofire " + boolToOnOff(options.game.autofire)});
|
||||
}
|
||||
|
||||
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
||||
void check()
|
||||
{
|
||||
@@ -162,6 +169,13 @@ namespace globalInputs
|
||||
return;
|
||||
}
|
||||
|
||||
// Autofire
|
||||
if (Input::get()->checkInput(InputType::AUTO_FIRE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
|
||||
{
|
||||
toggleFireMode();
|
||||
return;
|
||||
}
|
||||
|
||||
// Idioma
|
||||
if (Input::get()->checkInput(InputType::CHANGE_LANG, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
|
||||
{
|
||||
|
||||
@@ -205,9 +205,10 @@ void HiScoreTable::checkInput()
|
||||
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
|
||||
if (Input::get()->checkAnyButtonPressed())
|
||||
{
|
||||
JA_StopMusic();
|
||||
//JA_StopMusic();
|
||||
section::name = section::Name::TITLE;
|
||||
section::options = section::Options::TITLE_1;
|
||||
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ enum class InputType : int
|
||||
SHOWINFO,
|
||||
CONFIG,
|
||||
SWAP_CONTROLLERS,
|
||||
AUTO_FIRE,
|
||||
|
||||
// Input obligatorio
|
||||
NONE,
|
||||
|
||||
@@ -310,9 +310,10 @@ void Instructions::checkInput()
|
||||
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
|
||||
if (Input::get()->checkAnyButtonPressed())
|
||||
{
|
||||
JA_StopMusic();
|
||||
//JA_StopMusic();
|
||||
section::name = section::Name::TITLE;
|
||||
section::options = section::Options::TITLE_1;
|
||||
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -416,7 +416,6 @@ void Intro::render()
|
||||
void Intro::run()
|
||||
{
|
||||
JA_PlayMusic(Resource::get()->getMusic("intro.ogg"), 0);
|
||||
|
||||
while (section::name == section::Name::INTRO)
|
||||
{
|
||||
checkInput();
|
||||
|
||||
@@ -1,91 +1,92 @@
|
||||
#ifndef JA_USESDLMIXER
|
||||
|
||||
#include "jail_audio.h"
|
||||
#include <stdint.h> // para uint8_t
|
||||
#include <stdio.h> // para NULL, fseek, fclose, fopen, fread, ftell, FILE
|
||||
#include <stdlib.h> // para free, malloc
|
||||
#include "stb_vorbis.c" // para stb_vorbis_decode_memory
|
||||
#include "stb_vorbis.c"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define JA_MAX_SIMULTANEOUS_CHANNELS 5
|
||||
#define JA_MAX_SIMULTANEOUS_CHANNELS 20
|
||||
|
||||
struct JA_Sound_t
|
||||
{
|
||||
Uint32 length{0};
|
||||
Uint8 *buffer{NULL};
|
||||
struct JA_Sound_t {
|
||||
Uint32 length {0};
|
||||
Uint8* buffer {NULL};
|
||||
};
|
||||
|
||||
struct JA_Channel_t
|
||||
{
|
||||
JA_Sound_t *sound;
|
||||
int pos{0};
|
||||
int times{0};
|
||||
JA_Channel_state state{JA_CHANNEL_FREE};
|
||||
struct JA_Channel_t {
|
||||
JA_Sound_t *sound;
|
||||
int pos {0};
|
||||
int times {0};
|
||||
JA_Channel_state state { JA_CHANNEL_FREE };
|
||||
};
|
||||
|
||||
struct JA_Music_t
|
||||
{
|
||||
int samples{0};
|
||||
int pos{0};
|
||||
int times{0};
|
||||
short *output{NULL};
|
||||
JA_Music_state state{JA_MUSIC_INVALID};
|
||||
struct JA_Music_t {
|
||||
int samples {0};
|
||||
Uint32 length {0};
|
||||
int pos {0};
|
||||
int times {0};
|
||||
short* output {NULL};
|
||||
JA_Music_state state {JA_MUSIC_INVALID};
|
||||
};
|
||||
|
||||
JA_Music_t *current_music{NULL};
|
||||
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
|
||||
JA_Music_t *current_music{NULL};
|
||||
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
|
||||
|
||||
int JA_freq{48000};
|
||||
SDL_AudioFormat JA_format{AUDIO_S16};
|
||||
Uint8 JA_channels{2};
|
||||
int JA_musicVolume = 128;
|
||||
int JA_soundVolume = 64;
|
||||
bool JA_musicEnabled = true;
|
||||
bool JA_soundEnabled = true;
|
||||
int JA_freq {48000};
|
||||
SDL_AudioFormat JA_format {AUDIO_S16};
|
||||
Uint8 JA_channels {2};
|
||||
int JA_musicVolume = 128;
|
||||
int JA_soundVolume = 64;
|
||||
bool JA_musicEnabled = true;
|
||||
bool JA_soundEnabled = true;
|
||||
SDL_AudioDeviceID sdlAudioDevice = 0;
|
||||
|
||||
void audioCallback(void *userdata, uint8_t *stream, int len)
|
||||
{
|
||||
bool fading = false;
|
||||
int fade_start_time;
|
||||
int fade_duration;
|
||||
int fade_initial_volume;
|
||||
|
||||
void audioCallback(void * userdata, uint8_t * stream, int len) {
|
||||
SDL_memset(stream, 0, len);
|
||||
if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING)
|
||||
{
|
||||
const int size = SDL_min(len, current_music->samples * 2 - current_music->pos);
|
||||
SDL_MixAudioFormat(stream, (Uint8 *)(current_music->output + current_music->pos), AUDIO_S16, size, JA_musicVolume);
|
||||
current_music->pos += size / 2;
|
||||
if (size < len)
|
||||
{
|
||||
if (current_music->times != 0)
|
||||
{
|
||||
SDL_MixAudioFormat(stream + size, (Uint8 *)current_music->output, AUDIO_S16, len - size, JA_musicVolume);
|
||||
current_music->pos = (len - size) / 2;
|
||||
if (current_music->times > 0)
|
||||
current_music->times--;
|
||||
if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING) {
|
||||
int volume = JA_musicVolume;
|
||||
if (fading) {
|
||||
int time = SDL_GetTicks();
|
||||
if (time > (fade_start_time+fade_duration)) {
|
||||
fading = false;
|
||||
current_music->pos = 0;
|
||||
current_music->state = JA_MUSIC_STOPPED;
|
||||
volume = 0;
|
||||
} else {
|
||||
const int time_passed = time - fade_start_time;
|
||||
const float percent = (float)time_passed / (float)fade_duration;
|
||||
volume = JA_musicVolume * (1.0 - percent);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
const int size = SDL_min(len, current_music->length - current_music->pos);
|
||||
SDL_MixAudioFormat(stream, (Uint8*)(current_music->output)+current_music->pos, AUDIO_S16, size, volume);
|
||||
current_music->pos += size;
|
||||
if (size < len) {
|
||||
if (current_music->times != 0) {
|
||||
SDL_MixAudioFormat(stream+size, (Uint8*)current_music->output, AUDIO_S16, len-size, volume);
|
||||
current_music->pos = len-size;
|
||||
if (current_music->times > 0) current_music->times--;
|
||||
} else {
|
||||
current_music->pos = 0;
|
||||
current_music->state = JA_MUSIC_STOPPED;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Mixar els channels mi amol
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
||||
{
|
||||
if (channels[i].state == JA_CHANNEL_PLAYING)
|
||||
{
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
|
||||
if (channels[i].state == JA_CHANNEL_PLAYING) {
|
||||
const int size = SDL_min(len, channels[i].sound->length - channels[i].pos);
|
||||
SDL_MixAudioFormat(stream, channels[i].sound->buffer + channels[i].pos, AUDIO_S16, size, JA_soundVolume);
|
||||
channels[i].pos += size;
|
||||
if (size < len)
|
||||
{
|
||||
if (channels[i].times != 0)
|
||||
{
|
||||
SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len - size, JA_soundVolume);
|
||||
channels[i].pos = len - size;
|
||||
if (channels[i].times > 0)
|
||||
channels[i].times--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size < len) {
|
||||
if (channels[i].times != 0) {
|
||||
SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len-size, JA_soundVolume);
|
||||
channels[i].pos = len-size;
|
||||
if (channels[i].times > 0) channels[i].times--;
|
||||
} else {
|
||||
JA_StopChannel(i);
|
||||
}
|
||||
}
|
||||
@@ -95,69 +96,84 @@ void audioCallback(void *userdata, uint8_t *stream, int len)
|
||||
|
||||
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
|
||||
#endif
|
||||
|
||||
SDL_Log("Iniciant JailAudio...");
|
||||
JA_freq = freq;
|
||||
JA_format = format;
|
||||
JA_channels = channels;
|
||||
SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL};
|
||||
if (sdlAudioDevice != 0)
|
||||
SDL_CloseAudioDevice(sdlAudioDevice);
|
||||
if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice);
|
||||
sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
|
||||
if (sdlAudioDevice==0)
|
||||
{
|
||||
SDL_Log("FAILED!\n");
|
||||
SDL_Log("Failed to initialize SDL audio!\n");
|
||||
} else {
|
||||
SDL_Log("OK!\n");
|
||||
}
|
||||
SDL_PauseAudioDevice(sdlAudioDevice, 0);
|
||||
}
|
||||
|
||||
void JA_Quit()
|
||||
{
|
||||
void JA_Quit() {
|
||||
SDL_PauseAudioDevice(sdlAudioDevice, 1);
|
||||
if (sdlAudioDevice != 0)
|
||||
SDL_CloseAudioDevice(sdlAudioDevice);
|
||||
if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice);
|
||||
sdlAudioDevice = 0;
|
||||
}
|
||||
|
||||
JA_Music_t *JA_LoadMusic(const char *filename)
|
||||
JA_Music_t *JA_LoadMusic(Uint8* buffer, Uint32 length)
|
||||
{
|
||||
int chan, samplerate;
|
||||
|
||||
// [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid.
|
||||
FILE *f = fopen(filename, "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
long fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
Uint8 *buffer = (Uint8 *)malloc(fsize + 1);
|
||||
if (fread(buffer, fsize, 1, f) != 1)
|
||||
return NULL;
|
||||
fclose(f);
|
||||
|
||||
JA_Music_t *music = new JA_Music_t();
|
||||
|
||||
music->samples = stb_vorbis_decode_memory(buffer, fsize, &chan, &samplerate, &music->output);
|
||||
free(buffer);
|
||||
music->samples = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &music->output);
|
||||
// [RZC 28/08/22] Abans el descomprimiem mentre el teniem obert
|
||||
// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
|
||||
// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
|
||||
|
||||
SDL_AudioCVT cvt;
|
||||
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq);
|
||||
if (cvt.needed)
|
||||
{
|
||||
SDL_Log("Music length: %f\n", float(music->samples)/float(JA_freq));
|
||||
if (cvt.needed) {
|
||||
cvt.len = music->samples * chan * 2;
|
||||
cvt.buf = (Uint8 *)SDL_malloc(cvt.len * cvt.len_mult);
|
||||
music->length = cvt.len;
|
||||
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
|
||||
SDL_memcpy(cvt.buf, music->output, cvt.len);
|
||||
SDL_ConvertAudio(&cvt);
|
||||
free(music->output);
|
||||
music->output = (short *)cvt.buf;
|
||||
music->output = (short*)cvt.buf;
|
||||
}
|
||||
music->length = music->samples * chan * 2;
|
||||
music->pos = 0;
|
||||
music->state = JA_MUSIC_STOPPED;
|
||||
|
||||
return music;
|
||||
}
|
||||
|
||||
JA_Music_t *JA_LoadMusic(const char* filename)
|
||||
{
|
||||
// [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid.
|
||||
FILE *f = fopen(filename, "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
long fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
Uint8 *buffer = (Uint8*)malloc(fsize + 1);
|
||||
if (fread(buffer, fsize, 1, f)!=1) return NULL;
|
||||
fclose(f);
|
||||
|
||||
JA_Music_t *music = JA_LoadMusic(buffer, fsize);
|
||||
|
||||
free(buffer);
|
||||
|
||||
return music;
|
||||
}
|
||||
|
||||
void JA_PlayMusic(JA_Music_t *music, const int loop)
|
||||
{
|
||||
if (!JA_musicEnabled || !music)
|
||||
return;
|
||||
if (!JA_musicEnabled) return;
|
||||
|
||||
if (current_music != NULL)
|
||||
{
|
||||
if (current_music != NULL) {
|
||||
current_music->pos = 0;
|
||||
current_music->state = JA_MUSIC_STOPPED;
|
||||
}
|
||||
@@ -169,78 +185,108 @@ void JA_PlayMusic(JA_Music_t *music, const int loop)
|
||||
|
||||
void JA_PauseMusic()
|
||||
{
|
||||
if (!JA_musicEnabled)
|
||||
return;
|
||||
if (!JA_musicEnabled) return;
|
||||
|
||||
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
|
||||
return;
|
||||
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
|
||||
current_music->state = JA_MUSIC_PAUSED;
|
||||
}
|
||||
|
||||
void JA_ResumeMusic()
|
||||
{
|
||||
if (!JA_musicEnabled)
|
||||
return;
|
||||
if (!JA_musicEnabled) return;
|
||||
|
||||
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
|
||||
return;
|
||||
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
|
||||
current_music->state = JA_MUSIC_PLAYING;
|
||||
}
|
||||
|
||||
void JA_StopMusic()
|
||||
{
|
||||
if (!JA_musicEnabled)
|
||||
return;
|
||||
if (!JA_musicEnabled) return;
|
||||
|
||||
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
|
||||
return;
|
||||
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
|
||||
current_music->pos = 0;
|
||||
current_music->state = JA_MUSIC_STOPPED;
|
||||
}
|
||||
|
||||
JA_Music_state JA_GetMusicState()
|
||||
void JA_FadeOutMusic(const int milliseconds)
|
||||
{
|
||||
if (!JA_musicEnabled)
|
||||
return JA_MUSIC_DISABLED;
|
||||
if (!JA_musicEnabled) return;
|
||||
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
|
||||
|
||||
if (current_music == NULL)
|
||||
return JA_MUSIC_INVALID;
|
||||
fading = true;
|
||||
fade_start_time = SDL_GetTicks();
|
||||
fade_duration = milliseconds;
|
||||
fade_initial_volume = JA_musicVolume;
|
||||
}
|
||||
|
||||
JA_Music_state JA_GetMusicState() {
|
||||
if (!JA_musicEnabled) return JA_MUSIC_DISABLED;
|
||||
|
||||
if (current_music == NULL) return JA_MUSIC_INVALID;
|
||||
return current_music->state;
|
||||
}
|
||||
|
||||
void JA_DeleteMusic(JA_Music_t *music)
|
||||
{
|
||||
if (current_music == music)
|
||||
current_music = NULL;
|
||||
void JA_DeleteMusic(JA_Music_t *music) {
|
||||
if (current_music == music) current_music = NULL;
|
||||
free(music->output);
|
||||
delete music;
|
||||
}
|
||||
|
||||
int JA_SetMusicVolume(int volume)
|
||||
{
|
||||
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0
|
||||
: volume;
|
||||
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume;
|
||||
return JA_musicVolume;
|
||||
}
|
||||
|
||||
void JA_SetMusicPosition(float value)
|
||||
{
|
||||
if (!current_music) return;
|
||||
current_music->pos = value * JA_freq;
|
||||
}
|
||||
|
||||
float JA_GetMusicPosition()
|
||||
{
|
||||
if (!current_music) return 0;
|
||||
return float(current_music->pos)/float(JA_freq);
|
||||
}
|
||||
|
||||
void JA_EnableMusic(const bool value)
|
||||
{
|
||||
if (!value && current_music != NULL && current_music->state == JA_MUSIC_PLAYING)
|
||||
JA_StopMusic();
|
||||
if (!value && current_music != NULL && current_music->state==JA_MUSIC_PLAYING) JA_StopMusic();
|
||||
|
||||
JA_musicEnabled = value;
|
||||
}
|
||||
|
||||
JA_Sound_t *JA_NewSound(Uint8 *buffer, Uint32 length)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length) {
|
||||
JA_Sound_t *sound = new JA_Sound_t();
|
||||
sound->buffer = buffer;
|
||||
sound->length = length;
|
||||
return sound;
|
||||
}
|
||||
|
||||
JA_Sound_t *JA_LoadSound(const char *filename)
|
||||
{
|
||||
JA_Sound_t *JA_LoadSound(uint8_t* buffer, uint32_t size) {
|
||||
JA_Sound_t *sound = new JA_Sound_t();
|
||||
SDL_AudioSpec wavSpec;
|
||||
SDL_LoadWAV_RW(SDL_RWFromMem(buffer, size),1, &wavSpec, &sound->buffer, &sound->length);
|
||||
|
||||
SDL_AudioCVT cvt;
|
||||
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq);
|
||||
cvt.len = sound->length;
|
||||
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
|
||||
SDL_memcpy(cvt.buf, sound->buffer, sound->length);
|
||||
SDL_ConvertAudio(&cvt);
|
||||
SDL_FreeWAV(sound->buffer);
|
||||
sound->buffer = cvt.buf;
|
||||
sound->length = cvt.len_cvt;
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
||||
JA_Sound_t *JA_LoadSound(const char* filename) {
|
||||
JA_Sound_t *sound = new JA_Sound_t();
|
||||
SDL_AudioSpec wavSpec;
|
||||
SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length);
|
||||
@@ -248,7 +294,7 @@ JA_Sound_t *JA_LoadSound(const char *filename)
|
||||
SDL_AudioCVT cvt;
|
||||
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq);
|
||||
cvt.len = sound->length;
|
||||
cvt.buf = (Uint8 *)SDL_malloc(cvt.len * cvt.len_mult);
|
||||
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
|
||||
SDL_memcpy(cvt.buf, sound->buffer, sound->length);
|
||||
SDL_ConvertAudio(&cvt);
|
||||
SDL_FreeWAV(sound->buffer);
|
||||
@@ -260,16 +306,24 @@ JA_Sound_t *JA_LoadSound(const char *filename)
|
||||
|
||||
int JA_PlaySound(JA_Sound_t *sound, const int loop)
|
||||
{
|
||||
if (!JA_soundEnabled || !sound)
|
||||
return 0;
|
||||
if (!JA_soundEnabled) return -1;
|
||||
|
||||
int channel = 0;
|
||||
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE)
|
||||
{
|
||||
channel++;
|
||||
}
|
||||
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS)
|
||||
channel = 0;
|
||||
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }
|
||||
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0;
|
||||
|
||||
channels[channel].sound = sound;
|
||||
channels[channel].times = loop;
|
||||
channels[channel].pos = 0;
|
||||
channels[channel].state = JA_CHANNEL_PLAYING;
|
||||
return channel;
|
||||
}
|
||||
|
||||
int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop)
|
||||
{
|
||||
if (!JA_soundEnabled) return -1;
|
||||
|
||||
if (channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return -1;
|
||||
|
||||
channels[channel].sound = sound;
|
||||
channels[channel].times = loop;
|
||||
@@ -280,10 +334,8 @@ int JA_PlaySound(JA_Sound_t *sound, const int loop)
|
||||
|
||||
void JA_DeleteSound(JA_Sound_t *sound)
|
||||
{
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
||||
{
|
||||
if (channels[i].sound == sound)
|
||||
JA_StopChannel(i);
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
|
||||
if (channels[i].sound == sound) JA_StopChannel(i);
|
||||
}
|
||||
SDL_free(sound->buffer);
|
||||
delete sound;
|
||||
@@ -291,60 +343,41 @@ void JA_DeleteSound(JA_Sound_t *sound)
|
||||
|
||||
void JA_PauseChannel(const int channel)
|
||||
{
|
||||
if (!JA_soundEnabled)
|
||||
return;
|
||||
if (!JA_soundEnabled) return;
|
||||
|
||||
if (channel == -1)
|
||||
{
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
||||
{
|
||||
if (channels[i].state == JA_CHANNEL_PLAYING)
|
||||
channels[i].state = JA_CHANNEL_PAUSED;
|
||||
if (channel == -1) {
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
|
||||
if (channels[i].state == JA_CHANNEL_PLAYING) channels[i].state = JA_CHANNEL_PAUSED;
|
||||
}
|
||||
}
|
||||
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
|
||||
{
|
||||
if (channels[channel].state == JA_CHANNEL_PLAYING)
|
||||
channels[channel].state = JA_CHANNEL_PAUSED;
|
||||
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
|
||||
if (channels[channel].state == JA_CHANNEL_PLAYING) channels[channel].state = JA_CHANNEL_PAUSED;
|
||||
}
|
||||
}
|
||||
|
||||
void JA_ResumeChannel(const int channel)
|
||||
{
|
||||
if (!JA_soundEnabled)
|
||||
return;
|
||||
if (!JA_soundEnabled) return;
|
||||
|
||||
if (channel == -1)
|
||||
{
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
||||
{
|
||||
if (channels[i].state == JA_CHANNEL_PAUSED)
|
||||
channels[i].state = JA_CHANNEL_PLAYING;
|
||||
if (channel == -1) {
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
|
||||
if (channels[i].state == JA_CHANNEL_PAUSED) channels[i].state = JA_CHANNEL_PLAYING;
|
||||
}
|
||||
}
|
||||
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
|
||||
{
|
||||
if (channels[channel].state == JA_CHANNEL_PAUSED)
|
||||
channels[channel].state = JA_CHANNEL_PLAYING;
|
||||
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
|
||||
if (channels[channel].state == JA_CHANNEL_PAUSED) channels[channel].state = JA_CHANNEL_PLAYING;
|
||||
}
|
||||
}
|
||||
|
||||
void JA_StopChannel(const int channel)
|
||||
{
|
||||
if (!JA_soundEnabled)
|
||||
return;
|
||||
if (!JA_soundEnabled) return;
|
||||
|
||||
if (channel == -1)
|
||||
{
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
||||
{
|
||||
if (channel == -1) {
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
|
||||
channels[i].state = JA_CHANNEL_FREE;
|
||||
channels[i].pos = 0;
|
||||
channels[i].sound = NULL;
|
||||
}
|
||||
}
|
||||
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
|
||||
{
|
||||
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
|
||||
channels[channel].state = JA_CHANNEL_FREE;
|
||||
channels[channel].pos = 0;
|
||||
channels[channel].sound = NULL;
|
||||
@@ -353,18 +386,15 @@ void JA_StopChannel(const int channel)
|
||||
|
||||
JA_Channel_state JA_GetChannelState(const int channel)
|
||||
{
|
||||
if (!JA_soundEnabled)
|
||||
return JA_SOUND_DISABLED;
|
||||
if (!JA_soundEnabled) return JA_SOUND_DISABLED;
|
||||
|
||||
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS)
|
||||
return JA_CHANNEL_INVALID;
|
||||
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
|
||||
return channels[channel].state;
|
||||
}
|
||||
|
||||
int JA_SetSoundVolume(int volume)
|
||||
{
|
||||
JA_soundVolume = volume > 128 ? 128 : volume < 0 ? 0
|
||||
: volume;
|
||||
JA_soundVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume;
|
||||
return JA_soundVolume;
|
||||
}
|
||||
|
||||
@@ -372,17 +402,15 @@ void JA_EnableSound(const bool value)
|
||||
{
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
||||
{
|
||||
if (channels[i].state == JA_CHANNEL_PLAYING)
|
||||
JA_StopChannel(i);
|
||||
if (channels[i].state == JA_CHANNEL_PLAYING) JA_StopChannel(i);
|
||||
}
|
||||
JA_soundEnabled = value;
|
||||
}
|
||||
|
||||
int JA_SetVolume(int volume)
|
||||
{
|
||||
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0
|
||||
: volume;
|
||||
JA_soundVolume = JA_musicVolume / 2;
|
||||
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume;
|
||||
JA_soundVolume = JA_musicVolume/2;
|
||||
return JA_musicVolume;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,43 +1,34 @@
|
||||
#pragma once
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <SDL2/SDL_audio.h> // para SDL_AudioFormat
|
||||
#include <SDL2/SDL_stdinc.h> // para Uint32, Uint8
|
||||
struct JA_Music_t; // lines 5-5
|
||||
struct JA_Sound_t; // lines 6-6
|
||||
enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED, JA_SOUND_DISABLED };
|
||||
enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED, JA_MUSIC_DISABLED };
|
||||
|
||||
enum JA_Channel_state
|
||||
{
|
||||
JA_CHANNEL_INVALID,
|
||||
JA_CHANNEL_FREE,
|
||||
JA_CHANNEL_PLAYING,
|
||||
JA_CHANNEL_PAUSED,
|
||||
JA_SOUND_DISABLED
|
||||
};
|
||||
enum JA_Music_state
|
||||
{
|
||||
JA_MUSIC_INVALID,
|
||||
JA_MUSIC_PLAYING,
|
||||
JA_MUSIC_PAUSED,
|
||||
JA_MUSIC_STOPPED,
|
||||
JA_MUSIC_DISABLED
|
||||
};
|
||||
struct JA_Sound_t;
|
||||
struct JA_Music_t;
|
||||
|
||||
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels);
|
||||
void JA_Quit();
|
||||
|
||||
JA_Music_t *JA_LoadMusic(const char *filename);
|
||||
JA_Music_t *JA_LoadMusic(const char* filename);
|
||||
JA_Music_t *JA_LoadMusic(Uint8* buffer, Uint32 length);
|
||||
void JA_PlayMusic(JA_Music_t *music, const int loop = -1);
|
||||
void JA_PauseMusic();
|
||||
void JA_ResumeMusic();
|
||||
void JA_StopMusic();
|
||||
void JA_FadeOutMusic(const int milliseconds);
|
||||
JA_Music_state JA_GetMusicState();
|
||||
void JA_DeleteMusic(JA_Music_t *music);
|
||||
int JA_SetMusicVolume(int volume);
|
||||
void JA_SetMusicPosition(float value);
|
||||
float JA_GetMusicPosition();
|
||||
void JA_EnableMusic(const bool value);
|
||||
|
||||
JA_Sound_t *JA_NewSound(Uint8 *buffer, Uint32 length);
|
||||
JA_Sound_t *JA_LoadSound(const char *filename);
|
||||
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length);
|
||||
JA_Sound_t *JA_LoadSound(Uint8* buffer, Uint32 length);
|
||||
JA_Sound_t *JA_LoadSound(const char* filename);
|
||||
int JA_PlaySound(JA_Sound_t *sound, const int loop = 0);
|
||||
int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop = 0);
|
||||
void JA_PauseChannel(const int channel);
|
||||
void JA_ResumeChannel(const int channel);
|
||||
void JA_StopChannel(const int channel);
|
||||
|
||||
@@ -59,7 +59,7 @@ Logo::~Logo()
|
||||
{
|
||||
jail_texture_->setColor(255, 255, 255);
|
||||
since_texture_->setColor(255, 255, 255);
|
||||
JA_PauseChannel(-1);
|
||||
JA_StopChannel(-1);
|
||||
}
|
||||
|
||||
// Recarga todas las texturas
|
||||
@@ -101,7 +101,6 @@ void Logo::checkInput()
|
||||
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
|
||||
if (Input::get()->checkAnyButtonPressed())
|
||||
{
|
||||
JA_StopMusic();
|
||||
section::name = section::Name::TITLE;
|
||||
section::options = section::Options::TITLE_1;
|
||||
return;
|
||||
@@ -235,7 +234,7 @@ void Logo::render()
|
||||
void Logo::run()
|
||||
{
|
||||
// Detiene la música
|
||||
JA_StopMusic();
|
||||
JA_FadeOutMusic(300);
|
||||
|
||||
while (section::name == section::Name::LOGO)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,8 @@ enum class GameDifficulty
|
||||
// Estructura para las opciones de la ventana
|
||||
struct OptionsWindow
|
||||
{
|
||||
int size; // Contiene el valor por el que se multiplica el tamaño de la ventana
|
||||
int size = 1; // Contiene el valor por el que se multiplica el tamaño de la ventana
|
||||
int max_size = 1; // Tamaño máximo para que el tamaño de la ventana no sea mayor que el tamaño de la pantalla
|
||||
};
|
||||
|
||||
// Estructura con opciones para el video
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "param.h" // Para Param, ParamGame, param
|
||||
#include "scoreboard.h" // Para Scoreboard, ScoreboardMode
|
||||
#include "texture.h" // Para Texture
|
||||
#include "resource.h"
|
||||
#include "jail_audio.h"
|
||||
|
||||
// Constructor
|
||||
Player::Player(int id, float x, int y, bool demo, SDL_Rect &play_area, std::vector<std::shared_ptr<Texture>> texture, const std::vector<std::vector<std::string>> &animations)
|
||||
@@ -175,6 +177,7 @@ void Player::move()
|
||||
if ((player_sprite_->getPosX() < play_area_.x) || (player_sprite_->getPosX() + WIDTH_ > play_area_.w))
|
||||
{
|
||||
player_sprite_->setVelX(-player_sprite_->getVelX());
|
||||
JA_PlaySound(Resource::get()->getSound("bubble4.wav"));
|
||||
}
|
||||
|
||||
// Si el cadaver toca el suelo cambia el estado
|
||||
@@ -188,6 +191,7 @@ void Player::move()
|
||||
pos_y_ = default_pos_y_;
|
||||
player_sprite_->clear();
|
||||
shiftSprite();
|
||||
JA_PlaySound(Resource::get()->getSound("bubble4.wav"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -195,6 +199,7 @@ void Player::move()
|
||||
player_sprite_->setPosY(play_area_.h - HEIGHT_);
|
||||
player_sprite_->setVelY(player_sprite_->getVelY() * -0.5f);
|
||||
player_sprite_->setVelX(player_sprite_->getVelX() * 0.75f);
|
||||
JA_PlaySound(Resource::get()->getSound("bubble4.wav"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -290,7 +290,7 @@ void Resource::createTextures()
|
||||
NameAndText("game_text_powerup", lang::getText(117)),
|
||||
NameAndText("game_text_one_hit", lang::getText(118)),
|
||||
NameAndText("game_text_stop", lang::getText(119)),
|
||||
NameAndText("1000000_points", lang::getText(76))};
|
||||
NameAndText("game_text_1000000_points", lang::getText(76))};
|
||||
|
||||
auto text = getText("04b_25");
|
||||
for (const auto &s : strings)
|
||||
@@ -301,10 +301,10 @@ void Resource::createTextures()
|
||||
|
||||
// Tamaño doble
|
||||
std::vector<NameAndText> strings2X = {
|
||||
NameAndText("get_ready", lang::getText(75)),
|
||||
NameAndText("last_stage", lang::getText(79)),
|
||||
NameAndText("congratulations", lang::getText(50)),
|
||||
NameAndText("game_over", "Game Over")};
|
||||
NameAndText("game_text_get_ready", lang::getText(75)),
|
||||
NameAndText("game_text_last_stage", lang::getText(79)),
|
||||
NameAndText("game_text_congratulations", lang::getText(50)),
|
||||
NameAndText("game_text_game_over", "Game Over")};
|
||||
|
||||
auto text2 = getText("04b_25_2x");
|
||||
for (const auto &s : strings2X)
|
||||
|
||||
@@ -235,7 +235,7 @@ void Screen::decWindowSize()
|
||||
void Screen::incWindowSize()
|
||||
{
|
||||
++options.video.window.size;
|
||||
options.video.window.size = std::min(options.video.window.size, 4);
|
||||
options.video.window.size = std::min(options.video.window.size, options.video.window.max_size);
|
||||
setVideoMode(ScreenVideoMode::WINDOW);
|
||||
}
|
||||
|
||||
@@ -308,15 +308,15 @@ void Screen::updateShakeEffect()
|
||||
}
|
||||
|
||||
// Pone la pantalla de color
|
||||
void Screen::flash(Color color, int lenght)
|
||||
void Screen::flash(Color color, int lenght, int delay)
|
||||
{
|
||||
flash_effect_ = FlashEffect(true, lenght, color);
|
||||
flash_effect_ = FlashEffect(true, lenght, delay, color);
|
||||
}
|
||||
|
||||
// Actualiza y dibuja el efecto de flash en la pantalla
|
||||
void Screen::renderFlash()
|
||||
{
|
||||
if (flash_effect_.enabled)
|
||||
if (flash_effect_.isRendarable())
|
||||
{
|
||||
SDL_SetRenderDrawColor(renderer_, flash_effect_.color.r, flash_effect_.color.g, flash_effect_.color.b, 0xFF);
|
||||
SDL_RenderClear(renderer_);
|
||||
@@ -326,10 +326,7 @@ void Screen::renderFlash()
|
||||
// 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_.update();
|
||||
}
|
||||
|
||||
// Atenua la pantalla
|
||||
|
||||
@@ -51,12 +51,20 @@ private:
|
||||
struct FlashEffect
|
||||
{
|
||||
bool enabled; // Indica si el efecto está activo
|
||||
int lenght; // Duración del efecto
|
||||
int delay; // Frames iniciales en los que no se aplica
|
||||
int counter; // Contador para el efecto
|
||||
Color color; // Color del efecto
|
||||
|
||||
// Constructor
|
||||
explicit FlashEffect(bool en = false, int cnt = 0, Color col = Color(0xFF, 0xFF, 0xFF))
|
||||
: enabled(en), counter(cnt), color(col) {}
|
||||
explicit FlashEffect(bool enabled = false, int lenght = 0, int delay = 0, Color color = Color(0xFF, 0xFF, 0xFF))
|
||||
: enabled(enabled), lenght(lenght), delay(delay), counter(lenght), color(color) {}
|
||||
|
||||
// Actualiza
|
||||
void update() { (enabled && counter > 0) ? counter-- : enabled = false; }
|
||||
|
||||
// Indica si se pude dibujar
|
||||
bool isRendarable() { return enabled && counter < lenght - delay; }
|
||||
};
|
||||
|
||||
struct ShakeEffect
|
||||
@@ -155,7 +163,7 @@ public:
|
||||
void shake();
|
||||
|
||||
// Pone la pantalla de color
|
||||
void flash(Color color, int lenght);
|
||||
void flash(Color color, int lenght, int delay = 0);
|
||||
|
||||
// Activa / desactiva los shaders
|
||||
void toggleShaders();
|
||||
|
||||
145
source/tabe.cpp
Normal file
145
source/tabe.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
#include "tabe.h"
|
||||
#include "resource.h"
|
||||
#include "param.h"
|
||||
#include "jail_audio.h"
|
||||
#include <algorithm>
|
||||
|
||||
// Constructor
|
||||
Tabe::Tabe()
|
||||
: sprite_(std::make_unique<AnimatedSprite>(Resource::get()->getTexture("tabe.png"), Resource::get()->getAnimation("tabe.ani"))) {}
|
||||
|
||||
// Actualiza la lógica
|
||||
void Tabe::update()
|
||||
{
|
||||
if (enabled_)
|
||||
{
|
||||
sprite_->update();
|
||||
move();
|
||||
}
|
||||
}
|
||||
|
||||
// Dibuja el objeto
|
||||
void Tabe::render()
|
||||
{
|
||||
if (enabled_)
|
||||
{
|
||||
sprite_->render();
|
||||
}
|
||||
}
|
||||
|
||||
// Mueve el objeto
|
||||
void Tabe::move()
|
||||
{
|
||||
const int x = static_cast<int>(x_);
|
||||
speed_ += accel_;
|
||||
x_ += speed_;
|
||||
fly_distance_ -= std::abs(x - static_cast<int>(x_));
|
||||
|
||||
// Comprueba si sale por los bordes
|
||||
const float min_x = param.game.game_area.rect.x - WIDTH_;
|
||||
const float max_x = param.game.game_area.rect.x + param.game.game_area.rect.w;
|
||||
switch (destiny_)
|
||||
{
|
||||
case TabeDirection::TO_THE_LEFT:
|
||||
{
|
||||
if (x_ < min_x)
|
||||
{
|
||||
enabled_ = false;
|
||||
}
|
||||
if (x_ > param.game.game_area.rect.x + param.game.game_area.rect.w - WIDTH_ && direction_ == TabeDirection::TO_THE_RIGHT)
|
||||
{
|
||||
setRandomFlyPath(TabeDirection::TO_THE_LEFT, 80);
|
||||
x_ = param.game.game_area.rect.x + param.game.game_area.rect.w - WIDTH_;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TabeDirection::TO_THE_RIGHT:
|
||||
{
|
||||
if (x_ > max_x)
|
||||
{
|
||||
enabled_ = false;
|
||||
}
|
||||
if (x_ < param.game.game_area.rect.x && direction_ == TabeDirection::TO_THE_LEFT)
|
||||
{
|
||||
setRandomFlyPath(TabeDirection::TO_THE_RIGHT, 80);
|
||||
x_ = param.game.game_area.rect.x;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (fly_distance_ <= 0)
|
||||
{
|
||||
if (waiting_counter_ > 0)
|
||||
{
|
||||
accel_ = speed_ = 0.0f;
|
||||
--waiting_counter_;
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr int CHOICES = 4;
|
||||
const TabeDirection left[CHOICES] = {TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_RIGHT};
|
||||
const TabeDirection right[CHOICES] = {TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_RIGHT, TabeDirection::TO_THE_RIGHT, TabeDirection::TO_THE_RIGHT};
|
||||
const TabeDirection direction = destiny_ == TabeDirection::TO_THE_LEFT ? left[rand() % CHOICES] : right[rand() % CHOICES];
|
||||
setRandomFlyPath(direction, 20 + rand() % 40);
|
||||
}
|
||||
}
|
||||
|
||||
shiftSprite();
|
||||
}
|
||||
|
||||
// Habilita el objeto
|
||||
void Tabe::enable()
|
||||
{
|
||||
if (!enabled_)
|
||||
{
|
||||
enabled_ = true;
|
||||
y_ = 20.0f;
|
||||
|
||||
// Establece una dirección aleatoria
|
||||
destiny_ = direction_ = rand() % 2 == 0 ? TabeDirection::TO_THE_LEFT : TabeDirection::TO_THE_RIGHT;
|
||||
|
||||
// Establece la posición inicial
|
||||
x_ = (direction_ == TabeDirection::TO_THE_LEFT) ? param.game.game_area.rect.x + param.game.game_area.rect.w : param.game.game_area.rect.x - WIDTH_;
|
||||
|
||||
// Crea una ruta de vuelo
|
||||
setRandomFlyPath(direction_, 60);
|
||||
shiftSprite();
|
||||
}
|
||||
}
|
||||
|
||||
// Establece un vuelo aleatorio
|
||||
void Tabe::setRandomFlyPath(TabeDirection direction, int lenght)
|
||||
{
|
||||
direction_ = direction;
|
||||
fly_distance_ = lenght;
|
||||
waiting_counter_ = 5 + rand() % 15;
|
||||
JA_PlaySound(Resource::get()->getSound("tabe.wav"));
|
||||
|
||||
constexpr float SPEED = 2.0f;
|
||||
|
||||
switch (direction)
|
||||
{
|
||||
case TabeDirection::TO_THE_LEFT:
|
||||
{
|
||||
speed_ = -1.0f * SPEED;
|
||||
accel_ = -1.0f * (1 + rand() % 10) / 30.0f;
|
||||
sprite_->setFlip(SDL_FLIP_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case TabeDirection::TO_THE_RIGHT:
|
||||
{
|
||||
speed_ = SPEED;
|
||||
accel_ = (1 + rand() % 10) / 30.0f;
|
||||
sprite_->setFlip(SDL_FLIP_HORIZONTAL);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
58
source/tabe.h
Normal file
58
source/tabe.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "animated_sprite.h"
|
||||
#include <memory>
|
||||
|
||||
enum class TabeDirection : int
|
||||
{
|
||||
TO_THE_LEFT = 0,
|
||||
TO_THE_RIGHT = 1,
|
||||
};
|
||||
|
||||
// Clase Tabe
|
||||
class Tabe
|
||||
{
|
||||
private:
|
||||
// Constantes
|
||||
static constexpr int WIDTH_ = 32;
|
||||
static constexpr int HEIGHT_ = 32;
|
||||
|
||||
// Punteros
|
||||
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los graficos y animaciones
|
||||
|
||||
// Variables
|
||||
float x_ = 0; // Posición del objeto
|
||||
float y_ = 0; // Posición del objeto
|
||||
float speed_ = 0.0f; // Velocidad de movimiento del objeto
|
||||
float accel_ = 0.0f; // Aceleración del objeto
|
||||
int fly_distance_ = 0; // Distancia de vuelo
|
||||
int waiting_counter_ = 0; // Tiempo que pasa quieto el objeto
|
||||
bool enabled_ = false; // Indica si el objeto está activo
|
||||
TabeDirection direction_; // Dirección del objeto
|
||||
TabeDirection destiny_; // Destino del objeto
|
||||
|
||||
// Mueve el objeto
|
||||
void move();
|
||||
|
||||
// Actualiza la posición del sprite
|
||||
void shiftSprite() { sprite_->setPos(x_, y_); }
|
||||
|
||||
// Establece un vuelo aleatorio
|
||||
void setRandomFlyPath(TabeDirection direction, int lenght);
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Tabe();
|
||||
|
||||
// Destructor
|
||||
~Tabe() = default;
|
||||
|
||||
// Actualiza la lógica
|
||||
void update();
|
||||
|
||||
// Dibuja el objeto
|
||||
void render();
|
||||
|
||||
// Habilita el objeto
|
||||
void enable();
|
||||
};
|
||||
@@ -161,12 +161,14 @@ std::shared_ptr<Texture> Text::writeToTexture(const std::string &text, int zoom,
|
||||
auto texture = std::make_shared<Texture>(renderer);
|
||||
auto width = lenght(text, kerning) * zoom;
|
||||
auto height = box_height_ * zoom;
|
||||
auto temp = SDL_GetRenderTarget(renderer);
|
||||
texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
|
||||
texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
||||
texture->setAsRenderTarget(renderer);
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
||||
SDL_RenderClear(renderer);
|
||||
zoom == 1 ? write(0, 0, text, kerning) : write2X(0, 0, text, kerning);
|
||||
SDL_SetRenderTarget(renderer, temp);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
@@ -31,9 +31,10 @@ Title::Title()
|
||||
fade_(std::make_unique<Fade>()),
|
||||
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::RANDOM)),
|
||||
game_logo_(std::make_unique<GameLogo>(param.game.game_area.center_x, param.title.title_c_c_position)),
|
||||
mini_logo_sprite_(std::make_unique<Sprite>(Resource::get()->getTexture("logo_jailgames_mini.png"))),
|
||||
mini_logo_sprite_(std::make_unique<Sprite>(Resource::get()->getTexture("logo_jailgames_mini.png"))),
|
||||
define_buttons_(std::make_unique<DefineButtons>()),
|
||||
num_controllers_(Input::get()->getNumControllers())
|
||||
num_controllers_(Input::get()->getNumControllers()),
|
||||
state_(TitleState::LOGO_ANIMATING)
|
||||
{
|
||||
// Configura objetos
|
||||
game_logo_->enable();
|
||||
@@ -54,6 +55,7 @@ Title::Title()
|
||||
Title::~Title()
|
||||
{
|
||||
Resource::get()->getTexture("smb2.gif")->setPalette(0);
|
||||
JA_StopChannel(-1);
|
||||
}
|
||||
|
||||
// Actualiza las variables del objeto
|
||||
@@ -70,9 +72,9 @@ void Title::update()
|
||||
Screen::get()->update();
|
||||
|
||||
// Actualiza las variables de globalInputs
|
||||
globalInputs::update();
|
||||
globalInputs::update();
|
||||
|
||||
// Comprueba el fundido y si se ha acabado
|
||||
// Comprueba el fundido
|
||||
fade_->update();
|
||||
if (fade_->hasEnded())
|
||||
{
|
||||
@@ -88,18 +90,19 @@ void Title::update()
|
||||
}
|
||||
}
|
||||
|
||||
// Sección 1 - Titulo animandose
|
||||
if (section::options == section::Options::TITLE_1)
|
||||
// Establece la lógica según el estado
|
||||
switch (state_)
|
||||
{
|
||||
case TitleState::LOGO_ANIMATING:
|
||||
{
|
||||
game_logo_->update();
|
||||
if (game_logo_->hasFinished())
|
||||
{
|
||||
section::options = section::Options::TITLE_2;
|
||||
state_ = TitleState::LOGO_FINISHED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Sección 2 - La pantalla con el titulo, el fondo animado y la música
|
||||
else if (section::options == section::Options::TITLE_2)
|
||||
case TitleState::LOGO_FINISHED:
|
||||
{
|
||||
// El contador solo sube si no estamos definiendo botones
|
||||
counter_ = define_buttons_->isEnabled() ? 0 : counter_ + 1;
|
||||
@@ -121,6 +124,27 @@ void Title::update()
|
||||
fade_->activate();
|
||||
post_fade_ = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TitleState::START_HAS_BEEN_PRESSED:
|
||||
{
|
||||
// Actualiza el logo con el título del juego
|
||||
game_logo_->update();
|
||||
|
||||
// Actualiza el mosaico de fondo
|
||||
tiled_bg_->update();
|
||||
|
||||
if (counter_ == 100)
|
||||
{
|
||||
fade_->activate();
|
||||
}
|
||||
++counter_;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,16 +164,10 @@ void Title::render()
|
||||
// Dibuja el logo con el título del juego
|
||||
game_logo_->render();
|
||||
|
||||
if (section::options == section::Options::TITLE_2)
|
||||
constexpr Color shadow = Color(0x14, 0x87, 0xc4);
|
||||
|
||||
if (state_ != TitleState::LOGO_ANIMATING)
|
||||
{
|
||||
constexpr Color shadow = Color(0x14, 0x87, 0xc4);
|
||||
|
||||
// 'PRESS TO PLAY'
|
||||
if (counter_ % 50 > 14 && !define_buttons_->isEnabled())
|
||||
{
|
||||
text_->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, param.title.press_start_position, lang::getText(23), 1, no_color, 1, shadow);
|
||||
}
|
||||
|
||||
// Mini logo
|
||||
const int pos1 = (param.game.height / 5 * 4) + BLOCK;
|
||||
const int pos2 = pos1 + mini_logo_sprite_->getHeight() + 3;
|
||||
@@ -160,6 +178,24 @@ void Title::render()
|
||||
text_->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, pos2, TEXT_COPYRIGHT, 1, no_color, 1, shadow);
|
||||
}
|
||||
|
||||
if (state_ == TitleState::LOGO_FINISHED)
|
||||
{
|
||||
// 'PRESS TO PLAY'
|
||||
if (counter_ % 50 > 14 && !define_buttons_->isEnabled())
|
||||
{
|
||||
text_->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, param.title.press_start_position, lang::getText(23), 1, no_color, 1, shadow);
|
||||
}
|
||||
}
|
||||
|
||||
if (state_ == TitleState::START_HAS_BEEN_PRESSED)
|
||||
{
|
||||
// 'PRESS TO PLAY'
|
||||
if (counter_ % 10 > 4 && !define_buttons_->isEnabled())
|
||||
{
|
||||
text_->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, param.title.press_start_position, lang::getText(23), 1, no_color, 1, shadow);
|
||||
}
|
||||
}
|
||||
|
||||
// Define Buttons
|
||||
define_buttons_->render();
|
||||
|
||||
@@ -241,24 +277,28 @@ void Title::checkEvents()
|
||||
// Comprueba las entradas
|
||||
void Title::checkInput()
|
||||
{
|
||||
// Comprueba los controladores solo si no se estan definiendo los botones
|
||||
// Comprueba las entradas solo si no se estan definiendo los botones
|
||||
if (!define_buttons_->isEnabled())
|
||||
{
|
||||
// Comprueba los métodos de control
|
||||
// Comprueba todos los métodos de control
|
||||
for (const auto &controller : options.controllers)
|
||||
{
|
||||
// START
|
||||
if (Input::get()->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, controller.type, controller.index) &&
|
||||
!Input::get()->checkInput(InputType::SERVICE, INPUT_DO_NOT_ALLOW_REPEAT, controller.type, controller.index))
|
||||
{
|
||||
if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP)
|
||||
if (state_ == TitleState::LOGO_FINISHED || ALLOW_TITLE_ANIMATION_SKIP)
|
||||
{
|
||||
fade_->activate();
|
||||
JA_PlaySound(Resource::get()->getSound("game_start.wav"));
|
||||
JA_FadeOutMusic(1500);
|
||||
post_fade_ = controller.player_id;
|
||||
state_ = TitleState::START_HAS_BEEN_PRESSED;
|
||||
counter_ = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba si se va a intercambiar la asignación de mandos a jugadores
|
||||
// SWAP_CONTROLLERS
|
||||
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, controller.type, controller.index) &&
|
||||
Input::get()->checkInput(InputType::SWAP_CONTROLLERS, INPUT_DO_NOT_ALLOW_REPEAT, controller.type, controller.index))
|
||||
{
|
||||
@@ -266,7 +306,7 @@ void Title::checkInput()
|
||||
return;
|
||||
}
|
||||
|
||||
// Comprueba si algun mando quiere ser configurado
|
||||
// CONFIG
|
||||
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, controller.type, controller.index) &&
|
||||
Input::get()->checkInput(InputType::CONFIG, INPUT_DO_NOT_ALLOW_REPEAT, controller.type, controller.index))
|
||||
{
|
||||
@@ -345,7 +385,6 @@ void Title::showControllers()
|
||||
}
|
||||
}
|
||||
|
||||
// std::string spaces(lang::getText(100).length() + 3, ' ');
|
||||
// std::string kb_text = spaces + lang::getText(69);
|
||||
// Muestra la notificación
|
||||
Notifier::get()->showText({text.at(0), text.at(1)});
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace section
|
||||
constexpr const char TEXT_COPYRIGHT[] = "@2020,2024 JailDesigner";
|
||||
|
||||
// Parámetros
|
||||
constexpr bool ALLOW_TITLE_ANIMATION_SKIP = true;
|
||||
constexpr bool ALLOW_TITLE_ANIMATION_SKIP = false;
|
||||
|
||||
/*
|
||||
Esta clase gestiona un estado del programa. Se encarga de la parte del titulo o menu
|
||||
@@ -27,9 +27,10 @@ constexpr bool ALLOW_TITLE_ANIMATION_SKIP = true;
|
||||
- Dibujar el tileado de fondo
|
||||
- Redifinir los botones de los mandos de juego
|
||||
|
||||
Esta clase tiene dos estados:
|
||||
Esta clase tiene tres estados:
|
||||
- El titulo está animandose, con el fondo estático
|
||||
- El titulo ya está en su sitio y el fondo se está animando
|
||||
- Se ha pulsado el botón de start
|
||||
|
||||
Por razones de diseño, no se permite saltarse la animación del titulo, aunque es
|
||||
configurable mediante un define
|
||||
@@ -39,6 +40,14 @@ constexpr bool ALLOW_TITLE_ANIMATION_SKIP = true;
|
||||
class Title
|
||||
{
|
||||
private:
|
||||
// Enumeraciones
|
||||
enum class TitleState
|
||||
{
|
||||
LOGO_ANIMATING,
|
||||
LOGO_FINISHED,
|
||||
START_HAS_BEEN_PRESSED,
|
||||
};
|
||||
|
||||
// Objetos y punteros
|
||||
std::shared_ptr<Text> text_; // Objeto de texto para poder escribir textos en pantalla
|
||||
std::unique_ptr<Fade> fade_; // Objeto para realizar fundidos en pantalla
|
||||
@@ -53,6 +62,7 @@ private:
|
||||
section::Name next_section_; // Indica cual es la siguiente sección a cargar cuando termine el contador del titulo
|
||||
int post_fade_ = 0; // Opción a realizar cuando termina el fundido
|
||||
int num_controllers_; // Número de mandos conectados
|
||||
TitleState state_; // Estado en el que se encuentra la sección
|
||||
|
||||
// Actualiza las variables del objeto
|
||||
void update();
|
||||
|
||||
Reference in New Issue
Block a user