50 Commits

Author SHA1 Message Date
a2a6262ffe working on new font engine 2021-08-25 22:35:54 +02:00
dbd22fa719 new font added 2021-08-25 20:00:59 +02:00
5bb5022ebf fix bullet owner bug 2021-08-25 17:59:40 +02:00
3440dea0a5 working on game controller 2021-08-25 13:34:40 +02:00
36eaf1de4f working on game controller 2021-08-25 12:02:18 +02:00
c3d560a9b6 working on game controller input 2021-08-24 20:52:32 +02:00
09cee79122 working on game controller input 2021-08-24 20:28:27 +02:00
03cbc67cfb working on game controller input 2021-08-24 20:20:08 +02:00
23d9bb0e3d working on game controller input 2021-08-24 20:15:20 +02:00
f9d6917770 working on game controller input 2021-08-24 20:12:28 +02:00
bf45482c10 working on game controller input 2021-08-24 20:06:34 +02:00
39a59336e4 working on game controller input 2021-08-24 19:56:25 +02:00
7c0201f913 working on game controller input 2021-08-24 17:57:21 +02:00
b61fd84e22 working on 2p 2021-08-24 13:01:33 +02:00
52ea512eab working on 2p 2021-08-23 21:53:54 +02:00
Sergio Valor
26ac51b1be working on 2players 2021-08-23 13:44:05 +02:00
fb1ff3c97a working on 2players 2021-08-23 08:11:24 +02:00
943fb7bf27 working on 2players 2021-08-22 19:50:55 +02:00
2fd4334259 added poerup and helper 2021-08-22 16:15:10 +02:00
eb8f84a4b8 added player2 gfx 2021-08-22 09:41:38 +02:00
e793e08e85 added player2 gfx 2021-08-22 09:41:17 +02:00
837306f16e added power up on the player 2021-08-21 20:39:48 +02:00
182631b2b7 repository cleanup 2021-08-21 14:46:00 +02:00
5cc9b16d59 repository cleanup 2021-08-21 14:45:14 +02:00
6224ed2779 repository cleanup 2021-08-21 14:42:38 +02:00
fc3a4efc5f repositoty cleanup 2021-08-21 14:41:01 +02:00
2be1e566b2 repository cleanup 2021-08-21 14:40:37 +02:00
017f691841 update readme.md 2021-08-21 12:54:41 +02:00
43c5ddcd1e Update readme.md 2021-08-21 12:53:47 +02:00
ef9f855785 repository cleanup 2021-08-21 12:50:57 +02:00
a70402ab5e repository cleanup 2021-08-21 11:12:21 +02:00
91bed82fd2 repository cleanup 2021-08-21 11:11:48 +02:00
90812f2140 Game end completed 2021-05-21 21:08:43 +02:00
0c0b677474 working on endgame 2021-05-21 10:34:34 +02:00
63bae5c504 update 2021-05-18 20:34:27 +02:00
5847c79ffb added support for text with ñ and ç 2021-04-28 21:04:01 +02:00
176d0d4f90 multi lang support 2021-04-27 22:28:00 +02:00
a0e94035db bugfixed initEnemyFormations 2021-04-22 12:10:47 +02:00
9b5eaf36e1 bughunting 2021-04-22 09:58:24 +02:00
f97291110f debuging memory leaks 2021-04-21 21:20:20 +02:00
e9ff516b1d working on class sections 2021-04-17 23:46:14 +02:00
2330820a15 "How to play" added 2021-04-05 19:07:33 +02:00
36bb6b8fe8 working on "How to play" 2021-04-05 17:56:15 +02:00
d84137daa7 Throw coffe with rotation and time stop with clock sound 2021-04-04 12:31:48 +02:00
4980c0f712 Throw coffee with rotate and clock sound on time stopped 2021-04-04 12:31:08 +02:00
b8cc628dd7 Merge pull request 'Soport per a OpenDingux' (#11) from JailDoctor/coffee_crisis_opendingux_dev:master into master
Reviewed-on: https://sustancia.synology.me:3000/JailDesigner/coffee_crisis/pulls/11
2021-04-01 11:44:42 +00:00
b663916a59 Cagades arregleited; generation script cleanup 2021-04-01 13:39:47 +02:00
6c1c6cbc42 minor type corrected 2021-04-01 13:26:16 +02:00
bcb012fc65 Basic opendingux support 2021-04-01 13:15:34 +02:00
67acc46222 updated sync.sh 2021-03-17 16:50:10 +01:00
81 changed files with 8316 additions and 6647 deletions

11
.gitignore vendored
View File

@@ -1,11 +1,12 @@
.vscode
bin
data/config.bin
data/score.bin
dll
docs
icon
media_work
releases
resources
scripts
.DS_Store
todo.txt
data/config.bin
data/score.bin
*.opk
*.DS_Store

View File

@@ -1,19 +0,0 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"macFrameworkPath": [
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks"
],
"compilerPath": "/usr/bin/clang",
"intelliSenseMode": "macos-clang-x64",
"cStandard": "c11",
"cppStandard": "c++11"
}
],
"version": 4
}

21
.vscode/launch.json vendored
View File

@@ -1,21 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "g++ - Build and debug",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/coffee_crisis_macos_debug",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/bin",
"environment": [],
"externalConsole": false,
"MIMode": "lldb",
"preLaunchTask": "C/C++: g++ build"
}
]
}

19
.vscode/settings.json vendored
View File

@@ -1,19 +0,0 @@
{
"files.associations": {
"cstddef": "cpp",
"__tuple": "cpp",
"array": "cpp",
"algorithm": "cpp",
"__bit_reference": "cpp",
"__hash_table": "cpp",
"__split_buffer": "cpp",
"initializer_list": "cpp",
"iterator": "cpp",
"string": "cpp",
"string_view": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"iosfwd": "cpp",
"stdexcept": "cpp"
}
}

31
.vscode/tasks.json vendored
View File

@@ -1,31 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "C/C++: g++ build",
"command": "/usr/bin/g++",
"args": [
"-g",
"${workspaceFolder}/source/*.cpp",
"-std=c++11",
"-Wall",
"-O2",
"-lSDL2",
"-o",
"${workspaceFolder}/bin/coffee_crisis_macos_debug"
],
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "compiler: /usr/bin/g++"
}
]
}

View File

@@ -1,6 +1,6 @@
# Coffee Crisis
Coffe Crisis es un juego arcade que pondrá a prueba tus reflejos. Realizado entre el verano de 2020 y el invierno de 2021. Intenta conseguir todos los puntos que puedas con una sola vida y ayuda a Bal1 a defender la UPV ante la invasión de la cafeína.
Coffe Crisis es un juego arcade que pondrá a prueba tus reflejos. Empezado el verano de 2020 y terminado el verano de 2021. Intenta conseguir todos los puntos que puedas con una sola vida y ayuda a Bal1 a defender la UPV ante la invasión de la cafeína durante 10 estresantes oleadas.
## Compilar
@@ -8,10 +8,10 @@ Para compilar el código se necesitan tener las librerías SDL instaladas en el
En Linux:
```bash
sudo apt install lib-SDL2 g++
sudo apt install libsdl2-dev g++
```
En macos es más facil instalarlas con [brew](https://brew.sh):
En macOS se pueden instalar fácilmente con [brew](https://brew.sh):
```bash
brew install sdl2 g++
```
@@ -23,21 +23,31 @@ En Linux:
make linux
```
En macos:
En macOS:
```bash
make macos
```
## Como ejecutar
Para ejecutar el juego hay que escribir en la terminal la orden que se muestra a continuación.
En Linux:
```bash
./bin/coffee_crisis
bin/coffee_crisis_linux
```
En macOS:
```bash
bin/coffee_crisis_macos
```
En macOS tambien puedes hacer doble click sobre el archivo coffee_crisis_macos que hay en la carpeta bin
## Agradecimientos
A los jailers y a la jail. Y entre ellos, a JailDoctor por estar siempre ahí apoyándonos/obligándonos a sacar un Jailgame más.
Y por supuesto a ti por estar aquí.
## License
Buscar una licencia para que quiera haga con el código lo que le de la gana, menos sacar beneficio económico... que si lo hacen me expliquen como.
## Licencia
Usa el código para lo que quieras: aprender, reirte, curiosear... excepto para sacar beneficio económico. Si lo consigues, por favor avísame y vamos a medias.

BIN
media/.DS_Store vendored

Binary file not shown.

BIN
media/gfx/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

BIN
media/gfx/player1_body.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
media/gfx/player1_death.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
media/gfx/player1_head.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 785 B

After

Width:  |  Height:  |  Size: 785 B

BIN
media/gfx/player2_body.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
media/gfx/player2_death.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
media/gfx/player2_head.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
media/gfx/player2_legs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 B

BIN
media/music/.DS_Store vendored

Binary file not shown.

View File

@@ -1,10 +0,0 @@
playing.ogg
ARCADE GOBLINS
https://soundimage.org/chiptunes-3/
title.ogg
ARCADE STORIES
https://soundimage.org/chiptunes-3/
intro.ogg
JailDoctor

BIN
media/sound/clock.wav Normal file

Binary file not shown.

View File

@@ -1,59 +0,0 @@
bullet.wav
Gun11.wav
http://www.themotionmonkey.co.uk/free-resources/retro-arcade-sounds/
balloon.wav
Impact3.wav
http://www.themotionmonkey.co.uk/free-resources/retro-arcade-sounds/
player_collision.wav
Impact5.wav
http://www.themotionmonkey.co.uk/free-resources/retro-arcade-sounds/
title.wav
Explosion2.wav
http://www.themotionmonkey.co.uk/free-resources/retro-arcade-sounds/
menu_select.wav
kenney_digitalaudio/powerUp2.ogg
www.kenney.nl
menu_move.wav
kenney_uiaudio/switch11.ogg
www.kenney.nl
hiscore.wav
kenney_digitalaudio/powerUp1.ogg
www.kenney.nl
itemdrop.wav
kenney_digitalaudio/PowerUp10.ogg
www.kenney.nl
itempickup.wav
kenney_digitalaudio/PowerUp7.ogg
www.kenney.nl
coffeeout.wav
kenney_digitalaudio/lowDown.ogg
www.kenney.nl
stage_change.wav
JailDoctor
menu_cancel.wav
kenney_digitalaudio/lowRandom.ogg
kenney_digitalaudio/pepSound1.ogg <-
www.kenney.nl
bubble1.wav
JailDoctor
bubble2.wav
JailDoctor
bubble3.wav
JailDoctor
bubble4.wav
JailDoctor

BIN
media/sound/powerball.wav Normal file

Binary file not shown.

BIN
source/.DS_Store vendored

Binary file not shown.

View File

@@ -1,17 +1,16 @@
#include "const.h"
#include "animatedsprite.h"
#include <iostream>
// Constructor
AnimatedSprite::AnimatedSprite()
{
init(nullptr, nullptr);
//init(nullptr, nullptr);
}
// Destructor
AnimatedSprite::~AnimatedSprite()
{
init(nullptr, nullptr);
//init(nullptr, nullptr);
}
// Iniciador
@@ -19,13 +18,13 @@ void AnimatedSprite::init(LTexture *texture, SDL_Renderer *renderer)
{
mRenderer = renderer;
mTexture = texture;
for (Uint8 i = 0; i < 20; i++)
for (int i = 0; i < 20; i++)
{
mAnimation[i].numFrames = 0;
mAnimation[i].speed = 0;
mAnimation[i].loop = true;
mAnimation[i].completed = false;
for (Uint8 j = 0; i < 20; i++)
for (int j = 0; i < 20; i++)
{
mAnimation[i].frames[j].x = 0;
mAnimation[i].frames[j].y = 0;
@@ -40,30 +39,29 @@ void AnimatedSprite::init(LTexture *texture, SDL_Renderer *renderer)
// Calcula el frame correspondiente a la animación
void AnimatedSprite::animate(int index)
{
// Calculamos el frame actual a partir del contador
mCurrentFrame = mAnimationCounter / mAnimation[index].speed;
// Si alcanzamos el final de la animación, reiniciamos el contador de la animación
// en función de la variable loop
if (mCurrentFrame >= mAnimation[index].numFrames)
if (mEnabled)
{
if (mAnimation[index].loop)
// Calculamos el frame actual a partir del contador
mCurrentFrame = mAnimationCounter / mAnimation[index].speed;
// Si alcanzamos el final de la animación, reiniciamos el contador de la animación
// en función de la variable loop
if (mCurrentFrame >= mAnimation[index].numFrames)
{
mAnimationCounter = 0;
if (mAnimation[index].loop)
mAnimationCounter = 0;
else
mCurrentFrame = mAnimation[index].numFrames;
}
// En caso contrario
else
{
mCurrentFrame = mAnimation[index].numFrames;
}
}
// En caso contrario
else
{
// Escogemos el frame correspondiente de la animación
setSpriteClip(mAnimation[index].frames[mCurrentFrame]);
// Escogemos el frame correspondiente de la animación
setSpriteClip(mAnimation[index].frames[mCurrentFrame]);
// Incrementamos el contador de la animacion
++mAnimationCounter;
// Incrementamos el contador de la animacion
mAnimationCounter++;
}
}
}

View File

@@ -12,6 +12,7 @@ Balloon::Balloon()
Balloon::~Balloon()
{
delete mSprite;
mSprite = nullptr;
}
// Inicializador
@@ -34,8 +35,10 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_SIZE_1;
mHeight = BALLOON_SIZE_1;
mWidth = BALLOON_WIDTH_1;
mHeight = BALLOON_WIDTH_1;
mSize = BALLOON_SIZE_1;
mPower = 1;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
@@ -45,19 +48,19 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mDefaultVelY = 2.6f;
// Puntos que da el globo al ser destruido
mScore = 50;
mScore = BALLOON_SCORE_1;
// Amenaza que genera el globo
mMenace = 1;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
for (int i = 0; i < NUM_FRAMES_BALLON; i++)
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 50 + OFFSET_ORANGE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 50 + OFFSET_BLUE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 50 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight());
break;
@@ -66,8 +69,10 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_SIZE_2;
mHeight = BALLOON_SIZE_2;
mWidth = BALLOON_WIDTH_2;
mHeight = BALLOON_WIDTH_2;
mSize = BALLOON_SIZE_2;
mPower = 3;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
@@ -77,19 +82,19 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mDefaultVelY = 3.5f;
// Puntos que da el globo al ser destruido
mScore = 100;
mScore = BALLOON_SCORE_2;
// Amenaza que genera el globo
mMenace = 2;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
for (int i = 0; i < NUM_FRAMES_BALLON; i++)
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_ORANGE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_BLUE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight());
break;
@@ -98,8 +103,10 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_SIZE_3;
mHeight = BALLOON_SIZE_3;
mWidth = BALLOON_WIDTH_3;
mHeight = BALLOON_WIDTH_3;
mSize = BALLOON_SIZE_3;
mPower = 7;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
@@ -109,19 +116,19 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mDefaultVelY = 4.50f;
// Puntos que da el globo al ser destruido
mScore = 200;
mScore = BALLOON_SCORE_3;
// Amenaza que genera el globo
mMenace = 4;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
for (int i = 0; i < NUM_FRAMES_BALLON; i++)
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_ORANGE_BALLOONS, 37 * i, getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_BLUE_BALLOONS, 37 * i, getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight());
break;
@@ -130,8 +137,10 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_SIZE_4;
mHeight = BALLOON_SIZE_4;
mWidth = BALLOON_WIDTH_4;
mHeight = BALLOON_WIDTH_4;
mSize = BALLOON_SIZE_4;
mPower = 15;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
@@ -141,19 +150,19 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mDefaultVelY = 4.95f;
// Puntos que da el globo al ser destruido
mScore = 400;
mScore = BALLOON_SCORE_4;
// Amenaza que genera el globo
mMenace = 8;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
for (int i = 0; i < NUM_FRAMES_BALLON; i++)
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, OFFSET_ORANGE_BALLOONS, 37 * i, getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, OFFSET_BLUE_BALLOONS, 37 * i, getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight());
break;
@@ -162,8 +171,10 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_SIZE_1;
mHeight = BALLOON_SIZE_1;
mWidth = BALLOON_WIDTH_1;
mHeight = BALLOON_WIDTH_1;
mSize = BALLOON_SIZE_1;
mPower = 1;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
@@ -173,19 +184,19 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mDefaultVelY = abs(velx) * 2;
// Puntos que da el globo al ser destruido
mScore = 50;
mScore = BALLOON_SCORE_1;
// Amenaza que genera el globo
mMenace = 1;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
for (int i = 0; i < NUM_FRAMES_BALLON; i++)
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 50 + OFFSET_GREEN_BALLOONS, 21 + (37 * i), getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 50 + OFFSET_PURPLE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 50 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight());
break;
@@ -194,8 +205,10 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_SIZE_2;
mHeight = BALLOON_SIZE_2;
mWidth = BALLOON_WIDTH_2;
mHeight = BALLOON_WIDTH_2;
mSize = BALLOON_SIZE_2;
mPower = 3;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
@@ -205,19 +218,19 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mDefaultVelY = abs(velx) * 2;
// Puntos que da el globo al ser destruido
mScore = 100;
mScore = BALLOON_SCORE_2;
// Amenaza que genera el globo
mMenace = 2;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
for (int i = 0; i < NUM_FRAMES_BALLON; i++)
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_GREEN_BALLOONS, 21 + (37 * i), getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_PURPLE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight());
break;
@@ -226,8 +239,10 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_SIZE_3;
mHeight = BALLOON_SIZE_3;
mWidth = BALLOON_WIDTH_3;
mHeight = BALLOON_WIDTH_3;
mSize = BALLOON_SIZE_3;
mPower = 7;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
@@ -237,19 +252,19 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mDefaultVelY = abs(velx) * 2;
// Puntos que da el globo al ser destruido
mScore = 200;
mScore = BALLOON_SCORE_3;
// Amenaza que genera el globo
mMenace = 4;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
for (int i = 0; i < NUM_FRAMES_BALLON; i++)
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_GREEN_BALLOONS, 37 * i, getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_PURPLE_BALLOONS, 37 * i, getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight());
break;
@@ -258,8 +273,10 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_SIZE_4;
mHeight = BALLOON_SIZE_4;
mWidth = BALLOON_WIDTH_4;
mHeight = BALLOON_WIDTH_4;
mSize = BALLOON_SIZE_4;
mPower = 15;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
@@ -269,19 +286,19 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mDefaultVelY = abs(velx) * 2;
// Puntos que da el globo al ser destruido
mScore = 400;
mScore = BALLOON_SCORE_4;
// Amenaza que genera el globo
mMenace = 8;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
for (int i = 0; i < NUM_FRAMES_BALLON; i++)
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, OFFSET_GREEN_BALLOONS, 37 * i, getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, OFFSET_PURPLE_BALLOONS, 37 * i, getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight());
break;
@@ -290,8 +307,10 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_SIZE_4;
mHeight = BALLOON_SIZE_4;
mWidth = BALLOON_WIDTH_4;
mHeight = BALLOON_WIDTH_4;
mSize = 4;
mPower = 0;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
@@ -307,15 +326,19 @@ void Balloon::init(float x, float y, Uint8 kind, float velx, float speed, Uint16
mMenace = 0;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
for (int i = 0; i < NUM_FRAMES_BALLON; i++)
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, OFFSET_POWER_BALL, 37 * i, getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, OFFSET_BLUE_BALLOONS, 37 * i, getWidth(), getHeight());
for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, OFFSET_POWER_BALL, 37 * i, getWidth(), getHeight());
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight());
// Añade rotación al sprite
mSprite->setRotate(false);
mSprite->setRotateSpeed(1);
mSprite->setRotateAmount(2.0);
break;
default:
@@ -471,6 +494,9 @@ void Balloon::move()
// Invierte sentido
mVelX = -mVelX;
// Invierte la rotación
mSprite->switchRotate();
// Activa el efecto de rebote
bounceStart();
}
@@ -539,33 +565,38 @@ void Balloon::move()
// Deshabilita el globo y pone a cero todos los valores
void Balloon::disable()
{
mEnabled = false;
mPosX = 0.0f;
mPosY = 0.0f;
mWidth = 0;
mHeight = 0;
mVelX = 0.0f;
mVelY = 0.0f;
mGravity = 0.0f;
mDefaultVelY = 0.0f;
mMaxVelY = 0.0f;
mBeingCreated = false;
mBlinking = false;
mInvulnerable = false;
mPopping = false;
mStopped = false;
mVisible = false;
mCollider.r = 0;
mCollider.x = 0;
mCollider.y = 0;
mCollider.r = 0;
mCounter = 0;
mCreationCounter = 0;
mCreationCounterIni = 0;
mDefaultVelY = 0.0f;
mEnabled = false;
mGravity = 0.0f;
mHeight = 0;
mInvulnerable = false;
mKind = 0;
mMaxVelY = 0.0f;
mMenace = 0;
mPopping = false;
mPosX = 0.0f;
mPosY = 0.0f;
mPower = 0;
mScore = 0;
mSize = 0;
mSpeed = 0;
mStopped = false;
mStoppedCounter = 0;
mTimeToLive = 0;
mKind = 0;
mMenace = 0;
mTravelY = 0;
mVelX = 0.0f;
mVelY = 0.0f;
mVisible = false;
mWidth = 0;
mSprite->clear();
}
// Explosiona el globo
@@ -585,6 +616,7 @@ void Balloon::update()
{
if (mEnabled)
{
mSprite->MovingSprite::update();
move();
updateAnimation();
updateColliders();
@@ -661,6 +693,14 @@ void Balloon::updateState()
setStop(false);
setVisible(true);
setInvulnerable(false);
if (mKind == POWER_BALL)
{
mSprite->setRotate(true);
if (mVelX > 0.0f)
mSprite->setRotateAmount(2.0);
else
mSprite->setRotateAmount(-2.0);
}
}
}
// Solo comprueba el estado detenido cuando no se está creando
@@ -741,6 +781,12 @@ int Balloon::getKind()
return mKind;
}
// Obtiene del valor de la variable
Uint8 Balloon::getSize()
{
return mSize;
}
// Obtiene la clase a la que pertenece el globo
Uint8 Balloon::getClass()
{
@@ -877,6 +923,12 @@ Uint8 Balloon::getMenace()
return 0;
}
// Obtiene le valor de la variable
Uint8 Balloon::getPower()
{
return mPower;
}
void Balloon::bounceStart()
{
mBouncing.enabled = true;

View File

@@ -39,6 +39,8 @@ private:
Uint32 mCounter; // Contador interno
float mTravelY; // Distancia que ha de recorrer el globo en el eje Y antes de que se le aplique la gravedad
float mSpeed; // Velocidad a la que se mueven los globos
Uint8 mSize; // Tamaño del globo
Uint8 mPower; // Cantidad de poder que alberga el globo
struct bouncing // Estructura para las variables para el efecto de los rebotes
{
@@ -121,6 +123,9 @@ public:
// Obtiene del valor de la variable
int getKind();
// Obtiene del valor de la variable
Uint8 getSize();
// Obtiene la clase a la que pertenece el globo
Uint8 getClass();
@@ -171,6 +176,9 @@ public:
// Obtiene le valor de la variable
Uint8 getMenace();
// Obtiene le valor de la variable
Uint8 getPower();
};
#endif

View File

@@ -5,18 +5,19 @@
Bullet::Bullet()
{
mSprite = new Sprite();
init(0, 0, NO_KIND, nullptr, nullptr);
mKind = NO_KIND;
}
// Destructor
Bullet::~Bullet()
{
init(0, 0, NO_KIND, nullptr, nullptr);
//init(0, 0, NO_KIND, nullptr, nullptr);
delete mSprite;
mSprite = nullptr;
}
// Iniciador
void Bullet::init(int x, int y, int kind, LTexture *texture, SDL_Renderer *renderer)
void Bullet::init(int x, int y, int kind, bool poweredUp, int owner, LTexture *texture, SDL_Renderer *renderer)
{
// Posición inicial del objeto
mPosX = x;
@@ -32,6 +33,9 @@ void Bullet::init(int x, int y, int kind, LTexture *texture, SDL_Renderer *rende
// Tipo de bala
mKind = kind;
// Identificador del dueño del objeto
mOwner = owner;
// Textura con los gráficos del objeto
mSprite->setTexture(texture);
@@ -54,7 +58,10 @@ void Bullet::init(int x, int y, int kind, LTexture *texture, SDL_Renderer *rende
mVelX = 0;
// Rectangulo con los gráficos del objeto
mSprite->setSpriteClip(0 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
if (!poweredUp)
mSprite->setSpriteClip(0 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
else
mSprite->setSpriteClip((0 + 3) * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
break;
case BULLET_LEFT:
@@ -62,7 +69,10 @@ void Bullet::init(int x, int y, int kind, LTexture *texture, SDL_Renderer *rende
mVelX = -2;
// Rectangulo con los gráficos del objeto
mSprite->setSpriteClip(1 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
if (!poweredUp)
mSprite->setSpriteClip(1 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
else
mSprite->setSpriteClip((1 + 3) * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
break;
case BULLET_RIGHT:
@@ -70,7 +80,10 @@ void Bullet::init(int x, int y, int kind, LTexture *texture, SDL_Renderer *rende
mVelX = 2;
// Rectangulo con los gráficos del objeto
mSprite->setSpriteClip(2 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
if (!poweredUp)
mSprite->setSpriteClip(2 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
else
mSprite->setSpriteClip((2 + 3) * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
break;
default:
@@ -147,7 +160,7 @@ void Bullet::testMove()
// Deshabilita el objeto
void Bullet::erase()
{
init(0, 0, 0, nullptr, nullptr);
init(0, 0, 0, false, -1, nullptr, nullptr);
}
// Comprueba si el objeto está activo
@@ -199,6 +212,12 @@ int Bullet::getKind()
return mKind;
}
// Obtiene el valor de la variable
int Bullet::getOwner()
{
return mOwner;
}
// Obtiene el circulo de colisión
circle_t &Bullet::getCollider()
{

View File

@@ -8,6 +8,21 @@
// Clase bala
class Bullet
{
private:
int mPosX; // Posición en el eje X
int mPosY; // Posición en el eje Y
Uint8 mWidth; // Ancho del objeto
Uint8 mHeight; // Alto del objeto
int mVelX; // Velocidad en el eje X
int mVelY; // Velocidad en el eje Y
int mKind; // Tipo de objeto
int mOwner; // Identificador del dueño del objeto
Sprite *mSprite; // Sprite con los graficos y métodos de pintado
circle_t mCollider; // Circulo de colisión del objeto
// Alinea el circulo de colisión con el objeto
void shiftColliders();
public:
// Constructor
Bullet();
@@ -16,11 +31,11 @@ public:
~Bullet();
// Iniciador
void init(int x, int y, int kind, LTexture* texture, SDL_Renderer *renderer);
void init(int x, int y, int kind, bool poweredUp, int owner, LTexture *texture, SDL_Renderer *renderer);
// Pinta el objeto en pantalla
void render();
// Actualiza la posición y estado del objeto
Uint8 move();
@@ -48,33 +63,11 @@ public:
// Obtiene el valor de la variable
int getKind();
// Obtiene el valor de la variable
int getOwner();
// Obtiene el circulo de colisión
circle_t &getCollider();
private:
// Posición X/Y del objeto
int mPosX;
int mPosY;
// Alto y ancho el objeto
Uint8 mWidth;
Uint8 mHeight;
// Velocidad del objeto
int mVelX;
int mVelY;
// Tipo de objeto
int mKind;
// Sprite con los graficos y métodos de pintado
Sprite *mSprite;
// Balloon's collision circle
circle_t mCollider;
// Alinea el circulo de colisión con el objeto
void shiftColliders();
};
#endif

View File

@@ -1,5 +1,7 @@
#pragma once
#include "ifdefs.h"
#include "utils.h"
#include "lang.h"
#include <string>
#ifndef CONST_H
@@ -7,7 +9,7 @@
// Textos
#define WINDOW_CAPTION "Coffee Crisis"
#define TEXT_COPYRIGHT "@2020,2021 JAILDESIGNER (V1.4)"
#define TEXT_COPYRIGHT "@2020,2021 JAILDESIGNER (V1.5)"
// Recursos
#define BINFILE_SCORE 0
@@ -38,8 +40,10 @@
#define SOUND_PLAYER_COLLISION 13
#define SOUND_STAGE_CHANGE 14
#define SOUND_TITLE 15
#define SOUND_CLOCK 16
#define SOUND_POWERBALL 17
#define TOTAL_SOUND 16
#define TOTAL_SOUND 18
#define TEXTURE_BALLOON 0
#define TEXTURE_BULLET 1
@@ -130,25 +134,37 @@ const int SCREEN_THIRD_QUARTER_Y = (SCREEN_HEIGHT / 4) * 3;
#define PLAYER_ANIMATION_BODY_WALKING_STOP 4
#define PLAYER_ANIMATION_BODY_FIRING_UP 5
#define PLAYER_ANIMATION_HEAD_WALKING_LEFT 0
#define PLAYER_ANIMATION_HEAD_FIRING_LEFT 1
#define PLAYER_ANIMATION_HEAD_WALKING_RIGHT 2
#define PLAYER_ANIMATION_HEAD_FIRING_RIGHT 3
#define PLAYER_ANIMATION_HEAD_WALKING_STOP 4
#define PLAYER_ANIMATION_HEAD_FIRING_UP 5
// Variables del jugador
#define PLAYER_INVULNERABLE_COUNTER 200
#define PLAYER_POWERUP_COUNTER 2500
// Secciones del programa
#define PROG_SECTION_LOGO 0
#define PROG_SECTION_INTRO 1
#define PROG_SECTION_TITLE 2
#define PROG_SECTION_GAME 3
#define PROG_SECTION_QUIT 4
// Secciones del juego
#define GAME_SECTION_PLAY 0
#define GAME_SECTION_PAUSE 1
#define GAME_SECTION_GAMEOVER 2
// Subsecciones
#define GAME_SECTION_PLAY_1P 0
#define GAME_SECTION_PLAY_2P 1
#define GAME_SECTION_PAUSE 2
#define GAME_SECTION_GAMEOVER 3
#define TITLE_SECTION_1 3
#define TITLE_SECTION_2 4
#define TITLE_SECTION_3 5
#define TITLE_SECTION_INSTRUCTIONS 6
// Secciones del titulo
#define TITLE_SECTION_1 0
#define TITLE_SECTION_2 1
#define TITLE_SECTION_3 2
#define TITLE_SECTION_INSTRUCTIONS 3
// Modo para las instrucciones
#define INSTRUCTIONS_MODE_MANUAL 0
#define INSTRUCTIONS_MODE_AUTO 1
// Estados de cada elemento que pertenece a un evento
#define EVENT_WAITING 1
@@ -210,6 +226,18 @@ const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
#define HEXAGON_4 8
#define POWER_BALL 9
// Puntos de globo
#define BALLOON_SCORE_1 50
#define BALLOON_SCORE_2 100
#define BALLOON_SCORE_3 200
#define BALLOON_SCORE_4 400
// Tamaños de globo
#define BALLOON_SIZE_1 1
#define BALLOON_SIZE_2 2
#define BALLOON_SIZE_3 3
#define BALLOON_SIZE_4 4
// Clases de globo
#define BALLOON_CLASS 0
#define HEXAGON_CLASS 1
@@ -234,10 +262,13 @@ const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
#define BALLOON_SPEED_5 1.00f
// Tamaño de los globos
#define BALLOON_SIZE_1 8
#define BALLOON_SIZE_2 13
#define BALLOON_SIZE_3 21
#define BALLOON_SIZE_4 37
#define BALLOON_WIDTH_1 8
#define BALLOON_WIDTH_2 13
#define BALLOON_WIDTH_3 21
#define BALLOON_WIDTH_4 37
// PowerBall
#define POWERBALL_SCREENPOWER_MINIMUM 10
// Tipos de bala
#define BULLET_UP 1
@@ -252,9 +283,18 @@ const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
#define ITEM_POINTS_2_GAVINA 2
#define ITEM_POINTS_3_PACMAR 3
#define ITEM_CLOCK 4
#define ITEM_TNT 5
#define ITEM_COFFEE 6
#define ITEM_POWER_BALL 7
#define ITEM_COFFEE 5
#define ITEM_POWER_BALL 6
#define ITEM_COFFEE_MACHINE 7
// Porcentaje de aparición de los objetos
#define ITEM_POINTS_1_DISK_ODDS 10
#define ITEM_POINTS_2_GAVINA_ODDS 6
#define ITEM_POINTS_3_PACMAR_ODDS 3
#define ITEM_CLOCK_ODDS 5
#define ITEM_COFFEE_ODDS 5
#define ITEM_POWER_BALL_ODDS 0
#define ITEM_COFFEE_MACHINE_ODDS 4
// Cantidad de objetos simultaneos
#define MAX_ITEMS 5
@@ -266,14 +306,8 @@ const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
// Estados de entrada
#define NO_INPUT 0
#define INPUT_UP 1
#define INPUT_DOWN 2
#define INPUT_LEFT 3
#define INPUT_RIGHT 4
#define INPUT_ACCEPT 5
#define INPUT_CANCEL 6
#define INPUT_FIRE_UP 7
#define INPUT_FIRE_LEFT 8
#define INPUT_FIRE_LEFT 7
#define INPUT_FIRE_UP 8
#define INPUT_FIRE_RIGHT 9
#define INPUT_PAUSE 10
@@ -300,5 +334,16 @@ const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
#define INSTRUCTIONS_COUNTER 600
#define DEATH_COUNTER 350
#define SHAKE_COUNTER 10
#define HELP_COUNTER 1000
// Colores
const color_t bgColor = {0x27, 0x27, 0x36};
const color_t noColor = {0xFF, 0xFF, 0xFF};
const color_t shdwTxtColor = {0x43, 0x43, 0x4F};
// Formaciones enemigas
#define NUMBER_OF_ENEMY_FORMATIONS 100
#define MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION 50
#endif

494
source/director.cpp Normal file
View File

@@ -0,0 +1,494 @@
#include "const.h"
#include "utils.h"
#include "director.h"
#include <iostream>
#ifdef __MIPSEL__
#include <sys/stat.h>
#include <dirent.h>
#endif
// Constructor
Director::Director(std::string path)
{
// Crea los objetos
mInput1 = new Input(USE_KEYBOARD);
mInput2 = new Input(USE_GAMECONTROLLER);
mOptions = new options_t;
// Inicializa variables
setExecutablePath(path);
setFileList();
checkFileList();
// Inicializa SDL
initSDL();
// Inicializa JailAudio
initJailAudio();
#ifdef __MIPSEL__
DIR *dir = opendir("/media/data/local/home/.coffee_crisis");
if (dir)
{
closedir(dir);
}
else if (ENOENT == errno)
{
int status = mkdir("/media/data/local/home/.coffee_crisis", 755);
}
#endif
// Inicializa el resto de variables
init();
}
Director::~Director()
{
saveConfigFile();
delete mInput1;
mInput1 = nullptr;
delete mInput2;
mInput2 = nullptr;
delete mOptions;
mOptions = nullptr;
SDL_DestroyRenderer(mRenderer);
SDL_DestroyWindow(mWindow);
mRenderer = nullptr;
mWindow = nullptr;
SDL_Quit();
}
// Inicia las variables necesarias para arrancar el programa
void Director::init()
{
// Carga el fichero de configuración
if (!loadConfigFile())
{
mOptions->fullScreenMode = 0;
mOptions->windowSize = 3;
mOptions->language = en_UK;
}
// Sección
mSection.name = PROG_SECTION_LOGO;
mSection.subsection = 0;
// Textos
initTextStrings(mTextStrings, mOptions->language);
// Teclado
mInput1->bindKey(INPUT_UP, SDL_SCANCODE_UP);
mInput1->bindKey(INPUT_DOWN, SDL_SCANCODE_DOWN);
mInput1->bindKey(INPUT_LEFT, SDL_SCANCODE_LEFT);
mInput1->bindKey(INPUT_RIGHT, SDL_SCANCODE_RIGHT);
mInput1->bindKey(INPUT_ACCEPT, SDL_SCANCODE_RETURN);
mInput1->bindKey(INPUT_CANCEL, SDL_SCANCODE_ESCAPE);
#ifdef __MIPSEL__
mInput1->bindKey(INPUT_BUTTON_1, SDL_SCANCODE_LSHIFT);
mInput1->bindKey(INPUT_BUTTON_2, SDL_SCANCODE_SPACE);
mInput1->bindKey(INPUT_BUTTON_3, SDL_SCANCODE_LCTRL);
#else
mInput1->bindKey(INPUT_BUTTON_1, SDL_SCANCODE_Q);
mInput1->bindKey(INPUT_BUTTON_2, SDL_SCANCODE_W);
mInput1->bindKey(INPUT_BUTTON_3, SDL_SCANCODE_E);
#endif
mInput1->bindKey(INPUT_BUTTON_PAUSE, SDL_SCANCODE_ESCAPE); // PAUSE
mInput1->bindKey(INPUT_BUTTON_ESCAPE, SDL_SCANCODE_ESCAPE); // ESCAPE
mInput2->bindGameController(INPUT_UP, SDL_CONTROLLER_BUTTON_DPAD_UP);
mInput2->bindGameController(INPUT_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
mInput2->bindGameController(INPUT_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
mInput2->bindGameController(INPUT_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
mInput2->bindGameController(INPUT_ACCEPT, SDL_CONTROLLER_BUTTON_A);
mInput2->bindGameController(INPUT_CANCEL, SDL_CONTROLLER_BUTTON_B);
mInput2->bindGameController(INPUT_BUTTON_1, SDL_CONTROLLER_BUTTON_X);
mInput2->bindGameController(INPUT_BUTTON_2, SDL_CONTROLLER_BUTTON_Y);
mInput2->bindGameController(INPUT_BUTTON_3, SDL_CONTROLLER_BUTTON_B);
mInput2->bindGameController(INPUT_BUTTON_PAUSE, SDL_CONTROLLER_BUTTON_GUIDE); // PAUSE
mInput2->bindGameController(INPUT_BUTTON_ESCAPE, SDL_CONTROLLER_BUTTON_GUIDE); // ESCAPE
}
// Inicializa JailAudio
void Director::initJailAudio()
{
JA_Init(48000, AUDIO_S16, 2);
}
// Arranca SDL y crea la ventana
bool Director::initSDL()
{
// Indicador de inicialización
bool success = true;
// Inicializa SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO | SDL_INIT_HAPTIC) < 0)
//if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
printf("SDL could not initialize!\nSDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
// Establece el filtro de la textura a nearest
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"))
{
printf("Warning: Nearest texture filtering not enabled!\n");
}
// Crea la ventana
mWindow = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, VIEW_WIDTH, VIEW_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
if (mWindow == NULL)
{
printf("Window could not be created!\nSDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
// Crea un renderizador para la ventana con vsync
mRenderer = SDL_CreateRenderer(mWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (mRenderer == NULL)
{
printf("Renderer could not be created!\nSDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
// Inicializa el color de renderizado
SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF);
// Establece el tamaño del buffer de renderizado
SDL_RenderSetLogicalSize(mRenderer, SCREEN_WIDTH, SCREEN_HEIGHT);
// Establece el modo de mezcla
SDL_SetRenderDrawBlendMode(mRenderer, SDL_BLENDMODE_BLEND);
}
}
}
printf("\n");
return success;
}
// Crea el indice de ficheros
void Director::setFileList()
{
// Ficheros binarios
#ifdef __MIPSEL__
mFileList[0] = "/media/data/local/home/.coffee_crisis/score.bin";
mFileList[1] = "/media/data/local/home/.coffee_crisis/demo.bin";
mFileList[2] = "/media/data/local/home/.coffee_crisis/config.bin";
#else
mFileList[0] = mExecutablePath + "/" + "../data/score.bin";
mFileList[1] = mExecutablePath + "/" + "../data/demo.bin";
mFileList[2] = mExecutablePath + "/" + "../data/config.bin";
#endif
// Musicas
mFileList[3] = mExecutablePath + "/" + "../media/music/intro.ogg";
mFileList[4] = mExecutablePath + "/" + "../media/music/playing.ogg";
mFileList[5] = mExecutablePath + "/" + "../media/music/title.ogg";
// Sonidos
mFileList[6] = mExecutablePath + "/" + "../media/sound/balloon.wav";
mFileList[7] = mExecutablePath + "/" + "../media/sound/bubble1.wav";
mFileList[8] = mExecutablePath + "/" + "../media/sound/bubble2.wav";
mFileList[9] = mExecutablePath + "/" + "../media/sound/bubble3.wav";
mFileList[10] = mExecutablePath + "/" + "../media/sound/bubble4.wav";
mFileList[11] = mExecutablePath + "/" + "../media/sound/bullet.wav";
mFileList[12] = mExecutablePath + "/" + "../media/sound/coffeeout.wav";
mFileList[13] = mExecutablePath + "/" + "../media/sound/hiscore.wav";
mFileList[14] = mExecutablePath + "/" + "../media/sound/itemdrop.wav";
mFileList[15] = mExecutablePath + "/" + "../media/sound/itempickup.wav";
mFileList[16] = mExecutablePath + "/" + "../media/sound/menu_cancel.wav";
mFileList[17] = mExecutablePath + "/" + "../media/sound/menu_move.wav";
mFileList[18] = mExecutablePath + "/" + "../media/sound/menu_select.wav";
mFileList[19] = mExecutablePath + "/" + "../media/sound/player_collision.wav";
mFileList[20] = mExecutablePath + "/" + "../media/sound/stage_change.wav";
mFileList[21] = mExecutablePath + "/" + "../media/sound/title.wav";
mFileList[22] = mExecutablePath + "/" + "../media/sound/clock.wav";
mFileList[23] = mExecutablePath + "/" + "../media/sound/powerball.wav";
// Texturas
mFileList[24] = mExecutablePath + "/" + "../media/gfx/balloon.png";
mFileList[25] = mExecutablePath + "/" + "../media/gfx/bullet.png";
mFileList[26] = mExecutablePath + "/" + "../media/gfx/font_black_x2.png";
mFileList[27] = mExecutablePath + "/" + "../media/gfx/font_black.png";
mFileList[28] = mExecutablePath + "/" + "../media/gfx/font_nokia.png";
mFileList[29] = mExecutablePath + "/" + "../media/gfx/font_white_x2.png";
mFileList[30] = mExecutablePath + "/" + "../media/gfx/font_white.png";
mFileList[31] = mExecutablePath + "/" + "../media/gfx/game_bg.png";
mFileList[32] = mExecutablePath + "/" + "../media/gfx/game_text.png";
mFileList[33] = mExecutablePath + "/" + "../media/gfx/intro.png";
mFileList[34] = mExecutablePath + "/" + "../media/gfx/items.png";
mFileList[35] = mExecutablePath + "/" + "../media/gfx/logo.png";
mFileList[36] = mExecutablePath + "/" + "../media/gfx/menu.png";
mFileList[37] = mExecutablePath + "/" + "../media/gfx/player1_body.png";
mFileList[38] = mExecutablePath + "/" + "../media/gfx/player1_death.png";
mFileList[39] = mExecutablePath + "/" + "../media/gfx/player1_legs.png";
mFileList[40] = mExecutablePath + "/" + "../media/gfx/title.png";
mFileList[41] = mExecutablePath + "/" + "../media/gfx/player1_head.png";
mFileList[42] = mExecutablePath + "/" + "../media/gfx/player2_body.png";
mFileList[43] = mExecutablePath + "/" + "../media/gfx/player2_death.png";
mFileList[44] = mExecutablePath + "/" + "../media/gfx/player2_legs.png";
mFileList[45] = mExecutablePath + "/" + "../media/gfx/player2_head.png";
}
// Comprueba que todos los ficheros existen
bool Director::checkFileList()
{
bool success = true;
/*std::string p;
std::string filename;
SDL_RWops *file;
// Comprueba los ficheros de musica
printf("\n>> MUSIC FILES\n");
if (success)
for (int i = 0; i < TOTAL_MUSIC; i++)
{
p = mMusic[i].file.c_str();
filename = p.substr(p.find_last_of("\\/") + 1);
file = SDL_RWFromFile(p.c_str(), "r+b");
if (file != NULL)
{
printf("Checking file %-20s [OK]\n", filename.c_str());
}
else
{
printf("Checking file %-20s [ERROR]\n", filename.c_str());
success = false;
break;
}
SDL_RWclose(file);
}
// Comprueba los ficheros de sonidos
printf("\n>> SOUND FILES\n");
if (success)
for (int i = 0; i < TOTAL_SOUND; i++)
{
p = mSound[i].file.c_str();
filename = p.substr(p.find_last_of("\\/") + 1);
file = SDL_RWFromFile(p.c_str(), "r+b");
if (file != NULL)
{
printf("Checking file %-20s [OK]\n", filename.c_str());
}
else
{
printf("Checking file %-20s [ERROR]\n", filename.c_str());
success = false;
break;
}
SDL_RWclose(file);
}
// Comprueba los ficheros con texturas
printf("\n>> TEXTURE FILES\n");
if (success)
for (int i = 0; i < TOTAL_TEXTURE; i++)
{
p = mTexture[i].file.c_str();
filename = p.substr(p.find_last_of("\\/") + 1);
file = SDL_RWFromFile(p.c_str(), "r+b");
if (file != NULL)
{
printf("Checking file %-20s [OK]\n", filename.c_str());
}
else
{
printf("Checking file %-20s [ERROR]\n", filename.c_str());
success = false;
break;
}
SDL_RWclose(file);
}
// Resultado
if (success)
printf("\n** All files OK.\n\n");
else
printf("\n** A file is missing. Exiting.\n\n");
*/
return success;
}
// Carga el fichero de configuración
bool Director::loadConfigFile()
{
// Pone unos valores por defecto
mOptions->fullScreenMode = 0;
mOptions->windowSize = 3;
mOptions->language = en_UK;
// Indicador de éxito en la carga
bool success = true;
const std::string p = mFileList[2];
std::string filename = p.substr(p.find_last_of("\\/") + 1);
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b");
// El fichero no existe
if (file == NULL)
{
printf("Warning: Unable to open %s file\n", filename.c_str());
// Crea el fichero para escritura
file = SDL_RWFromFile(p.c_str(), "w+b");
if (file != NULL)
{
printf("New file (%s) created!\n", filename.c_str());
// Escribe los datos
SDL_RWwrite(file, &mOptions->fullScreenMode, sizeof(mOptions->fullScreenMode), 1);
SDL_RWwrite(file, &mOptions->windowSize, sizeof(mOptions->windowSize), 1);
SDL_RWwrite(file, &mOptions->language, sizeof(mOptions->language), 1);
// Cierra el fichero
SDL_RWclose(file);
}
else
{
printf("Error: Unable to create file %s\n", filename.c_str());
success = false;
}
}
// El fichero existe
else
{
// Carga los datos
printf("Reading file %s\n", filename.c_str());
SDL_RWread(file, &mOptions->fullScreenMode, sizeof(mOptions->fullScreenMode), 1);
SDL_RWread(file, &mOptions->windowSize, sizeof(mOptions->windowSize), 1);
SDL_RWread(file, &mOptions->language, sizeof(mOptions->language), 1);
// Normaliza los valores
if (!((mOptions->fullScreenMode == 0) ||
(mOptions->fullScreenMode == SDL_WINDOW_FULLSCREEN) ||
(mOptions->fullScreenMode == SDL_WINDOW_FULLSCREEN_DESKTOP)))
mOptions->fullScreenMode = 0;
if ((mOptions->windowSize < 1) || (mOptions->windowSize > 4))
mOptions->windowSize = 3;
if ((mOptions->language < 0) || (mOptions->language > MAX_LANGUAGES))
mOptions->language = en_UK;
// Aplica las opciones
SDL_SetWindowFullscreen(mWindow, mOptions->fullScreenMode);
SDL_SetWindowSize(mWindow, SCREEN_WIDTH * mOptions->windowSize, SCREEN_HEIGHT * mOptions->windowSize);
initTextStrings(mTextStrings, mOptions->language);
// Cierra el fichero
SDL_RWclose(file);
}
return success;
}
// Guarda el fichero de configuración
bool Director::saveConfigFile()
{
bool success = true;
const std::string p = mFileList[2];
std::string filename = p.substr(p.find_last_of("\\/") + 1);
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "w+b");
if (file != NULL)
{
// Guarda los datos
SDL_RWwrite(file, &mOptions->fullScreenMode, sizeof(Uint32), 1);
SDL_RWwrite(file, &mOptions->windowSize, sizeof(Uint8), 1);
SDL_RWwrite(file, &mOptions->language, sizeof(Uint8), 1);
printf("Writing file %s\n", filename.c_str());
// Cierra el fichero
SDL_RWclose(file);
}
else
{
printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError());
}
return success;
}
// Establece el valor de la variable
void Director::setExecutablePath(std::string path)
{
mExecutablePath = path.substr(0, path.find_last_of("\\/"));
}
// Obtiene el valor de la variable
Uint8 Director::getSubsection()
{
return mSection.subsection;
}
// Obtiene el valor de la variable
Uint8 Director::getSection()
{
return mSection.name;
}
// Establece el valor de la variable
void Director::setSection(section_t section)
{
mSection = section;
}
void Director::runLogo()
{
mLogo = new Logo(mRenderer, mFileList);
setSection(mLogo->run());
delete mLogo;
}
void Director::runIntro()
{
mIntro = new Intro(mRenderer, mFileList, mTextStrings);
setSection(mIntro->run());
delete mIntro;
}
void Director::runTitle()
{
mTitle = new Title(mWindow, mRenderer, mInput1, mFileList, mOptions, mTextStrings);
setSection(mTitle->run(mSection.subsection));
delete mTitle;
}
void Director::runGame()
{
if (mSection.subsection == GAME_SECTION_PLAY_1P)
mGame = new Game(1, mRenderer, mFileList, mTextStrings, mInput1, mInput2, false);
if (mSection.subsection == GAME_SECTION_PLAY_2P)
mGame = new Game(2, mRenderer, mFileList, mTextStrings, mInput1, mInput2, false);
setSection(mGame->run());
delete mGame;
}
void Director::run()
{
// Bucle principal
while (!(getSection() == PROG_SECTION_QUIT))
{
switch (getSection())
{
case PROG_SECTION_LOGO:
runLogo();
break;
case PROG_SECTION_INTRO:
runIntro();
break;
case PROG_SECTION_TITLE:
runTitle();
break;
case PROG_SECTION_GAME:
runGame();
break;
}
}
}

105
source/director.h Normal file
View File

@@ -0,0 +1,105 @@
#pragma once
#include "ifdefs.h"
#include "sprite.h"
#include "movingsprite.h"
#include "smartsprite.h"
#include "player.h"
#include "balloon.h"
#include "bullet.h"
#include "coffeedrop.h"
#include "item.h"
#include "text.h"
#include "text2.h"
#include "menu.h"
#include "const.h"
#include "jail_audio.h"
#include "utils.h"
#include "logo.h"
#include "intro.h"
#include "title.h"
#include "game.h"
#include "input.h"
#include "fade.h"
#include <math.h>
#ifndef DIRECTOR_H
#define DIRECTOR_H
// Director
class Director
{
private:
SDL_Window *mWindow; // La ventana donde dibujamos
SDL_Renderer *mRenderer; // El renderizador de la ventana
Input *mInput1; // Objeto Input para gestionar las entradas
Input *mInput2; // Objeto Input para gestionar las entradas
Logo *mLogo; // Objeto para la sección del logo
Intro *mIntro; // Objeto para la sección de la intro
Title *mTitle; // Objeto para la sección del titulo y el menu de opciones
Game *mGame; // Objeto para la sección del juego
std::string mFileList[100]; // Vector con las rutas a los ficheros de recursos
struct options_t *mOptions; // Variable con todas las opciones del programa
std::string mTextStrings[MAX_TEXT_STRINGS]; // Vector con los textos del juego
std::string mExecutablePath; // Path del ejecutable
section_t mSection; // Sección y subsección actual del programa;
// Inicializa jail_audio
void initJailAudio();
// Inicializa los textos del juego en el idioma seleccionado
//void initTextStrings(Uint8 lang);
// Arranca SDL y crea la ventana
bool initSDL();
// Crea el indice de ficheros
void setFileList();
// Comprueba que todos los ficheros existen
bool checkFileList();
// Carga el fichero de configuración
bool loadConfigFile();
// Guarda el fichero de configuración
bool saveConfigFile();
// Establece el valor de la variable
void setExecutablePath(std::string path);
// Obtiene el valor de la variable
Uint8 getSubsection();
// Obtiene el valor de la variable
Uint8 getSection();
// Establece el valor de la variable
void setSection(section_t section);
void runLogo();
void runIntro();
void runTitle();
void runGame();
public:
// Constructor
Director(std::string path);
// Destructor
~Director();
// Inicia las variables necesarias para arrancar el programa
void init();
// Bucle principal
void run();
};
#endif

171
source/fade.cpp Normal file
View File

@@ -0,0 +1,171 @@
#include "fade.h"
#include "const.h"
// Constructor
Fade::Fade(SDL_Renderer *renderer)
{
mRenderer = renderer;
mBackbuffer = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT);
if (mBackbuffer == NULL)
printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError());
init();
}
// Destructor
Fade::~Fade()
{
SDL_DestroyTexture(mBackbuffer);
mBackbuffer = nullptr;
}
// Inicializa las variables
void Fade::init()
{
mFadeType = FADE_CENTER;
mEnabled = false;
mFinished = false;
mCounter = 0;
mR = 0x27;
mG = 0x27;
mB = 0x36;
}
// Pinta una transición en pantalla
void Fade::render()
{
if (mEnabled && !mFinished)
{
switch (mFadeType)
{
case FADE_FULLSCREEN:
mRect1 = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
for (int i = 0; i < 256; i += 4)
{
// Dibujamos sobre el renderizador
SDL_SetRenderTarget(mRenderer, NULL);
// Copia el backbuffer con la imagen que había al renderizador
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, i);
SDL_RenderFillRect(mRenderer, &mRect1);
// Vuelca el renderizador en pantalla
SDL_RenderPresent(mRenderer);
}
// Deja todos los buffers del mismo color
SDL_SetRenderTarget(mRenderer, mBackbuffer);
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 255);
SDL_RenderClear(mRenderer);
SDL_SetRenderTarget(mRenderer, NULL);
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 255);
SDL_RenderClear(mRenderer);
break;
case FADE_CENTER:
mRect1 = {0, 0, SCREEN_WIDTH, 0};
mRect2 = {0, 0, SCREEN_WIDTH, 0};
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 64);
for (int i = 0; i < mCounter; i++)
{
mRect1.h = mRect2.h = i * 4;
mRect2.y = SCREEN_HEIGHT - (i * 4);
SDL_RenderFillRect(mRenderer, &mRect1);
SDL_RenderFillRect(mRenderer, &mRect2);
}
if ((mCounter * 4) > SCREEN_HEIGHT)
mFinished = true;
break;
case FADE_RANDOM_SQUARE:
mRect1 = {0, 0, 32, 32};
for (Uint16 i = 0; i < 50; i++)
{
// Crea un color al azar
mR = 255 * (rand() % 2);
mG = 255 * (rand() % 2);
mB = 255 * (rand() % 2);
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 64);
// Dibujamos sobre el backbuffer
SDL_SetRenderTarget(mRenderer, mBackbuffer);
mRect1.x = rand() % (SCREEN_WIDTH - mRect1.w);
mRect1.y = rand() % (SCREEN_HEIGHT - mRect1.h);
SDL_RenderFillRect(mRenderer, &mRect1);
// Volvemos a usar el renderizador de forma normal
SDL_SetRenderTarget(mRenderer, NULL);
// Copiamos el backbuffer al renderizador
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
// Volcamos el renderizador en pantalla
SDL_RenderPresent(mRenderer);
SDL_Delay(100);
}
break;
default:
break;
}
}
if (mFinished)
{
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 255);
SDL_RenderClear(mRenderer);
}
}
// Actualiza las variables internas
void Fade::update()
{
if (mEnabled)
mCounter++;
}
// Activa el fade
void Fade::activateFade()
{
mEnabled = true;
mFinished = false;
mCounter = 0;
}
// Comprueba si está activo
bool Fade::isEnabled()
{
return mEnabled;
}
// Comprueba si ha terminado la transicion
bool Fade::hasEnded()
{
if (mFinished)
{
//mEnabled = false;
//mFinished = false;
return true;
}
else
{
return false;
}
}
// Establece el tipo de fade
void Fade::setFadeType(Uint8 fadeType)
{
mFadeType = fadeType;
}

55
source/fade.h Normal file
View File

@@ -0,0 +1,55 @@
#pragma once
#include "ifdefs.h"
#include "ltexture.h"
#ifndef FADE_H
#define FADE_H
#define FADE_FULLSCREEN 0
#define FADE_CENTER 1
#define FADE_RANDOM_SQUARE 2
// Fade
class Fade
{
private:
SDL_Renderer *mRenderer; // El renderizador de la ventana
SDL_Texture *mBackbuffer; // Textura para usar como backbuffer
Uint8 mFadeType; // Tipo de fade a realizar
Uint16 mCounter; // Contador interno
bool mEnabled; // Indica si el fade está activo
bool mFinished; // Indica si ha terminado la transición
Uint8 mR, mG, mB; // Colores para el fade
SDL_Rect mRect1; // Rectangulo usado para crear los efectos de transición
SDL_Rect mRect2; // Rectangulo usado para crear los efectos de transición
public:
// Constructor
Fade(SDL_Renderer *renderer);
// Destructor
~Fade();
// Inicializa las variables
void init();
// Pinta una transición en pantalla
void render();
// Actualiza las variables internas
void update();
// Activa el fade
void activateFade();
// Comprueba si ha terminado la transicion
bool hasEnded();
// Comprueba si está activo
bool isEnabled();
// Establece el tipo de fade
void setFadeType(Uint8 fadeType);
};
#endif

3354
source/game.cpp Normal file

File diff suppressed because it is too large Load Diff

501
source/game.h Normal file
View File

@@ -0,0 +1,501 @@
#pragma once
#include "ifdefs.h"
#include "const.h"
#include "utils.h"
#include "sprite.h"
#include "movingsprite.h"
#include "smartsprite.h"
#include "player.h"
#include "balloon.h"
#include "bullet.h"
#include "item.h"
#include "text.h"
#include "text2.h"
#include "menu.h"
#include "input.h"
#include "fade.h"
#include "jail_audio.h"
#ifndef GAME_H
#define GAME_H
// Game
class Game
{
private:
struct enemyInits_t
{
int x; // Posición en el eje X donde crear al enemigo
int y; // Posición en el eje Y donde crear al enemigo
float velX; // Velocidad inicial en el eje X
Uint8 kind; // Tipo de enemigo
Uint16 creationCounter; // Temporizador para la creación del enemigo
};
struct enemyFormation_t // Contiene la información de una formación enemiga
{
Uint8 numberOfEnemies; // Cantidad de enemigos que forman la formación
enemyInits_t init[MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION]; // Vector con todas las inicializaciones de los enemigos de la formación
};
enemyFormation_t mEnemyFormation[NUMBER_OF_ENEMY_FORMATIONS]; // Vector con todas las formaciones enemigas
struct enemyPool_t
{
enemyFormation_t *set[10]; // Conjunto de formaciones enemigas
};
enemyPool_t mEnemyPool[10]; // Variable con los diferentes conjuntos de formaciones enemigas
struct stage_t // Contiene todas las variables relacionadas con una fase
{
enemyPool_t *enemyPool; // El conjunto de formaciones enemigas de la fase
Uint16 currentPower; // Cantidad actual de poder
Uint16 powerToComplete; // Cantidad de poder que se necesita para completar la fase
Uint8 maxMenace; // Umbral máximo de amenaza de la fase
Uint8 minMenace; // Umbral mínimo de amenaza de la fase
Uint8 number; // Numero de fase
};
struct effect_t
{
bool flash; // Indica si se ha de pintar la pantalla de blanco
bool shake; // Indica si se ha de agitar la pantalla
Uint8 shakeCounter; // Contador para medir el tiempo que dura el efecto
};
struct helper_t
{
bool needCoffee; // Indica si se necesitan cafes
bool needCoffeeMachine; // Indica si se necesita PowerUp
bool needPowerBall; // Indica si se necesita una PowerBall
int counter; // Contador para no dar ayudas consecutivas
int itemPoints1Odds; // Probabilidad de aparición del objeto
int itemPoints2Odds; // Probabilidad de aparición del objeto
int itemPoints3Odds; // Probabilidad de aparición del objeto
int itemClockOdds; // Probabilidad de aparición del objeto
int itemCoffeeOdds; // Probabilidad de aparición del objeto
int itemCoffeeMachineOdds; // Probabilidad de aparición del objeto
};
SDL_Renderer *mRenderer; // El renderizador de la ventana
std::string *mFileList; // Lista de ficheros con los recursos
std::string *mTextStrings; // Vector con los textos del juego
int mNumPlayers; // Numero de jugadores
Player *mPlayer[2]; // Vector con los jugadores jugador
Input *mInput[2]; // Manejador de entrada, uno por cada jugador
Balloon *mBalloon[MAX_BALLOONS]; // Vector con los objetos globo
Bullet *mBullet[MAX_BULLETS]; // Vector con los objetos bala
Item *mItem[MAX_ITEMS]; // Vector con los objetos item
SmartSprite *mSmartSprite[MAX_SMART_SPRITES]; // Vector para almacenar y gestionar SmartSprites
LTexture *mTextureBalloon; // Textura para los enemigos
LTexture *mTextureBullet; // Textura para las balas
LTexture *mTextureGameBG; // Textura para el fondo del juego
LTexture *mTextureGameText; // Textura para los sprites con textos
LTexture *mTextureItems; // Textura para los items
LTexture *mTexturePlayer1Head; // Textura para la cabeza del jugador1
LTexture *mTexturePlayer1Body; // Textura para el cuerpo del jugador1
LTexture *mTexturePlayer1Death; // Textura para la animación de muerte del jugador1
LTexture *mTexturePlayer1Legs; // Textura para las piernas del jugador
LTexture *mTexturePlayer2Head; // Textura para la cabeza del jugador2
LTexture *mTexturePlayer2Body; // Textura para el cuerpo del jugador2
LTexture *mTexturePlayer2Death; // Textura para la animación de muerte del jugador2
LTexture *mTexturePlayer2Legs; // Textura para las piernas del jugador
LTexture *mTextureText; // Textura para el texto
LTexture *mTextureText2; // Textura para el texto
Text *mText; // Variable con todos los objetos de texto
Text *mTextX2; // Variable con todos los objetos de texto
Menu *mMenuGameOver; // Menú de la pantalla de game over
Menu *mMenuPause; // Menú de la pantalla de pausa
Fade *mFade; // Objeto para renderizar fades
SDL_Event *mEventHandler; // Manejador de eventos
MovingSprite *mClouds1a; // Sprite para las nubes superiores
MovingSprite *mClouds1b; // Sprite para las nubes superiores
MovingSprite *mClouds2a; // Sprite para las nubes inferiores
MovingSprite *mClouds2b; // Sprite para las nubes inferiores
SmartSprite *m1000Bitmap; // Sprite con el texto 1.000
SmartSprite *m2500Bitmap; // Sprite con el texto 2.500
SmartSprite *m5000Bitmap; // Sprite con el texto 5.000
Sprite *mSpriteBackground; // Sprite con los graficos frontales del fondo
Sprite *mSpriteGetReady; // Sprite para el texto de GetReady del principio de la partida
Sprite *mSpriteGradient; // Sprite con los graficos del degradado de color de fondo
Sprite *mSpriteGrass; // Sprite para la hierba
Sprite *mSpritePowerMeter; // Sprite para el medidor de poder de la fase
Sprite *mSpriteScoreBoard; // Sprite para el fondo del marcador
JA_Sound mSoundBalloon; // Sonido para la explosión del globo
JA_Sound mSoundBullet; // Sonido para los disparos
JA_Sound mSoundPlayerCollision; // Sonido para la colisión del jugador con un enemigo
JA_Sound mSoundHiScore; // Sonido para cuando se alcanza la máxima puntuación
JA_Sound mSoundItemDrop; // Sonido para cuando se genera un item
JA_Sound mSoundItemPickup; // Sonido para cuando se recoge un item
JA_Sound mSoundCoffeeOut; // Sonido para cuando el jugador pierde el café al recibir un impacto
JA_Sound mSoundStageChange; // Sonido para cuando se cambia de fase
JA_Sound mSoundBubble1; // Sonido para cuando el jugador muere
JA_Sound mSoundBubble2; // Sonido para cuando el jugador muere
JA_Sound mSoundBubble3; // Sonido para cuando el jugador muere
JA_Sound mSoundBubble4; // Sonido para cuando el jugador muere
JA_Sound mSoundClock; // Sonido para cuando se detiene el tiempo con el item reloj
JA_Sound mSoundPowerBall; // Sonido para cuando se explota una Power Ball
JA_Sound mSoundCollision; // Sonido para cuando la máquina de café toca el suelo
JA_Music mMusicPlaying; // Musica de fondo
Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa
Uint8 mTicksSpeed; // Velocidad a la que se repiten los bucles del programa
//Uint32 mScore; // Puntuación actual
Uint32 mHiScore; // Puntuación máxima
bool mHiScoreAchieved; // Indica si se ha superado la puntuación máxima
section_t mSection; // Seccion actual dentro del juego
stage_t mStage[10]; // Variable con los datos de cada pantalla
Uint8 mCurrentStage; // Indica la fase actual
Uint8 mStageBitmapCounter; // Contador para el tiempo visible del texto de Stage
float mStageBitmapPath[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto
float mGetReadyBitmapPath[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto
Uint16 mDeathCounter; // Contador para la animación de muerte del jugador
Uint8 mDeathIndex; // Indice del vector de smartsprites que contiene el sprite del jugador
Uint8 mMenaceCurrent; // Nivel de amenaza actual
Uint8 mMenaceThreshold; // 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 numero de globos
bool mTimeStopped; // Indica si el tiempo está detenido
Uint16 mTimeStoppedCounter; // Temporizador para llevar la cuenta del tiempo detenido
Uint8 mRemainingExplosions; // Cantidad de explosiones restantes
Uint16 mRemainingExplosionsCounter; // Temporizador para la cantidad de explosiones restantes
bool mExplosionTime; // Indica si las explosiones estan en marcha
Uint32 mCounter; // Contador para el juego
Uint32 mScoreDataFile[TOTAL_SCORE_DATA]; // Datos del fichero de puntos
SDL_Rect mGradientRect[4]; // Vector con las coordenadas de los 4 gradientes
Uint16 mBalloonsPopped; // Lleva la cuenta de los globos explotados
Uint8 mLastEnemyDeploy; // Guarda cual ha sido la última formación desplegada para no repetir;
Uint8 mEnemyDeployCounter; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
float mEnemySpeed; // Velocidad a la que se mueven los enemigos
effect_t mEffect; // Variable para gestionar los efectos visuales
helper_t mHelper; // Variable para gestionar las ayudas
bool mPowerBallEnabled; // Indica si hay una powerball ya activa
bool mCoffeeMachineEnabled; // Indica si hay una máquina de café en el terreno de juego
Uint8 mPostFade; // Qué hacer al acabar el fade
float mSin[360]; // Vector con los valores del seno para 360 grados
bool mGameCompleted; // Indica si se ha completado la partida, llegando al final de la ultima pantalla
int mGameCompletedCounter; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
struct demo_t
{
bool enabled; // Indica si está activo el modo demo
bool recording; // Indica si está activado el modo para grabar la demo
Uint16 counter; // Contador para el modo demo
demoKeys_t keys; // Variable con las pulsaciones de teclas del modo demo
demoKeys_t dataFile[TOTAL_DEMO_DATA]; // Datos del fichero con los movimientos para la demo
};
demo_t mDemo; // Variable con todas las variables relacionadas con el modo demo
struct debug_t
{
bool enabled; // Indica si se va a mostrar la información de debug
Uint8 enemySet; // Escoge el set enemigo a generar
Uint8 gradR, gradG, gradB; // Colores RGB para modificar el color del gradiente de fondo
float hudW, hudH; // Multiplica el tamaño del hud de debug;
};
debug_t mDebug;
public:
// Constructor
Game(int numPlayers, SDL_Renderer *renderer, std::string *filelist, std::string *textStrings, Input *input1, Input *input2, bool demo);
// Destructor
~Game();
// Inicializa el vector con los valores del seno
void initSin();
// Inicializa las variables necesarias para la sección 'Game'
void init();
// Carga los recursos necesarios para la sección 'Game'
bool loadMedia();
// Carga el fichero de puntos
bool loadScoreFile();
// Carga el fichero de datos para la demo
bool loadDemoFile();
// Guarda el fichero de puntos
bool saveScoreFile();
// Guarda el fichero de datos para la demo
bool saveDemoFile();
// Inicializa las formaciones enemigas
void initEnemyFormations();
// Inicializa los conjuntos de formaciones
void initEnemyPools();
// Inicializa las fases del juego
void initGameStages();
// Crea una formación de enemigos
void deployEnemyFormation();
// Aumenta el poder de la fase
void increaseStageCurrentPower(Uint8 power);
// Establece el valor de la variable
//void setScore(Uint32 score);
// Establece el valor de la variable
void setHiScore(Uint32 score);
// Actualiza el valor de HiScore en caso necesario
void updateHiScore();
// Transforma un valor numérico en una cadena de 6 cifras
std::string updateScoreText(Uint32 num);
// Pinta el marcador en pantalla usando un objeto texto
void renderScoreBoard();
// Actualiza las variables del jugador
void updatePlayer();
// Actualiza las variables de la fase
void updateStage();
// Actualiza el estado de muerte
void updateDeath();
// Renderiza el fade final cuando se acaba la partida
void renderDeathFade(int counter);
// Actualiza los globos
void updateBalloons();
// Pinta en pantalla todos los globos activos
void renderBalloons();
// Devuelve el primer indice no activo del vector de globos
Uint8 getBalloonFreeIndex();
// Crea un globo nuevo en el vector de globos
Uint8 createNewBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 stoppedcounter, LTexture *texture);
// Crea una PowerBall
void createPowerBall();
// Establece a cero todos los valores del vector de objetos globo
void resetBalloons();
// Establece la velocidad de los globos
void setBalloonSpeed(float speed);
// Incrementa la velocidad de los globos
void incBalloonSpeed();
// Decrementa la velocidad de los globos
void decBalloonSpeed();
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
void updateBalloonSpeed();
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
void popBalloon(Uint8 index);
// Explosiona un globo. Lo destruye
void destroyBalloon(Uint8 index);
// Explosiona todos los globos
void popAllBalloons();
// Destruye todos los globos
void destroyAllBalloons();
// Detiene todos los globos
void stopAllBalloons(Uint16 time);
// Pone en marcha todos los globos
void startAllBalloons();
// Obtiene el numero de globos activos
Uint8 countBalloons();
// Comprueba la colisión entre el jugador y los globos activos
bool checkPlayerBalloonCollision(int index);
// Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision(int index);
// Comprueba la colisión entre las balas y los globos
void checkBulletBalloonCollision();
// Mueve las balas activas
void moveBullets();
// Pinta las balas activas
void renderBullets();
// Devuelve el primer indice no activo del vector de balas
Uint8 getBulletFreeIndex();
// Establece a cero todos los valores del vector de objetos bala
void resetBullets();
// Crea un objeto bala
void createBullet(int x, int y, Uint8 kind, bool poweredUp, int owner);
// Actualiza los items
void updateItems();
// Pinta los items activos
void renderItems();
// Devuelve el primer indice no activo del vector de items
Uint8 getItemFreeIndex();
// Establece a cero todos los valores del vector de objetos item
void resetItems();
// Devuelve un item en función del azar
Uint8 dropItem();
// Crea un objeto item
void createItem(int x, int y, Uint8 kind);
// Crea un objeto SmartSprite
void createItemScoreSprite(int x, int y, SmartSprite *sprite);
// Dibuja el efecto de flash
void renderFlashEffect();
// Actualiza el efecto de agitar la pantalla
void updateShakeEffect();
// Crea un SmartSprite para arrojar el item café al recibir un impacto
void throwCoffee(int x, int y);
// Crea un SmartSprite para arrojar al jugador al morir
void throwPlayer(int x, int y, int index);
// Actualiza los SmartSprites
void updateSmartSprites();
// Pinta los SmartSprites activos
void renderSmartSprites();
// Devuelve el primer indice no activo del vector de SmartSprites
Uint8 getSmartSpriteFreeIndex();
// Establece a cero todos los valores del vector de objetos SmafrtSprite
void resetSmartSprites();
// Acciones a realizar cuando el jugador muere
void killPlayer(int index);
// Obtiene el valor de la variable
Uint8 getSubsection();
// Calcula y establece el valor de amenaza en funcion de los globos activos
void evaluateAndSetMenace();
// Obtiene el valor de la variable
Uint8 getMenace();
// Establece el valor de la variable
void setTimeStopped(bool value);
// Obtiene el valor de la variable
bool isTimeStopped();
// Establece el valor de la variable
void setTimeStoppedCounter(Uint16 value);
// Incrementa el valor de la variable
void incTimeStoppedCounter(Uint16 value);
// Actualiza la variable EnemyDeployCounter
void updateEnemyDeployCounter();
// Actualiza y comprueba el valor de la variable
void updateTimeStoppedCounter();
// Establece el valor de la variable
void setExplosionTime(bool value);
// Obtiene el valor de la variable
bool isExplosionTime();
// Establece el valor de la variable
void setRemainingExplosions(Uint8 value);
// Actualiza y comprueba el valor de la variable
void updateRemainingExplosionsCounter();
// Gestiona el nivel de amenaza
void updateMenace();
// Actualiza el campo de juego
void updatePlayField();
// Actualiza el fondo
void updateBackground();
// Dibuja el fondo
void renderBackground();
// Dibuja el campo de juego
void renderPlayField();
// Gestiona las entradas desde el mando de juego
bool checkGameController(Uint8 state);
// Gestiona la entrada durante el juego
void checkGameInput();
// Pinta diferentes mensajes en la pantalla
void renderMessages();
// Habilita el efecto del item de detener el tiempo
void enableTimeStopItem();
// Deshabilita el efecto del item de detener el tiempo
void disableTimeStopItem();
// Agita la pantalla
void shakeScreen();
// Bucle para el juego
section_t run();
// Bucle para el menu de pausa del juego
void runPausedGame();
// Bucle para la pantalla de game over
void runGameOverScreen();
// Dibuja la informacion de debug en pantalla
void renderDebugInfo();
// Indica si se puede crear una powerball
bool canPowerBallBeCreated();
// Calcula el poder actual de los globos en pantalla
int calculateScreenPower();
// Inicializa las variables que contienen puntos de ruta para mover objetos
void initPaths();
// Actualiza el tramo final de juego, una vez completado
void updateGameCompleted();
// Actualiza las variables de ayuda
void updateHelper();
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,665 +0,0 @@
#pragma once
#include "ifdefs.h"
#include "sprite.h"
#include "movingsprite.h"
#include "smartsprite.h"
#include "player.h"
#include "balloon.h"
#include "bullet.h"
#include "coffeedrop.h"
#include "item.h"
#include "text.h"
#include "text2.h"
#include "menu.h"
#include "const.h"
#include "jail_audio.h"
#include "utils.h"
#include <math.h>
#ifndef GAMEDIRECTOR_H
#define GAMEDIRECTOR_H
// GameDirector
class GameDirector
{
private:
SDL_Window *mWindow; // La ventana donde dibujamos
SDL_Renderer *mRenderer; // El renderizador de la ventana
SDL_Event *mEventHandler; // Manejador de eventos
SDL_Texture *mBackbuffer; // Textura para usar como backbuffer
SDL_Texture *mTitleSurface; // Textura para dibujar el fondo de la pantalla de título
SDL_Texture *mInstructionsSurface; // Textura donde dibujar las instrucciones
SDL_Joystick *mGameController; // Manejador para el mando 1
SDL_Haptic *mControllerHaptic; // Manejador para el mando con vibración
bool mGameControllerFound; // Variable para saber si hay un mando conectado
#ifndef UNUSED
CoffeeDrop *mCoffeeDrop[MAX_COFFEE_DROPS]; // Vector con todas ls gotas de café;
#endif
struct text_t
{
Text *white; // Texto blanco de 8x8
Text *whiteX2; // Texto blanco de 16x16
Text *black; // Texto negro de 8x8
Text *blackX2; // Texto negro de 16x16
Text *nokia; // Texto de anchura variable y 10px de alto
};
text_t mText; // Variable con todos los objetos de texto
struct menu_t
{
Menu *title; // Menu de la pantalla de título
Menu *pause; // Menú de la pantalla de pausa
Menu *gameOver; // Menú de la pantalla de game over
Menu *options; // Menú de la pantalla de opciones
Menu *active; // Menu activo (de momento para la pantalla del titulo)
bool keyPressed; // Variable para evitar la repetición de teclas en los menus
};
menu_t mMenu; // Variable con todos los objetos menus y sus variables
struct intro_t
{
SmartSprite *bitmap[INTRO_TOTAL_BITMAPS]; // Vector con los sprites inteligentes para los dibujos de la intro
Text2 *text[INTRO_TOTAL_TEXTS]; // Textos de la intro
Uint8 events[INTRO_TOTAL_EVENTS]; // Vector para coordinar los eventos de la intro
};
intro_t mIntro; // Contiene todas las variables de la sección 'Intro'
struct enemyInits_t
{
int x; // Posición en el eje X donde crear al enemigo
int y; // Posición en el eje Y donde crear al enemigo
float velX; // Velocidad inicial en el eje X
Uint8 kind; // Tipo de enemigo
Uint16 creationCounter; // Temporizador para la creación del enemigo
};
struct enemyFormation_t // Contiene la información de una formación enemiga
{
Uint8 numberOfEnemies; // Cantidad de enemigos que forman la formación
enemyInits_t init[50]; // Vector con todas las inicializaciones de los enemigos de la formación
};
enemyFormation_t mEnemyFormation[100]; // Vector con todas las formaciones enemigas
struct enemyPool_t
{
enemyFormation_t *set[10]; // Conjunto de formaciones enemigas
};
enemyPool_t mEnemyPool[10]; // Variable con los diferentes conjuntos de formaciones enemigas
struct stage_t // Contiene todas las variables relacionadas con una fase
{
enemyPool_t *enemyPool; // El conjunto de formaciones enemigas de la fase
Uint16 currentPower; // Cantidad actual de poder
Uint16 powerToComplete; // Cantidad de poder que se necesita para completar la fase
Uint8 maxMenace; // Umbral máximo de amenaza de la fase
Uint8 minMenace; // Umbral mínimo de amenaza de la fase
Uint8 number; // Numero de fase
};
struct effect_t
{
bool flash; // Indica si se ha de pintar la pantalla de blanco
bool shake; // Indica si se ha de agitar la pantalla
Uint8 shakeCounter; // Contador para medir el tiempo que dura el efecto
};
struct game_t
{
Uint32 score; // Puntuación actual
Uint32 hiScore; // Puntuación máxima
Uint8 section; // Seccion actual dentro del juego
bool hiScoreAchieved; // Indica si se ha superado la puntuación máxima
Uint8 currentStage; // Indica la fase actual
stage_t stage[10]; // Variable con los datos de cada pantalla
Uint8 stageBitmapCounter; // Contador para el tiempo visible del texto de Stage
float stageBitmapPath[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto
float getReadyBitmapPath[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto
Uint16 deathCounter; // Contador para la animación de muerte del jugador
Uint8 deathIndex; // Indice del vector de smartsprites que contiene el sprite del jugador
Uint8 menaceCurrent; // Nivel de amenaza actual
Uint8 menaceThreshold; // 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 numero de globos
bool timeStopped; // Indica si el tiempo está detenido
Uint16 timeStoppedCounter; // Temporizador para llevar la cuenta del tiempo detenido
Uint8 remainingExplosions; // Cantidad de explosiones restantes
Uint16 remainingExplosionsCounter; // Temporizador para la cantidad de explosiones restantes
bool explosionTime; // Indica si las explosiones estan en marcha
Uint32 counter; // Contador para el juego
Uint32 scoreDataFile[TOTAL_SCORE_DATA]; // Datos del fichero de puntos
Sprite *getReadyBitmap; // Sprite para el texto de GetReady del principio de la partida
SmartSprite *_1000Bitmap; // Sprite con el texto 1.000
SmartSprite *_2500Bitmap; // Sprite con el texto 2.500
SmartSprite *_5000Bitmap; // Sprite con el texto 5.000
Sprite *background; // Sprite con los graficos frontales del fondo
Sprite *gradient; // Sprite con los graficos del degradado de color de fondo
SDL_Rect gradientRect[4]; // Vector con las coordenadas de los 4 gradientes
Uint16 balloonsPopped; // Lleva la cuenta de los globos explotados
MovingSprite *clouds1a; // Sprite para las nubes superiores
MovingSprite *clouds1b; // Sprite para las nubes superiores
MovingSprite *clouds2a; // Sprite para las nubes inferiores
MovingSprite *clouds2b; // Sprite para las nubes inferiores
Sprite *grass; // Sprite para la hierba
Sprite *scoreBoard; // Sprite para el fondo del marcador
Sprite *powerMeter; // Sprite para el medidor de poder de la fase
Player *player; // El jugador
Balloon *balloon[MAX_BALLOONS]; // Vector con los objetos globo
Bullet *bullet[MAX_BULLETS]; // Vector con los objetos bala
Item *item[MAX_ITEMS]; // Vector con los objetos item
SmartSprite *smartSprite[MAX_SMART_SPRITES]; // Vector para almacenar y gestionar SmartSprites
Uint8 lastEnemyDeploy; // Guarda cual ha sido la última formación desplegada para no repetir;
Uint8 enemyDeployCounter; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
float enemySpeed; // Velocidad a la que se mueven los enemigos
effect_t effect; // Variable para gestionar los efectos visuales
};
game_t mGame; // Variable con todas las variables usadas durante el juego
struct title_t
{
Uint16 counter; // Temporizador para la pantalla de titulo
Uint16 backgroundCounter; // Temporizador para el fondo de tiles de la pantalla de titulo
Uint8 backgroundMode; // Variable para almacenar el tipo de efecto que hará el fondo de la pantalla de titulo
bool menuVisible; // Indicador para saber si se muestra el menu del titulo o la frase intermitente
Sprite *tile; // Sprite para dibujar el fondo de pantalla del título
SDL_Rect backgroundWindow; // Ventana visible para la textura de fondo del titulo
Uint8 section; // Indicador para el bucle del titulo
Uint8 nextProgSection; // Indica cual es la siguiente sección a cargar cuando termine el contador del titulo
Uint8 events[TITLE_TOTAL_EVENTS]; // Vector para coordinar los eventos de la pantalla de titulo
Uint16 instructionsCounter; // Contador para las instrucciones
SmartSprite *coffeeBitmap; // Sprite con la palabra COFFEE para la pantalla de titulo
SmartSprite *crisisBitmap; // Sprite con la palabra CRISIS para la pantalla de titulo
AnimatedSprite *dustBitmapL; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
AnimatedSprite *dustBitmapR; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
};
title_t mTitle; // Variable con todas las variables de la pantalla de titulo
struct demo_t
{
bool enabled; // Indica si está activo el modo demo
bool recording; // Indica si está activado el modo para grabar la demo
Uint16 counter; // Contador para el modo demo
demoKeys_t keys; // Variable con las pulsaciones de teclas del modo demo
demoKeys_t dataFile[TOTAL_DEMO_DATA]; // Datos del fichero con los movimientos para la demo
};
demo_t mDemo; // Variable con todas las variables relacionadas con el modo demo
struct options_t
{
Uint32 fullScreenMode; // Contiene el valor del modo de pantalla completa
Uint32 fullScreenModePrevious;
Uint8 windowSize; // Contiene el valor del tamaño de la ventana
Uint8 windowSizePrevious;
bool displayCoffeeDrops; // Indica si se han de mostar las gotas de cafe
};
options_t mOptions; // Variable con todas las variables de las opciones del programa
struct logo_t
{
Uint16 counter; // Contador
Sprite *sprite; // Sprite con la textura del logo
};
logo_t mLogo; // Variable con las variables para el logo
struct prog_t
{
bool quit; // Indica si hay que salir del programa
input_t keyboard; // Almacena los códigos de teclado correspondientes
input_t keyboardBuffer; // Buffer para teclas pulsadas
std::string executablePath; // Path del ejecutable
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa
Uint8 section; // Sección actual del programa;
Uint8 subsection; // Subseccion dentro de la sección;
Uint8 ticksSpeed; // Velocidad a la que se repiten los bucles del programa
};
prog_t mProg; // Contiene todas las variables globales del programa
struct debug_t
{
bool enabled; // Indica si se va a mostrar la información de debug
Uint8 enemySet; // Escoge el set enemigo a generar
Uint8 gradR, gradG, gradB; // Colores RGB para modificar el color del gradiente de fondo
float hudW, hudH; // Multiplica el tamaño del hud de debug;
};
debug_t mDebug;
struct resourceBinFile_t
{
std::string file; // Ruta al fichero
};
resourceBinFile_t mBinFile[TOTAL_BINFILE]; // Todos los ficheros binarios
struct resourceSound_t
{
std::string file; // Ruta al fichero
JA_Sound sound; // Variable con el sonido
};
resourceSound_t mSound[TOTAL_SOUND]; // Todos los sonidos
struct resourceMusic_t
{
std::string file; // Ruta al fichero
JA_Music music; // Variable con la música
};
resourceMusic_t mMusic[TOTAL_MUSIC]; // Todas las músicas
struct resourceTexture_t
{
std::string file; // Ruta al fichero
LTexture *texture; // Variable con la textura
};
resourceTexture_t mTexture[TOTAL_TEXTURE]; // Todos los gráficos
public:
// Constructor
GameDirector(std::string path);
// Destructor
~GameDirector();
// Inicia las variables necesarias para arrancar el programa
void initProg();
// Carga los recursos necesarios para el programa
bool loadMediaProg();
// Libera las variables del programa
void quitProg();
// Inicializa jail_audio
void initJailAudio();
// Arranca SDL y crea la ventana
bool initSDL();
// Inicializa el vector con los valores del seno
void initSin();
// Inicializa las variables que contienen puntos de ruta para mover objetos
void initPaths();
// Inicializa las variables necesarias para la sección 'Logo'
void initLogo();
// Carga los recursos necesarios para la sección 'Logo'
bool loadMediaLogo();
// Libera las variables necesarias para la sección 'Logo'
void quitLogo();
// Inicializa las variables necesarias para la sección 'Intro'
void initIntro();
// Carga los recursos necesarios para la sección 'Intro'
bool loadMediaIntro();
// Libera las variables necesarias para la sección 'Intro'
void quitIntro();
// Inicializa las variables necesarias para la sección 'Title'
void initTitle(Uint8 subsection = TITLE_SECTION_1);
// Carga los recursos necesarios para la sección 'Title'
bool loadMediaTitle();
// Libera las variables necesarias para la sección 'Title'
void quitTitle();
// Inicializa las variables necesarias para la sección 'Game'
void initGame();
// Inicializa las variables especificas de la sección 'Game' para empezar una nueva partida
void resetGame();
// Carga los recursos necesarios para la sección 'Game'
bool loadMediaGame();
// Libera las variables necesarias para la sección 'Game'
void quitGame();
// Crea el indice de ficheros
void setFileList();
// Comprueba que todos los ficheros existen
bool checkFileList();
// Carga el fichero de puntos
bool loadScoreFile();
// Carga el fichero de configuración
bool loadConfigFile();
// Carga el fichero de datos para la demo
bool loadDemoFile();
// Guarda el fichero de puntos
bool saveScoreFile();
// Guarda el fichero de configuración
bool saveConfigFile();
// Guarda el fichero de datos para la demo
bool saveDemoFile();
// Carga un archivo de imagen en una textura
bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer);
// Comprueba el valor de la variable 'quit'
bool exit();
// Establece el valor de la variable
void setExecutablePath(std::string path);
// Inicializa las formaciones enemigas
void initEnemyFormations();
// Inicializa los conjuntos de formaciones
void initEnemyPools();
// Inicializa las fases del juego
void initGameStages();
// Crea una formación de enemigos
void deployEnemyFormation();
// Aumenta el poder de la fase
void increaseStageCurrentPower();
// Establece el valor de la variable
void setScore(Uint32 score);
// Establece el valor de la variable
void setHiScore(Uint32 score);
// Actualiza el valor de HiScore en caso necesario
void updateHiScore();
// Transforma un valor numérico en una cadena de 6 cifras
std::string updateScoreText(Uint32 num);
// Pinta el marcador en pantalla usando un objeto texto
void renderScoreBoard();
// Actualiza las variables del jugador
void updatePlayer();
// Actualiza las variables de la fase
void updateStage();
// Actualiza el estado de muerte
void updateDeath();
// Renderiza el fade final cuando se acaba la partida
void renderDeathFade();
// Actualiza los globos
void updateBalloons();
// Pinta en pantalla todos los globos activos
void renderBalloons();
// Devuelve el primer indice no activo del vector de globos
Uint8 getBalloonFreeIndex();
// Crea un globo nuevo en el vector de globos
Uint8 createNewBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 stoppedcounter, LTexture *texture);
// Crea una PowerBall
void createPowerBall();
// Establece a cero todos los valores del vector de objetos globo
void resetBalloons();
// Establece la velocidad de los globos
void setBalloonSpeed(float speed);
// Incrementa la velocidad de los globos
void incBalloonSpeed();
// Decrementa la velocidad de los globos
void decBalloonSpeed();
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
void updateBalloonSpeed();
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
void popBalloon(Uint8 index);
// Explosiona un globo. Lo destruye
void destroyBalloon(Uint8 index);
// Explosiona todos los globos
void popAllBalloons();
// Destruye todos los globos
void destroyAllBalloons();
// Detiene todos los globos
void stopAllBalloons(Uint16 time);
// Pone en marcha todos los globos
void startAllBalloons();
// Obtiene el numero de globos activos
Uint8 countBalloons();
// Comprueba la colisión entre el jugador y los globos activos
bool checkPlayerBalloonCollision();
// Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision();
// Comprueba la colisión entre las balas y los globos
void checkBulletBalloonCollision();
// Mueve las balas activas
void moveBullets();
// Pinta las balas activas
void renderBullets();
// Devuelve el primer indice no activo del vector de balas
Uint8 getBulletFreeIndex();
// Establece a cero todos los valores del vector de objetos bala
void resetBullets();
// Crea un objeto bala
void createBullet(int x, int y, Uint8 kind);
// Actualiza los items
void updateItems();
// Pinta los items activos
void renderItems();
// Devuelve el primer indice no activo del vector de items
Uint8 getItemFreeIndex();
// Establece a cero todos los valores del vector de objetos item
void resetItems();
// Devuelve un item en función del azar
Uint8 dropItem();
// Crea un objeto item
void createItem(int x, int y, Uint8 kind);
// Crea un objeto SmartSprite
void createItemScoreSprite(int x, int y, SmartSprite *sprite);
// Crea un objeto de bonus en función del azar
void dropBonus();
// Dibuja el efecto de flash
void renderFlashEffect();
// Actualiza el efecto de agitar la pantalla
void updateShakeEffect();
// Crea un SmartSprite para arrojar el item café al recibir un impacto
void throwCoffee(int x, int y);
// Crea un SmartSprite para arrojar al jugador al morir
void throwPlayer(int x, int y);
// Actualiza los SmartSprites
void updateSmartSprites();
// Pinta los SmartSprites activos
void renderSmartSprites();
// Devuelve el primer indice no activo del vector de SmartSprites
Uint8 getSmartSpriteFreeIndex();
// Establece a cero todos los valores del vector de objetos SmafrtSprite
void resetSmartSprites();
#ifndef UNUSED
// Deshabilita todas las gotas de café
void resetCoffeeDrops();
// Actualiza las gotas de cafe
void updateCoffeeDrops();
// Dibuja las gotas de cafe
void renderCoffeeDrops();
// Devuelve el primer indice libre del vector de CoffeeDrops
Uint8 getCoffeDropFreeIndex();
// Crea un numero de gotas de cafe
void createCoffeDrops(Uint8 num, int x, int y);
#endif
// Acciones a realizar cuando el jugador muere
void killPlayer();
// Obtiene el valor de la variable
Uint8 getSubsection();
// Calcula y establece el valor de amenaza en funcion de los globos activos
void setMenace();
// Obtiene el valor de la variable
Uint8 getMenace();
// Establece el valor de la variable
void setTimeStopped(bool value);
// Obtiene el valor de la variable
bool isTimeStopped();
// Establece el valor de la variable
void setTimeStoppedCounter(Uint16 value);
// Actualiza la variable EnemyDeployCounter
void updateEnemyDeployCounter();
// Actualiza y comprueba el valor de la variable
void updateTimeStoppedCounter();
// Establece el valor de la variable
void setExplosionTime(bool value);
// Obtiene el valor de la variable
bool isExplosionTime();
// Establece el valor de la variable
void setRemainingExplosions(Uint8 value);
// Actualiza y comprueba el valor de la variable
void updateRemainingExplosionsCounter();
// Gestiona el nivel de amenaza
void old_updateMenace();
// Gestiona el nivel de amenaza
void updateMenace();
// Actualiza el campo de juego
void updatePlayField();
// Actualiza el fondo
void updateBackground();
// Dibuja el fondo
void renderBackground();
// Dibuja el campo de juego
void renderPlayField();
// Gestiona las entradas desde el mando de juego
bool checkGameController(Uint8 state);
// Gestiona la entrada durante el juego
void checkGameInput();
// Gestiona la entrada de teclado y mando durante el menu
void checkMenuInput(Menu *menu);
// Obtiene el valor de la variable
Uint8 getProgSection();
// Establece el valor de la variable
void setProgSection(Uint8 section, Uint8 subsection = 0);
// Pinta una transición en pantalla
void renderFade(Uint8 index);
// Pinta diferentes mensajes en la pantalla
void renderMessages();
// Habilita el efecto del item de detener el tiempo
void enableTimeStopItem();
// Deshabilita el efecto del item de detener el tiempo
void disableTimeStopItem();
// Cambia el valor de la variable de modo de pantalla completa
void changeFullScreenMode();
// Actualiza los elementos del menu de opciones
void updateOptionsMenu();
// Agita la pantalla
void shakeScreen();
// Agita la pantalla
void shakeScreen2();
// Bucle para el logo del juego
void runLogo();
// Bucle para la intro del juego
void runIntro();
// Bucle para el titulo del juego
void runTitle(Uint8 subsection = TITLE_SECTION_1);
// Bucle para el juego
void runGame();
// Bucle para el menu de pausa del juego
void runPausedGame();
// Bucle para la pantalla de instrucciones
void runInstructions();
// Bucle para la pantalla de game over
void runGameOverScreen();
// Activa el modo Demo
void enableDemoMode();
// Desactiva el modo Demo
void disableDemoMode();
// Intercambia el proximo estado del juego despues del titulo
void toogleTitleNextGS();
// Dibuja la informacion de debug en pantalla
void renderDebugInfo();
};
#endif

View File

@@ -1,9 +1,9 @@
#ifdef _WIN64
#include "C:\mingw_dev_lib\include\SDL2\SDL.h"
#include "C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\SDL2\SDL.h"
#endif
#ifdef _WIN32
#include "C:\mingw_dev_lib\include\SDL2\SDL.h"
#include "C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\SDL2\SDL.h"
#endif
#ifdef __APPLE__
@@ -11,7 +11,11 @@
#endif
#ifdef __linux__
#include "/usr/include/SDL2/SDL.h"
#ifdef __MIPSEL__
#include "SDL.h"
#else
#include <SDL2/SDL.h>
#endif
#endif
#define UNUSED

324
source/input.cpp Normal file
View File

@@ -0,0 +1,324 @@
#include "input.h"
#include <stdio.h>
#include <iostream>
// Constructor
Input::Input(int source)
{
// Inicializa las variables
for (int i = 0; i < 17; i++)
{
mKeyBindings[i].scancode = 0;
mKeyBindings[i].active = false;
mGameControllerBindings[i].button = SDL_CONTROLLER_BUTTON_INVALID;
mGameControllerBindings[i].active = false;
}
mSource = source;
if (mSource == USE_GAMECONTROLLER)
{
/*
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) != 1)
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
int nJoysticks = SDL_NumJoysticks();
int numGamepads = 0;
// Count how many controllers there are
for (int i = 0; i < nJoysticks; i++)
if (SDL_IsGameController(i))
numGamepads++;
printf("%i joysticks found, %i are gamepads\n", nJoysticks, numGamepads);
//SDL_JoystickEventState(SDL_ENABLE);
*/
if (!discoverGameController())
mSource = USE_KEYBOARD;
}
// Comprueba si hay algún mando conectado
//discoverGameController();
// En caso de haber un mando, el objeto se puede utilizar con entradas de mando
//if (mGameControllerFound)
// mSource = source;
// Si no hay un mando, el objeto se configura como teclado
//else
// mSource = USE_KEYBOARD;
if (mSource == USE_KEYBOARD)
printf("Input using KEYBOARD\n");
else
printf("Input using GAMECONTROLLER\n");
}
// Destructor
Input::~Input()
{
}
// Asigna uno de los posibles inputs a una tecla del teclado
void Input::bindKey(Uint8 input, SDL_Scancode code)
{
mKeyBindings[input].scancode = code;
}
// Asigna uno de los posibles inputs a un botón del mando
void Input::bindGameController(Uint8 input, SDL_GameControllerButton button)
{
mGameControllerBindings[input].button = button;
}
// Comprueba si un input esta activo
bool Input::checkInput(Uint8 input, bool repeat)
{
if (mSource == USE_KEYBOARD)
{
const Uint8 *mKeystates = SDL_GetKeyboardState(NULL);
if (repeat)
{
if (mKeystates[mKeyBindings[input].scancode] != 0)
return true;
else
return false;
}
else
{
if (!mKeyBindings[input].active)
{
if (mKeystates[mKeyBindings[input].scancode] != 0)
{
mKeyBindings[input].active = true;
return true;
}
else
{
return false;
}
}
else
{
if (mKeystates[mKeyBindings[input].scancode] == 0)
{
mKeyBindings[input].active = false;
return false;
}
else
{
return false;
}
}
}
}
else // Utiliza mando
{
if (repeat)
{
if (SDL_GameControllerGetButton(mGameController, mGameControllerBindings[input].button) != 0)
return true;
else
return false;
}
else
{
if (!mGameControllerBindings[input].active)
{
if (SDL_GameControllerGetButton(mGameController, mGameControllerBindings[input].button) != 0)
{
mGameControllerBindings[input].active = true;
return true;
}
else
{
return false;
}
}
else
{
if (SDL_GameControllerGetButton(mGameController, mGameControllerBindings[input].button) == 0)
{
mGameControllerBindings[input].active = false;
return false;
}
else
{
return false;
}
}
}
}
}
// Gestiona las entradas desde el mando de juego
/*bool Input::checkGameController(Uint8 state)
{
bool success = false;
// No hay mando. Siempre devuelve falso salvo NO_INPUT que siempre es cierto
if (!mGameControllerFound)
{
if (state == NO_INPUT)
return true;
else
return false;
}
switch (state)
{
case INPUT_NULL:
success = !checkGameController(INPUT_UP) && !checkGameController(INPUT_DOWN) && !checkGameController(INPUT_LEFT) && !checkGameController(INPUT_RIGHT) &&
!checkGameController(INPUT_ACCEPT) && !checkGameController(INPUT_CANCEL) && !checkGameController(INPUT_PAUSE) &&
!checkGameController(INPUT_FIRE_UP) && !checkGameController(INPUT_FIRE_LEFT) && !checkGameController(INPUT_FIRE_RIGHT);
break;
case INPUT_UP:
success = (SDL_JoystickGetAxis(mGameController, 1) < -JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_UP));
break;
case INPUT_DOWN:
success = (SDL_JoystickGetAxis(mGameController, 1) > JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_DOWN));
break;
case INPUT_LEFT:
success = (SDL_JoystickGetAxis(mGameController, 0) < -JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_LEFT));
break;
case INPUT_RIGHT:
success = (SDL_JoystickGetAxis(mGameController, 0) > JOYSTICK_DEAD_ZONE) || (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_DPAD_RIGHT));
break;
case INPUT_ACCEPT:
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_B));
break;
case INPUT_CANCEL:
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_A));
break;
case INPUT_PAUSE:
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_START));
break;
case INPUT_FIRE_UP:
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_Y));
break;
case INPUT_FIRE_LEFT:
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_X));
break;
case INPUT_FIRE_RIGHT:
success = (SDL_JoystickGetButton(mGameController, SDL_CONTROLLER_BUTTON_B));
break;
default:
break;
}
return success;
}*/
// Comprueba si hay un mando conectado
bool Input::discoverGameController()
{
bool found = false;
/*
printf("%i joystics found\n", SDL_NumJoysticks());
for (int i = 0; i < SDL_NumJoysticks(); ++i)
{
if (SDL_IsGameController(i))
{
char *mapping;
printf("Index %i is a compatible controller, named %s\n", i, SDL_GameControllerNameForIndex(i));
mGameController = SDL_GameControllerOpen(i);
mapping = SDL_GameControllerMapping(mGameController);
printf("Controller %i is mapped as %s\n", i, mapping);
SDL_free(mapping);
found = true;
}
else
{
printf("Index %i is not a compatible controller.\n", i);
found = false;
}
}
*/
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) != 1)
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
int nJoysticks = SDL_NumJoysticks();
int numGamepads = 0;
// Count how many controllers there are
for (int i = 0; i < nJoysticks; i++)
if (SDL_IsGameController(i))
numGamepads++;
printf("%i joysticks found, %i are gamepads\n", nJoysticks, numGamepads);
//if (numGamepads > 0)
// found = true;
//SDL_JoystickEventState(SDL_ENABLE);
if (numGamepads > 0)
{
for (int i = 0; i < numGamepads; i++)
{
// Open the controller and add it to our list
mGameController = SDL_GameControllerOpen(i);
if (SDL_GameControllerGetAttached(mGameController) == 1)
//connectedControllers.push_back(pad);
{
found = true;
printf("%s\n", SDL_GameControllerNameForIndex(i));
}
else
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
}
SDL_GameControllerEventState(SDL_ENABLE);
}
//SDL_GameControllerGetButton(mGameController, SDL_CONTROLLER_BUTTON_A);
//printf("hola");
return found;
}
/*if (SDL_NumJoysticks() < 1)
{
printf("Warning: No joysticks connected!\n");
mGameControllerFound = false;
std::cout << "Warning: No joysticks connected!\n";
}
else
{*/
// Carga el mando
/*mGameController = SDL_GameControllerOpen(0);
if (mGameController == NULL)
{
printf("Warning: Unable to open game controller!\nSDL Error: %s\n", SDL_GetError());
mGameControllerFound = false;
}
else
{
printf("%i joysticks were found.\n", SDL_NumJoysticks());
std::cout << "joysticks were found!\n";
mGameControllerFound = true;
//printf("%i buttons\n", SDL_JoystickNumButtons(mGameController));
// Obtiene el dispositivo de control háptico
mControllerHaptic = SDL_HapticOpenFromJoystick(mGameController);
if (mControllerHaptic == NULL)
{
printf("Warning: Controller does not support haptics!\nSDL Error: %s\n", SDL_GetError());
}
else
{
printf("Haptics detected\n");
// Inicializa la vibración
if (SDL_HapticRumbleInit(mControllerHaptic) < 0)
{
printf("Warning: Unable to initialize rumble!\nSDL Error: %s\n", SDL_GetError());
}
}
}
}
return mGameControllerFound;
}*/

75
source/input.h Normal file
View File

@@ -0,0 +1,75 @@
#pragma once
#include "ifdefs.h"
#ifndef INPUT_H
#define INPUT_H
#define INPUT_NULL 0
#define INPUT_UP 1
#define INPUT_DOWN 2
#define INPUT_LEFT 3
#define INPUT_RIGHT 4
#define INPUT_ACCEPT 5
#define INPUT_CANCEL 6
#define INPUT_BUTTON_1 7
#define INPUT_BUTTON_2 8
#define INPUT_BUTTON_3 9
#define INPUT_BUTTON_4 10
#define INPUT_BUTTON_5 11
#define INPUT_BUTTON_6 12
#define INPUT_BUTTON_7 13
#define INPUT_BUTTON_8 14
#define INPUT_BUTTON_PAUSE 15
#define INPUT_BUTTON_ESCAPE 16
#define REPEAT_TRUE true
#define REPEAT_FALSE false
#define USE_KEYBOARD 0
#define USE_GAMECONTROLLER 1
// Clase Input
class Input
{
private:
struct keyBindings_t
{
Uint8 scancode; // Scancode asociado
bool active; // Indica si está activo
};
keyBindings_t mKeyBindings[17]; // Vector con las teclas asociadas a los inputs predefinidos
struct GameControllerBindings_t
{
SDL_GameControllerButton button; // GameControllerButton asociado
bool active; // Indica si está activo
};
GameControllerBindings_t mGameControllerBindings[17]; // Vector con las teclas asociadas a los inputs predefinidos
SDL_GameController *mGameController; // Manejador para el mando
//SDL_Haptic *mControllerHaptic; // Manejador para el mando con vibración
//bool mGameControllerFound; // Variable para saber si hay un mando conectado
int mSource; // Indica si el objeto usará un mando o un teclado
public:
// Constructor
Input(int source);
// Destructor
~Input();
// Asigna uno de los posibles inputs a una tecla del teclado
void bindKey(Uint8 input, SDL_Scancode code);
// Asigna uno de los posibles inputs a un botón del mando
void bindGameController(Uint8 input, SDL_GameControllerButton button);
// Comprueba si un input esta activo
bool checkInput(Uint8 input, bool repeat);
// Comprueba si hay un mando conectado
bool discoverGameController();
};
#endif

229
source/instructions.cpp Normal file
View File

@@ -0,0 +1,229 @@
#include "instructions.h"
#ifdef __MIPSEL__
#include <sys/stat.h>
#include <dirent.h>
#endif
const Uint8 SELF = 0;
// Constructor
Instructions::Instructions(SDL_Renderer *renderer, std::string *fileList, std::string *textStrings)
{
// Copia los punteros
mRenderer = renderer;
mFileList = fileList;
mTextStrings = textStrings;
// Reserva memoria para los punteros
mEventHandler = new SDL_Event();
mItemTexture = new LTexture();
mTextTexture = new LTexture();
mSprite = new Sprite();
mText = new Text(mTextTexture, mRenderer);
// Crea un backbuffer para el renderizador
mBackbuffer = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT);
if (mBackbuffer == NULL)
printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError());
}
// Destructor
Instructions::~Instructions()
{
mItemTexture->unload();
delete mItemTexture;
mItemTexture = nullptr;
mTextTexture->unload();
delete mTextTexture;
mTextTexture = nullptr;
delete mSprite;
mSprite = nullptr;
delete mEventHandler;
mEventHandler = nullptr;
delete mText;
mText = nullptr;
SDL_DestroyTexture(mBackbuffer);
mBackbuffer = nullptr;
}
// Carga los recursos necesarios para la sección 'Instructions'
bool Instructions::loadMedia()
{
bool success = true;
success &= loadTextureFromFile(mItemTexture, mFileList[34], mRenderer);
success &= loadTextureFromFile(mTextTexture, mFileList[30], mRenderer);
return success;
}
// Inicializa las variables necesarias para la sección 'Instructions'
void Instructions::init()
{
// Carga los recursos
loadMedia();
// Inicializa variables
mSection.name = SELF;
mSprite->init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mItemTexture, mRenderer);
mTicks = 0;
mTicksSpeed = 15;
mText->init(TEXT_FIXED, BLOCK);
mManualQuit = false;
mCounter = 0;
}
// Bucle para la pantalla de instrucciones
void Instructions::run(Uint8 mode)
{
init();
while (mSection.name == SELF)
{
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(mEventHandler) != 0)
{
// Evento de salida de la aplicación
if (mEventHandler->type == SDL_QUIT)
{
mSection.name = PROG_SECTION_QUIT;
break;
}
if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN))
{
if (mode == INSTRUCTIONS_MODE_AUTO)
{
JA_StopMusic();
mSection.name = PROG_SECTION_TITLE;
mSection.subsection = TITLE_SECTION_1;
}
else
mManualQuit = true;
}
}
// Actualiza las variables
if (SDL_GetTicks() - mTicks > mTicksSpeed)
{
// Actualiza el contador de ticks
mTicks = SDL_GetTicks();
// Modo automático
if (mode == INSTRUCTIONS_MODE_AUTO)
{
mCounter++;
if (mCounter == INSTRUCTIONS_COUNTER)
{
mSection.name = PROG_SECTION_TITLE;
mSection.subsection = TITLE_SECTION_1;
}
}
// Modo manual
else
{
++mCounter %= 60000;
if (mManualQuit)
{
mSection.name = PROG_SECTION_TITLE;
mSection.subsection = TITLE_SECTION_3;
}
}
}
// Pinta en pantalla
SDL_Rect window = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
SDL_Rect srcRect = {0, 0, 16, 16};
const color_t orangeColor = {0xFF, 0x7A, 0x00};
const SDL_Rect destRect1 = {60, 88 + (16 * 0), 16, 16}; // Disquito
const SDL_Rect destRect2 = {60, 88 + (16 * 1), 16, 16}; // Gavineixon
const SDL_Rect destRect3 = {60, 88 + (16 * 2), 16, 16}; // Pacmar
const SDL_Rect destRect4 = {60, 88 + (16 * 3), 16, 16}; // Time Stopper
const SDL_Rect destRect5 = {60, 88 + (16 * 4), 16, 16}; // Coffee
// Pinta en el backbuffer el texto y los sprites
SDL_SetRenderTarget(mRenderer, mBackbuffer);
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(mRenderer);
// Escribe el texto
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 8, mTextStrings[11], 0, orangeColor, 1, shdwTxtColor);
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 24, mTextStrings[12], 0, noColor, 1, shdwTxtColor);
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 34, mTextStrings[13], 0, noColor, 1, shdwTxtColor);
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 48, mTextStrings[14], 0, noColor, 1, shdwTxtColor);
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 58, mTextStrings[15], 0, noColor, 1, shdwTxtColor);
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 75, mTextStrings[16], 0, orangeColor, 1, shdwTxtColor);
mText->writeShadowed(84, 92, mTextStrings[17], shdwTxtColor);
mText->writeShadowed(84, 108, mTextStrings[18], shdwTxtColor);
mText->writeShadowed(84, 124, mTextStrings[19], shdwTxtColor);
mText->writeShadowed(84, 140, mTextStrings[20], shdwTxtColor);
mText->writeShadowed(84, 156, mTextStrings[21], shdwTxtColor);
if ((mode == INSTRUCTIONS_MODE_MANUAL) && (mCounter % 50 > 14))
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, SCREEN_HEIGHT - 12, mTextStrings[22], 0, orangeColor, 1, shdwTxtColor);
// Disquito
mSprite->init(destRect1, mItemTexture, mRenderer);
srcRect.x = 0;
srcRect.y = 16 * (((mCounter + 12) / 36) % 2);
mSprite->setSpriteClip(srcRect);
mSprite->render();
// Gavineixon
mSprite->init(destRect2, mItemTexture, mRenderer);
srcRect.x += srcRect.w;
srcRect.y = 16 * (((mCounter + 9) / 36) % 2);
mSprite->setSpriteClip(srcRect);
mSprite->render();
// Pacmar
mSprite->init(destRect3, mItemTexture, mRenderer);
srcRect.x += srcRect.w;
srcRect.y = 16 * (((mCounter + 6) / 36) % 2);
mSprite->setSpriteClip(srcRect);
mSprite->render();
// Time Stopper
mSprite->init(destRect4, mItemTexture, mRenderer);
srcRect.x += srcRect.w;
srcRect.y = 16 * (((mCounter + 3) / 36) % 2);
mSprite->setSpriteClip(srcRect);
mSprite->render();
// Coffee
mSprite->init(destRect5, mItemTexture, mRenderer);
srcRect.x += (srcRect.w * 2); // Se salta el icono del TNT
srcRect.y = 16 * (((mCounter + 0) / 36) % 2);
mSprite->setSpriteClip(srcRect);
mSprite->render();
// Cambia el destino de renderizado
SDL_SetRenderTarget(mRenderer, nullptr);
// Limpia el renderizador
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(mRenderer);
// Establece la ventana del backbuffer
if (mode == INSTRUCTIONS_MODE_AUTO)
window.y = std::max(8, SCREEN_HEIGHT - mCounter + 100);
else
window.y = 0;
// Copia el backbuffer al renderizador
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, &window);
// Dibuja el renderizador en pantalla
SDL_RenderPresent(mRenderer);
}
}

55
source/instructions.h Normal file
View File

@@ -0,0 +1,55 @@
#pragma once
#include "ifdefs.h"
#include "utils.h"
#include "const.h"
#include "sprite.h"
#include "text.h"
#include "jail_audio.h"
#ifndef INSTRUCTIONS_H
#define INSTRUCTIONS_H
// Instructions
class Instructions
{
private:
LTexture *mItemTexture; // Textura con los graficos
LTexture *mTextTexture; // Textura con los graficos
SDL_Event *mEventHandler; // Manejador de eventos
SDL_Renderer *mRenderer; // El renderizador de la ventana
SDL_Texture *mBackbuffer; // Textura para usar como backbuffer
Sprite *mSprite; // Sprite con la textura de las instrucciones
std::string *mFileList; // Lista de ficheros
std::string *mTextStrings; // Vector con los textos del juego
Text *mText; // Objeto para escribir texto
Uint16 mCounter; // Contador
section_t mSection; // Estado del bucle principal para saber si continua o se sale
Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa
Uint8 mTicksSpeed; // Velocidad a la que se repiten los bucles del programa
bool mManualQuit; // Indica si se quiere salir del modo manual
// Carga los recursos
bool loadMedia();
// Actualiza las variables
void update();
// Pinta en pantalla
void render();
// Inicializa las variables
void init();
public:
// Constructor
Instructions(SDL_Renderer *renderer, std::string *fileList, std::string *textStrings);
// Destructor
~Instructions();
// Bucle principal
void run(Uint8 mode);
};
#endif

373
source/intro.cpp Normal file
View File

@@ -0,0 +1,373 @@
#include "intro.h"
#ifdef __MIPSEL__
#include <sys/stat.h>
#include <dirent.h>
#endif
// Constructor
Intro::Intro(SDL_Renderer *renderer, std::string *fileList, std::string *textStrings)
{
// Copia los punteros
mRenderer = renderer;
mFileList = fileList;
mTextStrings = textStrings;
// Reserva memoria para los punteros
mEventHandler = new SDL_Event();
mBitmapTexture = new LTexture();
mTextTexture = new LTexture();
for (int i = 0; i < INTRO_TOTAL_BITMAPS; i++)
mBitmap[i] = new SmartSprite();
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
mText[i] = new Text2(mTextTexture, mRenderer);
}
// Destructor
Intro::~Intro()
{
delete mEventHandler;
mEventHandler = nullptr;
mBitmapTexture->unload();
delete mBitmapTexture;
mBitmapTexture = nullptr;
mTextTexture->unload();
delete mTextTexture;
mTextTexture = nullptr;
for (int i = 0; i < INTRO_TOTAL_BITMAPS; i++)
{
delete mBitmap[i];
mBitmap[i] = nullptr;
}
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
{
delete mText[i];
mText[i] = nullptr;
}
JA_DeleteMusic(mMusic);
}
// Inicializa las variables
void Intro::init()
{
// Carga los recursos
loadMedia();
mSection = {PROG_SECTION_INTRO, 0};
mTicks = 0;
mTicksSpeed = 15;
// Inicializa el vector de eventos de la intro
for (int i = 0; i < INTRO_TOTAL_EVENTS; i++)
mEvents[i] = EVENT_WAITING;
// Inicializa los bitmaps de la intro
for (int i = 0; i < INTRO_TOTAL_BITMAPS; i++)
{
mBitmap[i]->init(mBitmapTexture, mRenderer);
mBitmap[i]->setId(i);
mBitmap[i]->setIntroEvents(&mEvents[0]);
mBitmap[i]->setWidth(128);
mBitmap[i]->setHeight(96);
mBitmap[i]->setEnabled(false);
mBitmap[i]->setEnabledTimer(20);
mBitmap[i]->setDestX(SCREEN_CENTER_X - 64);
mBitmap[i]->setDestY(SCREEN_FIRST_QUARTER_Y - 24);
}
mBitmap[0]->setPosX(-128);
mBitmap[0]->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
mBitmap[0]->setVelX(0.0f);
mBitmap[0]->setVelY(0.0f);
mBitmap[0]->setAccelX(0.6f);
mBitmap[0]->setAccelY(0.0f);
mBitmap[0]->setSpriteClip(0, 0, 128, 96);
mBitmap[1]->setPosX(SCREEN_WIDTH);
mBitmap[1]->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
mBitmap[1]->setVelX(-1.0f);
mBitmap[1]->setVelY(0.0f);
mBitmap[1]->setAccelX(-0.3f);
mBitmap[1]->setAccelY(0.0f);
mBitmap[1]->setSpriteClip(128, 0, 128, 96);
mBitmap[2]->setPosX(SCREEN_CENTER_X - 64);
mBitmap[2]->setPosY(-96);
mBitmap[2]->setVelX(0.0f);
mBitmap[2]->setVelY(3.0f);
mBitmap[2]->setAccelX(0.1f);
mBitmap[2]->setAccelY(0.3f);
mBitmap[2]->setSpriteClip(0, 96, 128, 96);
mBitmap[2]->setEnabledTimer(250);
mBitmap[3]->setPosX(SCREEN_CENTER_X - 64);
mBitmap[3]->setPosY(SCREEN_HEIGHT);
mBitmap[3]->setVelX(0.0f);
mBitmap[3]->setVelY(-0.7f);
mBitmap[3]->setAccelX(0.0f);
mBitmap[3]->setAccelY(0.0f);
mBitmap[3]->setSpriteClip(128, 96, 128, 96);
mBitmap[4]->setPosX(SCREEN_CENTER_X - 64);
mBitmap[4]->setPosY(-96);
mBitmap[4]->setVelX(0.0f);
mBitmap[4]->setVelY(3.0f);
mBitmap[4]->setAccelX(0.1f);
mBitmap[4]->setAccelY(0.3f);
mBitmap[4]->setSpriteClip(0, 192, 128, 96);
mBitmap[5]->setPosX(SCREEN_WIDTH);
mBitmap[5]->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
mBitmap[5]->setVelX(-0.7f);
mBitmap[5]->setVelY(0.0f);
mBitmap[5]->setAccelX(0.0f);
mBitmap[5]->setAccelY(0.0f);
mBitmap[5]->setSpriteClip(128, 192, 128, 96);
// Inicializa los textos de la intro
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
{
mText[i]->init(TEXT_VARIABLE, 10);
mText[i]->setId(6 + i);
mText[i]->setIntroEvents(&mEvents[0]);
mText[i]->setPosX(BLOCK * 0);
mText[i]->setPosY(SCREEN_HEIGHT - (BLOCK * 6));
mText[i]->setKerning(-1);
mText[i]->setEnabled(false);
mText[i]->setEnabledTimer(180);
}
// Un dia qualsevol de l'any 2000
mText[0]->setCaption(mTextStrings[27]);
mText[0]->setWrittingSpeed(10);
// Tot esta tranquil a la UPV
mText[1]->setCaption(mTextStrings[28]);
mText[1]->setWrittingSpeed(10);
// Fins que un desaprensiu...
mText[2]->setCaption(mTextStrings[29]);
mText[2]->setWrittingSpeed(15);
// HEY! ME ANE A FERME UN CORTAET...
mText[3]->setCaption(mTextStrings[30]);
mText[3]->setWrittingSpeed(10);
// UAAAAAAAAAAAAA!!!
mText[4]->setCaption(mTextStrings[31]);
mText[4]->setWrittingSpeed(1);
// Espera un moment...
mText[5]->setCaption(mTextStrings[32]);
mText[5]->setWrittingSpeed(20);
// Si resulta que no tinc solt!
mText[6]->setCaption(mTextStrings[33]);
mText[6]->setWrittingSpeed(2);
// MERDA DE MAQUINA!
mText[7]->setCaption(mTextStrings[34]);
mText[7]->setWrittingSpeed(3);
// Blop... blop... blop...
mText[8]->setCaption(mTextStrings[35]);
mText[8]->setWrittingSpeed(20);
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
{
mText[i]->center(SCREEN_CENTER_X);
}
}
// Carga los recursos
bool Intro::loadMedia()
{
bool success = true;
// Texturas
success &= loadTextureFromFile(mBitmapTexture, mFileList[33], mRenderer);
success &= loadTextureFromFile(mTextTexture, mFileList[28], mRenderer);
// Musicas
mMusic = JA_LoadMusic(mFileList[3].c_str());
return success;
}
// Bucle principal
section_t Intro::run()
{
init();
// Si la música no está sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
// Reproduce la música
JA_PlayMusic(mMusic, 0);
}
while (mSection.name == PROG_SECTION_INTRO)
{
if (SDL_GetTicks() - mTicks > mTicksSpeed)
{
// Actualiza el contador de ticks
mTicks = SDL_GetTicks();
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(mEventHandler) != 0)
{
// Evento de salida de la aplicación
if (mEventHandler->type == SDL_QUIT)
{
mSection.name = PROG_SECTION_QUIT;
break;
}
if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN))
{
JA_StopMusic();
mSection = {PROG_SECTION_TITLE, TITLE_SECTION_1};
}
}
// Actualiza los objetos
for (int i = 0; i < INTRO_TOTAL_BITMAPS; i++)
mBitmap[i]->update();
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
mText[i]->update();
// Guión de eventos
// Primera imagen - UPV
if (mEvents[BITMAP0] == EVENT_WAITING)
{
mBitmap[0]->setEnabled(true);
mEvents[BITMAP0] = EVENT_RUNNING;
}
// Primer texto de la primera imagen
if ((mEvents[BITMAP0] == EVENT_COMPLETED) && (mEvents[TEXT0] == EVENT_WAITING))
{
mText[0]->setEnabled(true);
mEvents[TEXT0] = EVENT_RUNNING;
}
// Segundo texto de la primera imagen
if ((mEvents[TEXT0] == EVENT_COMPLETED) && (mEvents[TEXT1] == EVENT_WAITING))
{
mText[0]->setEnabled(false);
mText[1]->setEnabled(true);
mEvents[TEXT1] = EVENT_RUNNING;
}
// Tercer texto de la primera imagen
if ((mEvents[TEXT1] == EVENT_COMPLETED) && (mEvents[TEXT2] == EVENT_WAITING))
{
mText[1]->setEnabled(false);
mText[2]->setEnabled(true);
mEvents[TEXT2] = EVENT_RUNNING;
}
// Segunda imagen - Máquina
if ((mEvents[TEXT2] == EVENT_COMPLETED) && (mEvents[BITMAP1] == EVENT_WAITING))
{
mBitmap[0]->setEnabled(false);
mText[2]->setEnabled(false);
mBitmap[1]->setEnabled(true);
mEvents[BITMAP1] = EVENT_RUNNING;
}
// Primer texto de la segunda imagen
if ((mEvents[BITMAP1] == EVENT_COMPLETED) && (mEvents[TEXT3] == EVENT_WAITING))
{
mText[3]->setEnabled(true);
mEvents[TEXT3] = EVENT_RUNNING;
}
// Tercera imagen junto con primer texto - GRITO
if ((mEvents[TEXT3] == EVENT_COMPLETED) && (mEvents[BITMAP2] == EVENT_WAITING) && (mEvents[TEXT4] == EVENT_WAITING))
{
mBitmap[1]->setEnabled(false);
mText[3]->setEnabled(false);
mBitmap[2]->setEnabled(true);
mText[4]->setEnabled(true);
mEvents[BITMAP2] = EVENT_RUNNING;
mEvents[TEXT4] = EVENT_RUNNING;
}
// Cuarta imagen junto con primer texto - Reflexión
if ((mEvents[TEXT4] == EVENT_COMPLETED) && (mEvents[BITMAP3] == EVENT_WAITING) && (mEvents[TEXT5] == EVENT_WAITING))
{
mBitmap[2]->setEnabled(false);
mText[4]->setEnabled(false);
mBitmap[3]->setEnabled(true);
mText[5]->setEnabled(true);
mEvents[BITMAP3] = EVENT_RUNNING;
mEvents[TEXT5] = EVENT_RUNNING;
}
// Segundo texto de la cuarta imagen
if ((mEvents[TEXT5] == EVENT_COMPLETED) && (mEvents[TEXT6] == EVENT_WAITING))
{
mText[5]->setEnabled(false);
mText[6]->setEnabled(true);
mEvents[TEXT6] = EVENT_RUNNING;
}
// Quinta imagen - Patada
if ((mEvents[TEXT6] == EVENT_COMPLETED) && (mEvents[BITMAP4] == EVENT_WAITING))
{
mBitmap[3]->setEnabled(false);
mText[6]->setEnabled(false);
mBitmap[4]->setEnabled(true);
mEvents[BITMAP4] = EVENT_RUNNING;
}
// Primer texto de la quinta imagen
if ((mEvents[BITMAP4] == EVENT_COMPLETED) && (mEvents[TEXT7] == EVENT_WAITING))
{
mText[7]->setEnabled(true);
mEvents[TEXT7] = EVENT_RUNNING;
}
// Sexta imagen junto con texto - Globos de café
if ((mEvents[TEXT7] == EVENT_COMPLETED) && (mEvents[BITMAP5] == EVENT_WAITING) && (mEvents[TEXT8] == EVENT_WAITING))
{
mBitmap[4]->setEnabled(false);
mText[7]->setEnabled(false);
mBitmap[5]->setEnabled(true);
mText[8]->setEnabled(true);
mEvents[BITMAP5] = EVENT_RUNNING;
mEvents[TEXT8] = EVENT_RUNNING;
}
// Acaba el último texto
if (mEvents[TEXT8] == EVENT_COMPLETED)
{
mText[8]->setEnabled(false);
JA_StopMusic();
mSection = {PROG_SECTION_TITLE, TITLE_SECTION_1};
}
}
// Limpia la pantalla
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 0xFF);
SDL_RenderClear(mRenderer);
// Dibuja los objetos
for (int i = 0; i < INTRO_TOTAL_BITMAPS; i++)
mBitmap[i]->render();
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
mText[i]->render();
// Actualiza la pantalla
SDL_RenderPresent(mRenderer);
}
return mSection;
}

48
source/intro.h Normal file
View File

@@ -0,0 +1,48 @@
#pragma once
#include "ifdefs.h"
#include "const.h"
#include "utils.h"
#include "smartsprite.h"
#include "text2.h"
#include "jail_audio.h"
#ifndef INTRO_H
#define INTRO_H
// Intro
class Intro
{
private:
LTexture *mBitmapTexture; // Textura con los graficos
LTexture *mTextTexture; // Textura con los caracteres de texto
SDL_Event *mEventHandler; // Manejador de eventos
SDL_Renderer *mRenderer; // El renderizador de la ventana
std::string *mFileList; // Lista de ficheros
std::string *mTextStrings; // Vector con los textos del juego
section_t mSection; // Estado del bucle principal para saber si continua o se sale
Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa
Uint8 mTicksSpeed; // Velocidad a la que se repiten los bucles del programa
SmartSprite *mBitmap[INTRO_TOTAL_BITMAPS]; // Vector con los sprites inteligentes para los dibujos de la intro
Text2 *mText[INTRO_TOTAL_TEXTS]; // Textos de la intro
Uint8 mEvents[INTRO_TOTAL_EVENTS]; // Vector para coordinar los eventos de la intro
JA_Music mMusic; // Musica para la intro
public:
// Constructor
Intro(SDL_Renderer *renderer, std::string *fileList, std::string *textStrings);
// Destructor
~Intro();
// Inicializa las variables
void init();
// Carga los recursos
bool loadMedia();
// Bucle principal
section_t run();
};
#endif

View File

@@ -5,14 +5,14 @@
Item::Item()
{
mSprite = new AnimatedSprite();
init(NO_KIND, 0, 0, nullptr, nullptr);
mClass = NO_KIND;
}
// Destructor
Item::~Item()
{
init(NO_KIND, 0, 0, nullptr, nullptr);
delete mSprite;
mSprite = nullptr;
}
// Iniciador
@@ -29,6 +29,7 @@ void Item::init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer *
mVelY = -4.0f;
mAccelX = 0.0f;
mAccelY = 0.2f;
mStatus = 0;
mCollider.r = mWidth / 2;
shiftColliders();
@@ -54,30 +55,49 @@ void Item::init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer *
mVelX = 0;
mVelY = 0;
break;
case ITEM_POINTS_1_DISK:
mSprite->setAnimationFrames(0, 0, 16 * 0, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 0, 16 * 1, mWidth, mHeight);
break;
case ITEM_POINTS_2_GAVINA:
mSprite->setAnimationFrames(0, 0, 16 * 1, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 1, 16 * 1, mWidth, mHeight);
break;
case ITEM_POINTS_3_PACMAR:
mSprite->setAnimationFrames(0, 0, 16 * 2, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 2, 16 * 1, mWidth, mHeight);
break;
case ITEM_CLOCK:
mSprite->setAnimationFrames(0, 0, 16 * 3, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 3, 16 * 1, mWidth, mHeight);
break;
case ITEM_TNT:
mSprite->setAnimationFrames(0, 0, 16 * 4, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 4, 16 * 1, mWidth, mHeight);
break;
case ITEM_COFFEE:
mSprite->setAnimationFrames(0, 0, 16 * 5, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 5, 16 * 1, mWidth, mHeight);
break;
case ITEM_COFFEE_MACHINE:
mWidth = 32;
mHeight = 32;
//mPosX = (rand() % (PLAY_AREA_WIDTH - mWidth - 3)) + 3;
mPosX = (((int)x + (PLAY_AREA_WIDTH / 2)) % (PLAY_AREA_WIDTH - mWidth));
mPosY = PLAY_AREA_TOP - mHeight;
mVelX = 0.0f;
mVelY = -2.0f;
mSprite->setAnimationNumFrames(0, 4);
mSprite->setAnimationFrames(0, 0, 32 * 0, 16 * 2, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 32 * 1, 16 * 2, mWidth, mHeight);
mSprite->setAnimationFrames(0, 2, 32 * 2, 16 * 2, mWidth, mHeight);
mSprite->setAnimationFrames(0, 3, 32 * 3, 16 * 2, mWidth, mHeight);
mCollider.r = mWidth / 2;
shiftColliders();
break;
default:
break;
}
@@ -124,6 +144,8 @@ void Item::render()
// Actualiza la posición y estados del globo
void Item::move()
{
mStatus = 0;
// Calcula la nueva posición
mPosX += mVelX;
mPosY += mVelY;
@@ -164,6 +186,7 @@ void Item::move()
mAccelX = 0;
mAccelY = 0;
mPosY = PLAY_AREA_BOTTOM - mHeight;
if (mClass == ITEM_COFFEE_MACHINE) mStatus = 1;
}
// Actualiza la posición del sprite
@@ -178,7 +201,7 @@ void Item::erase()
}
// Actualiza el objeto a su posicion, animación y controla los contadores
void Item::update()
int Item::update()
{
if (mEnabled)
{
@@ -188,6 +211,8 @@ void Item::update()
updateTimeToLive();
checkTimeToLive();
}
return mStatus;
}
// Actualiza el contador
@@ -195,7 +220,7 @@ void Item::updateTimeToLive()
{
if (mTimeToLive > 0)
{
--mTimeToLive;
mTimeToLive--;
}
}
@@ -203,9 +228,7 @@ void Item::updateTimeToLive()
void Item::checkTimeToLive()
{
if (mTimeToLive == 0)
{
erase();
}
}
// Obtiene del valor de la variable

View File

@@ -9,6 +9,26 @@
// Clase AnimatedSprite
class Item
{
private:
float mPosX; // Posición X del objeto
float mPosY; // Posición Y del objeto
Uint8 mWidth; // Ancho del objeto
Uint8 mHeight; // Alto del objeto
float mVelX; // Velocidad en el eje X
float mVelY; // Velocidad en el eje Y
float mAccelX; // Aceleración en el eje X
float mAccelY; // Aceleración en el eje Y
int mStatus; // Contiene mensajes de estado
AnimatedSprite *mSprite; // Sprite con los graficos del objeto
Uint8 mClass; // Especifica el tipo de objeto que es
bool mEnabled; // Especifica si el objeto está habilitado
circle_t mCollider; // Circulo de colisión del objeto
// Alinea el circulo de colisión con la posición del objeto
void shiftColliders();
public:
// Constructor
Item();
@@ -17,7 +37,7 @@ public:
~Item();
// Iniciador
void init(Uint8 value, float x, float y, LTexture* texture, SDL_Renderer *renderer);
void init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer *renderer);
// Centra el objeto en la posición X
void allignTo(int x);
@@ -32,7 +52,7 @@ public:
void erase();
// Actualiza al objeto a su posicion, animación y controla los contadores
void update();
int update();
// Actualiza el contador
void updateTimeToLive();
@@ -64,40 +84,8 @@ public:
// Obtiene el circulo de colisión
circle_t &getCollider();
// Temporizador con el tiempo que el objeto está presente
// Temporizador con el tiempo que el objeto está presente
Uint16 mTimeToLive;
private:
// Posición X,Y del objeto
float mPosX;
float mPosY;
// Alto y ancho del objeto
Uint8 mWidth;
Uint8 mHeight;
// Variables para controlar la velocidad del objeto
float mVelX;
float mVelY;
// Aceleración
float mAccelX;
float mAccelY;
// Sprite con los graficos del objeto
AnimatedSprite *mSprite;
// Especifica el tipo de objeto que es
Uint8 mClass;
// Especifica si está habilitado el objeto
bool mEnabled;
// Circulo de colisión del objeto
circle_t mCollider;
// Alinea el circulo de colisión con la posición del objeto
void shiftColliders();
};
#endif

View File

@@ -1,6 +1,6 @@
#ifndef __MIPSEL__
#include "jail_audio.h"
#include "stb_vorbis.c"
//#include <SDL2/SDL.h>
#define JA_MAX_SIMULTANEOUS_CHANNELS 5
@@ -210,4 +210,4 @@ JA_Channel_state JA_GetChannelState(const int channel) {
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
return channels[channel].state;
}
#endif

View File

@@ -0,0 +1,106 @@
#ifdef __MIPSEL__
#include "jail_audio.h"
#include "SDL_mixer.h"
struct JA_Sound_t {
Mix_Chunk *mix_chunk;
};
struct JA_Music_t {
Mix_Music* mix_music;
};
JA_Music current_music{NULL};
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) {
Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024);
Mix_AllocateChannels(8);
}
JA_Music JA_LoadMusic(const char* filename) {
int chan, samplerate;
JA_Music music = new JA_Music_t();
music->mix_music = Mix_LoadMUS(filename);
return music;
}
void JA_PlayMusic(JA_Music music, const int loop) {
if (current_music == music) return;
if (current_music != NULL) {
Mix_HaltMusic();
}
current_music = music;
Mix_PlayMusic(music->mix_music, loop);
}
void JA_PauseMusic() {
Mix_PauseMusic();
}
void JA_ResumeMusic() {
Mix_ResumeMusic();
}
void JA_StopMusic() {
Mix_HaltMusic();
}
JA_Music_state JA_GetMusicState() {
if (current_music == NULL) return JA_MUSIC_INVALID;
if (Mix_PausedMusic()) {
return JA_MUSIC_PAUSED;
} else if (Mix_PlayingMusic()) {
return JA_MUSIC_PLAYING;
} else {
return JA_MUSIC_STOPPED;
}
}
void JA_DeleteMusic(JA_Music music) {
if (current_music == music) {
Mix_HaltMusic();
current_music = NULL;
}
Mix_FreeMusic(music->mix_music);
delete music;
}
JA_Sound JA_LoadSound(const char* filename) {
JA_Sound sound = new JA_Sound_t();
sound->mix_chunk = Mix_LoadWAV(filename);
return sound;
}
int JA_PlaySound(JA_Sound sound, const int loop) {
int channel = Mix_PlayChannel(-1, sound->mix_chunk, loop);
return channel;
}
void JA_DeleteSound(JA_Sound sound) {
Mix_FreeChunk(sound->mix_chunk);
delete sound;
}
void JA_PauseChannel(const int channel) {
Mix_Pause(channel);
}
void JA_ResumeChannel(const int channel) {
Mix_Resume(channel);
}
void JA_StopChannel(const int channel) {
Mix_HaltChannel(channel);
}
JA_Channel_state JA_GetChannelState(const int channel) {
if (Mix_Paused(channel)) {
return JA_CHANNEL_PAUSED;
} else if (Mix_Playing(channel)) {
return JA_CHANNEL_PLAYING;
} else {
return JA_CHANNEL_FREE;
}
}
#endif

10
source/lang.cpp Normal file
View File

@@ -0,0 +1,10 @@
#include "lang.h"
// Inicializa los textos del juego en el idioma seleccionado
void initTextStrings(std::string *textStrings, Uint8 lang)
{
if ((lang < 0) || (lang > MAX_LANGUAGES))
lang = en_UK;
for (int i = 0; i < MAX_TEXT_STRINGS; i++)
textStrings[i] = gTextStrings[i][lang].c_str();
}

287
source/lang.h Normal file
View File

@@ -0,0 +1,287 @@
#pragma once
#include "ifdefs.h"
#include <string>
#ifndef LANG_H
#define LANG_H
// iso codes
#define es_ES 0
#define ba_BA 1
#define en_UK 2
#define MAX_LANGUAGES 3
// Textos
#define MAX_TEXT_STRINGS 100
const std::string gTextStrings[MAX_TEXT_STRINGS][3] =
{
// 0 - TITULO E INSTRUCCIONES
{"JUGAR",
"JUGAR",
"PLAY"},
// 1
{"OPCIONES",
"OPCIONS",
"OPTIONS"},
// 2
{"INSTRUCCIONES",
"INSTRUCCIONS",
"HOW TO PLAY"},
// 3
{"SALIR",
"EIXIR",
"QUIT"},
// 4
{"VENTANA",
"FINESTRA",
"WINDOW"},
// 5
{"PANTALLA COMPLETA",
"PANTALLA COMPLETA",
"FULLSCREEN"},
// 6
{"PANTALLA COMPLETA FALSA",
"PANTALLA COMPLETA FALSA",
"FAKE FULLSCREEN"},
// 7
{"TAMA^O DE VENTANA",
"TAMANY DE FINESTRA",
"WINDOW SIZE"},
// 8
{"IDIOMA",
"IDIOMA",
"LANGUAGE"},
// 9
{"[ACEPTAR]",
"[ACEPTAR]",
"[ACCEPT]"},
// 10
{"[CANCELAR]",
"[CANCELAR]",
"[CANCEL]"},
// 11
{"OBJETIVO",
"OBJECTIU",
"OBJECTIVE"},
// 12
{"TIENES QUE EXPLOTAR",
"HAS D'EXPLOTAR",
"YOU HAVE TO POP AS MANY"},
// 13
{"TANTOS GLOBOS COMO PUEDAS",
"TANTS GLOBUS COM PUGUES",
"BALLOONS AS YOU CAN"},
// 14
{"LA DIFICULTAD SE INCREMENTA",
"LA DIFICULTAT AUGMENTA",
"DIFFICULTY WILL BE INCREASED"},
// 15
{"A MEDIDA QUE VAS PUNTUANDO",
"A MESURA QUE VAS PUNTUANT",
"AS YOU SCORE POINTS"},
// 16
{"OBJETOS",
"OBJECTES",
"ITEMS"},
// 17
{"1.000 PUNTOS",
"1.000 PUNTS",
"1.000 POINTS"},
// 18
{"2.500 PUNTOS",
"2.500 PUNTS",
"2.500 POINTS"},
// 19
{"5.000 PUNTOS",
"5.000 PUNTS",
"5.000 POINTS"},
// 20
{"DETIENE EL TIEMPO",
"PARA EL TEMPS",
"TIME STOPPER"},
// 21
{"VIDA EXTRA",
"VIDA EXTRA",
"EXTRA HIT"},
// 22
{"PULSA UNA TECLA PARA VOLVER",
"PREM UNA TECLA PER A TORNAR",
"PRESS ANY KEY TO RETURN"},
// 23
{"PULSA CUALQUIER TECLA",
"PREM QUALSEVOL TECLA",
"PRESS ANY KEY"},
// 24
{"ESPA^OL",
"ESPA^OL (ESPANYOL)",
"ESPA^OL (SPANISH)"},
// 25
{"BALOONCIA (VALENCIANO)",
"BALOONCIA",
"BALOONCIA (VALENCIAN)"},
// 26
{"ENGLISH (INGLES)",
"ENGLISH (ANGLES)",
"ENGLISH"},
// 27 - INTRO
{"Un dia cualquiera del a^o 2000",
"Un dia qualsevol de l'any 2000",
"Any day of the year 2000"},
// 28
{"Todo esta tranquilo en la UPV",
"Tot esta tranquil a la UPV",
"Everything is quiet at the UPV"},
// 29
{"Hasta que un desaprensivo...",
"Fins que un desaprensiu...",
"Until a bastard arrives..."},
// 30
{"HEY! VOY A SACARME UN TALLADET...",
"HEY! ME ANE A FERME UN CORTAET...",
" YO! GONNA TAKE A CAFELITO... "},
// 31
{"UAAAAAAAAAAAAA!!!",
"UAAAAAAAAAAAAA!!!",
"AAAAAAAARGHHHH!!!"},
// 32
{"Espera un momento...",
"Espera un moment...",
"Wait a moment..."},
// 33
{"Si no llevo suelto encima!",
"Si resulta que no tinc solt!",
" I don't have any loose! "},
// 34
{"MIERDA DE MAQUINA!",
"MERDA DE MAQUINA!",
"FUCKING MACHINE!"},
// 35
{"Blop... blop... blop...",
"Blop... blop... blop...",
"Blop... blop... blop..."},
// 36 - TEXTOS DEL JUEGO
{"Tiempo: ",
"Temps detes: ",
"Time Stopped: "},
// 37
{"D E M O",
"D E M O",
"D E M O"},
// 38
{"FASE ",
"PANTALLA ",
"STAGE "},
// 39 - MARCADOR
{"PUNTOS",
"PUNTS",
"SCORE"},
// 40
{"MAX.PUNT.",
"MAX.PUNT.",
"HI-SCORE"},
// 41
{"MULT",
"MULT",
"MULT"},
// 42
{"FASE ",
"PANTALLA ",
"STAGE "},
// 43 - PANTALLA DE GAME OVER
{"FIN DE JUEGO",
"FI DEL JOC",
"GAME OVER"},
// 44
{"TU PUNTUACION: ",
"ELS TEUS PUNTS: ",
"YOUR SCORE: "},
// 45
{"REINTENTAR?",
"REINTENTAR?",
"RETRY?"},
// 46 - MENU DE PAUSA
{"CONTINUAR",
"CONTINUAR",
"CONTINUE"},
// 47
{"SALIR DEL JUEGO ",
"EIXIR DEL JOC",
"LEAVE GAME"},
// 48 - MENU GAME OVER
{"SI",
"SI",
"YES"},
// 49
{"NO",
"NO",
"NO"},
// 50 - TEXTO DE COMPLETAR EL JUEGO
{"FELICIDADES!!",
"FELICITATS!!",
"NICE!!"},
// 51 - MENU DEL TITULO (1 JUGADOR)
{"1 JUGADOR",
"1 JUGADOR",
"1 PLAYER"},
// 52 - MENU DEL TITULO (2 JUGADORES)
{"2 JUGADORES",
"2 JUGADORS",
"2 PLAYERS"},
};
void initTextStrings(std::string *textStrings, Uint8 lang);
#endif

151
source/logo.cpp Normal file
View File

@@ -0,0 +1,151 @@
#include "logo.h"
#ifdef __MIPSEL__
#include <sys/stat.h>
#include <dirent.h>
#endif
// Constructor
Logo::Logo(SDL_Renderer *renderer, std::string *fileList)
{
// Copia la dirección del renderizador
mRenderer = renderer;
// Copia la dirección del la lista de ficheros
mFileList = fileList;
// Reserva memoria para los punteros
mEventHandler = new SDL_Event();
mTexture = new LTexture();
mSprite = new Sprite();
// Crea un backbuffer para el renderizador
mBackbuffer = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT);
if (mBackbuffer == NULL)
printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError());
}
// Destructor
Logo::~Logo()
{
mTexture->unload();
delete mTexture;
mTexture = nullptr;
delete mSprite;
mSprite = nullptr;
delete mEventHandler;
mEventHandler = nullptr;
SDL_DestroyTexture(mBackbuffer);
mBackbuffer = nullptr;
}
// Inicializa las variables necesarias para la sección 'Logo'
void Logo::init()
{
// Carga los recursos
loadMedia();
// Inicializa variables
mCounter = 0;
mSection.name = PROG_SECTION_LOGO;
mSection.subsection = 0;
mSprite->init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mTexture, mRenderer);
mTicks = 0;
mTicksSpeed = 15;
}
// Carga los recursos necesarios para la sección 'Logo'
bool Logo::loadMedia()
{
bool success = true;
success &= loadTextureFromFile(mTexture, mFileList[35], mRenderer);
return success;
}
// Bucle para el logo del juego
section_t Logo::run()
{
init();
const SDL_Rect rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
while (mSection.name == PROG_SECTION_LOGO)
{
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(mEventHandler) != 0)
{
// Evento de salida de la aplicación
if (mEventHandler->type == SDL_QUIT)
{
mSection.name = PROG_SECTION_QUIT;
break;
}
// Cualquier tecla pulsada
if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN))
{
mSection.name = PROG_SECTION_TITLE;
mSection.subsection = TITLE_SECTION_1;
}
}
// Cambia el destino donde se pinta todo
//SDL_SetRenderTarget(mRenderer, mBackbuffer);
// Limpia el destino
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(mRenderer);
// Dibuja los objetos
mSprite->render();
// Dibuja el fade
if (mCounter >= 200)
{
Uint16 alpha = mCounter - 200;
if (alpha < 256)
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, alpha);
else
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255); // alpha - 0 trans, 255 opaco
SDL_RenderFillRect(mRenderer, &rect);
}
// Vuelve a usar el renderizador como destino
//SDL_SetRenderTarget(mRenderer, NULL);
// Copia el backbufer al renderizador
//SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
// Actualiza la pantalla
SDL_RenderPresent(mRenderer);
// Comprueba si ha terminado el logo
if (SDL_GetTicks() - mTicks > mTicksSpeed)
{
// Actualiza el contador de ticks
mTicks = SDL_GetTicks();
if (mCounter == 0)
{
if (JA_GetMusicState() == JA_MUSIC_PLAYING)
JA_StopMusic();
}
if (mCounter == 500) // minimo 200 + 255
{
mCounter = 0;
mSection.name = PROG_SECTION_INTRO;
mSection.subsection = 0;
}
else
{
mCounter++;
}
}
}
return mSection;
}

44
source/logo.h Normal file
View File

@@ -0,0 +1,44 @@
#pragma once
#include "ifdefs.h"
#include "const.h"
#include "utils.h"
#include "sprite.h"
#include "jail_audio.h"
#ifndef LOGO_H
#define LOGO_H
// Logo
class Logo
{
private:
LTexture *mTexture; // Textura con los graficos
SDL_Event *mEventHandler; // Manejador de eventos
SDL_Renderer *mRenderer; // El renderizador de la ventana
SDL_Texture *mBackbuffer; // Textura para usar como backbuffer
Sprite *mSprite; // Sprite con la textura del logo
std::string *mFileList; // Lista de ficheros
Uint16 mCounter; // Contador
section_t mSection; // Estado del bucle principal para saber si continua o se sale
Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa
Uint8 mTicksSpeed; // Velocidad a la que se repiten los bucles del programa
public:
// Constructor
Logo(SDL_Renderer *renderer, std::string *fileList);
// Destructor
~Logo();
// Inicializa las variables
void init();
// Carga los recursos
bool loadMedia();
// Bucle principal
section_t run();
};
#endif

View File

@@ -1,5 +1,3 @@
#include <stdio.h>
#include <string>
#include "const.h"
#include "ltexture.h"
#define STB_IMAGE_IMPLEMENTATION

View File

@@ -1,9 +1,7 @@
/*
This source code copyrighted by JailDesigner (2020)
started on Castalla 15-07-2020.
*/
Código fuente creado por JailDesigner (2020)
Empezado en Castalla el 15/07/2020.
/*
Descripción del enfoque utilizado para crear el juego.
El programa contine una serie de clases/objetos básicos: la clase sprite
@@ -17,11 +15,11 @@ A continuación tenemos las clases enfocadas a la lógica del juego, la clase pl
contiene la información del jugador, la clase balloon la de los enemigos y la
clase bullet para las balas que dispara el jugador. La clase background es
muy simple y sirve para pintar el fondo de la pantalla. Por ultimo, la clase
gamedirector es la que realiza toda la lógica y se encarga de hacer interactuar
mDirector es la que realiza toda la lógica y se encarga de hacer interactuar
al resto de objetos entre si.
El objeto gamedirector tiene tres estados: titulo, juego y pausa. Segun su estado
el bucle que recorre es distinto. En el bucle juego, el objeto gamedirector
El objeto mDirector tiene tres estados: titulo, juego y pausa. Segun su estado
el bucle que recorre es distinto. En el bucle juego, el objeto mDirector
tiene un objeto jugador, un vector con los objetos globo y un vector con los
objetos bala. Se encarga de comprobar las entradas de teclado o gamepad para
cerrar la aplicacion, saltar al estado de pausa y para mover al jugador. Recorre
@@ -36,45 +34,26 @@ En los vectores que contienen objetos, se considera activos los objetos que tien
un tipo asociado diferente a NO_KIND
*/
#include "ifdefs.h"
#include "const.h"
#include "gamedirector.h"
#include <time.h>
#include "director.h"
#include <stdio.h>
#include <string>
int main(int argc, char *args[])
{
// Inicia el generador de numeros aleatorios
srand(time(nullptr));
//srand(time(nullptr));
std::srand(static_cast<unsigned int>(SDL_GetTicks()));
// Crea el objeto gameDirector
GameDirector *gameDirector = new GameDirector(args[0]);
// Crea el objeto mDirector
Director *mDirector = new Director(args[0]);
printf("Starting the game...\n\n");
// Mientras no se quiera salir del juego
while (!(gameDirector->exit()))
{
switch (gameDirector->getProgSection())
{
case PROG_SECTION_LOGO:
gameDirector->runLogo();
break;
case PROG_SECTION_INTRO:
gameDirector->runIntro();
break;
case PROG_SECTION_TITLE:
gameDirector->runTitle(gameDirector->getSubsection());
break;
case PROG_SECTION_GAME:
gameDirector->runGame();
break;
}
}
// Bucle principal
mDirector->run();
// Libera todos los recursos y cierra SDL
delete gameDirector;
gameDirector = nullptr;
delete mDirector;
mDirector = nullptr;
printf("Shutting down the game...\n");
return 0;

View File

@@ -1,23 +1,28 @@
#include "ifdefs.h"
#include "const.h"
#include "text.h"
#include "menu.h"
// Constructor
Menu::Menu()
Menu::Menu(SDL_Renderer *renderer, Text *text, Input *input, std::string *fileList)
{
init("", 0, 0, 0, nullptr, nullptr, nullptr);
mRenderer = renderer;
mText = text;
mInput = input;
mFileList = fileList;
}
Menu::~Menu()
{
mRenderer = nullptr;
mText = nullptr;
mInput = nullptr;
mFileList = nullptr;
}
// Inicializador
void Menu::init(std::string name, int x, int y, int backgroundType, LTexture *texture, SDL_Renderer *renderer, Text *text)
void Menu::init(std::string name, int x, int y, int backgroundType)
{
loadMedia();
// Inicia variables
mName = name;
mSelector.index = 0;
@@ -42,8 +47,6 @@ void Menu::init(std::string name, int x, int y, int backgroundType, LTexture *te
mSelector.b = 0;
mSelector.a = 255;
mBackgroundType = backgroundType;
mText = text;
mRenderer = renderer;
mIsCentered = false;
mAreElementsCentered = false;
mCenter = x + ((SCREEN_WIDTH - x) / 2);
@@ -82,6 +85,20 @@ void Menu::init(std::string name, int x, int y, int backgroundType, LTexture *te
//moveSelectorSprite(mSelector.index);
}
// Carga los recursos necesarios para la sección 'Title'
bool Menu::loadMedia()
{
// Indicador de éxito en la carga
bool success = true;
// Sonidos
mSoundMove = JA_LoadSound(mFileList[17].c_str());
mSoundAccept = JA_LoadSound(mFileList[18].c_str());
mSoundCancel = JA_LoadSound(mFileList[16].c_str());
return success;
}
// Obtiene el nombre del menu
std::string Menu::getName()
{
@@ -91,7 +108,9 @@ std::string Menu::getName()
// Obtiene el valor de la variable
Uint8 Menu::getItemSelected()
{
return mItemSelected;
const int temp = mItemSelected;
mItemSelected = MENU_NO_OPTION;
return temp;
}
// Mueve el grafico del selector al elemento seleccionado
@@ -159,7 +178,7 @@ Uint16 Menu::getWidestItem()
Uint16 result = 0;
// Obtenemos la anchura del item mas ancho
for (Uint8 i = 0; i < mTotalItems; i++)
for (int i = 0; i < mTotalItems; i++)
{
if (mItem[i].w > result)
{
@@ -232,30 +251,6 @@ bool Menu::decreaseSelectorIndex()
return success;
}
// Comprueba la entrada (teclado, gamepad) y actua en consecuencia
bool Menu::checkInput(Uint8 input)
{
bool success = false;
switch (input)
{
case INPUT_UP:
success = decreaseSelectorIndex();
//moveSelectorSprite(mSelector.index);
break;
case INPUT_DOWN:
success = increaseSelectorIndex();
//moveSelectorSprite(mSelector.index);
break;
case INPUT_ACCEPT:
mItemSelected = mSelector.index;
break;
case INPUT_CANCEL:
mItemSelected = mDefaultActionWhenCancel;
break;
}
return success;
}
// Actualiza la logica del menu
void Menu::update()
{
@@ -276,15 +271,23 @@ void Menu::render()
SDL_SetRenderDrawColor(mRenderer, mSelector.r, mSelector.g, mSelector.b, mSelector.a);
SDL_RenderFillRect(mRenderer, &mSelector.rect);
// Renderiza el borde del fondo
if (mBackgroundType == MENU_BACKGROUND_SOLID)
{
SDL_SetRenderDrawColor(mRenderer, mRectBG.r, mRectBG.g, mRectBG.b, 255);
SDL_RenderDrawRect(mRenderer, &mRectBG.rect);
}
// Renderiza el sprite del selector
//mSelectorSprite.render();
// Renderitza el text
for (Uint8 i = 0; i < mTotalItems; i++)
for (int i = 0; i < mTotalItems; i++)
{
if (i == mSelector.index)
{
mText->writeColored(mItem[i].x, mItem[i].y, mItem[i].label, mSelector.itemR, mSelector.itemG, mSelector.itemB);
const color_t color = {mSelector.itemR, mSelector.itemG, mSelector.itemB};
mText->writeColored(mItem[i].x, mItem[i].y, mItem[i].label, color);
}
else
{
@@ -378,7 +381,7 @@ void Menu::centerMenu(int value)
mPosX = (value) - (mWidestItem / 2);
// Reposiciona los elementos del menu
for (Uint8 i = 0; i < 10; i++)
for (int i = 0; i < 10; i++)
{
mItem[i].x = mPosX;
}
@@ -397,7 +400,7 @@ void Menu::centerMenuElements()
{
mAreElementsCentered = true;
for (Uint8 i = 0; i < mTotalItems; i++)
for (int i = 0; i < mTotalItems; i++)
{
//mItem[i].x = (mCenter - ((mText->lenght(mItem[i].label, 0)) / 2));
mItem[i].x = (mCenter - (mItem[i].w / 2));
@@ -453,3 +456,31 @@ void Menu::setDefaultActionWhenCancel(Uint8 item)
{
mDefaultActionWhenCancel = item;
}
// Gestiona la entrada de teclado y mando durante el menu
void Menu::checkInput()
{
if (mInput->checkInput(INPUT_UP, REPEAT_FALSE))
{
if (decreaseSelectorIndex())
JA_PlaySound(mSoundMove);
}
if (mInput->checkInput(INPUT_DOWN, REPEAT_FALSE))
{
if (increaseSelectorIndex())
JA_PlaySound(mSoundMove);
}
if (mInput->checkInput(INPUT_ACCEPT, REPEAT_FALSE))
{
mItemSelected = mSelector.index;
JA_PlaySound(mSoundAccept);
}
if (mInput->checkInput(INPUT_CANCEL, REPEAT_FALSE))
{
mItemSelected = mDefaultActionWhenCancel;
JA_PlaySound(mSoundCancel);
}
}

View File

@@ -1,6 +1,9 @@
#pragma once
#include "ifdefs.h"
#include "sprite.h"
#include "text.h"
#include "input.h"
#include "jail_audio.h"
#ifndef MENU_H
#define MENU_H
@@ -8,62 +11,73 @@
// Clase menu
class Menu
{
public:
// Constructor
Menu();
// Destructor
~Menu();
// Inicializador
void init(std::string name, int x, int y, int backgroundType, LTexture *texture, SDL_Renderer *renderer, Text *text);
// Obtiene el nombre del menu
std::string getName();
// Obtiene el valor de la variable
Uint8 getItemSelected();
// Deja el menu apuntando al primer elemento
void reset();
// Deja el menu sin elemento seleccionado
void deselectItem();
// Comprueba la entrada (teclado, gamepad) y actua en consecuencia
bool checkInput(Uint8 input);
// Actualiza la logica del menu
void update();
// Pinta el menu en pantalla
void render();
// Establece el color del rectangulo de fondo
void setBackgroundColor(int r, int g, int b, int alpha);
// Establece el color del rectangulo del selector
void setSelectorColor(int r, int g, int b, int alpha);
// Establece el color del texto del selector
void setSelectorTextColor(int r, int g, int b);
// Centra el menu respecto a un punto
void centerMenu(int value);
// Centra los elementos del menu
void centerMenuElements();
// Añade un item al menu
void addItem(std::string text, const Uint8 hPaddingUp = 0, const Uint8 hPaddingDown = 0);
// Cambia el texto de un item
void setItemCaption(Uint8 index, std::string text);
// Establece el indice del item que se usará por defecto al cancelar el menu
void setDefaultActionWhenCancel(Uint8 item);
private:
int mPosX; // Posición en el eje X de la primera letra del primer elemento
int mPosY; // Posición en el eje Y de la primera letra del primer elemento
std::string mName; // Nombre del menu
Uint8 mTotalItems; // Numero total de items del menu
int mItemSelected; // Índice del item del menu que ha sido seleccionado
Uint8 mDefaultActionWhenCancel; // Indice del item del menu que se selecciona cuando se cancela el menu
Uint8 mVerticalPadding; // Espacio de separacion entre items
Uint8 mBackgroundType; // Tipo de fondo para el menu
Sprite *mSelectorSprite; // Sprite con los graficos del selector
Text *mText; // Texto para poder escribir los items del menu
SDL_Renderer *mRenderer; // Puntero al renderizador de la ventana
std::string *mFileList; // Lista de ficheros
bool mIsCentered; // Variable para saber si el menu debe estar centrado respecto a un punto
int mCenter; // Centro del menu
bool mAreElementsCentered; // Variable para saber si los elementos van centrados
Uint16 mWidestItem; // Anchura del elemento más ancho
JA_Sound mSoundAccept; // Sonido al aceptar o elegir una opción del menu
JA_Sound mSoundCancel; // Sonido al cancelar el menu
JA_Sound mSoundMove; // Sonido al mover el selector
Input *mInput; // Gestor de eventos de entrada de teclado o gamepad
struct rectangle
{
SDL_Rect rect; // Rectangulo
Uint8 r; // Rojo
Uint8 g; // Verde
Uint8 b; // Azul
Uint8 a; // Transparencia
};
rectangle mRectBG; // Rectangulo de fondo del menu
struct item
{
std::string label; // Texto
int x; // Posición en el eje X de la primera letra del elemento
int y; // Posición en el eje Y de la primera letra del elemento
Uint8 w; // Ancho del elemento
Uint8 h; // Alto del elemento
Uint8 hPaddingUp; // Espaciado sobre el elemento
Uint8 hPaddingDown; // Espaciado bajo el elemento
};
item mItem[10]; // Estructura para cada elemento del menu
struct selector
{
double origin; // Coordenada de origen
double target; // Coordenada de destino
double y; // Coordenada actual
Uint8 numJumps; // Numero de pasos preestablecido para llegar al destino
double despY; // Cantidad de pixeles que se desplaza el selector en cada salto: (target - origin) / numJumps
bool moving; // Indica si el selector está avanzando hacia el destino
Uint8 index; // Elemento del menu que tiene el foco
SDL_Rect rect; // Rectangulo del selector
Uint8 r; // Cantidad de color rojo para el rectangulo del selector
Uint8 g; // Cantidad de color verde para el rectangulo del selector
Uint8 b; // Cantidad de color azul para el rectangulo del selector
Uint8 a; // Cantidad de transparencia para el rectangulo del selector
Uint8 itemR; // Cantidad de color rojo para el texto del elemento seleccionado
Uint8 itemG; // Cantidad de color verde para el texto del elemento seleccionado
Uint8 itemB; // Cantidad de color azul para el texto del elemento seleccionado
};
selector mSelector; // Variables para pintar el selector del menu
// Carga los recursos necesarios para la sección 'Title'
bool loadMedia();
// Establece el valor de la variable
void setTotalItems(int num);
@@ -91,100 +105,69 @@ private:
// Establece el destino del selector
void setSelectorTarget(int value);
// Coloca el selector en una posición específica
void setSelectorPos(Uint8 index);
// Obtiene la anchura del elemento más ancho del menu
Uint16 getWidestItem();
// Posicion X/Y del texto del primer elemento del menu
int mPosX; // En esta posición se pinta la primera letra del primer elemento
int mPosY;
// Gestiona la entrada de teclado y mando durante el menu
void checkMenuInput(Menu *menu);
// Nombre del menu
std::string mName;
public:
// Constructor
Menu(SDL_Renderer *renderer, Text *text, Input *input, std::string *fileList);
// Numero de items del menu
Uint8 mTotalItems;
// Destructor
~Menu();
// Item del menu que ha sido seleccionado
Uint8 mItemSelected;
// Inicializador
void init(std::string name, int x, int y, int backgroundType);
// Item del menu seleccionado cuando se cancela el menu
Uint8 mDefaultActionWhenCancel;
// Obtiene el nombre del menu
std::string getName();
// Espacio de separacion entre items
Uint8 mVerticalPadding;
// Obtiene el valor de la variable
Uint8 getItemSelected();
// Tipo de fondo para el menu
Uint8 mBackgroundType;
// Deja el menu apuntando al primer elemento
void reset();
// Sprite con los graficos del selector
//Sprite mSelectorSprite;
// Deja el menu sin elemento seleccionado
void deselectItem();
struct rectangle
{
SDL_Rect rect;
Uint8 r; // Rojo
Uint8 g; // Verde
Uint8 b; // Azul
Uint8 a; // Transparencia
};
// Gestiona la entrada de teclado y mando durante el menu
void checkInput();
rectangle mRectBG; // Rectangulo de fondo del menu
// Actualiza la logica del menu
void update();
// Estructura para cada elemento del menu
struct item
{
std::string label;
int x;
int y;
Uint8 w;
Uint8 h;
Uint8 hPaddingUp;
Uint8 hPaddingDown;
};
// Pinta el menu en pantalla
void render();
item mItem[10];
// Establece el color del rectangulo de fondo
void setBackgroundColor(int r, int g, int b, int alpha);
// Texto para poder escribir los items del menu
Text *mText;
// Establece el color del rectangulo del selector
void setSelectorColor(int r, int g, int b, int alpha);
// Puntero al renderizador de la ventana
SDL_Renderer *mRenderer;
// Establece el color del texto del selector
void setSelectorTextColor(int r, int g, int b);
// Variable para saber si el menu debe estar centrado respecto a un punto
bool mIsCentered;
// Centra el menu respecto a un punto
void centerMenu(int value);
// Centro del menu
int mCenter;
// Centra los elementos del menu
void centerMenuElements();
// Variable para saber si los elementos van centrados
bool mAreElementsCentered;
// Añade un item al menu
void addItem(std::string text, const Uint8 hPaddingUp = 0, const Uint8 hPaddingDown = 0);
// Anchura del elemento más ancho
Uint16 mWidestItem;
// Cambia el texto de un item
void setItemCaption(Uint8 index, std::string text);
struct selector
{
double origin; // Coordenada de origen
double target; // Coordenada de destino
double y; // Coordenada actual
Uint8 numJumps; // Numero de pasos preestablecido para llegar al destino
double despY; // (target - origin) / numJumps
bool moving; // Indica si el selector está avanzando hacia el destino
Uint8 index; // Elemento del menu que tiene el foco
SDL_Rect rect;
Uint8 r; // Rojo
Uint8 g; // Verde
Uint8 b; // Azul
Uint8 a; // Transparencia
Uint8 itemR; // Rojo
Uint8 itemG; // Verde
Uint8 itemB; // Azul
};
// Establece el indice del item que se usará por defecto al cancelar el menu
void setDefaultActionWhenCancel(Uint8 item);
selector mSelector;
// Coloca el selector en una posición específica
void setSelectorPos(Uint8 index);
};
#endif

View File

@@ -1,17 +1,38 @@
#include "const.h"
#include "movingsprite.h"
#include <iostream>
// Constructor
MovingSprite::MovingSprite()
{
init(0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr);
clear();
}
// Destructor
MovingSprite::~MovingSprite()
{
init(0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr);
clear();
}
// Reinicia todas las variables
void MovingSprite::clear()
{
mPosX = 0.0f; // Posición en el eje X
mPosY = 0.0f; // Posición en el eje Y
mVelX = 0.0f; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
mVelY = 0.0f; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
mAccelX = 0.0f; // Aceleración en el eje X. Variación de la velocidad
mAccelY = 0.0f; // Aceleración en el eje Y. Variación de la velocidad
mZoomW = 1.0f; // Zoom aplicado a la anchura
mZoomH = 1.0f; // Zoom aplicado a la altura
mAngle = 0.0; // Angulo para dibujarlo
mRotate = false; // Indica si ha de rotar
mRotateSpeed = 0; // Velocidad de giro
mRotateAmount = 0.0; // Cantidad de grados a girar en cada iteración
mCounter = 0; // Contador interno
}
// Iniciador
@@ -37,6 +58,17 @@ void MovingSprite::init(float x, float y, int w, int h, float velx, float vely,
setZoomW(1);
setZoomH(1);
// Establece el angulo con el que se dibujará
setAngle(0.0);
// Establece los valores de rotacion
setRotate(false);
setRotateSpeed(0);
setRotateAmount(0.0);
// Contador interno
mCounter = 0;
// Establece la textura donde están los gráficos para el sprite
setTexture(texture);
@@ -50,68 +82,77 @@ void MovingSprite::init(float x, float y, int w, int h, float velx, float vely,
// Mueve el sprite
void MovingSprite::move()
{
mPosX += mVelX;
mPosY += mVelY;
if (mEnabled)
{
mPosX += mVelX;
mPosY += mVelY;
mVelX += mAccelX;
mVelY += mAccelY;
mVelX += mAccelX;
mVelY += mAccelY;
}
}
// Muestra el sprite por pantalla
void MovingSprite::render()
{
//mTexture->render(mRenderer, (int)mPosX, (int)mPosY, &mSpriteClip);
mTexture->render(mRenderer, (int)mPosX, (int)mPosY, &mSpriteClip, mZoomW, mZoomH);
if (mEnabled)
mTexture->render(mRenderer, (int)mPosX, (int)mPosY, &mSpriteClip, mZoomW, mZoomH, mAngle);
}
// Establece el valor de la variable
// Obtiene el valor de la variable
float MovingSprite::getPosX()
{
return mPosX;
}
// Establece el valor de la variable
// Obtiene el valor de la variable
float MovingSprite::getPosY()
{
return mPosY;
}
// Establece el valor de la variable
// Obtiene el valor de la variable
float MovingSprite::getVelX()
{
return mVelX;
}
// Establece el valor de la variable
// Obtiene el valor de la variable
float MovingSprite::getVelY()
{
return mVelY;
}
// Establece el valor de la variable
// Obtiene el valor de la variable
float MovingSprite::getAccelX()
{
return mAccelX;
}
// Establece el valor de la variable
// Obtiene el valor de la variable
float MovingSprite::getAccelY()
{
return mAccelY;
}
// Establece el valor de la variable
// Obtiene el valor de la variable
float MovingSprite::getZoomW()
{
return mZoomW;
}
// Establece el valor de la variable
// Obtiene el valor de la variable
float MovingSprite::getZoomH()
{
return mZoomH;
}
// Obtiene el valor de la variable
double MovingSprite::getAngle()
{
return mAngle;
}
// Establece el valor de la variable
void MovingSprite::setPosX(float x)
{
@@ -158,4 +199,81 @@ void MovingSprite::setZoomW(float w)
void MovingSprite::setZoomH(float h)
{
mZoomH = h;
}
// Establece el valor de la variable
void MovingSprite::setAngle(double a)
{
mAngle = a;
}
// Incrementa el valor de la variable
void MovingSprite::incAngle(double inc)
{
mAngle += inc;
}
// Decrementa el valor de la variable
void MovingSprite::decAngle(double dec)
{
mAngle -= dec;
}
// Obtiene el valor de la variable
bool MovingSprite::getRotate()
{
return mRotate;
}
// Obtiene el valor de la variable
Uint16 MovingSprite::getRotateSpeed()
{
return mRotateSpeed;
}
// Establece la rotacion
void MovingSprite::rotate()
{
if (mEnabled)
if (mRotate)
{
if (mCounter % mRotateSpeed == 0)
{
incAngle(mRotateAmount);
}
}
}
// Establece el valor de la variable
void MovingSprite::setRotate(bool value)
{
mRotate = value;
}
// Establece el valor de la variable
void MovingSprite::setRotateSpeed(Uint16 value)
{
mRotateSpeed = value;
}
// Establece el valor de la variable
void MovingSprite::setRotateAmount(double value)
{
mRotateAmount = value;
}
// Actualiza las variables internas del objeto
void MovingSprite::update()
{
move();
rotate();
if (mEnabled)
++mCounter %= 60000;
}
// Cambia el sentido de la rotación
void MovingSprite::switchRotate()
{
mRotateAmount *= -1;
}

View File

@@ -8,7 +8,7 @@
// Clase MovingSprite. Añade posicion y velocidad en punto flotante
class MovingSprite : public Sprite
{
private:
protected:
float mPosX; // Posición en el eje X
float mPosY; // Posición en el eje Y
@@ -21,6 +21,12 @@ private:
float mZoomW; // Zoom aplicado a la anchura
float mZoomH; // Zoom aplicado a la altura
double mAngle; // Angulo para dibujarlo
bool mRotate; // Indica si ha de rotar
Uint16 mRotateSpeed; // Velocidad de giro
double mRotateAmount; // Cantidad de grados a girar en cada iteración
Uint16 mCounter; // Contador interno
public:
// Constructor
MovingSprite();
@@ -34,6 +40,15 @@ public:
// Mueve el sprite
void move();
// Rota el sprite
void rotate();
// Actualiza las variables internas del objeto
void update();
// Reinicia todas las variables
void clear();
// Muestra el sprite por pantalla
void render();
@@ -61,6 +76,15 @@ public:
// Obten el valor de la variable
float getZoomH();
// Obten el valor de la variable
double getAngle();
// Obtiene el valor de la variable
bool getRotate();
// Obtiene el valor de la variable
Uint16 getRotateSpeed();
// Establece el valor de la variable
void setPosX(float x);
@@ -84,6 +108,27 @@ public:
// Establece el valor de la variable
void setZoomH(float h);
// Establece el valor de la variable
void setAngle(double a);
// Incrementa el valor de la variable
void incAngle(double inc);
// Decrementa el valor de la variable
void decAngle(double dec);
// Establece el valor de la variable
void setRotate(bool value);
// Establece el valor de la variable
void setRotateSpeed(Uint16 value);
// Establece el valor de la variable
void setRotateAmount(double value);
// Cambia el sentido de la rotación
void switchRotate();
};
#endif

View File

@@ -7,29 +7,35 @@ Player::Player()
mSpriteLegs = new AnimatedSprite();
mSpriteBody = new AnimatedSprite();
mSpriteHead = new AnimatedSprite();
init(0, 0, nullptr, nullptr, nullptr);
}
// Destructor
Player::~Player()
{
init(0, 0, nullptr, nullptr, nullptr);
mSpriteLegs = nullptr;
mSpriteBody = nullptr;
delete mSpriteLegs;
mSpriteLegs = nullptr;
delete mSpriteBody;
mSpriteBody = nullptr;
delete mSpriteHead;
mSpriteHead = nullptr;
}
// Iniciador
void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody, SDL_Renderer *renderer)
void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody, LTexture *textureHead, LTexture *textureDead, SDL_Renderer *renderer)
{
// Copia punteros
mPlayerDeadTexture = textureDead;
// Inicializa variables de estado
mAlive = true;
mStatusWalking = PLAYER_STATUS_WALKING_STOP;
mStatusFiring = PLAYER_STATUS_FIRING_NO;
mInvulnerable = false;
mInvulnerableCounter = PLAYER_INVULNERABLE_COUNTER;
mPowerUp = false;
mPowerUpCounter = PLAYER_POWERUP_COUNTER;
mExtraHit = false;
mCoffees = 0;
mInput = true;
@@ -59,7 +65,7 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mScore = 0;
// Establece el multiplicador de puntos inicial
mScoreMultiplier = 1.0f;
mScoreMultiplier = 2.0f;
// Inicia el contador para la cadencia de disparo
mCooldown = 10;
@@ -67,6 +73,7 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
// Inicia el sprite
mSpriteLegs->init(textureLegs, renderer);
mSpriteBody->init(textureBody, renderer);
mSpriteHead->init(textureHead, renderer);
// Establece el alto y ancho del sprite
mSpriteLegs->setWidth(mWidth);
@@ -75,6 +82,9 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setWidth(mWidth);
mSpriteBody->setHeight(mHeight);
mSpriteHead->setWidth(mWidth);
mSpriteHead->setHeight(mHeight);
// Establece la posición del sprite
mSpriteLegs->setPosX(int(mPosX));
mSpriteLegs->setPosY(mPosY);
@@ -82,6 +92,9 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setPosX(int(mPosX));
mSpriteBody->setPosY(mPosY);
mSpriteHead->setPosX(int(mPosX));
mSpriteHead->setPosY(mPosY);
// Inicializa las variables para la animación
mSpriteLegs->setCurrentFrame(0);
mSpriteLegs->setAnimationCounter(0);
@@ -89,6 +102,9 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setCurrentFrame(0);
mSpriteBody->setAnimationCounter(0);
mSpriteHead->setCurrentFrame(0);
mSpriteHead->setAnimationCounter(0);
// Establece el numero de frames de cada animacion
mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 4);
mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 4);
@@ -101,6 +117,13 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 4);
mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 4);
mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 4);
mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 4);
mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 4);
mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, 4);
mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, 4);
// Establece la velocidad de cada animación
mSpriteLegs->setAnimationSpeed(PLAYER_ANIMATION_LEGS_WALKING_STOP, 10);
mSpriteLegs->setAnimationSpeed(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 5);
@@ -113,6 +136,13 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_STOP, 10);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_UP, 5);
mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 5);
mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 5);
mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 5);
mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 5);
mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_WALKING_STOP, 10);
mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_FIRING_UP, 5);
// Establece si la animación se reproduce en bucle
mSpriteLegs->setAnimationLoop(PLAYER_ANIMATION_LEGS_WALKING_STOP, true);
mSpriteLegs->setAnimationLoop(PLAYER_ANIMATION_LEGS_WALKING_LEFT, true);
@@ -125,6 +155,13 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_STOP, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_UP, true);
mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_WALKING_LEFT, true);
mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_FIRING_LEFT, true);
mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, true);
mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, true);
mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_WALKING_STOP, true);
mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_FIRING_UP, true);
// Establece los frames de cada animación
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 0, mWidth * 0, mHeight * 0, mWidth, mHeight);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 1, mWidth * 1, mHeight * 0, mWidth, mHeight);
@@ -171,9 +208,40 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 2, mWidth * 2, mHeight * 5, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 3, mWidth * 3, mHeight * 5, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 0, mWidth * 0, mHeight * 0, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 1, mWidth * 1, mHeight * 0, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 2, mWidth * 2, mHeight * 0, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 3, mWidth * 3, mHeight * 0, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 0, mWidth * 0, mHeight * 1, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 1, mWidth * 1, mHeight * 1, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 2, mWidth * 2, mHeight * 1, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 3, mWidth * 3, mHeight * 1, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 0, mWidth * 0, mHeight * 2, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 1, mWidth * 1, mHeight * 2, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 2, mWidth * 2, mHeight * 2, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 3, mWidth * 3, mHeight * 2, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 0, mWidth * 0, mHeight * 3, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 1, mWidth * 1, mHeight * 3, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 2, mWidth * 2, mHeight * 3, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 3, mWidth * 3, mHeight * 3, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, 0, mWidth * 0, mHeight * 4, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, 1, mWidth * 1, mHeight * 4, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, 2, mWidth * 2, mHeight * 4, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, 3, mWidth * 3, mHeight * 4, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, 0, mWidth * 0, mHeight * 5, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, 1, mWidth * 1, mHeight * 5, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, 2, mWidth * 2, mHeight * 5, mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, 3, mWidth * 3, mHeight * 5, mWidth, mHeight);
// Selecciona un frame para pintar
mSpriteLegs->setSpriteClip(mSpriteLegs->getAnimationClip(PLAYER_ANIMATION_LEGS_WALKING_STOP, 0));
mSpriteBody->setSpriteClip(mSpriteBody->getAnimationClip(PLAYER_ANIMATION_BODY_WALKING_STOP, 0));
mSpriteHead->setSpriteClip(mSpriteHead->getAnimationClip(PLAYER_ANIMATION_HEAD_WALKING_STOP, 0));
}
// Actua en consecuencia de la entrada recibida
@@ -231,6 +299,9 @@ void Player::move()
mSpriteBody->setPosX(getPosX());
mSpriteBody->setPosY(mPosY);
mSpriteHead->setPosX(getPosX());
mSpriteHead->setPosY(mPosY);
}
}
@@ -245,12 +316,14 @@ void Player::render()
{
mSpriteLegs->render();
mSpriteBody->render();
mSpriteHead->render();
}
}
else
{
mSpriteLegs->render();
mSpriteBody->render();
mSpriteHead->render();
}
}
}
@@ -274,6 +347,7 @@ void Player::setFiringStatus(Uint8 status)
{
mStatusFiring = status;
mSpriteBody->setCurrentFrame(0);
mSpriteHead->setCurrentFrame(0);
}
}
@@ -281,7 +355,7 @@ void Player::setFiringStatus(Uint8 status)
void Player::setAnimation()
{
// Actualiza los frames de la animación en función del número de cafes
for (Uint8 i = 0; i < 4; i++)
for (int i = 0; i < 4; i++)
{
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, i, mWidth * i, mHeight * (0 + (6 * mCoffees)), mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, i, mWidth * i, mHeight * (1 + (6 * mCoffees)), mWidth, mHeight);
@@ -291,6 +365,17 @@ void Player::setAnimation()
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, i, mWidth * i, mHeight * (5 + (6 * mCoffees)), mWidth, mHeight);
}
// Actualiza los frames de la animación en función de si se tiene el PowerUp
for (int i = 0; i < 4; i++)
{
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, i, (mWidth * i) + (mPowerUp * 96), mHeight * (0 + (6 * mCoffees)), mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, i, (mWidth * i) + (mPowerUp * 96), mHeight * (1 + (6 * mCoffees)), mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, i, (mWidth * i) + (mPowerUp * 96), mHeight * (2 + (6 * mCoffees)), mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, i, (mWidth * i) + (mPowerUp * 96), mHeight * (3 + (6 * mCoffees)), mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, i, (mWidth * i) + (mPowerUp * 96), mHeight * (4 + (6 * mCoffees)), mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, i, (mWidth * i) + (mPowerUp * 96), mHeight * (5 + (6 * mCoffees)), mWidth, mHeight);
}
switch (mStatusWalking)
{
case PLAYER_STATUS_WALKING_LEFT:
@@ -299,22 +384,27 @@ void Player::setAnimation()
{
case PLAYER_STATUS_FIRING_UP:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_UP);
break;
case PLAYER_STATUS_FIRING_LEFT:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_LEFT);
break;
case PLAYER_STATUS_FIRING_RIGHT:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_RIGHT);
break;
case PLAYER_STATUS_FIRING_NO:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_LEFT);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_LEFT);
break;
default:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_STOP);
break;
}
break;
@@ -325,22 +415,27 @@ void Player::setAnimation()
{
case PLAYER_STATUS_FIRING_UP:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_UP);
break;
case PLAYER_STATUS_FIRING_LEFT:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_LEFT);
break;
case PLAYER_STATUS_FIRING_RIGHT:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_RIGHT);
break;
case PLAYER_STATUS_FIRING_NO:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_RIGHT);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_RIGHT);
break;
default:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_STOP);
break;
}
break;
@@ -351,22 +446,27 @@ void Player::setAnimation()
{
case PLAYER_STATUS_FIRING_UP:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_UP);
break;
case PLAYER_STATUS_FIRING_LEFT:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_LEFT);
break;
case PLAYER_STATUS_FIRING_RIGHT:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_RIGHT);
break;
case PLAYER_STATUS_FIRING_NO:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_STOP);
break;
default:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_STOP);
break;
}
break;
@@ -426,7 +526,9 @@ void Player::updateCooldown()
{
if (mCooldown > 0)
{
--mCooldown;
mCooldown--;
if (mPowerUp)
mCooldown--;
}
else
{
@@ -441,23 +543,24 @@ void Player::update()
setAnimation();
shiftColliders();
updateCooldown();
updatePowerUpCounter();
updateInvulnerableCounter();
}
// Obtiene la puntuación del jugador
int Player::getScore()
Uint32 Player::getScore()
{
return mScore;
}
// Asigna un valor a la puntuación del jugador
void Player::setScore(int score)
void Player::setScore(Uint32 score)
{
mScore = score;
}
// Incrementa la puntuación del jugador
void Player::addScore(int score)
void Player::addScore(Uint32 score)
{
mScore += score;
}
@@ -490,18 +593,18 @@ void Player::setScoreMultiplier(float value)
void Player::incScoreMultiplier()
{
if (mScoreMultiplier < 5.0f)
{
mScoreMultiplier += 0.1f;
}
else
mScoreMultiplier = 5.0f;
}
// Decrementa el valor de la variable hasta un mínimo
void Player::decScoreMultiplier()
{
if (mScoreMultiplier > 1.0f)
{
mScoreMultiplier -= 0.1f;
}
else
mScoreMultiplier = 1.0f;
}
// Obtiene el valor de la variable
@@ -542,6 +645,44 @@ void Player::updateInvulnerableCounter()
}
}
// Obtiene el valor de la variable
bool Player::isPowerUp()
{
return mPowerUp;
}
// Establece el valor de la variable
void Player::setPowerUp(bool value)
{
mPowerUp = value;
}
// Obtiene el valor de la variable
Uint16 Player::getPowerUpCounter()
{
return mPowerUpCounter;
}
// Establece el valor de la variable
void Player::setPowerUpCounter(Uint16 value)
{
mPowerUpCounter = value;
}
// Actualiza el valor de la variable
void Player::updatePowerUpCounter()
{
if (mPowerUpCounter > 0)
{
--mPowerUpCounter;
}
else
{
mPowerUp = false;
mPowerUpCounter = PLAYER_POWERUP_COUNTER;
}
}
// Obtiene el valor de la variable
bool Player::hasExtraHit()
{
@@ -597,4 +738,10 @@ void Player::shiftColliders()
{
mCollider.x = Uint16(mPosX + (mWidth / 2));
mCollider.y = mPosY + (mHeight / 2);
}
// Obtiene el puntero a la textura con los gráficos de la animación de morir
LTexture *Player::getDeadTexture()
{
return mPlayerDeadTexture;
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "utils.h"
#include "input.h"
#include "animatedsprite.h"
#ifndef PLAYER_H
@@ -32,11 +33,14 @@ private:
Uint16 mInvulnerableCounter; // Temporizador para la invulnerabilidad
bool mExtraHit; // Indica si el jugador tiene un toque extra
Uint8 mCoffees; // Indica cuantos cafes lleva acumulados
bool mPowerUp; // Indica si el jugador tiene activo el modo PowerUp
Uint16 mPowerUpCounter; // Temporizador para el modo PowerUp
bool mInput; // Indica si puede recibir ordenes de entrada
AnimatedSprite *mSpriteLegs; // Sprite para dibujar las piernas
AnimatedSprite *mSpriteBody; // Sprite para dibujar el cuerpo
AnimatedSprite *mSpriteHead; // Sprite para dibujar la cabeza
AnimatedSprite *mSpriteLegs; // Sprite para dibujar las piernas
AnimatedSprite *mSpriteBody; // Sprite para dibujar el cuerpo
AnimatedSprite *mSpriteHead; // Sprite para dibujar la cabeza
LTexture *mPlayerDeadTexture; // Textura con los gráficos para la animación de muerte
circle_t mCollider; // Circulo de colisión del jugador
void shiftColliders(); // Actualiza el circulo de colisión a la posición del jugador
@@ -49,7 +53,7 @@ public:
~Player();
// Iniciador
void init(float x, int y, LTexture *textureLegs, LTexture *textureBody, SDL_Renderer *renderer);
void init(float x, int y, LTexture *textureLegs, LTexture *textureBody, LTexture *textureHead, LTexture *textureDead, SDL_Renderer *renderer);
// Actua en consecuencia de la entrada recibida
void setInput(Uint8 input);
@@ -92,13 +96,13 @@ public:
void update();
// Obtiene la puntuación del jugador
int getScore();
Uint32 getScore();
// Asigna un valor a la puntuación del jugador
void setScore(int score);
void setScore(Uint32 score);
// Incrementa la puntuación del jugador
void addScore(int score);
void addScore(Uint32 score);
// Obtiene el valor de la variable
bool isAlive();
@@ -133,6 +137,21 @@ public:
// Actualiza el valor de la variable
void updateInvulnerableCounter();
// Obtiene el valor de la variable
bool isPowerUp();
// Establece el valor de la variable
void setPowerUp(bool value);
// Obtiene el valor de la variable
Uint16 getPowerUpCounter();
// Establece el valor de la variable
void setPowerUpCounter(Uint16 value);
// Actualiza el valor de la variable
void updatePowerUpCounter();
// Obtiene el valor de la variable
bool hasExtraHit();
@@ -153,6 +172,9 @@ public:
// Obtiene el circulo de colisión
circle_t &getCollider();
// Obtiene el puntero a la textura con los gráficos de la animación de morir
LTexture *getDeadTexture();
};
#endif

View File

@@ -4,13 +4,13 @@
// Constructor
SmartSprite::SmartSprite()
{
init(nullptr, nullptr);
//init(nullptr, nullptr);
}
// Destructor
SmartSprite::~SmartSprite()
{
init(nullptr, nullptr);
//init(nullptr, nullptr);
}
// Inicializador
@@ -38,6 +38,12 @@ void SmartSprite::init(LTexture *texture, SDL_Renderer *renderer)
mDestX = 0;
mDestY = 0;
setRotate(false);
setRotateSpeed(0);
setRotateAmount(0.0);
mCounter = 0;
// El Id siempre es >=0, por lo tanto si no se le asigna Id se queda en negativo
mId = -1;
@@ -65,13 +71,13 @@ void SmartSprite::setEnabled(bool state)
// Obtiene el valor de la variable
Uint16 SmartSprite::getEnabledTimer()
{
return mEnabledTimer;
return mEnabledCounter;
}
// Establece el valor de la variable
void SmartSprite::setEnabledTimer(Uint16 time)
{
mEnabledTimer = time;
mEnabledCounter = time;
}
// Establece el valor de la variable
@@ -103,7 +109,7 @@ bool SmartSprite::update()
{
if (mEnabled)
{
move();
MovingSprite::update();
// Comprueba si se desplaza en el eje X hacia la derecha
if ((getAccelX() > 0) || ((getAccelX() == 0) && (getVelX() > 0)))
@@ -119,7 +125,6 @@ bool SmartSprite::update()
setAccelX(0.0f);
}
}
// Comprueba si se desplaza en el eje X hacia la izquierda
else if ((getAccelX() < 0) || ((getAccelX() == 0) && (getVelX() < 0)))
{
@@ -178,12 +183,12 @@ bool SmartSprite::update()
if (mIsOnDestination)
{
// Si el contador es mayor que cero, lo decrementa
if (mEnabledTimer > 0)
if (mEnabledCounter > 0)
{
--mEnabledTimer;
--mEnabledCounter;
}
// Si ha llegado a cero, deshabilita el objeto o manda el aviso en función de si tiene Id
else if (mEnabledTimer == 0)
else if (mEnabledCounter == 0)
{
if (mId < 0)
{

View File

@@ -8,6 +8,15 @@
// Clase SmartSprite
class SmartSprite : public AnimatedSprite
{
private:
bool mEnabled; // Indica si esta habilitado
bool mIsOnDestination; // Indica si está en el destino
int mDestX; // Posicion de destino en el eje X
int mDestY; // Posicion de destino en el eje Y
int mId; // Identificador
Uint16 mEnabledCounter; // Contador para deshabilitarlo
Uint8 *mIntroEvents; // Dirección del array de eventos donde notificar el estado
public:
// Constructor
SmartSprite();
@@ -47,7 +56,7 @@ public:
// Actualiza la posición y comprueba si ha llegado a su destino
bool update();
// Obtiene el valor de la variable
bool isOnDestination();
@@ -59,26 +68,6 @@ public:
// Establece el valor de la variable
void setIntroEvents(Uint8 *value);
private:
// Indica si esta habilitado
bool mEnabled;
// Contador
Uint16 mEnabledTimer;
// Indica si está en el destino
bool mIsOnDestination;
// Posicion de destino
int mDestX;
int mDestY;
// Identificador
int mId;
// Dirección del array de eventos donde notificar el estado
Uint8 *mIntroEvents;
};
#endif

View File

@@ -32,6 +32,9 @@ void Sprite::init(int x, int y, int w, int h, LTexture *texture, SDL_Renderer *r
// Establece el rectangulo de donde coger la imagen
setSpriteClip(0, 0, w, h);
// Habilita el objeto
setEnabled(true);
}
// Inicializador
@@ -58,7 +61,8 @@ void Sprite::init(SDL_Rect rect, LTexture *texture, SDL_Renderer *renderer)
// Muestra el sprite por pantalla
void Sprite::render()
{
mTexture->render(mRenderer, mPosX, mPosY, &mSpriteClip);
if (mEnabled)
mTexture->render(mRenderer, mPosX, mPosY, &mSpriteClip);
}
// Obten el valor de la variable
@@ -146,4 +150,16 @@ void Sprite::setTexture(LTexture *texture)
void Sprite::setRenderer(SDL_Renderer *renderer)
{
mRenderer = renderer;
}
// Establece el valor de la variable
void Sprite::setEnabled(bool value)
{
mEnabled = value;
}
// Comprueba si el objeto está habilitado
bool Sprite::isEnabled()
{
return mEnabled;
}

View File

@@ -8,44 +8,56 @@
// Clase sprite
class Sprite
{
protected:
int mPosX; // Posición en el eje X donde dibujar el sprite
int mPosY; // Posición en el eje Y donde dibujar el sprite
Uint16 mWidth; // Ancho del sprite
Uint16 mHeight; // Alto del sprite
SDL_Renderer *mRenderer; // Puntero al renderizador de la ventana
LTexture *mTexture; // Textura donde estan todos los dibujos del sprite
SDL_Rect mSpriteClip; // Rectangulo de origen de la textura que se dibujará en pantalla
bool mEnabled; // Indica si el sprite esta habilitado
public:
// Constructor
Sprite();
// Constructor
Sprite();
// Destructor
~Sprite();
// Inicializador
void init(int x, int y, int w, int h, LTexture *texture, SDL_Renderer *renderer);
// Inicializador
void init(int x, int y, int w, int h, LTexture *texture, SDL_Renderer *renderer);
void init(SDL_Rect rect, LTexture *texture, SDL_Renderer *renderer);
// Muestra el sprite por pantalla
void render();
// Obten el valor de la variable
int getPosX();
// Obten el valor de la variable
int getPosY();
// Obten el valor de la variable
int getWidth();
// Obten el valor de la variable
int getHeight();
// Establece el valor de la variable
void setPosX(int x);
// Establece el valor de la variable
void setPosY(int y);
// Establece el valor de la variable
void setWidth(int w);
// Establece el valor de la variable
void setHeight(int h);
// Obten el valor de la variable
SDL_Rect getSpriteClip();
@@ -56,32 +68,19 @@ public:
void setSpriteClip(int x, int y, int w, int h);
// Obten el valor de la variable
LTexture* getTexture();
LTexture *getTexture();
// Establece el valor de la variable
void setTexture(LTexture *texture);
// Establece el valor de la variable
// Establece el valor de la variable
void setRenderer(SDL_Renderer *renderer);
// Establece el valor de la variable
void setEnabled(bool value);
protected:
// Posición X,Y donde dibujar el sprite
int mPosX;
int mPosY;
// Alto y ancho del sprite
Uint16 mWidth;
Uint16 mHeight;
// Puntero al renderizador de la ventana
SDL_Renderer *mRenderer;
// Textura donde estan todos los dibujos del sprite
LTexture *mTexture;
// Rectangulo de la textura que se dibujará en pantalla
SDL_Rect mSpriteClip;
// Comprueba si el objeto está habilitado
bool isEnabled();
};
#endif

View File

@@ -2,20 +2,28 @@
#include "text.h"
// Constructor
Text::Text()
Text::Text(LTexture *texture, SDL_Renderer *renderer)
{
mSprite = new Sprite();
init(nullptr, nullptr, 0, 0);
mSprite->setTexture(texture);
mSprite->setRenderer(renderer);
}
// Destructor
Text::~Text()
{
delete mSprite;
mSprite = nullptr;
}
// en el constructor se le pasa la ruta del fichero de descripcion
// el fichero tendra el alto y ancho del cuadrado donde esta cada letra
// y el listado de anchos de cada una
// el init ya no necesita type ni size
// Inicializador
void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size)
void Text::init(Uint8 type, Uint8 size)
{
// Inicializa variables
mType = type;
@@ -26,15 +34,13 @@ void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 siz
mSprite->setHeight(size);
mSprite->setPosX(0);
mSprite->setPosY(0);
mSprite->setTexture(texture);
mSprite->setRenderer(renderer);
mSprite->setSpriteClip(0, 0, mSprite->getWidth(), mSprite->getHeight());
// Cadena con los caracteres ascii que se van a inicializar
std::string text = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ{\\[]]^_`abcdefghijklmnopqrstuvwxyz";
const std::string text = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ{\\[]]^_`abcdefghijklmnopqrstuvwxyz";
// Inicializa a cero el vector con las coordenadas
for (Uint8 i = 0; i < 255; i++)
for (int i = 0; i < 128; i++)
{
mOffset[i].x = 0;
mOffset[i].y = 0;
@@ -42,16 +48,24 @@ void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 siz
}
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho
for (Uint8 i = 0; i < text.length(); ++i)
for (int i = 0; i < text.length(); ++i)
{
mOffset[int(text[i])].x = ((int(text[i]) - 32) % 15) * mSprite->getWidth();
mOffset[int(text[i])].y = ((int(text[i]) - 32) / 15) * mSprite->getHeight();
if (type == TEXT_FIXED)
{
mOffset[int(text[i])].w = size;
}
}
// Establece las coordenadas de forma manual para la ñ
mOffset[int('^')].x = mOffset[int('z')].x + size;
mOffset[int('^')].y = mOffset[int('z')].y;
mOffset[int('^')].w = size;
// Establece las coordenadas de forma manual para la ñç
mOffset[int('~')].x = mOffset[int('z')].x + size * 2;
mOffset[int('~')].y = mOffset[int('z')].y;
mOffset[int('~')].w = size;
// Establece el ancho de cada caracter
if (type == TEXT_VARIABLE)
{
@@ -104,6 +118,9 @@ void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 siz
mOffset[int('Y')].w = 8;
mOffset[int('Z')].w = 7;
mOffset[int('^')].w = 7;
mOffset[int('~')].w = 7;
mOffset[int('a')].w = 7;
mOffset[int('b')].w = 7;
mOffset[int('c')].w = 6;
@@ -133,25 +150,15 @@ void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 siz
}
}
// Escribe el texto en pantalla
void Text::write(int x, int y, std::string text)
// Escribe texto en pantalla
void Text::write(int x, int y, std::string text, int kerning, int lenght)
{
Uint16 shift = 0;
for (Uint8 i = 0; i < text.length(); ++i)
{
mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight());
mSprite->setPosX(x + shift);
mSprite->setPosY(y);
mSprite->render();
shift += (mOffset[int(text[i])].w);
}
}
// Escribe el texto en pantalla con kerning
void Text::write(int x, int y, std::string text, int kerning)
{
Uint16 shift = 0;
for (Uint8 i = 0; i < text.length(); ++i)
if (lenght == -1)
lenght = text.length();
for (int i = 0; i < lenght; ++i)
{
mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight());
mSprite->setPosX(x + shift);
@@ -161,69 +168,57 @@ void Text::write(int x, int y, std::string text, int kerning)
}
}
// Escribe una cantidad determinada de caracteres del texto en pantalla
void Text::write(int x, int y, std::string text, int kerning, Uint8 lenght)
{
Uint16 shift = 0;
for (Uint8 i = 0; i < lenght; ++i)
{
if (text[i] == '*')
{
shift = 0;
y += mSize;
}
else
{
mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight());
mSprite->setPosX(x + shift);
mSprite->setPosY(y);
mSprite->render();
shift += (mOffset[int(text[i])].w + kerning);
}
}
}
// Escribe el texto con colores
void Text::writeColored(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B)
void Text::writeColored(int x, int y, std::string text, color_t color, int kerning, int lenght)
{
mSprite->getTexture()->setColor(R, G, B);
write(x, y, text);
mSprite->getTexture()->setColor(color.r, color.g, color.b);
write(x, y, text, kerning, lenght);
mSprite->getTexture()->setColor(255, 255, 255);
}
// Escribe el texto con sombra
void Text::writeShadowed(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B)
void Text::writeShadowed(int x, int y, std::string text, color_t color, Uint8 shadowDistance, int kerning, int lenght)
{
mSprite->getTexture()->setColor(R, G, B);
write(x+1, y+1, text);
mSprite->getTexture()->setColor(color.r, color.g, color.b);
write(x + shadowDistance, y + shadowDistance, text, kerning, lenght);
mSprite->getTexture()->setColor(255, 255, 255);
write(x, y, text);
write(x, y, text, kerning, lenght);
}
// Escribe el texto centrado en un punto x y con kerning
void Text::writeCentered(int x, int y, std::string text, int kerning)
// Escribe el texto centrado en un punto x
void Text::writeCentered(int x, int y, std::string text, int kerning, int lenght)
{
// Uint16 lenght = Text::lenght(text, kerning);
x = x - (Text::lenght(text, kerning) / 2);
Uint16 shift = 0;
for (Uint8 i = 0; i < text.length(); ++i)
{
mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight());
mSprite->setPosX(x + shift);
mSprite->setPosY(y);
mSprite->render();
shift += (mOffset[int(text[i])].w + kerning);
}
x -= (Text::lenght(text, kerning) / 2);
write(x, y, text, kerning, lenght);
}
// Escribe texto con extras
void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, color_t textColor, Uint8 shadowDistance, color_t shadowColor, int lenght)
{
const bool centered = ((flags & TXT_CENTER) == TXT_CENTER);
const bool shadowed = ((flags & TXT_SHADOW) == TXT_SHADOW);
const bool colored = ((flags & TXT_COLOR) == TXT_COLOR);
if (centered)
x -= (Text::lenght(text, kerning) / 2);
if (shadowed)
writeColored(x + shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
if (colored)
writeColored(x, y, text, textColor, kerning, lenght);
else
write(x, y, text, kerning, lenght);
}
// Obtiene la longitud en pixels de una cadena
Uint16 Text::lenght(std::string text, int kerning)
{
Uint16 shift = 0;
for (Uint8 i = 0; i < text.length(); ++i)
{
for (int i = 0; i < text.length(); ++i)
shift += (mOffset[int(text[i])].w + kerning);
}
return shift;
}

View File

@@ -1,14 +1,19 @@
#pragma once
#include "sprite.h"
#include "utils.h"
#ifndef TEXT_H
#define TEXT_H
#define TXT_COLOR 1
#define TXT_SHADOW 2
#define TXT_CENTER 4
// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text
{
private:
Sprite *mSprite;// Objeto con los graficos para el texto
private:
Sprite *mSprite; // Objeto con los graficos para el texto
struct Offset
{
@@ -16,34 +21,35 @@ class Text
int y;
Uint8 w;
};
Offset mOffset[255];// Vector con las posiciones y ancho de cada letra
Offset mOffset[255]; // Vector con las posiciones y ancho de cada letra
Uint8 mType;// Indica si el texto es de anchura fija o variable
Uint8 mSize;// Altura del texto
Uint8 mType; // Indica si el texto es de anchura fija o variable
Uint8 mSize; // Altura del texto
public:
// Constructor
Text();
Text(LTexture *texture, SDL_Renderer *renderer);
// Destructor
~Text();
// Inicializador
void init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size);
void init(Uint8 type, Uint8 size);
// Escribe el texto en pantalla
void write(int x, int y, std::string text);
void write(int x, int y, std::string text, int kerning);
void write(int x, int y, std::string text, int kerning, Uint8 lenght);
void write(int x, int y, std::string text, int kerning = 0, int lenght = -1);
// Escribe el texto con colores
void writeColored(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B);
void writeColored(int x, int y, std::string text, color_t color, int kerning = 0, int lenght = -1);
// Escribe el texto con sombra
void writeShadowed(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B);
// Escribe el texto con sombra
void writeShadowed(int x, int y, std::string text, color_t color, Uint8 shadowDistance = 1, int kerning = 0, int lenght = -1);
// Escribe el texto centrado en un punto x y con kerning
void writeCentered(int x, int y, std::string text, int kerning = 0);
void writeCentered(int x, int y, std::string text, int kerning = 0, int lenght = -1);
// Escribe texto con extras
void writeDX(Uint8 flags, int x, int y, std::string text, int kerning = 0, color_t textColor = {255, 255, 255}, Uint8 shadowDistance = 1, color_t shadowColor = {0, 0, 0}, int lenght = -1);
// Obtiene la longitud en pixels de una cadena
Uint16 lenght(std::string text, int kerning);
@@ -53,7 +59,7 @@ public:
// Establece el valor de la variable
void setType(Uint8 type);
// Obtiene el valor de la variable
Uint8 getSize();

View File

@@ -2,21 +2,19 @@
#include "text2.h"
// Constructor
Text2::Text2()
Text2::Text2(LTexture *texture, SDL_Renderer *renderer) : Text(texture, renderer)
{
init(nullptr, nullptr, 0, 0);
}
// Destructor
Text2::~Text2()
{
init(nullptr, nullptr, 0, 0);
}
// Inicializador
void Text2::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size)
void Text2::init(Uint8 type, Uint8 size)
{
Text::init(texture, renderer, type, size);
Text::init(type, size);
mPosX = 0;
mPosY = 0;
mKerning = 0;

View File

@@ -10,13 +10,13 @@ class Text2 : public Text
{
public:
// Constructor
Text2();
Text2(LTexture *texture, SDL_Renderer *renderer);
// Destructor
~Text2();
// Inicializador
void init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size);
void init(Uint8 type, Uint8 size);
// Establece el valor de la variable
void setPosX(int value);

703
source/title.cpp Normal file
View File

@@ -0,0 +1,703 @@
#include "title.h"
#ifdef __MIPSEL__
#include <sys/stat.h>
#include <dirent.h>
#endif
// Constructor
Title::Title(SDL_Window *window, SDL_Renderer *renderer, Input *input, std::string *fileList, options_t *options, std::string *textStrings)
{
// Copia las direcciones de los punteros
mWindow = window;
mRenderer = renderer;
mInput = input;
mFileList = fileList;
mOptions = options;
mTextStrings = textStrings;
// Reserva memoria para los punteros propios
mEventHandler = new SDL_Event();
mFade = new Fade(renderer);
mTitleTexture = new LTexture();
mItemsTexture = new LTexture();
mTextTexture = new LTexture();
mCoffeeBitmap = new SmartSprite();
mCrisisBitmap = new SmartSprite();
mDustBitmapL = new AnimatedSprite();
mDustBitmapR = new AnimatedSprite();
mTile = new Sprite();
mText = new Text(mTextTexture, mRenderer);
mMenu.title = new Menu(mRenderer, mText, mInput, mFileList);
mMenu.options = new Menu(mRenderer, mText, mInput, mFileList);
mBackground = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2);
if (mBackground == NULL)
printf("TitleSurface could not be created!\nSDL Error: %s\n", SDL_GetError());
}
// Destructor
Title::~Title()
{
delete mEventHandler;
mEventHandler = nullptr;
delete mText;
mText = nullptr;
delete mFade;
mFade = nullptr;
mTitleTexture->unload();
delete mTitleTexture;
mTitleTexture = nullptr;
mItemsTexture->unload();
delete mItemsTexture;
mItemsTexture = nullptr;
mTextTexture->unload();
delete mTextTexture;
mTextTexture = nullptr;
delete mCoffeeBitmap;
mCoffeeBitmap = nullptr;
delete mCrisisBitmap;
mCrisisBitmap = nullptr;
delete mDustBitmapL;
mDustBitmapL = nullptr;
delete mDustBitmapR;
mDustBitmapR = nullptr;
delete mTile;
mTile = nullptr;
delete mMenu.title;
mMenu.title = nullptr;
delete mMenu.options;
mMenu.options = nullptr;
mMenu.active = nullptr;
JA_DeleteSound(mSound);
JA_DeleteMusic(mMusic);
SDL_DestroyTexture(mBackground);
mBackground = nullptr;
mWindow = nullptr;
mRenderer = nullptr;
mInput = nullptr;
mFileList = nullptr;
mOptions = nullptr;
}
// Inicializa las variables necesarias para la sección 'Title'
void Title::init(bool demo, Uint8 subsection)
{
// Carga los recursos
loadMedia();
// Inicializa variables
mSection.name = PROG_SECTION_TITLE;
mSection.subsection = subsection;
mCounter = TITLE_COUNTER;
mBackgroundCounter = 0;
mBackgroundMode = rand() % 2;
mMenuVisible = false;
mMenu.active = mMenu.title;
mNextSection.name = PROG_SECTION_GAME;
mPostFade = 0;
mTicks = 0;
mTicksSpeed = 15;
mText->init(TEXT_FIXED, BLOCK);
mFade->init();
mDemo = demo;
// Inicializa el bitmap de Coffee
mCoffeeBitmap->init(mTitleTexture, mRenderer);
mCoffeeBitmap->setId(0);
mCoffeeBitmap->setIntroEvents(&mEvents[0]);
mCoffeeBitmap->setPosX(45);
mCoffeeBitmap->setPosY(11 - 200);
mCoffeeBitmap->setWidth(167);
mCoffeeBitmap->setHeight(46);
mCoffeeBitmap->setVelX(0.0f);
mCoffeeBitmap->setVelY(2.5f);
mCoffeeBitmap->setAccelX(0.0f);
mCoffeeBitmap->setAccelY(0.1f);
mCoffeeBitmap->setSpriteClip(0, 0, 167, 46);
mCoffeeBitmap->setEnabled(true);
mCoffeeBitmap->setEnabledTimer(0);
mCoffeeBitmap->setDestX(45);
mCoffeeBitmap->setDestY(11);
// Inicializa el bitmap de Crisis
mCrisisBitmap->init(mTitleTexture, mRenderer);
mCrisisBitmap->setId(1);
mCrisisBitmap->setIntroEvents(&mEvents[0]);
mCrisisBitmap->setPosX(60);
mCrisisBitmap->setPosY(57 + 200);
mCrisisBitmap->setWidth(137);
mCrisisBitmap->setHeight(46);
mCrisisBitmap->setVelX(0.0f);
mCrisisBitmap->setVelY(-2.5f);
mCrisisBitmap->setAccelX(0.0f);
mCrisisBitmap->setAccelY(-0.1f);
mCrisisBitmap->setSpriteClip(0, 46, 137, 46);
mCrisisBitmap->setEnabled(true);
mCrisisBitmap->setEnabledTimer(0);
mCrisisBitmap->setDestX(60);
mCrisisBitmap->setDestY(57);
// Inicializa el bitmap de DustRight
mDustBitmapR->init(mTitleTexture, mRenderer);
mDustBitmapR->setPosX(218);
mDustBitmapR->setPosY(47);
mDustBitmapR->setWidth(16);
mDustBitmapR->setHeight(14);
mDustBitmapR->setCurrentFrame(0);
mDustBitmapR->setAnimationCounter(0);
mDustBitmapR->setAnimationNumFrames(0, 7);
mDustBitmapR->setAnimationSpeed(0, 8);
mDustBitmapR->setAnimationLoop(0, false);
mDustBitmapR->setAnimationFrames(0, 0, 160 + (mDustBitmapR->getWidth() * 0), 80, mDustBitmapR->getWidth(), mDustBitmapR->getHeight());
mDustBitmapR->setAnimationFrames(0, 1, 160 + (mDustBitmapR->getWidth() * 1), 80, mDustBitmapR->getWidth(), mDustBitmapR->getHeight());
mDustBitmapR->setAnimationFrames(0, 2, 160 + (mDustBitmapR->getWidth() * 2), 80, mDustBitmapR->getWidth(), mDustBitmapR->getHeight());
mDustBitmapR->setAnimationFrames(0, 3, 160 + (mDustBitmapR->getWidth() * 3), 80, mDustBitmapR->getWidth(), mDustBitmapR->getHeight());
mDustBitmapR->setAnimationFrames(0, 4, 160 + (mDustBitmapR->getWidth() * 4), 80, mDustBitmapR->getWidth(), mDustBitmapR->getHeight());
mDustBitmapR->setAnimationFrames(0, 5, 160 + (mDustBitmapR->getWidth() * 5), 80, mDustBitmapR->getWidth(), mDustBitmapR->getHeight());
mDustBitmapR->setAnimationFrames(0, 6, 160 + (mDustBitmapR->getWidth() * 6), 80, mDustBitmapR->getWidth(), mDustBitmapR->getHeight());
// Inicializa el bitmap de DustLeft
mDustBitmapL->init(mTitleTexture, mRenderer);
mDustBitmapL->setPosX(33);
mDustBitmapL->setPosY(47);
mDustBitmapL->setWidth(16);
mDustBitmapL->setHeight(14);
mDustBitmapL->setCurrentFrame(0);
mDustBitmapL->setAnimationCounter(0);
mDustBitmapL->setAnimationNumFrames(0, 7);
mDustBitmapL->setAnimationSpeed(0, 8);
mDustBitmapL->setAnimationLoop(0, false);
mDustBitmapL->setAnimationFrames(0, 0, 160 + (mDustBitmapL->getWidth() * 0), 66, mDustBitmapL->getWidth(), mDustBitmapL->getHeight());
mDustBitmapL->setAnimationFrames(0, 1, 160 + (mDustBitmapL->getWidth() * 1), 66, mDustBitmapL->getWidth(), mDustBitmapL->getHeight());
mDustBitmapL->setAnimationFrames(0, 2, 160 + (mDustBitmapL->getWidth() * 2), 66, mDustBitmapL->getWidth(), mDustBitmapL->getHeight());
mDustBitmapL->setAnimationFrames(0, 3, 160 + (mDustBitmapL->getWidth() * 3), 66, mDustBitmapL->getWidth(), mDustBitmapL->getHeight());
mDustBitmapL->setAnimationFrames(0, 4, 160 + (mDustBitmapL->getWidth() * 4), 66, mDustBitmapL->getWidth(), mDustBitmapL->getHeight());
mDustBitmapL->setAnimationFrames(0, 5, 160 + (mDustBitmapL->getWidth() * 5), 66, mDustBitmapL->getWidth(), mDustBitmapL->getHeight());
mDustBitmapL->setAnimationFrames(0, 6, 160 + (mDustBitmapL->getWidth() * 6), 66, mDustBitmapL->getWidth(), mDustBitmapL->getHeight());
// Inicializa el vector de eventos de la pantalla de titulo
for (int i = 0; i < TITLE_TOTAL_EVENTS; i++)
mEvents[i] = EVENT_WAITING;
// Crea el mosaico de fondo del titulo
SDL_SetRenderTarget(mRenderer, mBackground);
SDL_SetRenderDrawColor(mRenderer, 0x43, 0x43, 0x4F, 0xFF);
SDL_RenderClear(mRenderer);
mTile->init(0, 0, 64, 64, mTitleTexture, mRenderer);
mTile->setSpriteClip(192, 0, 64, 64);
for (int i = 0; i < 8; i++)
for (int j = 0; j < 6; j++)
{
mTile->setPosX(i * 64);
mTile->setPosY(j * 64);
mTile->render();
}
SDL_SetRenderTarget(mRenderer, nullptr);
mBackgroundWindow.x = 0;
mBackgroundWindow.y = 0;
mBackgroundWindow.w = SCREEN_WIDTH;
mBackgroundWindow.h = SCREEN_HEIGHT;
// Inicializa los valores del vector con los valores del seno
for (int i = 0; i < 360; i++)
{
mSin[i] = SDL_sinf((float)i * 3.14f / 180.0f);
}
// Inicializa los objetos de menu
mMenu.title->init("TITLE", 0, 14 * BLOCK, MENU_BACKGROUND_SOLID);
mMenu.title->addItem(mTextStrings[51]); // 1 PLAYER
mMenu.title->addItem(mTextStrings[52]); // 2 PLAYERS
mMenu.title->addItem(mTextStrings[1]); // OPTIONS
mMenu.title->addItem(mTextStrings[2], 0, 5); // HOW TO PLAY
mMenu.title->addItem(mTextStrings[3]); // QUIT
mMenu.title->setDefaultActionWhenCancel(4);
mMenu.title->setBackgroundColor(0x30, 0x30, 0x40, 192);
mMenu.title->setSelectorColor(0xe5, 0x1c, 0x23, 255);
mMenu.title->setSelectorTextColor(0xFF, 0xF1, 0x76);
mMenu.title->centerMenu(SCREEN_CENTER_X);
mMenu.title->centerMenuElements();
mMenu.options->init("OPTIONS", 0, 14 * BLOCK, MENU_BACKGROUND_SOLID);
mMenu.options->addItem(mTextStrings[4]);
mMenu.options->addItem(mTextStrings[7]);
mMenu.options->addItem(mTextStrings[8], 0, 5);
mMenu.options->addItem(mTextStrings[9]);
mMenu.options->addItem(mTextStrings[10]);
mMenu.options->setDefaultActionWhenCancel(4);
mMenu.options->setBackgroundColor(0x30, 0x30, 0x40, 192);
mMenu.options->setSelectorColor(0xe5, 0x1c, 0x23, 255);
mMenu.options->setSelectorTextColor(0xFF, 0xF1, 0x76);
mMenu.options->centerMenu(SCREEN_CENTER_X);
mMenu.options->centerMenuElements();
// Actualiza los textos de los menus
updateMenuLabels();
}
// Carga los recursos necesarios para la sección 'Title'
bool Title::loadMedia()
{
// Indicador de éxito en la carga
bool success = true;
// Texturas
success &= loadTextureFromFile(mTitleTexture, mFileList[40], mRenderer);
success &= loadTextureFromFile(mItemsTexture, mFileList[34], mRenderer);
success &= loadTextureFromFile(mTextTexture, mFileList[30], mRenderer);
// Sonidos
mSound = JA_LoadSound(mFileList[21].c_str());
// Musicas
mMusic = JA_LoadMusic(mFileList[5].c_str());
return success;
}
// Cambia el valor de la variable de modo de pantalla completa
void Title::switchFullScreenModeVar()
{
switch (mOptions->fullScreenMode)
{
case 0:
mOptions->fullScreenMode = SDL_WINDOW_FULLSCREEN;
break;
case SDL_WINDOW_FULLSCREEN:
mOptions->fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
break;
case SDL_WINDOW_FULLSCREEN_DESKTOP:
mOptions->fullScreenMode = 0;
break;
default:
mOptions->fullScreenMode = 0;
break;
}
}
// Actualiza los elementos de los menus
void Title::updateMenuLabels()
{
switch (mOptions->fullScreenMode)
{
case 0:
mMenu.options->setItemCaption(0, mTextStrings[4]); // WINDOW
break;
case SDL_WINDOW_FULLSCREEN:
mMenu.options->setItemCaption(0, mTextStrings[5]); // FULLSCREEN
break;
case SDL_WINDOW_FULLSCREEN_DESKTOP:
mMenu.options->setItemCaption(0, mTextStrings[6]); // FAKE FULLSCREEN
break;
default:
mMenu.options->setItemCaption(0, mTextStrings[4]); // WINDOW
break;
}
mMenu.options->setItemCaption(1, mTextStrings[7] + " x" + std::to_string(mOptions->windowSize)); // WINDOW SIZE
switch (mOptions->language)
{
case es_ES:
mMenu.options->setItemCaption(2, mTextStrings[8] + " " + mTextStrings[24]);
break;
case ba_BA:
mMenu.options->setItemCaption(2, mTextStrings[8] + " " + mTextStrings[25]);
break;
case en_UK:
mMenu.options->setItemCaption(2, mTextStrings[8] + " " + mTextStrings[26]);
break;
}
mMenu.options->setItemCaption(3, mTextStrings[9]);
mMenu.options->setItemCaption(4, mTextStrings[10]);
mMenu.options->centerMenu(SCREEN_CENTER_X);
mMenu.options->centerMenuElements();
mMenu.title->setItemCaption(0, mTextStrings[51]);
mMenu.title->setItemCaption(1, mTextStrings[52]);
mMenu.title->setItemCaption(2, mTextStrings[1]);
mMenu.title->setItemCaption(3, mTextStrings[2]);
mMenu.title->setItemCaption(4, mTextStrings[3]);
mMenu.title->centerMenu(SCREEN_CENTER_X);
mMenu.title->centerMenuElements();
}
// Aplica las opciones de menu seleccionadas
void Title::applyOptions()
{
SDL_SetWindowFullscreen(mWindow, mOptions->fullScreenMode);
SDL_SetWindowSize(mWindow, SCREEN_WIDTH * mOptions->windowSize, SCREEN_HEIGHT * mOptions->windowSize);
initTextStrings(mTextStrings, mOptions->language);
updateMenuLabels();
}
// Bucle para el titulo del juego
section_t Title::run(Uint8 subsection)
{
init(subsection);
while (mSection.name == PROG_SECTION_TITLE)
{
// Sección 1 - Titulo desplazandose
if (mSection.subsection == TITLE_SECTION_1)
{
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(mEventHandler) != 0)
{
// Evento de salida de la aplicación
if (mEventHandler->type == SDL_QUIT)
{
mSection.name = PROG_SECTION_QUIT;
break;
}
}
// Calcula la lógica de los objetos
if (SDL_GetTicks() - mTicks > mTicksSpeed)
{
// Actualiza el contador de ticks
mTicks = SDL_GetTicks();
// Actualiza los objetos
mCoffeeBitmap->update();
mCrisisBitmap->update();
}
// Limpia la pantalla
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(mRenderer);
// Dibuja los objetos
mCoffeeBitmap->render();
mCrisisBitmap->render();
// Actualiza la pantalla
SDL_RenderPresent(mRenderer);
// Si los objetos han llegado a su destino, cambiamos de Sección
if ((mEvents[0] == EVENT_COMPLETED) && (mEvents[0] == EVENT_COMPLETED))
{
mSection.subsection = TITLE_SECTION_2;
// Pantallazo blanco
SDL_SetRenderDrawColor(mRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(mRenderer);
SDL_RenderPresent(mRenderer);
}
}
// Sección 2 - Titulo vibrando
if (mSection.subsection == TITLE_SECTION_2)
{
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(mEventHandler) != 0)
{
// Evento de salida de la aplicación
if (mEventHandler->type == SDL_QUIT)
{
mSection.name = PROG_SECTION_QUIT;
break;
}
}
// Reproduce el efecto sonoro
JA_PlaySound(mSound);
// Agita la pantalla
int v[] = {-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 0};
int a = mCoffeeBitmap->getPosX();
int b = mCrisisBitmap->getPosX();
for (int n = 0; n < 11 * 3; n++)
{
// Limpia la pantalla
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(mRenderer);
// Dibuja los objetos
mCoffeeBitmap->setPosX(a + v[n / 3]);
mCrisisBitmap->setPosX(b + v[n / 3]);
mCoffeeBitmap->render();
mCrisisBitmap->render();
mDustBitmapR->animate(0);
mDustBitmapL->animate(0);
mDustBitmapR->render();
mDustBitmapL->render();
// Actualiza la pantalla
SDL_RenderPresent(mRenderer);
}
mSection.subsection = TITLE_SECTION_3;
}
// Sección 3 - La pantalla de titulo con el menú y la música
if (mSection.subsection == TITLE_SECTION_3)
{
if (mCounter > 0)
{
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(mEventHandler) != 0)
{
// Evento de salida de la aplicación
if (mEventHandler->type == SDL_QUIT)
{
mSection.name = PROG_SECTION_QUIT;
break;
}
if ((mEventHandler->type == SDL_KEYUP) || (mEventHandler->type == SDL_JOYBUTTONUP))
{
mMenuVisible = true;
mCounter = TITLE_COUNTER;
}
}
// Si la música no está sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
// Reproduce la música
JA_PlayMusic(mMusic);
}
// Calcula la lógica de los objetos
if (SDL_GetTicks() - mTicks > mTicksSpeed)
{
// Actualiza el contador de ticks
mTicks = SDL_GetTicks();
// Actualiza la lógica del titulo
mMenu.active->update();
mFade->update();
if (mFade->hasEnded())
{
switch (mPostFade)
{
case 0: // 1 PLAYER
mSection.name = PROG_SECTION_GAME;
mSection.subsection = GAME_SECTION_PLAY_1P;
JA_StopMusic();
break;
case 1: // 2 PLAYERS
mSection.name = PROG_SECTION_GAME;
mSection.subsection = GAME_SECTION_PLAY_2P;
JA_StopMusic();
break;
case 2: // QUIT
mSection.name = PROG_SECTION_QUIT;
JA_StopMusic();
break;
case 3: // TIME OUT
mCounter = TITLE_COUNTER;
mMenu.active->reset();
if (mDemo)
{
runDemoGame();
runInstructions(INSTRUCTIONS_MODE_AUTO);
init(false);
}
else
mSection.name = PROG_SECTION_LOGO;
break;
default:
break;
}
}
// Comprueba las entradas para el menu
if (mMenuVisible == true)
mMenu.active->checkInput();
// Comprueba si se ha seleccionado algún item del menú
if (mMenu.active->getName() == "TITLE")
{
switch (mMenu.active->getItemSelected())
{
case 0: // 1 PLAYER
mPostFade = 0;
mFade->activateFade();
break;
case 1: // 2 PLAYERS
mPostFade = 1;
mFade->activateFade();
break;
case 2: // OPTIONS
mMenu.active = mMenu.options;
mOptions->fullScreenModePrevious = mOptions->fullScreenMode;
mOptions->windowSizePrevious = mOptions->windowSize;
mOptions->languagePrevious = mOptions->language;
break;
case 3: // HOW TO PLAY
runInstructions(INSTRUCTIONS_MODE_MANUAL);
break;
case 4: // QUIT
mPostFade = 2;
mFade->activateFade();
break;
default:
break;
}
}
// Comprueba si se ha seleccionado algún item de opciones
if (mMenu.active->getName() == "OPTIONS")
{
switch (mMenu.active->getItemSelected())
{
case 0: // Fullscreen mode
switchFullScreenModeVar();
updateMenuLabels();
break;
case 1: // Windows size
mOptions->windowSize++;
if (mOptions->windowSize == 5)
mOptions->windowSize = 1;
updateMenuLabels();
break;
case 2: // Language
mOptions->language++;
if (mOptions->language == 3)
mOptions->language = 0;
updateMenuLabels();
break;
case 3: // OK
applyOptions();
mMenu.active->reset();
mMenu.active = mMenu.title;
break;
case 4: // CANCEL
mOptions->fullScreenMode = mOptions->fullScreenModePrevious;
mOptions->windowSize = mOptions->windowSizePrevious;
mOptions->language = mOptions->languagePrevious;
updateMenuLabels();
mMenu.active->reset();
mMenu.active = mMenu.title;
break;
default:
break;
}
}
if (mMenu.active->getName() == "TITLE")
{
mCounter--;
}
}
// Limpia la pantalla
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(mRenderer);
// Pinta el tileado de fondo
switch (mBackgroundMode)
{
case 0: // El tileado de fondo se desplaza en diagonal
mBackgroundWindow.x++;
mBackgroundWindow.x %= 64;
mBackgroundWindow.y++;
mBackgroundWindow.y %= 64;
break;
case 1: // El tileado de fondo se desplaza en circulo
++mBackgroundCounter %= 360;
mBackgroundWindow.x = 128 + (int(mSin[(mBackgroundCounter + 270) % 360] * 128));
mBackgroundWindow.y = 96 + (int(mSin[(360 - mBackgroundCounter) % 360] * 96));
break;
default:
break;
}
SDL_RenderCopy(mRenderer, mBackground, &mBackgroundWindow, NULL);
// Dibuja los objetos
mCoffeeBitmap->render();
mCrisisBitmap->render();
if (mMenuVisible == true)
mMenu.active->render();
mDustBitmapR->animate(0);
mDustBitmapL->animate(0);
mDustBitmapR->render();
mDustBitmapL->render();
// PRESS ANY KEY!
if ((mCounter % 50 > 14) && (mMenuVisible == false))
mText->writeDX(TXT_CENTER | TXT_SHADOW, SCREEN_CENTER_X, PLAY_AREA_THIRD_QUARTER_Y + BLOCK, mTextStrings[23], 0, noColor, 1, shdwTxtColor);
// Texto con el copyright y versión
mText->writeDX(TXT_CENTER | TXT_SHADOW, SCREEN_CENTER_X, SCREEN_HEIGHT - (BLOCK * 2), TEXT_COPYRIGHT, 0, noColor, 1, shdwTxtColor);
// Fade
mFade->render();
// Actualiza la pantalla
SDL_RenderPresent(mRenderer);
}
else if (mCounter == 0)
{
if (mDemo)
{
runDemoGame();
runInstructions(INSTRUCTIONS_MODE_AUTO);
init(false);
}
else
mSection.name = PROG_SECTION_LOGO;
}
}
// Sección Instrucciones
if (mSection.subsection == TITLE_SECTION_INSTRUCTIONS)
{
runInstructions(INSTRUCTIONS_MODE_AUTO);
init();
}
}
return mSection;
}
// Ejecuta la parte donde se muestran las instrucciones
void Title::runInstructions(Uint8 mode)
{
mInstructions = new Instructions(mRenderer, mFileList, mTextStrings);
mInstructions->run(mode);
delete mInstructions;
}
// Ejecuta el juego en modo demo
void Title::runDemoGame()
{
mDemoGame = new Game(1, mRenderer, mFileList, mTextStrings, mInput, mInput, true);
mDemoGame->run();
delete mDemoGame;
}

105
source/title.h Normal file
View File

@@ -0,0 +1,105 @@
#pragma once
#include "ifdefs.h"
#include "const.h"
#include "utils.h"
#include "sprite.h"
#include "movingsprite.h"
#include "smartsprite.h"
#include "item.h"
#include "text.h"
#include "menu.h"
#include "fade.h"
#include "input.h"
#include "instructions.h"
#include "game.h"
#include "jail_audio.h"
#ifndef TITLE_H
#define TITLE_H
// Title
class Title
{
private:
SDL_Window *mWindow; // Ventana de la aplicación
AnimatedSprite *mDustBitmapL; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
AnimatedSprite *mDustBitmapR; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
bool mMenuVisible; // Indicador para saber si se muestra el menu del titulo o la frase intermitente
float mSin[360]; // Vector con los valores del seno precalculados
JA_Music mMusic; // Musica para el titulo
JA_Sound mSound; // Sonido con el impacto del título
LTexture *mItemsTexture; // Textura con los gráficos de los items para las instrucciones
LTexture *mTitleTexture; // Textura con los graficos para el titulo
LTexture *mTextTexture; // Textura con los gráficos para el texto
SDL_Event *mEventHandler; // Manejador de eventos
SDL_Rect mBackgroundWindow; // Ventana visible para la textura de fondo del titulo
SDL_Renderer *mRenderer; // El renderizador de la ventana
//SDL_Texture *mBackbuffer; // Textura para usar como backbuffer
SDL_Texture *mBackground; // Textura dibujar el fondo del titulo
SmartSprite *mCoffeeBitmap; // Sprite con la palabra COFFEE para la pantalla de titulo
SmartSprite *mCrisisBitmap; // Sprite con la palabra CRISIS para la pantalla de titulo
Sprite *mTile; // Sprite para dibujar el fondo de pantalla del título
std::string *mFileList; // Lista de ficheros
std::string *mTextStrings; // Vector con los textos del juego
Uint16 mBackgroundCounter; // Temporizador para el fondo de tiles de la pantalla de titulo
Uint16 mCounter; // Temporizador para la pantalla de titulo
Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa
Uint8 mBackgroundMode; // Variable para almacenar el tipo de efecto que hará el fondo de la pantalla de titulo
Uint8 mEvents[TITLE_TOTAL_EVENTS]; // Vector para coordinar los eventos de la pantalla de titulo
bool mDemo; // Indica si el modo demo estará activo
section_t mSection; // Indicador para el bucle del titulo
section_t mNextSection; // Indica cual es la siguiente sección a cargar cuando termine el contador del titulo
Uint8 mTicksSpeed; // Velocidad a la que se repiten los bucles del programa
Text *mText; // Objeto de texto para poder escribir textos en pantalla
Fade *mFade; // Objeto para realizar fundidos en pantalla
Uint8 mPostFade; // Opción a realizar cuando termina el fundido
Input *mInput; // Objeto para leer las entradas de teclado o mando
Instructions *mInstructions; // Objeto para la sección de las instrucciones
Game *mDemoGame; // Objeto para lanzar la demo del juego
struct menu_t
{
Menu *title; // Menu de la pantalla de título
Menu *options; // Menú de la pantalla de opciones
Menu *active; // Menu activo (de momento para la pantalla del titulo)
bool keyPressed; // Variable para evitar la repetición de teclas en los menus
};
menu_t mMenu; // Variable con todos los objetos menus y sus variables
struct options_t *mOptions; // Variable con todas las variables de las opciones del programa
// Carga los recursos necesarios para la sección 'Title'
bool loadMedia();
// Cambia el valor de la variable de modo de pantalla completa
void switchFullScreenModeVar();
// Actualiza los elementos de los menus
void updateMenuLabels();
// Aplica las opciones de menu seleccionadas
void applyOptions();
// Ejecuta la parte donde se muestran las instrucciones
void runInstructions(Uint8 mode);
// Ejecuta el juego en modo demo
void runDemoGame();
public:
// Constructor
Title(SDL_Window *window, SDL_Renderer *renderer, Input *input, std::string *fileList, options_t *options, std::string *textStrings);
// Destructor
~Title();
// Inicializa las variables necesarias para la sección 'Title'
void init(bool demo = true, Uint8 subsection = TITLE_SECTION_1);
// Bucle para el titulo del juego
section_t run(Uint8 subsection = TITLE_SECTION_1);
};
#endif

View File

@@ -109,4 +109,16 @@ bool checkCollision(SDL_Rect &a, SDL_Rect &b)
//If none of the sides from A are outside B
return true;
}
// Carga un archivo de imagen en una textura
bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer)
{
bool success = true;
if (!texture->loadFromFile(path, renderer))
{
printf("Failed to load %s texture!\n", path.c_str());
success = false;
}
return success;
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "ifdefs.h"
#include "ltexture.h"
#ifndef UTILS_H
#define UTILS_H
@@ -12,20 +13,19 @@ struct circle_t
Uint8 r;
};
// Estructura para definir todas las entradas que aceptará el programa
struct input_t
// Estructura para definir un color
struct color_t
{
Uint8 up;
Uint8 down;
Uint8 left;
Uint8 right;
Uint8 escape;
Uint8 pause;
Uint8 fire;
Uint8 fireLeft;
Uint8 fireRight;
Uint8 accept;
Uint8 cancel;
Uint8 r;
Uint8 g;
Uint8 b;
};
// Estructura para saber la seccion y subseccion del programa
struct section_t
{
Uint8 name;
Uint8 subsection;
};
// Estructura para mapear el teclado usado en la demo
@@ -39,6 +39,17 @@ struct demoKeys_t
Uint8 fireRight;
};
// Estructura con todas las opciones de configuración del programa
struct options_t
{
Uint32 fullScreenMode; // Contiene el valor del modo de pantalla completa
Uint32 fullScreenModePrevious; // Usado por si se cancelan los cambios en el menu de opciones
Uint8 windowSize; // Contiene el valor del tamaño de la ventana
Uint8 windowSizePrevious; // Usado por si se cancelan los cambios en el menu de opciones
Uint8 language; // Idioma usado en el juego
Uint8 languagePrevious; // Usado por si se cancelan los cambios en el menu de opciones
};
// Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2);
@@ -51,4 +62,7 @@ bool checkCollision(circle_t &a, SDL_Rect &b);
// Detector de colisiones entre un dos rectangulos
bool checkCollision(SDL_Rect a, SDL_Rect b);
// Carga un archivo de imagen en una textura
bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer);
#endif

36
sync.sh
View File

@@ -1,36 +0,0 @@
#!/bin/bash
readonly PROJECT=coffee_crisis
readonly USAGE="
USAGE:
$(basename "$0") [UPLOAD or DOWNLOAD]"
function help_message() {
echo "$USAGE"
}
PARAMETERS="UPLOAD DOWNLOAD upload download"
# check if there are all the parameters
if [ "$#" -ne 1 ]; then
help_message
exit 0
fi
# check if the systems parameter is valid
if ! echo "$PARAMETERS" | grep -w "$1" >/dev/null; then
help_message
exit 0
fi
# UPLOAD
if [ "$1" = upload ] || [ "$1" = UPLOAD ]; then
printf "\n%s\n" "uploading $PROJECT"
rsync -azmPu --delete -e 'ssh -p 4545' . sergio@sustancia.synology.me:/home/sergio/backup/code/$PROJECT/
rsync -azmPu -e 'ssh -p 4545' . sergio@sustancia.synology.me:/home/sergio/backup/code/$PROJECT.all/
fi
if [ "$1" = download ] || [ "$1" = DOWNLOAD ]; then
printf "%s\n" "downloading $PROJECT"
rsync -azmP --delete -e 'ssh -p 4545' sergio@sustancia.synology.me:/home/sergio/backup/code/$PROJECT/* .
fi