Winforms API и встроенный в Windows 32 интерфейс обмена сообщениями Windows Win32 просто не предназначены для "плавной анимации". Будет трудно, если не невозможно, добиться идеально плавной анимации.
Тем не менее, многое можно сделать, чтобы улучшить вашу попытку выше:
- Не используйте
CreateGraphics()
. Вместо этого всегда рисуйте в ответ на событие Paint
. - Не используйте какие-либо реализации таймера .NET для планирования рендеринга. Вместо этого нарисуйте как можно быстрее, принимая во внимание время между кадрами для обновления позиции вашего объекта.
Применяя эти идеи, вот версия вашего кода, которая работает на намного лучше:
const float speedXPerSecond = 1000f / 30;
const int bar_width = 40;
public Form1()
{
InitializeComponent();
DoubleBuffered = true;
}
float x_position = 0;
TimeSpan _lastFrameTime = TimeSpan.Zero;
Stopwatch _frameTimer = Stopwatch.StartNew();
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
TimeSpan currentFrameTime = _frameTimer.Elapsed;
float distance = (float)(currentFrameTime - _lastFrameTime).TotalSeconds * speedXPerSecond;
x_position += distance;
while (x_position > this.Width) x_position -= this.Width;
e.Graphics.FillRectangle(Brushes.Black, x_position, 0, bar_width, 500);
_lastFrameTime = currentFrameTime;
Invalidate();
}
Вы можете применить эту общую технику к любому интерактивному сценарию. Настоящая игра будет иметь другие элементы в этом общем «цикле рендеринга», включая пользовательский ввод и обновление состояния игры (например, на основе физической модели). Это добавит накладные расходы к циклу рендеринга и обязательно уменьшит частоту кадров. Но для любой основной игры на любом относительно новом оборудовании (например, построенном в последние пару десятилетий) чистая частота кадров будет все еще намного выше, чем требуется для приемлемо плавного игрового процесса.
Обратите внимание, что вВ управляемом контексте .NET / Winforms всегда будет предел успешности этого подхода по сравнению с использованием низкоуровневого API. В частности, без какой-либо дополнительной работы с вашей стороны сборка мусора будет периодически прерываться, вызывая незначительное заикание частоты кадров, а также неравномерность в планировании потока и очереди сообщений потока.
Но это был мой опыт, что людизадавая подобные вопросы, не нужно, чтобы все было идеально. Им нужно «достаточно хорошо», чтобы они могли перейти к изучению других тем, связанных с разработкой игр.