Как оптимизировать перерисовку формы

Пытаюсь написать простую 2D игру. Сделано это:

public interface GameObject
{
    Bitmap Picture  { get; }
    int OffsetX     { get; }
    int OffsetY     { get; }
}

Здесь свойство Picture возвращает изображение, которое должно быть нарисовано для текущего объекта.

public static class Game
{
    public class MapIndexer
    {
        public GameObject this[int x, int y]
        {
            get => map[y, x];
            set => map[y, x] = value;
        }
    }

    private static MapIndexer indexer;
    public static MapIndexer Map
    {
        get => indexer ?? (indexer = new MapIndexer());
    }

    static GameObject[,] map = new GameObject[,]
    {
        { null, null, null },
        { null, null, null },
        { null, null, null }
    };

    public static int MapWidth
    {
        get => map.GetLength(1);
    }
    public static int MapHeight
    {
        get => map.GetLength(0);
    }
}

Класс Game, который содержит индексатор карт и предназначен для дальнейшей разработки. Индексация [y, x] предназначена для доступа к карте, такой как декартовы координаты, иначе я получаю перевернутые размеры. NULL в массиве — это просто наполнитель (т.е. трава в моей игре ничего не делает и нужна только для заполнения карты, поэтому не вижу смысла создавать для нее отдельный класс). Также создан простой класс Player из интерфейса GameObject, который просто возвращает изображение для рисования. А вот собственно код краски:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    for (int y = 0; y < Game.MapHeight; y++)
        for (int x = 0; x < Game.MapWidth; x++)
        {
            e.Graphics.DrawImage(Properties.Resources.Grass, new Point(x * size, y * size));
            if (Game.Map[x, y] is not null)
                e.Graphics.DrawImage(Game.Map[x, y].Picture, new Point(x * size + Game.Map[x, y].OffsetX, y * size + Game.Map[x, y].OffsetY));
        }
}

Поэтому, когда я делаю какое-то движение, я аннулирую форму и получаю следующий кадр. Для меня это выглядит странно, на самом деле это потому, что при выполнении действия картинка мигает при каждой операции перерисовки. Анимация для теста — это движение игрока, которое происходит каждые 200 мс, что немного. Итак, вопрос: как оптимизировать отрисовку, чтобы она выглядела плавно, или мой дизайн кода изначально плохой?

Первое, что вам нужно сделать: 1. Назначьте объект Properties.Resources.Grass Bitmap свойству/полю вашего игрового класса. Properties.Resources — это фабрика, поэтому вы каждый раз создаете новое изображение. Вы не хотите этого. 2. Включите двойную буферизацию на холсте, используемом для рисования, если вы этого не сделали. Используйте другой контейнер, например PictureBox (двойная буферизация включена по умолчанию), а не саму форму. 3. Сделайте недействительным только тот раздел, который нужно перерисовать. См. перегрузки метода Invalidate(). 4. Избегайте значений, которые появляются в коде из ниоткуда, например size.

Jimi 12.12.2020 07:51

Что вы имеете в виду под 4. о размере?

SelfishCrawler 12.12.2020 07:53
new Point(x * size, y * size) <- откуда берется size и где оно определено, не определено. Это значение должно быть частью объекта, который описывает изображения, которые вы используете, а не поле в форме (или что-то еще).
Jimi 12.12.2020 07:57

Размер действительно является полем формы и используется только в этом событии рисования и больше нигде. Каждая картинка одинакового размера

SelfishCrawler 12.12.2020 08:29

Form.DoubleBuffered == true: ? Для формы вы можете включить его напрямую, для PBox он уже включен, для других элементов управления вы можете включить его в коде(..

TaW 12.12.2020 08:42
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Эффект, который вы испытываете, на самом деле не связан с производительностью. То, что вы видите, скорее всего, является эффектом очистки экрана перед перерисовкой. Вы должны изучить концепцию под названием «двойная буферизация».

Другие вопросы по теме