Compare commits

...

11 Commits

32 changed files with 17681 additions and 4066 deletions

5
.gitignore vendored
View File

@@ -1,4 +1,5 @@
.DS_store
.vscode
super_pang_clone
bin
super_pang_clone*
bin/*
info.plist*

View File

@@ -2,14 +2,10 @@ executable = super_pang_clone
source = 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 $(executable).exe
g++ $(source) -std=c++11 -Wall -O2 -lmingw32 -lSDL2main -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows -o $(executable).exe
strip -s -R .comment -R .gnu.version $(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 $(executable)_macos
g++ $(source) -std=c++11 -Wall -O2 -lSDL2 -ffunction-sections -fdata-sections -o $(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 $(executable)_linux
g++ $(source) -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -o $(executable)_linux
strip -s -R .comment -R .gnu.version $(executable)_linux --strip-unneeded

View File

@@ -78,6 +78,11 @@ void Bullet::init(int x, int y, int kind)
break;
default:
// Establece la velocidad inicial
mVelX = 0;
// Rectangulo con los gráficos del objeto
mSprite.setSpriteClip(0 * mWidth, 0, mSprite.getWidth(), mSprite.getHeight());
break;
}

View File

@@ -31,118 +31,60 @@ GameDirector::GameDirector(SDL_Renderer *gRenderer)
{
this->gRenderer = gRenderer;
init();
}
// Destructor
GameDirector::~GameDirector()
{
// 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;
// Libera texturas
gGameBackgroundTexture->free();
gTitleBackgroundTexture->free();
gWhiteFontTexture->free();
gBlackFontTexture->free();
gMiscTexture->free();
// Libera objetos
delete player;
delete menuPause;
delete menuTitle;
for (Uint8 i = 0; i < mMaxBalloons; i++)
mMaxBalloons = 50;
for (int i = 0; i < mMaxBalloons; ++i)
{
if (balloon[i])
{
delete balloon[i];
}
balloon[i] = new Balloon(gRenderer);
}
for (int i = 0; i < mMaxBullets; i++)
mMaxBullets = 50;
for (int i = 0; i < mMaxBullets; ++i)
{
if (bullet[i])
{
delete bullet[i];
}
bullet[i] = new Bullet(gRenderer);
}
}
// Iniciador
void GameDirector::init()
{
// 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());
}
gTitleMusic = JA_LoadMusic("media/music/title.ogg");
// 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());
}
gPlayingMusic = JA_LoadMusic("media/music/playing.ogg");
// 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());
}
gPopBalloonFX = JA_LoadSound("media/sound/balloon.wav");
// 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());
}
gBulletFX = JA_LoadSound("media/sound/bullet.wav");
gGameBackgroundTexture = new LTexture(gRenderer);
// Carga los gráficos del fondo del juego
gGameBackgroundTexture = new LTexture(gRenderer);
if (!gGameBackgroundTexture->loadFromFile("media/gfx/background.png"))
{
printf("Failed to load game background texture!\n");
}
gTitleBackgroundTexture = new LTexture(gRenderer);
// Carga los gráficos del fondo de la pantalla de titulo
gTitleBackgroundTexture = new LTexture(gRenderer);
if (!gTitleBackgroundTexture->loadFromFile("media/gfx/title.png"))
{
printf("Failed to load title texture!\n");
}
gMiscTexture = new LTexture(gRenderer);
// Carga varios gráficos para varios propósitos
gMiscTexture = new LTexture(gRenderer);
if (!gMiscTexture->loadFromFile("media/gfx/misc.png"))
{
printf("Failed to load misc texture!\n");
}
gWhiteFontTexture = new LTexture(gRenderer);
// Carga los gráficos para el texto blanco
gWhiteFontTexture = new LTexture(gRenderer);
if (!gWhiteFontTexture->loadFromFile("media/gfx/white_font.png"))
{
printf("Failed to load white font texture!\n");
}
gBlackFontTexture = new LTexture(gRenderer);
// Carga los gráficos para el texto negro
gBlackFontTexture = new LTexture(gRenderer);
if (!gBlackFontTexture->loadFromFile("media/gfx/black_font.png"))
{
printf("Failed to load black font texture!\n");
@@ -165,11 +107,53 @@ void GameDirector::init()
std::cout << SDL_JoystickNumButtons(gGameController) << " buttons\n";
}
init();
}
// Destructor
GameDirector::~GameDirector()
{
// Libera los efectos de sonido
JA_DeleteSound(gPopBalloonFX);
JA_DeleteSound(gBulletFX);
// Libra la música
JA_DeleteMusic(gTitleMusic);
JA_DeleteMusic(gPlayingMusic);
// Libera el mando
SDL_JoystickClose(gGameController);
gGameController = NULL;
// Libera texturas
gGameBackgroundTexture->free();
gTitleBackgroundTexture->free();
gWhiteFontTexture->free();
gBlackFontTexture->free();
gMiscTexture->free();
// Libera objetos
delete player;
delete menuPause;
delete menuTitle;
for (int i = 0; i < mMaxBalloons; ++i)
{
delete balloon[i];
}
for (int i = 0; i < mMaxBullets; ++i)
{
delete bullet[i];
}
}
// Iniciador
void GameDirector::init()
{
// Variables
mGameStatus = GAME_STATE_TITLE;
mOldTicks = 0;
mMaxBalloons = 50;
mMaxBullets = 50;
mGameSpeed = 15;
mMenaceLevel = 0;
mMenaceLevelThreshold = 7;
@@ -186,24 +170,12 @@ void GameDirector::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);
@@ -229,16 +201,6 @@ void GameDirector::init()
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)
{
@@ -288,6 +250,7 @@ std::string GameDirector::updateScoreText(Uint32 num)
case 100000 ... 999999:
return (std::to_string(num));
break;
default:
return (std::to_string(num));
break;
@@ -349,8 +312,7 @@ Uint8 GameDirector::getBallonFreeIndex()
// 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] = new Balloon(gRenderer);
const Uint8 index = getBallonFreeIndex();
balloon[index]->init(x, y, kind, velx, creationtimer);
return index;
}
@@ -358,7 +320,7 @@ Uint8 GameDirector::createNewBalloon(int x, int y, Uint8 kind, float velx, Uint1
// Establece a cero todos los valores del vector de objetos globo
void GameDirector::resetBalloons()
{
for (Uint8 i = 0; i < mMaxBalloons; i++)
for (int i = 0; i < mMaxBalloons; ++i)
{
balloon[i]->erase();
}
@@ -468,7 +430,7 @@ void GameDirector::processBulletBallonCollision()
setScore(player->getScore());
updateHiScore();
popBalloon(i);
Mix_PlayChannel(-1, gPopBalloonFX, 0);
JA_PlaySound(gPopBalloonFX);
bullet[j]->erase();
calculateMenaceLevel();
break;
@@ -522,7 +484,7 @@ Uint8 GameDirector::getBulletFreeIndex()
// Establece a cero todos los valores del vector de objetos bala
void GameDirector::resetBullets()
{
for (Uint8 i = 0; i < mMaxBullets; i++)
for (int i = 0; i < mMaxBullets; ++i)
{
bullet[i]->init(0, 0, NO_KIND);
}
@@ -532,7 +494,6 @@ void GameDirector::resetBullets()
void GameDirector::createBullet(int x, int y, Uint8 kind)
{
const int index = getBulletFreeIndex();
bullet[index] = new Bullet(gRenderer);
bullet[index]->init(x, y, kind);
}
@@ -540,7 +501,7 @@ void GameDirector::createBullet(int x, int y, Uint8 kind)
void GameDirector::calculateMenaceLevel()
{
mMenaceLevel = 0;
for (Uint8 i = 0; i < mMaxBalloons; i++)
for (int i = 0; i < mMaxBalloons; ++i)
{
switch (balloon[i]->getKind())
{
@@ -634,7 +595,7 @@ void GameDirector::checkGameInput()
player->setFireCooldown(10);
// Reproduce el sonido de disparo
Mix_PlayChannel(-1, gBulletFX, 0);
JA_PlaySound(gBulletFX);
}
}
@@ -647,7 +608,7 @@ void GameDirector::checkGameInput()
player->setFireCooldown(10);
// Reproduce el sonido de disparo
Mix_PlayChannel(-1, gBulletFX, 0);
JA_PlaySound(gBulletFX);
}
}
@@ -660,7 +621,7 @@ void GameDirector::checkGameInput()
player->setFireCooldown(10);
// Reproduce el sonido de disparo
Mix_PlayChannel(-1, gBulletFX, 0);
JA_PlaySound(gBulletFX);
}
}
@@ -670,7 +631,7 @@ void GameDirector::checkGameInput()
setGameStatus(GAME_STATE_PAUSED);
// Detiene la música
Mix_HaltMusic();
JA_StopMusic();
}
}
@@ -695,88 +656,6 @@ void GameDirector::checkMenuInput(Menu *menu)
{
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
@@ -886,10 +765,10 @@ void GameDirector::renderGetReady()
void GameDirector::runTitle()
{
// Si la música no está sonando
if (Mix_PlayingMusic() == 0)
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
// Reproduce la música
Mix_PlayMusic(gTitleMusic, -1);
JA_PlayMusic(gTitleMusic);
}
// Comprueba los eventos que hay en la cola
@@ -923,15 +802,17 @@ void GameDirector::runTitle()
setGameStatus(GAME_STATE_PLAYING);
menuTitle->resetMenu();
renderTransition(1);
Mix_HaltMusic();
JA_StopMusic();
SDL_Delay(1200);
break;
case 1:
setGameStatus(GAME_STATE_QUIT);
menuTitle->resetMenu();
renderTransition(1);
Mix_HaltMusic();
JA_StopMusic();
break;
default:
break;
}
@@ -941,10 +822,10 @@ void GameDirector::runTitle()
void GameDirector::runGame()
{
// Si la música no está sonando
if (Mix_PlayingMusic() == 0)
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
// Reproduce la música
Mix_PlayMusic(gPlayingMusic, -1);
JA_PlayMusic(gPlayingMusic);
}
// Lógica del juego
@@ -973,39 +854,6 @@ void GameDirector::runGame()
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
@@ -1014,10 +862,6 @@ void GameDirector::runGame()
// Mueve los globos
moveBalloons();
#ifdef TEST
balloonTest.move();
#endif
// Mueve las balas
moveBullets();
@@ -1041,16 +885,6 @@ void GameDirector::runGame()
// 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);
@@ -1094,12 +928,14 @@ void GameDirector::runPausedGame()
setGameStatus(GAME_STATE_PLAYING);
menuPause->resetMenu();
break;
case 1:
setGameStatus(GAME_STATE_TITLE);
menuPause->resetMenu();
renderTransition(1);
init();
break;
default:
break;
}

View File

@@ -9,6 +9,7 @@
#include "menu.h"
#include "player.h"
#include "text.h"
#include "jail_audio.h"
#ifndef GAMEDIRECTOR_H
#define GAMEDIRECTOR_H
@@ -26,9 +27,6 @@ public:
// Iniciador
void init();
// Hace una pausa de milisegundos
void sleep(Uint16 time);
// Establece el valor de la variable
void setScore(Uint32 score);
@@ -133,12 +131,16 @@ private:
SDL_Renderer *gRenderer = NULL;
// Objetos con la música del juego
Mix_Music *gTitleMusic = NULL;
Mix_Music *gPlayingMusic = NULL;
//Mix_Music *gTitleMusic = NULL;
//Mix_Music *gPlayingMusic = NULL;
JA_Music gTitleMusic;
JA_Music gPlayingMusic;
// Objetos con los efectos de sonido del juego
Mix_Chunk *gPopBalloonFX = NULL;
Mix_Chunk *gBulletFX = NULL;
//Mix_Chunk *gPopBalloonFX = NULL;
//Mix_Chunk *gBulletFX = NULL;
JA_Sound gPopBalloonFX;
JA_Sound gBulletFX;
// Manejador para el mando 1
SDL_Joystick *gGameController = NULL;

View File

@@ -1,8 +1,6 @@
#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_mixer.h>
#ifndef GLOBALS_H
#define GLOBALS_H

238
source/jail_audio.cpp Normal file
View File

@@ -0,0 +1,238 @@
#include "jail_audio.h"
#include "stb_vorbis.c"
#include <SDL2/SDL.h>
#include <stdio.h>
#define JA_MAX_SIMULTANEOUS_CHANNELS 5
struct JA_Sound_t {
Uint32 length {0};
Uint8* buffer {NULL};
};
struct JA_Channel_t {
JA_Sound sound;
int pos {0};
int times {0};
JA_Channel_state state { JA_CHANNEL_FREE };
};
struct JA_Music_t {
int samples {0};
int pos {0};
int times {0};
short* output {NULL};
JA_Music_state state {JA_MUSIC_INVALID};
};
JA_Music current_music{NULL};
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
int JA_freq {48000};
SDL_AudioFormat JA_format {AUDIO_S16};
Uint8 JA_channels {2};
int JA_volume = 128;
void audioCallback(void * userdata, uint8_t * stream, int len) {
SDL_memset(stream, 0, len);
if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING) {
const int size = SDL_min(len, current_music->samples*2-current_music->pos);
SDL_MixAudioFormat(stream, (Uint8*)(current_music->output+current_music->pos), AUDIO_S16, size, JA_volume);
current_music->pos += size/2;
if (size < len) {
if (current_music->times != 0) {
SDL_MixAudioFormat(stream+size, (Uint8*)current_music->output, AUDIO_S16, len-size, JA_volume);
current_music->pos = (len-size)/2;
if (current_music->times > 0) current_music->times--;
} else {
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
}
}
// Mixar els channels mi amol
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PLAYING) {
const int size = SDL_min(len, channels[i].sound->length - channels[i].pos);
SDL_MixAudioFormat(stream, channels[i].sound->buffer + channels[i].pos, AUDIO_S16, size, JA_volume/2);
channels[i].pos += size;
if (size < len) {
if (channels[i].times != 0) {
SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len-size, JA_volume/2);
channels[i].pos = len-size;
if (channels[i].times > 0) channels[i].times--;
} else {
JA_StopChannel(i);
}
}
}
}
}
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) {
JA_freq = freq;
JA_format = format;
JA_channels = channels;
SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL};
SDL_AudioDeviceID sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
SDL_PauseAudioDevice(sdlAudioDevice, 0);
}
JA_Music JA_LoadMusic(const char* filename) {
int chan, samplerate;
JA_Music music = new JA_Music_t();
// [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid.
FILE *f = fopen(filename, "rb");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
Uint8 *buffer = (Uint8*)malloc(fsize + 1);
fread(buffer, fsize, 1, f);
fclose(f);
music->samples = stb_vorbis_decode_memory(buffer, fsize, &chan, &samplerate, &music->output);
free(buffer);
// [RZC 28/08/22] Abans el descomprimiem mentre el teniem obert
// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq);
cvt.len = music->samples * chan * 2;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, music->output, cvt.len);
SDL_ConvertAudio(&cvt);
free(music->output);
music->output = (short*)cvt.buf;
music->pos = 0;
music->state = JA_MUSIC_STOPPED;
return music;
}
void JA_PlayMusic(JA_Music music, const int loop) {
if (current_music != NULL) {
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
current_music = music;
current_music->pos = 0;
current_music->state = JA_MUSIC_PLAYING;
current_music->times = loop;
}
void JA_PauseMusic() {
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->state = JA_MUSIC_PAUSED;
}
void JA_ResumeMusic() {
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->state = JA_MUSIC_PLAYING;
}
void JA_StopMusic() {
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
JA_Music_state JA_GetMusicState() {
if (current_music == NULL) return JA_MUSIC_INVALID;
return current_music->state;
}
void JA_DeleteMusic(JA_Music music) {
if (current_music == music) current_music = NULL;
SDL_free(music->output);
delete music;
}
JA_Sound JA_NewSound(Uint8* buffer, Uint32 length) {
JA_Sound sound = new JA_Sound_t();
sound->buffer = buffer;
sound->length = length;
return sound;
}
JA_Sound JA_LoadSound(const char* filename) {
JA_Sound sound = new JA_Sound_t();
SDL_AudioSpec wavSpec;
SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length);
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq);
cvt.len = sound->length;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, sound->buffer, sound->length);
SDL_ConvertAudio(&cvt);
SDL_FreeWAV(sound->buffer);
sound->buffer = cvt.buf;
sound->length = cvt.len_cvt;
return sound;
}
int JA_PlaySound(JA_Sound sound, const int loop) {
int channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0;
channels[channel].sound = sound;
channels[channel].times = loop;
channels[channel].pos = 0;
channels[channel].state = JA_CHANNEL_PLAYING;
return channel;
}
void JA_DeleteSound(JA_Sound sound) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].sound == sound) JA_StopChannel(i);
}
SDL_free(sound->buffer);
delete sound;
}
void JA_PauseChannel(const int channel) {
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PLAYING) channels[i].state = JA_CHANNEL_PAUSED;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PLAYING) channels[channel].state = JA_CHANNEL_PAUSED;
}
}
void JA_ResumeChannel(const int channel) {
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PAUSED) channels[i].state = JA_CHANNEL_PLAYING;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PAUSED) channels[channel].state = JA_CHANNEL_PLAYING;
}
}
void JA_StopChannel(const int channel) {
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
channels[i].state = JA_CHANNEL_FREE;
channels[i].pos = 0;
channels[i].sound = NULL;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
channels[channel].state = JA_CHANNEL_FREE;
channels[channel].pos = 0;
channels[channel].sound = NULL;
}
}
JA_Channel_state JA_GetChannelState(const int channel) {
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
return channels[channel].state;
}
int JA_SetVolume(int volume) {
JA_volume = volume > 128 ? 128 : volume < 0 ? 0 : volume;
return JA_volume;
}

29
source/jail_audio.h Normal file
View File

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

View File

@@ -1,4 +1,6 @@
#include "ltexture.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
LTexture::LTexture(SDL_Renderer *gRenderer)
{
@@ -18,6 +20,72 @@ LTexture::~LTexture()
bool LTexture::loadFromFile(std::string path)
{
const std::string filename = path.substr(path.find_last_of("\\/") + 1);
int req_format = STBI_rgb_alpha;
int width, height, orig_format;
unsigned char *data = stbi_load(path.c_str(), &width, &height, &orig_format, req_format);
if (data == nullptr)
{
SDL_Log("Loading image failed: %s", stbi_failure_reason());
exit(1);
}
else
{
printf("Image loaded: %s\n", filename.c_str());
}
int depth, pitch;
Uint32 pixel_format;
if (req_format == STBI_rgb)
{
depth = 24;
pitch = 3 * width; // 3 bytes por pixel * pixels per linea
pixel_format = SDL_PIXELFORMAT_RGB24;
}
else
{ // STBI_rgb_alpha (RGBA)
depth = 32;
pitch = 4 * width;
pixel_format = SDL_PIXELFORMAT_RGBA32;
}
// Limpia
free();
// La textura final
SDL_Texture *newTexture = nullptr;
// Carga la imagen desde una ruta específica
SDL_Surface *loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom((void *)data, width, height, depth, pitch, pixel_format);
if (loadedSurface == nullptr)
{
printf("Unable to load image %s!\n", path.c_str());
}
else
{
// Crea la textura desde los pixels de la surface
newTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface);
if (newTexture == nullptr)
{
printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
}
else
{
// Obtiene las dimensiones de la imagen
this->mWidth = loadedSurface->w;
this->mHeight = loadedSurface->h;
}
// Elimina la textura cargada
SDL_FreeSurface(loadedSurface);
}
// Return success
mTexture = newTexture;
return mTexture != nullptr;
/*
// Get rid of preexisting texture
free();
@@ -55,6 +123,7 @@ bool LTexture::loadFromFile(std::string path)
// Return success
mTexture = newTexture;
return mTexture != NULL;
*/
}
bool LTexture::createBlank(int width, int height, SDL_TextureAccess access)

View File

@@ -35,7 +35,6 @@ 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 "background.h"
#include "balloon.h"
@@ -88,13 +87,6 @@ bool init()
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;
}
// 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)
@@ -118,18 +110,13 @@ bool init()
// 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;
}
}
}
}
// Inicializa JailAudio
JA_Init(44100, AUDIO_S16, 2);
return success;
}
@@ -143,7 +130,6 @@ void close()
gRenderer = NULL;
// Sal del subsistema SDL
IMG_Quit();
SDL_Quit();
}
@@ -161,13 +147,6 @@ int main(int argc, char *args[])
// Crea el objeto gameDirector
GameDirector gameDirector(gRenderer);
// Inicializa el objeto gameDirector
gameDirector.init();
#ifdef TEST
gameDirector.resetBalloons();
#endif
// Mientras no se quiera salir del juego
while (!(gameDirector.getGameStatus() == GAME_STATE_QUIT))
{

View File

@@ -12,7 +12,7 @@ Menu::Menu(SDL_Renderer *gRenderer)
printf("Failed to load menu texture!\n");
}
init(0, 0, 0, MENU_BACKGROUND_SOLID);
//init(0, 0, 0, MENU_BACKGROUND_SOLID);
}
// Destructor
@@ -50,9 +50,9 @@ void Menu::init(int x, int y, int offset_sprite_selector, int backgroundType)
// Elementos del menu
for (Uint8 i = 0; i < 10; i++)
{
mMenuItem[i].label = "";
mMenuItem[i].x = mPosX;
mMenuItem[i].y = mPosY + (i * (BLOCK + 2));
mMenuItem[i].label = "s";
}
// Mueve el grafico del selector al elemento seleccionado

7897
source/stb_image.h Normal file

File diff suppressed because it is too large Load Diff

5565
source/stb_vorbis.c Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.