Which is faster when animating the UI: a Control o

2019-09-07 15:58发布

问题:

/I'm working with and testing on a computer that is built with the following: {1 GB RAM (now 1.5 GB), 1.7 GHz Intel Pentium Processor, ATI Mobility Radeon X600 GFX}

I need scale / transform controls and make it flow smoothly. Currently I'm manipulating the size and location of a control every 24-33ms (30fps), ±3px. When I add a 'fade' effect to an image, it fades in and out smoothly, but it is only 25x25 px in size. The control is 450x75 px to 450x250 px in size. In 2D games such as Bejeweled 3, the sprites animate with no choppy animation.

So as the title would suggest: which is easier/faster on the processor: animating a bitmap (rendering it to the parent control during animation) or animating the control it's self?

EDIT: Hey, I thought this was a helpful community, not one that down-rates questions that don't seem challenging! (And I've seen more ridiculous questions here with better ratings too!) Please drop me a line first before negatively rating my questions!

回答1:

I managed to find some free-time in my heck-tick scheduled, to quickly whip up a new project. I'm sure my time could have been better spent else where but hopefully someone else in my shoes may find this of use out there...

The answer is: a Picture over a Control. When rendering a bitmap onto the canvas, there are very little events that will fire, if any. As for the control, it is filled with events - some chained, some looped, and the addition of recursion, so a simple 'LocationChanged' event wouldn't even cover the half of what actually is taking place under the hood.

What I would do for controls that have lots of dynamic animations applied to them during runtime, is to develop a two piece set: a control [rendering] template or active interface (for when the control is at a stand-still or before the play of an animation), and a the animating structure with basic defining properties such as the display image [the rendered control], the rectangle bounds, and any animation algorithms that may be applied latter.

Edit: As Requested, here are the before and after code examples:

// This is the triggering event of the translating animation
private void object_Click(object sender, EventArgs e)
{
      // the starting point is at (75,75)
      element.Transform(new Point(500, 250));
}

Before:

public class ControlElement : UserControl
{
      private Timer tick;
      private Point pT0;
      public ControlElement() : base()
      {
            tick = new Timer();
            tick.Interval = 30; // about 30fps
            tick.Tick += new EventHandler(tick_Tick);
      }
      void tick_Tick(object sender, EventArgs e)
      {
            // get the new point from distance and current location/destination
            this.Location = Utils.Transform(this.Location, pT0, 3);
            if ((pT0.X - this.Location.X)+(pT0.Y - this.Location.Y) <= 0)
            {
                this.Location = pT0;
                tick.Stop();
                //this.Visible = true;
            }
      }
      public void Transform(Point destination)
      {
            pT0 = destination;
            //this.Visible = false;
            tick.Start();
      }
}

After: I create a class that holds a picture of what the control would look like using the DrawToBitmap feature. It still contains the same animation methods as above. I had to add the Location and LocationChanged elements since this class was no longer a control. If and when the actual control needed to be accessed, I would stop rendering and display an instance of the control it's self.
Here is the rendering call:

void element_LocationChanged(object sender, EventArgs e)
{
      canvas.Invalidate();
}
void canvas_Paint(object sender, PaintEventArgs e)
{
      if (element != null)
      {
            Bitmap bmp = new Bitmap(element.Display);
            Pen p = new Pen(Color.FromArgb(128, 128, 128), 1);
            e.Graphics.DrawImage(bmp, element.Location);
            e.Graphics.DrawRectangle(p, 
                 element.Location.X, element.Location.Y, 
                 bmp.Width, bmp.Height);
      }
}