Skip to content

Instantly share code, notes, and snippets.

@Oxore
Last active July 1, 2018 11:17
Show Gist options
  • Save Oxore/109589011b05f46aef817f6575ebe165 to your computer and use it in GitHub Desktop.
Save Oxore/109589011b05f46aef817f6575ebe165 to your computer and use it in GitHub Desktop.
Паттерн handle для реализации двухмерного отрисовщика (Черновик)

Паттерн handle для реализации двухмерного отрисовщика (Черновик)

Задача

Необходимо отделить типы данных, с которыми работает логика приложения от типов данных, предоставляемых графической прослойкой (например SFML или SDL). Такое абстрагирование и сегрегация сделает тестирование проще, а архитектуру чище.

Например есть объект и его надо отрисовать. Пусть это будет текст. Такая структура содержит текст и его позицию.

struct text {
	vector2f pos;
	char *text;
} mytext;

Отрисовка

Есть не класс и не неймспейс, не на джаве и не на плюсах, а обычный файл .c на обычных няшных сях. Хедер с прототипами функций прилагается. Ко всем далее описанным функциям можно приписать в начале какое-нибудь слово, например painter_, чтобы как-то обособить все эти функции и очертить своеобразный статический класс или неймспейс, а по сути синглтон. Но далее я всё равно буду называть его классом.

В этом классе хранятся зарегистрированные графические представления объектов, обрабатываемых в бизнес-логике приложения. Эти представления просто визуализируют имеющиеся объекты. А так же предоставляются методы настройки этих визуализаций.

Вариант 1

  • Регистрируешь одно отображение одного объекта и получаешь его хендл (хендл - это просто идентификатор типа int)
     int register_text(void);
  • Текст изменился и его нужно обновить. Тем более сначала он вообще не задаётся - нужно задать.
     void update_text(int handle, struct text *text);
  • Отрисовываешь все объекты. Отрисовка в том порядке, в котором была произведена их регистрация.
     void draw(void);
  • Освобождаешь все ресурсы разом.
     void destroy(void);

Вариант 2

  • Регистрируешь одно отображение одного объекта и он агрегируется в синглтоне, возвращая тебе хендл (хендл - это просто идентификатор типа int)
     int register_text(struct text *text);
  • Обновлять не нужно, он обновляется сам перед каждой отрисовкой, потому что агрегировал указатель
  • Отрисовываешь тупо всё. Отрисовка в том порядке, в котором была произведена регистрация.
     void draw(void);
  • Освобождаешь все ресурсы разом.
     void destroy(void);

Другие варианты

Ещё можно докинуть методов, удаляющих конкретные отображения по хендлу, меняющих порядок отображения по хендлу и в этом есть смысл, это действительно стоит сделать. Но можно ещё заменить один общий draw() на ручную отрисовку каждого объекта по хендлу, то есть у каждого типа объектов будет свой draw_obj(handle), тогда достаточно легко можно было бы задать порядок отрисовки объектов (он был бы только таким, ручным), но код был бы более громоздкий.

Хорошо, а как задать шрифт?

Да и не только шрифт, ещё цвет, размер кегля, угол поворота, якорь и чёрта лысого! Если угол поворота логично наряду с позицией так же запихнуть в структуру, то всё остальное нужно задавать предварительными настройками.

Создадим набор настроек для текста, который как бы является аналогом класса в HTML+CSS вёрстке. Получим хендл этих настроек.

int new_settings_text(void);

Затем настройки нужно установить послав специальную структуру с настройками и хендл этих настроек.

void settings_text(int handle, struct settings_text *settings);

Хендл этих настроек нужно включить в структуру struct text в виде отдельного поля, чтобы к этому тексту применялись эти настройки.

Не одним текстом единым

Имеется необходимость отображения объектов отличных от текста, более сложных. Например игровое поле тетриса. Оно состоит из пары сотен клеток имеющих цвет, состояние, размер, положение, шаг, декорацию. Точно так же как и текст, поле должно иметь регистрируемый тип отображения, собственные методы для регистрации, для обновления, собственные настройки отображения и собственные контейнеры хранения.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment