Continue music

This commit is contained in:
Miloslav Číž 2020-04-16 16:59:06 +02:00
parent 443adbe950
commit 2a58188ee0
3 changed files with 101 additions and 25 deletions

95
main.c
View File

@ -101,6 +101,14 @@ static inline void SFG_setPixel(uint16_t x, uint16_t y, uint8_t colorIndex);
*/
void SFG_playSound(uint8_t soundIndex, uint8_t volume);
/**
Informs the frontend whether music should get enabled/disabled. Playing music
is optional and the frontend can ignore it. If a frontend wants to implement
music, it can use the one provided in sounds.h or use its own.
*/
void SFG_enableMusic(uint8_t enable);
/* ========================================================================= */
/**
@ -285,6 +293,9 @@ struct
uint8_t selectedMenuItem;
uint8_t selectedLevel; ///< Level to play selected in the main menu.
uint8_t antiSpam; ///< Prevents log message spamming.
uint8_t soundSettings; /**< Sound settings: LSB says whether SFX is on,
second LSB says whether music is on. */
} SFG_game;
/**
@ -442,8 +453,11 @@ uint8_t SFG_random()
return SFG_game.currentRandom;
}
void SFG_playSoundSafe(uint8_t soundIndex, uint8_t volume)
void SFG_playGameSound(uint8_t soundIndex, uint8_t volume)
{
if (!(SFG_game.soundSettings & 0x01))
return;
uint8_t mask = 0x01 << soundIndex;
if (!(SFG_game.soundsPlayedThisFrame & mask))
@ -1418,6 +1432,9 @@ void SFG_init()
SFG_game.antiSpam = 0;
SFG_game.soundSettings = 0xff;
SFG_enableMusic(1);
SFG_LOG("computing average texture colors")
for (uint8_t i = 0; i < SFG_WALL_TEXTURE_COUNT; ++i)
@ -1693,10 +1710,10 @@ void SFG_monsterChangeHealth(SFG_MonsterRecord *monster, int8_t healthAdd)
SFG_MONSTER_COORD_TO_SQUARES(monster->coords[0]),
SFG_MONSTER_COORD_TO_SQUARES(monster->coords[1])));
SFG_playSoundSafe(5,volume);
SFG_playGameSound(5,volume);
if (monster->health == 0)
SFG_playSoundSafe(2,volume);
SFG_playGameSound(2,volume);
}
}
@ -1748,7 +1765,7 @@ void SFG_createExplosion(RCL_Unit x, RCL_Unit y, RCL_Unit z)
{
SFG_ProjectileRecord explosion;
SFG_playSound(2,SFG_distantSoundVolume(x,y,z));
SFG_playGameSound(2,SFG_distantSoundVolume(x,y,z));
explosion.type = SFG_PROJECTILE_EXPLOSION;
@ -1926,7 +1943,7 @@ void SFG_monsterPerformAI(SFG_MonsterRecord *monster)
}
if (projectile == SFG_PROJECTILE_BULLET)
SFG_playSoundSafe(0,
SFG_playGameSound(0,
SFG_distantSoundVolume(
SFG_MONSTER_COORD_TO_RCL_UNITS(monster->coords[0]),
SFG_MONSTER_COORD_TO_RCL_UNITS(monster->coords[1]),
@ -2014,7 +2031,7 @@ void SFG_monsterPerformAI(SFG_MonsterRecord *monster)
SFG_playerChangeHealth(
-1 * SFG_getDamageValue(SFG_WEAPON_FIRE_TYPE_MELEE));
SFG_playSoundSafe(3,255);
SFG_playGameSound(3,255);
}
else // SFG_MONSTER_ATTACK_EXPLODE
{
@ -2085,7 +2102,7 @@ void SFG_monsterPerformAI(SFG_MonsterRecord *monster)
if ((coordAdd[0] != 0 || coordAdd[1] != 0) && SFG_random() <
SFG_MONSTER_SOUND_PROBABILITY)
SFG_playSoundSafe(5,
SFG_playGameSound(5,
SFG_distantSoundVolume(
SFG_MONSTER_COORD_TO_RCL_UNITS(monster->coords[0]),
SFG_MONSTER_COORD_TO_RCL_UNITS(monster->coords[1]),
@ -2309,7 +2326,7 @@ void SFG_updateLevel()
else if (p->type == SFG_PROJECTILE_BULLET)
SFG_createDust(p->position[0],p->position[1],p->position[2]);
else if (p->type == SFG_PROJECTILE_PLASMA)
SFG_playSoundSafe(4,SFG_distantSoundVolume(pos[0],pos[1],pos[2]));
SFG_playGameSound(4,SFG_distantSoundVolume(pos[0],pos[1],pos[2]));
// remove the projectile
@ -2360,7 +2377,7 @@ void SFG_updateLevel()
) ? SFG_DOOR_UP_DOWN_MASK : 0x00;
if (upDownState != newUpDownState)
SFG_playSoundSafe(1,255);
SFG_playGameSound(1,255);
door->state = (door->state & ~SFG_DOOR_UP_DOWN_MASK) | newUpDownState;
@ -2567,7 +2584,7 @@ void SFG_gameStepPlaying()
}
if (sound != 255)
SFG_playSoundSafe(sound,255);
SFG_playGameSound(sound,255);
if (ammo != SFG_AMMO_NONE)
SFG_player.ammo[ammo] -= projectileCount;
@ -2970,7 +2987,7 @@ void SFG_gameStepPlaying()
SFG_removeItem(i);
SFG_player.lastItemTakenFrame = SFG_game.frame;
i--;
SFG_playSoundSafe(3,255);
SFG_playGameSound(3,255);
#endif
}
else if (
@ -3011,7 +3028,7 @@ void SFG_gameStepPlaying()
SFG_player.justTeleported = 1;
SFG_playSoundSafe(4,255);
SFG_playGameSound(4,255);
break;
}
@ -3104,12 +3121,12 @@ void SFG_gameStepMenu()
(SFG_game.selectedMenuItem < menuItems - 1))
{
SFG_game.selectedMenuItem++;
SFG_playSoundSafe(3,64);
SFG_playGameSound(3,64);
}
else if (SFG_keyRegisters(SFG_KEY_UP) && (SFG_game.selectedMenuItem > 0))
{
SFG_game.selectedMenuItem--;
SFG_playSoundSafe(3,64);
SFG_playGameSound(3,64);
}
else if (SFG_keyJustPressed(SFG_KEY_A))
{
@ -3135,6 +3152,23 @@ void SFG_gameStepMenu()
SFG_setGameState(SFG_GAME_STATE_MAP);
break;
case SFG_MENU_ITEM_SOUND:
SFG_LOG("sound changed");
SFG_game.soundSettings++;
SFG_playGameSound(3,64);
if ((SFG_game.soundSettings & 0x02) !=
((SFG_game.soundSettings - 1) & 0x02))
{
if (SFG_game.soundSettings & 0x02)
SFG_enableMusic(1);
else
SFG_enableMusic(0);
}
break;
default:
break;
}
@ -3145,12 +3179,12 @@ void SFG_gameStepMenu()
(SFG_game.selectedLevel < SFG_NUMBER_OF_LEVELS - 1))
{
SFG_game.selectedLevel++;
SFG_playSoundSafe(3,64);
SFG_playGameSound(3,64);
}
else if (SFG_keyRegisters(SFG_KEY_LEFT) && SFG_game.selectedLevel > 0)
{
SFG_game.selectedLevel--;
SFG_playSoundSafe(3,64);
SFG_playGameSound(3,64);
}
}
}
@ -3625,12 +3659,29 @@ void SFG_drawMenu()
SFG_drawText(text,drawX,y,SFG_FONT_SIZE_MEDIUM,textColor,0,0);
if (item == SFG_MENU_ITEM_PLAY &&
(((i != SFG_game.selectedMenuItem) ||
(SFG_game.frame / SFG_BLINK_PERIOD_FRAMES) % 2)))
SFG_drawNumber((SFG_game.selectedLevel + 1),
drawX + SFG_characterSize(SFG_FONT_SIZE_MEDIUM) * (textLen + 1),
y,SFG_FONT_SIZE_MEDIUM,93);
if ((item == SFG_MENU_ITEM_PLAY || item == SFG_MENU_ITEM_SOUND) &&
((i != SFG_game.selectedMenuItem) ||
((SFG_game.frame / SFG_BLINK_PERIOD_FRAMES) % 2)))
{
//uint8_t blink = (SFG_game.frame / SFG_BLINK_PERIOD_FRAMES) % 2;
uint32_t x =
drawX + SFG_characterSize(SFG_FONT_SIZE_MEDIUM) * (textLen + 1);
uint8_t c = 93;
if (item == SFG_MENU_ITEM_PLAY)
SFG_drawNumber((SFG_game.selectedLevel + 1),x,y,SFG_FONT_SIZE_MEDIUM,c);
else
{
char settingText[3] = " ";
settingText[0] = (SFG_game.soundSettings & 0x01) ? 'S' : ' ';
settingText[1] = (SFG_game.soundSettings & 0x02) ? 'M' : ' ';
SFG_drawText(settingText,x,y,SFG_FONT_SIZE_MEDIUM,c,0,0);
}
}
y += SFG_characterSize(SFG_FONT_SIZE_MEDIUM) + SFG_FONT_SIZE_MEDIUM;
i++;

View File

@ -188,16 +188,26 @@ static inline uint8_t addSamples(uint8_t sample1, uint8_t sample2)
return mixed;
}
uint8_t musicOn = 1;
void audioFillCallback(void *userdata, uint8_t *s, int l)
{
for (int i = 0; i < l; ++i)
{
s[i] = addSamples(audioBuff[audioPos],SFG_getNextMusicSample());
s[i] = musicOn ?
addSamples(audioBuff[audioPos],SFG_getNextMusicSample()) :
audioBuff[audioPos];
audioBuff[audioPos] = 127;
audioPos = (audioPos < SFG_SFX_SAMPLE_COUNT - 1) ? (audioPos + 1) : 0;
}
}
void SFG_enableMusic(uint8_t enable)
{
musicOn = enable;
}
void SFG_playSound(uint8_t soundIndex, uint8_t volume)
{
uint8_t volumeStep = volume / 16;

View File

@ -10,6 +10,9 @@
by Miloslav Ciz (drummyfish), 2019
Music is based on bytebeat (procedural waveforms generated by short bitwise
operation formulas).
Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
plus a waiver of all other intellectual property. The goal of this work is
be and remain completely in the public domain forever, available for any use
@ -34,6 +37,7 @@
struct
{ // all should be initialized to 0
// TODO: leave only those needed here
uint8_t track;
uint32_t t;
uint32_t t2;
@ -42,13 +46,17 @@ struct
uint32_t n7t;
} SFG_MusicState;
/**
Gets the next 8bit 8KHz music sample for the bytebeat soundtrack. This
function is to be used by the frontend that plays music.
*/
uint8_t SFG_getNextMusicSample()
{
if (SFG_MusicState.t >= SFG_TRACK_SAMPLES)
{
SFG_MusicState.track++;
if (SFG_MusicState.track >= 3)
if (SFG_MusicState.track >= 4)
SFG_MusicState.track = 0;
SFG_MusicState.t = 0;
@ -64,7 +72,7 @@ uint8_t SFG_getNextMusicSample()
#define t2 SFG_MusicState.t2
#define n3t SFG_MusicState.n3t
switch (SFG_MusicState.track)
switch (SFG_MusicState.track) // individual music tracks
{
case 0:
{
@ -82,6 +90,13 @@ uint8_t SFG_getNextMusicSample()
}
case 2:
{
result =
~((((t >> (t >> 2)) | (t >> (t >> 5))) & 0x12) << 1) | (t >> 11);
break;
}
case 3:
{
result =
((((t >> (t >> 2)) + (t >> (t >> 7)))) & 0x3f | (t >> 5) | (t >> 11))