From 04c1df4352473b7a8800d9b3f11d630e9bf0c702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Valor=20Mart=C3=ADnez?= Date: Fri, 19 Feb 2021 21:45:04 +0100 Subject: [PATCH] update 19-02-21 --- source/const.h | 292 +++++++++++++++++++++++++--- source/game.cpp | 500 ++++++++++++++++++++++++++++++++++++++++++++++++ source/game.h | 165 ++++++++++++++++ source/main.cpp | 108 ++--------- 4 files changed, 944 insertions(+), 121 deletions(-) create mode 100644 source/game.cpp create mode 100644 source/game.h diff --git a/source/const.h b/source/const.h index 3994978..509450c 100644 --- a/source/const.h +++ b/source/const.h @@ -5,16 +5,6 @@ #ifndef 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 UP = 0; @@ -133,25 +123,267 @@ const Uint8 ZONE_VOLCANO = 1; const std::string WINDOW_TITLE = "Volcano v0005"; 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"; -const std::string FILE_TILES_SURFACE = "../media/gfx/tiles_surface.png"; -const std::string FILE_BKG_SURFACE = "../media/gfx/bkg_surface.png"; -const std::string FILE_MENU = "../media/gfx/menu.png"; -const std::string FILE_MENU_ANIMATION = "../media/gfx/menu_animation.png"; -const std::string FILE_ACTORS = "../media/gfx/actors.png"; -const std::string FILE_PLAYER = "../media/gfx/player.png"; -const std::string FILE_HUD = "../media/gfx/hud.png"; -const std::string FILE_FILTER = "../media/gfx/filter.png"; -const std::string FILE_SOUND_JUMP = "../media/sound/sound_player_jump.wav"; -const std::string FILE_SOUND_DEATH = "../media/sound/sound_player_death.wav"; -const std::string FILE_SOUND_COIN = "../media/sound/sound_player_coin.wav"; -const std::string FILE_SOUND_MENU_LOGO = "../media/sound/sound_menu_logo.wav"; -const std::string FILE_SOUND_MENU_START = "../media/sound/sound_menu_start.wav"; -const std::string FILE_SOUND_DROP_ENEMY = "../media/sound/sound_drop_enemy.wav"; -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 std::string FILE_MUSIC_VOLCANO = "../media/music/music_volcano.ogg"; -const std::string FILE_MUSIC_MENU = "../media/music/music_menu.ogg"; + +// Recursos +const Uint8 FILE_MAP_VOLCANO = 0; +const Uint8 FILE_CONFIG = 1; + +const Uint8 TOTAL_FILE = 2; + +const Uint8 TEXTURE_ACTORS = 0; +const Uint8 TEXTURE_BKG_SURFACE = 1; +const Uint8 TEXTURE_FILTER = 2; +const Uint8 TEXTURE_HUD = 3; +const Uint8 TEXTURE_MENU = 4; +const Uint8 TEXTURE_MENU_ANIMATION = 5; +const Uint8 TEXTURE_PLAYER = 6; +const Uint8 TEXTURE_TILES_SURFACE = 7; +const Uint8 TEXTURE_TILES_VOLCANO = 8; + +const Uint8 TOTAL_TEXTURE = 9; + +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 \ No newline at end of file diff --git a/source/game.cpp b/source/game.cpp new file mode 100644 index 0000000..fec5a79 --- /dev/null +++ b/source/game.cpp @@ -0,0 +1,500 @@ +#include "const.h" +#include "struct.h" +#include "game.h" +#include + +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() +{ +} \ No newline at end of file diff --git a/source/game.h b/source/game.h new file mode 100644 index 0000000..3e4c22a --- /dev/null +++ b/source/game.h @@ -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 + +#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 diff --git a/source/main.cpp b/source/main.cpp index 4d42b08..fcb55c9 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -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" @@ -41,88 +17,38 @@ un tipo asociado diferente a NO_KIND #include #include #include "const.h" -#include "gamedirector.h" +#include "game.h" int main(int argc, char *args[]) { // Inicia el generador de numeros aleatorios srand(time(nullptr)); - // Crea el objeto gameDirector - GameDirector *gameDirector = new GameDirector(); + // Crea el objeto game + Game *game = new Game(); // Establece el valor de la variable con el path del ejecutable - gameDirector->setExecutablePath(args[0]); + game->setPath(args[0]); // Inicializa la lista de ficheros - gameDirector->setFileList(); + game->setFileList(); // Comprueba que existen todos los ficheros - if (!gameDirector->checkFileList()) + if (!game->checkFileList()) { return -1; } // Arranca SDL y crea la ventana - if (!gameDirector->initSDL()) + if (!game->initSDL()) { printf("Failed to initialize!\n"); return -1; } else { - // Carga los recursos - if (!gameDirector->loadMedia(GAME_STATE_INIT)) - { - printf("Failed to load media!\n"); - } - else - { - // Inicializa el objeto gameDirector - gameDirector->init(false); - printf("Starting the game...\n\n"); - - // Mientras no se quiera salir del juego - while (!(gameDirector->getGameStatus() == GAME_STATE_QUIT)) - { - switch (gameDirector->getGameStatus()) - { - case GAME_STATE_LOGO: - gameDirector->loadMedia(GAME_STATE_LOGO); - gameDirector->runLogo(); - gameDirector->unLoadMedia(GAME_STATE_LOGO); - break; - case GAME_STATE_INTRO: - gameDirector->loadMedia(GAME_STATE_INTRO); - gameDirector->runIntro(); - gameDirector->unLoadMedia(GAME_STATE_INTRO); - break; - case GAME_STATE_TITLE: - gameDirector->loadMedia(GAME_STATE_TITLE); - gameDirector->runTitle(); - gameDirector->unLoadMedia(GAME_STATE_TITLE); - break; - case GAME_STATE_PLAYING: - gameDirector->loadMedia(GAME_STATE_PLAYING); - gameDirector->runGame(); - gameDirector->unLoadMedia(GAME_STATE_PLAYING); - break; - case GAME_STATE_GAME_OVER_SCREEN: - gameDirector->loadMedia(GAME_STATE_GAME_OVER_SCREEN); - gameDirector->runGameOverScreen(); - gameDirector->unLoadMedia(GAME_STATE_GAME_OVER_SCREEN); - break; - case GAME_STATE_INSTRUCTIONS: - gameDirector->loadMedia(GAME_STATE_INSTRUCTIONS); - gameDirector->runInstructions(); - gameDirector->unLoadMedia(GAME_STATE_INSTRUCTIONS); - break; - } - } - } - // Libera todos los recursos y cierra SDL - delete gameDirector; + delete game; printf("Shutting down the game...\n"); return 0;