Hi,
I've been trying to pin down an annoying performance bug in my C# 2d game engine.
It only occurs when I have sound enabled, and I am trying to figure out what I am doing wrong. I suspect multiple things, since the sound functionality was implemented quite a while ago to achieve basic functionality. At this stage in development it is now a higher priority. I need to resolve it.
When I implemented sound it was after much experimentation with sound APIs. I tried SoundPlayer, MediaPlayer, and WindowsMediaPlayer - with the latter the only one I could get working in an acceptable manner.
My implementation was based around setting up an array of players for each sound I wanted to play. They are all instantiated up-front. The method by which they are used is:
1. Search through player array until you find one which isn't currently playing.
2. Play the sound.
Now for some reason, which I can't figure out, this implementation is causing a wierd problem. I have a method which fires when you die, and from what I can tell this does NOTHING with sound whatsoever. It basically waits 5 seconds before restarting the game. But with sound on the screen flickers for a millisecond, something in sharpdevelop refreshes, and it's as if there is a sudden lag in the game. From a functionality point of view I don't have a problem - but the performance is unacceptable.
To give you an idea of what I'm doing, here is some code from my sound initialisation method:
if(soundLibrary=="WindowsMediaPlayer")
{
// Music player
WMP_Music = new WMPLib.WindowsMediaPlayer();
WMP_Music.settings.autoStart = false;
WMP_Music.URL = "D:\\Programming\\SFX\\MUSIC\\IN_GAME_1.wav";
// Array of players ----------------------------------------
WMP_EATEN_GHOST_Array = new WMPLib.WindowsMediaPlayer[EATEN_GHOST_noOfPlayers];
WMP_EATEN_PILL_Array = new WMPLib.WindowsMediaPlayer[EATEN_PILL_noOfPlayers];
WMP_EATEN_POWERPILL_Array = new WMPLib.WindowsMediaPlayer[EATEN_POWERPILL_noOfPlayers];
WMP_KILLED_BY_GHOST_Array = new WMPLib.WindowsMediaPlayer[KILLED_BY_GHOST_noOfPlayers];
for(int i=0;i<WMP_EATEN_GHOST_Array.Length;i++)
{
WMP_EATEN_GHOST_Array[i] = new WMPLib.WindowsMediaPlayer();
WMP_EATEN_GHOST_Array[i].settings.autoStart = false;
WMP_EATEN_GHOST_Array[i].URL = "D:\\Programming\\SFX\\EATEN_GHOST\\Hit_55.wav";
WMP_EATEN_PILL_Array[i] = new WMPLib.WindowsMediaPlayer();
WMP_EATEN_PILL_Array[i].settings.autoStart = false;
WMP_EATEN_PILL_Array[i].URL = "D:\\Programming\\SFX\\EATEN_PILL\\Hit_43_s.wav";
WMP_EATEN_POWERPILL_Array[i] = new WMPLib.WindowsMediaPlayer();
WMP_EATEN_POWERPILL_Array[i].settings.autoStart = false;
WMP_EATEN_POWERPILL_Array[i].URL = "D:\\Programming\\SFX\\EATEN_POWERPILL\\Hit_49.wav";
WMP_KILLED_BY_GHOST_Array[i] = new WMPLib.WindowsMediaPlayer();
WMP_KILLED_BY_GHOST_Array[i].settings.autoStart = false;
WMP_KILLED_BY_GHOST_Array[i].URL = "D:\\Programming\\SFX\\KILLED_BY_GHOST\\Hit_55.wav";
}
So with these set up, here's the code which plays the sound:
public void PlayPCM_WindowsMediaPlayer_FX(string effectIn)
{
int i=-1;
bool found = false;
if(soundEnabled)
{
switch(effectIn)
{
case "KILLED_BY_GHOST":
// 1. Choose a media player which is not playing.
i = 0;
do
{
if(WMP_KILLED_BY_GHOST_Array[i].playState == WMPLib.WMPPlayState.wmppsPlaying)
{
// Keep looking
i++;
}
else
{
found = true;
}
} while( (i<WMP_KILLED_BY_GHOST_Array.Length) && (!found));
// Now 'i' holds the index of the player which is not playing.
// 2. Play effect
if(found)
{
Thread thread = new Thread(new ThreadStart( WMP_KILLED_BY_GHOST_Array[i].controls.play ));
thread.Start();
}
break;
case "EATEN_PILL":
// 1. Choose a media player which is not playing.
i = 0;
do
{
if(WMP_EATEN_PILL_Array[i].playState == WMPLib.WMPPlayState.wmppsPlaying)
{
// Keep looking
i++;
}
else
{
found = true;
}
} while( (i<WMP_EATEN_PILL_Array.Length) && (!found));
// Now 'i' holds the index of the player which is not playing.
// 2. Play effect
if(found)
{
Thread thread = new Thread(new ThreadStart( WMP_EATEN_PILL_Array[i].controls.play ));
thread.Start();
}
break;
case "EATEN_GHOST":
// 1. Choose a media player which is not playing.
i = 0;
do
{
if(WMP_EATEN_GHOST_Array[i].playState == WMPLib.WMPPlayState.wmppsPlaying)
{
// Keep looking
i++;
}
else
{
found = true;
}
} while( (i<WMP_EATEN_GHOST_Array.Length) && (!found));
// Now 'i' holds the index of the player which is not playing.
// 2. Play effect
if(found)
{
Thread thread = new Thread(new ThreadStart( WMP_EATEN_GHOST_Array[i].controls.play ));
thread.Start();
}
break;
case "EATEN_POWERPILL":
// 1. Choose a media player which is not playing.
i = 0;
do
{
if(WMP_EATEN_POWERPILL_Array[i].playState == WMPLib.WMPPlayState.wmppsPlaying)
{
// Keep looking
i++;
}
else
{
found = true;
}
} while( (i<WMP_EATEN_POWERPILL_Array.Length) && (!found));
// Now 'i' holds the index of the player which is not playing.
// 2. Play effect
if(found)
{
Thread thread = new Thread(new ThreadStart( WMP_EATEN_POWERPILL_Array[i].controls.play ));
thread.Start();
}
break;
} // switch
} // soundEnabled
}
It's pretty clunky I know, but it worked at the time - well enough anyway. Can anyone see anything which would explain why I get a screen flicker?
My threading expertise is really basic at the moment.
Thanks in advance