commit eb7538ab591f4a6d21df2ebc841d0f61054dddb9 Author: Sergio Valor Date: Thu Oct 20 13:45:49 2022 +0200 Primer commit diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..ff29095 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "g++.exe - Build and debug active file", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}\\bin\\${workspaceFolderBasename}_debug.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}\\bin", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "gdb.exe", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "C/C++: g++.exe build active file" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..431ca21 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,52 @@ +{ + "files.associations": { + "new": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "optional": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "bit": "cpp", + "compare": "cpp", + "concepts": "cpp", + "functional": "cpp", + "iterator": "cpp", + "numeric": "cpp", + "random": "cpp", + "numbers": "cpp" + } +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..d397b20 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,33 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: g++.exe build active file", + "command": "g++.exe", + "args": [ + "${workspaceFolder}\\*.cpp", + "-g", + "-std=c++11", + "-lmingw32", + "-lSDL2main", + "-lSDL2_image", + "-lSDL2_mixer", + "-lSDL2", + "-o", + "${workspaceFolder}\\bin\\${workspaceFolderBasename}_debug.exe" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "compiler: g++.exe" + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..147483e --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +executable = super_pang_clone +source = *.cpp + +windows: + @echo off + if not exist bin\ (mkdir bin) + g++ $(source) -std=c++11 -Wall -O2 -lmingw32 -lSDL2main -lSDL2 -lSDL2_image -lSDL2_mixer -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows -o bin/$(executable).exe + strip -s -R .comment -R .gnu.version bin/$(executable).exe --strip-unneeded +macos: + mkdir -p bin + g++ $(source) -std=c++11 -Wall -O2 -lSDL2 -lSDL2_image -lSDL2_mixer -ffunction-sections -fdata-sections -o bin/$(executable)_macos +linux: + mkdir -p bin + g++ $(source) -std=c++11 -Wall -Os -lSDL2 -lSDL2_image -lSDL2_mixer -ffunction-sections -fdata-sections -Wl,--gc-sections -o bin/$(executable)_linux + strip -s -R .comment -R .gnu.version bin/$(executable)_linux --strip-unneeded \ No newline at end of file diff --git a/background.cpp b/background.cpp new file mode 100644 index 0000000..02a4462 --- /dev/null +++ b/background.cpp @@ -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(); +} \ No newline at end of file diff --git a/background.h b/background.h new file mode 100644 index 0000000..3bcedbb --- /dev/null +++ b/background.h @@ -0,0 +1,24 @@ +#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 \ No newline at end of file diff --git a/balloon.cpp b/balloon.cpp new file mode 100644 index 0000000..7ab3b4e --- /dev/null +++ b/balloon.cpp @@ -0,0 +1,469 @@ +#include "const.h" +#include "globals.h" +#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; +} \ No newline at end of file diff --git a/balloon.h b/balloon.h new file mode 100644 index 0000000..78741b2 --- /dev/null +++ b/balloon.h @@ -0,0 +1,148 @@ +#include "struct.h" +#include "sprite.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 \ No newline at end of file diff --git a/bullet.cpp b/bullet.cpp new file mode 100644 index 0000000..2d4952c --- /dev/null +++ b/bullet.cpp @@ -0,0 +1,192 @@ +#include "const.h" +#include "globals.h" +#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; +} diff --git a/bullet.h b/bullet.h new file mode 100644 index 0000000..63e6259 --- /dev/null +++ b/bullet.h @@ -0,0 +1,78 @@ +#include "struct.h" +#include "sprite.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 \ No newline at end of file diff --git a/const.h b/const.h new file mode 100644 index 0000000..ce2757e --- /dev/null +++ b/const.h @@ -0,0 +1,109 @@ +#include + +#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 \ No newline at end of file diff --git a/gamedirector.cpp b/gamedirector.cpp new file mode 100644 index 0000000..fae017d --- /dev/null +++ b/gamedirector.cpp @@ -0,0 +1,981 @@ +#include "const.h" +#include "struct.h" +#include "ltexture.h" +#include "globals.h" +#include "player.h" +#include "balloon.h" +#include "bullet.h" +#include "background.h" +#include "text.h" +#include "menu.h" +#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() +{ + bool result = false; + 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 + 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 + 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; + } +} \ No newline at end of file diff --git a/gamedirector.h b/gamedirector.h new file mode 100644 index 0000000..af6916d --- /dev/null +++ b/gamedirector.h @@ -0,0 +1,190 @@ +#include "player.h" +#include "balloon.h" +#include "bullet.h" +#include "background.h" +#include "text.h" +#include "menu.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 \ No newline at end of file diff --git a/globals.h b/globals.h new file mode 100644 index 0000000..22d1b48 --- /dev/null +++ b/globals.h @@ -0,0 +1,37 @@ +#include +#include +#include +#include "ltexture.h" + +#ifndef GLOBALS_H +#define GLOBALS_H + +//La ventana donde dibujamos +SDL_Window *gWindow = NULL; + +//El renderizador de la ventana +SDL_Renderer *gRenderer = NULL; + +//Texturas con gráficos +LTexture gPlayerTexture; +LTexture gGameBackgroundTexture; +LTexture gTitleBackgroundTexture; +LTexture gWhiteFontTexture; +LTexture gBlackFontTexture; +LTexture gMenuTexture; +LTexture gBalloonTexture; +LTexture gBulletTexture; +LTexture gMiscTexture; + +//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 \ No newline at end of file diff --git a/libFLAC-8.dll b/libFLAC-8.dll new file mode 100644 index 0000000..b56ea2a Binary files /dev/null and b/libFLAC-8.dll differ diff --git a/libjpeg-9.dll b/libjpeg-9.dll new file mode 100644 index 0000000..9d8911c Binary files /dev/null and b/libjpeg-9.dll differ diff --git a/libmodplug-1.dll b/libmodplug-1.dll new file mode 100644 index 0000000..d66a317 Binary files /dev/null and b/libmodplug-1.dll differ diff --git a/libmpg123-0.dll b/libmpg123-0.dll new file mode 100644 index 0000000..240298b Binary files /dev/null and b/libmpg123-0.dll differ diff --git a/libogg-0.dll b/libogg-0.dll new file mode 100644 index 0000000..233c0f4 Binary files /dev/null and b/libogg-0.dll differ diff --git a/libopus-0.dll b/libopus-0.dll new file mode 100644 index 0000000..94ea541 Binary files /dev/null and b/libopus-0.dll differ diff --git a/libopusfile-0.dll b/libopusfile-0.dll new file mode 100644 index 0000000..260796b Binary files /dev/null and b/libopusfile-0.dll differ diff --git a/libpng16-16.dll b/libpng16-16.dll new file mode 100644 index 0000000..fd5db8d Binary files /dev/null and b/libpng16-16.dll differ diff --git a/libtiff-5.dll b/libtiff-5.dll new file mode 100644 index 0000000..af3c3e6 Binary files /dev/null and b/libtiff-5.dll differ diff --git a/libvorbis-0.dll b/libvorbis-0.dll new file mode 100644 index 0000000..4e4aaa5 Binary files /dev/null and b/libvorbis-0.dll differ diff --git a/libvorbisfile-3.dll b/libvorbisfile-3.dll new file mode 100644 index 0000000..5d90a23 Binary files /dev/null and b/libvorbisfile-3.dll differ diff --git a/libwebp-7.dll b/libwebp-7.dll new file mode 100644 index 0000000..c11bf13 Binary files /dev/null and b/libwebp-7.dll differ diff --git a/ltexture.cpp b/ltexture.cpp new file mode 100644 index 0000000..fba3356 --- /dev/null +++ b/ltexture.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include "const.h" +#include "globals.h" +#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; +} \ No newline at end of file diff --git a/ltexture.h b/ltexture.h new file mode 100644 index 0000000..3473443 --- /dev/null +++ b/ltexture.h @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +#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 \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..9dd1dbc --- /dev/null +++ b/main.cpp @@ -0,0 +1,356 @@ +/* +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 +#include +#include +#include +#include +#include "const.h" +#include "struct.h" +#include "ltexture.h" +#include "globals.h" +#include "sprite.h" +#include "spriteanimated.h" +#include "player.h" +#include "balloon.h" +#include "bullet.h" +#include "background.h" +#include "text.h" +#include "menu.h" +#include "gamedirector.h" +#include "ltexture.cpp" +#include "sprite.cpp" +#include "spriteanimated.cpp" +#include "player.cpp" +#include "balloon.cpp" +#include "bullet.cpp" +#include "background.cpp" +#include "text.cpp" +#include "menu.cpp" +#include "gamedirector.cpp" + +//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; + } +} \ No newline at end of file diff --git a/media/.DS_Store b/media/.DS_Store new file mode 100644 index 0000000..a6a64ad Binary files /dev/null and b/media/.DS_Store differ diff --git a/media/fonts/font-8x8-fps_blanca.png b/media/fonts/font-8x8-fps_blanca.png new file mode 100644 index 0000000..197976d Binary files /dev/null and b/media/fonts/font-8x8-fps_blanca.png differ diff --git a/media/fonts/font-8x8-fps_negra.png b/media/fonts/font-8x8-fps_negra.png new file mode 100644 index 0000000..eb8bfa2 Binary files /dev/null and b/media/fonts/font-8x8-fps_negra.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/CREDIT.txt b/media/fonts/superpowers-asset-packs-fonts/CREDIT.txt new file mode 100644 index 0000000..a009275 --- /dev/null +++ b/media/fonts/superpowers-asset-packs-fonts/CREDIT.txt @@ -0,0 +1,10 @@ +The assets in this repository are created at Sparklin Labs by Pixel-boy: https://twitter.com/2pblog1 +Their creation is funded by your support on Patreon (http://patreon.com/SparklinLabs) and through donations (http://sparklinlabs.itch.io/superpowers) Thanks! + +Originally downloaded from https://github.com/sparklinlabs/superpowers-asset-packs + +Attribution/Licensing: + Creative Commons Zero: http://creativecommons.org/publicdomain/zero/1.0/ + Attribution is not required but appreciated. Placing a link to http://superpowers-html5.com/ somewhere would be awesome :) + +Also available at http://opengameart.org/content/superpowers-assets-bitmap-fonts \ No newline at end of file diff --git a/media/fonts/superpowers-asset-packs-fonts/LICENSE.txt b/media/fonts/superpowers-asset-packs-fonts/LICENSE.txt new file mode 100644 index 0000000..670154e --- /dev/null +++ b/media/fonts/superpowers-asset-packs-fonts/LICENSE.txt @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font-1-tds.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font-1-tds.png new file mode 100644 index 0000000..87fe2c2 Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font-1-tds.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font-1.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font-1.png new file mode 100644 index 0000000..1cca8f5 Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font-1.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font-16x16.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font-16x16.png new file mode 100644 index 0000000..8523fac Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font-16x16.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font-2-tds.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font-2-tds.png new file mode 100644 index 0000000..28294bc Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font-2-tds.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font-2.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font-2.png new file mode 100644 index 0000000..594f7dc Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font-2.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font-20x20-RPG.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font-20x20-RPG.png new file mode 100644 index 0000000..d710639 Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font-20x20-RPG.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font-20x20-shmup.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font-20x20-shmup.png new file mode 100644 index 0000000..2057a62 Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font-20x20-shmup.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font-20x20.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font-20x20.png new file mode 100644 index 0000000..782d49a Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font-20x20.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font-40x40-fps.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font-40x40-fps.png new file mode 100644 index 0000000..bb97d37 Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font-40x40-fps.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font-8x8-fps.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font-8x8-fps.png new file mode 100644 index 0000000..2ff9ddd Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font-8x8-fps.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font-number-40x40.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font-number-40x40.png new file mode 100644 index 0000000..ba02086 Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font-number-40x40.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font30x30.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font30x30.png new file mode 100644 index 0000000..b6807d2 Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font30x30.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/font8x8.png b/media/fonts/superpowers-asset-packs-fonts/fonts/font8x8.png new file mode 100644 index 0000000..5831a2f Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/font8x8.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/title-font-shmup.png b/media/fonts/superpowers-asset-packs-fonts/fonts/title-font-shmup.png new file mode 100644 index 0000000..33b4eac Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/title-font-shmup.png differ diff --git a/media/fonts/superpowers-asset-packs-fonts/fonts/title-font.png b/media/fonts/superpowers-asset-packs-fonts/fonts/title-font.png new file mode 100644 index 0000000..10ba2e8 Binary files /dev/null and b/media/fonts/superpowers-asset-packs-fonts/fonts/title-font.png differ diff --git a/media/gfx/background.aseprite b/media/gfx/background.aseprite new file mode 100644 index 0000000..a1b1657 Binary files /dev/null and b/media/gfx/background.aseprite differ diff --git a/media/gfx/background.png b/media/gfx/background.png new file mode 100644 index 0000000..bb4ab47 Binary files /dev/null and b/media/gfx/background.png differ diff --git a/media/gfx/balloon.aseprite b/media/gfx/balloon.aseprite new file mode 100644 index 0000000..5755d30 Binary files /dev/null and b/media/gfx/balloon.aseprite differ diff --git a/media/gfx/balloon.png b/media/gfx/balloon.png new file mode 100644 index 0000000..634f427 Binary files /dev/null and b/media/gfx/balloon.png differ diff --git a/media/gfx/black_font.aseprite b/media/gfx/black_font.aseprite new file mode 100644 index 0000000..821d5ae Binary files /dev/null and b/media/gfx/black_font.aseprite differ diff --git a/media/gfx/black_font.png b/media/gfx/black_font.png new file mode 100644 index 0000000..a6149cb Binary files /dev/null and b/media/gfx/black_font.png differ diff --git a/media/gfx/bullet.aseprite b/media/gfx/bullet.aseprite new file mode 100644 index 0000000..e8bb4e4 Binary files /dev/null and b/media/gfx/bullet.aseprite differ diff --git a/media/gfx/bullet.png b/media/gfx/bullet.png new file mode 100644 index 0000000..418a958 Binary files /dev/null and b/media/gfx/bullet.png differ diff --git a/media/gfx/menu.aseprite b/media/gfx/menu.aseprite new file mode 100644 index 0000000..7df1e54 Binary files /dev/null and b/media/gfx/menu.aseprite differ diff --git a/media/gfx/menu.png b/media/gfx/menu.png new file mode 100644 index 0000000..87db9cc Binary files /dev/null and b/media/gfx/menu.png differ diff --git a/media/gfx/misc.aseprite b/media/gfx/misc.aseprite new file mode 100644 index 0000000..1b6c2bb Binary files /dev/null and b/media/gfx/misc.aseprite differ diff --git a/media/gfx/misc.png b/media/gfx/misc.png new file mode 100644 index 0000000..6c6215c Binary files /dev/null and b/media/gfx/misc.png differ diff --git a/media/gfx/player.aseprite b/media/gfx/player.aseprite new file mode 100644 index 0000000..1c1289c Binary files /dev/null and b/media/gfx/player.aseprite differ diff --git a/media/gfx/player.png b/media/gfx/player.png new file mode 100644 index 0000000..7552ddd Binary files /dev/null and b/media/gfx/player.png differ diff --git a/media/gfx/title.aseprite b/media/gfx/title.aseprite new file mode 100644 index 0000000..8d04210 Binary files /dev/null and b/media/gfx/title.aseprite differ diff --git a/media/gfx/title.png b/media/gfx/title.png new file mode 100644 index 0000000..6f52cb5 Binary files /dev/null and b/media/gfx/title.png differ diff --git a/media/gfx/white_font.aseprite b/media/gfx/white_font.aseprite new file mode 100644 index 0000000..0afbdcd Binary files /dev/null and b/media/gfx/white_font.aseprite differ diff --git a/media/gfx/white_font.png b/media/gfx/white_font.png new file mode 100644 index 0000000..22f336d Binary files /dev/null and b/media/gfx/white_font.png differ diff --git a/media/music/.DS_Store b/media/music/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/media/music/.DS_Store differ diff --git a/media/music/playing.ogg b/media/music/playing.ogg new file mode 100644 index 0000000..75f86e7 Binary files /dev/null and b/media/music/playing.ogg differ diff --git a/media/music/title.ogg b/media/music/title.ogg new file mode 100644 index 0000000..4204e28 Binary files /dev/null and b/media/music/title.ogg differ diff --git a/media/resources/.DS_Store b/media/resources/.DS_Store new file mode 100644 index 0000000..2ea66a8 Binary files /dev/null and b/media/resources/.DS_Store differ diff --git a/media/resources/Action Force II.png b/media/resources/Action Force II.png new file mode 100644 index 0000000..7287f13 Binary files /dev/null and b/media/resources/Action Force II.png differ diff --git a/media/resources/Action Force.png b/media/resources/Action Force.png new file mode 100644 index 0000000..2bd7c2d Binary files /dev/null and b/media/resources/Action Force.png differ diff --git a/media/resources/Arcade - Super Pang - Balloons.png b/media/resources/Arcade - Super Pang - Balloons.png new file mode 100644 index 0000000..91e97ef Binary files /dev/null and b/media/resources/Arcade - Super Pang - Balloons.png differ diff --git a/media/resources/DNi183CUEAAETYM.png-large.png b/media/resources/DNi183CUEAAETYM.png-large.png new file mode 100644 index 0000000..05030ca Binary files /dev/null and b/media/resources/DNi183CUEAAETYM.png-large.png differ diff --git a/media/resources/PANG128K-200730-181353.png b/media/resources/PANG128K-200730-181353.png new file mode 100644 index 0000000..a69d0c5 Binary files /dev/null and b/media/resources/PANG128K-200730-181353.png differ diff --git a/media/resources/PANG128K-200731-193807.png b/media/resources/PANG128K-200731-193807.png new file mode 100644 index 0000000..e4de907 Binary files /dev/null and b/media/resources/PANG128K-200731-193807.png differ diff --git a/media/resources/PANG128K-200731-211743.png b/media/resources/PANG128K-200731-211743.png new file mode 100644 index 0000000..996d705 Binary files /dev/null and b/media/resources/PANG128K-200731-211743.png differ diff --git a/media/resources/PANG128K-200731-211824.png b/media/resources/PANG128K-200731-211824.png new file mode 100644 index 0000000..9a2847b Binary files /dev/null and b/media/resources/PANG128K-200731-211824.png differ diff --git a/media/resources/PANG128K-200731-211851.png b/media/resources/PANG128K-200731-211851.png new file mode 100644 index 0000000..fb72a93 Binary files /dev/null and b/media/resources/PANG128K-200731-211851.png differ diff --git a/media/resources/PANG128K-200731-211923.png b/media/resources/PANG128K-200731-211923.png new file mode 100644 index 0000000..5860020 Binary files /dev/null and b/media/resources/PANG128K-200731-211923.png differ diff --git a/media/resources/PANG128K-200731-211945.png b/media/resources/PANG128K-200731-211945.png new file mode 100644 index 0000000..060b09d Binary files /dev/null and b/media/resources/PANG128K-200731-211945.png differ diff --git a/media/resources/PANG128K-200731-212000.png b/media/resources/PANG128K-200731-212000.png new file mode 100644 index 0000000..43cf749 Binary files /dev/null and b/media/resources/PANG128K-200731-212000.png differ diff --git a/media/resources/Palette_NTSC.png b/media/resources/Palette_NTSC.png new file mode 100644 index 0000000..708ce24 Binary files /dev/null and b/media/resources/Palette_NTSC.png differ diff --git a/media/resources/SNES - Super Buster Bros Super Pang - Backgrounds.png b/media/resources/SNES - Super Buster Bros Super Pang - Backgrounds.png new file mode 100644 index 0000000..95e6603 Binary files /dev/null and b/media/resources/SNES - Super Buster Bros Super Pang - Backgrounds.png differ diff --git a/media/resources/balloon.png b/media/resources/balloon.png new file mode 100644 index 0000000..4cceac9 Binary files /dev/null and b/media/resources/balloon.png differ diff --git a/media/resources/balloon.pxd/QuickLook/Icon.tiff b/media/resources/balloon.pxd/QuickLook/Icon.tiff new file mode 100644 index 0000000..930f5e8 Binary files /dev/null and b/media/resources/balloon.pxd/QuickLook/Icon.tiff differ diff --git a/media/resources/balloon.pxd/QuickLook/Thumbnail.tiff b/media/resources/balloon.pxd/QuickLook/Thumbnail.tiff new file mode 100644 index 0000000..3c2a7d6 Binary files /dev/null and b/media/resources/balloon.pxd/QuickLook/Thumbnail.tiff differ diff --git a/media/resources/balloon.pxd/data/D8D4B8B0-ED78-4C66-AB6F-66A9AFCC7AEB b/media/resources/balloon.pxd/data/D8D4B8B0-ED78-4C66-AB6F-66A9AFCC7AEB new file mode 100644 index 0000000..3a16c7f Binary files /dev/null and b/media/resources/balloon.pxd/data/D8D4B8B0-ED78-4C66-AB6F-66A9AFCC7AEB differ diff --git a/media/resources/balloon.pxd/metadata.info b/media/resources/balloon.pxd/metadata.info new file mode 100644 index 0000000..4e5c49b Binary files /dev/null and b/media/resources/balloon.pxd/metadata.info differ diff --git a/media/resources/balloon2.png b/media/resources/balloon2.png new file mode 100644 index 0000000..46b239d Binary files /dev/null and b/media/resources/balloon2.png differ diff --git a/media/resources/balloon2.pxd/QuickLook/Icon.tiff b/media/resources/balloon2.pxd/QuickLook/Icon.tiff new file mode 100644 index 0000000..0d70ce5 Binary files /dev/null and b/media/resources/balloon2.pxd/QuickLook/Icon.tiff differ diff --git a/media/resources/balloon2.pxd/QuickLook/Thumbnail.tiff b/media/resources/balloon2.pxd/QuickLook/Thumbnail.tiff new file mode 100644 index 0000000..146b830 Binary files /dev/null and b/media/resources/balloon2.pxd/QuickLook/Thumbnail.tiff differ diff --git a/media/resources/balloon2.pxd/data/2F9766E5-E908-4B49-A1CD-AFCAFAC73C08 b/media/resources/balloon2.pxd/data/2F9766E5-E908-4B49-A1CD-AFCAFAC73C08 new file mode 100644 index 0000000..41347ea Binary files /dev/null and b/media/resources/balloon2.pxd/data/2F9766E5-E908-4B49-A1CD-AFCAFAC73C08 differ diff --git a/media/resources/balloon2.pxd/data/35391D99-93B6-498A-B9D3-11580AFA8719 b/media/resources/balloon2.pxd/data/35391D99-93B6-498A-B9D3-11580AFA8719 new file mode 100644 index 0000000..836ce2b Binary files /dev/null and b/media/resources/balloon2.pxd/data/35391D99-93B6-498A-B9D3-11580AFA8719 differ diff --git a/media/resources/balloon2.pxd/data/37C244B5-FDC9-4C04-97E6-33CE13FD74B5 b/media/resources/balloon2.pxd/data/37C244B5-FDC9-4C04-97E6-33CE13FD74B5 new file mode 100644 index 0000000..76b0e1a Binary files /dev/null and b/media/resources/balloon2.pxd/data/37C244B5-FDC9-4C04-97E6-33CE13FD74B5 differ diff --git a/media/resources/balloon2.pxd/data/82DB9AF2-2792-4B98-93F7-8E6B17147D37 b/media/resources/balloon2.pxd/data/82DB9AF2-2792-4B98-93F7-8E6B17147D37 new file mode 100644 index 0000000..22fbb08 Binary files /dev/null and b/media/resources/balloon2.pxd/data/82DB9AF2-2792-4B98-93F7-8E6B17147D37 differ diff --git a/media/resources/balloon2.pxd/data/selection/meta b/media/resources/balloon2.pxd/data/selection/meta new file mode 100644 index 0000000..76a4034 --- /dev/null +++ b/media/resources/balloon2.pxd/data/selection/meta @@ -0,0 +1,33 @@ + + + + + backingScale + 1 + mode + 0 + shapeSelectionFilename + shapeSelection + size + + NC10UHpTVFAQAAAAQCAAAAAAAABAIgAAAAAAAA== + + softness + 0.0 + timestamp + 617963639.40729403 + transform + + 1 + 0.0 + 0.0 + 1 + 0.0 + 0.0 + 0.0 + 0.0 + + version + 2 + + diff --git a/media/resources/balloon2.pxd/data/selection/shapeSelection/meta b/media/resources/balloon2.pxd/data/selection/shapeSelection/meta new file mode 100644 index 0000000..0acda1a --- /dev/null +++ b/media/resources/balloon2.pxd/data/selection/shapeSelection/meta @@ -0,0 +1,12 @@ + + + + + backingScale + 1 + pathFilename + path + version + 1 + + diff --git a/media/resources/balloon2.pxd/data/selection/shapeSelection/path b/media/resources/balloon2.pxd/data/selection/shapeSelection/path new file mode 100644 index 0000000..5c54dd6 Binary files /dev/null and b/media/resources/balloon2.pxd/data/selection/shapeSelection/path differ diff --git a/media/resources/balloon2.pxd/metadata.info b/media/resources/balloon2.pxd/metadata.info new file mode 100644 index 0000000..3bb973c Binary files /dev/null and b/media/resources/balloon2.pxd/metadata.info differ diff --git a/media/resources/fondo.png b/media/resources/fondo.png new file mode 100644 index 0000000..734c049 Binary files /dev/null and b/media/resources/fondo.png differ diff --git a/media/resources/fondo.pxm b/media/resources/fondo.pxm new file mode 100644 index 0000000..6127737 Binary files /dev/null and b/media/resources/fondo.pxm differ diff --git a/media/resources/fondo2.png b/media/resources/fondo2.png new file mode 100644 index 0000000..611e049 Binary files /dev/null and b/media/resources/fondo2.png differ diff --git a/media/resources/fondo3.png b/media/resources/fondo3.png new file mode 100644 index 0000000..f7dfa17 Binary files /dev/null and b/media/resources/fondo3.png differ diff --git a/media/resources/font_8px_blanca.png b/media/resources/font_8px_blanca.png new file mode 100644 index 0000000..197976d Binary files /dev/null and b/media/resources/font_8px_blanca.png differ diff --git a/media/resources/font_8px_blanca2.pxm b/media/resources/font_8px_blanca2.pxm new file mode 100644 index 0000000..4b9072e Binary files /dev/null and b/media/resources/font_8px_blanca2.pxm differ diff --git a/media/resources/font_8px_negra.png b/media/resources/font_8px_negra.png new file mode 100644 index 0000000..eb8bfa2 Binary files /dev/null and b/media/resources/font_8px_negra.png differ diff --git a/media/resources/marcador.png b/media/resources/marcador.png new file mode 100644 index 0000000..68c7fc8 Binary files /dev/null and b/media/resources/marcador.png differ diff --git a/media/resources/menu.pxm b/media/resources/menu.pxm new file mode 100644 index 0000000..d65e2f8 Binary files /dev/null and b/media/resources/menu.pxm differ diff --git a/media/resources/nokia_cellphone/nokiafc22.ttf b/media/resources/nokia_cellphone/nokiafc22.ttf new file mode 100644 index 0000000..9dd011a Binary files /dev/null and b/media/resources/nokia_cellphone/nokiafc22.ttf differ diff --git a/media/resources/nokia_cellphone/nokiafc22.txt b/media/resources/nokia_cellphone/nokiafc22.txt new file mode 100644 index 0000000..e0546cd --- /dev/null +++ b/media/resources/nokia_cellphone/nokiafc22.txt @@ -0,0 +1,127 @@ +============================================================================== +NOKIA CELLPHONE FC SMALL +======================== + + +============================================================================== +Info +==== + +This is a font that emulates the bitmap font used by Nokia-based cell phones. +As the name implies ("Nokia Cellphone Small"), this is the "Small" font - used +on some menus, not the data fields (which it used a "big" font). + +This was done because 1) I needed to use it on some projects and 2) I saw lots +of people asking for a font like this. So I had some experience in creating +bitmap-emulating truetype fonts (that is, a truetype, vector-based font that +works as if it was a bitmap-based font) and then I decided to do this thingie. +I send a message to my Nokia 6120 cell phone with every characters that the +cell phone had and then scanned the cellphone screens to rebuild it using +fontlab 3 and 4. + + +============================================================================== +How to use (read it please) +=========================== + +This is a "bitmap" font, a truetype font that emulates real bitmap fonts (with +no antialias, that is). It should be used at the same point size (8) or +multiples thereof (16, 24, 32) to produce the best result. When used properly, +it renders as the font found on the Nokia cellphones software. + +Here's some specific hints: + +Photoshop 5: use it as a normal font, with no antialias. The underline is way +too low, but I can't fix it. + +Photoshop 7: use it as a normal font, with no antialias. If you're +experiencing variating vertical positions for the underline, use a fixed +leading/line spacing (10, for example) instead of the "auto" mode. + +Flash: use it normally. It will not produce antialias as long as you position +your textfield on "rounded" pixels, related to the main flash stage. To do +this, draw/type your textfield on stage, go to the "Info" panel, and be sure +the topmost axis is selected (little black box) and its X and Y position are +set to a position with no decimal points (e.g., 10 and 8 instead of 10.1 and +8.5). You can embed the fonts too, *NO* antialias will occur as long as you use +it on the right positions. + + +============================================================================== +Modifications +============= + +* VERSION 2.2 - A minor correction on wordspacing which got increased on the +last version. Now it's correct again (from 5 to 4 pixels). + +* VERSION 2.1 - Small additions, due to a BIG help by Panu Tuominen from +PanuWorld (www.panuworld.net). Added characters: + + Ý ý - Y/y with acute + Å å - A/a with ring + Ÿ ÿ - Y/y with diaeresis (Y being *done from certain clues* - not sure it's right, but it probably is) + ` - grave accent (unicode 0060) + +* VERSION 2.0 - Took it to a new metric system (more fit for "bitmap fonts"), +fixed lots of small polygon discrepancies, and fixed some Flash filling holes +bugs. I've changed the leading too; since there's no standard leading on the +cellphone menus I've chosen one of my own. + +Also, since I got a new Nokia (3310) cellphone, there's ton of new characters +available that I have added to the font. There are now 164 glyphs on the Nokia +cellphone truetype font. Here's what have been added: + + Ä ä - A/a with diaeresis + È è - E/e with grave + Ë ë - E/e with diaeresis + Ï ï - I/i with diaeresis + Î î - I/i with circumflex + Ò ò - O/o with grave + Ö ö - O/o with diaeresis + Ù ù - U/u with grave + Û û - U/u with circumflex + Ñ ñ - N/n with tilde + Ø ø - O/o with slash/stroke + * * - G/g with breve (turkish codepage) + ¤ - currency sign + Æ - latin capital letter AE + æ - latin small letter AE + ß - greek beta (I think) + € - Euro + +* VERSION 1.4 - Fixed the WORDSPACE and LEADING size. Thanks to Gustavo Rodrigues +(from www.escritaurbana.com.br) for pointing me my mistakes. I also fixed some +mistakes on the documentation (this file). + +* VERSION 1.2 - Optimized for Macromedia Flash usage (no hollows) and with +a MAC TTF version provided by Chris Moritz (members.home.net/fieldofaction3). + + +============================================================================== +Copyright and stuff +=================== + +This is a free font/file, distribute as you wish to who you wish. Do NOT sell +this font within a CD or any other media; it's not yours and you can't make +money of it. You'd rather ask me first via email, I may probably let you do it +as long as it's for a good cause. + +I don't know if the original Nokia font has some copyright which prevents +people from making new fonts based on it. I hope not. Anyways, buy a Nokia, +and I think everything's gonna be alright. + +Special thanks on this version go out to Carlos Bêla (www.goldenshower.gs) and +Diogo Kalil (www.sincolor.com.br) for helping me out with the Mac version of +the font. It has been extensively tested to ensure it's as smooth (hint, +kerning, spacing and aliasing-wise) as the pc one is. + + +============================================================================== +Author +====== + +This font was done by Zeh Fernando on Fontlab 4 (www.fontlab.com) on a PC. + +Zeh Fernando +zeh@fatorcaos.com.br +www.fatorcaos.com.br diff --git a/media/resources/pear36-32x.png b/media/resources/pear36-32x.png new file mode 100644 index 0000000..c92a859 Binary files /dev/null and b/media/resources/pear36-32x.png differ diff --git a/media/resources/photo_2020-07-23_08-22-30.jpg b/media/resources/photo_2020-07-23_08-22-30.jpg new file mode 100644 index 0000000..867a405 Binary files /dev/null and b/media/resources/photo_2020-07-23_08-22-30.jpg differ diff --git a/media/resources/pixel-gradient-vector-11276347.jpg b/media/resources/pixel-gradient-vector-11276347.jpg new file mode 100644 index 0000000..f0f3c92 Binary files /dev/null and b/media/resources/pixel-gradient-vector-11276347.jpg differ diff --git a/media/resources/player.png b/media/resources/player.png new file mode 100644 index 0000000..7745487 Binary files /dev/null and b/media/resources/player.png differ diff --git a/media/resources/player2.png b/media/resources/player2.png new file mode 100644 index 0000000..0041a5a Binary files /dev/null and b/media/resources/player2.png differ diff --git a/media/resources/player24.png b/media/resources/player24.png new file mode 100644 index 0000000..d7686f3 Binary files /dev/null and b/media/resources/player24.png differ diff --git a/media/resources/player24.pxm b/media/resources/player24.pxm new file mode 100644 index 0000000..e7f1247 Binary files /dev/null and b/media/resources/player24.pxm differ diff --git a/media/resources/sprite.png b/media/resources/sprite.png new file mode 100644 index 0000000..8fd3dd3 Binary files /dev/null and b/media/resources/sprite.png differ diff --git a/media/resources/title 3.pxm b/media/resources/title 3.pxm new file mode 100644 index 0000000..dc4c54f Binary files /dev/null and b/media/resources/title 3.pxm differ diff --git a/media/resources/title 4.png b/media/resources/title 4.png new file mode 100644 index 0000000..816fd15 Binary files /dev/null and b/media/resources/title 4.png differ diff --git a/media/resources/title.afdesign b/media/resources/title.afdesign new file mode 100644 index 0000000..52dce44 Binary files /dev/null and b/media/resources/title.afdesign differ diff --git a/media/resources/title.png b/media/resources/title.png new file mode 100644 index 0000000..bd5d5e0 Binary files /dev/null and b/media/resources/title.png differ diff --git a/media/resources/title.svg b/media/resources/title.svg new file mode 100644 index 0000000..ecb7cef --- /dev/null +++ b/media/resources/title.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/media/resources/title2.png b/media/resources/title2.png new file mode 100644 index 0000000..05de8e7 Binary files /dev/null and b/media/resources/title2.png differ diff --git a/media/resources/title2.pxm b/media/resources/title2.pxm new file mode 100644 index 0000000..cbebec6 Binary files /dev/null and b/media/resources/title2.pxm differ diff --git a/media/resources/title3.png b/media/resources/title3.png new file mode 100644 index 0000000..11db4d3 Binary files /dev/null and b/media/resources/title3.png differ diff --git a/media/sound/.DS_Store b/media/sound/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/media/sound/.DS_Store differ diff --git a/media/sound/balloon.wav b/media/sound/balloon.wav new file mode 100644 index 0000000..e9e654e Binary files /dev/null and b/media/sound/balloon.wav differ diff --git a/media/sound/bullet.wav b/media/sound/bullet.wav new file mode 100644 index 0000000..d4bb34e Binary files /dev/null and b/media/sound/bullet.wav differ diff --git a/menu.cpp b/menu.cpp new file mode 100644 index 0000000..64a7049 --- /dev/null +++ b/menu.cpp @@ -0,0 +1,198 @@ +#include "const.h" +#include "globals.h" +#include "text.h" +#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 (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(); + } +} \ No newline at end of file diff --git a/menu.h b/menu.h new file mode 100644 index 0000000..45fc6a0 --- /dev/null +++ b/menu.h @@ -0,0 +1,88 @@ +#include "sprite.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 \ No newline at end of file diff --git a/player.cpp b/player.cpp new file mode 100644 index 0000000..d62cba7 --- /dev/null +++ b/player.cpp @@ -0,0 +1,254 @@ +#include "const.h" +#include "globals.h" +#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); +} \ No newline at end of file diff --git a/player.h b/player.h new file mode 100644 index 0000000..d372c9a --- /dev/null +++ b/player.h @@ -0,0 +1,109 @@ +#include "struct.h" +#include "spriteanimated.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 \ No newline at end of file diff --git a/sprite.cpp b/sprite.cpp new file mode 100644 index 0000000..db558ad --- /dev/null +++ b/sprite.cpp @@ -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; +} \ No newline at end of file diff --git a/sprite.h b/sprite.h new file mode 100644 index 0000000..87a4232 --- /dev/null +++ b/sprite.h @@ -0,0 +1,71 @@ +#include +#include +#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 \ No newline at end of file diff --git a/spriteanimated.cpp b/spriteanimated.cpp new file mode 100644 index 0000000..dbcc781 --- /dev/null +++ b/spriteanimated.cpp @@ -0,0 +1,90 @@ +#include "const.h" +#include "spriteanimated.h" + +#include + +//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]; +} \ No newline at end of file diff --git a/spriteanimated.h b/spriteanimated.h new file mode 100644 index 0000000..5840c08 --- /dev/null +++ b/spriteanimated.h @@ -0,0 +1,57 @@ +#include +#include +#include "sprite.h" + +#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 \ No newline at end of file diff --git a/struct.h b/struct.h new file mode 100644 index 0000000..3ae9fff --- /dev/null +++ b/struct.h @@ -0,0 +1,12 @@ +#ifndef STRUCT_H +#define STRUCT_H + +//Estructura para definir un circulo +struct Circle +{ + Uint16 x; + Uint16 y; + Uint8 r; +}; + +#endif \ No newline at end of file diff --git a/text.cpp b/text.cpp new file mode 100644 index 0000000..eaf29bf --- /dev/null +++ b/text.cpp @@ -0,0 +1,50 @@ +#include "const.h" +#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(); + } +} \ No newline at end of file diff --git a/text.h b/text.h new file mode 100644 index 0000000..0f56af8 --- /dev/null +++ b/text.h @@ -0,0 +1,31 @@ +#include "sprite.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 \ No newline at end of file diff --git a/zlib1.dll b/zlib1.dll new file mode 100644 index 0000000..3a45deb Binary files /dev/null and b/zlib1.dll differ