简体   繁体   中英

How to do fast smooth animation in C# using WPF

I'm currently programming a game of Pong. I have the majority of the game completed but I've run into an annoying problem. I'm using a dispatcherTimer with priority set to Send and time span set to 1 millisecond. I'm animating the rectangle using up to dx=9 and dy=9 in order to make the ball move fast enough. Because of the large pixel jumps the ball appears skip across the screen instead of a smooth travel. According to math in 1 millisecond per cycle this ball should be moving MUCH faster than it is. I need to update the ball more often and move it by less...

Are there any suggestions on a better method to do this? Here is a snippet of what I have...

pongballTimer = new DispatcherTimer(DispatcherPriority.Send);
pongballTimer.Tick += new EventHandler(pongballTimer_Tick);
pongballTimer.Interval = new TimeSpan(0, 0, 0, 0, _balldt);

private void pongballTimer_Tick(object sender, EventArgs e)
{
   double pongtop = Canvas.GetTop(PongBall);
   double pongleft = Canvas.GetLeft(PongBall);
   double paddletop = Canvas.GetTop( RightPaddle );
   double paddleleft = Canvas.GetLeft( RightPaddle );

   if (pongleft + PongBall.Width > paddleleft)
   {
      if (((pongtop < paddletop + RightPaddle.Height) && (pongtop > paddletop)) ||
         ((pongtop + PongBall.Height < paddletop + RightPaddle.Height) &&
         (pongtop + PongBall.Height > paddletop)))
      { 
         _dx *= -1;
         SetBalldy(pongtop, PongBall.Height, paddletop, RightPaddle.Height);
         _rightpoint++;
         lblRightPoint.Content = _rightpoint.ToString();
         meHitSound.Play();
      }

      else // The ball went past the paddle without a collision
      {
         RespawnPongBall(true); 
         _leftpoint++;
         lblLeftPoint.Content = _leftpoint.ToString();
         meMissSound.Play();

         if (_leftpoint >= _losepoint)
               LoseHappened("You Lost!!");
               return; 
      }
   }

   if (pongleft < 0)
   {
      meHitSound.Play();
      _dx *= -1;
   }

   if (pongtop <= _linepady ||
         pongtop + PongBall.Height >= PongCanvas.Height - _linepady)
   {
      meDeflectSound.Play();
      _dy *= -1;
   }
   Canvas.SetTop(PongBall, pongtop + _dy);
   Canvas.SetLeft(PongBall, pongleft + _dx);
}

Instead of doing the movement in a timer callback, you may use one of the animation techniques that are built into WPF.

Start reading Property Animation Techniques Overview , perhaps with special attention to the last section Per-Frame Animation: Bypass the Animation and Timing System .

Then you may proceed to How to: Render on a Per Frame Interval Using CompositionTarget .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM