views:

41

answers:

1

I want to create some kind of simulation. There will be numerous sprites floating around. Because I think that rendering every frame thousand times the same primitives which make up a sprite, will be slow, I want render them once into a bitmap and then show this sprite every frame.

But it doesn't seem to work, the screen stays white.

My WPF source is trivial:

<Window x:Class="WPFGraphicsTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="800" Width="1000">
    <Canvas>

    </Canvas>
</Window>

And this is my code:

    public partial class MainWindow : Window
    {
        Ellipse e;
        RenderTargetBitmap bmp2;

        public MainWindow()
        {
            InitializeComponent();

            e = new Ellipse();
            e.Width = 40;
            e.Height = 40;
            e.Fill = new SolidColorBrush(Color.FromRgb(0, 0, 200));

            ((Canvas)this.Content).Children.Add(e);
            ((Canvas)this.Content).Measure(new Size(1000, 800));
            ((Canvas)this.Content).Arrange(new Rect(new Size(1000, 800)));

            RenderTargetBitmap bmp2 = new RenderTargetBitmap(40, 40, 96, 96, PixelFormats.Pbgra32);

            bmp2.Render(e);
            ((Canvas)this.Content).Children.Remove(e);
}


        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);

            drawingContext.DrawImage(bmp2, new Rect(100,100, 40, 40));

        }
}

Why doesn't this work?

+1  A: 

You could put an Image object on the Canvas and then use the RenderTargetBitmap to update the image. For example

<Window x:Class="WPFGraphicsTest.MainWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="MainWindow" Height="800" Width="1000"> 
    <Canvas> 
      <Image Name="frameImage" />
    </Canvas> 
</Window> 

Then you can update the image like this, for the example, I am just rendering a new ellipse every 100 ms. Of course you should manage the Pens and Brushes better than what I show here, this is just an example to clarify the suggestion.

public partial class MainWindow : Window
  {
    DispatcherTimer _timer = new DispatcherTimer();

    RenderTargetBitmap _renderSurface = 
      new RenderTargetBitmap(100, 100, 96, 96, PixelFormats.Pbgra32);

    Random _rnd = new Random();

    public MainWindow()
    {
      InitializeComponent();

      _timer = new DispatcherTimer();
      _timer.Interval = TimeSpan.FromMilliseconds(100);
      _timer.Tick += new EventHandler(_timer_Tick);
      _timer.Start();      
    }

    void _timer_Tick(object sender, EventArgs e)
    {
      DrawingVisual visual = new DrawingVisual();
      DrawingContext context = visual.RenderOpen();
      int value = _rnd.Next(40);
      context.DrawEllipse(
        new SolidColorBrush(Colors.Red), 
        new Pen(new SolidColorBrush(Colors.Black), 1), 
        new Point(value, value), value, value);
      context.Close();

      _renderSurface.Render(visual);
      frameImage.Source = _renderSurface;
    }    
  }
Chris Taylor
Thanks for the answer, but your code renders the ellipse every frame. I want to render the ellipse once into a bitmap and then every frame draw just the bitmap.
codymanix
@codymanix, using this example you can get the bitmap to render. Basically the code in the _timer_Tick is what you need to render to the bitmap. If you want to do that only once then you can shift that code out of the _timer_Tick function. I simply included that in the sample so that you could see that the update to the bitmap is shown on the screen.
Chris Taylor
OK thanks, that will work. But this means I have to create an Image object for each sprite I want to draw. Isn't it possible to draw images on the fly? What was wrong with my code, isn't it supposed to work?
codymanix
@codymanix, why not just use a single bitmap and draw all the sprites on to that one bitmap, then each frame you only ever render the one bitmap? That is somewhat like the example I have provided.
Chris Taylor