release v1.3 beta 1

This commit is contained in:
2021-02-18 17:16:33 +01:00
parent 8dc5fe049d
commit 9298025cd6
78 changed files with 23440 additions and 0 deletions

6
Makefile Normal file
View File

@@ -0,0 +1,6 @@
macos:
mkdir -p bin
g++ -std=c++11 -Wall -O2 source/*.cpp -o bin/coffee_crisis_macos -lSDL2
linux:
mkdir -p bin
g++ -std=c++11 -Wall -O2 source/*.cpp -o bin/coffee_crisis_linux -lSDL2

BIN
data/demo.bin Normal file

Binary file not shown.

BIN
media/.DS_Store vendored Normal file

Binary file not shown.

BIN
media/gfx/.DS_Store vendored Normal file

Binary file not shown.

BIN
media/gfx/balloon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
media/gfx/bullet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

BIN
media/gfx/font_black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
media/gfx/font_nokia.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
media/gfx/font_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
media/gfx/game_bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
media/gfx/game_text.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

BIN
media/gfx/intro.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
media/gfx/items.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
media/gfx/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
media/gfx/menu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

BIN
media/gfx/player_body.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
media/gfx/player_death.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

BIN
media/gfx/player_legs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

BIN
media/gfx/title.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
media/music/.DS_Store vendored Normal file

Binary file not shown.

10
media/music/credits.txt Normal file
View File

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

BIN
media/music/intro.ogg Normal file

Binary file not shown.

BIN
media/music/playing.ogg Normal file

Binary file not shown.

BIN
media/music/title.ogg Normal file

Binary file not shown.

BIN
media/sound/balloon.wav Normal file

Binary file not shown.

BIN
media/sound/bubble1.wav Normal file

Binary file not shown.

BIN
media/sound/bubble2.wav Normal file

Binary file not shown.

BIN
media/sound/bubble3.wav Normal file

Binary file not shown.

BIN
media/sound/bubble4.wav Normal file

Binary file not shown.

BIN
media/sound/bullet.wav Normal file

Binary file not shown.

BIN
media/sound/coffeeout.wav Normal file

Binary file not shown.

60
media/sound/credits.txt Normal file
View File

@@ -0,0 +1,60 @@
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/hiscore.wav Normal file

Binary file not shown.

BIN
media/sound/itemdrop.wav Normal file

Binary file not shown.

BIN
media/sound/itempickup.wav Normal file

Binary file not shown.

BIN
media/sound/menu_cancel.wav Normal file

Binary file not shown.

BIN
media/sound/menu_move.wav Normal file

Binary file not shown.

BIN
media/sound/menu_select.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
media/sound/title.wav Normal file

Binary file not shown.

BIN
media/sound/tnt.wav Normal file

Binary file not shown.

BIN
source/.DS_Store vendored Normal file

Binary file not shown.

112
source/animatedsprite.cpp Normal file
View File

@@ -0,0 +1,112 @@
#include "const.h"
#include "animatedsprite.h"
#include <iostream>
// Constructor
AnimatedSprite::AnimatedSprite()
{
init(nullptr, nullptr);
}
// Destructor
AnimatedSprite::~AnimatedSprite()
{
init(nullptr, nullptr);
}
// Iniciador
void AnimatedSprite::init(LTexture *texture, SDL_Renderer *renderer)
{
mRenderer = renderer;
mTexture = texture;
for (Uint8 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].frames[j].x = 0;
mAnimation[i].frames[j].y = 0;
mAnimation[i].frames[j].w = 0;
mAnimation[i].frames[j].h = 0;
}
}
mCurrentFrame = 0;
mAnimationCounter = 0;
}
// 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 (mAnimation[index].loop)
{
mAnimationCounter = 0;
}
else
{
mCurrentFrame = mAnimation[index].numFrames;
}
}
// En caso contrario
else
{
// Escogemos el frame correspondiente de la animación
setSpriteClip(mAnimation[index].frames[mCurrentFrame]);
// Incrementamos el contador de la animacion
++mAnimationCounter;
}
}
// Establece el frame actual de la animación
void AnimatedSprite::setCurrentFrame(Uint8 num)
{
mCurrentFrame = num;
}
// Establece el valor del contador
void AnimatedSprite::setAnimationCounter(Uint16 num)
{
mAnimationCounter = num;
}
// Establece el rectangulo para un frame de una animación
void AnimatedSprite::setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h)
{
mAnimation[index_animation].frames[index_frame].x = x;
mAnimation[index_animation].frames[index_frame].y = y;
mAnimation[index_animation].frames[index_frame].w = w;
mAnimation[index_animation].frames[index_frame].h = h;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(Uint8 index, Uint8 speed)
{
mAnimation[index].speed = speed;
}
// Establece el numero de frames de una animación
void AnimatedSprite::setAnimationNumFrames(Uint8 index, Uint8 num)
{
mAnimation[index].numFrames = num;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(Uint8 index, bool loop)
{
mAnimation[index].loop = loop;
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(Uint8 index_animation, Uint8 index_frame)
{
return mAnimation[index_animation].frames[index_frame];
}

64
source/animatedsprite.h Normal file
View File

@@ -0,0 +1,64 @@
#pragma once
#include "ifdefs.h"
#include "movingsprite.h"
#ifndef ANIMATEDSPRITE_H
#define ANIMATEDSPRITE_H
// Clase AnimatedSprite
class AnimatedSprite : public MovingSprite
{
public:
// Constructor
AnimatedSprite();
// Destructor
~AnimatedSprite();
// Iniciador
void init(LTexture *texture, SDL_Renderer *renderer);
// Calcula el frame correspondiente a la animación
void animate(int index);
// Establece el frame actual de la animación
void setCurrentFrame(Uint8 num);
// Establece el valor del contador
void setAnimationCounter(Uint16 num);
// Establece el rectangulo para un frame de una animación
void setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h);
// Establece la velocidad de una animación
void setAnimationSpeed(Uint8 index, Uint8 speed);
// Establece el numero de frames de una animación
void setAnimationNumFrames(Uint8 index, Uint8 num);
// Establece si la animación se reproduce en bucle
void setAnimationLoop(Uint8 index, bool loop);
// 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

644
source/balloon.cpp Normal file
View File

@@ -0,0 +1,644 @@
#include "const.h"
#include "balloon.h"
// Constructor
Balloon::Balloon()
{
mSprite = new AnimatedSprite();
init(0, 0, NO_KIND, BALLON_VELX_POSITIVE, 0, nullptr, nullptr);
}
// Destructor
Balloon::~Balloon()
{
delete mSprite;
}
// Inicializador
void Balloon::init(float x, int y, Uint8 kind, float velx, Uint16 creationtimer, LTexture *texture, SDL_Renderer *renderer)
{
const Uint8 NUM_FRAMES_BALLON = 10;
const Uint8 NUM_FRAMES_BALLON_POP = 12;
const Uint8 NUM_FRAMES_BALLON_BORN = 10;
switch (kind)
{
case BALLOON_1:
// Posición inicial
mPosX = x;
mPosY = y;
// Alto y ancho del objeto
mWidth = 8;
mHeight = mWidth;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = 0;
mMaxVelY = 3;
mGravity = 0.09f;
mDefaultVelY = 3;
// Puntos que da el globo al ser destruido
mScore = 50;
// Amenaza que genera el globo
mMenace = 1;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
{
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 50, 21 + (37 * i), getWidth(), getHeight());
}
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
{
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 50 + 58, 21 + (37 * i), getWidth(), getHeight());
}
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
{
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 50 + 58 + 58, 21 + (37 * i), getWidth(), getHeight());
}
break;
case BALLOON_2:
// Posición inicial
mPosX = x;
mPosY = y;
// Alto y ancho del objeto
mWidth = 13;
mHeight = mWidth;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = 0;
mMaxVelY = 3;
mGravity = 0.10f;
mDefaultVelY = 4;
// Puntos que da el globo al ser destruido
mScore = 100;
// Amenaza que genera el globo
mMenace = 2;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
{
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37, 21 + (37 * i), getWidth(), getHeight());
}
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
{
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + 58, 21 + (37 * i), getWidth(), getHeight());
}
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
{
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + 58 + 58, 21 + (37 * i), getWidth(), getHeight());
}
break;
case BALLOON_3:
// Posición inicial
mPosX = x;
mPosY = y;
// Alto y ancho del objeto
mWidth = 21;
mHeight = mWidth;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = 0;
mMaxVelY = 3;
mGravity = 0.10f;
mDefaultVelY = 4.5;
// Puntos que da el globo al ser destruido
mScore = 200;
// Amenaza que genera el globo
mMenace = 4;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
{
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37, 37 * i, getWidth(), getHeight());
}
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
{
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + 58, 37 * i, getWidth(), getHeight());
}
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
{
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + 58 + 58, 37 * i, getWidth(), getHeight());
}
break;
case BALLOON_4:
// Posición inicial
mPosX = x;
mPosY = y;
// Alto y ancho del objeto
mWidth = 37;
mHeight = mWidth;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = 0;
mMaxVelY = 3;
mGravity = 0.10f;
mDefaultVelY = 5;
// Puntos que da el globo al ser destruido
mScore = 400;
// Amenaza que genera el globo
mMenace = 8;
// Establece los frames de cada animación
for (Uint8 i = 0; i < NUM_FRAMES_BALLON; i++)
{
mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 0, 37 * i, getWidth(), getHeight());
}
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
{
mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 58, 37 * i, getWidth(), getHeight());
}
for (Uint8 i = 0; i < NUM_FRAMES_BALLON_POP; i++)
{
mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 58 + 58, 37 * i, getWidth(), getHeight());
}
break;
default:
// Posición inicial
mPosX = x;
mPosY = y;
// Alto y ancho del objeto
mWidth = 0;
mHeight = mWidth;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = 0;
mMaxVelY = 0;
mGravity = 0;
mDefaultVelY = 0;
// Puntos que da el globo al ser destruido
mScore = 0;
// Amenaza que genera el globo
mMenace = 0;
// Establece los frames de cada animación
mSprite->setAnimationFrames(0, 0, 0, 0, getWidth(), getHeight());
mSprite->setAnimationFrames(1, 0, 0, 0, getWidth(), getHeight());
mSprite->setAnimationFrames(2, 0, 0, 0, getWidth(), getHeight());
break;
}
// Textura con los gráficos del sprite
mSprite->setTexture(texture);
// Renderizador
mSprite->setRenderer(renderer);
// Alto y ancho del sprite
mSprite->setWidth(mWidth);
mSprite->setHeight(mHeight);
// Posición X,Y del sprite
mSprite->setPosX(int(mPosX));
mSprite->setPosY(mPosY);
// Tamaño del circulo de colisión
mCollider.r = mWidth / 2;
// Alinea el circulo de colisión con el objeto
shiftColliders();
// Inicializa variables
mStopped = true;
mStoppedTimer = 0;
mBlinking = false;
mVisible = true;
mInvulnerable = false;
mBeingCreated = true;
mCreationTimer = creationtimer;
mPopping = false;
// Tipo
mKind = kind;
// Inicializa las variables para la animación
mSprite->setCurrentFrame(0);
mSprite->setAnimationCounter(0);
// Establece el numero de frames de cada animacion
mSprite->setAnimationNumFrames(BALLOON_MOVING_ANIMATION, NUM_FRAMES_BALLON);
mSprite->setAnimationNumFrames(BALLOON_POP_ANIMATION, NUM_FRAMES_BALLON_POP);
mSprite->setAnimationNumFrames(BALLOON_BORN_ANIMATION, NUM_FRAMES_BALLON_BORN);
// Establece la velocidad de cada animación
mSprite->setAnimationSpeed(BALLOON_MOVING_ANIMATION, 10);
mSprite->setAnimationSpeed(BALLOON_POP_ANIMATION, 5);
mSprite->setAnimationSpeed(BALLOON_BORN_ANIMATION, 20);
// Establece si la animación se reproduce en bucle
mSprite->setAnimationLoop(BALLOON_MOVING_ANIMATION, true);
mSprite->setAnimationLoop(BALLOON_POP_ANIMATION, false);
mSprite->setAnimationLoop(BALLOON_BORN_ANIMATION, true);
// Selecciona un frame para pintar
mSprite->setSpriteClip(mSprite->getAnimationClip(0, 0));
}
// Centra el globo en la posición X
void Balloon::allignTo(int x)
{
mPosX = float(x - (mWidth / 2));
if (mPosX < PLAY_AREA_LEFT)
{
mPosX = PLAY_AREA_LEFT + 1;
}
else if ((mPosX + mWidth) > PLAY_AREA_RIGHT)
{
mPosX = float(PLAY_AREA_RIGHT - mWidth - 1);
}
// Posición X,Y del sprite
mSprite->setPosX(getPosX());
mSprite->setPosY(getPosY());
// Alinea el circulo de colisión con el objeto
shiftColliders();
}
// Pinta el globo en la pantalla
void Balloon::render()
{
if (mVisible)
{
mSprite->render();
}
}
// Actualiza la posición y estados del globo
void Balloon::move()
{
// Comprobamos si se puede mover
if (isStopped() == false)
{
// Lo movemos a izquierda o derecha
mPosX += mVelX;
// Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido
if ((mPosX < PLAY_AREA_LEFT) || (mPosX + mWidth > PLAY_AREA_RIGHT))
{
// Corregir posición
mPosX -= mVelX;
// Invertir sentido
mVelX = -mVelX;
}
// Mueve el globo hacia arriba o hacia abajo
mPosY += int(mVelY);
// Si se sale por arriba
if (mPosY < PLAY_AREA_TOP)
{
// Corregimos
mPosY -= int(mVelY);
// Invertimos sentido
mVelY = -mVelY;
}
// Si el globo se sale por la parte inferior
if (mPosY + mHeight > PLAY_AREA_BOTTOM)
{
// Corregimos
mPosY -= int(mVelY);
// Invertimos colocando una velocidad por defecto
mVelY = -mDefaultVelY;
}
// Aplica gravedad al objeto, sin pasarse de un limite establecido
if (int(mVelY) > mMaxVelY)
{
mVelY = float(mMaxVelY);
}
else
{
mVelY += mGravity;
}
// Actualiza la posición del sprite
mSprite->setPosX(getPosX());
mSprite->setPosY(mPosY);
}
// Si no se puede mover:
// Comprobar si se está creando
else if (isBeingCreated() == true)
{
// Actualiza el valor de las variables
setStop(true);
setInvulnerable(true);
// Todavia tiene tiempo en el contador
if (mCreationTimer > 0)
{
// Desplaza lentamente el globo hacia abajo y hacia un lado
if (mCreationTimer % 10 == 0)
{
++mPosY;
mPosX += mVelX;
// Actualiza la posición del sprite
mSprite->setPosX(getPosX());
mSprite->setPosY(mPosY);
// Actualiza la posición del circulo de colisión
shiftColliders();
}
// Hace visible el globo de forma intermitente
if (mCreationTimer > 100)
{
setVisible(mCreationTimer / 10 % 2 == 0);
}
else
{
setVisible(mCreationTimer / 5 % 2 == 0);
}
--mCreationTimer;
}
// El contador ha llegado a cero
else
{
setBeingCreated(false);
setStop(false);
setVisible(true);
setInvulnerable(false);
}
}
// Comprobar si está detenido
else if (isStopped() == true)
{
// Si todavía está detenido, reduce el contador
if (mStoppedTimer > 0)
{
--mStoppedTimer;
} // Si el contador ha llegado a cero, ya no está detenido
else
{
setStop(false);
}
}
}
// Pone a cero todos los valores del globo
void Balloon::erase()
{
init(0, 0, NO_KIND, 0, 0, nullptr, nullptr);
}
// Explosiona el globo
void Balloon::pop()
{
setPopping(true);
mSprite->setAnimationCounter(0);
setTimeToLive(120);
setStop(true);
setStoppedTimer(2000);
setInvulnerable(true);
mMenace = 0;
}
// Actualiza al globo a su posicion, animación y controla los contadores
void Balloon::update()
{
move();
setAnimation();
shiftColliders();
if (isPopping())
{
setInvulnerable(true);
setStop(true);
if (mTimeToLive > 0)
{
--mTimeToLive;
}
else
{
erase();
}
}
}
// Establece la animación correspondiente al estado
void Balloon::setAnimation()
{
// Establece el frame de animación
if (isPopping())
{
mSprite->animate(BALLOON_POP_ANIMATION);
}
else if (isBeingCreated())
{
mSprite->animate(BALLOON_BORN_ANIMATION);
}
else
{
mSprite->animate(BALLOON_MOVING_ANIMATION);
}
}
// Comprueba si el globo tiene algun tipo asignado
bool Balloon::isActive()
{
if (mKind == NO_KIND)
{
return false;
}
else
{
return true;
}
}
// Obtiene del valor de la variable
int Balloon::getPosX()
{
return int(mPosX);
}
// Obtiene del valor de la variable
int Balloon::getPosY()
{
return mPosY;
}
// Obtiene del valor de la variable
float Balloon::getVelY()
{
return mVelY;
}
// Obtiene del valor de la variable
int Balloon::getWidth()
{
return mWidth;
}
// Obtiene del valor de la variable
int Balloon::getHeight()
{
return mHeight;
}
// Establece el valor de la variable
void Balloon::setVelY(float velY)
{
mVelY = velY;
}
// Obtiene del valor de la variable
int Balloon::getKind()
{
return mKind;
}
// Establece el valor de la variable
void Balloon::setStop(bool state)
{
mStopped = state;
}
// Obtiene del valor de la variable
bool Balloon::isStopped()
{
return mStopped;
}
// Establece el valor de la variable
void Balloon::setBlink(bool state)
{
mBlinking = state;
}
// Obtiene del valor de la variable
bool Balloon::isBlinking()
{
return mBlinking;
}
// Establece el valor de la variable
void Balloon::setVisible(bool state)
{
mVisible = state;
}
// Obtiene del valor de la variable
bool Balloon::isVisible()
{
return mVisible;
}
// Establece el valor de la variable
void Balloon::setInvulnerable(bool state)
{
mInvulnerable = state;
}
// Obtiene del valor de la variable
bool Balloon::isInvulnerable()
{
return mInvulnerable;
}
// Establece el valor de la variable
void Balloon::setBeingCreated(bool state)
{
mBeingCreated = state;
}
// Obtiene del valor de la variable
bool Balloon::isBeingCreated()
{
return mBeingCreated;
}
// Establece el valor de la variable
void Balloon::setPopping(bool state)
{
mPopping = state;
}
// Obtiene del valor de la variable
bool Balloon::isPopping()
{
return mPopping;
}
// Establece el valor de la variable
void Balloon::setTimeToLive(Uint16 time)
{
mTimeToLive = time;
}
// Obtiene del valor de la variable
Uint16 Balloon::getTimeToLive()
{
return mTimeToLive;
}
// Establece el valor de la variable
void Balloon::setStoppedTimer(Uint16 time)
{
mStoppedTimer = time;
}
// Obtiene del valor de la variable
Uint16 Balloon::getStoppedTimer()
{
return mStoppedTimer;
}
// Obtiene del valor de la variable
Uint16 Balloon::getScore()
{
return mScore;
}
// Obtiene el circulo de colisión
Circle &Balloon::getCollider()
{
return mCollider;
}
// Alinea el circulo de colisión con la posición del objeto globo
void Balloon::shiftColliders()
{
// Align collider to center of balloon
mCollider.x = Uint16(mPosX + mCollider.r);
mCollider.y = mPosY + mCollider.r;
}
// Obtiene le valor de la variable
Uint8 Balloon::getMenace()
{
return mMenace;
}

185
source/balloon.h Normal file
View File

@@ -0,0 +1,185 @@
#pragma once
#include "struct.h"
#include "animatedsprite.h"
#ifndef BALLOON_H
#define BALLOON_H
// Clase globo
class Balloon
{
public:
// Constructor
Balloon();
// Destructor
~Balloon();
// Inicializador
void init(float x, int y, Uint8 kind, float velx, Uint16 creationtimer, LTexture* texture, SDL_Renderer *renderer);
// Centra el globo en la posición X
void allignTo(int x);
// Pinta el globo en la pantalla
void render();
// Actualiza la posición y estados del globo
void move();
// Pone a cero todos los valores del globo
void erase();
// Explosiona el globo
void pop();
// 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();
// Obtiene del valor de la variable
int getPosX();
// Obtiene del valor de la variable
int getPosY();
// Obtiene del valor de la variable
float getVelY();
// Obtiene del valor de la variable
int getWidth();
// Obtiene del valor de la variable
int getHeight();
// Establece el valor de la variable
void setVelY(float velY);
// Obtiene del valor de la variable
int getKind();
// Establece el valor de la variable
void setStop(bool state);
// Obtiene del valor de la variable
bool isStopped();
// Establece el valor de la variable
void setBlink(bool state);
// Obtiene del valor de la variable
bool isBlinking();
// Establece el valor de la variable
void setVisible(bool state);
// Obtiene del valor de la variable
bool isVisible();
// Establece el valor de la variable
void setInvulnerable(bool state);
// 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();
// Establece el valor de la variable
void setPopping(bool state);
// 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);
// Obtiene del valor de la variable
Uint16 getStoppedTimer();
// Obtiene del valor de la variable
Uint16 getScore();
// Obtiene el circulo de colisión
Circle &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();
};
#endif

213
source/bullet.cpp Normal file
View File

@@ -0,0 +1,213 @@
#include "const.h"
#include "bullet.h"
// Constructor
Bullet::Bullet()
{
mSprite = new Sprite();
init(0, 0, NO_KIND, nullptr, nullptr);
}
// Destructor
Bullet::~Bullet()
{
init(0, 0, NO_KIND, nullptr, nullptr);
delete mSprite;
}
// Iniciador
void Bullet::init(int x, int y, int kind, LTexture *texture, SDL_Renderer *renderer)
{
// Posición inicial del objeto
mPosX = x;
mPosY = y;
// Alto y ancho del objeto
mWidth = 10;
mHeight = mWidth;
// Velocidad inicial en el eje Y
mVelY = -3;
// Tipo de bala
mKind = kind;
// Textura con los gráficos del objeto
mSprite->setTexture(texture);
// Renderizador
mSprite->setRenderer(renderer);
// Alto y ancho del sprite
mSprite->setWidth(mWidth);
mSprite->setHeight(mHeight);
// Posición inicial del sprite
mSprite->setPosX(mPosX);
mSprite->setPosY(mPosY);
// Valores especificos según el tipo
switch (kind)
{
case BULLET_UP:
// Establece la velocidad inicial
mVelX = 0;
// Rectangulo con los gráficos del objeto
mSprite->setSpriteClip(0 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
break;
case BULLET_LEFT:
// Establece la velocidad inicial
mVelX = -2;
// Rectangulo con los gráficos del objeto
mSprite->setSpriteClip(1 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
break;
case BULLET_RIGHT:
// Establece la velocidad inicial
mVelX = 2;
// Rectangulo con los gráficos del objeto
mSprite->setSpriteClip(2 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
break;
default:
break;
}
// Establece el tamaño del circulo de colisión
mCollider.r = mWidth / 2;
// Alinea el circulo de colisión con el objeto
shiftColliders();
}
// Pinta el objeto en pantalla
void Bullet::render()
{
mSprite->render();
}
// Actualiza la posición y estado del objeto en horizontal
Uint8 Bullet::move()
{
// Variable con el valor de retorno
Uint8 msg = MSG_OK;
// Mueve el objeto a su nueva posición
mPosX += mVelX;
// Si el objeto se sale del area de juego por los laterales
if ((mPosX < PLAY_AREA_LEFT) || (mPosX + mWidth > PLAY_AREA_RIGHT))
{
// Se deshabilita
mKind = NO_KIND;
// Mensaje de salida
msg = MSG_BULLET_OUT;
}
// Mueve el objeto a su nueva posición en vertical
mPosY += int(mVelY);
// Si el objeto se sale del area de juego por la parte superior o inferior
if ((mPosY < PLAY_AREA_TOP) || (mPosY + mHeight > PLAY_AREA_BOTTOM))
{
// Se deshabilita
mKind = NO_KIND;
// Mensaje de salida
msg = MSG_BULLET_OUT;
}
// Actualiza la posición del sprite
mSprite->setPosX(mPosX);
mSprite->setPosY(mPosY);
// Alinea el circulo de colisión con el objeto
shiftColliders();
return msg;
}
#ifdef TEST
void Bullet::testMove()
{
// Update sprite position
mSprite->setPosX(mPosX);
mSprite->setPosY(mPosY);
// Update circle colliders
shiftColliders();
}
#endif
// Deshabilita el objeto
void Bullet::erase()
{
init(0, 0, 0, nullptr, nullptr);
}
// Comprueba si el objeto está activo
bool Bullet::isActive()
{
if (mKind == NO_KIND)
{
return false;
}
else
{
return true;
}
}
// Obtiene el valor de la variable
int Bullet::getPosX()
{
return mPosX;
}
// Obtiene el valor de la variable
int Bullet::getPosY()
{
return mPosY;
}
// Establece el valor de la variable
void Bullet::setPosX(int x)
{
mPosX = x;
}
// Establece el valor de la variable
void Bullet::setPosY(int y)
{
mPosY = y;
}
// Obtiene el valor de la variable
int Bullet::getVelY()
{
return mVelY;
}
// Obtiene el valor de la variable
int Bullet::getKind()
{
return mKind;
}
// Obtiene el circulo de colisión
Circle &Bullet::getCollider()
{
return mCollider;
}
// Alinea el circulo de colisión con el objeto
void Bullet::shiftColliders()
{
mCollider.x = mPosX + mCollider.r;
mCollider.y = mPosY + mCollider.r;
}

80
source/bullet.h Normal file
View File

@@ -0,0 +1,80 @@
#pragma once
#include "struct.h"
#include "sprite.h"
#ifndef BULLET_H
#define BULLET_H
// Clase bala
class Bullet
{
public:
// Constructor
Bullet();
// Destructor
~Bullet();
// Iniciador
void init(int x, int y, int kind, LTexture* texture, SDL_Renderer *renderer);
// Pinta el objeto en pantalla
void render();
// Actualiza la posición y estado del objeto
Uint8 move();
// Deshabilita el objeto
void erase();
// Comprueba si el objeto está activo
bool isActive();
// Obtiene el valor de la variable
int getPosX();
// Obtiene el valor de la variable
int getPosY();
// Establece el valor de la variable
void setPosX(int x);
// Establece el valor de la variable
void setPosY(int y);
// Obtiene el valor de la variable
int getVelY();
// Obtiene el valor de la variable
int getKind();
// Obtiene el circulo de colisión
Circle &getCollider();
private:
// Posición X/Y del objeto
int mPosX;
int mPosY;
// Alto y ancho el objeto
Uint8 mWidth;
Uint8 mHeight;
// Velocidad del objeto
int mVelX;
int mVelY;
// Tipo de objeto
int mKind;
// Sprite con los graficos y métodos de pintado
Sprite *mSprite;
// Balloon's collision circle
Circle mCollider;
// Alinea el circulo de colisión con el objeto
void shiftColliders();
};
#endif

282
source/const.h Normal file
View File

@@ -0,0 +1,282 @@
#pragma once
#include "ifdefs.h"
#include <string>
#ifndef CONST_H
#define CONST_H
// Textos
#define WINDOW_CAPTION "Coffee Crisis"
#define TEXT_COPYRIGHT "@2020,2021 JAILDESIGNER (V1.3*)"
// Recursos
const Uint8 BINFILE_SCORE = 0;
const Uint8 BINFILE_DEMO = 1;
const Uint8 BINFILE_CONFIG = 2;
const Uint8 TOTAL_BINFILE = 3;
const Uint8 MUSIC_INTRO = 0;
const Uint8 MUSIC_PLAYING = 1;
const Uint8 MUSIC_TITLE = 2;
const Uint8 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;
const Uint8 TOTAL_SOUND = 16;
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;
const Uint8 TOTAL_TEXTURE = 15;
// Tamaño de bloque
const Uint8 BLOCK = 8;
const Uint8 HALF_BLOCK = BLOCK / 2;
// Tamaño de la pantalla real
const int SCREEN_WIDTH = 256;
const int SCREEN_HEIGHT = SCREEN_WIDTH * 3 / 4; // 192
// Tamaño de la pantalla que se muestra
const int VIEW_WIDTH = SCREEN_WIDTH * 3; // 768
const int VIEW_HEIGHT = SCREEN_HEIGHT * 3; // 576
// Cantidad de enteros a escribir en los ficheros de datos
const Uint8 TOTAL_SCORE_DATA = 3;
const Uint16 TOTAL_DEMO_DATA = 2000;
// Zona de juego
const int PLAY_AREA_TOP = (0 * BLOCK);
const int PLAY_AREA_BOTTOM = SCREEN_HEIGHT - (4 * BLOCK);
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_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;
// Anclajes de pantalla
const int SCREEN_CENTER_X = SCREEN_WIDTH / 2;
const int SCREEN_FIRST_QUARTER_X = SCREEN_WIDTH / 4;
const int SCREEN_THIRD_QUARTER_X = (SCREEN_WIDTH / 4) * 3;
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);
// Tipos de fondos para el menu
const int MENU_BACKGROUND_TRANSPARENT = 0;
const int 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;
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;
const Uint8 PLAYER_ANIMATION_LEGS_WALKING_LEFT = 0;
const Uint8 PLAYER_ANIMATION_LEGS_WALKING_RIGHT = 1;
const Uint8 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;
// Variables del jugador
const Uint16 PLAYER_INVULNERABLE_TIMER = 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;
// Estados de cada elemento que pertenece a un evento
const Uint8 EVENT_WAITING = 1;
const Uint8 EVENT_RUNNING = 2;
const Uint8 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;
// Cantidad de eventos de la pantalla de titulo
const Uint8 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;
// Anclajes para el marcador de puntos
const int SCORE_WORD_X = (SCREEN_WIDTH / 4) - ((5 * BLOCK) / 2);
const int SCORE_WORD_Y = SCREEN_HEIGHT - (3 * BLOCK) + 2;
const int SCORE_NUMBER_X = (SCREEN_WIDTH / 4) - ((6 * BLOCK) / 2);
const int SCORE_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
const int HISCORE_WORD_X = ((SCREEN_WIDTH / 4) * 3) - ((8 * BLOCK) / 2);
const int HISCORE_WORD_Y = SCREEN_HEIGHT - (3 * BLOCK) + 2;
const int HISCORE_NUMBER_X = ((SCREEN_WIDTH / 4) * 3) - ((6 * BLOCK) / 2);
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_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
// Ningun tipo
const Uint8 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;
// Velocidad del globo
const float BALLON_VELX_POSITIVE = 0.7f;
const float BALLON_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;
// Cantidad posible de globos
const Uint8 MAX_BALLOONS = 75;
// Tipos de bala
const Uint8 BULLET_UP = 1;
const Uint8 BULLET_LEFT = 2;
const Uint8 BULLET_RIGHT = 3;
// Cantidad posible de globos
const Uint8 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;
// Cantidad de objetos simultaneos
const Uint8 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;
// 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;
// Zona muerta del mando analógico
const int JOYSTICK_DEAD_ZONE = 8000;
// Tipos de mensajes para el retorno de las funciones
const Uint8 MSG_OK = 0;
const Uint8 MSG_BULLET_OUT = 1;
// Tipos de texto
const Uint8 TEXT_FIXED = 0;
const Uint8 TEXT_VARIABLE = 1;
// Cantidad de elementos del vector de SmartSprites
const Uint8 MAX_SMART_SPRITES = 10;
// Contadores
const Uint16 TITLE_TIMER = 800;
const Uint8 STAGE_COUNTER = 200;
const Uint16 INSTRUCTIONS_COUNTER = 600;
const Uint16 DEATH_COUNTER = 350;
#endif

3950
source/gamedirector.cpp Normal file

File diff suppressed because it is too large Load Diff

549
source/gamedirector.h Normal file
View File

@@ -0,0 +1,549 @@
#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

15
source/ifdefs.h Normal file
View File

@@ -0,0 +1,15 @@
#ifdef _WIN64
#include "C:\mingw_dev_lib\include\SDL2\SDL.h"
#endif
#ifdef _WIN32
#include "C:\mingw_dev_lib\include\SDL2\SDL.h"
#endif
#ifdef __APPLE__
#include "/Library/Frameworks/SDL2.framework/Versions/A/Headers/SDL.h"
#endif
#ifdef __linux__
#include "/usr/include/SDL2/SDL.h"
#endif

264
source/item.cpp Normal file
View File

@@ -0,0 +1,264 @@
#include "const.h"
#include "item.h"
// Constructor
Item::Item()
{
mSprite = new AnimatedSprite();
init(NO_KIND, 0, 0, nullptr, nullptr);
}
// Destructor
Item::~Item()
{
init(NO_KIND, 0, 0, nullptr, nullptr);
delete mSprite;
}
// Iniciador
void Item::init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer *renderer)
{
mClass = value;
mEnabled = true;
mTimeToLive = 600;
mPosX = x;
mPosY = y;
mWidth = 16;
mHeight = 16;
mVelX = -1.0f + ((rand() % 5) * 0.5f);
mVelY = -4.0f;
mAccelX = 0.0f;
mAccelY = 0.2f;
mCollider.r = mWidth / 2;
shiftColliders();
mSprite->init(texture, renderer);
mSprite->setAnimationFrames(0, 0, 0, 48, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 0, 64, mWidth, mHeight);
mSprite->setCurrentFrame(0);
mSprite->setAnimationCounter(0);
mSprite->setAnimationNumFrames(0, 2);
mSprite->setAnimationSpeed(0, 10);
mSprite->setAnimationLoop(0, true);
mSprite->setSpriteClip(mSprite->getAnimationClip(0, 0));
switch (value)
{
case NO_KIND:
mEnabled = false;
mTimeToLive = 0;
mPosX = 0;
mPosY = 0;
mWidth = 0;
mHeight = 0;
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;
}
}
// Centra el globo en la posición X
void Item::allignTo(int x)
{
mPosX = float(x - (mWidth / 2));
if (mPosX < PLAY_AREA_LEFT)
{
mPosX = PLAY_AREA_LEFT + 1;
}
else if ((mPosX + mWidth) > PLAY_AREA_RIGHT)
{
mPosX = float(PLAY_AREA_RIGHT - mWidth - 1);
}
// Posición X,Y del sprite
mSprite->setPosX(int(mPosX));
mSprite->setPosY(int(mPosY));
// Alinea el circulo de colisión con el objeto
shiftColliders();
}
// Pinta el globo en la pantalla
void Item::render()
{
if (mEnabled)
{
if (mTimeToLive > 200)
{
mSprite->render();
}
else if (mTimeToLive % 20 > 10)
{
mSprite->render();
}
}
}
// Actualiza la posición y estados del globo
void Item::move()
{
// Calcula la nueva posición
mPosX += mVelX;
mPosY += mVelY;
// Aplica las aceleraciones a la velocidad
mVelX += mAccelX;
mVelY += mAccelY;
// Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido
if ((mPosX < PLAY_AREA_LEFT) || (mPosX + mWidth > PLAY_AREA_RIGHT))
{
// Corregir posición
mPosX -= mVelX;
// Invertir sentido
mVelX = -mVelX;
}
// Si se sale por arriba
if (mPosY < PLAY_AREA_TOP)
{
// Corrige
mPosY = PLAY_AREA_TOP;
// Invierte el sentido
mVelY = -mVelY;
}
// Si el objeto se sale por la parte inferior
if (mPosY + mHeight > PLAY_AREA_BOTTOM)
{
// Corrige
mPosY -= mVelY;
// Detiene el objeto
mVelY = 0;
mVelX = 0;
mAccelX = 0;
mAccelY = 0;
mPosY = PLAY_AREA_BOTTOM - mHeight;
}
// Actualiza la posición del sprite
mSprite->setPosX(int(mPosX));
mSprite->setPosY(int(mPosY));
}
// Pone a cero todos los valores del objeto
void Item::erase()
{
init(NO_KIND, 0, 0, nullptr, nullptr);
}
// Actualiza el objeto a su posicion, animación y controla los contadores
void Item::update()
{
if (mEnabled)
{
move();
shiftColliders();
mSprite->animate(0);
updateTimeToLive();
checkTimeToLive();
}
}
// Actualiza el contador
void Item::updateTimeToLive()
{
if (mTimeToLive > 0)
{
--mTimeToLive;
}
}
// Comprueba si el objeto sigue vivo
void Item::checkTimeToLive()
{
if (mTimeToLive == 0)
{
erase();
}
}
// Obtiene del valor de la variable
float Item::getPosX()
{
return mPosX;
}
// Obtiene del valor de la variable
float Item::getPosY()
{
return mPosY;
}
// Obtiene del valor de la variable
int Item::getWidth()
{
return mWidth;
}
// Obtiene del valor de la variable
int Item::getHeight()
{
return mHeight;
}
// Obtiene del valor de la variable
int Item::getClass()
{
return mClass;
}
// Obtiene el valor de la variable
bool Item::isEnabled()
{
return mEnabled;
}
// Establece el valor de la variable
void Item::setEnabled(bool value)
{
mEnabled = value;
}
// Obtiene el circulo de colisión
Circle &Item::getCollider()
{
return mCollider;
}
// Alinea el circulo de colisión con la posición del objeto
void Item::shiftColliders()
{
mCollider.x = Uint16(mPosX + mCollider.r);
mCollider.y = Uint16(mPosY + mCollider.r);
}

105
source/item.h Normal file
View File

@@ -0,0 +1,105 @@
#pragma once
#include "ifdefs.h"
#include "animatedsprite.h"
#include "struct.h"
#ifndef ITEM_H
#define ITEM_H
// Clase AnimatedSprite
class Item
{
public:
// Constructor
Item();
// Destructor
~Item();
// Iniciador
void init(Uint8 value, float x, float y, LTexture* texture, SDL_Renderer *renderer);
// Centra el objeto en la posición X
void allignTo(int x);
// Pinta el objeto en la pantalla
void render();
// Actualiza la posición y estados del objeto
void move();
// Pone a cero todos los valores del objeto
void erase();
// Actualiza al objeto a su posicion, animación y controla los contadores
void update();
// Actualiza el contador
void updateTimeToLive();
// Comprueba si el objeto sigue vivo
void checkTimeToLive();
// Obtiene del valor de la variable
float getPosX();
// Obtiene del valor de la variable
float getPosY();
// Obtiene del valor de la variable
int getWidth();
// Obtiene del valor de la variable
int getHeight();
// Obtiene del valor de la variable
int getClass();
// Obtiene el valor de la variable
bool isEnabled();
// Establece el valor de la variable
void setEnabled(bool value);
// Obtiene el circulo de colisión
Circle &getCollider();
// Temporizador con el tiempo que el objeto está presente
Uint16 mTimeToLive;
private:
// Posición X,Y del objeto
float mPosX;
float mPosY;
// Alto y ancho del objeto
Uint8 mWidth;
Uint8 mHeight;
// Variables para controlar la velocidad del objeto
float mVelX;
float mVelY;
// Aceleración
float mAccelX;
float mAccelY;
// Sprite con los graficos del objeto
AnimatedSprite *mSprite;
// Especifica el tipo de objeto que es
Uint8 mClass;
// Especifica si está habilitado el objeto
bool mEnabled;
// Circulo de colisión del objeto
Circle mCollider;
// Alinea el circulo de colisión con la posición del objeto
void shiftColliders();
};
#endif

213
source/jail_audio.cpp Normal file
View File

@@ -0,0 +1,213 @@
#include "jail_audio.h"
#include "stb_vorbis.c"
//#include <SDL2/SDL.h>
#define JA_MAX_SIMULTANEOUS_CHANNELS 5
struct JA_Sound_t {
Uint32 length {0};
Uint8* buffer {NULL};
};
struct JA_Channel_t {
JA_Sound sound;
int pos {0};
int times {0};
JA_Channel_state state { JA_CHANNEL_FREE };
};
struct JA_Music_t {
int samples {0};
int pos {0};
int times {0};
short* output {NULL};
JA_Music_state state {JA_MUSIC_INVALID};
};
JA_Music current_music{NULL};
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
int JA_freq {48000};
SDL_AudioFormat JA_format {AUDIO_S16};
Uint8 JA_channels {2};
void audioCallback(void * userdata, uint8_t * stream, int len) {
SDL_memset(stream, 0, len);
if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING) {
const int size = SDL_min(len, current_music->samples*2-current_music->pos);
SDL_memcpy(stream, current_music->output+current_music->pos, size);
current_music->pos += size/2;
if (size < len) {
if (current_music->times != 0) {
SDL_memcpy(stream+size, current_music->output, len-size);
current_music->pos = (len-size)/2;
if (current_music->times > 0) current_music->times--;
} else {
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
}
}
// Mixar els channels mi amol
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PLAYING) {
const int size = SDL_min(len, channels[i].sound->length - channels[i].pos);
SDL_MixAudioFormat(stream, channels[i].sound->buffer + channels[i].pos, AUDIO_S16, size, 64);
channels[i].pos += size;
if (size < len) {
if (channels[i].times != 0) {
SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len-size, 64);
channels[i].pos = len-size;
if (channels[i].times > 0) channels[i].times--;
} else {
JA_StopChannel(i);
}
}
}
}
}
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) {
JA_freq = freq;
JA_format = format;
JA_channels = channels;
SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL};
SDL_AudioDeviceID sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
SDL_PauseAudioDevice(sdlAudioDevice, 0);
}
JA_Music JA_LoadMusic(const char* filename) {
int chan, samplerate;
JA_Music music = new JA_Music_t();
music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq);
cvt.len = music->samples * chan * 2;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, music->output, cvt.len);
SDL_ConvertAudio(&cvt);
free(music->output);
music->output = (short*)cvt.buf;
music->pos = 0;
music->state = JA_MUSIC_STOPPED;
return music;
}
void JA_PlayMusic(JA_Music music, const int loop) {
if (current_music != NULL) {
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
current_music = music;
current_music->pos = 0;
current_music->state = JA_MUSIC_PLAYING;
current_music->times = loop;
}
void JA_PauseMusic() {
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->state = JA_MUSIC_PAUSED;
}
void JA_ResumeMusic() {
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->state = JA_MUSIC_PLAYING;
}
void JA_StopMusic() {
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
JA_Music_state JA_GetMusicState() {
if (current_music == NULL) return JA_MUSIC_INVALID;
return current_music->state;
}
void JA_DeleteMusic(JA_Music music) {
if (current_music == music) current_music = NULL;
SDL_free(music->output);
delete music;
}
JA_Sound JA_LoadSound(const char* filename) {
JA_Sound sound = new JA_Sound_t();
SDL_AudioSpec wavSpec;
SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length);
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq);
cvt.len = sound->length;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, sound->buffer, sound->length);
SDL_ConvertAudio(&cvt);
SDL_FreeWAV(sound->buffer);
sound->buffer = cvt.buf;
sound->length = cvt.len_cvt;
return sound;
}
int JA_PlaySound(JA_Sound sound, const int loop) {
int channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0;
channels[channel].sound = sound;
channels[channel].times = loop;
channels[channel].pos = 0;
channels[channel].state = JA_CHANNEL_PLAYING;
return channel;
}
void JA_DeleteSound(JA_Sound sound) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].sound == sound) JA_StopChannel(i);
}
SDL_free(sound->buffer);
delete sound;
}
void JA_PauseChannel(const int channel) {
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PLAYING) channels[i].state = JA_CHANNEL_PAUSED;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PLAYING) channels[channel].state = JA_CHANNEL_PAUSED;
}
}
void JA_ResumeChannel(const int channel) {
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PAUSED) channels[i].state = JA_CHANNEL_PLAYING;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PAUSED) channels[channel].state = JA_CHANNEL_PLAYING;
}
}
void JA_StopChannel(const int channel) {
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
channels[i].state = JA_CHANNEL_FREE;
channels[i].pos = 0;
channels[i].sound = NULL;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
channels[channel].state = JA_CHANNEL_FREE;
channels[channel].pos = 0;
channels[channel].sound = NULL;
}
}
JA_Channel_state JA_GetChannelState(const int channel) {
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
return channels[channel].state;
}

26
source/jail_audio.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include "ifdefs.h"
enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED };
enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED };
typedef struct JA_Sound_t *JA_Sound;
typedef struct JA_Music_t *JA_Music;
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels);
JA_Music JA_LoadMusic(const char* filename);
void JA_PlayMusic(JA_Music music, const int loop = -1);
void JA_PauseMusic();
void JA_ResumeMusic();
void JA_StopMusic();
JA_Music_state JA_GetMusicState();
void JA_DeleteMusic(JA_Music music);
JA_Sound JA_LoadSound(const char* filename);
int JA_PlaySound(JA_Sound sound, const int loop = 0);
void JA_PauseChannel(const int channel);
void JA_ResumeChannel(const int channel);
void JA_StopChannel(const int channel);
JA_Channel_state JA_GetChannelState(const int channel);
void JA_DeleteSound(JA_Sound sound);

165
source/ltexture.cpp Normal file
View File

@@ -0,0 +1,165 @@
#include <stdio.h>
#include <string>
#include "const.h"
#include "ltexture.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
LTexture::LTexture()
{
// Initialize
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
LTexture::~LTexture()
{
// Deallocate
free();
}
bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer)
{
int req_format = STBI_rgb_alpha;
int width, height, orig_format;
unsigned char *data = stbi_load(path.c_str(), &width, &height, &orig_format, req_format);
if (data == NULL)
{
SDL_Log("Loading image failed: %s", stbi_failure_reason());
exit(1);
}
int depth, pitch;
Uint32 pixel_format;
if (req_format == STBI_rgb)
{
depth = 24;
pitch = 3 * width; // 3 bytes per pixel * pixels per row
pixel_format = SDL_PIXELFORMAT_RGB24;
}
else
{ // STBI_rgb_alpha (RGBA)
depth = 32;
pitch = 4 * width;
pixel_format = SDL_PIXELFORMAT_RGBA32;
}
// Get rid of preexisting texture
free();
// 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);
if (loadedSurface == NULL)
{
printf("Unable to load image %s!\n", path.c_str());
}
else
{
// Color key image
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);
if (newTexture == NULL)
{
printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
}
else
{
// Get image dimensions
mWidth = loadedSurface->w;
mHeight = loadedSurface->h;
}
// Get rid of old loaded surface
SDL_FreeSurface(loadedSurface);
}
// Return success
mTexture = newTexture;
return mTexture != NULL;
}
bool LTexture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess access)
{
// Create uninitialized texture
mTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, access, width, height);
if (mTexture == NULL)
{
printf("Unable to create blank texture! SDL Error: %s\n", SDL_GetError());
}
else
{
mWidth = width;
mHeight = height;
}
return mTexture != NULL;
}
void LTexture::free()
{
// Free texture if it exists
if (mTexture != NULL)
{
SDL_DestroyTexture(mTexture);
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
}
void LTexture::setColor(Uint8 red, Uint8 green, Uint8 blue)
{
// Modulate texture rgb
SDL_SetTextureColorMod(mTexture, red, green, blue);
}
void LTexture::setBlendMode(SDL_BlendMode blending)
{
// Set blending function
SDL_SetTextureBlendMode(mTexture, blending);
}
void LTexture::setAlpha(Uint8 alpha)
{
// Modulate texture 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)
{
// Set rendering space and render to screen
SDL_Rect renderQuad = {x, y, mWidth, mHeight};
// Set clip rendering dimensions
if (clip != NULL)
{
renderQuad.w = clip->w;
renderQuad.h = clip->h;
}
// Render to screen
SDL_RenderCopyEx(renderer, mTexture, clip, &renderQuad, angle, center, flip);
}
void LTexture::setAsRenderTarget(SDL_Renderer *renderer)
{
// Make self render target
SDL_SetRenderTarget(renderer, mTexture);
}
int LTexture::getWidth()
{
return mWidth;
}
int LTexture::getHeight()
{
return mHeight;
}

66
source/ltexture.h Normal file
View File

@@ -0,0 +1,66 @@
#pragma once
#include "ifdefs.h"
#include <stdio.h>
#include <string>
#ifndef LTEXTURE_H
#define LTEXTURE_H
// Texture wrapper class
class LTexture
{
public:
// Initializes variables
LTexture();
// Deallocates memory
~LTexture();
// Loads image at specified path
bool loadFromFile(std::string path, SDL_Renderer *renderer);
// Creates blank texture
bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING);
// Deallocates texture
void free();
// Set color modulation
void setColor(Uint8 red, Uint8 green, Uint8 blue);
// Set blending
void setBlendMode(SDL_BlendMode blending);
// Set alpha modulation
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);
// Set self as render target
void setAsRenderTarget(SDL_Renderer *renderer);
// Gets image dimensions
int getWidth();
int getHeight();
// Pixel manipulators
bool lockTexture();
bool unlockTexture();
void *getPixels();
void copyPixels(void *pixels);
int getPitch();
Uint32 getPixel32(unsigned int x, unsigned int y);
private:
// The actual hardware texture
SDL_Texture *mTexture;
void *mPixels;
int mPitch;
// Image dimensions
int mWidth;
int mHeight;
};
#endif

130
source/main.cpp Normal file
View File

@@ -0,0 +1,130 @@
/*
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.
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
contiene funcionalidad adicional para crear animaciones. La clase text permite
dibujar letras de un png en pantalla a partir de una cadena de texto. La clase
menu permite crear una estructura con diferentes elementos, escribirlos en
pantalla y seleccionar uno de ellos.
A continuación tenemos las clases enfocadas a la lógica del juego, la clase player
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
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
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
el vector de globos y de balas y si tienen algun tipo asignado las gestiona.
Comprueba las colisiones entre los globos y el jugador y entre las balas y los
globos. Tiene ademas un nivel de amenaza que calcula en funcion del numero de globos
en pantalla y que se va incrementando conforme aumenta la puntuación del jugador.
Los objetos globo tienen varios contadores para alternar de un estado a otro.
En los vectores que contienen objetos, se considera activos los objetos que tienen
un tipo asociado diferente a NO_KIND
*/
#include "ifdefs.h"
#include <time.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();
// Establece el valor de la variable con el path del ejecutable
gameDirector->setExecutablePath(args[0]);
// Inicializa la lista de ficheros
gameDirector->setFileList();
// 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;
}
}

455
source/menu.cpp Normal file
View File

@@ -0,0 +1,455 @@
#include "ifdefs.h"
#include "const.h"
#include "text.h"
#include "menu.h"
// Constructor
Menu::Menu()
{
init("", 0, 0, 0, nullptr, nullptr, nullptr);
}
Menu::~Menu()
{
mRenderer = nullptr;
mText = nullptr;
}
// Inicializador
void Menu::init(std::string name, int x, int y, int backgroundType, LTexture *texture, SDL_Renderer *renderer, Text *text)
{
// Inicia variables
mName = name;
mSelector.index = 0;
mTotalItems = 0;
mItemSelected = MENU_NO_OPTION;
mVerticalPadding = 1;
mPosX = x;
mPosY = y;
mRectBG.rect.x = 0;
mRectBG.rect.y = 0;
mRectBG.rect.w = 0;
mRectBG.rect.h = 0;
mRectBG.r = 0;
mRectBG.g = 0;
mRectBG.b = 0;
mSelector.rect.x = 0;
mSelector.rect.y = 0;
mSelector.rect.w = 0;
mSelector.rect.h = 0;
mSelector.r = 0;
mSelector.g = 0;
mSelector.b = 0;
mSelector.a = 255;
mBackgroundType = backgroundType;
mText = text;
mRenderer = renderer;
mIsCentered = false;
mAreElementsCentered = false;
mCenter = x + ((SCREEN_WIDTH - x) / 2);
mWidestItem = 0;
// Selector
mSelector.origin = 0;
mSelector.target = 0;
mSelector.y = 0;
mSelector.numJumps = 4;
mSelector.despY = 0;
mSelector.moving = false;
// Sprite con los graficos del selector
//mSelectorSprite.setWidth(8);
//mSelectorSprite.setHeight(8);
//mSelectorSprite.setPosX(0);
//mSelectorSprite.setPosY(0);
//mSelectorSprite.setTexture(texture);
//mSelectorSprite.setRenderer(renderer);
//mSelectorSprite.setSpriteClip(0, 0, mSelectorSprite.getWidth(), mSelectorSprite.getHeight());
// Elementos del menu
for (int i = 0; i < 10; i++)
{
mItem[i].label = "";
mItem[i].w = 0;
mItem[i].h = 0;
mItem[i].x = 0;
mItem[i].y = 0;
mItem[i].hPaddingUp = 0;
mItem[i].hPaddingDown = 0;
}
// Mueve el grafico del selector al elemento seleccionado
//moveSelectorSprite(mSelector.index);
}
// Obtiene el nombre del menu
std::string Menu::getName()
{
return mName;
}
// Obtiene el valor de la variable
Uint8 Menu::getItemSelected()
{
return mItemSelected;
}
// Mueve el grafico del selector al elemento seleccionado
/*void Menu::moveSelectorSprite(int pos)
{
mSelector.rect.y = mItem[pos].y - 1;
}*/
// Actualiza la posicion y el estado del selector
void Menu::updateSelector()
{
if (mSelector.moving)
{
mSelector.y += mSelector.despY;
if (mSelector.despY > 0) // Va hacia abajo
{
if (mSelector.y > mSelector.target) // Ha llegado al destino
{
mSelector.origin = mSelector.y = mSelector.target;
mSelector.moving = false;
}
}
if (mSelector.despY < 0) // Va hacia abajo
{
if (mSelector.y < mSelector.target) // Ha llegado al destino
{
mSelector.origin = mSelector.y = mSelector.target;
mSelector.moving = false;
}
}
mSelector.rect.y = int(mSelector.y) - 1;
}
else
{
mSelector.rect.y = int(mSelector.y) - 1;
}
}
// Establece el origen del selector
void Menu::setSelectorOrigin(int value)
{
mSelector.origin = value;
}
// Establece el destino del selector
void Menu::setSelectorTarget(int value)
{
mSelector.target = value;
}
// Coloca el selector en una posición específica
void Menu::setSelectorPos(Uint8 index)
{
if (index < mTotalItems)
{
mSelector.index = index;
mSelector.y = mSelector.origin = mSelector.target = mItem[mSelector.index].y;
mSelector.moving = false;
}
}
// Obtiene la anchura del elemento más ancho del menu
Uint16 Menu::getWidestItem()
{
Uint16 result = 0;
// Obtenemos la anchura del item mas ancho
for (Uint8 i = 0; i < mTotalItems; i++)
{
if (mItem[i].w > result)
{
result = mItem[i].w;
}
}
return result;
}
// Deja el menu apuntando al primer elemento
void Menu::reset()
{
mItemSelected = MENU_NO_OPTION;
mSelector.index = 0;
//moveSelectorSprite(mSelector.index);
mSelector.origin = mSelector.target = mSelector.y = mItem[0].y;
mSelector.moving = false;
}
// Deja el menu sin elemento seleccionado
void Menu::deselectItem()
{
mItemSelected = MENU_NO_OPTION;
}
// Actualiza el menu para recolocarlo correctamente y establecer el tamaño
void Menu::reorganize()
{
setRectSize();
if (mIsCentered)
centerMenu(mCenter);
if (mAreElementsCentered)
centerMenuElements();
}
// Deja el menu apuntando al siguiente elemento
bool Menu::increaseSelectorIndex()
{
bool success = false;
mSelector.y = mSelector.origin = mItem[mSelector.index].y;
if (mSelector.index < (mTotalItems - 1))
{
mSelector.index++;
success = true;
}
mSelector.target = mItem[mSelector.index].y;
mSelector.despY = (mSelector.target - mSelector.origin) / mSelector.numJumps;
mSelector.moving = true;
return success;
}
// Deja el menu apuntando al elemento anterior
bool Menu::decreaseSelectorIndex()
{
bool success = false;
mSelector.y = mSelector.origin = mItem[mSelector.index].y;
if (mSelector.index > 0)
{
mSelector.index--;
success = true;
}
mSelector.target = mItem[mSelector.index].y;
mSelector.despY = (mSelector.target - mSelector.origin) / mSelector.numJumps;
mSelector.moving = true;
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()
{
updateSelector();
}
// Pinta el menu en pantalla
void Menu::render()
{
// Rendereritza el fondo del menu
if (mBackgroundType == MENU_BACKGROUND_SOLID)
{
SDL_SetRenderDrawColor(mRenderer, mRectBG.r, mRectBG.g, mRectBG.b, mRectBG.a);
SDL_RenderFillRect(mRenderer, &mRectBG.rect);
}
// Renderiza el rectangulo del selector
SDL_SetRenderDrawColor(mRenderer, mSelector.r, mSelector.g, mSelector.b, mSelector.a);
SDL_RenderFillRect(mRenderer, &mSelector.rect);
// Renderiza el sprite del selector
//mSelectorSprite.render();
// Renderitza el text
for (Uint8 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);
}
else
{
mText->write(mItem[i].x, mItem[i].y, mItem[i].label, 0);
}
}
}
// Establece el rectangulo de fondo del menu y el selector
void Menu::setRectSize()
{
Uint8 i = 0;
mRectBG.rect.w = 0;
mRectBG.rect.h = 0;
mSelector.rect.w = 0;
mSelector.rect.h = 0;
// Obtenemos la anchura del item mas ancho y la altura de la suma de alturas de los items
for (i = 0; i < mTotalItems; i++)
{
if (mItem[i].w > mRectBG.rect.w)
{
mRectBG.rect.w = mItem[i].w;
}
mRectBG.rect.h += mItem[i].h + mItem[i].hPaddingDown;
}
// La anchura de la cadena más larga, mas un caracter, mas la anchura del sprite del selector
mRectBG.rect.w += (mText->getSize() * 1); // + mSelectorSprite.getWidth();
// La altura de la suma de los items mas un caracter y menos un pixel (porque el texto en realidad es de 7 pixeles)
mRectBG.rect.h += (mText->getSize() * 1) - 1;
// La posición X es la del menú menos la anchura del sprite del selector y menos medio caracter
mRectBG.rect.x = mPosX - (mText->getSize() / 2); // - mSelectorSprite.getWidth();
// La posición Y es la del menu menos la altura de medio caracter i el padding
mRectBG.rect.y = mPosY - (mText->getSize() / 2) - mVerticalPadding;
// Establecemos los valores del rectangulo del selector a partir de los valores del rectangulo de fondo
mSelector.rect.h = (mText->getSize() * 1) + 1;
mSelector.rect.w = mRectBG.rect.w;
mSelector.rect.x = mRectBG.rect.x;
}
// Establece el valor de la variable
void Menu::setTotalItems(int num)
{
mTotalItems = num;
}
// Establece el color del rectangulo de fondo
void Menu::setBackgroundColor(int r, int g, int b, int alpha)
{
mRectBG.r = r;
mRectBG.g = g;
mRectBG.b = b;
mRectBG.a = alpha;
}
// Establece el color del rectangulo del selector
void Menu::setSelectorColor(int r, int g, int b, int alpha)
{
mSelector.r = r;
mSelector.g = g;
mSelector.b = b;
mSelector.a = alpha;
}
// Establece el color del texto del selector
void Menu::setSelectorTextColor(int r, int g, int b)
{
mSelector.itemR = r;
mSelector.itemG = g;
mSelector.itemB = b;
}
// Centra el menu respecto un punto
void Menu::centerMenu(int value)
{
mIsCentered = true;
mCenter = value;
// Actualiza el rectangulo de fondo para recalcular las dimensiones
setRectSize();
// Obten el acho del menu
mWidestItem = getWidestItem();
// Establece la nueva posición centrada en funcion del elemento más ancho
mPosX = (value) - (mWidestItem / 2);
// Reposiciona los elementos del menu
for (Uint8 i = 0; i < 10; i++)
{
mItem[i].x = mPosX;
}
// Recalcula el rectangulo de fondo
setRectSize();
// Recoloca el selector
mSelector.origin = mSelector.target = mSelector.y = mItem[mSelector.index].y;
mSelector.moving = false;
//moveSelectorSprite(mSelector.index);
}
// Centra los elementos del menu
void Menu::centerMenuElements()
{
mAreElementsCentered = true;
for (Uint8 i = 0; i < mTotalItems; i++)
{
//mItem[i].x = (mCenter - ((mText->lenght(mItem[i].label, 0)) / 2));
mItem[i].x = (mCenter - (mItem[i].w / 2));
}
// Mueve el grafico del selector al elemento seleccionado
//moveSelectorSprite(mSelector.index);
}
// Añade un item al menu
void Menu::addItem(std::string text, const Uint8 hPaddingUp, const Uint8 hPaddingDown)
{
// Si es el primer item coge la posición y del propio menu
if (mTotalItems == 0)
{
mItem[mTotalItems].label = text;
mItem[mTotalItems].w = mText->lenght(mItem[mTotalItems].label, 0);
mItem[mTotalItems].h = mText->getSize() + (mVerticalPadding * 2);
mItem[mTotalItems].x = mPosX;
mItem[mTotalItems].y = mPosY;
mItem[mTotalItems].hPaddingUp = hPaddingUp;
mItem[mTotalItems].hPaddingDown = hPaddingDown;
}
else
{
// En caso contrario, coge la posición y a partir del elemento anterior
if (mTotalItems < 10)
{
mItem[mTotalItems].label = text;
mItem[mTotalItems].w = mText->lenght(mItem[mTotalItems].label, 0);
mItem[mTotalItems].h = mText->getSize() + (mVerticalPadding * 2);
mItem[mTotalItems].x = mPosX;
mItem[mTotalItems].y = mItem[mTotalItems - 1].y + mItem[mTotalItems - 1].h + mItem[mTotalItems - 1].hPaddingDown;
mItem[mTotalItems].hPaddingUp = hPaddingUp;
mItem[mTotalItems].hPaddingDown = hPaddingDown;
}
}
setTotalItems(mTotalItems + 1);
reorganize();
setSelectorPos(0);
}
// Cambia el texto de un item
void Menu::setItemCaption(Uint8 index, std::string text)
{
mItem[index].label = text;
mItem[index].w = mText->lenght(mItem[index].label, 0);
reorganize();
}
// Establece el indice del itemm que se usará por defecto al cancelar el menu
void Menu::setDefaultActionWhenCancel(Uint8 item)
{
mDefaultActionWhenCancel = item;
}

190
source/menu.h Normal file
View File

@@ -0,0 +1,190 @@
#pragma once
#include "sprite.h"
#include "text.h"
#ifndef MENU_H
#define MENU_H
// 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:
// Establece el valor de la variable
void setTotalItems(int num);
// Establece el rectangulo de fondo del menu
void setRectSize();
// Actualiza el menu para recolocarlo correctamente y establecer el tamaño
void reorganize();
// Deja el menu apuntando al siguiente elemento
bool increaseSelectorIndex();
// Deja el menu apuntando al elemento anterior
bool decreaseSelectorIndex();
// Mueve el grafico del selector al elemento seleccionado
//void moveSelectorSprite(int pos);
// Actualiza la posicion y el estado del selector
void updateSelector();
// Establece el origen del selector
void setSelectorOrigin(int value);
// 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;
// Nombre del menu
std::string mName;
// Numero de items del menu
Uint8 mTotalItems;
// Item del menu que ha sido seleccionado
Uint8 mItemSelected;
// Item del menu seleccionado cuando se cancela el menu
Uint8 mDefaultActionWhenCancel;
// Espacio de separacion entre items
Uint8 mVerticalPadding;
// Tipo de fondo para el menu
Uint8 mBackgroundType;
// Sprite con los graficos del selector
//Sprite mSelectorSprite;
struct rectangle
{
SDL_Rect rect;
Uint8 r; // Rojo
Uint8 g; // Verde
Uint8 b; // Azul
Uint8 a; // Transparencia
};
rectangle mRectBG; // Rectangulo de fondo del menu
// Estructura para cada elemento del menu
struct item
{
std::string label;
int x;
int y;
Uint8 w;
Uint8 h;
Uint8 hPaddingUp;
Uint8 hPaddingDown;
};
item mItem[10];
// Texto para poder escribir los items del menu
Text *mText;
// Puntero al renderizador de la ventana
SDL_Renderer *mRenderer;
// Variable para saber si el menu debe estar centrado respecto a un punto
bool mIsCentered;
// Centro del menu
int mCenter;
// Variable para saber si los elementos van centrados
bool mAreElementsCentered;
// Anchura del elemento más ancho
Uint16 mWidestItem;
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
};
selector mSelector;
};
#endif

132
source/movingsprite.cpp Normal file
View File

@@ -0,0 +1,132 @@
#include "const.h"
#include "movingsprite.h"
#include <iostream>
// Constructor
MovingSprite::MovingSprite()
{
init(0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr);
}
// Destructor
MovingSprite::~MovingSprite()
{
init(0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr);
}
// Iniciador
void MovingSprite::init(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, 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 la velocidad X,Y del sprite
setVelX(velx);
setVelY(vely);
// Establece la aceleración X,Y del sprite
setAccelX(accelx);
setAccelY(accely);
// Establece la textura donde están los gráficos para el sprite
setTexture(texture);
// Establece el renderizador
setRenderer(renderer);
// Establece el rectangulo de donde coger la imagen
setSpriteClip(0, 0, w, h);
}
// Mueve el sprite
void MovingSprite::move()
{
mPosX += mVelX;
mPosY += mVelY;
mVelX += mAccelX;
mVelY += mAccelY;
}
// Muestra el sprite por pantalla
void MovingSprite::render()
{
mTexture->render(mRenderer, (int)mPosX, (int)mPosY, &mSpriteClip);
}
// Establece el valor de la variable
float MovingSprite::getPosX()
{
return mPosX;
}
// Establece el valor de la variable
float MovingSprite::getPosY()
{
return mPosY;
}
// Establece el valor de la variable
float MovingSprite::getVelX()
{
return mVelX;
}
// Establece el valor de la variable
float MovingSprite::getVelY()
{
return mVelY;
}
// Establece el valor de la variable
float MovingSprite::getAccelX()
{
return mAccelX;
}
// Establece el valor de la variable
float MovingSprite::getAccelY()
{
return mAccelY;
}
// Establece el valor de la variable
void MovingSprite::setPosX(float x)
{
mPosX = x;
}
// Establece el valor de la variable
void MovingSprite::setPosY(float y)
{
mPosY = y;
}
// Establece el valor de la variable
void MovingSprite::setVelX(float x)
{
mVelX = x;
}
// Establece el valor de la variable
void MovingSprite::setVelY(float y)
{
mVelY = y;
}
// Establece el valor de la variable
void MovingSprite::setAccelX(float x)
{
mAccelX = x;
}
// Establece el valor de la variable
void MovingSprite::setAccelY(float y)
{
mAccelY = y;
}

77
source/movingsprite.h Normal file
View File

@@ -0,0 +1,77 @@
#pragma once
#include "ifdefs.h"
#include "sprite.h"
#ifndef MOVINGSPRITE_H
#define MOVINGSPRITE_H
// Clase MovingSprite. Añade posicion y velocidad en punto flotante
class MovingSprite : public Sprite
{
public:
// Constructor
MovingSprite();
// Destructor
~MovingSprite();
// Iniciador
void init(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, LTexture *texture, SDL_Renderer *renderer);
// Mueve el sprite
void move();
// 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();
// 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;
// Velocidad
float mVelX;
float mVelY;
// Aceleración
float mAccelX;
float mAccelY;
};
#endif

751
source/player.cpp Normal file
View File

@@ -0,0 +1,751 @@
#include "const.h"
#include "player.h"
// Constructor
Player::Player()
{
mSpriteLegs = new AnimatedSprite();
mSpriteBody = new AnimatedSprite();
init(0, 0, nullptr, nullptr, nullptr);
}
// Destructor
Player::~Player()
{
init(0, 0, nullptr, nullptr, nullptr);
mSpriteLegs = nullptr;
mSpriteBody = nullptr;
delete mSpriteLegs;
delete mSpriteBody;
}
// Iniciador
void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody, SDL_Renderer *renderer)
{
// Inicializa variables de estado
mAlive = true;
mStatusWalking = PLAYER_STATUS_WALKING_STOP;
mStatusFiring = PLAYER_STATUS_FIRING_NO;
mInvulnerable = false;
mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER;
mExtraHit = false;
// Establece la altura y el ancho del jugador
mWidth = 3 * BLOCK;
mHeight = 3 * BLOCK;
// Establece la posición inicial del jugador
mPosX = x;
mPosY = y;
// Establece el tamaño del circulo de colisión
mCollider.r = 7;
// Actualiza la posición del circulo de colisión
shiftColliders();
// Establece la velocidad inicial
mVelX = 0;
mVelY = 0;
// Establece la velocidad base
mBaseSpeed = 1.5;
// Establece el numero inicial de vidas
mStartingLives = 3;
mLives = mStartingLives;
// Establece la puntuación inicial
mScore = 0;
// Establece el multiplicador de puntos inicial
mScoreMultiplier = 1.0f;
// Inicia el contador para la cadencia de disparo
mCooldown = 10;
// Inicia el sprite
mSpriteLegs->init(textureLegs, renderer);
mSpriteBody->init(textureBody, renderer);
// Establece el alto y ancho del sprite
mSpriteLegs->setWidth(mWidth);
mSpriteLegs->setHeight(mHeight);
mSpriteBody->setWidth(mWidth);
mSpriteBody->setHeight(mHeight);
// Establece la posición del sprite
mSpriteLegs->setPosX(int(mPosX));
mSpriteLegs->setPosY(mPosY);
mSpriteBody->setPosX(int(mPosX));
mSpriteBody->setPosY(mPosY);
// Inicializa las variables para la animación
mSpriteLegs->setCurrentFrame(0);
mSpriteLegs->setAnimationCounter(0);
mSpriteBody->setCurrentFrame(0);
mSpriteBody->setAnimationCounter(0);
// Establece el numero de frames de cada animacion
mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 4);
mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 4);
mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 4);
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);
mSpriteLegs->setAnimationSpeed(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 5);
mSpriteLegs->setAnimationSpeed(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_LEFT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_LEFT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 5);
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);
mSpriteLegs->setAnimationLoop(PLAYER_ANIMATION_LEGS_WALKING_LEFT, true);
mSpriteLegs->setAnimationLoop(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_LEFT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_LEFT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_RIGHT, true);
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);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 1, mWidth * 1, mHeight * 0, mWidth, mHeight);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 2, mWidth * 2, mHeight * 0, mWidth, mHeight);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 3, mWidth * 3, mHeight * 0, mWidth, mHeight);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 0, mWidth * 0, mHeight * 1, mWidth, mHeight);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 1, mWidth * 1, mHeight * 1, mWidth, mHeight);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 2, mWidth * 2, mHeight * 1, mWidth, mHeight);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 3, mWidth * 3, mHeight * 1, mWidth, mHeight);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 0, mWidth * 0, mHeight * 2, mWidth, mHeight);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 1, mWidth * 1, mHeight * 2, mWidth, mHeight);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 2, mWidth * 2, mHeight * 2, mWidth, mHeight);
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 3, mWidth * 3, mHeight * 2, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, 0, mWidth * 0, mHeight * 0, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, 1, mWidth * 1, mHeight * 0, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, 2, mWidth * 2, mHeight * 0, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, 3, mWidth * 3, mHeight * 0, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, 0, mWidth * 0, mHeight * 1, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, 1, mWidth * 1, mHeight * 1, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, 2, mWidth * 2, mHeight * 1, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, 3, mWidth * 3, mHeight * 1, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 0, mWidth * 0, mHeight * 2, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 1, mWidth * 1, mHeight * 2, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 2, mWidth * 2, mHeight * 2, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 3, mWidth * 3, mHeight * 2, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 0, mWidth * 0, mHeight * 3, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 1, mWidth * 1, mHeight * 3, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 2, mWidth * 2, mHeight * 3, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 3, mWidth * 3, mHeight * 3, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 0, mWidth * 0, mHeight * 4, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 1, mWidth * 1, mHeight * 4, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 2, mWidth * 2, mHeight * 4, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 3, mWidth * 3, mHeight * 4, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 0, mWidth * 0, mHeight * 5, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 1, mWidth * 1, mHeight * 5, mWidth, mHeight);
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));
}
// Actua en consecuencia de la entrada recibida
void Player::setInput(Uint8 input)
{
switch (input)
{
case INPUT_LEFT:
mVelX = -mBaseSpeed;
if (mExtraHit)
{
setWalkingStatus(PLAYER_STATUS_WALKING_LEFT);
}
else
{
setWalkingStatus(PLAYER_STATUS_WALKING_LEFT);
}
break;
case INPUT_RIGHT:
mVelX = mBaseSpeed;
if (mExtraHit)
{
setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT);
}
else
{
setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT);
}
break;
case INPUT_FIRE_UP:
if (mExtraHit)
{
setFiringStatus(PLAYER_STATUS_FIRING_UP);
}
else
{
setFiringStatus(PLAYER_STATUS_FIRING_UP);
}
break;
case INPUT_FIRE_LEFT:
if (mExtraHit)
{
setFiringStatus(PLAYER_STATUS_FIRING_LEFT);
}
else
{
setFiringStatus(PLAYER_STATUS_FIRING_LEFT);
}
break;
case INPUT_FIRE_RIGHT:
if (mExtraHit)
{
setFiringStatus(PLAYER_STATUS_FIRING_RIGHT);
}
else
{
setFiringStatus(PLAYER_STATUS_FIRING_RIGHT);
}
break;
default:
mVelX = 0;
if (mExtraHit)
{
setWalkingStatus(PLAYER_STATUS_WALKING_STOP);
}
else
{
setWalkingStatus(PLAYER_STATUS_WALKING_STOP);
}
break;
}
}
// Mueve el jugador a la posición y animación que le corresponde
void Player::move()
{
if (isAlive())
{
// Mueve el jugador a derecha o izquierda
mPosX += mVelX;
// Si el jugador abandona el area de juego por los laterales
if ((mPosX < PLAY_AREA_LEFT) || (mPosX + mWidth > PLAY_AREA_RIGHT))
{
// Restaura su posición
mPosX -= mVelX;
}
// Actualiza la posición del sprite
mSpriteLegs->setPosX(getPosX());
mSpriteLegs->setPosY(mPosY);
mSpriteBody->setPosX(getPosX());
mSpriteBody->setPosY(mPosY);
}
}
// Pinta el jugador en pantalla
void Player::render()
{
if (isAlive())
{
if (mInvulnerable)
{
if ((mInvulnerableTimer % 10) > 4)
{
mSpriteLegs->render();
mSpriteBody->render();
}
}
else
{
mSpriteLegs->render();
mSpriteBody->render();
}
}
}
// Establece el estado del jugador cuando camina
void Player::setWalkingStatus(Uint8 status)
{
// Si cambiamos de estado, reiniciamos la animación
if (mStatusWalking != status)
{
mStatusWalking = status;
mSpriteLegs->setCurrentFrame(0);
}
}
// Establece el estado del jugador cuando dispara
void Player::setFiringStatus(Uint8 status)
{
// Si cambiamos de estado, reiniciamos la animación
if (mStatusFiring != status)
{
mStatusFiring = status;
mSpriteBody->setCurrentFrame(0);
}
}
// Establece la animación correspondiente al estado
void Player::setAnimation()
{
switch (mStatusWalking)
{
case PLAYER_STATUS_WALKING_LEFT:
mSpriteLegs->animate(PLAYER_ANIMATION_LEGS_WALKING_LEFT);
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);
}
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);
}
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);
}
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);
}
break;
default:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
break;
}
break;
case PLAYER_STATUS_WALKING_RIGHT:
mSpriteLegs->animate(PLAYER_ANIMATION_LEGS_WALKING_RIGHT);
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);
}
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);
}
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);
}
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);
}
break;
default:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
break;
}
break;
case PLAYER_STATUS_WALKING_STOP:
mSpriteLegs->animate(PLAYER_ANIMATION_LEGS_WALKING_STOP);
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);
}
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);
}
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);
}
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);
}
break;
default:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
break;
}
break;
default:
mSpriteLegs->animate(PLAYER_ANIMATION_LEGS_WALKING_STOP);
break;
}
}
// Obtiene el valor de la variable
int Player::getPosX()
{
return int(mPosX);
}
// Obtiene el valor de la variable
int Player::getPosY()
{
return mPosY;
}
// Obtiene el valor de la variable
int Player::getWidth()
{
return mWidth;
}
// Obtiene el valor de la variable
int Player::getHeight()
{
return mHeight;
}
// Indica si el jugador puede disparar
bool Player::canFire()
{
// Si el contador a llegado a cero, podemos disparar. En caso contrario decrementamos el contador
if (mCooldown > 0)
{
return false;
}
else
{
return true;
}
}
// Establece el valor de la variable
void Player::setFireCooldown(int time)
{
mCooldown = time;
}
// Actualiza el valor de la variable
void Player::updateCooldown()
{
if (mCooldown > 0)
{
--mCooldown;
}
else
{
setFiringStatus(PLAYER_STATUS_FIRING_NO);
}
}
// Actualiza al jugador a su posicion, animación y controla los contadores
void Player::update()
{
move();
setAnimation();
shiftColliders();
updateCooldown();
updateInvulnerableTimer();
}
// Obtiene la puntuación del jugador
int Player::getScore()
{
return mScore;
}
// Asigna un valor a la puntuación del jugador
void Player::setScore(int score)
{
mScore = score;
}
// Incrementa la puntuación del jugador
void Player::addScore(int score)
{
mScore += score;
}
// Obtiene el valor de la variable
bool Player::isAlive()
{
return mAlive;
}
// Establece el valor de la variable
void Player::setAlive(bool value)
{
mAlive = value;
}
// Obtiene el valor de la variable
float Player::getScoreMultiplier()
{
return mScoreMultiplier;
}
// Establece el valor de la variable
void Player::setScoreMultiplier(float value)
{
mScoreMultiplier = value;
}
// Aumenta el valor de la variable hasta un máximo
void Player::incScoreMultiplier()
{
if (mScoreMultiplier < 5.0f)
{
mScoreMultiplier += 0.1f;
}
}
// Decrementa el valor de la variable hasta un mínimo
void Player::decScoreMultiplier()
{
if (mScoreMultiplier > 1.0f)
{
mScoreMultiplier -= 0.1f;
}
}
// Obtiene el valor de la variable
bool Player::isInvulnerable()
{
return mInvulnerable;
}
// Establece el valor de la variable
void Player::setInvulnerable(bool value)
{
mInvulnerable = value;
}
// Obtiene el valor de la variable
bool Player::getInvulnerableTimer()
{
return mInvulnerableTimer;
}
// Establece el valor de la variable
void Player::setInvulnerableTimer(Uint16 value)
{
mInvulnerableTimer = value;
}
// Actualiza el valor de la variable
void Player::updateInvulnerableTimer()
{
if (mInvulnerableTimer > 0)
{
--mInvulnerableTimer;
}
else
{
mInvulnerable = false;
mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER;
}
}
// Obtiene el valor de la variable
bool Player::hasExtraHit()
{
return mExtraHit;
}
// Concede un toque extra al jugador
void Player::giveExtraHit()
{
mExtraHit = true;
}
// Quita el toque extra al jugador
void Player::removeExtraHit()
{
mExtraHit = false;
mInvulnerable = true;
mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER;
}
// Obtiene el circulo de colisión
Circle &Player::getCollider()
{
return mCollider;
}
// Actualiza el circulo de colisión a la posición del jugador
void Player::shiftColliders()
{
mCollider.x = Uint16(mPosX + (mWidth / 2));
mCollider.y = mPosY + (mHeight / 2);
}

173
source/player.h Normal file
View File

@@ -0,0 +1,173 @@
#pragma once
#include "struct.h"
#include "animatedsprite.h"
#ifndef PLAYER_H
#define PLAYER_H
// The player
class Player
{
public:
// Constructor
Player();
// Destructor
~Player();
// Iniciador
void init(float x, int y, LTexture *textureLegs, LTexture *textureBody, SDL_Renderer *renderer);
// Actua en consecuencia de la entrada recibida
void setInput(Uint8 input);
// Mueve el jugador a la posición y animación que le corresponde
void move();
// Pinta el jugador en pantalla
void render();
// Establece el estado del jugador
void setWalkingStatus(Uint8 status);
void setFiringStatus(Uint8 status);
// Establece la animación correspondiente al estado
void setAnimation();
// Obtiene el valor de la variable
int getPosX();
// Obtiene el valor de la variable
int getPosY();
// Obtiene el valor de la variable
int getWidth();
// Obtiene el valor de la variable
int getHeight();
// Indica si el jugador puede disparar
bool canFire();
// Establece el valor de la variable
void setFireCooldown(int time);
// Actualiza el valor de la variable
void updateCooldown();
// Actualiza al jugador a su posicion, animación y controla los contadores
void update();
// Obtiene la puntuación del jugador
int getScore();
// Asigna un valor a la puntuación del jugador
void setScore(int score);
// Incrementa la puntuación del jugador
void addScore(int score);
// Obtiene el valor de la variable
bool isAlive();
// Establece el valor de la variable
void setAlive(bool value);
// Obtiene el valor de la variable
float getScoreMultiplier();
// Establece el valor de la variable
void setScoreMultiplier(float value);
// Aumenta el valor de la variable hasta un máximo
void incScoreMultiplier();
// Decrementa el valor de la variable hasta un mínimo
void decScoreMultiplier();
// Obtiene el valor de la variable
bool isInvulnerable();
// Establece el valor de la variable
void setInvulnerable(bool value);
// Obtiene el valor de la variable
bool getInvulnerableTimer();
// Establece el valor de la variable
void setInvulnerableTimer(Uint16 value);
// Actualiza el valor de la variable
void updateInvulnerableTimer();
// Obtiene el valor de la variable
bool hasExtraHit();
// Concede un toque extra al jugador
void giveExtraHit();
// Quita el toque extra al jugador
void removeExtraHit();
// 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();
};
#endif

228
source/smartsprite.cpp Normal file
View File

@@ -0,0 +1,228 @@
#include "const.h"
#include "smartsprite.h"
// Constructor
SmartSprite::SmartSprite()
{
init(nullptr, nullptr);
}
// Destructor
SmartSprite::~SmartSprite()
{
init(nullptr, nullptr);
}
// Inicializador
void SmartSprite::init(LTexture *texture, SDL_Renderer *renderer)
{
setTexture(texture);
setRenderer(renderer);
setPosX(0);
setPosY(0);
setWidth(0);
setHeight(0);
setVelX(0);
setVelY(0);
setAccelX(0);
setAccelY(0);
setSpriteClip(0, 0, 0, 0);
setEnabled(false);
setEnabledTimer(0);
mIsOnDestination = false;
mDestX = 0;
mDestY = 0;
// El Id siempre es >=0, por lo tanto si no se le asigna Id se queda en negativo
mId = -1;
mIntroEvents = nullptr;
}
// Pone a cero los elementos del objeto
void SmartSprite::erase()
{
init(nullptr, nullptr);
}
// Obtiene el valor de la variable
bool SmartSprite::isEnabled()
{
return mEnabled;
}
// Establece el valor de la variable
void SmartSprite::setEnabled(bool state)
{
mEnabled = state;
}
// Obtiene el valor de la variable
Uint16 SmartSprite::getEnabledTimer()
{
return mEnabledTimer;
}
// Establece el valor de la variable
void SmartSprite::setEnabledTimer(Uint16 time)
{
mEnabledTimer = time;
}
// Establece el valor de la variable
void SmartSprite::setDestX(int value)
{
mDestX = value;
}
// Establece el valor de la variable
void SmartSprite::setDestY(int value)
{
mDestY = value;
}
// Obtiene el valor de la variable
int SmartSprite::getDestX()
{
return mDestX;
}
// Obtiene el valor de la variable
int SmartSprite::getDestY()
{
return mDestY;
}
// Actualiza la posición y comprueba si ha llegado a su destino
bool SmartSprite::update()
{
if (mEnabled)
{
move();
// Comprueba si se desplaza en el eje X hacia la derecha
if ((getAccelX() > 0) || ((getAccelX() == 0) && (getVelX() > 0)))
{
// Comprueba si hemos llegado al destino
if (getPosX() > mDestX)
{
// Lo coloca en posición
setPosX(mDestX);
// Lo detiene
setVelX(0.0f);
setAccelX(0.0f);
}
}
// Comprueba si se desplaza en el eje X hacia la izquierda
else if ((getAccelX() < 0) || ((getAccelX() == 0) && (getVelX() < 0)))
{
// Comprueba si hemos llegado al destino
if (getPosX() < mDestX)
{
// Lo coloca en posición
setPosX(mDestX);
// Lo detiene
setVelX(0.0f);
setAccelX(0.0f);
}
}
// Comprueba si se desplaza en el eje Y hacia abajo
if ((getAccelY() > 0) || ((getAccelY() == 0) && (getVelY() > 0)))
{
// Comprueba si hemos llegado al destino
if (getPosY() > mDestY)
{
// Lo coloca en posición
setPosY(mDestY);
// Lo detiene
setVelY(0.0f);
setAccelY(0.0f);
}
}
// Comprueba si se desplaza en el eje Y hacia arriba
else if ((getAccelY() < 0) || ((getAccelY() == 0) && (getVelY() < 0)))
{
// Comprueba si hemos llegado al destino
if (getPosY() < mDestY)
{
// Lo coloca en posición
setPosY(mDestY);
// Lo detiene
setVelY(0.0f);
setAccelY(0.0f);
}
}
// Comprueba si ha llegado a su destino
if ((getPosX() == mDestX) && (getPosY() == mDestY))
{
mIsOnDestination = true;
}
else
{
mIsOnDestination = false;
}
// Si esta en el destino comprueba su contador
if (mIsOnDestination)
{
// Si el contador es mayor que cero, lo decrementa
if (mEnabledTimer > 0)
{
--mEnabledTimer;
}
// Si ha llegado a cero, deshabilita el objeto o manda el aviso en función de si tiene Id
else if (mEnabledTimer == 0)
{
if (mId < 0)
{
mEnabled = false;
}
else
{
mIntroEvents[mId] = EVENT_COMPLETED;
}
}
}
}
return mIsOnDestination;
}
// Obtiene el valor de la variable
bool SmartSprite::isOnDestination()
{
return mIsOnDestination;
}
// Pinta el objeto en pantalla
void SmartSprite::render()
{
if (mEnabled)
{
MovingSprite::render();
}
}
// Establece el valor de la variable
void SmartSprite::setId(int id)
{
mId = id;
}
// Establece el valor de la variable
void SmartSprite::setIntroEvents(Uint8 *value)
{
mIntroEvents = value;
}

84
source/smartsprite.h Normal file
View File

@@ -0,0 +1,84 @@
#pragma once
#include "struct.h"
#include "animatedsprite.h"
#ifndef SMARTSPRITE_H
#define SMARTSPRITE_H
// Clase SmartSprite
class SmartSprite : public AnimatedSprite
{
public:
// Constructor
SmartSprite();
// Destructor
~SmartSprite();
// Inicializador
void init(LTexture *texture, SDL_Renderer *renderer);
// Pone a cero los elementos del objeto
void erase();
// Obtiene el valor de la variable
bool isEnabled();
// Establece el valor de la variable
void setEnabled(bool state);
// Obtiene el valor de la variable
Uint16 getEnabledTimer();
// Establece el valor de la variable
void setEnabledTimer(Uint16 time);
// Establece el valor de la variable
void setDestX(int value);
// Establece el valor de la variable
void setDestY(int value);
// Obtiene el valor de la variable
int getDestX();
// Obtiene el valor de la variable
int getDestY();
// Actualiza la posición y comprueba si ha llegado a su destino
bool update();
// Obtiene el valor de la variable
bool isOnDestination();
// Pinta el objeto en pantalla
void render();
// Establece el valor de la variable
void setId(int id);
// 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

149
source/sprite.cpp Normal file
View File

@@ -0,0 +1,149 @@
#include "sprite.h"
// Constructor
Sprite::Sprite()
{
init(0, 0, 0, 0, nullptr, nullptr);
}
// Destructor
Sprite::~Sprite()
{
mTexture = nullptr;
mRenderer = nullptr;
}
// 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 puntero al renderizador de la ventana
setRenderer(renderer);
// Establece la textura donde están los gráficos para el sprite
setTexture(texture);
// Establece el rectangulo de donde coger la imagen
setSpriteClip(0, 0, w, h);
}
// Inicializador
void Sprite::init(SDL_Rect rect, LTexture *texture, SDL_Renderer *renderer)
{
// Establece el alto y el ancho del sprite
mWidth = rect.w;
mHeight = rect.h;
// Establece la posición X,Y del sprite
mPosX = rect.x;
mPosY = rect.y;
// Establece el puntero al renderizador de la ventana
setRenderer(renderer);
// Establece la textura donde están los gráficos para el sprite
setTexture(texture);
// Establece el rectangulo de donde coger la imagen
setSpriteClip(rect);
}
// Muestra el sprite por pantalla
void Sprite::render()
{
mTexture->render(mRenderer, mPosX, mPosY, &mSpriteClip);
}
// Obten el valor de la variable
int Sprite::getPosX()
{
return mPosX;
}
// Obten el valor de la variable
int Sprite::getPosY()
{
return mPosY;
}
// Obten el valor de la variable
int Sprite::getWidth()
{
return mWidth;
}
// Obten el valor de la variable
int Sprite::getHeight()
{
return mHeight;
}
// Establece el valor de la variable
void Sprite::setPosX(int x)
{
mPosX = x;
}
// Establece el valor de la variable
void Sprite::setPosY(int y)
{
mPosY = y;
}
// Establece el valor de la variable
void Sprite::setWidth(int w)
{
mWidth = w;
}
// Establece el valor de la variable
void Sprite::setHeight(int h)
{
mHeight = h;
}
// Obten el valor de la variable
SDL_Rect Sprite::getSpriteClip()
{
return mSpriteClip;
}
// Establece el valor de la variable
void Sprite::setSpriteClip(SDL_Rect rect)
{
mSpriteClip = rect;
}
// Establece el valor de la variable
void Sprite::setSpriteClip(int x, int y, int w, int h)
{
mSpriteClip.x = x;
mSpriteClip.y = y;
mSpriteClip.w = w;
mSpriteClip.h = h;
}
// Obten el valor de la variable
LTexture *Sprite::getTexture()
{
return mTexture;
}
// Establece el valor de la variable
void Sprite::setTexture(LTexture *texture)
{
mTexture = texture;
}
// Establece el valor de la variable
void Sprite::setRenderer(SDL_Renderer *renderer)
{
mRenderer = renderer;
}

87
source/sprite.h Normal file
View File

@@ -0,0 +1,87 @@
#pragma once
#include "ifdefs.h"
#include "ltexture.h"
#ifndef SPRITE_H
#define SPRITE_H
// Clase sprite
class Sprite
{
public:
// Constructor
Sprite();
// Destructor
~Sprite();
// 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();
// Establece el valor de la variable
void setSpriteClip(SDL_Rect rect);
// Establece el valor de la variable
void setSpriteClip(int x, int y, int w, int h);
// Obten el valor de la variable
LTexture* getTexture();
// Establece el valor de la variable
void setTexture(LTexture *texture);
// Establece el valor de la variable
void setRenderer(SDL_Renderer *renderer);
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;
};
#endif

7762
source/stb_image.h Normal file

File diff suppressed because it is too large Load Diff

5565
source/stb_vorbis.c Normal file

File diff suppressed because it is too large Load Diff

42
source/struct.h Normal file
View File

@@ -0,0 +1,42 @@
#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

244
source/text.cpp Normal file
View File

@@ -0,0 +1,244 @@
#include "const.h"
#include "text.h"
// Constructor
Text::Text()
{
mSprite = new Sprite();
init(nullptr, nullptr, 0, 0);
}
// Destructor
Text::~Text()
{
delete mSprite;
}
// Inicializador
void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size)
{
// Inicializa variables
mType = type;
mSize = size;
// Inicia los valores del sprite que dibuja las letras
mSprite->setWidth(size);
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";
// Inicializa a cero el vector con las coordenadas
for (Uint8 i = 0; i < 255; i++)
{
mOffset[i].x = 0;
mOffset[i].y = 0;
mOffset[i].w = 0;
}
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho
for (Uint8 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 el ancho de cada caracter
if (type == TEXT_VARIABLE)
{
mOffset[int(' ')].w = 7;
mOffset[int('-')].w = 6;
mOffset[int('/')].w = 5;
mOffset[int('(')].w = 5;
mOffset[int(')')].w = 5;
mOffset[int('.')].w = 4;
mOffset[int(':')].w = 4;
mOffset[int('#')].w = 7;
mOffset[int('!')].w = 7;
mOffset[int('\'')].w = 3;
mOffset[int('0')].w = 7;
mOffset[int('1')].w = 5;
mOffset[int('2')].w = 7;
mOffset[int('3')].w = 7;
mOffset[int('4')].w = 7;
mOffset[int('5')].w = 7;
mOffset[int('6')].w = 7;
mOffset[int('7')].w = 7;
mOffset[int('8')].w = 7;
mOffset[int('9')].w = 7;
mOffset[int('A')].w = 7;
mOffset[int('B')].w = 7;
mOffset[int('C')].w = 7;
mOffset[int('D')].w = 7;
mOffset[int('E')].w = 7;
mOffset[int('F')].w = 7;
mOffset[int('G')].w = 7;
mOffset[int('H')].w = 7;
mOffset[int('I')].w = 4;
mOffset[int('J')].w = 6;
mOffset[int('K')].w = 8;
mOffset[int('L')].w = 6;
mOffset[int('M')].w = 9;
mOffset[int('N')].w = 8;
mOffset[int('O')].w = 8;
mOffset[int('P')].w = 7;
mOffset[int('Q')].w = 8;
mOffset[int('R')].w = 7;
mOffset[int('S')].w = 6;
mOffset[int('T')].w = 8;
mOffset[int('U')].w = 7;
mOffset[int('V')].w = 8;
mOffset[int('W')].w = 9;
mOffset[int('X')].w = 8;
mOffset[int('Y')].w = 8;
mOffset[int('Z')].w = 7;
mOffset[int('a')].w = 7;
mOffset[int('b')].w = 7;
mOffset[int('c')].w = 6;
mOffset[int('d')].w = 7;
mOffset[int('e')].w = 7;
mOffset[int('f')].w = 5;
mOffset[int('g')].w = 7;
mOffset[int('h')].w = 7;
mOffset[int('i')].w = 4;
mOffset[int('j')].w = 5;
mOffset[int('k')].w = 7;
mOffset[int('l')].w = 4;
mOffset[int('m')].w = 10;
mOffset[int('n')].w = 7;
mOffset[int('o')].w = 7;
mOffset[int('p')].w = 7;
mOffset[int('q')].w = 7;
mOffset[int('r')].w = 6;
mOffset[int('s')].w = 6;
mOffset[int('t')].w = 5;
mOffset[int('u')].w = 7;
mOffset[int('v')].w = 7;
mOffset[int('w')].w = 9;
mOffset[int('x')].w = 7;
mOffset[int('y')].w = 7;
mOffset[int('z')].w = 7;
}
}
// Escribe el texto en pantalla
void Text::write(int x, int y, std::string text)
{
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)
{
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 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)
{
mSprite->getTexture()->setColor(R, G, B);
write(x, y, text);
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)
{
// 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);
}
}
// 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)
{
shift += (mOffset[int(text[i])].w + kerning);
}
return shift;
}
// Obtiene el valor de la variable
Uint8 Text::getType()
{
return mType;
}
// Establece el valor de la variable
void Text::setType(Uint8 type)
{
mType = type;
}
// Obtiene el valor de la variable
Uint8 Text::getSize()
{
return mSize;
}
// Establece el valor de la variable
void Text::setSize(Uint8 size)
{
mSize = size;
}

66
source/text.h Normal file
View File

@@ -0,0 +1,66 @@
#pragma once
#include "sprite.h"
#ifndef TEXT_H
#define TEXT_H
// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text
{
public:
// Constructor
Text();
// Destructor
~Text();
// Inicializador
void init(LTexture *texture, SDL_Renderer *renderer, 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);
// Escribe el texto con colores
void writeColored(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B);
// Escribe el texto centrado en un punto x y con kerning
void writeCentered(int x, int y, std::string text, int kerning);
// Obtiene la longitud en pixels de una cadena
Uint16 lenght(std::string text, int kerning);
// Obtiene el valor de la variable
Uint8 getType();
// 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

158
source/text2.cpp Normal file
View File

@@ -0,0 +1,158 @@
#include "const.h"
#include "text2.h"
// Constructor
Text2::Text2()
{
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)
{
Text::init(texture, renderer, type, size);
mPosX = 0;
mPosY = 0;
mKerning = 0;
mCaption = "";
mWrittingSpeed = 0;
mWrittingTimer = 0;
mIndex = 0;
mLenght = 0;
mWrittingCompleted = false;
mEnabled = false;
mEnabledTimer = 0;
mId = -1;
mIntroEvents = nullptr;
}
// Establece el valor de la variable
void Text2::setPosX(int value)
{
mPosX = value;
}
// Establece el valor de la variable
void Text2::setPosY(int value)
{
mPosY = value;
}
// Establece el valor de la variable
void Text2::setKerning(int value)
{
mKerning = value;
}
// Establece el valor de la variable
void Text2::setCaption(std::string text)
{
mCaption = text;
mLenght = text.length();
}
// Establece el valor de la variable
void Text2::setWrittingSpeed(Uint16 value)
{
mWrittingSpeed = value;
mWrittingTimer = value;
}
// Establece el valor de la variable
void Text2::setEnabled(bool value)
{
mEnabled = value;
}
// Obtiene el valor de la variable
bool Text2::IsEnabled()
{
return mEnabled;
}
// Establece el valor de la variable
void Text2::setEnabledTimer(Uint16 value)
{
mEnabledTimer = value;
}
// Obtiene el valor de la variable
Uint16 Text2::getEnabledTimer()
{
return mEnabledTimer;
}
// Actualiza el objeto
void Text2::update()
{
if (mEnabled)
{
if (mWrittingCompleted == false)
{
if (mWrittingTimer > 0)
{
--mWrittingTimer;
}
if (mWrittingTimer == 0)
{
++mIndex;
mWrittingTimer = mWrittingSpeed;
}
if (mIndex == mLenght)
{
mWrittingCompleted = true;
}
}
if (mWrittingCompleted)
{
if (mEnabledTimer > 0)
{
--mEnabledTimer;
}
else if (mEnabledTimer == 0)
{
if (mId < 0)
{
mEnabled = false;
}
else
{
mIntroEvents[mId] = EVENT_COMPLETED;
}
}
}
}
}
// Dibuja el objeto en pantalla
void Text2::render()
{
if (mEnabled)
{
Text::write(mPosX, mPosY, mCaption, mKerning, mIndex);
}
}
// Centra la cadena de texto a un punto X
void Text2::center(int x)
{
setPosX(x - (lenght(mCaption, mKerning) / 2));
}
// Establece el valor de la variable
void Text2::setId(int id)
{
mId = id;
}
// Establece el valor de la variable
void Text2::setIntroEvents(Uint8 *value)
{
mIntroEvents = value;
}

102
source/text2.h Normal file
View File

@@ -0,0 +1,102 @@
#pragma once
#include "sprite.h"
#include "text.h"
#ifndef TEXT2_H
#define TEXT2_H
// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text2 : public Text
{
public:
// Constructor
Text2();
// Destructor
~Text2();
// Inicializador
void init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size);
// Establece el valor de la variable
void setPosX(int value);
// Establece el valor de la variable
void setPosY(int value);
// Establece el valor de la variable
void setKerning(int value);
// Establece el valor de la variable
void setCaption(std::string text);
// Establece el valor de la variable
void setWrittingSpeed(Uint16 value);
// Establece el valor de la variable
void setEnabled(bool value);
// Obtiene el valor de la variable
bool IsEnabled();
// Establece el valor de la variable
void setEnabledTimer(Uint16 value);
// Obtiene el valor de la variable
Uint16 getEnabledTimer();
// Actualiza el objeto
void update();
// Dibuja el objeto en pantalla
void render();
// Centra la cadena de texto a un punto X
void center(int x);
// Establece el valor de la variable
void setId(int id);
// Establece el valor de la variable
void setIntroEvents(Uint8 *value);
private:
// Posicion X/Y donde empezar a escribir el texto
int mPosX;
int mPosY;
// Kerning del texto
int mKerning;
// Texto para escribir
std::string mCaption;
// Velocidad de escritura
Uint16 mWrittingSpeed;
// Temporizador de escritura para cada caracter
Uint16 mWrittingTimer;
// Posición del texto que se está escribiendo
Uint16 mIndex;
// Longitud de la cadena a escribir
Uint16 mLenght;
// Indica si se ha escrito todo el texto
bool mWrittingCompleted;
// Indica si el objeto está habilitado
bool mEnabled;
// Temporizador para deshabilitar el objeto
Uint16 mEnabledTimer;
// Identificador
int mId;
// Dirección del array de eventos donde notificar el estado
Uint8 *mIntroEvents;
};
#endif

36
sync.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/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