mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-06-26 06:28:30 +02:00
In C++, when you have two variables in different scopes with the same name, the inner scope wins. Except you have to be really careful because sometimes they're not (#507). So it's better to just always have unique variable names and make sure to never clash a name with a variable in an outer scope - after all, the C++ compiler and standard might be fine with it, but that doesn't mean humans can't make mistakes reading or writing it. Usually I just renamed the inner variables, but for tx/ty in editor.cpp, I just got rid of the ridiculous overcomplicated modulo calculations and replaced them with actual simple modulo calculations, because the existing ones were just ridiculous. Actually, somebody ought to find every instance of the overcomplicated modulos and replace them with the actual good ones, because it's really stupid, quite frankly...
363 lines
8.0 KiB
C++
363 lines
8.0 KiB
C++
#define MUSIC_DEFINITION
|
|
#include "Music.h"
|
|
|
|
#include <SDL.h>
|
|
#include <stdio.h>
|
|
|
|
#include "BinaryBlob.h"
|
|
#include "Map.h"
|
|
#include "UtilityClass.h"
|
|
|
|
void songend();
|
|
|
|
void musicclass::init()
|
|
{
|
|
for (size_t i = 0; i < soundTracks.size(); ++i) {
|
|
Mix_FreeChunk(soundTracks[i].sound);
|
|
}
|
|
soundTracks.clear();
|
|
for (size_t i = 0; i < musicTracks.size(); ++i) {
|
|
Mix_FreeMusic(musicTracks[i].m_music);
|
|
}
|
|
musicTracks.clear();
|
|
|
|
musicReadBlob.clear();
|
|
|
|
soundTracks.push_back(SoundTrack( "sounds/jump.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/jump2.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/hurt.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/souleyeminijingle.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/coin.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/save.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crumble.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/vanish.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/blip.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/preteleport.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/teleport.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew1.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew2.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew3.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew4.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew5.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew6.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/terminal.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/gamesaved.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crashing.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/blip2.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/countdown.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/go.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crash.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/combine.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/newrecord.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/trophy.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/rescue.wav" ));
|
|
|
|
#ifdef VVV_COMPILEMUSIC
|
|
binaryBlob musicWriteBlob;
|
|
#define FOREACH_TRACK(track_name) musicWriteBlob.AddFileToBinaryBlob(track_name);
|
|
TRACK_NAMES
|
|
#undef FOREACH_TRACK
|
|
|
|
musicWriteBlob.writeBinaryBlob("data/BinaryMusic.vvv");
|
|
#endif
|
|
|
|
num_mmmmmm_tracks = 0;
|
|
num_pppppp_tracks = 0;
|
|
|
|
if (!musicReadBlob.unPackBinary("mmmmmm.vvv"))
|
|
{
|
|
mmmmmm = false;
|
|
usingmmmmmm=false;
|
|
bool ohCrap = musicReadBlob.unPackBinary("vvvvvvmusic.vvv");
|
|
SDL_assert(ohCrap && "Music not found!");
|
|
}
|
|
else
|
|
{
|
|
mmmmmm = true;
|
|
usingmmmmmm = true;
|
|
int index;
|
|
SDL_RWops *rw;
|
|
|
|
#define FOREACH_TRACK(track_name) \
|
|
index = musicReadBlob.getIndex(track_name); \
|
|
if (index >= 0 && index < musicReadBlob.max_headers) \
|
|
{ \
|
|
rw = SDL_RWFromMem(musicReadBlob.getAddress(index), musicReadBlob.getSize(index)); \
|
|
if (rw == NULL) \
|
|
{ \
|
|
printf("Unable to read music file header: %s\n", SDL_GetError()); \
|
|
} \
|
|
else \
|
|
{ \
|
|
musicTracks.push_back(MusicTrack( rw )); \
|
|
} \
|
|
}
|
|
|
|
TRACK_NAMES
|
|
|
|
num_mmmmmm_tracks += musicTracks.size();
|
|
|
|
const std::vector<int> extra = musicReadBlob.getExtra();
|
|
for (size_t i = 0; i < extra.size(); i++)
|
|
{
|
|
const int& index_ = extra[i];
|
|
rw = SDL_RWFromMem(musicReadBlob.getAddress(index_), musicReadBlob.getSize(index_));
|
|
musicTracks.push_back(MusicTrack( rw ));
|
|
|
|
num_mmmmmm_tracks++;
|
|
}
|
|
|
|
bool ohCrap = musicReadBlob.unPackBinary("vvvvvvmusic.vvv");
|
|
SDL_assert(ohCrap && "Music not found!");
|
|
}
|
|
|
|
int index;
|
|
SDL_RWops *rw;
|
|
|
|
TRACK_NAMES
|
|
|
|
#undef FOREACH_TRACK
|
|
|
|
num_pppppp_tracks += musicTracks.size() - num_mmmmmm_tracks;
|
|
|
|
const std::vector<int> extra = musicReadBlob.getExtra();
|
|
for (size_t i = 0; i < extra.size(); i++)
|
|
{
|
|
const int& index_ = extra[i];
|
|
rw = SDL_RWFromMem(musicReadBlob.getAddress(index_), musicReadBlob.getSize(index_));
|
|
musicTracks.push_back(MusicTrack( rw ));
|
|
|
|
num_pppppp_tracks++;
|
|
}
|
|
|
|
safeToProcessMusic= false;
|
|
m_doFadeInVol = false;
|
|
musicVolume = MIX_MAX_VOLUME;
|
|
FadeVolAmountPerFrame = 0;
|
|
|
|
currentsong = 0;
|
|
nicechange = 0;
|
|
nicefade = 0;
|
|
resumesong = 0;
|
|
fadeoutqueuesong = -1;
|
|
dontquickfade = false;
|
|
|
|
songStart = 0;
|
|
songEnd = 0;
|
|
|
|
Mix_HookMusicFinished(&songend);
|
|
|
|
usingmmmmmm = false;
|
|
}
|
|
|
|
void songend()
|
|
{
|
|
extern musicclass music;
|
|
music.songEnd = SDL_GetPerformanceCounter();
|
|
music.currentsong = -1;
|
|
}
|
|
|
|
void musicclass::play(int t, const double position_sec /*= 0.0*/, const int fadein_ms /*= 3000*/)
|
|
{
|
|
if (mmmmmm && usingmmmmmm)
|
|
{
|
|
// Don't conjoin this if-statement with the above one...
|
|
if (num_mmmmmm_tracks > 0)
|
|
{
|
|
t %= num_mmmmmm_tracks;
|
|
}
|
|
}
|
|
else if (num_pppppp_tracks > 0)
|
|
{
|
|
t %= num_pppppp_tracks;
|
|
}
|
|
|
|
if(mmmmmm && !usingmmmmmm)
|
|
{
|
|
t += num_mmmmmm_tracks;
|
|
}
|
|
safeToProcessMusic = true;
|
|
musicVolume = MIX_MAX_VOLUME;
|
|
if (currentsong !=t)
|
|
{
|
|
if (t != -1)
|
|
{
|
|
currentsong = t;
|
|
if (!INBOUNDS_VEC(t, musicTracks))
|
|
{
|
|
puts("play() out-of-bounds!");
|
|
currentsong = -1;
|
|
return;
|
|
}
|
|
if (currentsong == 0 || currentsong == 7 || (!map.custommode && (currentsong == 0+num_pppppp_tracks || currentsong == 7+num_pppppp_tracks)))
|
|
{
|
|
// Level Complete theme, no fade in or repeat
|
|
if(Mix_FadeInMusicPos(musicTracks[t].m_music, 0, 0, position_sec)==-1)
|
|
{
|
|
printf("Mix_FadeInMusicPos: %s\n", Mix_GetError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Mix_FadingMusic() == MIX_FADING_OUT) {
|
|
// We're already fading out
|
|
fadeoutqueuesong = t;
|
|
currentsong = -1;
|
|
if (!dontquickfade)
|
|
Mix_FadeOutMusic(500); // fade out quicker
|
|
else
|
|
dontquickfade = false;
|
|
}
|
|
else if(Mix_FadeInMusicPos(musicTracks[t].m_music, -1, fadein_ms, position_sec)==-1)
|
|
{
|
|
printf("Mix_FadeInMusicPos: %s\n", Mix_GetError());
|
|
}
|
|
}
|
|
|
|
songStart = SDL_GetPerformanceCounter();
|
|
}
|
|
else
|
|
{
|
|
currentsong = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void musicclass::resume(const int fadein_ms /*= 0*/)
|
|
{
|
|
const double offset = static_cast<double>(songEnd - songStart);
|
|
const double frequency = static_cast<double>(SDL_GetPerformanceFrequency());
|
|
|
|
const double position_sec = offset / frequency;
|
|
|
|
play(resumesong, position_sec, fadein_ms);
|
|
}
|
|
|
|
void musicclass::fadein()
|
|
{
|
|
resume(3000); // 3000 ms fadein
|
|
}
|
|
|
|
void musicclass::haltdasmusik()
|
|
{
|
|
Mix_HaltMusic();
|
|
resumesong = currentsong;
|
|
}
|
|
|
|
void musicclass::silencedasmusik()
|
|
{
|
|
musicVolume = 0;
|
|
}
|
|
|
|
void musicclass::fadeMusicVolumeIn(int ms)
|
|
{
|
|
m_doFadeInVol = true;
|
|
FadeVolAmountPerFrame = MIX_MAX_VOLUME / (ms / 33);
|
|
}
|
|
|
|
void musicclass::fadeout()
|
|
{
|
|
Mix_FadeOutMusic(2000);
|
|
resumesong = currentsong;
|
|
}
|
|
|
|
void musicclass::processmusicfadein()
|
|
{
|
|
musicVolume += FadeVolAmountPerFrame;
|
|
if (musicVolume >= MIX_MAX_VOLUME)
|
|
{
|
|
m_doFadeInVol = false;
|
|
}
|
|
}
|
|
|
|
void musicclass::processmusic()
|
|
{
|
|
if(!safeToProcessMusic)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (fadeoutqueuesong != -1 && Mix_PlayingMusic() == 0) {
|
|
play(fadeoutqueuesong);
|
|
fadeoutqueuesong = -1;
|
|
}
|
|
|
|
if (nicefade == 1 && Mix_PlayingMusic() == 0)
|
|
{
|
|
play(nicechange);
|
|
nicechange = -1; nicefade = 0;
|
|
}
|
|
|
|
if(m_doFadeInVol)
|
|
{
|
|
processmusicfadein();
|
|
}
|
|
}
|
|
|
|
|
|
void musicclass::niceplay(int t)
|
|
{
|
|
// important: do nothing if the correct song is playing!
|
|
if((!mmmmmm && currentsong!=t) || (mmmmmm && usingmmmmmm && currentsong!=t) || (mmmmmm && !usingmmmmmm && currentsong!=t+16))
|
|
{
|
|
if(currentsong!=-1)
|
|
{
|
|
dontquickfade = true;
|
|
fadeout();
|
|
}
|
|
nicefade = 1;
|
|
nicechange = t;
|
|
}
|
|
}
|
|
|
|
void musicclass::changemusicarea(int x, int y)
|
|
{
|
|
switch(musicroom(x, y))
|
|
{
|
|
case musicroom(11, 4):
|
|
niceplay(2);
|
|
break;
|
|
|
|
case musicroom(2, 4):
|
|
case musicroom(7, 15):
|
|
niceplay(3);
|
|
break;
|
|
|
|
case musicroom(18, 1):
|
|
case musicroom(15, 0):
|
|
niceplay(12);
|
|
break;
|
|
|
|
case musicroom(0, 0):
|
|
case musicroom(0, 16):
|
|
case musicroom(2, 11):
|
|
case musicroom(7, 9):
|
|
case musicroom(8, 11):
|
|
case musicroom(13, 2):
|
|
case musicroom(17, 12):
|
|
case musicroom(14, 19):
|
|
case musicroom(17, 17):
|
|
niceplay(4);
|
|
break;
|
|
|
|
default:
|
|
niceplay(1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void musicclass::playef(int t)
|
|
{
|
|
if (!INBOUNDS_VEC(t, soundTracks))
|
|
{
|
|
return;
|
|
}
|
|
int channel;
|
|
|
|
channel = Mix_PlayChannel(-1, soundTracks[t].sound, 0);
|
|
if(channel == -1)
|
|
{
|
|
fprintf(stderr, "Unable to play WAV file: %s\n", Mix_GetError());
|
|
}
|
|
}
|