简体   繁体   English

在C#中以流畅的方式绘制运动球体的最佳方法

[英]Best way to draw moving sphere in a smooth way in C#

Hello: I am trying to create an app which will display a moving sphere. 您好:我正在尝试创建一个显示移动球体的应用程序。 App will vary speed and direction. 应用程序将改变速度和方向。 I've tried Adobe Flash but cannot get it smooth. 我已经尝试过Adobe Flash,但无法使其流畅。 Smoothness is essential in this case. 在这种情况下,光滑度至关重要。 So I am trying C#. 所以我正在尝试C#。

Initially, I can see that this can be implemented by: 1) Creating a PictureBox of a sphere, and using a Timer, change its coordinates. 最初,我可以看到这可以通过以下方式实现:1)创建一个球的PictureBox,并使用Timer更改其坐标。 or 2) Using the this.paint function to draw a filled circle, and somehow, with a timer, erasing and redrawing it. 或2)使用this.paint函数绘制一个实心圆,并使用计时器以某种方式擦除并重新绘制它。

Can someone recommend the best path to take? 有人可以推荐最好的选择吗? I'll have a main menu where the user will chose speed/direction/how many etc... and then simply show the "game window" with the moving spheres. 我将有一个主菜单,用户将在其中选择速度/方向/数量等...,然后简单地显示带有移动球体的“游戏窗口”。 Any guidance would be much appreciated. 任何指导将不胜感激。

This is to be displayed on a PC only. 仅在PC上显示。

Thanks -Ed 谢谢-编辑

I just answered a similar question here . 我只是在这里 回答了类似的问题。

NOTE : Depending on your needs, it is possible to achieve smooth animations under (under certain conditions) though you are responsible for everything. 注意 :根据您的需要,尽管您负责所有工作,但仍可以在 (在某些条件下)下实现流畅的动画。 provides an animation framework but is perhaps a milestone harder. 提供了动画框架,但可能更难实现。

It probably does not matter should you pursue first or WPF. 您应该先追求还是WPF,这可能并不重要。 You arguably could learn the basics under then move over to . 您可以说可以在下学习基础知识,然后转到 may require you to learn quite a bit before you can do anything. 可能需要您学习很多知识,然后才能做任何事情。

Summary 摘要

Essentially what this does is to create an offscreen bitmap that we will draw into first. 本质上,此操作是创建一个屏幕外位图,我们将首先绘制该位图。 It is the same size as the UserControl. 它与UserControl的大小相同。 The control's OnPaint calls DrawOffscreen passing in the Graphics that is attached to the offscreen bitmap. 控件的OnPaint调用DrawOffscreen传递附加到屏幕外位图的Graphics Here we loop around just rendering the tiles/sky that are visible and ignoring others so as to improve performance. 在这里,我们只渲染可见的图块/天空,而忽略其他图块/天空,以提高性能。

Once it's all done we zap the entire offscreen bitmap to the display in one operation. 完成所有操作后,我们只需一次操作即可将整个屏幕外位图转换为显示内容。 This serves to eliminate: 这有助于消除:

  • Flicker 闪烁
  • Tearing effects (typically associated with lateral movement) 撕裂效果(通常与横向移动有关)

There is a Timer that is scheduled to update the positions of all the tiles based on the time since the last update . 有一个Timer ,该Timer计划根据自上次更新以来的时间更新所有图块的位置。 This allows for a more realistic movement and avoids speed-ups and slow-downs under load. 这样可以实现更逼真的运动,并避免负载下的加速和减速。 Tiles are moved in the OnUpdate method. OnUpdateOnUpdate方法移动。

If you note in the code for Timer1OnTick I call Invalidate(Bounds); 如果您在Timer1OnTick的代码中Timer1OnTick我将调用Invalidate(Bounds); after animating everything. 动画一切之后。 This does not cause an immediate paint rather Windows will queue a paint operation to be done at a later time. 这不会导致立即进行绘制,而是Windows将在以后的某个时间排队进行绘制操作。 Consecutive pending operations will be fused into one. 连续的待处理操作将融合为一个。 This means that we can be animating positions more frequently than painting during heavy load. 这意味着在重负载下,我们可以比绘画更频繁地对位置进行动画处理。 Animation mechanic is independent of paint . 动画技工独立于颜料 That's a good thing, you don't want to be waiting for paints to occur. 那是一件好事,您不想等待油漆的出现。 does a similar thing 做类似的事情

Please refer to my full SO answer complete with sample code 请参考我的完整SO回答以及示例代码

Here are a few hints to get you going: 以下是一些提示,助您一臂之力:

First you will need to come to a decision about which platform to target: WPF or Winforms . 首先,您需要确定目标平台: WPFWinforms

Then you should know what to move across what; 那么你应该知道 什么移动; a nice Bitmap or just a circle across an empty background or a Bitmap or a Form with controls on it. 一个不错的Bitmap或者是一个空背景上的圆圈,或者是Bitmap或带有控件的Form

In Winforms both your approaches will work, esp. Winforms两种方法都可以使用,尤其是。 if you set a circular region see here for an example of that. 如果您设置圆形区域, 请参见此处的示例。 (The part in the fun comment!) (有趣的评论部分!)

And yes, a Timer is the way to animate the sphere. 是的, Timer是对球体进行动画处理的方式。 Btw, a Panel or even a Label can display an Bitmap just as well as a PictureBox . 顺便说一句, Panel甚至Label都可以显示Bitmap以及PictureBox

For smooth movements make sure to set the Form.Doublebuffered=true , if you move across a Form . 为了平稳移动,请确保在Form移动时设置Form.Doublebuffered=true If you move across any other control (except a PictureBox or a Label ) you will need to subclass it to get access to the DoubleBuffered property! 如果在任何其他控件( PictureBoxLabel除外)上移动,则需要对其进行子类化以访问DoubleBuffered属性!

It is often also a good idea to keep the Location of a moving item in a variable as a PointF and use floats for its speed because this way you can fine grain the speed and Location changes and also the Timer Intervals ! 将移动项的Location保留在变量中作为PointF并使用floats作为其速度通常也是个好主意,因为这样您可以细化速度和Location变化以及Timer Intervals

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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