3
\$\begingroup\$

I'm working on a project that requires doing sprite based animation in XAML / C# for a windows store app. I've worked out a method for displaying the animation, but it causes flickering during the initial load of the images. The method I used basically involves creating a class which subclasses canvas that loops through all children during the its CompositionTarget.Rendering event. If any of the child objects are of type SpriteImage (another class I created that subclasses content control and is a container for the image control that displays the current frame) it calls the update method so that the SpriteImage may display the appropriate bitmap image for the current frame.

I have shared the sample project at the following link: Sample Sprite Animation Project for VS 2012 and Windows 8.

It seems that after the animation has completed one iteration and all of the BitmapImages have been loaded from the source URIs, the animation runs smoothly. I suspect that the BitmapImage is not loaded until the Image who is using it for the source is loaded.

So I was hoping to get two things from the community:

Anyone have any good ideas on how I can use preload those images so that the flicker does not happen?

Anyone have any good ideas on how to get these into a sprite sheet so that I do not have to have use separate files? I haven't found a good way to do it with Win8 XAML / C#.

Any help is greatly appreciated.

\$\endgroup\$

3 Answers 3

1
\$\begingroup\$

The flickering problem is because BitmapImage does not load the image really until it's shown.

Consider using WriteableBitmaps instead of BitmapImages and Invalidate() them after setting the Source to ensure it's loaded.

\$\endgroup\$
-1
\$\begingroup\$

You can use a usercontrol with only 1 canvas inside; in the constructor, you can load all images in a list, and use it to animate your image

public sealed partial class sampleSprite : UserControl
{
    List<ImageSource> ImageSources;
    private DispatcherTimer timerLoop;
    int imageIndex;
    public sampleSprite()
    {
        this.InitializeComponent();
        ImageSources = new List<ImageSource>();
        ImageSources.Add((ImageSource)new BitmapImage(new Uri("ms-appx:///Assets/TilePart1.png")));
        ImageSources.Add((ImageSource)new BitmapImage(new Uri("ms-appx:///Assets/TilePart2.png")));
        timerLoop = new DispatcherTimer();
        timerLoop.Interval = TimeSpan.FromMilliseconds(10);
        timerLoop.Tick += timerLoop_Tick;
    }

    protected void timerLoop_Tick(object sender, object e)
    {
        CanvasRoot.Background=new ImageBrush() { ImageSource = ImageSources[imageIndex]};
        imageIndex = (++imageIndex)% ImageSources.Count;
    }

    public void StartAnimation()
    {
        timerLoop.Start();
    }
    public void StopAnimation()
    {
        timerLoop.Stop();
    }
}
\$\endgroup\$
-1
\$\begingroup\$

Here is my implementation based on the answer from S-téphan Wegener.

// FOR SPRITE BASED ANIMATION:
// ******************************************************
// *** right now, flickers on first cycle, but NO FLICKER after that unless animation cycle 
// *** restart
// *** can fix later some how with creative pre-call/loads
// *** for UWA/XAML Windows10 Image.Source, not Canvas.Background

In declarations:

List<ImageSource> ImageSources;
int imageIndex;

In initial startup declarations:

ImageSources = new List<ImageSource>();
ImageSources.Add((ImageSource)new BitmapImage(new Uri("ms-appx:///Assets/images/01.png")));
ImageSources.Add((ImageSource)new BitmapImage(new Uri("ms-appx:///Assets/images/02.png")));
ImageSources.Add((ImageSource)new BitmapImage(new Uri("ms-appx:///Assets/images/03.png")));
ImageSources.Add((ImageSource)new BitmapImage(new Uri("ms-appx:///Assets/images/04.png")));
ImageSources.Add((ImageSource)new BitmapImage(new Uri("ms-appx:///Assets/images/05.png")));
ImageSources.Add((ImageSource)new BitmapImage(new Uri("ms-appx:///Assets/images/06.png")));

In run-time:

if (OOP.frame == 93) {
    imageIndex = 0; }
if (OOP.frame == 94) {
    imageIndex = 1;}
if (OOP.frame == 95) {
    imageIndex = 2; }
if (OOP.frame == 96) {
    imageIndex = 3; }
if (OOP.frame == 97) {
    imageIndex = 4; }
if (OOP.frame == 98) {
    imageIndex = 5; }

OOP_xaml_image_tag.Source = ImageSources[imageIndex];
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .