Reestructurados los ficheros en carpetas
This commit is contained in:
31
source/background.cpp
Normal file
31
source/background.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "background.h"
|
||||
|
||||
//Constructor
|
||||
Background::Background()
|
||||
{
|
||||
init(0, 0, 0, 0, NULL);
|
||||
}
|
||||
|
||||
//Inicializador
|
||||
void Background::init(int x, int y, int w, int h, LTexture *texture)
|
||||
{
|
||||
//Establece el alto y el ancho del sprite del fondo
|
||||
mSprite.setWidth(w);
|
||||
mSprite.setHeight(h);
|
||||
|
||||
//Establece la posición X,Y del sprite del fondo
|
||||
mSprite.setPosX(x);
|
||||
mSprite.setPosY(y);
|
||||
|
||||
//Establece la textura donde están los gráficos para el sprite del fondo
|
||||
mSprite.setTexture(*texture);
|
||||
|
||||
//Establece el rectangulo de donde coger la imagen
|
||||
mSprite.setSpriteClip(0, 0, mSprite.getWidth(), mSprite.getHeight());
|
||||
}
|
||||
|
||||
//Pinta el fondo en la pantalla
|
||||
void Background::render()
|
||||
{
|
||||
mSprite.render();
|
||||
}
|
||||
26
source/background.h
Normal file
26
source/background.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "sprite.h"
|
||||
|
||||
#ifndef BACKGROUND_H
|
||||
#define BACKGROUND_H
|
||||
|
||||
//Clase para el fondo de pantalla del juego
|
||||
class Background
|
||||
{
|
||||
public:
|
||||
//Constructor
|
||||
Background();
|
||||
|
||||
//Inicializador
|
||||
void init(int x, int y, int w, int h, LTexture *texture);
|
||||
|
||||
//Pinta el fondo en la pantalla
|
||||
void render();
|
||||
|
||||
private:
|
||||
//Variables
|
||||
Sprite mSprite;
|
||||
};
|
||||
|
||||
#endif
|
||||
467
source/balloon.cpp
Normal file
467
source/balloon.cpp
Normal file
@@ -0,0 +1,467 @@
|
||||
#include "balloon.h"
|
||||
|
||||
//Constructor
|
||||
Balloon::Balloon()
|
||||
{
|
||||
init(0, 0, NO_KIND, BALLON_VELX_POSITIVE, 0);
|
||||
}
|
||||
|
||||
//Inicializador
|
||||
void Balloon::init(int x, int y, Uint8 kind, float velx, Uint16 creationtimer)
|
||||
{
|
||||
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.09;
|
||||
mDefaultVelY = 3;
|
||||
|
||||
//Puntos que da el globo al ser destruido
|
||||
mScore = 50;
|
||||
|
||||
//Rectangulo con la imagen del sprite
|
||||
mSprite.setSpriteClip(37 + 21 + 13, 0, mWidth, mHeight);
|
||||
|
||||
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.10;
|
||||
mDefaultVelY = 4;
|
||||
|
||||
//Puntos que da el globo al ser destruido
|
||||
mScore = 100;
|
||||
|
||||
//Rectangulo con la imagen del sprite
|
||||
mSprite.setSpriteClip(37 + 21, 0, mWidth, mHeight);
|
||||
|
||||
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.10;
|
||||
mDefaultVelY = 4.5;
|
||||
|
||||
//Puntos que da el globo al ser destruido
|
||||
mScore = 200;
|
||||
|
||||
//Rectangulo con la imagen del sprite
|
||||
mSprite.setSpriteClip(37, 0, mWidth, mHeight);
|
||||
|
||||
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.10;
|
||||
mDefaultVelY = 5;
|
||||
|
||||
//Puntos que da el globo al ser destruido
|
||||
mScore = 400;
|
||||
|
||||
//Rectangulo con la imagen del sprite
|
||||
mSprite.setSpriteClip(0, 0, mWidth, mHeight);
|
||||
|
||||
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;
|
||||
|
||||
//Rectangulo con la imagen del sprite
|
||||
mSprite.setSpriteClip(0, 0, mWidth, mHeight);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//Textura con los gráficos del sprite
|
||||
mSprite.setTexture(gBalloonTexture);
|
||||
|
||||
//Alto y ancho del sprite
|
||||
mSprite.setWidth(mWidth);
|
||||
mSprite.setHeight(mHeight);
|
||||
|
||||
//Posición X,Y del sprite
|
||||
mSprite.setPosX(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;
|
||||
|
||||
//Tipo
|
||||
mKind = kind;
|
||||
}
|
||||
|
||||
//Centra el globo en la posición X
|
||||
void Balloon::allignTo(int x)
|
||||
{
|
||||
mPosX = x - (mWidth / 2);
|
||||
|
||||
if (mPosX < PLAY_AREA_LEFT)
|
||||
{
|
||||
mPosX = PLAY_AREA_LEFT + 1;
|
||||
}
|
||||
else if ((mPosX + mWidth) > PLAY_AREA_RIGHT)
|
||||
{
|
||||
mPosX = 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 = mMaxVelY;
|
||||
}
|
||||
else
|
||||
{
|
||||
mVelY += mGravity;
|
||||
}
|
||||
|
||||
//Actualiza la posición del sprite
|
||||
mSprite.setPosX(getPosX());
|
||||
mSprite.setPosY(mPosY);
|
||||
|
||||
//Actualiza la posición del circulo de colisión
|
||||
shiftColliders();
|
||||
}
|
||||
//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);
|
||||
}
|
||||
|
||||
//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::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 = mPosX + mCollider.r;
|
||||
mCollider.y = mPosY + mCollider.r;
|
||||
}
|
||||
152
source/balloon.h
Normal file
152
source/balloon.h
Normal file
@@ -0,0 +1,152 @@
|
||||
#pragma once
|
||||
|
||||
#include "struct.h"
|
||||
#include "sprite.h"
|
||||
#include "const.h"
|
||||
#include "globals.h"
|
||||
|
||||
#ifndef BALLOON_H
|
||||
#define BALLOON_H
|
||||
|
||||
//Clase globo
|
||||
class Balloon
|
||||
{
|
||||
public:
|
||||
//Constructor
|
||||
Balloon();
|
||||
|
||||
//Inicializador
|
||||
void init(int x, int y, Uint8 kind, float velx, Uint16 creationtimer);
|
||||
|
||||
//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();
|
||||
|
||||
//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 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();
|
||||
|
||||
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;
|
||||
|
||||
//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;
|
||||
|
||||
//Temporizador para controlar el estado "creandose"
|
||||
Uint16 mCreationTimer;
|
||||
|
||||
//Tipo de globo
|
||||
Uint8 mKind;
|
||||
|
||||
//Sprite del objeto globo
|
||||
Sprite 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
|
||||
190
source/bullet.cpp
Normal file
190
source/bullet.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
#include "bullet.h"
|
||||
|
||||
//Constructor
|
||||
Bullet::Bullet()
|
||||
{
|
||||
init(0, 0, NO_KIND);
|
||||
}
|
||||
|
||||
//Iniciador
|
||||
void Bullet::init(int x, int y, int kind)
|
||||
{
|
||||
//Posición inicial del objeto
|
||||
mPosX = x;
|
||||
mPosY = y;
|
||||
|
||||
//Alto y ancho del objeto
|
||||
mWidth = 8;
|
||||
mHeight = mWidth;
|
||||
|
||||
//Velocidad inicial en el eje Y
|
||||
mVelY = -3;
|
||||
|
||||
//Tipo de bala
|
||||
mKind = kind;
|
||||
|
||||
//Textura con los gráficos del objeto
|
||||
mSprite.setTexture(gBulletTexture);
|
||||
|
||||
//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
|
||||
void Bullet::move()
|
||||
{
|
||||
//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;
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
//Actualiza la posición del sprite
|
||||
mSprite.setPosX(mPosX);
|
||||
mSprite.setPosY(mPosY);
|
||||
|
||||
//Alinea el circulo de colisión con el objeto
|
||||
shiftColliders();
|
||||
}
|
||||
|
||||
#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()
|
||||
{
|
||||
mKind = NO_KIND;
|
||||
}
|
||||
|
||||
//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
|
||||
float 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;
|
||||
}
|
||||
82
source/bullet.h
Normal file
82
source/bullet.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include "struct.h"
|
||||
#include "sprite.h"
|
||||
#include "const.h"
|
||||
#include "globals.h"
|
||||
|
||||
#ifndef BULLET_H
|
||||
#define BULLET_H
|
||||
|
||||
//Clase bala
|
||||
class Bullet
|
||||
{
|
||||
public:
|
||||
//Constructor
|
||||
Bullet();
|
||||
|
||||
//Iniciador
|
||||
void init(int x, int y, int kind);
|
||||
|
||||
//Pinta el objeto en pantalla
|
||||
void render();
|
||||
|
||||
//Actualiza la posición y estado del objeto
|
||||
void move();
|
||||
#ifdef TEST
|
||||
void testMove();
|
||||
#endif
|
||||
//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
|
||||
float 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
|
||||
111
source/const.h
Normal file
111
source/const.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#ifndef CONST_H
|
||||
#define CONST_H
|
||||
|
||||
//Tamaño de bloque
|
||||
const int BLOCK = 8;
|
||||
|
||||
//Tamaño de la pantalla real
|
||||
const int SCREEN_WIDTH = 256;
|
||||
const int SCREEN_HEIGHT = SCREEN_WIDTH * 3 / 4;
|
||||
|
||||
//Tamaño de la pantalla que se muestra
|
||||
const int VIEW_WIDTH = SCREEN_WIDTH * 3;
|
||||
const int VIEW_HEIGHT = SCREEN_HEIGHT * 3;
|
||||
|
||||
//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;
|
||||
|
||||
//Color transparente para los sprites
|
||||
const int COLOR_KEY_R = 0xff;
|
||||
const int COLOR_KEY_G = 0x00;
|
||||
const int 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 int PLAYER_STATE_STOPPED = 0;
|
||||
const int PLAYER_STATE_WALKING_LEFT = 1;
|
||||
const int PLAYER_STATE_WALKING_RIGHT = 2;
|
||||
const int PLAYER_STATE_TOTAL = 3;
|
||||
|
||||
//Estados del juego
|
||||
const int GAME_STATE_TITLE = 0;
|
||||
const int GAME_STATE_PLAYING = 1;
|
||||
const int GAME_STATE_PAUSED = 2;
|
||||
const int GAME_STATE_QUIT = 3;
|
||||
const int GAME_STATE_TOTAL = 4;
|
||||
|
||||
//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) + 4;
|
||||
const int SCORE_NUMBER_X = (SCREEN_WIDTH / 4) - (3 * BLOCK);
|
||||
const int SCORE_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 4;
|
||||
const int HISCORE_WORD_X = ((SCREEN_WIDTH / 4) * 3) - ((8 * BLOCK) / 2);
|
||||
const int HISCORE_WORD_Y = SCREEN_HEIGHT - (3 * BLOCK) + 4;
|
||||
const int HISCORE_NUMBER_X = ((SCREEN_WIDTH / 4) * 3) - (3 * BLOCK);
|
||||
const int HISCORE_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 4;
|
||||
|
||||
//Ningun tipo
|
||||
const int NO_KIND = 0;
|
||||
|
||||
//Tipos de globo
|
||||
const int BALLOON_1 = 1;
|
||||
const int BALLOON_2 = 2;
|
||||
const int BALLOON_3 = 3;
|
||||
const int BALLOON_4 = 4;
|
||||
|
||||
//Velocidad del globo
|
||||
const float BALLON_VELX_POSITIVE = 0.7;
|
||||
const float BALLON_VELX_NEGATIVE = -0.7;
|
||||
|
||||
//Tipos de bala
|
||||
const int BULLET_UP = 1;
|
||||
const int BULLET_LEFT = 2;
|
||||
const int BULLET_RIGHT = 3;
|
||||
|
||||
//Estados de entrada
|
||||
const int NO_INPUT = 0;
|
||||
const int INPUT_UP = 1;
|
||||
const int INPUT_DOWN = 2;
|
||||
const int INPUT_LEFT = 3;
|
||||
const int INPUT_RIGHT = 4;
|
||||
const int INPUT_FIRE = 5;
|
||||
|
||||
//Zona muerta del mando analógico
|
||||
const int JOYSTICK_DEAD_ZONE = 8000;
|
||||
|
||||
//Mapeo de bottones (8bitdo)
|
||||
const int BUTTON_A = 0;
|
||||
const int BUTTON_B = 1;
|
||||
const int BUTTON_X = 3;
|
||||
const int BUTTON_Y = 4;
|
||||
const int BUTTON_SELECT = 10;
|
||||
const int BUTTON_START = 11;
|
||||
const int BUTTON_L = 6;
|
||||
const int BUTTON_R = 7;
|
||||
|
||||
//Estado del teclado SDL
|
||||
//const Uint8 *keystates;
|
||||
|
||||
#endif
|
||||
970
source/gamedirector.cpp
Normal file
970
source/gamedirector.cpp
Normal file
@@ -0,0 +1,970 @@
|
||||
#include "gamedirector.h"
|
||||
|
||||
//Calcula el cuadrado de la distancia entre dos puntos
|
||||
double distanceSquared(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
int deltaX = x2 - x1;
|
||||
int deltaY = y2 - y1;
|
||||
return deltaX * deltaX + deltaY * deltaY;
|
||||
}
|
||||
|
||||
//Detector de colisiones entre dos circulos
|
||||
bool checkCollision(Circle &a, Circle &b)
|
||||
{
|
||||
//Calcula el radio total al cuadrado
|
||||
int totalRadiusSquared = a.r + b.r;
|
||||
totalRadiusSquared = totalRadiusSquared * totalRadiusSquared;
|
||||
|
||||
//Si la distancia entre el centro de los circulos es inferior a la suma de sus radios
|
||||
if (distanceSquared(a.x, a.y, b.x, b.y) < (totalRadiusSquared))
|
||||
{
|
||||
//Los circulos han colisionado
|
||||
return true;
|
||||
}
|
||||
|
||||
//En caso contrario
|
||||
return false;
|
||||
}
|
||||
|
||||
//Constructor
|
||||
GameDirector::GameDirector()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
//Iniciador
|
||||
void GameDirector::init()
|
||||
{
|
||||
//Variables
|
||||
mGameStatus = GAME_STATE_TITLE;
|
||||
mOldTicks = 0;
|
||||
mMaxBalloons = 50;
|
||||
mMaxBullets = 50;
|
||||
mGameSpeed = 15;
|
||||
mMenaceLevel = 0;
|
||||
mMenaceLevelThreshold = 7;
|
||||
mScore = 0;
|
||||
mHiScore = 0;
|
||||
mScoreText = std::to_string(mScore);
|
||||
mHiScoreText = std::to_string(mHiScore);
|
||||
mGetReady = true;
|
||||
|
||||
//Objeto jugador
|
||||
player.init();
|
||||
|
||||
//Establece a cero todos los valores del vector de objetos globo
|
||||
resetBalloons();
|
||||
|
||||
//Crea dos objetos globo y los centra en el area de juego
|
||||
//balloon[0].init(0, BLOCK, BALLOON_4, BALLON_VELX_POSITIVE, 0);
|
||||
//balloon[0].allignTo(PLAY_AREA_WIDTH / 2);
|
||||
//balloon[1].init(0, BLOCK, BALLOON_4, BALLON_VELX_NEGATIVE, 0);
|
||||
//balloon[1].allignTo(PLAY_AREA_WIDTH / 2);
|
||||
|
||||
//Con los globos creados, calcula el nivel de amenaza
|
||||
calculateMenaceLevel();
|
||||
|
||||
//Establece a cero todos los valores del vector de objetos bala
|
||||
resetBullets();
|
||||
|
||||
#ifdef TEST
|
||||
balloonTest.init(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, BALLOON_4, 0);
|
||||
balloonTest.stop();
|
||||
bulletTest.init(SCREEN_WIDTH / 4, SCREEN_HEIGHT / 2, BULLET_UP);
|
||||
#endif
|
||||
|
||||
//Los fondos
|
||||
gameBackground.init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT - (0 * BLOCK), &gGameBackgroundTexture);
|
||||
titleBackground.init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, &gTitleBackgroundTexture);
|
||||
|
||||
//Objetos texto, uno de cada color
|
||||
whiteText.init(&gWhiteFontTexture);
|
||||
blackText.init(&gBlackFontTexture);
|
||||
|
||||
//Inicializa el objeto con el menu del titulo
|
||||
menuTitle.init(0, 16 * BLOCK, MENU_SELECTOR_WHITE, MENU_BACKGROUND_TRANSPARENT);
|
||||
menuTitle.addItem("START");
|
||||
menuTitle.addItem("EXIT");
|
||||
menuTitle.setBackgroundColor(0, 0, 0, 255);
|
||||
menuTitle.centerMenuOnScreen();
|
||||
|
||||
//Inicializa el objeto con el menu de pausa
|
||||
menuPause.init(0, 12 * BLOCK, MENU_SELECTOR_WHITE, MENU_BACKGROUND_SOLID);
|
||||
menuPause.addItem("CONTINUE");
|
||||
menuPause.addItem("EXIT TO TITLE");
|
||||
menuPause.setBackgroundColor(0x73, 0x27, 0x5c, 255);
|
||||
menuPause.centerMenuOnScreen();
|
||||
}
|
||||
|
||||
//Hace una pausa de milisegundos
|
||||
void GameDirector::sleep(Uint16 time)
|
||||
{
|
||||
Uint32 ticks = SDL_GetTicks();
|
||||
while (SDL_GetTicks() - ticks < time)
|
||||
{
|
||||
/* code */
|
||||
}
|
||||
}
|
||||
|
||||
//Establece el valor de la variable
|
||||
void GameDirector::setScore(Uint32 score)
|
||||
{
|
||||
mScore = score;
|
||||
}
|
||||
|
||||
//Establece el valor de la variable
|
||||
void GameDirector::setHiScore(Uint32 score)
|
||||
{
|
||||
mHiScore = score;
|
||||
}
|
||||
|
||||
//Actualiza el valor de HiScore en caso necesario
|
||||
void GameDirector::updateHiScore()
|
||||
{
|
||||
if (mScore > mHiScore)
|
||||
{
|
||||
mHiScore = mScore;
|
||||
}
|
||||
}
|
||||
|
||||
//Transforma un valor numérico en una cadena de 6 cifras
|
||||
std::string GameDirector::updateScoreText(Uint32 num)
|
||||
{
|
||||
switch (num)
|
||||
{
|
||||
case 0 ... 9:
|
||||
return ("00000" + std::to_string(num));
|
||||
break;
|
||||
|
||||
case 10 ... 99:
|
||||
return ("0000" + std::to_string(num));
|
||||
break;
|
||||
|
||||
case 100 ... 999:
|
||||
return ("000" + std::to_string(num));
|
||||
break;
|
||||
|
||||
case 1000 ... 9999:
|
||||
return ("00" + std::to_string(num));
|
||||
break;
|
||||
|
||||
case 10000 ... 99999:
|
||||
return ("0" + std::to_string(num));
|
||||
break;
|
||||
|
||||
case 100000 ... 999999:
|
||||
return (std::to_string(num));
|
||||
break;
|
||||
default:
|
||||
return (std::to_string(num));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Pinta el marcador en pantalla usando un objeto texto
|
||||
void GameDirector::renderScoreBoard(Text &text)
|
||||
{
|
||||
mScoreText = updateScoreText(mScore);
|
||||
mHiScoreText = updateScoreText(mHiScore);
|
||||
text.write(SCORE_WORD_X, SCORE_WORD_Y, "SCORE");
|
||||
text.write(SCORE_NUMBER_X, SCORE_NUMBER_Y, mScoreText);
|
||||
text.write(HISCORE_WORD_X, HISCORE_WORD_Y, "HI-SCORE");
|
||||
text.write(HISCORE_NUMBER_X, HISCORE_NUMBER_Y, mHiScoreText);
|
||||
}
|
||||
|
||||
//Mueve todos los globos activos
|
||||
void GameDirector::moveBalloons()
|
||||
{
|
||||
for (Uint8 i = 0; i < mMaxBalloons; i++)
|
||||
{
|
||||
if (balloon[i].isActive())
|
||||
{
|
||||
balloon[i].move();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Pinta en pantalla todos los globos activos
|
||||
void GameDirector::renderBalloons()
|
||||
{
|
||||
for (Uint8 i = 0; i < mMaxBalloons; i++)
|
||||
{
|
||||
if (balloon[i].isActive())
|
||||
{
|
||||
balloon[i].render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Devuelve el primer indice no activo del vector de globos
|
||||
Uint8 GameDirector::getBallonFreeIndex()
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
for (Uint8 i = 0; i < mMaxBalloons; i++)
|
||||
{
|
||||
if (balloon[i].isActive() == false)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
//Crea un globo nuevo en el vector de globos
|
||||
Uint8 GameDirector::createNewBalloon(int x, int y, Uint8 kind, float velx, Uint16 creationtimer)
|
||||
{
|
||||
Uint8 index = getBallonFreeIndex();
|
||||
balloon[index].init(x, y, kind, velx, creationtimer);
|
||||
return index;
|
||||
}
|
||||
|
||||
//Establece a cero todos los valores del vector de objetos globo
|
||||
void GameDirector::resetBalloons()
|
||||
{
|
||||
for (Uint8 i = 0; i < mMaxBalloons; i++)
|
||||
{
|
||||
balloon[i].erase();
|
||||
}
|
||||
}
|
||||
|
||||
//Explosiona un globo. Lo destruye y crea otros dos si es el caso
|
||||
void GameDirector::popBalloon(Uint8 index)
|
||||
{
|
||||
if (balloon[index].isActive())
|
||||
{
|
||||
Uint8 kind = balloon[index].getKind();
|
||||
Uint8 freeIndex = 0;
|
||||
switch (kind)
|
||||
{
|
||||
//Si es del tipo más pequeño, simplemente elimina el globo
|
||||
case BALLOON_1:
|
||||
balloon[index].erase();
|
||||
break;
|
||||
|
||||
//En cualquier otro caso, crea dos globos de un tipo inferior
|
||||
default:
|
||||
freeIndex = getBallonFreeIndex();
|
||||
balloon[freeIndex].init(0, balloon[index].getPosY(), balloon[index].getKind() - 1, BALLON_VELX_NEGATIVE, 0);
|
||||
balloon[freeIndex].allignTo(balloon[index].getPosX() + (balloon[index].getWidth() / 2));
|
||||
balloon[freeIndex].setVelY(-2.5);
|
||||
|
||||
freeIndex = getBallonFreeIndex();
|
||||
balloon[freeIndex].init(0, balloon[index].getPosY(), balloon[index].getKind() - 1, BALLON_VELX_POSITIVE, 0);
|
||||
balloon[freeIndex].allignTo(balloon[index].getPosX() + (balloon[index].getWidth() / 2));
|
||||
balloon[freeIndex].setVelY(-2.5);
|
||||
|
||||
//Elimina el globo
|
||||
balloon[index].erase();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Detiene todos los globos
|
||||
void GameDirector::stopAllBalloons()
|
||||
{
|
||||
for (Uint8 i = 0; i < mMaxBalloons; i++)
|
||||
{
|
||||
if (balloon[i].isActive())
|
||||
{
|
||||
balloon[i].setStop(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Pone en marcha todos los globos
|
||||
void GameDirector::startAllBalloons()
|
||||
{
|
||||
for (Uint8 i = 0; i < mMaxBalloons; i++)
|
||||
{
|
||||
if (balloon[i].isActive())
|
||||
{
|
||||
balloon[i].setStop(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Obtiene el numero de globos activos
|
||||
Uint8 GameDirector::countBalloons()
|
||||
{
|
||||
Uint8 num = 0;
|
||||
for (Uint8 i = 0; i < mMaxBalloons; i++)
|
||||
{
|
||||
if (balloon[i].isActive())
|
||||
{
|
||||
++num;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
//Comprueba la colisión entre el jugador y los globos activos
|
||||
bool GameDirector::checkPlayerBallonCollision()
|
||||
{
|
||||
bool result = false;
|
||||
for (Uint8 i = 0; i < mMaxBalloons; i++)
|
||||
{
|
||||
if (balloon[i].isActive())
|
||||
{
|
||||
if (checkCollision(player.getCollider(), balloon[i].getCollider()))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//Comprueba y procesa la colisión entre las balas y los globos
|
||||
void GameDirector::processBulletBallonCollision()
|
||||
{
|
||||
for (Uint8 i = 0; i < mMaxBalloons; i++)
|
||||
{
|
||||
for (Uint8 j = 0; j < mMaxBullets; j++)
|
||||
{
|
||||
if (balloon[i].isActive() && !(balloon[i].isInvulnerable()) && bullet[j].isActive())
|
||||
{
|
||||
if (checkCollision(balloon[i].getCollider(), bullet[j].getCollider()))
|
||||
{
|
||||
player.addScore(balloon[i].getScore());
|
||||
setScore(player.getScore());
|
||||
updateHiScore();
|
||||
popBalloon(i);
|
||||
Mix_PlayChannel(-1, gPopBalloonFX, 0);
|
||||
bullet[j].erase();
|
||||
calculateMenaceLevel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Mueve las balas activas
|
||||
void GameDirector::moveBullets()
|
||||
{
|
||||
for (Uint8 i = 0; i < mMaxBullets; i++)
|
||||
{
|
||||
if (bullet[i].isActive())
|
||||
{
|
||||
bullet[i].move();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Pinta las balas activas
|
||||
void GameDirector::renderBullets()
|
||||
{
|
||||
for (Uint8 i = 0; i < mMaxBullets; i++)
|
||||
{
|
||||
if (bullet[i].isActive())
|
||||
{
|
||||
bullet[i].render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Devuelve el primer indice no activo del vector de balas
|
||||
Uint8 GameDirector::getBulletFreeIndex()
|
||||
{
|
||||
Uint8 index = 0;
|
||||
|
||||
for (int i = 0; i < mMaxBullets; i++)
|
||||
{
|
||||
if (bullet[i].isActive() == false)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
//Establece a cero todos los valores del vector de objetos bala
|
||||
void GameDirector::resetBullets()
|
||||
{
|
||||
for (Uint8 i = 0; i < mMaxBullets; i++)
|
||||
{
|
||||
bullet[i].init(0, 0, NO_KIND);
|
||||
}
|
||||
}
|
||||
|
||||
//Crea un objeto bala
|
||||
void GameDirector::createBullet(int x, int y, Uint8 kind)
|
||||
{
|
||||
bullet[getBulletFreeIndex()].init(x, y, kind);
|
||||
}
|
||||
|
||||
//Calcula y establece el valor de amenaza en funcion de los globos activos
|
||||
void GameDirector::calculateMenaceLevel()
|
||||
{
|
||||
mMenaceLevel = 0;
|
||||
for (Uint8 i = 0; i < mMaxBalloons; i++)
|
||||
{
|
||||
switch (balloon[i].getKind())
|
||||
{
|
||||
case BALLOON_1:
|
||||
mMenaceLevel += 1;
|
||||
break;
|
||||
|
||||
case BALLOON_2:
|
||||
mMenaceLevel += 2;
|
||||
break;
|
||||
|
||||
case BALLOON_3:
|
||||
mMenaceLevel += 4;
|
||||
break;
|
||||
|
||||
case BALLOON_4:
|
||||
mMenaceLevel += 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
mMenaceLevel += 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Obtiene el valor de la variable
|
||||
Uint8 GameDirector::getMenaceLevel()
|
||||
{
|
||||
return mMenaceLevel;
|
||||
}
|
||||
|
||||
//Gestiona el nivel de amenaza
|
||||
void GameDirector::checkMenaceLevel()
|
||||
{
|
||||
//Aumenta el nivel de amenaza en función de la puntuación
|
||||
mMenaceLevelThreshold = 7 + (4 * (mScore / 10000));
|
||||
|
||||
//Si el nivel de amenza es inferior al umbral
|
||||
if (mMenaceLevel < mMenaceLevelThreshold)
|
||||
{
|
||||
Uint8 index = 0;
|
||||
|
||||
//Obtiene el centro del jugador en el eje X
|
||||
int x = player.getPosX() + (player.getWidth() / 2);
|
||||
|
||||
//Crea un globo sobre el jugador en dirección hacia el centro
|
||||
if (x < (PLAY_AREA_WIDTH / 2))
|
||||
{
|
||||
index = createNewBalloon(0, PLAY_AREA_TOP + BLOCK - 37, BALLOON_4, BALLON_VELX_POSITIVE, 400);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = createNewBalloon(0, PLAY_AREA_TOP + BLOCK - 37, BALLOON_4, BALLON_VELX_NEGATIVE, 400);
|
||||
}
|
||||
balloon[index].allignTo(x);
|
||||
|
||||
//Recalcula el nivel de amenaza con el nuevo globo
|
||||
calculateMenaceLevel();
|
||||
}
|
||||
}
|
||||
|
||||
//Gestiona la entrada de teclado y mando durante el juego
|
||||
void GameDirector::checkGameInput()
|
||||
{
|
||||
//Obtiene el estado de las teclas pulsadas del teclado
|
||||
const Uint8 *keystates = SDL_GetKeyboardState(NULL);
|
||||
|
||||
//Si está pulsada la tecla izquierda o el mando hacia la izquierda
|
||||
if ((keystates[SDL_SCANCODE_LEFT] != 0) || (SDL_JoystickGetAxis(gGameController, 0) < -JOYSTICK_DEAD_ZONE))
|
||||
{
|
||||
player.checkInput(INPUT_LEFT);
|
||||
}
|
||||
//Si está pulsada la tecla derecha o el mando hacia la derecha
|
||||
else if ((keystates[SDL_SCANCODE_RIGHT] != 0) || (SDL_JoystickGetAxis(gGameController, 0) > JOYSTICK_DEAD_ZONE))
|
||||
{
|
||||
player.checkInput(INPUT_RIGHT);
|
||||
}
|
||||
//Ninguna de las dos direcciones pulsadas
|
||||
else
|
||||
{
|
||||
player.checkInput(NO_INPUT);
|
||||
}
|
||||
|
||||
//Comprobamos la tecla o el botón de disparo central
|
||||
if ((SDL_JoystickGetButton(gGameController, BUTTON_X)) || (keystates[SDL_SCANCODE_W] != 0))
|
||||
{
|
||||
if (player.canFire())
|
||||
{
|
||||
createBullet(player.getPosX() + (player.getWidth() / 2) - 4, player.getPosY(), BULLET_UP);
|
||||
player.setFireCooldown(10);
|
||||
|
||||
//Reproduce el sonido de disparo
|
||||
Mix_PlayChannel(-1, gBulletFX, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//Comprobamos la tecla o el botón de disparo izquierdo
|
||||
if ((SDL_JoystickGetButton(gGameController, BUTTON_Y)) || (keystates[SDL_SCANCODE_Q] != 0))
|
||||
{
|
||||
if (player.canFire())
|
||||
{
|
||||
createBullet(player.getPosX() + (player.getWidth() / 2) - 4, player.getPosY(), BULLET_LEFT);
|
||||
player.setFireCooldown(10);
|
||||
|
||||
//Reproduce el sonido de disparo
|
||||
Mix_PlayChannel(-1, gBulletFX, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//Comprobamos la tecla o el botón de disparo derecho
|
||||
if ((SDL_JoystickGetButton(gGameController, BUTTON_A)) || (keystates[SDL_SCANCODE_E] != 0))
|
||||
{
|
||||
if (player.canFire())
|
||||
{
|
||||
createBullet(player.getPosX() + (player.getWidth() / 2) - 4, player.getPosY(), BULLET_RIGHT);
|
||||
player.setFireCooldown(10);
|
||||
|
||||
//Reproduce el sonido de disparo
|
||||
Mix_PlayChannel(-1, gBulletFX, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//Comprobamos la tecla o el botón de pausa/menu
|
||||
if ((SDL_JoystickGetButton(gGameController, BUTTON_START)) || (keystates[SDL_SCANCODE_ESCAPE] != 0))
|
||||
{
|
||||
setGameStatus(GAME_STATE_PAUSED);
|
||||
|
||||
//Detiene la música
|
||||
Mix_HaltMusic();
|
||||
}
|
||||
}
|
||||
|
||||
//Gestiona la entrada de teclado y mando durante el menu
|
||||
void GameDirector::checkMenuInput(Menu *menu)
|
||||
{
|
||||
//Obtiene el estado de las teclas pulsadas del teclado
|
||||
const Uint8 *keystates = SDL_GetKeyboardState(NULL);
|
||||
|
||||
//Si está pulsada la tecla izquierda o el mando hacia la izquierda
|
||||
if ((keystates[SDL_SCANCODE_UP] != 0) || (SDL_JoystickGetAxis(gGameController, 1) < -JOYSTICK_DEAD_ZONE))
|
||||
{
|
||||
menu->checkInput(INPUT_UP);
|
||||
}
|
||||
//Si está pulsada la tecla derecha o el mando hacia la derecha
|
||||
else if ((keystates[SDL_SCANCODE_DOWN] != 0) || (SDL_JoystickGetAxis(gGameController, 1) > JOYSTICK_DEAD_ZONE))
|
||||
{
|
||||
menu->checkInput(INPUT_DOWN);
|
||||
}
|
||||
//Comprobamos la tecla o el botón de menu/pausa
|
||||
else if (keystates[SDL_SCANCODE_RETURN] != 0 || (SDL_JoystickGetButton(gGameController, BUTTON_A)))
|
||||
{
|
||||
menu->checkInput(INPUT_FIRE);
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
if (SDL_JoystickGetButton(gGameController, 1))
|
||||
{
|
||||
std::cout << "button1\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 1))
|
||||
{
|
||||
std::cout << "button1\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 2))
|
||||
{
|
||||
std::cout << "button2\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 3))
|
||||
{
|
||||
std::cout << "button3\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 4))
|
||||
{
|
||||
std::cout << "button4\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 5))
|
||||
{
|
||||
std::cout << "button5\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 6))
|
||||
{
|
||||
std::cout << "button6\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 7))
|
||||
{
|
||||
std::cout << "button7\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 8))
|
||||
{
|
||||
std::cout << "button8\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 9))
|
||||
{
|
||||
std::cout << "button9\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 10))
|
||||
{
|
||||
std::cout << "button10\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 11))
|
||||
{
|
||||
std::cout << "button11\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 12))
|
||||
{
|
||||
std::cout << "button12\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 13))
|
||||
{
|
||||
std::cout << "button13\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 14))
|
||||
{
|
||||
std::cout << "button14\n";
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, 15))
|
||||
{
|
||||
std::cout << "button15\n";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//Obtiene el valor de la variable
|
||||
Uint8 GameDirector::getGameStatus()
|
||||
{
|
||||
return mGameStatus;
|
||||
}
|
||||
|
||||
//Establece el valor de la variable
|
||||
void GameDirector::setGameStatus(Uint8 status)
|
||||
{
|
||||
mGameStatus = status;
|
||||
}
|
||||
|
||||
//Pinta una transición en pantalla
|
||||
void GameDirector::renderTransition(Uint8 index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
SDL_Rect rect;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.w = SCREEN_WIDTH;
|
||||
rect.h = 0;
|
||||
|
||||
SDL_RenderPresent(gRenderer);
|
||||
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 0);
|
||||
|
||||
for (Uint16 i = 0; i < SCREEN_HEIGHT; i = i + 2)
|
||||
{
|
||||
rect.h = i;
|
||||
SDL_RenderFillRect(gRenderer, &rect);
|
||||
SDL_RenderPresent(gRenderer);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
SDL_Rect rect1;
|
||||
rect1.x = 0;
|
||||
rect1.y = 0;
|
||||
rect1.w = SCREEN_WIDTH;
|
||||
rect1.h = 0;
|
||||
|
||||
SDL_Rect rect2;
|
||||
rect2.x = 0;
|
||||
rect2.y = 0;
|
||||
rect2.w = SCREEN_WIDTH;
|
||||
rect2.h = 0;
|
||||
|
||||
SDL_RenderPresent(gRenderer);
|
||||
SDL_SetRenderDrawBlendMode(gRenderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 64);
|
||||
|
||||
for (Uint16 i = 0; i < (SCREEN_HEIGHT / 2); i = i + 4)
|
||||
{
|
||||
rect1.h = i;
|
||||
SDL_RenderFillRect(gRenderer, &rect1);
|
||||
|
||||
rect2.h = i;
|
||||
rect2.y = SCREEN_HEIGHT - (i);
|
||||
SDL_RenderFillRect(gRenderer, &rect2);
|
||||
|
||||
SDL_RenderPresent(gRenderer);
|
||||
}
|
||||
|
||||
rect1.x = 0;
|
||||
rect1.y = 0;
|
||||
rect1.w = SCREEN_WIDTH;
|
||||
rect1.h = SCREEN_HEIGHT;
|
||||
|
||||
for (Uint16 i = 0; i < (SCREEN_HEIGHT / 2); i = i + 4)
|
||||
{
|
||||
SDL_RenderFillRect(gRenderer, &rect1);
|
||||
SDL_RenderPresent(gRenderer);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Pinta el texto GetReady en pantalla
|
||||
void GameDirector::renderGetReady()
|
||||
{
|
||||
if (mGetReady)
|
||||
{
|
||||
Sprite sprite;
|
||||
sprite.setTexture(gMiscTexture);
|
||||
sprite.setWidth(53);
|
||||
sprite.setHeight(10);
|
||||
sprite.setPosX((PLAY_AREA_WIDTH / 2) - (sprite.getWidth() / 2));
|
||||
sprite.setPosY((PLAY_AREA_HEIGHT / 2) - (sprite.getHeight() / 2));
|
||||
sprite.setSpriteClip(0, 0, sprite.getWidth(), sprite.getHeight());
|
||||
for (Uint8 i = 0; i < 1; i++)
|
||||
{
|
||||
sprite.render();
|
||||
SDL_RenderPresent(gRenderer);
|
||||
SDL_Delay(1500);
|
||||
}
|
||||
mGetReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
//Bucle para el titulo del juego
|
||||
void GameDirector::runTitle()
|
||||
{
|
||||
//Si la música no está sonando
|
||||
if (Mix_PlayingMusic() == 0)
|
||||
{
|
||||
//Reproduce la música
|
||||
Mix_PlayMusic(gTitleMusic, -1);
|
||||
}
|
||||
|
||||
//Comprueba los eventos que hay en la cola
|
||||
while (SDL_PollEvent(&eventHandler) != 0)
|
||||
{
|
||||
//Evento de salida de la aplicación
|
||||
if (eventHandler.type == SDL_QUIT)
|
||||
{
|
||||
setGameStatus(GAME_STATE_QUIT);
|
||||
}
|
||||
}
|
||||
|
||||
//Limpia la pantalla
|
||||
SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0x00, 0xFF);
|
||||
SDL_RenderClear(gRenderer);
|
||||
|
||||
//Dibuja los objetos
|
||||
titleBackground.render();
|
||||
menuTitle.render(whiteText);
|
||||
|
||||
//Actualiza la pantalla
|
||||
SDL_RenderPresent(gRenderer);
|
||||
|
||||
//Comprueba las entradas para el menu
|
||||
checkMenuInput(&menuTitle);
|
||||
|
||||
//Comprueba si se ha seleccionado algún item del menú
|
||||
switch (menuTitle.getItemSelected())
|
||||
{
|
||||
case 0:
|
||||
setGameStatus(GAME_STATE_PLAYING);
|
||||
menuTitle.resetMenu();
|
||||
renderTransition(1);
|
||||
Mix_HaltMusic();
|
||||
SDL_Delay(1200);
|
||||
break;
|
||||
case 1:
|
||||
setGameStatus(GAME_STATE_QUIT);
|
||||
menuTitle.resetMenu();
|
||||
renderTransition(1);
|
||||
Mix_HaltMusic();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Bucle para el juego
|
||||
void GameDirector::runGame()
|
||||
{
|
||||
//Si la música no está sonando
|
||||
if (Mix_PlayingMusic() == 0)
|
||||
{
|
||||
//Reproduce la música
|
||||
Mix_PlayMusic(gPlayingMusic, -1);
|
||||
}
|
||||
|
||||
//Lógica del juego
|
||||
//Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
||||
if (SDL_GetTicks() - mOldTicks > mGameSpeed)
|
||||
{
|
||||
//Actualiza el contador de ticks
|
||||
mOldTicks = SDL_GetTicks();
|
||||
|
||||
//Comprueba el teclado/mando
|
||||
checkGameInput();
|
||||
|
||||
//Comprueba los eventos que hay en la cola
|
||||
while (SDL_PollEvent(&eventHandler) != 0)
|
||||
{
|
||||
//Evento de salida de la aplicación
|
||||
if (eventHandler.type == SDL_QUIT)
|
||||
{
|
||||
setGameStatus(GAME_STATE_QUIT);
|
||||
}
|
||||
|
||||
//Tecla T pulsada
|
||||
if (eventHandler.key.keysym.sym == SDLK_t)
|
||||
{
|
||||
//startAllBalloons();
|
||||
popBalloon(0);
|
||||
break;
|
||||
}
|
||||
#ifdef TEST
|
||||
//W key pressed
|
||||
if (eventHandler.key.keysym.sym == SDLK_w)
|
||||
{
|
||||
bulletTest.setPosY(bulletTest.getPosY() - 1);
|
||||
bulletTest.testMove();
|
||||
break;
|
||||
}
|
||||
|
||||
//S key pressed
|
||||
if (eventHandler.key.keysym.sym == SDLK_s)
|
||||
{
|
||||
bulletTest.setPosY(bulletTest.getPosY() + 1);
|
||||
bulletTest.testMove();
|
||||
break;
|
||||
}
|
||||
|
||||
//A key pressed
|
||||
if (eventHandler.key.keysym.sym == SDLK_a)
|
||||
{
|
||||
bulletTest.setPosX(bulletTest.getPosX() - 1);
|
||||
bulletTest.testMove();
|
||||
break;
|
||||
}
|
||||
|
||||
//D key pressed
|
||||
if (eventHandler.key.keysym.sym == SDLK_d)
|
||||
{
|
||||
bulletTest.setPosX(bulletTest.getPosX() + 1);
|
||||
bulletTest.testMove();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//Actualiza el jugador
|
||||
player.update();
|
||||
|
||||
//Mueve los globos
|
||||
moveBalloons();
|
||||
|
||||
#ifdef TEST
|
||||
balloonTest.move();
|
||||
#endif
|
||||
|
||||
//Mueve las balas
|
||||
moveBullets();
|
||||
|
||||
//Procesa las colisiones entre globos y balas
|
||||
processBulletBallonCollision();
|
||||
|
||||
//Comprueba el nivel de amenaza
|
||||
checkMenaceLevel();
|
||||
|
||||
//Comprueba la colisión entre el jugador y los globos
|
||||
if (checkPlayerBallonCollision())
|
||||
{
|
||||
//stopAllBalloons();
|
||||
}
|
||||
}
|
||||
|
||||
//Limpia la pantalla
|
||||
SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0x00, 0xFF);
|
||||
SDL_RenderClear(gRenderer);
|
||||
|
||||
//Dibuja los objetos
|
||||
gameBackground.render();
|
||||
renderBalloons();
|
||||
#ifdef TEST
|
||||
balloonTest.render();
|
||||
bulletTest.render();
|
||||
if (checkCollision(balloonTest.getCollider(), bulletTest.getCollider()))
|
||||
{
|
||||
whiteText.write(0, 0, "X");
|
||||
}
|
||||
#endif
|
||||
//whiteText.write(0, 0, std::to_string(mMenaceLevelThreshold));
|
||||
//whiteText.write(0, BLOCK, std::to_string(player.getPosX() + player.getWidth()));
|
||||
renderBullets();
|
||||
player.render();
|
||||
renderScoreBoard(whiteText);
|
||||
renderGetReady();
|
||||
|
||||
//Actualiza la pantalla
|
||||
SDL_RenderPresent(gRenderer);
|
||||
}
|
||||
|
||||
//Bucle para el menu de pausa del juego
|
||||
void GameDirector::runPausedGame()
|
||||
{
|
||||
//Comprueba los eventos que hay en la cola
|
||||
while (SDL_PollEvent(&eventHandler) != 0)
|
||||
{
|
||||
//Evento de salida de la aplicación
|
||||
if (eventHandler.type == SDL_QUIT)
|
||||
{
|
||||
setGameStatus(GAME_STATE_QUIT);
|
||||
}
|
||||
}
|
||||
|
||||
//Dibuja los objetos
|
||||
gameBackground.render();
|
||||
renderBalloons();
|
||||
renderBullets();
|
||||
player.render();
|
||||
renderScoreBoard(whiteText);
|
||||
menuPause.render(whiteText);
|
||||
|
||||
//Limpia la pantalla
|
||||
SDL_RenderPresent(gRenderer);
|
||||
|
||||
//Comprueba las entradas para el menu
|
||||
checkMenuInput(&menuPause);
|
||||
|
||||
//Comprueba si se ha seleccionado algún item del menú
|
||||
switch (menuPause.getItemSelected())
|
||||
{
|
||||
case 0:
|
||||
setGameStatus(GAME_STATE_PLAYING);
|
||||
menuPause.resetMenu();
|
||||
break;
|
||||
case 1:
|
||||
setGameStatus(GAME_STATE_TITLE);
|
||||
menuPause.resetMenu();
|
||||
renderTransition(1);
|
||||
init();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
196
source/gamedirector.h
Normal file
196
source/gamedirector.h
Normal file
@@ -0,0 +1,196 @@
|
||||
#pragma once
|
||||
|
||||
#include "background.h"
|
||||
#include "balloon.h"
|
||||
#include "bullet.h"
|
||||
#include "const.h"
|
||||
#include "globals.h"
|
||||
#include "ltexture.h"
|
||||
#include "menu.h"
|
||||
#include "player.h"
|
||||
#include "struct.h"
|
||||
#include "text.h"
|
||||
|
||||
#ifndef GAMEDIRECTOR_H
|
||||
#define GAMEDIRECTOR_H
|
||||
|
||||
//GameDirector
|
||||
class GameDirector
|
||||
{
|
||||
public:
|
||||
//Constructor
|
||||
GameDirector();
|
||||
|
||||
//Iniciador
|
||||
void init();
|
||||
|
||||
//Hace una pausa de milisegundos
|
||||
void sleep(Uint16 time);
|
||||
|
||||
//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(Text &text);
|
||||
|
||||
//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(int x, int y, Uint8 kind, float velx, Uint16 stoppedtimer);
|
||||
|
||||
//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);
|
||||
|
||||
//Detiene todos los globos
|
||||
void stopAllBalloons();
|
||||
|
||||
//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 y procesa la colisión entre las balas y los globos
|
||||
void processBulletBallonCollision();
|
||||
|
||||
//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);
|
||||
|
||||
//Calcula y establece el valor de amenaza en funcion de los globos activos
|
||||
void calculateMenaceLevel();
|
||||
|
||||
//Obtiene el valor de la variable
|
||||
Uint8 getMenaceLevel();
|
||||
|
||||
//Gestiona el nivel de amenaza
|
||||
void checkMenaceLevel();
|
||||
|
||||
//Gestiona la entrada de teclado y mando 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 renderTransition(Uint8 index);
|
||||
|
||||
//Pinta el texto GetReady en pantalla
|
||||
void renderGetReady();
|
||||
|
||||
//Bucle para el titulo del juego
|
||||
void runTitle();
|
||||
|
||||
//Bucle para el juego
|
||||
void runGame();
|
||||
|
||||
//Bucle para el menu de pausa del juego
|
||||
void runPausedGame();
|
||||
|
||||
private:
|
||||
//Manejador de eventos
|
||||
SDL_Event eventHandler;
|
||||
|
||||
//El jugador
|
||||
Player player;
|
||||
|
||||
//Vector con los objetos globo
|
||||
Balloon balloon[50];
|
||||
#ifdef TEST
|
||||
Balloon balloonTest;
|
||||
Bullet bulletTest;
|
||||
#endif
|
||||
|
||||
//Vector con los objetos bala
|
||||
Bullet bullet[50];
|
||||
|
||||
//Fondo del juego
|
||||
Background gameBackground;
|
||||
|
||||
//Fondo de la pantalla de titulo
|
||||
Background titleBackground;
|
||||
|
||||
//Texto blanco
|
||||
Text whiteText;
|
||||
|
||||
//Texto negro
|
||||
Text blackText;
|
||||
|
||||
//Menu de la pantalla de título
|
||||
Menu menuTitle;
|
||||
|
||||
//Menú de la pantalla de pausa
|
||||
Menu menuPause;
|
||||
|
||||
//Indicador para el bucle principal
|
||||
Uint8 mGameStatus;
|
||||
|
||||
//Puntuación actual y puntuación máxima
|
||||
Uint32 mScore;
|
||||
Uint32 mHiScore;
|
||||
|
||||
//Cadena de texto con la puntuación actual y la puntuación máxima de 6 cifras
|
||||
std::string mScoreText;
|
||||
std::string mHiScoreText;
|
||||
|
||||
//Número máximo de globos y balas que puede almacenar el vector
|
||||
Uint8 mMaxBalloons;
|
||||
Uint8 mMaxBullets;
|
||||
|
||||
//Contador de ticks para ajustar la velocidad del juego
|
||||
Uint32 mOldTicks;
|
||||
|
||||
//Velocidad a la que se repite el bucle de juego
|
||||
Uint8 mGameSpeed;
|
||||
|
||||
//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 ha de aparecer el texto de GetReady en pantalla
|
||||
bool mGetReady;
|
||||
};
|
||||
|
||||
#endif
|
||||
27
source/globals.h
Normal file
27
source/globals.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_mixer.h>
|
||||
|
||||
#ifndef GLOBALS_H
|
||||
#define GLOBALS_H
|
||||
|
||||
//La ventana donde dibujamos
|
||||
SDL_Window *gWindow = NULL;
|
||||
|
||||
//El renderizador de la ventana
|
||||
SDL_Renderer *gRenderer = NULL;
|
||||
|
||||
//Manejador para el mando 1
|
||||
SDL_Joystick* gGameController = NULL;
|
||||
|
||||
//Objetos con la música del juego
|
||||
Mix_Music *gTitleMusic = NULL;
|
||||
Mix_Music *gPlayingMusic = NULL;
|
||||
|
||||
//Objetos con los efectos de sonido del juego
|
||||
Mix_Chunk *gPopBalloonFX = NULL;
|
||||
Mix_Chunk *gBulletFX = NULL;
|
||||
|
||||
#endif
|
||||
19
source/globals2.h
Normal file
19
source/globals2.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "ltexture.h"
|
||||
|
||||
#ifndef GLOBALS2_H
|
||||
#define GLOBALS2_H
|
||||
|
||||
//Texturas con gráficos
|
||||
LTexture gPlayerTexture;
|
||||
LTexture gGameBackgroundTexture;
|
||||
LTexture gTitleBackgroundTexture;
|
||||
LTexture gWhiteFontTexture;
|
||||
LTexture gBlackFontTexture;
|
||||
LTexture gMenuTexture;
|
||||
LTexture gBalloonTexture;
|
||||
LTexture gBulletTexture;
|
||||
LTexture gMiscTexture;
|
||||
|
||||
#endif
|
||||
135
source/ltexture.cpp
Normal file
135
source/ltexture.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
#include "ltexture.h"
|
||||
|
||||
LTexture::LTexture()
|
||||
{
|
||||
//Initialize
|
||||
mTexture = NULL;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
}
|
||||
|
||||
LTexture::~LTexture()
|
||||
{
|
||||
//Deallocate
|
||||
free();
|
||||
}
|
||||
|
||||
bool LTexture::loadFromFile(std::string path)
|
||||
{
|
||||
//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());
|
||||
if (loadedSurface == NULL)
|
||||
{
|
||||
printf("Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError());
|
||||
}
|
||||
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(gRenderer, 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( int width, int height, SDL_TextureAccess access )
|
||||
{
|
||||
//Create uninitialized texture
|
||||
mTexture = SDL_CreateTexture( gRenderer, 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(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(gRenderer, mTexture, clip, &renderQuad, angle, center, flip);
|
||||
}
|
||||
|
||||
void LTexture::setAsRenderTarget()
|
||||
{
|
||||
//Make self render target
|
||||
SDL_SetRenderTarget( gRenderer, mTexture );
|
||||
}
|
||||
|
||||
int LTexture::getWidth()
|
||||
{
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
int LTexture::getHeight()
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
70
source/ltexture.h
Normal file
70
source/ltexture.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include "const.h"
|
||||
#include "globals2.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 );
|
||||
|
||||
//Creates blank texture
|
||||
bool createBlank( 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( 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();
|
||||
|
||||
//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
|
||||
348
source/main.cpp
Normal file
348
source/main.cpp
Normal file
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
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 spriteanimated
|
||||
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
|
||||
*/
|
||||
#define TEST_
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_mixer.h>
|
||||
#include "background.h"
|
||||
#include "balloon.h"
|
||||
#include "bullet.h"
|
||||
#include "const.h"
|
||||
#include "gamedirector.h"
|
||||
#include "globals.h"
|
||||
#include "globals2.h"
|
||||
#include "ltexture.h"
|
||||
#include "menu.h"
|
||||
#include "player.h"
|
||||
#include "sprite.h"
|
||||
#include "spriteanimated.h"
|
||||
#include "struct.h"
|
||||
#include "text.h"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
//Arranca SDL y crea la ventana
|
||||
bool init();
|
||||
|
||||
//Carga todos los recursos
|
||||
bool loadMedia();
|
||||
|
||||
//Libera todos los recursos y cierra SDL
|
||||
void close();
|
||||
|
||||
//Arranca SDL y crea la ventana
|
||||
bool init()
|
||||
{
|
||||
//Indicador de inicialización
|
||||
bool success = true;
|
||||
|
||||
//Inicializa SDL
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0)
|
||||
{
|
||||
printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Establece el filtro de la textura a nearest
|
||||
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"))
|
||||
{
|
||||
printf("Warning: Nearest texture filtering not enabled!");
|
||||
}
|
||||
|
||||
//Inicializa SDL_mixer
|
||||
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
|
||||
{
|
||||
printf("SDL_mixer could not initialize! SDL_mixer Error: %s\n", Mix_GetError());
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Comprueba los mandos
|
||||
if (SDL_NumJoysticks() < 1)
|
||||
{
|
||||
printf("Warning: No joysticks connected!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
//Carga el mando
|
||||
gGameController = SDL_JoystickOpen(0);
|
||||
if (gGameController == NULL)
|
||||
{
|
||||
printf("Warning: Unable to open game controller! SDL Error: %s\n", SDL_GetError());
|
||||
}
|
||||
printf("%i joysticks were found.\n", SDL_NumJoysticks());
|
||||
std::cout << SDL_JoystickNumButtons(gGameController) << " buttons\n";
|
||||
}
|
||||
|
||||
//Crea la ventana
|
||||
gWindow = SDL_CreateWindow("Super Popping (Like Loc) in Jailers World", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, VIEW_WIDTH, VIEW_HEIGHT, SDL_WINDOW_SHOWN);
|
||||
if (gWindow == NULL)
|
||||
{
|
||||
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Crea un renderizador para la ventana con vsync
|
||||
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
if (gRenderer == NULL)
|
||||
{
|
||||
printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Inicializa el color de renderizado
|
||||
SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0x00, 0xFF);
|
||||
|
||||
//Establece el tamaño del buffer de renderizado
|
||||
SDL_RenderSetLogicalSize(gRenderer, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
|
||||
//Inicializa el cargador de PNG
|
||||
int imgFlags = IMG_INIT_PNG;
|
||||
if (!(IMG_Init(imgFlags) & imgFlags))
|
||||
{
|
||||
printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//Carga todos los recursos
|
||||
bool loadMedia()
|
||||
{
|
||||
//Indicador de éxito en la carga
|
||||
bool success = true;
|
||||
|
||||
//Carga los gráficos del jugador
|
||||
if (!gPlayerTexture.loadFromFile("media/gfx/player.png"))
|
||||
{
|
||||
printf("Failed to load player texture!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga los gráficos de los globos
|
||||
if (!gBalloonTexture.loadFromFile("media/gfx/balloon.png"))
|
||||
{
|
||||
printf("Failed to load balloon texture!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga los gráficos de las balas
|
||||
if (!gBulletTexture.loadFromFile("media/gfx/bullet.png"))
|
||||
{
|
||||
printf("Failed to load bullet texture!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga los gráficos del fondo del juego
|
||||
if (!gGameBackgroundTexture.loadFromFile("media/gfx/background.png"))
|
||||
{
|
||||
printf("Failed to load game background texture!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga los gráficos del fondo de la pantalla de titulo
|
||||
if (!gTitleBackgroundTexture.loadFromFile("media/gfx/title.png"))
|
||||
{
|
||||
printf("Failed to load title texture!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga varios gráficos para varios propósitos
|
||||
if (!gMiscTexture.loadFromFile("media/gfx/misc.png"))
|
||||
{
|
||||
printf("Failed to load misc texture!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga los gráficos para el menu
|
||||
if (!gMenuTexture.loadFromFile("media/gfx/menu.png"))
|
||||
{
|
||||
printf("Failed to load menu texture!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga los gráficos para el texto blanco
|
||||
if (!gWhiteFontTexture.loadFromFile("media/gfx/white_font.png"))
|
||||
{
|
||||
printf("Failed to load white font texture!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga los gráficos para el texto negro
|
||||
if (!gBlackFontTexture.loadFromFile("media/gfx/black_font.png"))
|
||||
{
|
||||
printf("Failed to load black font texture!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga la música del titulo
|
||||
gTitleMusic = Mix_LoadMUS("media/music/title.ogg");
|
||||
if (gTitleMusic == NULL)
|
||||
{
|
||||
printf("Failed to load title music! SDL_mixer Error: %s\n", Mix_GetError());
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga la música del juego
|
||||
gPlayingMusic = Mix_LoadMUS("media/music/playing.ogg");
|
||||
if (gPlayingMusic == NULL)
|
||||
{
|
||||
printf("Failed to load playing music! SDL_mixer Error: %s\n", Mix_GetError());
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga los efectos de sonido para la explosión de los globos
|
||||
gPopBalloonFX = Mix_LoadWAV("media/sound/balloon.wav");
|
||||
if (gPopBalloonFX == NULL)
|
||||
{
|
||||
printf("Failed to load balloon sound effect! SDL_mixer Error: %s\n", Mix_GetError());
|
||||
success = false;
|
||||
}
|
||||
|
||||
//Carga los efectos de sonido para los disparos del jugador
|
||||
gBulletFX = Mix_LoadWAV("media/sound/bullet.wav");
|
||||
if (gBulletFX == NULL)
|
||||
{
|
||||
printf("Failed to load bullet sound effect! SDL_mixer Error: %s\n", Mix_GetError());
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//Libera todos los recursos y cierra SDL
|
||||
void close()
|
||||
{
|
||||
//Libera todas las imagenes
|
||||
gPlayerTexture.free();
|
||||
gGameBackgroundTexture.free();
|
||||
gTitleBackgroundTexture.free();
|
||||
gWhiteFontTexture.free();
|
||||
gBlackFontTexture.free();
|
||||
gMenuTexture.free();
|
||||
gBalloonTexture.free();
|
||||
gMiscTexture.free();
|
||||
|
||||
//Libera los efectos de sonido
|
||||
Mix_FreeChunk(gPopBalloonFX);
|
||||
Mix_FreeChunk(gBulletFX);
|
||||
gPopBalloonFX = NULL;
|
||||
gBulletFX = NULL;
|
||||
|
||||
//Libra la música
|
||||
Mix_FreeMusic(gTitleMusic);
|
||||
gTitleMusic = NULL;
|
||||
Mix_FreeMusic(gPlayingMusic);
|
||||
gPlayingMusic = NULL;
|
||||
|
||||
//Libera el mando
|
||||
SDL_JoystickClose(gGameController);
|
||||
gGameController = NULL;
|
||||
|
||||
//Destruye la ventana
|
||||
SDL_DestroyRenderer(gRenderer);
|
||||
SDL_DestroyWindow(gWindow);
|
||||
gWindow = NULL;
|
||||
gRenderer = NULL;
|
||||
|
||||
//Sal del subsistema SDL
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
int main(int argc, char *args[])
|
||||
{
|
||||
//Arranca SDL y crea la ventana
|
||||
if (!init())
|
||||
{
|
||||
printf("Failed to initialize!\n");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Carga los recursos
|
||||
if (!loadMedia())
|
||||
{
|
||||
printf("Failed to load media!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
//Crea el objeto gameDirector
|
||||
GameDirector gameDirector;
|
||||
|
||||
//Inicializa el objeto gameDirector
|
||||
gameDirector.init();
|
||||
|
||||
#ifdef TEST
|
||||
gameDirector.resetBalloons();
|
||||
#endif
|
||||
|
||||
//Mientras no se quiera salir del juego
|
||||
while (!(gameDirector.getGameStatus() == GAME_STATE_QUIT))
|
||||
{
|
||||
switch (gameDirector.getGameStatus())
|
||||
{
|
||||
case GAME_STATE_TITLE:
|
||||
gameDirector.runTitle();
|
||||
break;
|
||||
|
||||
case GAME_STATE_PLAYING:
|
||||
gameDirector.runGame();
|
||||
break;
|
||||
|
||||
case GAME_STATE_PAUSED:
|
||||
gameDirector.runPausedGame();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Libera todos los recursos y cierra SDL
|
||||
close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
195
source/menu.cpp
Normal file
195
source/menu.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include "menu.h"
|
||||
|
||||
//Constructor
|
||||
Menu::Menu()
|
||||
{
|
||||
init(0, 0, 0, MENU_BACKGROUND_SOLID);
|
||||
}
|
||||
|
||||
//Inicializador
|
||||
void Menu::init(int x, int y, int offset_sprite_selector, int backgroundType)
|
||||
{
|
||||
//Inicia variables
|
||||
mSelectorIndex = 0;
|
||||
mTotalItems = 0;
|
||||
mItemSelected = MENU_NO_OPTION;
|
||||
mPosX = x;
|
||||
mPosY = y;
|
||||
mRect.x = 0;
|
||||
mRect.y = 0;
|
||||
mRect.w = 0;
|
||||
mRect.h = 0;
|
||||
mRectR = 0;
|
||||
mRectG = 0;
|
||||
mRectB = 0;
|
||||
mBackgroundType = backgroundType;
|
||||
|
||||
//Sprite con los graficos del selector
|
||||
mSelectorSprite.setWidth(8);
|
||||
mSelectorSprite.setHeight(8);
|
||||
mSelectorSprite.setPosX(0);
|
||||
mSelectorSprite.setPosY(0);
|
||||
mSelectorSprite.setTexture(gMenuTexture);
|
||||
mSelectorSprite.setSpriteClip(offset_sprite_selector, 0, mSelectorSprite.getWidth(), mSelectorSprite.getHeight());
|
||||
|
||||
//Elementos del menu
|
||||
for (Uint8 i = 0; i < 10; i++)
|
||||
{
|
||||
mMenuItem[i].label = "";
|
||||
mMenuItem[i].x = mPosX;
|
||||
mMenuItem[i].y = mPosY + (i * (BLOCK + 2));
|
||||
}
|
||||
|
||||
//Mueve el grafico del selector al elemento seleccionado
|
||||
moveSelectorSprite(mSelectorIndex);
|
||||
}
|
||||
|
||||
//Obtiene el valor de la variable
|
||||
Uint8 Menu::getItemSelected()
|
||||
{
|
||||
return mItemSelected;
|
||||
};
|
||||
|
||||
//Mueve el grafico del selector al elemento seleccionado
|
||||
void Menu::moveSelectorSprite(int pos)
|
||||
{
|
||||
mSelectorSprite.setPosX(mMenuItem[pos].x - (BLOCK * 1));
|
||||
mSelectorSprite.setPosY(mMenuItem[pos].y);
|
||||
}
|
||||
|
||||
//Deja el menu apuntando al primer elemento
|
||||
void Menu::resetMenu()
|
||||
{
|
||||
mItemSelected = MENU_NO_OPTION;
|
||||
mSelectorIndex = 0;
|
||||
moveSelectorSprite(mSelectorIndex);
|
||||
};
|
||||
|
||||
//Deja el menu apuntando al siguiente elemento
|
||||
void Menu::increaseSelectorIndex()
|
||||
{
|
||||
if (mSelectorIndex < (mTotalItems - 1))
|
||||
{
|
||||
++mSelectorIndex;
|
||||
}
|
||||
};
|
||||
|
||||
//Deja el menu apuntando al elemento anterior
|
||||
void Menu::decreaseSelectorIndex()
|
||||
{
|
||||
if (mSelectorIndex > 0)
|
||||
{
|
||||
--mSelectorIndex;
|
||||
}
|
||||
};
|
||||
|
||||
//Comprueba la entrada (teclado, gamepad) y actua en consecuencia
|
||||
void Menu::checkInput(Uint8 input)
|
||||
{
|
||||
switch (input)
|
||||
{
|
||||
case INPUT_UP:
|
||||
decreaseSelectorIndex();
|
||||
moveSelectorSprite(mSelectorIndex);
|
||||
break;
|
||||
case INPUT_DOWN:
|
||||
increaseSelectorIndex();
|
||||
moveSelectorSprite(mSelectorIndex);
|
||||
break;
|
||||
case INPUT_FIRE:
|
||||
mItemSelected = mSelectorIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Pinta el menu en pantalla
|
||||
void Menu::render(Text &text)
|
||||
{
|
||||
//Render color filled quad
|
||||
if (mBackgroundType == MENU_BACKGROUND_SOLID)
|
||||
{
|
||||
SDL_SetRenderDrawColor(gRenderer, mRectR, mRectG, mRectB, mRectA);
|
||||
SDL_RenderFillRect(gRenderer, &mRect);
|
||||
}
|
||||
|
||||
//Render text
|
||||
int i = 0;
|
||||
mSelectorSprite.render();
|
||||
for (i = 0; i < mTotalItems; i++)
|
||||
{
|
||||
text.write(mMenuItem[i].x, mMenuItem[i].y, mMenuItem[i].label);
|
||||
}
|
||||
}
|
||||
|
||||
//Establece el rectangulo de fondo del menu
|
||||
void Menu::setRectSize()
|
||||
{
|
||||
int i = 0;
|
||||
int maxLength = 0;
|
||||
|
||||
//La altura se corresponde al numero de items mas un hueco arriba y otro abajo
|
||||
mRect.h = (mTotalItems + 2) * BLOCK;
|
||||
|
||||
//La anchura es la de la cadena mas larga mas tres bloques, uno por la derecha
|
||||
//y dos por la izquierda, uno de ellos para el selector
|
||||
for (i = 0; i < mTotalItems; i++)
|
||||
{
|
||||
if ((int)mMenuItem[i].label.length() > maxLength)
|
||||
{
|
||||
maxLength = mMenuItem[i].label.length();
|
||||
}
|
||||
}
|
||||
mRect.w = (maxLength + 3) * BLOCK;
|
||||
|
||||
mRect.x = mPosX - (BLOCK * 2);
|
||||
mRect.y = mPosY - BLOCK;
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
mRectR = r;
|
||||
mRectG = g;
|
||||
mRectB = b;
|
||||
mRectA = alpha;
|
||||
}
|
||||
|
||||
//Centra el menu en pantalla
|
||||
void Menu::centerMenuOnScreen()
|
||||
{
|
||||
//Actualiza el rectangulo de fondo para recalcular las dimensiones
|
||||
setRectSize();
|
||||
|
||||
//Establece la nueva posición centrada en funcion del ancho
|
||||
//de la pantalla y del ancho del rectangulo
|
||||
mPosX = (SCREEN_WIDTH / 2) - (mRect.w / 2) + (BLOCK * 2);
|
||||
|
||||
//Reposiciona los elementos del menu
|
||||
for (Uint8 i = 0; i < 10; i++)
|
||||
{
|
||||
mMenuItem[i].x = mPosX;
|
||||
}
|
||||
|
||||
//Recalcula el rectangulo de fondo
|
||||
setRectSize();
|
||||
|
||||
//Recoloca el selector
|
||||
moveSelectorSprite(mSelectorIndex);
|
||||
}
|
||||
|
||||
//Añade un item al menu
|
||||
void Menu::addItem(std::string text)
|
||||
{
|
||||
if (mTotalItems < 10)
|
||||
{
|
||||
mMenuItem[mTotalItems].label = text;
|
||||
setTotalItems(mTotalItems + 1);
|
||||
setRectSize();
|
||||
}
|
||||
}
|
||||
93
source/menu.h
Normal file
93
source/menu.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
|
||||
#include "sprite.h"
|
||||
#include "const.h"
|
||||
#include "globals.h"
|
||||
#include "text.h"
|
||||
|
||||
#ifndef MENU_H
|
||||
#define MENU_H
|
||||
|
||||
//Clase menu
|
||||
class Menu
|
||||
{
|
||||
public:
|
||||
//Constructor
|
||||
Menu();
|
||||
|
||||
//Inicializador
|
||||
void init(int x, int y, int offset_sprite_selector, int backgroundType);
|
||||
|
||||
//Obtiene el valor de la variable
|
||||
Uint8 getItemSelected();
|
||||
|
||||
//Mueve el grafico del selector al elemento seleccionado
|
||||
void moveSelectorSprite(int pos);
|
||||
|
||||
//Deja el menu apuntando al primer elemento
|
||||
void resetMenu();
|
||||
|
||||
//Deja el menu apuntando al siguiente elemento
|
||||
void increaseSelectorIndex();
|
||||
|
||||
//Deja el menu apuntando al elemento anterior
|
||||
void decreaseSelectorIndex();
|
||||
|
||||
//Comprueba la entrada (teclado, gamepad) y actua en consecuencia
|
||||
void checkInput(Uint8 input);
|
||||
|
||||
//Pinta el menu en pantalla
|
||||
void render(Text &text);
|
||||
|
||||
//Establece el rectangulo de fondo del menu
|
||||
void setRectSize();
|
||||
|
||||
//Establece el valor de la variable
|
||||
void setTotalItems(int num);
|
||||
|
||||
//Establece el color del rectangulo de fondo
|
||||
void setBackgroundColor(int r, int g, int b, int alpha);
|
||||
|
||||
//Centra el menu en pantalla
|
||||
void centerMenuOnScreen();
|
||||
|
||||
//Añade un item al menu
|
||||
void addItem(std::string text);
|
||||
|
||||
private:
|
||||
//Posicion X/Y del texto del primer elemento del menu
|
||||
int mPosX;
|
||||
int mPosY;
|
||||
|
||||
//Elemento del menu que tiene el foco
|
||||
Uint8 mSelectorIndex;
|
||||
|
||||
//Numero de items del menu
|
||||
Uint8 mTotalItems;
|
||||
|
||||
//Item del menu que ha sido seleccionado
|
||||
Uint8 mItemSelected;
|
||||
|
||||
//Tipo de fondo para el menu
|
||||
Uint8 mBackgroundType;
|
||||
|
||||
//Sprite con los graficos del selector
|
||||
Sprite mSelectorSprite;
|
||||
|
||||
//Rectangulo y colores para el fondo del menu
|
||||
SDL_Rect mRect;
|
||||
Uint8 mRectR; //Rojo
|
||||
Uint8 mRectG; //Verde
|
||||
Uint8 mRectB; //Azul
|
||||
Uint8 mRectA; //Alfa o transparencia
|
||||
|
||||
//Estructura para cada elemento del menu
|
||||
struct MenuItem
|
||||
{
|
||||
std::string label;
|
||||
int x;
|
||||
int y;
|
||||
} mMenuItem[10];
|
||||
};
|
||||
|
||||
#endif
|
||||
252
source/player.cpp
Normal file
252
source/player.cpp
Normal file
@@ -0,0 +1,252 @@
|
||||
#include "player.h"
|
||||
|
||||
//Constructor
|
||||
Player::Player()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
//Iniciador
|
||||
void Player::init()
|
||||
{
|
||||
//Establece la altura y el ancho del jugador
|
||||
mWidth = 3 * BLOCK;
|
||||
mHeight = 3 * BLOCK;
|
||||
|
||||
//Establece la posición inicial del jugador
|
||||
mPosX = PLAY_AREA_LEFT + (PLAY_AREA_WIDTH / 2) - (mWidth / 2);
|
||||
mPosY = PLAY_AREA_BOTTOM - mHeight;
|
||||
|
||||
//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;
|
||||
|
||||
//Inicia el contador
|
||||
mCooldown = 10;
|
||||
|
||||
//Inicia el sprite
|
||||
mSprite.init();
|
||||
|
||||
//Set width and height of the player sprite
|
||||
mSprite.setWidth(mWidth);
|
||||
mSprite.setHeight(mHeight);
|
||||
|
||||
//Set sprite position
|
||||
mSprite.setPosX(mPosX);
|
||||
mSprite.setPosY(mPosY);
|
||||
|
||||
//Set sprite sheet
|
||||
mSprite.setTexture(gPlayerTexture);
|
||||
|
||||
//Set status
|
||||
mStatus = PLAYER_STATE_STOPPED;
|
||||
|
||||
//Initialize animation variables
|
||||
mSprite.setCurrentFrame(0);
|
||||
mSprite.setAnimationCounter(0);
|
||||
|
||||
mSprite.setAnimationNumFrames(PLAYER_STATE_STOPPED, 1);
|
||||
mSprite.setAnimationNumFrames(PLAYER_STATE_WALKING_LEFT, 4);
|
||||
mSprite.setAnimationNumFrames(PLAYER_STATE_WALKING_RIGHT, 4);
|
||||
|
||||
mSprite.setAnimationSpeed(PLAYER_STATE_STOPPED, 10);
|
||||
mSprite.setAnimationSpeed(PLAYER_STATE_WALKING_LEFT, 5);
|
||||
mSprite.setAnimationSpeed(PLAYER_STATE_WALKING_RIGHT, 5);
|
||||
|
||||
//Set animation clips
|
||||
mSprite.setAnimationFrames(PLAYER_STATE_WALKING_LEFT, 0, mSprite.getWidth() * 0, mSprite.getWidth() * 0, mSprite.getWidth(), mSprite.getHeight());
|
||||
mSprite.setAnimationFrames(PLAYER_STATE_WALKING_LEFT, 1, mSprite.getWidth() * 1, mSprite.getWidth() * 0, mSprite.getWidth(), mSprite.getHeight());
|
||||
mSprite.setAnimationFrames(PLAYER_STATE_WALKING_LEFT, 2, mSprite.getWidth() * 2, mSprite.getWidth() * 0, mSprite.getWidth(), mSprite.getHeight());
|
||||
mSprite.setAnimationFrames(PLAYER_STATE_WALKING_LEFT, 3, mSprite.getWidth() * 3, mSprite.getWidth() * 0, mSprite.getWidth(), mSprite.getHeight());
|
||||
mSprite.setAnimationFrames(PLAYER_STATE_WALKING_RIGHT, 0, mSprite.getWidth() * 0, mSprite.getHeight() * 1, mSprite.getWidth(), mSprite.getHeight());
|
||||
mSprite.setAnimationFrames(PLAYER_STATE_WALKING_RIGHT, 1, mSprite.getWidth() * 1, mSprite.getHeight() * 1, mSprite.getWidth(), mSprite.getHeight());
|
||||
mSprite.setAnimationFrames(PLAYER_STATE_WALKING_RIGHT, 2, mSprite.getWidth() * 2, mSprite.getHeight() * 1, mSprite.getWidth(), mSprite.getHeight());
|
||||
mSprite.setAnimationFrames(PLAYER_STATE_WALKING_RIGHT, 3, mSprite.getWidth() * 3, mSprite.getHeight() * 1, mSprite.getWidth(), mSprite.getHeight());
|
||||
mSprite.setAnimationFrames(PLAYER_STATE_STOPPED, 0, mSprite.getWidth() * 0, mSprite.getHeight() * 2, mSprite.getWidth(), mSprite.getHeight());
|
||||
|
||||
//Set window for sprite sheet
|
||||
mSprite.setSpriteClip(mSprite.getAnimationClip(PLAYER_STATE_STOPPED, 0));
|
||||
}
|
||||
|
||||
//Comprueba el teclado y actua en consecuencia
|
||||
void Player::checkInput(Uint8 input)
|
||||
{
|
||||
switch (input)
|
||||
{
|
||||
case INPUT_LEFT:
|
||||
mVelX = -mBaseSpeed;
|
||||
setStatus(PLAYER_STATE_WALKING_LEFT);
|
||||
break;
|
||||
|
||||
case INPUT_RIGHT:
|
||||
mVelX = mBaseSpeed;
|
||||
setStatus(PLAYER_STATE_WALKING_RIGHT);
|
||||
break;
|
||||
|
||||
default:
|
||||
mVelX = 0;
|
||||
setStatus(PLAYER_STATE_STOPPED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Mueve el jugador a la posición y animación que le corresponde
|
||||
void Player::move()
|
||||
{
|
||||
//Move the player left or right
|
||||
mPosX += mVelX;
|
||||
|
||||
//If the player went too far to the left or right
|
||||
if ((mPosX < PLAY_AREA_LEFT) || (mPosX + mWidth > PLAY_AREA_RIGHT))
|
||||
{
|
||||
//Move back
|
||||
mPosX -= mVelX;
|
||||
}
|
||||
|
||||
//Move the player up or down
|
||||
mPosY += mVelY;
|
||||
|
||||
//If the player went too far up or down
|
||||
if ((mPosY < PLAY_AREA_TOP) || (mPosY + mHeight > PLAY_AREA_BOTTOM))
|
||||
{
|
||||
//Move back
|
||||
mPosY -= mVelY;
|
||||
}
|
||||
|
||||
//Update sprite position
|
||||
mSprite.setPosX(getPosX());
|
||||
mSprite.setPosY(mPosY);
|
||||
}
|
||||
|
||||
//Pinta el jugador en pantalla
|
||||
void Player::render()
|
||||
{
|
||||
mSprite.render();
|
||||
}
|
||||
|
||||
//Establece el estado del jugador
|
||||
void Player::setStatus(int status)
|
||||
{
|
||||
//Si cambiamos de estado, reiniciamos la animación
|
||||
if (mStatus != status)
|
||||
{
|
||||
mStatus = status;
|
||||
mSprite.setCurrentFrame(0);
|
||||
}
|
||||
}
|
||||
|
||||
//Establece la animación correspondiente al estado
|
||||
void Player::setAnimation()
|
||||
{
|
||||
mSprite.animate(mStatus);
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
}
|
||||
|
||||
//Actualiza al jugador a su posicion, animación y controla los contadores
|
||||
void Player::update()
|
||||
{
|
||||
move();
|
||||
setAnimation();
|
||||
shiftColliders();
|
||||
updateCooldown();
|
||||
}
|
||||
|
||||
//Obtiene la puntuación del jugador
|
||||
int Player::getScore()
|
||||
{
|
||||
return mScore;
|
||||
}
|
||||
|
||||
//Establece la puntuación del jugador
|
||||
void Player::setScore(int score)
|
||||
{
|
||||
mScore = score;
|
||||
}
|
||||
|
||||
//Añade a la puntuación del jugador
|
||||
void Player::addScore(int score)
|
||||
{
|
||||
mScore += score;
|
||||
}
|
||||
|
||||
//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()
|
||||
{
|
||||
//Align collider to center of player
|
||||
mCollider.x = mPosX + (mWidth / 2);
|
||||
mCollider.y = mPosY + (mHeight / 2);
|
||||
}
|
||||
114
source/player.h
Normal file
114
source/player.h
Normal file
@@ -0,0 +1,114 @@
|
||||
#pragma once
|
||||
|
||||
#include "struct.h"
|
||||
#include "spriteanimated.h"
|
||||
#include "const.h"
|
||||
#include "globals.h"
|
||||
#include "globals2.h"
|
||||
|
||||
#ifndef PLAYER_H
|
||||
#define PLAYER_H
|
||||
|
||||
//The player
|
||||
class Player
|
||||
{
|
||||
public:
|
||||
//Constructor
|
||||
Player();
|
||||
|
||||
//Iniciador
|
||||
void init();
|
||||
|
||||
//Comprueba la entrada (teclado, gamepad) y actua en consecuencia
|
||||
void checkInput(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 setStatus(int 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();
|
||||
|
||||
//Establece la puntuación del jugador
|
||||
void setScore(int score);
|
||||
|
||||
//Añade a la puntuación del jugador
|
||||
void addScore(int score);
|
||||
|
||||
//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
|
||||
int mScore;
|
||||
|
||||
//Estado del jugador
|
||||
Uint8 mStatus;
|
||||
|
||||
//Sprite para dibujar al jugador en pantalla
|
||||
SpriteAnimated mSprite;
|
||||
|
||||
//Circulo de colisión del jugador
|
||||
Circle mCollider;
|
||||
|
||||
//Actualiza el circulo de colisión a la posición del jugador
|
||||
void shiftColliders();
|
||||
};
|
||||
|
||||
#endif
|
||||
88
source/sprite.cpp
Normal file
88
source/sprite.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "sprite.h"
|
||||
|
||||
void Sprite::render()
|
||||
{
|
||||
//Muestra el sprite por pantalla
|
||||
mTexture->render(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;
|
||||
}
|
||||
73
source/sprite.h
Normal file
73
source/sprite.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include "ltexture.h"
|
||||
|
||||
#ifndef SPRITE_H
|
||||
#define SPRITE_H
|
||||
|
||||
//Clase sprite
|
||||
class Sprite
|
||||
{
|
||||
public:
|
||||
//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);
|
||||
|
||||
|
||||
private:
|
||||
//Posición X,Y donde dibujar el sprite
|
||||
int mPosX;
|
||||
int mPosY;
|
||||
|
||||
//Alto y ancho del sprite
|
||||
Uint16 mWidth;
|
||||
Uint16 mHeight;
|
||||
|
||||
//Textura donde estan todos los dibujos del sprite
|
||||
LTexture *mTexture;
|
||||
|
||||
//Rectangulo de la textura que se dibujará en pantalla
|
||||
SDL_Rect mSpriteClip;
|
||||
};
|
||||
|
||||
#endif
|
||||
87
source/spriteanimated.cpp
Normal file
87
source/spriteanimated.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "spriteanimated.h"
|
||||
|
||||
//Constructor
|
||||
SpriteAnimated::SpriteAnimated()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
//Iniciador
|
||||
void SpriteAnimated::init()
|
||||
{
|
||||
for (Uint8 i = 0; i < 20; i++)
|
||||
{
|
||||
mAnimation[i].numFrames = 0;
|
||||
mAnimation[i].speed = 0;
|
||||
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 SpriteAnimated::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
|
||||
if (mCurrentFrame >= mAnimation[index].numFrames)
|
||||
{
|
||||
mAnimationCounter = 0;
|
||||
}
|
||||
//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 SpriteAnimated::setCurrentFrame(Uint8 num)
|
||||
{
|
||||
mCurrentFrame = num;
|
||||
}
|
||||
|
||||
//Establece el numero de frames de la animacion
|
||||
void SpriteAnimated::setAnimationCounter(Uint16 num)
|
||||
{
|
||||
mAnimationCounter = num;
|
||||
}
|
||||
|
||||
//Establece el rectangulo para un frame de una animación
|
||||
void SpriteAnimated::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 SpriteAnimated::setAnimationSpeed(Uint8 index, Uint8 speed)
|
||||
{
|
||||
mAnimation[index].speed = speed;
|
||||
}
|
||||
|
||||
//Establece el numero de frames de una animación
|
||||
void SpriteAnimated::setAnimationNumFrames(Uint8 index, Uint8 num)
|
||||
{
|
||||
mAnimation[index].numFrames = num;
|
||||
}
|
||||
|
||||
//Devuelve el rectangulo de una animación y frame concreto
|
||||
SDL_Rect SpriteAnimated::getAnimationClip(Uint8 index_animation, Uint8 index_frame)
|
||||
{
|
||||
return mAnimation[index_animation].frames[index_frame];
|
||||
}
|
||||
61
source/spriteanimated.h
Normal file
61
source/spriteanimated.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include "sprite.h"
|
||||
#include "const.h"
|
||||
#include <iostream>
|
||||
|
||||
#ifndef SPRITEANIMATED_H
|
||||
#define SPRITEANIMATED_H
|
||||
|
||||
//Clase spriteAnimated
|
||||
class SpriteAnimated : public Sprite
|
||||
{
|
||||
public:
|
||||
//Constructor
|
||||
SpriteAnimated();
|
||||
|
||||
//Iniciador
|
||||
void init();
|
||||
|
||||
//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 numero de frames de la animacion
|
||||
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);
|
||||
|
||||
//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];
|
||||
Uint8 numFrames;
|
||||
Uint8 speed;
|
||||
};
|
||||
|
||||
//Vector con las diferentes animaciones y los diferentes frames de cada animación
|
||||
sAnimation mAnimation[20];
|
||||
|
||||
//Frame actual
|
||||
Uint8 mCurrentFrame;
|
||||
|
||||
//Contador para las animaciones
|
||||
Uint16 mAnimationCounter;
|
||||
};
|
||||
|
||||
#endif
|
||||
16
source/struct.h
Normal file
16
source/struct.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#ifndef STRUCT_H
|
||||
#define STRUCT_H
|
||||
|
||||
//Estructura para definir un circulo
|
||||
struct Circle
|
||||
{
|
||||
Uint16 x;
|
||||
Uint16 y;
|
||||
Uint8 r;
|
||||
};
|
||||
|
||||
#endif
|
||||
49
source/text.cpp
Normal file
49
source/text.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "text.h"
|
||||
|
||||
//Constructor
|
||||
Text::Text()
|
||||
{
|
||||
init(NULL);
|
||||
}
|
||||
|
||||
//Inicializador
|
||||
void Text::init(LTexture *texture)
|
||||
{
|
||||
//Inicia los valores del sprite que dibuja las letras
|
||||
mSprite.setWidth(8);
|
||||
mSprite.setHeight(8);
|
||||
mSprite.setPosX(0);
|
||||
mSprite.setPosY(0);
|
||||
mSprite.setTexture(*texture);
|
||||
mSprite.setSpriteClip(8, 8, mSprite.getWidth(), mSprite.getHeight());
|
||||
|
||||
//Cadena con los caracteres ascii que se van a inicializar
|
||||
std::string text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-/().:#";
|
||||
Uint8 i;
|
||||
|
||||
//Inicializa a cero el vector con las coordenadas
|
||||
for (i = 0; i < 255; ++i)
|
||||
{
|
||||
mOffset[i].x = 0;
|
||||
mOffset[i].y = 0;
|
||||
}
|
||||
|
||||
//Establece las coordenadas para cada caracter ascii de la cadena
|
||||
for (i = 0; i < text.length(); ++i)
|
||||
{
|
||||
mOffset[int(text[i])].x = (((int(text[i]) - 32) % 15) - 0) * BLOCK;
|
||||
mOffset[int(text[i])].y = ((int(text[i]) - 32) / 15) * BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
//Escribe el texto en pantalla
|
||||
void Text::write(int x, int y, std::string text)
|
||||
{;
|
||||
for (Uint8 i = 0; i < text.length(); ++i)
|
||||
{
|
||||
mSprite.setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, 8, 8);
|
||||
mSprite.setPosX(x + (i * BLOCK));
|
||||
mSprite.setPosY(y);
|
||||
mSprite.render();
|
||||
}
|
||||
}
|
||||
34
source/text.h
Normal file
34
source/text.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "sprite.h"
|
||||
#include "const.h"
|
||||
|
||||
#ifndef TEXT_H
|
||||
#define TEXT_H
|
||||
|
||||
//Text class
|
||||
class Text
|
||||
{
|
||||
public:
|
||||
//Constructor
|
||||
Text();
|
||||
|
||||
//Inicializador
|
||||
void init(LTexture *texture);
|
||||
|
||||
//Escribe el texto en pantalla
|
||||
void write(int x, int y, std::string text);
|
||||
|
||||
private:
|
||||
//Objeto con los graficos para el texto
|
||||
Sprite mSprite;
|
||||
|
||||
//Coordenadas dentro del PNG para cada código ascii
|
||||
struct Offset
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} mOffset[255];
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user