Version 1.12

Added Numpad Keys,
Fixed ResourcePack code on Linux
Updated Sound PGEX to be compilable, but not functional on linux
pull/113/head
Javidx9 6 years ago committed by GitHub
parent 742e5d1c3a
commit f8bda426d4
  1. 188
      olcPGEX_Sound.h
  2. 50
      olcPixelGameEngine.h

@ -69,6 +69,16 @@
#undef min
#undef max
typedef struct {
unsigned short wFormatTag;
unsigned short nChannels;
unsigned long nSamplesPerSec;
unsigned long nAvgBytesPerSec;
unsigned short nBlockAlign;
unsigned short wBitsPerSample;
unsigned short cbSize;
} OLC_WAVEFORMATEX;
namespace olc
{
// Container class for Advanced 2D Drawing functions
@ -84,7 +94,7 @@ namespace olc
olc::rcode LoadFromFile(std::string sWavFile, olc::ResourcePack *pack = nullptr);
public:
WAVEFORMATEX wavHeader;
OLC_WAVEFORMATEX wavHeader;
float *fSample = nullptr;
long nSamples = 0;
int nChannels = 0;
@ -115,10 +125,10 @@ namespace olc
static void StopAll();
static float GetMixerOutput(int nChannel, float fGlobalTime, float fTimeStep);
#ifdef WIN32
private:
#ifdef WIN32 // Windows specific sound management
static void CALLBACK waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD dwParam1, DWORD dwParam2);
static void AudioThread();
static unsigned int m_nSampleRate;
static unsigned int m_nChannels;
static unsigned int m_nBlockCount;
@ -127,15 +137,18 @@ namespace olc
static short* m_pBlockMemory;
static WAVEHDR *m_pWaveHeaders;
static HWAVEOUT m_hwDevice;
static std::thread m_AudioThread;
static std::atomic<bool> m_bAudioThreadActive;
static std::atomic<unsigned int> m_nBlockFree;
static std::condition_variable m_cvBlockNotZero;
static std::mutex m_muxBlockNotZero;
#endif
static void AudioThread();
static std::thread m_AudioThread;
static std::atomic<bool> m_bAudioThreadActive;
static std::atomic<float> m_fGlobalTime;
static std::function<float(int, float, float)> funcUserSynth;
static std::function<float(int, float, float)> funcUserFilter;
#endif
};
}
@ -143,14 +156,11 @@ namespace olc
#ifdef WIN32
#pragma comment(lib, "winmm.lib")
namespace olc
{
SOUND::AudioSample::AudioSample()
{
}
{ }
SOUND::AudioSample::AudioSample(std::string sWavFile, olc::ResourcePack *pack)
{
@ -506,8 +516,162 @@ namespace olc
std::function<float(int, float, float)> SOUND::funcUserSynth = nullptr;
std::function<float(int, float, float)> SOUND::funcUserFilter = nullptr;
}
#else // Non Windows
namespace olc
{
SOUND::AudioSample::AudioSample()
{}
SOUND::AudioSample::AudioSample(std::string sWavFile, olc::ResourcePack *pack)
{
LoadFromFile(sWavFile, pack);
}
olc::rcode SOUND::AudioSample::LoadFromFile(std::string sWavFile, olc::ResourcePack *pack)
{
return olc::OK;
}
bool SOUND::InitialiseAudio(unsigned int nSampleRate, unsigned int nChannels, unsigned int nBlocks, unsigned int nBlockSamples)
{
return true;
}
// Stop and clean up audio system
bool SOUND::DestroyAudio()
{
return false;
}
// Audio thread. This loop responds to requests from the soundcard to fill 'blocks'
// with audio data. If no requests are available it goes dormant until the sound
// card is ready for more data. The block is fille by the "user" in some manner
// and then issued to the soundcard.
void SOUND::AudioThread()
{
}
// This vector holds all loaded sound samples in memory
std::vector<olc::SOUND::AudioSample> vecAudioSamples;
// This structure represents a sound that is currently playing. It only
// holds the sound ID and where this instance of it is up to for its
// current playback
void SOUND::SetUserSynthFunction(std::function<float(int, float, float)> func)
{
funcUserSynth = func;
}
void SOUND::SetUserFilterFunction(std::function<float(int, float, float)> func)
{
funcUserFilter = func;
}
// Load a 16-bit WAVE file @ 44100Hz ONLY into memory. A sample ID
// number is returned if successful, otherwise -1
unsigned int SOUND::LoadAudioSample(std::string sWavFile, olc::ResourcePack *pack)
{
olc::SOUND::AudioSample a(sWavFile, pack);
if (a.bSampleValid)
{
vecAudioSamples.push_back(a);
return vecAudioSamples.size();
}
else
return -1;
}
// Add sample 'id' to the mixers sounds to play list
void SOUND::PlaySample(int id, bool bLoop)
{
olc::SOUND::sCurrentlyPlayingSample a;
a.nAudioSampleID = id;
a.nSamplePosition = 0;
a.bFinished = false;
a.bFlagForStop = false;
a.bLoop = bLoop;
SOUND::listActiveSamples.push_back(a);
}
void SOUND::StopSample(int id)
{
// Find first occurence of sample id
auto s = std::find_if(listActiveSamples.begin(), listActiveSamples.end(), [&](const olc::SOUND::sCurrentlyPlayingSample &s) { return s.nAudioSampleID == id; });
if (s != listActiveSamples.end())
s->bFlagForStop = true;
}
void SOUND::StopAll()
{
for (auto &s : listActiveSamples)
{
s.bFlagForStop = true;
}
}
float SOUND::GetMixerOutput(int nChannel, float fGlobalTime, float fTimeStep)
{
// Accumulate sample for this channel
float fMixerSample = 0.0f;
for (auto &s : listActiveSamples)
{
if (m_bAudioThreadActive)
{
if (s.bFlagForStop)
{
s.bLoop = false;
s.bFinished = true;
}
else
{
// Calculate sample position
s.nSamplePosition += (long)((float)vecAudioSamples[s.nAudioSampleID - 1].wavHeader.nSamplesPerSec * fTimeStep);
// If sample position is valid add to the mix
if (s.nSamplePosition < vecAudioSamples[s.nAudioSampleID - 1].nSamples)
fMixerSample += vecAudioSamples[s.nAudioSampleID - 1].fSample[(s.nSamplePosition * vecAudioSamples[s.nAudioSampleID - 1].nChannels) + nChannel];
else
{
if (s.bLoop)
{
s.nSamplePosition = 0;
}
else
s.bFinished = true; // Else sound has completed
}
}
}
else
return 0.0f;
}
// If sounds have completed then remove them
listActiveSamples.remove_if([](const sCurrentlyPlayingSample &s) {return s.bFinished; });
// The users application might be generating sound, so grab that if it exists
if (funcUserSynth != nullptr)
fMixerSample += funcUserSynth(nChannel, fGlobalTime, fTimeStep);
// Return the sample via an optional user override to filter the sound
if (funcUserFilter != nullptr)
return funcUserFilter(nChannel, fGlobalTime, fMixerSample);
else
return fMixerSample;
}
std::thread SOUND::m_AudioThread;
std::atomic<bool> SOUND::m_bAudioThreadActive{ false };
std::atomic<float> SOUND::m_fGlobalTime{ 0.0f };
std::list<SOUND::sCurrentlyPlayingSample> SOUND::listActiveSamples;
std::function<float(int, float, float)> SOUND::funcUserSynth = nullptr;
std::function<float(int, float, float)> SOUND::funcUserFilter = nullptr;
}
#endif
// Currently no Linux implementation so just go blank :(
#endif

@ -2,12 +2,10 @@
olcPixelGameEngine.h
+-------------------------------------------------------------+
| OneLoneCoder Pixel Game Engine v1.11 |
| OneLoneCoder Pixel Game Engine v1.12 |
| "Like the command prompt console one, but not..." - javidx9 |
+-------------------------------------------------------------+
The Original & Best... :P
What is this?
~~~~~~~~~~~~~
The olcConsoleGameEngine has been a surprsing and wonderful
@ -90,6 +88,7 @@
Twitch: https://www.twitch.tv/javidx9
GitHub: https://www.github.com/onelonecoder
Homepage: https://www.onelonecoder.com
Patreon: https://www.patreon.com/javidx9
Relevant Videos
~~~~~~~~~~~~~~~
@ -121,17 +120,20 @@
~~~~~~
I'd like to extend thanks to Eremiell, slavka, gurkanctn, Phantim,
JackOJC, KrossX, Huhlig, Dragoneye, Appa, JustinRichardsMusic, SliceNDice
& MagetzUb for advice, ideas and testing, and I'd like to extend
my appreciation to the 14K YouTube followers and 1K Discord server
Ralakus, Gorbit99, raoul & MagetzUb for advice, ideas and testing, and I'd like
to extend my appreciation to the 23K YouTube followers and 1.5K Discord server
members who give me the motivation to keep going with all this :D
Special thanks to those who bring gifts!
GnarGnarHead.......Domina
Gorbit99...........Bastion
Special thanks to my Patreons too - I wont name you on here, but I've
certainly enjoyed my tea and flapjacks :D
Author
~~~~~~
David Barr, aka javidx9, ©OneLoneCoder 2018
David Barr, aka javidx9, ©OneLoneCoder 2018, 2019
*/
//////////////////////////////////////////////////////////////////////////////////////////
@ -279,7 +281,8 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
ResourcePack();
~ResourcePack();
struct sEntry : public std::streambuf {
uint32_t nID, nFileOffset, nFileSize; uint8_t* data; void _config() { this->setg((char*)data, (char*)data, (char*)(data + nFileSize)); }};
uint32_t nID, nFileOffset, nFileSize; uint8_t* data; void _config() { this->setg((char*)data, (char*)data, (char*)(data + nFileSize)); }
};
public:
olc::rcode AddToPack(std::string sFile);
@ -346,7 +349,9 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
UP, DOWN, LEFT, RIGHT,
SPACE, TAB, SHIFT, CTRL, INS, DEL, HOME, END, PGUP, PGDN,
BACK, ESCAPE, ENTER, PAUSE, SCROLL,
BACK, ESCAPE, RETURN, ENTER, PAUSE, SCROLL,
NP0, NP1, NP2, NP3, NP4, NP5, NP6, NP7, NP8, NP9,
NP_MUL, NP_DIV, NP_ADD, NP_SUB, NP_DECIMAL,
};
@ -402,6 +407,7 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
// olc::Pixel::MASK = Transparent if alpha is < 255
// olc::Pixel::ALPHA = Full transparency
void SetPixelMode(Pixel::Mode m);
Pixel::Mode GetPixelMode();
// Use a custom blend function
void SetPixelMode(std::function<olc::Pixel(const int x, const int y, const olc::Pixel& pSource, const olc::Pixel& pDest)> pixelMode);
// Change the blend factor form between 0.0f to 1.0f;
@ -647,7 +653,8 @@ namespace olc
}
else
{
std::istream is(&(pack->GetStreamBuffer(sImageFile)));
auto streamBuffer = pack->GetStreamBuffer(sImageFile);
std::istream is(&streamBuffer);
ReadData(is);
}
@ -852,10 +859,10 @@ namespace olc
// Create entry
sEntry e;
e.data = nullptr;
e.nFileSize = p;
e.nFileSize = (uint32_t)p;
// Read file into memory
e.data = new uint8_t[e.nFileSize];
e.data = new uint8_t[(uint32_t)e.nFileSize];
ifs.read((char*)e.data, e.nFileSize);
ifs.close();
@ -886,7 +893,7 @@ namespace olc
std::streampos offset = ofs.tellp();
for (auto &e : mapFiles)
{
e.second.nFileOffset = offset;
e.second.nFileOffset = (uint32_t)offset;
ofs.write((char*)e.second.data, e.second.nFileSize);
offset += e.second.nFileSize;
}
@ -936,12 +943,10 @@ namespace olc
// 2) Read Data
for (auto &e : mapFiles)
{
e.second.data = new uint8_t[e.second.nFileSize];
e.second.data = new uint8_t[(uint32_t)e.second.nFileSize];
ifs.seekg(e.second.nFileOffset);
ifs.read((char*)e.second.data, e.second.nFileSize);
//e.second.setg
e.second._config();
//e.second.pubsetbuf((char*)e.second.data, e.second.nFileSize);
}
ifs.close();
@ -1542,6 +1547,11 @@ namespace olc
nPixelMode = m;
}
Pixel::Mode PixelGameEngine::GetPixelMode()
{
return nPixelMode;
}
void PixelGameEngine::SetPixelMode(std::function<olc::Pixel(const int x, const int y, const olc::Pixel&, const olc::Pixel&)> pixelMode)
{
funcPixelMode = pixelMode;
@ -1884,6 +1894,7 @@ namespace olc
mapKeys[VK_F9] = Key::F9; mapKeys[VK_F10] = Key::F10; mapKeys[VK_F11] = Key::F11; mapKeys[VK_F12] = Key::F12;
mapKeys[VK_DOWN] = Key::DOWN; mapKeys[VK_LEFT] = Key::LEFT; mapKeys[VK_RIGHT] = Key::RIGHT; mapKeys[VK_UP] = Key::UP;
mapKeys[VK_RETURN] = Key::ENTER; //mapKeys[VK_RETURN] = Key::RETURN;
mapKeys[VK_BACK] = Key::BACK; mapKeys[VK_ESCAPE] = Key::ESCAPE; mapKeys[VK_RETURN] = Key::ENTER; mapKeys[VK_PAUSE] = Key::PAUSE;
mapKeys[VK_SCROLL] = Key::SCROLL; mapKeys[VK_TAB] = Key::TAB; mapKeys[VK_DELETE] = Key::DEL; mapKeys[VK_HOME] = Key::HOME;
@ -1894,6 +1905,10 @@ namespace olc
mapKeys[0x30] = Key::K0; mapKeys[0x31] = Key::K1; mapKeys[0x32] = Key::K2; mapKeys[0x33] = Key::K3; mapKeys[0x34] = Key::K4;
mapKeys[0x35] = Key::K5; mapKeys[0x36] = Key::K6; mapKeys[0x37] = Key::K7; mapKeys[0x38] = Key::K8; mapKeys[0x39] = Key::K9;
mapKeys[VK_NUMPAD0] = Key::NP0; mapKeys[VK_NUMPAD1] = Key::NP1; mapKeys[VK_NUMPAD2] = Key::NP2; mapKeys[VK_NUMPAD3] = Key::NP3; mapKeys[VK_NUMPAD4] = Key::NP4;
mapKeys[VK_NUMPAD5] = Key::NP5; mapKeys[VK_NUMPAD6] = Key::NP6; mapKeys[VK_NUMPAD7] = Key::NP7; mapKeys[VK_NUMPAD8] = Key::NP8; mapKeys[VK_NUMPAD9] = Key::NP9;
mapKeys[VK_MULTIPLY] = Key::NP_MUL; mapKeys[VK_ADD] = Key::NP_ADD; mapKeys[VK_DIVIDE] = Key::NP_DIV; mapKeys[VK_SUBTRACT] = Key::NP_SUB; mapKeys[VK_DECIMAL] = Key::NP_DECIMAL;
return olc_hWnd;
}
@ -1995,6 +2010,7 @@ namespace olc
mapKeys[XK_F9] = Key::F9; mapKeys[XK_F10] = Key::F10; mapKeys[XK_F11] = Key::F11; mapKeys[XK_F12] = Key::F12;
mapKeys[XK_Down] = Key::DOWN; mapKeys[XK_Left] = Key::LEFT; mapKeys[XK_Right] = Key::RIGHT; mapKeys[XK_Up] = Key::UP;
mapKeys[XK_KP_Enter] = Key::ENTER; mapKeys[XK_Return] = Key::ENTER;
mapKeys[XK_BackSpace] = Key::BACK; mapKeys[XK_Escape] = Key::ESCAPE; mapKeys[XK_Linefeed] = Key::ENTER; mapKeys[XK_Pause] = Key::PAUSE;
mapKeys[XK_Scroll_Lock] = Key::SCROLL; mapKeys[XK_Tab] = Key::TAB; mapKeys[XK_Delete] = Key::DEL; mapKeys[XK_Home] = Key::HOME;
@ -2005,6 +2021,10 @@ namespace olc
mapKeys[XK_0] = Key::K0; mapKeys[XK_1] = Key::K1; mapKeys[XK_2] = Key::K2; mapKeys[XK_3] = Key::K3; mapKeys[XK_4] = Key::K4;
mapKeys[XK_5] = Key::K5; mapKeys[XK_6] = Key::K6; mapKeys[XK_7] = Key::K7; mapKeys[XK_8] = Key::K8; mapKeys[XK_9] = Key::K9;
mapKeys[XK_KP_0] = Key::NP0; mapKeys[XK_KP_1] = Key::NP1; mapKeys[XK_KP_2] = Key::NP2; mapKeys[XK_KP_3] = Key::NP3; mapKeys[XK_KP_4] = Key::NP4;
mapKeys[XK_KP_5] = Key::NP5; mapKeys[XK_KP_6] = Key::NP6; mapKeys[XK_KP_7] = Key::NP7; mapKeys[XK_KP_8] = Key::NP8; mapKeys[XK_KP_9] = Key::NP9;
mapKeys[XK_KP_Multiply] = Key::NP_MUL; mapKeys[XK_KP_Add] = Key::NP_ADD; mapKeys[XK_KP_Divide] = Key::NP_DIV; mapKeys[XK_KP_Subtract] = Key::NP_SUB; mapKeys[XK_KP_Decimal] = Key::NP_DECIMAL;
return olc_Display;
}

Loading…
Cancel
Save