26 Commits

Author SHA1 Message Date
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
8099e6dab6 v1.4 2021-03-17 13:51:01 +01:00
965ed711f7 v1.4 2021-03-17 12:34:11 +01:00
a3e608b01e before change player animation 2021-02-26 22:48:52 +01:00
765b64c29c code reorganized 2021-02-26 17:51:46 +01:00
190f1e9a47 bugfix: player could fire and get items after death 2021-02-20 19:04:13 +01:00
a8eff04d6a added .gitignore 2021-02-19 09:37:58 +01:00
73 changed files with 8800 additions and 5935 deletions

13
.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
.vscode
bin
data/config.bin
data/score.bin
dll
docs
gfx
icon
releases
resources
scripts
*.opk
*.DS_Store

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,9 +23,9 @@ En Linux:
make linux
```
En macos:
En macOS:
```bash
make macos
make macOS
```
## Como ejecutar
@@ -40,4 +40,4 @@ A los jailers y a la jail. Y entre ellos, a JailDoctor por estar siempre ahí ap
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.
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: 16 KiB

After

Width:  |  Height:  |  Size: 57 KiB

BIN
media/gfx/font_black_x2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

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

BIN
media/gfx/font_white_x2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

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,60 +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
kenney_digitalaudio/phaserUp2.ogg
www.kenney.nl
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.

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,12 +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;
for (Uint8 j = 0; i < 20; i++)
mAnimation[i].completed = false;
for (int j = 0; i < 20; i++)
{
mAnimation[i].frames[j].x = 0;
mAnimation[i].frames[j].y = 0;
@@ -39,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++;
}
}
}
@@ -105,6 +104,18 @@ void AnimatedSprite::setAnimationLoop(Uint8 index, bool loop)
mAnimation[index].loop = loop;
}
// Establece el valor de la variable
void AnimatedSprite::setCompleted(Uint8 index, bool value)
{
mAnimation[index].completed = value;
}
// Comprueba si ha terminado la animación
bool AnimatedSprite::isCompleted(Uint8 index)
{
return mAnimation[index].completed;
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(Uint8 index_animation, Uint8 index_frame)
{

View File

@@ -5,9 +5,26 @@
#ifndef ANIMATEDSPRITE_H
#define ANIMATEDSPRITE_H
#define MAX_FRAMES 30
#define MAX_ANIMATIONS 20
// Clase AnimatedSprite
class AnimatedSprite : public MovingSprite
{
private:
struct sAnimation
{
SDL_Rect frames[MAX_FRAMES]; // Cada uno de los frames que componen la animación
Uint8 numFrames; // Numero de frames que componen la animación
Uint8 speed; // Velocidad de la animación
bool loop; // Indica si la animación se reproduce en bucle
bool completed; // Indica si ha finalizado la animación
};
sAnimation mAnimation[MAX_ANIMATIONS]; // Vector con las diferentes animaciones
Uint8 mCurrentFrame; // Frame actual
Uint16 mAnimationCounter; // Contador para las animaciones
public:
// Constructor
AnimatedSprite();
@@ -39,26 +56,14 @@ public:
// Establece si la animación se reproduce en bucle
void setAnimationLoop(Uint8 index, bool loop);
// Establece el valor de la variable
void setCompleted(Uint8 index, bool value);
// Comprueba si ha terminado la animación
bool isCompleted(Uint8 index);
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(Uint8 index_animation, Uint8 index_frame);
private:
struct sAnimation
{
SDL_Rect frames[20]; // Hasta 20 frames
Uint8 numFrames;
Uint8 speed;
bool loop;
};
// Vector con las diferentes animaciones y los diferentes frames de cada animación
sAnimation mAnimation[20]; // Hasta 20 animaciones
// Frame actual
Uint8 mCurrentFrame;
// Contador para las animaciones
Uint16 mAnimationCounter;
};
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,73 @@
#pragma once
#include "struct.h"
#include "utils.h"
#include "animatedsprite.h"
#ifndef BALLOON_H
#define BALLOON_H
#define MAX_BOUNCE 10
// Clase globo
class Balloon
{
private:
float mPosX; // Posición en el eje X
float mPosY; // Posición en el eje Y
Uint8 mWidth; // Ancho
Uint8 mHeight; // Alto
float mVelX; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float mVelY; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
float mGravity; // Aceleración en el eje Y. Modifica la velocidad
float mDefaultVelY; // Velocidad inicial que tienen al rebotar contra el suelo
float mMaxVelY; // Máxima velocidad que puede alcanzar el objeto en el eje Y
AnimatedSprite *mSprite; // Sprite del objeto globo
bool mBeingCreated; // Indica si el globo se está creando
bool mBlinking; // Indica si el globo está intermitente
bool mEnabled; // Indica si el globo esta activo
bool mInvulnerable; // Indica si el globo es invulnerable
bool mPopping; // Indica si el globo está explotando
bool mStopped; // Indica si el globo está parado
bool mVisible; // Indica si el globo es visible
circle_t mCollider; // Circulo de colisión del objeto
Uint16 mCreationCounter; // Temporizador para controlar el estado "creandose"
Uint16 mCreationCounterIni; // Valor inicial para el temporizador para controlar el estado "creandose"
Uint16 mScore; // Puntos que da el globo al ser destruido
Uint16 mStoppedCounter; // Contador para controlar el estado "parado"
Uint16 mTimeToLive; // Indica el tiempo de vida que le queda al globo
Uint8 mKind; // Tipo de globo
Uint8 mMenace; // Cantidad de amenaza que genera el globo
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
{
bool enabled; // Si el efecto está activo
Uint8 counter; // Countador para el efecto
Uint8 speed; // Velocidad a la que transcurre el efecto
float zoomW; // Zoom aplicado a la anchura
float zoomH; // Zoom aplicado a la altura
float despX; // Desplazamiento de pixeles en el eje X antes de pintar el objeto con zoom
float despY; // idem
// Vector con los valores de zoom para el ancho y alto del globo
float w[MAX_BOUNCE] = {1.10f, 1.05f, 1.00f, 0.95f, 0.90f, 0.95f, 1.00f, 1.02f, 1.05f, 1.02f};
float h[MAX_BOUNCE] = {0.90f, 0.95f, 1.00f, 1.05f, 1.10f, 1.05f, 1.00f, 0.98f, 0.95f, 0.98f};
};
bouncing mBouncing;
void updateColliders(); // Alinea el circulo de colisión con la posición del objeto globo
void bounceStart(); // Activa el efecto
void bounceStop(); // Detiene el efecto
void updateBounce(); // Aplica el efecto
void updateState(); // Actualiza los estados del globo
void updateAnimation(); // Establece la animación correspondiente
void setBeingCreated(bool state); // Establece el valor de la variable
void setTimeToLive(Uint16 time); // Establece el valor de la variable
Uint16 getTimeToLive(); // Obtiene del valor de la variable
public:
// Constructor
Balloon();
@@ -16,7 +76,7 @@ public:
~Balloon();
// Inicializador
void init(float x, int y, Uint8 kind, float velx, Uint16 creationtimer, LTexture* texture, SDL_Renderer *renderer);
void init(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, LTexture *texture, SDL_Renderer *renderer);
// Centra el globo en la posición X
void allignTo(int x);
@@ -27,8 +87,8 @@ public:
// Actualiza la posición y estados del globo
void move();
// Pone a cero todos los valores del globo
void erase();
// Deshabilita el globo y pone a cero todos los valores
void disable();
// Explosiona el globo
void pop();
@@ -36,17 +96,14 @@ public:
// Actualiza al globo a su posicion, animación y controla los contadores
void update();
// Establece la animación correspondiente
void setAnimation();
// Comprueba si el globo tiene algun tipo asignado
bool isActive();
// Comprueba si el globo está habilitado
bool isEnabled();
// Obtiene del valor de la variable
int getPosX();
float getPosX();
// Obtiene del valor de la variable
int getPosY();
float getPosY();
// Obtiene del valor de la variable
float getVelY();
@@ -60,9 +117,18 @@ public:
// Establece el valor de la variable
void setVelY(float velY);
// Establece el valor de la variable
void setSpeed(float speed);
// 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();
// Establece el valor de la variable
void setStop(bool state);
@@ -87,9 +153,6 @@ public:
// Obtiene del valor de la variable
bool isInvulnerable();
// Establece el valor de la variable
void setBeingCreated(bool state);
// Obtiene del valor de la variable
bool isBeingCreated();
@@ -99,12 +162,6 @@ public:
// Obtiene del valor de la variable
bool isPopping();
// Establece el valor de la variable
void setTimeToLive(Uint16 time);
// Obtiene del valor de la variable
Uint16 getTimeToLive();
// Establece el valor de la variable
void setStoppedTimer(Uint16 time);
@@ -115,71 +172,13 @@ public:
Uint16 getScore();
// Obtiene el circulo de colisión
Circle &getCollider();
circle_t &getCollider();
// Obtiene le valor de la variable
Uint8 getMenace();
private:
// Posición X,Y del objeto globo
float mPosX;
int mPosY;
// Alto y ancho del objeto globo
Uint8 mWidth;
Uint8 mHeight;
// Variables para controlar la velocidad del globo
float mVelX;
float mVelY;
float mGravity;
float mDefaultVelY;
int mMaxVelY;
// Puntos que da el globo al ser destruido
Uint16 mScore;
// Nivel de amenaza del globo
Uint8 mMenace;
// Indica si el globo está parado
bool mStopped;
// Temporizador para controlar el estado "parado"
Uint16 mStoppedTimer;
// Indica si el globo está intermitente
bool mBlinking;
// Indica si el globo es visible
bool mVisible;
// Indica si el globo es invulnerable
bool mInvulnerable;
// Indica si el globo se está creando
bool mBeingCreated;
// Indica si el globo está explotando
bool mPopping;
// Indica el tiempo de vida que le queda al globo
Uint16 mTimeToLive;
// Temporizador para controlar el estado "creandose"
Uint16 mCreationTimer;
// Tipo de globo
Uint8 mKind;
// Sprite del objeto globo
AnimatedSprite *mSprite;
// Circulo de colisión del objeto
Circle mCollider;
// Alinea el circulo de colisión con la posición del objeto globo
void shiftColliders();
// Obtiene le valor de la variable
Uint8 getPower();
};
#endif

View File

@@ -5,14 +5,16 @@
Bullet::Bullet()
{
mSprite = new Sprite();
init(0, 0, NO_KIND, nullptr, nullptr);
//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
@@ -200,7 +202,7 @@ int Bullet::getKind()
}
// Obtiene el circulo de colisión
Circle &Bullet::getCollider()
circle_t &Bullet::getCollider()
{
return mCollider;
}

View File

@@ -1,5 +1,5 @@
#pragma once
#include "struct.h"
#include "utils.h"
#include "sprite.h"
#ifndef BULLET_H
@@ -49,7 +49,7 @@ public:
int getKind();
// Obtiene el circulo de colisión
Circle &getCollider();
circle_t &getCollider();
private:
// Posición X/Y del objeto
@@ -71,7 +71,7 @@ private:
Sprite *mSprite;
// Balloon's collision circle
Circle mCollider;
circle_t mCollider;
// Alinea el circulo de colisión con el objeto
void shiftColliders();

89
source/coffeedrop.cpp Normal file
View File

@@ -0,0 +1,89 @@
#include "const.h"
#include "coffeedrop.h"
#ifndef UNUSED
// Constructor
CoffeeDrop::CoffeeDrop()
{
mPosX = 0;
mPosY = 0;
mWidth = 8;
mHeight = 8;
mVelX = 0;
mVelY = 0;
mGravity = 0.1f;
mFloor = 0;
mEnabled = false;
mSprite = new Sprite();
mAlpha = 128;
}
// Destructor
CoffeeDrop::~CoffeeDrop()
{
delete mSprite;
}
// Inicializador
void CoffeeDrop::init(LTexture *texture, SDL_Renderer *renderer, float x, float y, float velX, float velY, int floor)
{
mEnabled = true;
mPosX = x;
mPosY = y;
mVelX = velX;
mVelY = velY;
mFloor = floor;
mSprite->setRenderer(renderer);
mSprite->setTexture(texture);
mSprite->setSpriteClip(256, 97, mWidth, mHeight);
mSprite->setPosX(x);
mSprite->setPosY(y);
}
// Actualiza las variables del objeto
void CoffeeDrop::update()
{
if (mEnabled)
{
mVelY += mGravity;
mPosX += mVelX;
mPosY += mVelY;
mSprite->setPosX((int)mPosX);
mSprite->setPosY((int)mPosY);
if ((mPosY > mFloor) || (mPosX > PLAY_AREA_RIGHT) || ((mPosX - mWidth) < PLAY_AREA_LEFT))
mEnabled = false;
mAlpha -= 2;
if (mAlpha == 0)
mEnabled = false;
}
}
// Pinta el objeto
void CoffeeDrop::render()
{
if (mEnabled)
{
mSprite->getTexture()->setAlpha(mAlpha);
mSprite->render();
mSprite->getTexture()->setAlpha(255);
}
}
// Deshabilita el objeto
void CoffeeDrop::disable()
{
mEnabled = false;
}
// Comprueba si està habilitado
bool CoffeeDrop::isEnabled()
{
return mEnabled;
}
#endif

50
source/coffeedrop.h Normal file
View File

@@ -0,0 +1,50 @@
#pragma once
#include "sprite.h"
#ifndef COFFEEDROP_H
#define COFFEEDROP_H
#ifndef UNUSED
// Clase CoffeeDrop. Gotas de café que aparecen al explotar un globo
class CoffeeDrop
{
private:
float mPosX; // Posicion en el eje X del objeto
float mPosY; // Posicion en el eje Y del objeto
Uint8 mWidth; // Ancho del sprite
Uint8 mHeight; // Alto del sprite
float mVelX; // Velocidad en el eje X
float mVelY; // Velocidad en el eje Y
float mGravity; // Aceleración en el eje Y
int mFloor; // Punto donde se encuentra el suelo y desaparecen
bool mEnabled; // Si esta habilitado. Sirve para saber si se pinta, se actualiza o se puede usar
Sprite *mSprite; // Puntero al sprite con los graficos
Uint8 mAlpha;
public:
// Constructor
CoffeeDrop();
// Destructor
~CoffeeDrop();
// Inicializador
void init(LTexture *texture, SDL_Renderer *renderer, float x, float y, float velX, float velY, int floor);
// Actualiza las variables del objeto
void update();
// Pinta el objeto
void render();
// Deshabilita el objeto
void disable();
// Comprueba si està habilitado
bool isEnabled();
};
#endif
#endif

View File

@@ -1,5 +1,7 @@
#pragma once
#include "ifdefs.h"
#include "utils.h"
#include "lang.h"
#include <string>
#ifndef CONST_H
@@ -7,73 +9,77 @@
// Textos
#define WINDOW_CAPTION "Coffee Crisis"
#define TEXT_COPYRIGHT "@2020,2021 JAILDESIGNER (V1.3*)"
#define TEXT_COPYRIGHT "@2020,2021 JAILDESIGNER (V1.5)"
// Recursos
const Uint8 BINFILE_SCORE = 0;
const Uint8 BINFILE_DEMO = 1;
const Uint8 BINFILE_CONFIG = 2;
#define BINFILE_SCORE 0
#define BINFILE_DEMO 1
#define BINFILE_CONFIG 2
const Uint8 TOTAL_BINFILE = 3;
#define TOTAL_BINFILE 3
const Uint8 MUSIC_INTRO = 0;
const Uint8 MUSIC_PLAYING = 1;
const Uint8 MUSIC_TITLE = 2;
#define MUSIC_INTRO 0
#define MUSIC_PLAYING 1
#define MUSIC_TITLE 2
const Uint8 TOTAL_MUSIC = 3;
#define TOTAL_MUSIC 3
const Uint8 SOUND_BALLON = 0;
const Uint8 SOUND_BULLET = 1;
const Uint8 SOUND_MENU_SELECT = 2;
const Uint8 SOUND_MENU_CANCEL = 3;
const Uint8 SOUND_MENU_MOVE = 4;
const Uint8 SOUND_TITLE = 5;
const Uint8 SOUND_PLAYER_COLLISION = 6;
const Uint8 SOUND_HISCORE = 7;
const Uint8 SOUND_ITEM_DROP = 8;
const Uint8 SOUND_ITEM_PICKUP = 9;
const Uint8 SOUND_COFFEE_OUT = 10;
const Uint8 SOUND_STAGE_CHANGE = 11;
const Uint8 SOUND_BUBBLE1 = 12;
const Uint8 SOUND_BUBBLE2 = 13;
const Uint8 SOUND_BUBBLE3 = 14;
const Uint8 SOUND_BUBBLE4 = 15;
#define SOUND_BALLOON 0
#define SOUND_BUBBLE1 1
#define SOUND_BUBBLE2 2
#define SOUND_BUBBLE3 3
#define SOUND_BUBBLE4 4
#define SOUND_BULLET 5
#define SOUND_COFFEE_OUT 6
#define SOUND_HISCORE 7
#define SOUND_ITEM_DROP 8
#define SOUND_ITEM_PICKUP 9
#define SOUND_MENU_CANCEL 10
#define SOUND_MENU_MOVE 11
#define SOUND_MENU_SELECT 12
#define SOUND_PLAYER_COLLISION 13
#define SOUND_STAGE_CHANGE 14
#define SOUND_TITLE 15
#define SOUND_CLOCK 16
#define SOUND_POWERBALL 17
const Uint8 TOTAL_SOUND = 16;
#define TOTAL_SOUND 18
const Uint8 TEXTURE_BALLOON = 0;
const Uint8 TEXTURE_BULLET = 1;
const Uint8 TEXTURE_FONT_BLACK = 2;
const Uint8 TEXTURE_FONT_NOKIA = 3;
const Uint8 TEXTURE_FONT_WHITE = 4;
const Uint8 TEXTURE_GAME_BG = 5;
const Uint8 TEXTURE_GAME_TEXT = 6;
const Uint8 TEXTURE_INTRO = 7;
const Uint8 TEXTURE_ITEMS = 8;
const Uint8 TEXTURE_LOGO = 9;
const Uint8 TEXTURE_MENU = 10;
const Uint8 TEXTURE_PLAYER_BODY = 11;
const Uint8 TEXTURE_PLAYER_LEGS = 12;
const Uint8 TEXTURE_PLAYER_DEATH = 13;
const Uint8 TEXTURE_TITLE = 14;
#define TEXTURE_BALLOON 0
#define TEXTURE_BULLET 1
#define TEXTURE_FONT_BLACK 2
#define TEXTURE_FONT_BLACK_X2 3
#define TEXTURE_FONT_NOKIA 4
#define TEXTURE_FONT_WHITE 5
#define TEXTURE_FONT_WHITE_X2 6
#define TEXTURE_GAME_BG 7
#define TEXTURE_GAME_TEXT 8
#define TEXTURE_INTRO 9
#define TEXTURE_ITEMS 10
#define TEXTURE_LOGO 11
#define TEXTURE_MENU 12
#define TEXTURE_PLAYER_BODY 13
#define TEXTURE_PLAYER_DEATH 14
#define TEXTURE_PLAYER_LEGS 15
#define TEXTURE_TITLE 16
const Uint8 TOTAL_TEXTURE = 15;
#define TOTAL_TEXTURE 17
// Tamaño de bloque
const Uint8 BLOCK = 8;
const Uint8 HALF_BLOCK = BLOCK / 2;
#define BLOCK 8
#define HALF_BLOCK BLOCK / 2
// Tamaño de la pantalla real
const int SCREEN_WIDTH = 256;
const int SCREEN_HEIGHT = SCREEN_WIDTH * 3 / 4; // 192
#define SCREEN_WIDTH 256
const int SCREEN_HEIGHT = SCREEN_WIDTH * 3 / 4;
// Tamaño de la pantalla que se muestra
const int VIEW_WIDTH = SCREEN_WIDTH * 3; // 768
const int VIEW_HEIGHT = SCREEN_HEIGHT * 3; // 576
const int VIEW_WIDTH = SCREEN_WIDTH * 3;
const int VIEW_HEIGHT = SCREEN_HEIGHT * 3;
// Cantidad de enteros a escribir en los ficheros de datos
const Uint8 TOTAL_SCORE_DATA = 3;
const Uint16 TOTAL_DEMO_DATA = 2000;
#define TOTAL_SCORE_DATA 3
#define TOTAL_DEMO_DATA 2000
// Zona de juego
const int PLAY_AREA_TOP = (0 * BLOCK);
@@ -82,7 +88,9 @@ const int PLAY_AREA_LEFT = (0 * BLOCK);
const int PLAY_AREA_RIGHT = SCREEN_WIDTH - (0 * BLOCK);
const int PLAY_AREA_WIDTH = PLAY_AREA_RIGHT - PLAY_AREA_LEFT;
const int PLAY_AREA_HEIGHT = PLAY_AREA_BOTTOM - PLAY_AREA_TOP;
const int PLAY_AREA_CENTER_X = PLAY_AREA_LEFT + (PLAY_AREA_WIDTH / 2);
const int PLAY_AREA_CENTER_X = PLAY_AREA_LEFT + (PLAY_AREA_WIDTH / 2);
const int PLAY_AREA_CENTER_FIRST_QUARTER_X = (PLAY_AREA_WIDTH / 4);
const int PLAY_AREA_CENTER_THIRD_QUARTER_X = (PLAY_AREA_WIDTH / 4) * 3;
const int PLAY_AREA_CENTER_Y = PLAY_AREA_TOP + (PLAY_AREA_HEIGHT / 2);
const int PLAY_AREA_FIRST_QUARTER_Y = PLAY_AREA_HEIGHT / 4;
const int PLAY_AREA_THIRD_QUARTER_Y = (PLAY_AREA_HEIGHT / 4) * 3;
@@ -95,95 +103,89 @@ const int SCREEN_CENTER_Y = SCREEN_HEIGHT / 2;
const int SCREEN_FIRST_QUARTER_Y = SCREEN_HEIGHT / 4;
const int SCREEN_THIRD_QUARTER_Y = (SCREEN_HEIGHT / 4) * 3;
// Color transparente para los sprites
const Uint8 COLOR_KEY_R = 0xff;
const Uint8 COLOR_KEY_G = 0x00;
const Uint8 COLOR_KEY_B = 0xff;
// Opciones de menu
const int MENU_NO_OPTION = -1;
const int MENU_OPTION_START = 0;
const int MENU_OPTION_QUIT = 1;
const int MENU_OPTION_TOTAL = 2;
// Selector de menu
const int MENU_SELECTOR_BLACK = (BLOCK * 0);
const int MENU_SELECTOR_WHITE = (BLOCK * 1);
#define MENU_NO_OPTION -1
#define MENU_OPTION_START 0
#define MENU_OPTION_QUIT 1
#define MENU_OPTION_TOTAL 2
// Tipos de fondos para el menu
const int MENU_BACKGROUND_TRANSPARENT = 0;
const int MENU_BACKGROUND_SOLID = 1;
#define MENU_BACKGROUND_TRANSPARENT 0
#define MENU_BACKGROUND_SOLID 1
// Estados del jugador
const Uint8 PLAYER_STATUS_WALKING_LEFT = 0;
const Uint8 PLAYER_STATUS_WALKING_RIGHT = 1;
const Uint8 PLAYER_STATUS_WALKING_STOP = 2;
#define PLAYER_STATUS_WALKING_LEFT 0
#define PLAYER_STATUS_WALKING_RIGHT 1
#define PLAYER_STATUS_WALKING_STOP 2
const Uint8 PLAYER_STATUS_FIRING_UP = 0;
const Uint8 PLAYER_STATUS_FIRING_LEFT = 1;
const Uint8 PLAYER_STATUS_FIRING_RIGHT = 2;
const Uint8 PLAYER_STATUS_FIRING_NO = 3;
#define PLAYER_STATUS_FIRING_UP 0
#define PLAYER_STATUS_FIRING_LEFT 1
#define PLAYER_STATUS_FIRING_RIGHT 2
#define PLAYER_STATUS_FIRING_NO 3
const Uint8 PLAYER_ANIMATION_LEGS_WALKING_LEFT = 0;
const Uint8 PLAYER_ANIMATION_LEGS_WALKING_RIGHT = 1;
const Uint8 PLAYER_ANIMATION_LEGS_WALKING_STOP = 2;
#define PLAYER_ANIMATION_LEGS_WALKING_LEFT 0
#define PLAYER_ANIMATION_LEGS_WALKING_RIGHT 1
#define PLAYER_ANIMATION_LEGS_WALKING_STOP 2
const Uint8 PLAYER_ANIMATION_BODY_WALKING_LEFT = 0;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_LEFT = 1;
const Uint8 PLAYER_ANIMATION_BODY_WALKING_RIGHT = 2;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_RIGHT = 3;
const Uint8 PLAYER_ANIMATION_BODY_WALKING_STOP = 4;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_UP = 5;
const Uint8 PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT = 6;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT = 7;
const Uint8 PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT = 8;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT = 9;
const Uint8 PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT = 10;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT = 11;
#define PLAYER_ANIMATION_BODY_WALKING_LEFT 0
#define PLAYER_ANIMATION_BODY_FIRING_LEFT 1
#define PLAYER_ANIMATION_BODY_WALKING_RIGHT 2
#define PLAYER_ANIMATION_BODY_FIRING_RIGHT 3
#define PLAYER_ANIMATION_BODY_WALKING_STOP 4
#define PLAYER_ANIMATION_BODY_FIRING_UP 5
// Variables del jugador
const Uint16 PLAYER_INVULNERABLE_TIMER = 200;
#define PLAYER_INVULNERABLE_COUNTER 200
// Estados del juego
const Uint8 GAME_STATE_TITLE = 0;
const Uint8 GAME_STATE_PLAYING = 1;
const Uint8 GAME_STATE_QUIT = 2;
const Uint8 GAME_STATE_GAME_OVER_SCREEN = 3;
const Uint8 GAME_STATE_INTRO = 4;
const Uint8 GAME_STATE_DEMO = 5;
const Uint8 GAME_STATE_INSTRUCTIONS = 6;
const Uint8 GAME_STATE_LOGO = 7;
const Uint8 GAME_STATE_INIT = 8;
// 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
// Subsecciones
#define GAME_SECTION_PLAY 0
#define GAME_SECTION_PAUSE 1
#define GAME_SECTION_GAMEOVER 2
#define TITLE_SECTION_1 3
#define TITLE_SECTION_2 4
#define TITLE_SECTION_3 5
#define TITLE_SECTION_INSTRUCTIONS 6
// Modo para las instrucciones
#define INSTRUCTIONS_MODE_MANUAL 0
#define INSTRUCTIONS_MODE_AUTO 1
// Estados de cada elemento que pertenece a un evento
const Uint8 EVENT_WAITING = 1;
const Uint8 EVENT_RUNNING = 2;
const Uint8 EVENT_COMPLETED = 3;
#define EVENT_WAITING 1
#define EVENT_RUNNING 2
#define EVENT_COMPLETED 3
// Cantidad de eventos de la intro
const Uint8 INTRO_TOTAL_BITMAPS = 6;
const Uint8 INTRO_TOTAL_TEXTS = 9;
const Uint8 INTRO_TOTAL_EVENTS = INTRO_TOTAL_BITMAPS + INTRO_TOTAL_TEXTS;
#define INTRO_TOTAL_BITMAPS 6
#define INTRO_TOTAL_TEXTS 9
const int INTRO_TOTAL_EVENTS = INTRO_TOTAL_BITMAPS + INTRO_TOTAL_TEXTS;
// Cantidad de eventos de la pantalla de titulo
const Uint8 TITLE_TOTAL_EVENTS = 2;
#define TITLE_TOTAL_EVENTS 2
// Relaciones de Id con nomnbres
const Uint8 BITMAP0 = 0;
const Uint8 BITMAP1 = 1;
const Uint8 BITMAP2 = 2;
const Uint8 BITMAP3 = 3;
const Uint8 BITMAP4 = 4;
const Uint8 BITMAP5 = 5;
const Uint8 TEXT0 = 6;
const Uint8 TEXT1 = 7;
const Uint8 TEXT2 = 8;
const Uint8 TEXT3 = 9;
const Uint8 TEXT4 = 10;
const Uint8 TEXT5 = 11;
const Uint8 TEXT6 = 12;
const Uint8 TEXT7 = 13;
const Uint8 TEXT8 = 14;
#define BITMAP0 0
#define BITMAP1 1
#define BITMAP2 2
#define BITMAP3 3
#define BITMAP4 4
#define BITMAP5 5
#define TEXT0 6
#define TEXT1 7
#define TEXT2 8
#define TEXT3 9
#define TEXT4 10
#define TEXT5 11
#define TEXT6 12
#define TEXT7 13
#define TEXT8 14
// Anclajes para el marcador de puntos
const int SCORE_WORD_X = (SCREEN_WIDTH / 4) - ((5 * BLOCK) / 2);
@@ -198,85 +200,130 @@ const int HISCORE_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
const int MULTIPLIER_WORD_X = (SCREEN_WIDTH / 2) - ((4 * BLOCK) / 2);
const int MULTIPLIER_WORD_Y = SCREEN_HEIGHT - (3 * BLOCK) + 2;
const int MULTIPLIER_NUMBER_X = (SCREEN_WIDTH / 2) - ((3 * BLOCK) / 2);;
const int MULTIPLIER_NUMBER_X = (SCREEN_WIDTH / 2) - ((3 * BLOCK) / 2);
const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
// Ningun tipo
const Uint8 NO_KIND = 0;
#define NO_KIND 0
// Tipos de globo
const Uint8 BALLOON_1 = 1;
const Uint8 BALLOON_2 = 2;
const Uint8 BALLOON_3 = 3;
const Uint8 BALLOON_4 = 4;
#define BALLOON_1 1
#define BALLOON_2 2
#define BALLOON_3 3
#define BALLOON_4 4
#define HEXAGON_1 5
#define HEXAGON_2 6
#define HEXAGON_3 7
#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
// Velocidad del globo
const float BALLON_VELX_POSITIVE = 0.7f;
const float BALLON_VELX_NEGATIVE = -0.7f;
#define BALLOON_VELX_POSITIVE 0.7f
#define BALLOON_VELX_NEGATIVE -0.7f
// Indice para las animaciones de los globos
const Uint8 BALLOON_MOVING_ANIMATION = 0;
const Uint8 BALLOON_POP_ANIMATION = 1;
const Uint8 BALLOON_BORN_ANIMATION = 2;
#define BALLOON_MOVING_ANIMATION 0
#define BALLOON_POP_ANIMATION 1
#define BALLOON_BORN_ANIMATION 2
// Cantidad posible de globos
const Uint8 MAX_BALLOONS = 75;
#define MAX_BALLOONS 100
// Velocidades a las que se mueven los enemigos
#define BALLOON_SPEED_1 0.60f
#define BALLOON_SPEED_2 0.70f
#define BALLOON_SPEED_3 0.80f
#define BALLOON_SPEED_4 0.90f
#define BALLOON_SPEED_5 1.00f
// Tamaño de los globos
#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
const Uint8 BULLET_UP = 1;
const Uint8 BULLET_LEFT = 2;
const Uint8 BULLET_RIGHT = 3;
#define BULLET_UP 1
#define BULLET_LEFT 2
#define BULLET_RIGHT 3
// Cantidad posible de globos
const Uint8 MAX_BULLETS = 50;
#define MAX_BULLETS 50
// Tipos de objetos
const Uint8 ITEM_POINTS_1_DISK = 1;
const Uint8 ITEM_POINTS_2_GAVINA = 2;
const Uint8 ITEM_POINTS_3_PACMAR = 3;
const Uint8 ITEM_CLOCK = 4;
const Uint8 ITEM_TNT = 5;
const Uint8 ITEM_COFFEE = 6;
#define ITEM_POINTS_1_DISK 1
#define ITEM_POINTS_2_GAVINA 2
#define ITEM_POINTS_3_PACMAR 3
#define ITEM_CLOCK 4
#define ITEM_COFFEE 5
#define ITEM_POWER_BALL 6
// Cantidad de objetos simultaneos
const Uint8 MAX_ITEMS = 5;
#define MAX_ITEMS 5
// Valores para las variables asociadas a los objetos
const Uint8 REMAINING_EXPLOSIONS = 3;
const Uint8 REMAINING_EXPLOSIONS_TIMER = 50;
const Uint16 TIME_STOPPED_TIMER = 300;
#define REMAINING_EXPLOSIONS 3
#define REMAINING_EXPLOSIONS_COUNTER 50
#define TIME_STOPPED_COUNTER 300
// Estados de entrada
const Uint8 NO_INPUT = 0;
const Uint8 INPUT_UP = 1;
const Uint8 INPUT_DOWN = 2;
const Uint8 INPUT_LEFT = 3;
const Uint8 INPUT_RIGHT = 4;
const Uint8 INPUT_ACCEPT = 5;
const Uint8 INPUT_CANCEL = 6;
const Uint8 INPUT_FIRE_UP = 7;
const Uint8 INPUT_FIRE_LEFT = 8;
const Uint8 INPUT_FIRE_RIGHT = 9;
const Uint8 INPUT_PAUSE = 10;
#define NO_INPUT 0
#define INPUT_FIRE_LEFT 7
#define INPUT_FIRE_UP 8
#define INPUT_FIRE_RIGHT 9
#define INPUT_PAUSE 10
// Zona muerta del mando analógico
const int JOYSTICK_DEAD_ZONE = 8000;
#define JOYSTICK_DEAD_ZONE 8000
// Tipos de mensajes para el retorno de las funciones
const Uint8 MSG_OK = 0;
const Uint8 MSG_BULLET_OUT = 1;
#define MSG_OK 0
#define MSG_BULLET_OUT 1
// Tipos de texto
const Uint8 TEXT_FIXED = 0;
const Uint8 TEXT_VARIABLE = 1;
#define TEXT_FIXED 0
#define TEXT_VARIABLE 1
// Cantidad de elementos del vector de SmartSprites
const Uint8 MAX_SMART_SPRITES = 10;
#define MAX_SMART_SPRITES 10
// Cantidad máxima de gotas de café
#define MAX_COFFEE_DROPS 100
// Contadores
const Uint16 TITLE_TIMER = 800;
const Uint8 STAGE_COUNTER = 200;
const Uint16 INSTRUCTIONS_COUNTER = 600;
const Uint16 DEATH_COUNTER = 350;
#define TITLE_COUNTER 800
#define STAGE_COUNTER 200
#define INSTRUCTIONS_COUNTER 600
#define DEATH_COUNTER 350
#define SHAKE_COUNTER 10
// 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

470
source/director.cpp Normal file
View File

@@ -0,0 +1,470 @@
#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
mInput = new Input();
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 mInput;
mInput = 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
mInput->bindKey(INPUT_UP, SDL_SCANCODE_UP);
mInput->bindKey(INPUT_DOWN, SDL_SCANCODE_DOWN);
mInput->bindKey(INPUT_LEFT, SDL_SCANCODE_LEFT);
mInput->bindKey(INPUT_RIGHT, SDL_SCANCODE_RIGHT);
mInput->bindKey(INPUT_ACCEPT, SDL_SCANCODE_RETURN);
mInput->bindKey(INPUT_CANCEL, SDL_SCANCODE_ESCAPE);
#ifdef __MIPSEL__
mInput->bindKey(INPUT_BUTTON_1, SDL_SCANCODE_LSHIFT);
mInput->bindKey(INPUT_BUTTON_2, SDL_SCANCODE_SPACE);
mInput->bindKey(INPUT_BUTTON_3, SDL_SCANCODE_LCTRL);
#else
mInput->bindKey(INPUT_BUTTON_1, SDL_SCANCODE_Q);
mInput->bindKey(INPUT_BUTTON_2, SDL_SCANCODE_W);
mInput->bindKey(INPUT_BUTTON_3, SDL_SCANCODE_E);
#endif
mInput->bindKey(INPUT_BUTTON_4, SDL_SCANCODE_ESCAPE); // PAUSE
mInput->bindKey(INPUT_BUTTON_5, SDL_SCANCODE_ESCAPE); // 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_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_HAPTIC) < 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/player_body.png";
mFileList[38] = mExecutablePath + "/" + "../media/gfx/player_death.png";
mFileList[39] = mExecutablePath + "/" + "../media/gfx/player_legs.png";
mFileList[40] = mExecutablePath + "/" + "../media/gfx/title.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, mInput, mFileList, mOptions, mTextStrings);
setSection(mTitle->run(mSection.subsection));
delete mTitle;
}
void Director::runGame()
{
mGame = new Game(mRenderer, mFileList, mTextStrings, mInput, 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;
}
}
}

104
source/director.h Normal file
View File

@@ -0,0 +1,104 @@
#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 *mInput;
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

3197
source/game.cpp Normal file

File diff suppressed because it is too large Load Diff

475
source/game.h Normal file
View File

@@ -0,0 +1,475 @@
#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
};
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
Input *mInput; // Manejador de entrada
Player *mPlayer; // El 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 *mTexturePlayerBody; // Textura para el cuerpo del jugador
LTexture *mTexturePlayerDeath; // Textura para la animación de muerte del jugador
LTexture *mTexturePlayerLegs; // 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_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
bool mPowerBallEnabled; // Indica si hay una powerball ya activa
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(SDL_Renderer *renderer, std::string *filelist, std::string *textStrings, Input *input, 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();
// 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);
// 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();
// 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 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();
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,549 +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 "item.h"
#include "text.h"
#include "text2.h"
#include "menu.h"
#include "const.h"
#include "jail_audio.h"
#include <math.h>
#ifndef GAMEDIRECTOR_H
#define GAMEDIRECTOR_H
// GameDirector
class GameDirector
{
public:
// Constructor
GameDirector();
// Destructor
~GameDirector();
// Iniciador
void init(bool reset);
// Arranca SDL y crea la ventana
bool initSDL();
// Crea el indice de ficheros
void setFileList();
// Comprueba que todos los ficheros existen
bool checkFileList();
// Carga un archivo de imagen en una textura
bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer);
// Carga los recursos necesarios
bool loadMedia(Uint8 section);
// Descrga los recursos necesarios
bool unLoadMedia(Uint8 section);
// Establece el valor de la variable
void setExecutablePath(std::string path);
// 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 el valor de la variable mStage
void updateStage();
// Actualiza el estado de muerte
void updateDeath();
// Renderiza el fade final cuando se acaba la partida
void renderDeathFade();
// Mueve todos los globos activos
void moveBalloons();
// Pinta en pantalla todos los globos activos
void renderBalloons();
// Devuelve el primer indice no activo del vector de globos
Uint8 getBallonFreeIndex();
// Crea un globo nuevo en el vector de globos
Uint8 createNewBalloon(float x, int y, Uint8 kind, float velx, Uint16 stoppedtimer, LTexture *texture);
// Establece a cero todos los valores del vector de objetos globo
void resetBalloons();
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
void popBalloon(Uint8 index);
// Explosiona todos los globos
void popAllBallons();
// 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 checkPlayerBallonCollision();
// Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision();
// Comprueba la colisión entre las balas y los globos
void checkBulletBallonCollision();
// 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 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();
// Acciones a realizar cuando el jugador muere
void killPlayer();
// Calcula y establece el valor de amenaza en funcion de los globos activos
void calculateMenaceLevel();
// Obtiene el valor de la variable
Uint8 getMenaceLevel();
// Obtiene el valor de la variable
bool isPlayFieldDrawOnly();
// Establece el valor de la variable
void setPlayFieldDrawOnly(bool state);
// 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 setTimeStoppedTimer(Uint16 value);
// Actualiza y comprueba el valor de la variable
void updateTimeStoppedTimer();
// 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 updateRemainingExplosionsTimer();
// Gestiona el nivel de amenaza
void checkMenaceLevel();
// 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 getGameStatus();
// Establece el valor de la variable
void setGameStatus(Uint8 status);
// 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();
// Bucle para el logo del juego
void runLogo();
// Bucle para la intro del juego
void runIntro();
// Bucle para el titulo del juego
void runTitle();
// 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();
// Dibuja la informacion de debug en pantalla
void renderDebugInfo();
// Activa el modo Demo
void enableDemoMode();
// Desactiva el modo Demo
void disableDemoMode();
// Intercambia el proximo estado del juego despues del titulo
void toogleTitleNextGS();
private:
// La ventana donde dibujamos
SDL_Window *mWindow;
// El renderizador de la ventana
SDL_Renderer *mRenderer;
// Texturas donde dibujar
SDL_Texture *mBackbuffer;
SDL_Texture *mTitleSurface;
SDL_Texture *mInstructionsSurface;
// Manejador para el mando 1
SDL_Joystick *mGameController;
bool mGameControllerFound;
SDL_Haptic *mControllerHaptic;
// Datos del fichero
Uint32 mScoreDataFile[TOTAL_SCORE_DATA];
DemoKeys mDemoDataFile[TOTAL_DEMO_DATA];
// Manejador de eventos
SDL_Event *mEventHandler;
// El jugador
Player *mPlayer;
// Vector con los objetos globo
Balloon *mBalloon[MAX_BALLOONS];
// Vector con los objetos bala
Bullet *mBullet[MAX_BULLETS];
// Vector con los objetos item
Item *mItem[MAX_ITEMS];
// Fondo del juego
Sprite *mGameBackgroundFront;
Sprite *mGameBackgroundSky;
MovingSprite *mGBClouds1;
MovingSprite *mGBClouds1b;
MovingSprite *mGBClouds2;
MovingSprite *mGBClouds2b;
Sprite *mGrass;
// Instrucciones
Sprite *mInstructions;
// Fondo de la pantalla de titulo
Sprite *mTitleTile;
// Ventana visible de la textura de fondo del titulo
SDL_Rect mBackgroundWindow;
// Vector con los valores del seno para 360 grados
double mSen[360];
// Texto
struct text
{
Text *white;
Text *black;
Text *nokia;
};
text mText;
// Variable con lkos menus del juego
struct menu
{
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)
};
menu mMenu;
// Notificación GetReady!
SmartSprite *mGetReadyBitmap;
// Dibujos de la intro
SmartSprite *mIntroBitmap[INTRO_TOTAL_BITMAPS];
// Sprites con el titulo del juego para la pantalla de titulo
SmartSprite *mCoffeeBitmap;
SmartSprite *mCrisisBitmap;
AnimatedSprite *mDustSpriteLeft;
AnimatedSprite *mDustSpriteRight;
// Sprites con los puntos de algunos objetos
SmartSprite *m1000Bitmap;
SmartSprite *m2500Bitmap;
SmartSprite *m5000Bitmap;
// Vector para almacenar y gestionar SmartSprites
SmartSprite *mSmartSprite[MAX_SMART_SPRITES];
// Textos de la intro
Text2 *mIntroText[INTRO_TOTAL_TEXTS];
// Vector para coordinar los eventos de la intro
Uint8 mIntroEvents[INTRO_TOTAL_EVENTS];
// Vector para coordinar los eventos de la pantalla de titulo
Uint8 mTitleEvents[TITLE_TOTAL_EVENTS];
// Indicador para el bucle del titulo
Uint8 mTitleStatus;
struct game
{
Uint32 score; // Puntuación actual
Uint32 hiScore; // Puntuación máxima
Uint8 status; // Indicador para el bucle principal
bool paused; // Idica si el juego está en pausa
bool hiScoreAchieved; // Indica si se ha superado la puntuación máxima
Uint8 stage; // Pantalla actual
Uint8 stageCounter; // Contador para el tiempo visible del texto de Stage
double stagePath[STAGE_COUNTER]; // Vector con los puntos Y por donde pasará la etiqueta
Uint16 deathCounter; // Contador para la animación de muerte del jugador
Uint8 deathIndex; // Indice del vector de smartsprites que contiene el sprite del jugador
};
game mGame;
// Contador de ticks para ajustar la velocidad del juego
Uint32 mTicks;
// Velocidad a la que se repite el bucle de juego
Uint8 mTicksSpeed;
// Nivel de amenaza actual
Uint8 mMenaceLevel;
// 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
Uint8 mMenaceLevelThreshold;
// Indica si el bucle de juego avanza o solo pinta
bool mPlayFieldDrawOnly;
// Indica si se va a mostrar la información de debug
bool mDebug;
// Almacena los códigos de teclado correspondientes
Input mKeyboard;
// Buffer para teclas pulsadas
Input mKeyboardBuffer;
// Indica si el tiempo está detenido
bool mTimeStopped;
// Temporizador para llevar la cuenta del tiempo detenido
Uint16 mTimeStoppedTimer;
// Cantidad de explosiones restantes
Uint8 mRemainingExplosions;
// Temporizador para la cantidad de explosiones restantes
Uint16 mRemainingExplosionsTimer;
// Indica si las explosiones estan en marcha
bool mExplosionTime;
// Contador para las instrucciones
Uint16 mInstructionsCounter;
// Temporizador para la pantalla de titulo
Uint16 mTitleTimer;
// Temporizador para el fondo de tiles de la pantalla de titulo
Uint16 mTitleBackgroundTimer;
// Variable para almacenar el tipo de efecto que hará el foindo del titulo
Uint8 mTitleBackgroundMode;
// Indicador para saber si se muestra el menu del titulo o la frase intermitente
bool mTitleMenuVisible;
// Indica si está activo el modo demo
bool mDemo;
// Indica si está activado el modo para grabar la demo
bool mDemoRecording;
// Contador para el modo demo
Uint16 mDemoCounter;
DemoKeys mDemoKeys;
// Indica a que estado pasara el juego cuando acabe el temporizador del titulo
Uint8 mTiteNextGS;
// Contador para el juego
Uint32 mGameCounter;
// Variable para evitar la repetición de teclas en los menus
bool mMenuKeyPressed;
// Variables para el tamaño y modo de la ventana y variables para almacenar el valor si cancelamos en el menu de opciones
Uint32 mFullScreenMode;
Uint32 mFullScreenModePrevious;
Uint8 mWindowSize;
Uint8 mWindowSizePrevious;
// Variables para el logo
struct logo
{
Uint16 counter;
Sprite *sprite;
};
logo mLogo;
// Path del ejecutable
std::string mExecutablePath;
// Recursos
struct resourceBinFile
{
std::string file;
bool loaded;
};
resourceBinFile mBinFile[TOTAL_BINFILE];
struct resourceSound
{
std::string file;
bool loaded;
JA_Sound sound;
};
resourceSound mSound[TOTAL_SOUND];
struct resourceMusic
{
std::string file;
bool loaded;
JA_Music music;
};
resourceMusic mMusic[TOTAL_MUSIC];
struct resourceTexture
{
std::string file;
bool loaded;
LTexture *texture;
};
resourceTexture mTexture[TOTAL_TEXTURE];
};
#endif

View File

@@ -11,5 +11,11 @@
#endif
#ifdef __linux__
#include "/usr/include/SDL2/SDL.h"
#endif
#ifdef __MIPSEL__
#include "SDL.h"
#else
#include <SDL2/SDL.h>
#endif
#endif
#define UNUSED

163
source/input.cpp Normal file
View File

@@ -0,0 +1,163 @@
#include "input.h"
// Constructor
Input::Input()
{
for (int i = 0; i < 15; i++)
{
mInput[i].scancode = 0;
mInput[i].active = false;
}
}
// Destructor
Input::~Input()
{
}
// Asigna uno de los posibles inputs a una tecla del teclado
void Input::bindKey(Uint8 input, SDL_Scancode code)
{
mInput[input].scancode = code;
}
// Comprueba si un input esta activo
bool Input::checkInput(Uint8 input, bool repeat)
{
const Uint8 *mKeystates = SDL_GetKeyboardState(NULL);
if (repeat)
{
if (mKeystates[mInput[input].scancode] != 0)
return true;
else
return false;
}
else
{
if (!mInput[input].active)
{
if (mKeystates[mInput[input].scancode] != 0)
{
mInput[input].active = true;
return true;
}
else
{
return false;
}
}
else
{
if (mKeystates[mInput[input].scancode] == 0)
{
mInput[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 algun mando conectado
/*if (SDL_NumJoysticks() < 1)
{
printf("Warning: No joysticks connected!\n");
mGameControllerFound = false;
}
else
{
// Carga el mando
mGameController = SDL_JoystickOpen(0);
mGameControllerFound = true;
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 << SDL_JoystickNumButtons(mGameController) << " buttons\n";
// 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());
}
}
}
}*/

58
source/input.h Normal file
View File

@@ -0,0 +1,58 @@
#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 REPEAT_TRUE true
#define REPEAT_FALSE false
// Clase Input
class Input
{
private:
struct input_t
{
Uint8 scancode; // Scancode asociado
bool active; // Indica si está activo
};
input_t mInput[15]; // Vector con las teclas asociadas a los inputs predefinidos
//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
public:
// Constructor
Input();
// Destructor
~Input();
// Asigna uno de los posibles inputs a una tecla del teclado
void bindKey(Uint8 input, SDL_Scancode code);
// Comprueba si un input esta activo
bool checkInput(Uint8 input, bool repeat);
// Gestiona las entradas desde el mando de juego
bool checkGameController(Uint8 state);
};
#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,16 @@
Item::Item()
{
mSprite = new AnimatedSprite();
init(NO_KIND, 0, 0, nullptr, nullptr);
//init(NO_KIND, 0, 0, nullptr, nullptr);
mClass = NO_KIND;
}
// Destructor
Item::~Item()
{
init(NO_KIND, 0, 0, nullptr, nullptr);
//init(NO_KIND, 0, 0, nullptr, nullptr);
delete mSprite;
mSprite = nullptr;
}
// Iniciador
@@ -54,30 +56,32 @@ 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;
default:
break;
}
@@ -195,7 +199,7 @@ void Item::updateTimeToLive()
{
if (mTimeToLive > 0)
{
--mTimeToLive;
mTimeToLive--;
}
}
@@ -203,9 +207,7 @@ void Item::updateTimeToLive()
void Item::checkTimeToLive()
{
if (mTimeToLive == 0)
{
erase();
}
}
// Obtiene del valor de la variable
@@ -251,7 +253,7 @@ void Item::setEnabled(bool value)
}
// Obtiene el circulo de colisión
Circle &Item::getCollider()
circle_t &Item::getCollider()
{
return mCollider;
}

View File

@@ -1,7 +1,7 @@
#pragma once
#include "ifdefs.h"
#include "animatedsprite.h"
#include "struct.h"
#include "utils.h"
#ifndef ITEM_H
#define ITEM_H
@@ -62,7 +62,7 @@ public:
void setEnabled(bool value);
// Obtiene el circulo de colisión
Circle &getCollider();
circle_t &getCollider();
// Temporizador con el tiempo que el objeto está presente
Uint16 mTimeToLive;
@@ -93,10 +93,8 @@ private:
// Especifica si está habilitado el objeto
bool mEnabled;
// Circulo de colisión del objeto
Circle mCollider;
circle_t mCollider;
// Alinea el circulo de colisión con la posición del objeto
void shiftColliders();

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();
}

277
source/lang.h Normal file
View File

@@ -0,0 +1,277 @@
#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!!",
"CONGRATULATIONS!!"},
};
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
@@ -16,7 +14,7 @@ LTexture::LTexture()
LTexture::~LTexture()
{
// Deallocate
free();
unload();
}
bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer)
@@ -46,14 +44,14 @@ bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer)
}
// Get rid of preexisting texture
free();
unload();
// The final texture
SDL_Texture *newTexture = NULL;
// Load image at specified path
//SDL_Surface *loadedSurface = IMG_Load(path.c_str());
SDL_Surface *loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom((void*)data, width, height, depth, pitch, pixel_format);
SDL_Surface *loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom((void *)data, width, height, depth, pitch, pixel_format);
if (loadedSurface == NULL)
{
printf("Unable to load image %s!\n", path.c_str());
@@ -61,7 +59,7 @@ bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer)
else
{
// Color key image
SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, COLOR_KEY_R, COLOR_KEY_G, COLOR_KEY_B));
//SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, COLOR_KEY_R, COLOR_KEY_G, COLOR_KEY_B));
// Create texture from surface pixels
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
@@ -102,7 +100,7 @@ bool LTexture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_Te
return mTexture != NULL;
}
void LTexture::free()
void LTexture::unload()
{
// Free texture if it exists
if (mTexture != NULL)
@@ -132,7 +130,7 @@ void LTexture::setAlpha(Uint8 alpha)
SDL_SetTextureAlphaMod(mTexture, alpha);
}
void LTexture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, double angle, SDL_Point *center, SDL_RendererFlip flip)
void LTexture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float zoomW, float zoomH, double angle, SDL_Point *center, SDL_RendererFlip flip)
{
// Set rendering space and render to screen
SDL_Rect renderQuad = {x, y, mWidth, mHeight};
@@ -144,6 +142,9 @@ void LTexture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, doub
renderQuad.h = clip->h;
}
renderQuad.w = renderQuad.w * zoomW;
renderQuad.h = renderQuad.h * zoomH;
// Render to screen
SDL_RenderCopyEx(renderer, mTexture, clip, &renderQuad, angle, center, flip);
}

View File

@@ -23,7 +23,7 @@ public:
bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING);
// Deallocates texture
void free();
void unload();
// Set color modulation
void setColor(Uint8 red, Uint8 green, Uint8 blue);
@@ -35,7 +35,7 @@ public:
void setAlpha(Uint8 alpha);
// Renders texture at given point
void render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip = NULL, double angle = 0.0, SDL_Point *center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE);
void render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip = NULL, float zoomW = 1, float zoomH = 1, double angle = 0.0, SDL_Point *center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE);
// Set self as render target
void setAsRenderTarget(SDL_Renderer *renderer);

View File

@@ -1,10 +1,10 @@
/*
This source code copyrighted by JailDesigner (2020)
started on Castalla 15-07-2020.
Using some sample source code from Lazy Foo' Productions
*/
/*Descripción del enfoque utilizado para crear el juego.
/*
Descripción del enfoque utilizado para crear el juego.
El programa contine una serie de clases/objetos básicos: la clase sprite
permite dibujar partes de un fichero png en pantalla. La clase AnimatedSprite
@@ -17,11 +17,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,95 +36,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 <time.h>
#include "director.h"
#include <stdio.h>
#include <string>
#include "const.h"
#include "gamedirector.h"
int main(int argc, char *args[])
{
// Inicia el generador de numeros aleatorios
srand(time(nullptr));
// Crea el objeto gameDirector
GameDirector *gameDirector = new GameDirector();
// Crea el objeto mDirector
Director *mDirector = new Director(args[0]);
printf("Starting the game...\n\n");
// Establece el valor de la variable con el path del ejecutable
gameDirector->setExecutablePath(args[0]);
// Bucle principal
mDirector->run();
// Inicializa la lista de ficheros
gameDirector->setFileList();
// Libera todos los recursos y cierra SDL
delete mDirector;
mDirector = nullptr;
printf("Shutting down the game...\n");
// Comprueba que existen todos los ficheros
if (!gameDirector->checkFileList())
{
return -1;
}
// Arranca SDL y crea la ventana
if (!gameDirector->initSDL())
{
printf("Failed to initialize!\n");
return -1;
}
else
{
// Carga los recursos
if (!gameDirector->loadMedia(GAME_STATE_INIT))
{
printf("Failed to load media!\n");
}
else
{
// Inicializa el objeto gameDirector
gameDirector->init(false);
printf("Starting the game...\n\n");
// Mientras no se quiera salir del juego
while (!(gameDirector->getGameStatus() == GAME_STATE_QUIT))
{
switch (gameDirector->getGameStatus())
{
case GAME_STATE_LOGO:
gameDirector->loadMedia(GAME_STATE_LOGO);
gameDirector->runLogo();
gameDirector->unLoadMedia(GAME_STATE_LOGO);
break;
case GAME_STATE_INTRO:
gameDirector->loadMedia(GAME_STATE_INTRO);
gameDirector->runIntro();
gameDirector->unLoadMedia(GAME_STATE_INTRO);
break;
case GAME_STATE_TITLE:
gameDirector->loadMedia(GAME_STATE_TITLE);
gameDirector->runTitle();
gameDirector->unLoadMedia(GAME_STATE_TITLE);
break;
case GAME_STATE_PLAYING:
gameDirector->loadMedia(GAME_STATE_PLAYING);
gameDirector->runGame();
gameDirector->unLoadMedia(GAME_STATE_PLAYING);
break;
case GAME_STATE_GAME_OVER_SCREEN:
gameDirector->loadMedia(GAME_STATE_GAME_OVER_SCREEN);
gameDirector->runGameOverScreen();
gameDirector->unLoadMedia(GAME_STATE_GAME_OVER_SCREEN);
break;
case GAME_STATE_INSTRUCTIONS:
gameDirector->loadMedia(GAME_STATE_INSTRUCTIONS);
gameDirector->runInstructions();
gameDirector->unLoadMedia(GAME_STATE_INSTRUCTIONS);
break;
}
}
}
// Libera todos los recursos y cierra SDL
delete gameDirector;
printf("Shutting down the game...\n");
return 0;
}
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
@@ -33,6 +54,21 @@ void MovingSprite::init(float x, float y, int w, int h, float velx, float vely,
setAccelX(accelx);
setAccelY(accely);
// Establece el zoom W,H del sprite
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);
@@ -46,55 +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);
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;
}
// Obtiene el valor de la variable
float MovingSprite::getZoomW()
{
return mZoomW;
}
// 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)
{
@@ -129,4 +187,93 @@ void MovingSprite::setAccelX(float x)
void MovingSprite::setAccelY(float y)
{
mAccelY = y;
}
// Establece el valor de la variable
void MovingSprite::setZoomW(float w)
{
mZoomW = w;
}
// Establece el valor de la variable
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,6 +8,25 @@
// Clase MovingSprite. Añade posicion y velocidad en punto flotante
class MovingSprite : public Sprite
{
protected:
float mPosX; // Posición en el eje X
float mPosY; // Posición en el eje Y
float mVelX; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float mVelY; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
float mAccelX; // Aceleración en el eje X. Variación de la velocidad
float mAccelY; // Aceleración en el eje Y. Variación de la velocidad
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();
@@ -21,57 +40,95 @@ 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();
// Obten el valor de la variable
float getPosX();
// Obten el valor de la variable
float getPosY();
// Obten el valor de la variable
float getVelX();
// Obten el valor de la variable
float getVelY();
// Obten el valor de la variable
float getAccelX();
// Obten el valor de la variable
float getAccelY();
// Obten el valor de la variable
float getZoomW();
// 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);
// Establece el valor de la variable
void setPosY(float y);
// Establece el valor de la variable
void setVelX(float x);
// Establece el valor de la variable
void setVelY(float y);
// Establece el valor de la variable
void setAccelX(float x);
// Establece el valor de la variable
void setAccelY(float y);
private:
// Posición
float mPosX;
float mPosY;
// Establece el valor de la variable
void setZoomW(float w);
// Velocidad
float mVelX;
float mVelY;
// Establece el valor de la variable
void setZoomH(float h);
// Aceleración
float mAccelX;
float mAccelY;
// 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

@@ -6,17 +6,20 @@ Player::Player()
{
mSpriteLegs = new AnimatedSprite();
mSpriteBody = new AnimatedSprite();
init(0, 0, nullptr, nullptr, nullptr);
mSpriteHead = new AnimatedSprite();
}
// 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
@@ -27,8 +30,10 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mStatusWalking = PLAYER_STATUS_WALKING_STOP;
mStatusFiring = PLAYER_STATUS_FIRING_NO;
mInvulnerable = false;
mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER;
mInvulnerableCounter = PLAYER_INVULNERABLE_COUNTER;
mExtraHit = false;
mCoffees = 0;
mInput = true;
// Establece la altura y el ancho del jugador
mWidth = 3 * BLOCK;
@@ -51,10 +56,6 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
// Establece la velocidad base
mBaseSpeed = 1.5;
// Establece el numero inicial de vidas
mStartingLives = 3;
mLives = mStartingLives;
// Establece la puntuación inicial
mScore = 0;
@@ -100,12 +101,6 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 4);
// Establece la velocidad de cada animación
mSpriteLegs->setAnimationSpeed(PLAYER_ANIMATION_LEGS_WALKING_STOP, 10);
@@ -118,12 +113,6 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_STOP, 10);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_UP, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 10);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 5);
// Establece si la animación se reproduce en bucle
mSpriteLegs->setAnimationLoop(PLAYER_ANIMATION_LEGS_WALKING_STOP, true);
@@ -136,12 +125,6 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_RIGHT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_STOP, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_UP, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, true);
// Establece los frames de cada animación
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 0, mWidth * 0, mHeight * 0, mWidth, mHeight);
@@ -189,36 +172,6 @@ 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);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 0, mWidth * 0, mHeight * 6, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 1, mWidth * 1, mHeight * 6, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 2, mWidth * 2, mHeight * 6, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 3, mWidth * 3, mHeight * 6, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 0, mWidth * 0, mHeight * 7, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 1, mWidth * 1, mHeight * 7, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 2, mWidth * 2, mHeight * 7, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 3, mWidth * 3, mHeight * 7, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 0, mWidth * 0, mHeight * 8, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 1, mWidth * 1, mHeight * 8, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 2, mWidth * 2, mHeight * 8, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 3, mWidth * 3, mHeight * 8, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 0, mWidth * 0, mHeight * 9, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 1, mWidth * 1, mHeight * 9, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 2, mWidth * 2, mHeight * 9, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 3, mWidth * 3, mHeight * 9, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 0, mWidth * 0, mHeight * 10, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 1, mWidth * 1, mHeight * 10, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 2, mWidth * 2, mHeight * 10, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 3, mWidth * 3, mHeight * 10, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 0, mWidth * 0, mHeight * 11, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 1, mWidth * 1, mHeight * 11, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 2, mWidth * 2, mHeight * 11, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 3, mWidth * 3, mHeight * 11, 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));
@@ -231,71 +184,29 @@ void Player::setInput(Uint8 input)
{
case INPUT_LEFT:
mVelX = -mBaseSpeed;
if (mExtraHit)
{
setWalkingStatus(PLAYER_STATUS_WALKING_LEFT);
}
else
{
setWalkingStatus(PLAYER_STATUS_WALKING_LEFT);
}
setWalkingStatus(PLAYER_STATUS_WALKING_LEFT);
break;
case INPUT_RIGHT:
mVelX = mBaseSpeed;
if (mExtraHit)
{
setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT);
}
else
{
setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT);
}
setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT);
break;
case INPUT_FIRE_UP:
if (mExtraHit)
{
setFiringStatus(PLAYER_STATUS_FIRING_UP);
}
else
{
setFiringStatus(PLAYER_STATUS_FIRING_UP);
}
setFiringStatus(PLAYER_STATUS_FIRING_UP);
break;
case INPUT_FIRE_LEFT:
if (mExtraHit)
{
setFiringStatus(PLAYER_STATUS_FIRING_LEFT);
}
else
{
setFiringStatus(PLAYER_STATUS_FIRING_LEFT);
}
setFiringStatus(PLAYER_STATUS_FIRING_LEFT);
break;
case INPUT_FIRE_RIGHT:
if (mExtraHit)
{
setFiringStatus(PLAYER_STATUS_FIRING_RIGHT);
}
else
{
setFiringStatus(PLAYER_STATUS_FIRING_RIGHT);
}
setFiringStatus(PLAYER_STATUS_FIRING_RIGHT);
break;
default:
mVelX = 0;
if (mExtraHit)
{
setWalkingStatus(PLAYER_STATUS_WALKING_STOP);
}
else
{
setWalkingStatus(PLAYER_STATUS_WALKING_STOP);
}
setWalkingStatus(PLAYER_STATUS_WALKING_STOP);
break;
}
}
@@ -309,7 +220,7 @@ void Player::move()
mPosX += mVelX;
// Si el jugador abandona el area de juego por los laterales
if ((mPosX < PLAY_AREA_LEFT) || (mPosX + mWidth > PLAY_AREA_RIGHT))
if ((mPosX < PLAY_AREA_LEFT - 5) || (mPosX + mWidth > PLAY_AREA_RIGHT + 5))
{
// Restaura su posición
mPosX -= mVelX;
@@ -331,7 +242,7 @@ void Player::render()
{
if (mInvulnerable)
{
if ((mInvulnerableTimer % 10) > 4)
if ((mInvulnerableCounter % 10) > 4)
{
mSpriteLegs->render();
mSpriteBody->render();
@@ -370,6 +281,17 @@ void Player::setFiringStatus(Uint8 status)
// Establece la animación correspondiente al estado
void Player::setAnimation()
{
// Actualiza los frames de la animación en función del número de cafes
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);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, i, mWidth * i, mHeight * (2 + (6 * mCoffees)), mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, i, mWidth * i, mHeight * (3 + (6 * mCoffees)), mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, i, mWidth * i, mHeight * (4 + (6 * mCoffees)), mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, i, mWidth * i, mHeight * (5 + (6 * mCoffees)), mWidth, mHeight);
}
switch (mStatusWalking)
{
case PLAYER_STATUS_WALKING_LEFT:
@@ -377,51 +299,19 @@ void Player::setAnimation()
switch (mStatusFiring)
{
case PLAYER_STATUS_FIRING_UP:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
break;
case PLAYER_STATUS_FIRING_LEFT:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
break;
case PLAYER_STATUS_FIRING_RIGHT:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
break;
case PLAYER_STATUS_FIRING_NO:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_LEFT);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_LEFT);
break;
default:
@@ -435,51 +325,19 @@ void Player::setAnimation()
switch (mStatusFiring)
{
case PLAYER_STATUS_FIRING_UP:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
break;
case PLAYER_STATUS_FIRING_LEFT:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
break;
case PLAYER_STATUS_FIRING_RIGHT:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
break;
case PLAYER_STATUS_FIRING_NO:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_RIGHT);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_RIGHT);
break;
default:
@@ -493,51 +351,19 @@ void Player::setAnimation()
switch (mStatusFiring)
{
case PLAYER_STATUS_FIRING_UP:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
break;
case PLAYER_STATUS_FIRING_LEFT:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
break;
case PLAYER_STATUS_FIRING_RIGHT:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
break;
case PLAYER_STATUS_FIRING_NO:
if (mExtraHit)
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
}
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
break;
default:
@@ -616,7 +442,7 @@ void Player::update()
setAnimation();
shiftColliders();
updateCooldown();
updateInvulnerableTimer();
updateInvulnerableCounter();
}
// Obtiene la puntuación del jugador
@@ -692,28 +518,28 @@ void Player::setInvulnerable(bool value)
}
// Obtiene el valor de la variable
bool Player::getInvulnerableTimer()
Uint16 Player::getInvulnerableCounter()
{
return mInvulnerableTimer;
return mInvulnerableCounter;
}
// Establece el valor de la variable
void Player::setInvulnerableTimer(Uint16 value)
void Player::setInvulnerableCounter(Uint16 value)
{
mInvulnerableTimer = value;
mInvulnerableCounter = value;
}
// Actualiza el valor de la variable
void Player::updateInvulnerableTimer()
void Player::updateInvulnerableCounter()
{
if (mInvulnerableTimer > 0)
if (mInvulnerableCounter > 0)
{
--mInvulnerableTimer;
--mInvulnerableCounter;
}
else
{
mInvulnerable = false;
mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER;
mInvulnerableCounter = PLAYER_INVULNERABLE_COUNTER;
}
}
@@ -727,18 +553,42 @@ bool Player::hasExtraHit()
void Player::giveExtraHit()
{
mExtraHit = true;
mCoffees++;
if (mCoffees > 2)
mCoffees = 2;
}
// Quita el toque extra al jugador
void Player::removeExtraHit()
{
mExtraHit = false;
if (mCoffees > 0)
mCoffees--;
if (mCoffees == 0)
mExtraHit = false;
mInvulnerable = true;
mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER;
mInvulnerableCounter = PLAYER_INVULNERABLE_COUNTER;
}
// Habilita la entrada de ordenes
void Player::enableInput()
{
mInput = true;
}
// Deshabilita la entrada de ordenes
void Player::disableInput()
{
mInput = false;
}
// Devuelve el numero de cafes actuales
Uint8 Player::getCoffees()
{
return mCoffees;
}
// Obtiene el circulo de colisión
Circle &Player::getCollider()
circle_t &Player::getCollider()
{
return mCollider;
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "struct.h"
#include "utils.h"
#include "input.h"
#include "animatedsprite.h"
#ifndef PLAYER_H
@@ -8,6 +9,39 @@
// The player
class Player
{
private:
float mPosX; // Posicion en el eje X
int mPosY; // Posicion en el eje Y
Uint8 mWidth; // Anchura
Uint8 mHeight; // Altura
float mVelX; // Cantidad de pixeles a desplazarse en el eje X
int mVelY; // Cantidad de pixeles a desplazarse en el eje Y
float mBaseSpeed; // Velocidad base del jugador
int mCooldown; // Contador durante el cual no puede disparar
Uint32 mScore; // Puntos del jugador
float mScoreMultiplier; // Multiplicador de puntos
Uint8 mStatusWalking; // Estado del jugador
Uint8 mStatusFiring; // Estado del jugador
bool mAlive; // Indica si el jugador está vivo
bool mInvulnerable; // Indica si el jugador es invulnerable
Uint16 mInvulnerableCounter; // Temporizador para la invulnerabilidad
bool mExtraHit; // Indica si el jugador tiene un toque extra
Uint8 mCoffees; // Indica cuantos cafes lleva acumulados
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
circle_t mCollider; // Circulo de colisión del jugador
void shiftColliders(); // Actualiza el circulo de colisión a la posición del jugador
public:
// Constructor
Player();
@@ -92,13 +126,13 @@ public:
void setInvulnerable(bool value);
// Obtiene el valor de la variable
bool getInvulnerableTimer();
Uint16 getInvulnerableCounter();
// Establece el valor de la variable
void setInvulnerableTimer(Uint16 value);
void setInvulnerableCounter(Uint16 value);
// Actualiza el valor de la variable
void updateInvulnerableTimer();
void updateInvulnerableCounter();
// Obtiene el valor de la variable
bool hasExtraHit();
@@ -109,65 +143,17 @@ public:
// Quita el toque extra al jugador
void removeExtraHit();
// Habilita la entrada de ordenes
void enableInput();
// Deshabilita la entrada de ordenes
void disableInput();
// Devuelve el numero de cafes actuales
Uint8 getCoffees();
// Obtiene el circulo de colisión
Circle &getCollider();
private:
// Posición X, Y del jugador
float mPosX;
int mPosY;
// Altura y anchura del jugador
Uint8 mWidth;
Uint8 mHeight;
// Velocidad X, Y del jugador
float mVelX;
int mVelY;
// Velocidad base del jugador
float mBaseSpeed;
// Contador durante el cual no puede disparar
int mCooldown;
// Vidas actuales del jugador
Uint8 mLives;
// Vidas iniciales del jugador
Uint8 mStartingLives;
// Puntos del jugador
Uint32 mScore;
// Multiplicador de puntos
float mScoreMultiplier;
// Estado del jugador
Uint8 mStatusWalking;
Uint8 mStatusFiring;
// Indica si el jugador está vivo
bool mAlive;
// Indica si el jugador es invulnerable
bool mInvulnerable;
// Temporizador para la invulnerabilidad
Uint16 mInvulnerableTimer;
// Indica si el jugador tiene un toque extra
bool mExtraHit;
// Sprite para dibujar al jugador en pantalla
AnimatedSprite *mSpriteLegs;
AnimatedSprite *mSpriteBody;
// Circulo de colisión del jugador
Circle mCollider;
// Actualiza el circulo de colisión a la posición del jugador
void shiftColliders();
circle_t &getCollider();
};
#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

@@ -1,5 +1,5 @@
#pragma once
#include "struct.h"
#include "utils.h"
#include "animatedsprite.h"
#ifndef SMARTSPRITE_H
@@ -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

@@ -16,14 +16,14 @@ Sprite::~Sprite()
// Inicializador
void Sprite::init(int x, int y, int w, int h, LTexture *texture, SDL_Renderer *renderer)
{
// Establece el alto y el ancho del sprite
setWidth(w);
setHeight(h);
// Establece la posición X,Y del sprite
setPosX(x);
setPosY(y);
// Establece el alto y el ancho del sprite
setWidth(w);
setHeight(h);
// Establece el puntero al renderizador de la ventana
setRenderer(renderer);
@@ -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

@@ -1,42 +0,0 @@
#pragma once
#include "ifdefs.h"
#ifndef STRUCT_H
#define STRUCT_H
// Estructura para definir un circulo
struct Circle
{
Uint16 x;
Uint16 y;
Uint8 r;
};
// Estructura para definir todas las entradas que aceptará el programa
struct Input
{
Uint8 up;
Uint8 down;
Uint8 left;
Uint8 right;
Uint8 escape;
Uint8 pause;
Uint8 fire;
Uint8 fireLeft;
Uint8 fireRight;
Uint8 accept;
Uint8 cancel;
};
// Estructura para mapear el teclado usado en la demo
struct DemoKeys
{
Uint8 left;
Uint8 right;
Uint8 noInput;
Uint8 fire;
Uint8 fireLeft;
Uint8 fireRight;
};
#endif

View File

@@ -2,20 +2,22 @@
#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;
}
// 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,16 +28,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 = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-/().:#!";
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;
@@ -43,16 +42,23 @@ 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 ñ y la ç
mOffset[int('^')].x = mOffset[int('z')].x + size;
mOffset[int('^')].y = mOffset[int('z')].y;
mOffset[int('^')].w = size;
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)
{
@@ -105,6 +111,10 @@ 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;
@@ -134,25 +144,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);
@@ -162,60 +162,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 centrado en un punto x y con kerning
void Text::writeCentered(int x, int y, std::string text, int kerning)
// Escribe el texto con sombra
void Text::writeShadowed(int x, int y, std::string text, color_t color, Uint8 shadowDistance, 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);
}
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, kerning, lenght);
}
// Escribe el texto centrado en un punto x
void Text::writeCentered(int x, int y, std::string text, int kerning, int lenght)
{
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,32 +1,55 @@
#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
struct Offset
{
int x;
int y;
Uint8 w;
};
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
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, 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);
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);
@@ -36,31 +59,12 @@ public:
// Establece el valor de la variable
void setType(Uint8 type);
// Obtiene el valor de la variable
Uint8 getSize();
// Establece el valor de la variable
void setSize(Uint8 size);
private:
// Objeto con los graficos para el texto
Sprite *mSprite;
// Coordenadas dentro del PNG para cada código ascii y su anchura
struct Offset
{
int x;
int y;
Uint8 w;
};
// Vector con las posiciones y ancho de cada letra
Offset mOffset[255];
// Indica si el texto es de anchura fija o variable
Uint8 mType;
Uint8 mSize;
};
#endif

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);

690
source/title.cpp Normal file
View File

@@ -0,0 +1,690 @@
#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] = sin((float)i * 3.14f / 180.0f);
}
// Inicializa los objetos de menu
mMenu.title->init("TITLE", 0, 15 * BLOCK, MENU_BACKGROUND_SOLID);
mMenu.title->addItem(mTextStrings[0]); // PLAY
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(3);
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[0]);
mMenu.title->setItemCaption(1, mTextStrings[1]);
mMenu.title->setItemCaption(2, mTextStrings[2]);
mMenu.title->setItemCaption(3, 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: // PLAY
mSection.name = PROG_SECTION_GAME;
JA_StopMusic();
break;
case 1: // QUIT
mSection.name = PROG_SECTION_QUIT;
JA_StopMusic();
break;
case 2: // 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: // PLAY
mPostFade = 0;
mFade->activateFade();
break;
case 1: // OPTIONS
mMenu.active = mMenu.options;
mOptions->fullScreenModePrevious = mOptions->fullScreenMode;
mOptions->windowSizePrevious = mOptions->windowSize;
mOptions->languagePrevious = mOptions->language;
break;
case 2: // HOW TO PLAY
runInstructions(INSTRUCTIONS_MODE_MANUAL);
break;
case 3: // QUIT
mPostFade = 1;
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(mRenderer, mFileList, mTextStrings, 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

124
source/utils.cpp Normal file
View File

@@ -0,0 +1,124 @@
#include "utils.h"
// Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2)
{
int deltaX = x2 - x1;
int deltaY = y2 - y1;
return deltaX * deltaX + deltaY * deltaY;
}
// Detector de colisiones entre dos circulos
bool checkCollision(circle_t &a, circle_t &b)
{
// Calcula el radio total al cuadrado
int totalRadiusSquared = a.r + b.r;
totalRadiusSquared = totalRadiusSquared * totalRadiusSquared;
// Si la distancia entre el centro de los circulos es inferior a la suma de sus radios
if (distanceSquared(a.x, a.y, b.x, b.y) < (totalRadiusSquared))
{
// Los circulos han colisionado
return true;
}
// En caso contrario
return false;
}
// Detector de colisiones entre un circulo y un rectangulo
bool checkCollision(circle_t &a, SDL_Rect &b)
{
//Closest point on collision box
int cX, cY;
//Find closest x offset
if (a.x < b.x)
{
cX = b.x;
}
else if (a.x > b.x + b.w)
{
cX = b.x + b.w;
}
else
{
cX = a.x;
}
//Find closest y offset
if (a.y < b.y)
{
cY = b.y;
}
else if (a.y > b.y + b.h)
{
cY = b.y + b.h;
}
else
{
cY = a.y;
}
//If the closest point is inside the circle_t
if (distanceSquared(a.x, a.y, cX, cY) < a.r * a.r)
{
//This box and the circle_t have collided
return true;
}
//If the shapes have not collided
return false;
}
// Detector de colisiones entre un dos rectangulos
bool checkCollision(SDL_Rect &a, SDL_Rect &b)
{
//Calculate the sides of rect A
int leftA = a.x;
int rightA = a.x + a.w;
int topA = a.y;
int bottomA = a.y + a.h;
//Calculate the sides of rect B
int leftB = b.x;
int rightB = b.x + b.w;
int topB = b.y;
int bottomB = b.y + b.h;
//If any of the sides from A are outside of B
if (bottomA <= topB)
{
return false;
}
if (topA >= bottomB)
{
return false;
}
if (rightA <= leftB)
{
return false;
}
if (leftA >= rightB)
{
return false;
}
//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;
}

68
source/utils.h Normal file
View File

@@ -0,0 +1,68 @@
#pragma once
#include "ifdefs.h"
#include "ltexture.h"
#ifndef UTILS_H
#define UTILS_H
// Estructura para definir un circulo
struct circle_t
{
Uint16 x;
Uint16 y;
Uint8 r;
};
// Estructura para definir un color
struct color_t
{
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
struct demoKeys_t
{
Uint8 left;
Uint8 right;
Uint8 noInput;
Uint8 fire;
Uint8 fireLeft;
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);
// Detector de colisiones entre dos circulos
bool checkCollision(circle_t &a, circle_t &b);
// Detector de colisiones entre un circulo y un rectangulo
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