update 19-02-21

This commit is contained in:
2021-02-19 21:45:04 +01:00
parent 06bbb22ce5
commit 04c1df4352
4 changed files with 944 additions and 121 deletions

View File

@@ -5,16 +5,6 @@
#ifndef CONST_H #ifndef CONST_H
#define CONST_H #define CONST_H
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
#define min(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
const Uint8 GAME_SPEED = 24; //16 = normal-rapid, 24 = normal. Quan menor, m<>s r<>pid const Uint8 GAME_SPEED = 24; //16 = normal-rapid, 24 = normal. Quan menor, m<>s r<>pid
const Uint8 UP = 0; const Uint8 UP = 0;
@@ -133,25 +123,267 @@ const Uint8 ZONE_VOLCANO = 1;
const std::string WINDOW_TITLE = "Volcano v0005"; const std::string WINDOW_TITLE = "Volcano v0005";
const std::string BUILD = ".05"; const std::string BUILD = ".05";
const std::string FILE_MAP_VOLCANO = "../data/volcano.map";
const std::string FILE_TILES_VOLCANO = "../media/gfx/tiles_volcano.png"; // Recursos
const std::string FILE_TILES_SURFACE = "../media/gfx/tiles_surface.png"; const Uint8 FILE_MAP_VOLCANO = 0;
const std::string FILE_BKG_SURFACE = "../media/gfx/bkg_surface.png"; const Uint8 FILE_CONFIG = 1;
const std::string FILE_MENU = "../media/gfx/menu.png";
const std::string FILE_MENU_ANIMATION = "../media/gfx/menu_animation.png"; const Uint8 TOTAL_FILE = 2;
const std::string FILE_ACTORS = "../media/gfx/actors.png";
const std::string FILE_PLAYER = "../media/gfx/player.png"; const Uint8 TEXTURE_ACTORS = 0;
const std::string FILE_HUD = "../media/gfx/hud.png"; const Uint8 TEXTURE_BKG_SURFACE = 1;
const std::string FILE_FILTER = "../media/gfx/filter.png"; const Uint8 TEXTURE_FILTER = 2;
const std::string FILE_SOUND_JUMP = "../media/sound/sound_player_jump.wav"; const Uint8 TEXTURE_HUD = 3;
const std::string FILE_SOUND_DEATH = "../media/sound/sound_player_death.wav"; const Uint8 TEXTURE_MENU = 4;
const std::string FILE_SOUND_COIN = "../media/sound/sound_player_coin.wav"; const Uint8 TEXTURE_MENU_ANIMATION = 5;
const std::string FILE_SOUND_MENU_LOGO = "../media/sound/sound_menu_logo.wav"; const Uint8 TEXTURE_PLAYER = 6;
const std::string FILE_SOUND_MENU_START = "../media/sound/sound_menu_start.wav"; const Uint8 TEXTURE_TILES_SURFACE = 7;
const std::string FILE_SOUND_DROP_ENEMY = "../media/sound/sound_drop_enemy.wav"; const Uint8 TEXTURE_TILES_VOLCANO = 8;
const std::string FILE_SOUND_DROP_SPLAT = "../media/sound/sound_drop_splat.wav";
const std::string FILE_MUSIC_SURFACE = "../media/music/music_surface.ogg"; const Uint8 TOTAL_TEXTURE = 9;
const std::string FILE_MUSIC_VOLCANO = "../media/music/music_volcano.ogg";
const std::string FILE_MUSIC_MENU = "../media/music/music_menu.ogg"; const Uint8 SOUND_COIN = 0;
const Uint8 SOUND_DEATH = 1;
const Uint8 SOUND_DROP_ENEMY = 2;
const Uint8 SOUND_DROP_SPLAT = 3;
const Uint8 SOUND_JUMP = 4;
const Uint8 SOUND_MENU_LOGO = 5;
const Uint8 SOUND_MENU_START = 6;
const Uint8 TOTAL_SOUND = 7;
const Uint8 MUSIC_MENU = 0;
const Uint8 MUSIC_SURFACE = 1;
const Uint8 MUSIC_VOLCANO = 2;
const Uint8 TOTAL_MUSIC = 3;
///////////////////////////////COFFEE CRISIS///////////////////
// Textos
#define WINDOW_CAPTION "Coffee Crisis"
#define TEXT_COPYRIGHT "@2016,2021 JAILDESIGNER (V0.5)"
// Tamaño de bloque
const Uint8 BLOCK = 8;
const Uint8 HALF_BLOCK = BLOCK / 2;
// Tamaño de la pantalla real
const int SCREEN_WIDTH = 256;
const int SCREEN_HEIGHT = SCREEN_WIDTH * 3 / 4; // 192
// Tamaño de la pantalla que se muestra
const int VIEW_WIDTH = SCREEN_WIDTH * 3; // 768
const int VIEW_HEIGHT = SCREEN_HEIGHT * 3; // 576
// Cantidad de enteros a escribir en los ficheros de datos
const Uint8 TOTAL_SCORE_DATA = 3;
const Uint16 TOTAL_DEMO_DATA = 2000;
// Zona de juego
const int PLAY_AREA_TOP = (0 * BLOCK);
const int PLAY_AREA_BOTTOM = SCREEN_HEIGHT - (4 * BLOCK);
const int PLAY_AREA_LEFT = (0 * BLOCK);
const int PLAY_AREA_RIGHT = SCREEN_WIDTH - (0 * BLOCK);
const int PLAY_AREA_WIDTH = PLAY_AREA_RIGHT - PLAY_AREA_LEFT;
const int PLAY_AREA_HEIGHT = PLAY_AREA_BOTTOM - PLAY_AREA_TOP;
const int PLAY_AREA_CENTER_X = PLAY_AREA_LEFT + (PLAY_AREA_WIDTH / 2);
const int PLAY_AREA_CENTER_Y = PLAY_AREA_TOP + (PLAY_AREA_HEIGHT / 2);
const int PLAY_AREA_FIRST_QUARTER_Y = PLAY_AREA_HEIGHT / 4;
const int PLAY_AREA_THIRD_QUARTER_Y = (PLAY_AREA_HEIGHT / 4) * 3;
// Anclajes de pantalla
const int SCREEN_CENTER_X = SCREEN_WIDTH / 2;
const int SCREEN_FIRST_QUARTER_X = SCREEN_WIDTH / 4;
const int SCREEN_THIRD_QUARTER_X = (SCREEN_WIDTH / 4) * 3;
const int SCREEN_CENTER_Y = SCREEN_HEIGHT / 2;
const int SCREEN_FIRST_QUARTER_Y = SCREEN_HEIGHT / 4;
const int SCREEN_THIRD_QUARTER_Y = (SCREEN_HEIGHT / 4) * 3;
// Color transparente para los sprites
const Uint8 COLOR_KEY_R = 0xff;
const Uint8 COLOR_KEY_G = 0x00;
const Uint8 COLOR_KEY_B = 0xff;
// Opciones de menu
const int MENU_NO_OPTION = -1;
const int MENU_OPTION_START = 0;
const int MENU_OPTION_QUIT = 1;
const int MENU_OPTION_TOTAL = 2;
// Selector de menu
const int MENU_SELECTOR_BLACK = (BLOCK * 0);
const int MENU_SELECTOR_WHITE = (BLOCK * 1);
// Tipos de fondos para el menu
const int MENU_BACKGROUND_TRANSPARENT = 0;
const int MENU_BACKGROUND_SOLID = 1;
// Estados del jugador
const Uint8 PLAYER_STATUS_WALKING_LEFT = 0;
const Uint8 PLAYER_STATUS_WALKING_RIGHT = 1;
const Uint8 PLAYER_STATUS_WALKING_STOP = 2;
const Uint8 PLAYER_STATUS_FIRING_UP = 0;
const Uint8 PLAYER_STATUS_FIRING_LEFT = 1;
const Uint8 PLAYER_STATUS_FIRING_RIGHT = 2;
const Uint8 PLAYER_STATUS_FIRING_NO = 3;
const Uint8 PLAYER_ANIMATION_LEGS_WALKING_LEFT = 0;
const Uint8 PLAYER_ANIMATION_LEGS_WALKING_RIGHT = 1;
const Uint8 PLAYER_ANIMATION_LEGS_WALKING_STOP = 2;
const Uint8 PLAYER_ANIMATION_BODY_WALKING_LEFT = 0;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_LEFT = 1;
const Uint8 PLAYER_ANIMATION_BODY_WALKING_RIGHT = 2;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_RIGHT = 3;
const Uint8 PLAYER_ANIMATION_BODY_WALKING_STOP = 4;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_UP = 5;
const Uint8 PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT = 6;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT = 7;
const Uint8 PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT = 8;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT = 9;
const Uint8 PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT = 10;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT = 11;
// Variables del jugador
const Uint16 PLAYER_INVULNERABLE_TIMER = 200;
// Estados del juego
const Uint8 GAME_SECTION_TITLE = 0;
const Uint8 GAME_SECTION_PLAYING = 1;
const Uint8 GAME_SECTION_QUIT = 2;
const Uint8 GAME_SECTION_GAME_OVER_SCREEN = 3;
const Uint8 GAME_SECTION_INTRO = 4;
const Uint8 GAME_SECTION_DEMO = 5;
const Uint8 GAME_SECTION_INSTRUCTIONS = 6;
const Uint8 GAME_SECTION_LOGO = 7;
const Uint8 GAME_SECTION_INIT = 8;
// Estados de cada elemento que pertenece a un evento
const Uint8 EVENT_WAITING = 1;
const Uint8 EVENT_RUNNING = 2;
const Uint8 EVENT_COMPLETED = 3;
// Cantidad de eventos de la intro
const Uint8 INTRO_TOTAL_BITMAPS = 6;
const Uint8 INTRO_TOTAL_TEXTS = 9;
const Uint8 INTRO_TOTAL_EVENTS = INTRO_TOTAL_BITMAPS + INTRO_TOTAL_TEXTS;
// Cantidad de eventos de la pantalla de titulo
const Uint8 TITLE_TOTAL_EVENTS = 2;
// Relaciones de Id con nomnbres
const Uint8 BITMAP0 = 0;
const Uint8 BITMAP1 = 1;
const Uint8 BITMAP2 = 2;
const Uint8 BITMAP3 = 3;
const Uint8 BITMAP4 = 4;
const Uint8 BITMAP5 = 5;
const Uint8 TEXT0 = 6;
const Uint8 TEXT1 = 7;
const Uint8 TEXT2 = 8;
const Uint8 TEXT3 = 9;
const Uint8 TEXT4 = 10;
const Uint8 TEXT5 = 11;
const Uint8 TEXT6 = 12;
const Uint8 TEXT7 = 13;
const Uint8 TEXT8 = 14;
// Anclajes para el marcador de puntos
const int SCORE_WORD_X = (SCREEN_WIDTH / 4) - ((5 * BLOCK) / 2);
const int SCORE_WORD_Y = SCREEN_HEIGHT - (3 * BLOCK) + 2;
const int SCORE_NUMBER_X = (SCREEN_WIDTH / 4) - ((6 * BLOCK) / 2);
const int SCORE_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
const int HISCORE_WORD_X = ((SCREEN_WIDTH / 4) * 3) - ((8 * BLOCK) / 2);
const int HISCORE_WORD_Y = SCREEN_HEIGHT - (3 * BLOCK) + 2;
const int HISCORE_NUMBER_X = ((SCREEN_WIDTH / 4) * 3) - ((6 * BLOCK) / 2);
const int HISCORE_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
const int MULTIPLIER_WORD_X = (SCREEN_WIDTH / 2) - ((4 * BLOCK) / 2);
const int MULTIPLIER_WORD_Y = SCREEN_HEIGHT - (3 * BLOCK) + 2;
const int MULTIPLIER_NUMBER_X = (SCREEN_WIDTH / 2) - ((3 * BLOCK) / 2);;
const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
// Ningun tipo
const Uint8 NO_KIND = 0;
// Tipos de globo
const Uint8 BALLOON_1 = 1;
const Uint8 BALLOON_2 = 2;
const Uint8 BALLOON_3 = 3;
const Uint8 BALLOON_4 = 4;
// Velocidad del globo
const float BALLON_VELX_POSITIVE = 0.7f;
const float BALLON_VELX_NEGATIVE = -0.7f;
// Indice para las animaciones de los globos
const Uint8 BALLOON_MOVING_ANIMATION = 0;
const Uint8 BALLOON_POP_ANIMATION = 1;
const Uint8 BALLOON_BORN_ANIMATION = 2;
// Cantidad posible de globos
const Uint8 MAX_BALLOONS = 75;
// Tipos de bala
const Uint8 BULLET_UP = 1;
const Uint8 BULLET_LEFT = 2;
const Uint8 BULLET_RIGHT = 3;
// Cantidad posible de globos
const Uint8 MAX_BULLETS = 50;
// Tipos de objetos
const Uint8 ITEM_POINTS_1_DISK = 1;
const Uint8 ITEM_POINTS_2_GAVINA = 2;
const Uint8 ITEM_POINTS_3_PACMAR = 3;
const Uint8 ITEM_CLOCK = 4;
const Uint8 ITEM_TNT = 5;
const Uint8 ITEM_COFFEE = 6;
// Cantidad de objetos simultaneos
const Uint8 MAX_ITEMS = 5;
// Valores para las variables asociadas a los objetos
const Uint8 REMAINING_EXPLOSIONS = 3;
const Uint8 REMAINING_EXPLOSIONS_TIMER = 50;
const Uint16 TIME_STOPPED_TIMER = 300;
// Estados de entrada
const Uint8 NO_INPUT = 0;
const Uint8 INPUT_UP = 1;
const Uint8 INPUT_DOWN = 2;
const Uint8 INPUT_LEFT = 3;
const Uint8 INPUT_RIGHT = 4;
const Uint8 INPUT_ACCEPT = 5;
const Uint8 INPUT_CANCEL = 6;
const Uint8 INPUT_FIRE_UP = 7;
const Uint8 INPUT_FIRE_LEFT = 8;
const Uint8 INPUT_FIRE_RIGHT = 9;
const Uint8 INPUT_PAUSE = 10;
// Zona muerta del mando analógico
const int JOYSTICK_DEAD_ZONE = 8000;
// Tipos de mensajes para el retorno de las funciones
const Uint8 MSG_OK = 0;
const Uint8 MSG_BULLET_OUT = 1;
// Tipos de texto
const Uint8 TEXT_FIXED = 0;
const Uint8 TEXT_VARIABLE = 1;
// Cantidad de elementos del vector de SmartSprites
const Uint8 MAX_SMART_SPRITES = 10;
// Contadores
const Uint16 TITLE_TIMER = 800;
const Uint8 STAGE_COUNTER = 200;
const Uint16 INSTRUCTIONS_COUNTER = 600;
const Uint16 DEATH_COUNTER = 350;
#endif #endif

500
source/game.cpp Normal file
View File

@@ -0,0 +1,500 @@
#include "const.h"
#include "struct.h"
#include "game.h"
#include <iostream>
const Uint8 *keystates;
// Constructor
Game::Game()
{
}
Game::~Game()
{
}
// Iniciador
void Game::init()
{
}
// Arranca SDL y crea la ventana
bool Game::initSDL()
{
// Indicador de inicialización
bool success = true;
// Inicializa SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_HAPTIC) < 0)
{
printf("SDL could not initialize!\nSDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
// Establece el filtro de la textura a nearest
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"))
{
printf("Warning: Nearest texture filtering not enabled!\n");
}
// Inicializa jail_audio
JA_Init(48000, AUDIO_S16, 2);
// Comprueba si hay algun mando conectado
if (SDL_NumJoysticks() < 1)
{
printf("Warning: No joysticks connected!\n");
mGameControllerFound = false;
}
else
{
// Carga el mando
mGameController = SDL_JoystickOpen(0);
mGameControllerFound = true;
if (mGameController == NULL)
{
printf("Warning: Unable to open game controller!\nSDL Error: %s\n", SDL_GetError());
mGameControllerFound = false;
}
else
{
printf("%i joysticks were found.\n", SDL_NumJoysticks());
std::cout << SDL_JoystickNumButtons(mGameController) << " buttons\n";
//Get controller haptic device
mControllerHaptic = SDL_HapticOpenFromJoystick(mGameController);
if (mControllerHaptic == NULL)
{
printf("Warning: Controller does not support haptics!\nSDL Error: %s\n", SDL_GetError());
}
else
{
printf("Haptics detected\n");
//Get initialize rumble
if (SDL_HapticRumbleInit(mControllerHaptic) < 0)
{
printf("Warning: Unable to initialize rumble!\nSDL Error: %s\n", SDL_GetError());
}
}
}
}
// Crea la ventana
mWindow = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, VIEW_WIDTH, VIEW_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
if (mWindow == NULL)
{
printf("Window could not be created!\nSDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
// Crea un renderizador para la ventana con vsync
mRenderer = SDL_CreateRenderer(mWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (mRenderer == NULL)
{
printf("Renderer could not be created!\nSDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
// Inicializa el color de renderizado
SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF);
// Establece el tamaño del buffer de renderizado
SDL_RenderSetLogicalSize(mRenderer, SCREEN_WIDTH, SCREEN_HEIGHT);
// Establece el modo de mezcla
SDL_SetRenderDrawBlendMode(mRenderer, SDL_BLENDMODE_BLEND);
}
// Crea un backbuffer para el renderizador
mBackbuffer = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT);
if (mBackbuffer == NULL)
{
printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError());
success = false;
}
}
}
printf("\n");
return success;
}
// Crea el indice de ficheros
void Game::setFileList()
{
// Ficheros binarios
mResource.file[FILE_MAP_VOLCANO].file = mGame.path + "/" + "../data/volcano.map";
mResource.file[FILE_CONFIG].file = mGame.path + "/" + "../data/config.bin";
// Texturas
mResource.texture[TEXTURE_ACTORS].file = mGame.path + "/" + "../media/gfx/actors.png";
mResource.texture[TEXTURE_BKG_SURFACE].file = mGame.path + "/" + "../media/gfx/bkg_surface.png";
mResource.texture[TEXTURE_FILTER].file = mGame.path + "/" + "../media/gfx/filter.png";
mResource.texture[TEXTURE_HUD].file = mGame.path + "/" + "../media/gfx/hud.png";
mResource.texture[TEXTURE_MENU_ANIMATION].file = mGame.path + "/" + "../media/gfx/menu_animation.png";
mResource.texture[TEXTURE_MENU].file = mGame.path + "/" + "../media/gfx/menu.png";
mResource.texture[TEXTURE_PLAYER].file = mGame.path + "/" + "../media/gfx/player.png";
mResource.texture[TEXTURE_TILES_SURFACE].file = mGame.path + "/" + "../media/gfx/tiles_surface.png";
mResource.texture[TEXTURE_TILES_VOLCANO].file = mGame.path + "/" + "../media/gfx/tiles_volcano.png";
// Sonidos
mResource.sound[SOUND_COIN].file = mGame.path + "/" + "../media/sound/sound_player_coin.wav";
mResource.sound[SOUND_DEATH].file = mGame.path + "/" + "../media/sound/sound_player_death.wav";
mResource.sound[SOUND_DROP_ENEMY].file = mGame.path + "/" + "../media/sound/sound_drop_enemy.wav";
mResource.sound[SOUND_DROP_SPLAT].file = mGame.path + "/" + "../media/sound/sound_drop_splat.wav";
mResource.sound[SOUND_JUMP].file = mGame.path + "/" + "../media/sound/sound_player_jump.wav";
mResource.sound[SOUND_MENU_LOGO].file = mGame.path + "/" + "../media/sound/sound_menu_logo.wav";
mResource.sound[SOUND_MENU_START].file = mGame.path + "/" + "../media/sound/sound_menu_start.wav";
// Musicas
mResource.music[MUSIC_MENU].file = mGame.path + "/" + "../media/music/music_menu.ogg";
mResource.music[MUSIC_SURFACE].file = mGame.path + "/" + "../media/music/music_surface.ogg";
mResource.music[MUSIC_VOLCANO].file = mGame.path + "/" + "../media/music/music_volcano.ogg";
}
// Comprueba que todos los ficheros existen
bool Game::checkFileList()
{
bool success = true;
std::string p;
std::string filename;
SDL_RWops *file;
// Comprueba los ficheros de musica
printf("\n>> MUSIC FILES\n");
for (Uint8 i = 0; i < TOTAL_MUSIC; i++)
{
p = mResource.music[i].file.c_str();
filename = p.substr(p.find_last_of("\\/") + 1);
file = SDL_RWFromFile(p.c_str(), "r+b");
if (file != NULL)
{
printf("Checking file %-20s [OK]\n", filename.c_str());
}
else
{
success = false;
printf("Checking file %-20s [ERROR]\n", filename.c_str());
}
SDL_RWclose(file);
}
// Comprueba los ficheros de sonidos
printf("\n>> SOUND FILES\n");
for (Uint8 i = 0; i < TOTAL_SOUND; i++)
{
p = mResource.sound[i].file.c_str();
filename = p.substr(p.find_last_of("\\/") + 1);
file = SDL_RWFromFile(p.c_str(), "r+b");
if (file != NULL)
{
printf("Checking file %-20s [OK]\n", filename.c_str());
}
else
{
success = false;
printf("Checking file %-20s [ERROR]\n", filename.c_str());
}
SDL_RWclose(file);
}
// Comprueba los ficheros con texturas
printf("\n>> TEXTURE FILES\n");
for (Uint8 i = 0; i < TOTAL_TEXTURE; i++)
{
p = mResource.texture[i].file.c_str();
filename = p.substr(p.find_last_of("\\/") + 1);
file = SDL_RWFromFile(p.c_str(), "r+b");
if (file != NULL)
{
printf("Checking file %-20s [OK]\n", filename.c_str());
}
else
{
success = false;
printf("Checking file %-20s [ERROR]\n", filename.c_str());
}
SDL_RWclose(file);
}
// Resultado
if (success)
{
printf("\n** All files OK.\n\n");
}
else
{
printf("\n** File is missing. Exiting.\n\n");
}
return success;
}
// Carga un archivo de imagen en una textura
bool Game::loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer)
{
bool success = true;
if (!texture->loadFromFile(path, renderer))
{
printf("Failed to load %s texture!\n", path.c_str());
success = false;
}
return success;
}
// Carga los recursos necesarios
bool Game::loadMedia(Uint8 section)
{
// Indicador de éxito en la carga
bool success = true;
std::string path = mGame.path + "/";
std::string p;
switch (section)
{
case GAME_SECTION_INIT:
{
p = mResource.file[FILE_CONFIG].file.c_str();
std::string filename = p.substr(p.find_last_of("\\/") + 1);
filename = p.substr(p.find_last_of("\\/") + 1);
// Abre el fichero con la configuracion de las opciones para leer en binario
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b");
// El fichero no existe
if (file == NULL)
{
printf("Warning: Unable to open %s file\n", filename.c_str());
// Crea el fichero para escribir
file = SDL_RWFromFile(p.c_str(), "w+b");
if (file != NULL)
{
printf("New file (%s) created!\n", filename.c_str());
// Inicializa los datos
mGame.options.fullScreenMode = 0;
SDL_RWwrite(file, &mGame.options.fullScreenMode, sizeof(mGame.options.fullScreenMode), 1);
mGame.options.windowSize = 3;
SDL_RWwrite(file, &mGame.options.windowSize, sizeof(mGame.options.windowSize), 1);
// Cierra el fichero
SDL_RWclose(file);
}
else
{
printf("Error: Unable to create file %s\n", filename.c_str());
success = false;
}
}
// El fichero existe
else
{
// Carga los datos
printf("Reading file %s\n", filename.c_str());
SDL_RWread(file, &mGame.options.fullScreenMode, sizeof(mGame.options.fullScreenMode), 1);
SDL_SetWindowFullscreen(mWindow, mGame.options.fullScreenMode);
SDL_RWread(file, &mGame.options.windowSize, sizeof(mGame.options.windowSize), 1);
SDL_SetWindowSize(mWindow, SCREEN_WIDTH * mGame.options.windowSize, SCREEN_HEIGHT * mGame.options.windowSize);
// Cierra el fichero
SDL_RWclose(file);
}
printf("\n");
// Texturas
// Sonidos
// Musicas
}
break;
case GAME_SECTION_TITLE:
{
}
break;
case GAME_SECTION_PLAYING:
{
}
break;
case GAME_SECTION_GAME_OVER_SCREEN:
{
}
break;
case GAME_SECTION_INTRO:
{
}
break;
case GAME_SECTION_DEMO:
{
}
break;
case GAME_SECTION_INSTRUCTIONS:
{
}
break;
case GAME_SECTION_LOGO:
{
}
break;
default:
{
}
break;
}
return success;
}
// Descrga los recursos necesarios
bool Game::unLoadMedia(Uint8 section)
{
// Indicador de éxito en la carga
bool success = true;
std::string path = mGame.path + "/";
std::string p;
switch (section)
{
case GAME_SECTION_INIT:
{
p = mResource.file[FILE_CONFIG].file;
std::string filename = p.substr(p.find_last_of("\\/") + 1);
// Abre el fichero de puntuación para escribir
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "w+b");
if (file != NULL)
{
// Guardamos los datos
SDL_RWwrite(file, &mGame.options.fullScreenMode, sizeof(Uint32), 1);
SDL_RWwrite(file, &mGame.options.windowSize, sizeof(Uint8), 1);
printf("Writing file %s\n", filename.c_str());
// Cerramos el fichero
SDL_RWclose(file);
}
else
{
printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError());
}
}
break;
case GAME_SECTION_TITLE:
{
}
break;
case GAME_SECTION_PLAYING:
{
}
break;
case GAME_SECTION_GAME_OVER_SCREEN:
{
}
break;
case GAME_SECTION_INTRO:
{
}
break;
case GAME_SECTION_DEMO:
{
}
break;
case GAME_SECTION_INSTRUCTIONS:
{
}
break;
case GAME_SECTION_LOGO:
{
}
break;
default:
{
}
break;
}
return success;
}
// Establece el valor de la variable
void Game::setPath(std::string path)
{
mGame.path = path.substr(0, path.find_last_of("\\/"));
}
// Obtiene el valor de la variable
Uint8 Game::getGameSection()
{
return mGame.section;
}
// Establece el valor de la variable
void Game::setGameSection(Uint8 section)
{
mGame.section = section;
}
// Cambia el valor de la variable de modo de pantalla completa
void Game::changeFullScreenMode()
{
switch (mGame.options.fullScreenMode)
{
case 0:
mGame.options.fullScreenMode = SDL_WINDOW_FULLSCREEN;
break;
case SDL_WINDOW_FULLSCREEN:
mGame.options.fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
break;
case SDL_WINDOW_FULLSCREEN_DESKTOP:
mGame.options.fullScreenMode = 0;
break;
default:
mGame.options.fullScreenMode = 0;
break;
}
}
// Bucle para el logo del juego
void Game::runLogo()
{
}
// Bucle para la intro del juego
void Game::runIntro()
{
}
// Bucle para el titulo del juego
void Game::runTitle()
{
}
// Bucle para el juego
void Game::runGame()
{
}

165
source/game.h Normal file
View File

@@ -0,0 +1,165 @@
#pragma once
#include "ifdefs.h"
#include "sprite.h"
#include "movingsprite.h"
#include "smartsprite.h"
#include "player.h"
#include "text.h"
#include "text2.h"
#include "menu.h"
#include "const.h"
#include "jail_audio.h"
#include "utils.h"
#include <math.h>
#ifndef GAME_H
#define GAME_H
// GameDirector
class Game
{
public:
// Constructor
Game();
// Destructor
~Game();
// Iniciador
void init();
// Arranca SDL y crea la ventana
bool initSDL();
// Crea el indice de ficheros
void setFileList();
// Comprueba que todos los ficheros existen
bool checkFileList();
// Carga un archivo de imagen en una textura
bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer);
// Carga los recursos necesarios
bool loadMedia(Uint8 section);
// Descrga los recursos necesarios
bool unLoadMedia(Uint8 section);
// Establece el valor de la variable
void setPath(std::string path);
// Obtiene el valor de la variable
Uint8 getGameSection();
// Establece el valor de la variable
void setGameSection(Uint8 section);
// Cambia el valor de la variable de modo de pantalla completa
void changeFullScreenMode();
// Bucle para el logo del juego
void runLogo();
// Bucle para la intro del juego
void runIntro();
// Bucle para el titulo del juego
void runTitle();
// Bucle para el juego
void runGame();
private:
SDL_Window *mWindow; // La ventana de la aplicación
SDL_Renderer *mRenderer; // El renderizador donde se dibuja todo
SDL_Event *mEventHandler; // Manejador de eventos
SDL_Texture *mBackbuffer; // Texturas
SDL_Joystick *mGameController; // Manejador para el mando 1
bool mGameControllerFound; // Indica si se ha encontrado algun mando conectado
SDL_Haptic *mControllerHaptic; // Manejador para la vibración del mando
Uint32 mScoreData[TOTAL_SCORE_DATA]; // Datos del fichero de puntuación
Player *mPlayer; // El jugador
double mSen[360]; // Vector con los valores del seno para 360 grados
struct _text // Objetos de texto
{
Text *white;
};
_text mText; // Variable con los objetos texto
struct _menu // Objetos menu
{
Menu *title; // Menu de la pantalla de título
};
_menu mMenu; // Variable con los objetos menu
struct _options // Variables relacionadas con las opciones del juego
{
Uint32 fullScreenMode; // Guarda el valor elegido para el modo de pantalla completa
Uint32 fullScreenModePrevious; // Guarda el valor previo del modo de pantalla completa
Uint8 windowSize; // Guarda el valor elegido para el tamaño de la ventana
Uint8 windowSizePrevious; // Guarda el valor previo del tamaño de la ventana
};
struct _game // Variables para el control del juego
{
Uint32 score; // Puntuación actual
Uint8 section; // Indicador para el bucle principal
bool paused; // Idica si el juego está en pausa
Uint32 ticks; // Contador de ticks para ajustar la velocidad del juego
Uint8 ticksSpeed; // Velocidad a la que se repite el bucle de juego
Uint32 counter; // Contador para el juego
_options options; // Contiene todas las opciones del juego
std::string path; // Path donde está el ejecutable del juego
};
_game mGame;
// Recursos
struct _resourceFile
{
std::string file;
bool loaded;
};
struct _resourceSound
{
std::string file;
bool loaded;
JA_Sound sound;
};
struct _resourceMusic
{
std::string file;
bool loaded;
JA_Music music;
};
struct _resourceTexture
{
std::string file;
bool loaded;
LTexture *texture;
};
struct _resource
{
_resourceFile file[TOTAL_FILE];
_resourceSound sound[TOTAL_SOUND];
_resourceMusic music[TOTAL_MUSIC];
_resourceTexture texture[TOTAL_TEXTURE];
};
_resource mResource;
};
#endif

View File

@@ -1,39 +1,15 @@
/* /*
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. Volcano (abans "Rise of the Bal1")
Programat i dissenyat per
Sergio Valor @JailDesigner
Editor, música i suport técnic per
Raimon Zamora @JailDoc
Gràfics per
Diego Valor @JailBrother
Començat un 19 de febrer de 2016
Repres un 14 de febrer de 2021
El programa contine una serie de clases/objetos básicos: la clase sprite
permite dibujar partes de un fichero png en pantalla. La clase AnimatedSprite
contiene funcionalidad adicional para crear animaciones. La clase text permite
dibujar letras de un png en pantalla a partir de una cadena de texto. La clase
menu permite crear una estructura con diferentes elementos, escribirlos en
pantalla y seleccionar uno de ellos.
A continuación tenemos las clases enfocadas a la lógica del juego, la clase player
contiene la información del jugador, la clase balloon la de los enemigos y la
clase bullet para las balas que dispara el jugador. La clase background es
muy simple y sirve para pintar el fondo de la pantalla. Por ultimo, la clase
gamedirector es la que realiza toda la lógica y se encarga de hacer interactuar
al resto de objetos entre si.
El objeto gamedirector tiene tres estados: titulo, juego y pausa. Segun su estado
el bucle que recorre es distinto. En el bucle juego, el objeto gamedirector
tiene un objeto jugador, un vector con los objetos globo y un vector con los
objetos bala. Se encarga de comprobar las entradas de teclado o gamepad para
cerrar la aplicacion, saltar al estado de pausa y para mover al jugador. Recorre
el vector de globos y de balas y si tienen algun tipo asignado las gestiona.
Comprueba las colisiones entre los globos y el jugador y entre las balas y los
globos. Tiene ademas un nivel de amenaza que calcula en funcion del numero de globos
en pantalla y que se va incrementando conforme aumenta la puntuación del jugador.
Los objetos globo tienen varios contadores para alternar de un estado a otro.
En los vectores que contienen objetos, se considera activos los objetos que tienen
un tipo asociado diferente a NO_KIND
*/ */
#include "ifdefs.h" #include "ifdefs.h"
@@ -41,88 +17,38 @@ un tipo asociado diferente a NO_KIND
#include <stdio.h> #include <stdio.h>
#include <string> #include <string>
#include "const.h" #include "const.h"
#include "gamedirector.h" #include "game.h"
int main(int argc, char *args[]) int main(int argc, char *args[])
{ {
// Inicia el generador de numeros aleatorios // Inicia el generador de numeros aleatorios
srand(time(nullptr)); srand(time(nullptr));
// Crea el objeto gameDirector // Crea el objeto game
GameDirector *gameDirector = new GameDirector(); Game *game = new Game();
// Establece el valor de la variable con el path del ejecutable // Establece el valor de la variable con el path del ejecutable
gameDirector->setExecutablePath(args[0]); game->setPath(args[0]);
// Inicializa la lista de ficheros // Inicializa la lista de ficheros
gameDirector->setFileList(); game->setFileList();
// Comprueba que existen todos los ficheros // Comprueba que existen todos los ficheros
if (!gameDirector->checkFileList()) if (!game->checkFileList())
{ {
return -1; return -1;
} }
// Arranca SDL y crea la ventana // Arranca SDL y crea la ventana
if (!gameDirector->initSDL()) if (!game->initSDL())
{ {
printf("Failed to initialize!\n"); printf("Failed to initialize!\n");
return -1; return -1;
} }
else else
{ {
// Carga los recursos
if (!gameDirector->loadMedia(GAME_STATE_INIT))
{
printf("Failed to load media!\n");
}
else
{
// Inicializa el objeto gameDirector
gameDirector->init(false);
printf("Starting the game...\n\n");
// Mientras no se quiera salir del juego
while (!(gameDirector->getGameStatus() == GAME_STATE_QUIT))
{
switch (gameDirector->getGameStatus())
{
case GAME_STATE_LOGO:
gameDirector->loadMedia(GAME_STATE_LOGO);
gameDirector->runLogo();
gameDirector->unLoadMedia(GAME_STATE_LOGO);
break;
case GAME_STATE_INTRO:
gameDirector->loadMedia(GAME_STATE_INTRO);
gameDirector->runIntro();
gameDirector->unLoadMedia(GAME_STATE_INTRO);
break;
case GAME_STATE_TITLE:
gameDirector->loadMedia(GAME_STATE_TITLE);
gameDirector->runTitle();
gameDirector->unLoadMedia(GAME_STATE_TITLE);
break;
case GAME_STATE_PLAYING:
gameDirector->loadMedia(GAME_STATE_PLAYING);
gameDirector->runGame();
gameDirector->unLoadMedia(GAME_STATE_PLAYING);
break;
case GAME_STATE_GAME_OVER_SCREEN:
gameDirector->loadMedia(GAME_STATE_GAME_OVER_SCREEN);
gameDirector->runGameOverScreen();
gameDirector->unLoadMedia(GAME_STATE_GAME_OVER_SCREEN);
break;
case GAME_STATE_INSTRUCTIONS:
gameDirector->loadMedia(GAME_STATE_INSTRUCTIONS);
gameDirector->runInstructions();
gameDirector->unLoadMedia(GAME_STATE_INSTRUCTIONS);
break;
}
}
}
// Libera todos los recursos y cierra SDL // Libera todos los recursos y cierra SDL
delete gameDirector; delete game;
printf("Shutting down the game...\n"); printf("Shutting down the game...\n");
return 0; return 0;