This blog post is a follow-up of the previous one dedicated to the Shock improvements.
I'll just list all tips or other interesting findings/updates in no particular order:
Playing Short Sounds in Silverlight (Improved)
You probably know by now that Silverlight (2,3) has an annoying issue with short sounds - sometimes the sound is not played correctly. The simple workaround is here.
If you happen to play too many sounds/sec, the above workaround can cause your memory usage to grow more than you want to for short time. The easiest way to avoid the surge in mem usage is to cache the streams that contain the .mp3 sounds, like this:
private static Dictionary<string, Stream> _streams = new Dictionary<string, Stream>();
public static void PlayShortSound(string embeddedSoundName, double volume)
{
Stream stream;
if (!_streams.TryGetValue(embeddedSoundName, out stream))
{
stream = Application.GetResourceStream(new Uri(String.Format("/Shock;component/Sounds/{0}", embeddedSoundName), UriKind.Relative)).Stream;
_streams[embeddedSoundName] = stream;
}
MediaElement media = new MediaElement();
_soundContainer.Children.Add(media);
media.MediaFailed += media_MediaFailed;
media.MediaEnded += media_MediaEnded;
media.Volume = volume;
media.AutoPlay = true;
media.Position = TimeSpan.FromMilliseconds(0);
media.SetSource(stream);
}
Then, just call the function like this example: PlayShortSound("explosion.mp3"). You can use this trick, because multiple sounds using the same stream don't cause issues with each other, which is nice.
"Shatter" Effect
In my previous blog post I mentioned the "shatter" brick effect, which is based on this one: http://www.shinedraw.com/animation-effect/flash-vs-silverlight-colorful-fireworks/
I changed the effect and made it self-recycling: removes itself from the parent after a given time period. It will also display "fireworks" in an area, not a dot. All of these are really small modifications, but help make the effect "run and forget", and easy to use for "shattering" stuff like bricks.
Here's an usage sample:
public static TimeSpan ShatterEffectTimeSpan = TimeSpan.FromSeconds(0.3);
Fireworks fireworks = new Fireworks(TimeSpan.FromSeconds(0.3), (int)width, (int)height, brickAppearance == BrickAppearance.Ice);
Canvas.SetLeft(fireworks, centerX);
Canvas.SetTop(fireworks, centerY);
Globals.BoomContaier.Children.Add(fireworks);
fireworks.Start();
And here's the source code. Note: get the complete sample from the shinedraw.com link above and then change the 2 files below. The code won't compile, but you just have to call your own Random() function, and maybe fix few other basic things.
Fireworks.xaml.cs (4.98 kb) MagicDot.cs (2.89 kb)
I want to call out something very interesting in the above effect (not made by me originally) - each MagicDot is created within its own container. I believe it will cause less layout work than putting all dots within the same container (this is a gut-feeling unverified speculation)
If you want to see the shatter effect in action, break the ice bricks on level 2 of Shock: http://nokola.com/shock
When (Not) To Use BitmapCache, Even For Images That Don't Move
I found out that if I use CacheMode="BitmapCache" for each brick (100+ per level), the performance suffers. This is very interesting, and is something to keep in mind when using bitmap cache.
Seems like the larger the image, the better.
More On Speed
Some blogs (don't remember where) mention that images with Opacity=0 still render and take valuable CPU/GPU time - I tested it and it seems that in Silverlight 4 Beta this is not the case.
I observed no noticeable speed change when a UserControl (the highscore) had Opacity=0 vs Visibility=Invisible. Note, however that Opacity=0 means you get hit testing, so there is some speed difference - don't just blindly overuse Opacity=0 instead of Visibility=Invisible.