Частина 11 - В'юпорти

SDL2 дозволяє використовувати в'юпорти.Погляньте на наступний знімок гри SDL2 (Битва за Веснот).

Модифікований знімок екрану Битви за Веснот. (Оригінальне джерело зображеня, як знайдено в Wesnoth Wiki розробниками Весноту. Ліцензія зображення: GFDL.)

Це класична ситуація використання в'юпортів. Екран гри чітко розділений на три виділені області. Головний екран - це велика частина зліва з горами та замками. Тоді в правому верхньому кутку є мінікарта. І під мінікартою огляд статистики. Ці області та відповідні в'юпорти виділено на наступному знімку екрану.

Модифікований знімок екрану Битви за Веснот. (Оригінальне джерело зображеня, як знайдено в Wesnoth Wiki розробниками Весноту. Ліцензія зображення: GFDL.)

Перевагою в'юпортів є те, що кожен з них поводиться як власне вікно, тому якщо Ви будете малювати за правою границею в'юпорта 1 на скріншоті нижче, текстура буде просто обрізана і не буде перекриватись у в'юпортах 2 або 3.

SDL2 window and viewport coordinates diagram
Тут показано співвідношення Вашого екрану, вікна SDL2 та в'юпорта.

Давайте подивимось на код.

program SDL2_Viewport;

uses SDL2;

const
  Viewport1: TSDL_Rect = (x: 0;   y:   0; w: 400; h: 500);
  Viewport2: TSDL_Rect = (x: 400; y:   0; w: 100; h: 300);
  Viewport3: TSDL_Rect = (x: 400; y: 300; w: 100; h: 200);

  BlackDot:  TSDL_Rect = (x: 10;  y:  10; w:   3; h:   3);

var
  sdlWindow1: PSDL_Window;
  sdlRenderer: PSDL_Renderer;

begin

  //ініціалізація підсистеми відео
  if SDL_Init(SDL_INIT_VIDEO) < 0 then Halt;

  SDL_CreateWindowAndRenderer(500, 500, SDL_WINDOW_SHOWN, @sdlWindow1, @sdlRenderer);
  if (sdlWindow1 = nil) or (sdlRenderer = nil) then Halt;

  //заповнити кожен в'юпорт кольором фону і намалювати в ньому чорну точку
  SDL_RenderSetViewport(sdlRenderer, @Viewport1);
  SDL_SetRenderDrawColor(sdlRenderer, 255, 0, 0, SDL_ALPHA_OPAQUE);
  SDL_RenderFillRect(sdlRenderer, nil);
  SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
  SDL_RenderFillRect(sdlRenderer, @BlackDot);

  SDL_RenderSetViewport(sdlRenderer, @Viewport2);
  SDL_SetRenderDrawColor(sdlRenderer, 255, 255, 0, SDL_ALPHA_OPAQUE);
  SDL_RenderFillRect(sdlRenderer, nil);
  SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
  SDL_RenderFillRect(sdlRenderer, @BlackDot);

  SDL_RenderSetViewport(sdlRenderer, @Viewport3);
  SDL_SetRenderDrawColor(sdlRenderer, 0, 255, 0, SDL_ALPHA_OPAQUE);
  SDL_RenderFillRect(sdlRenderer, nil);
  SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
  SDL_RenderFillRect(sdlRenderer, @BlackDot);

  //візуалізувати у вікно на 2 секунди
  SDL_RenderPresent(sdlRenderer);
  SDL_Delay(2000);

  //очистити пам'ять
  SDL_DestroyRenderer(sdlRenderer);
  SDL_DestroyWindow (sdlWindow1);

  //вимкнути підсистему відео
  SDL_Quit;

end.  

Результат буде виглядати так:

Creative Commons License This Зображення від https://www.freepascal-meets-sdl.net ліцензовано під Creative Commons Attribution 4.0 International License.
Три в'юпорти з різним кольором фонуі чорною точкою в верхньому лівому кутку.

Спочатку ми заадаємо декілька прямокутників SDL2

const
  Viewport1: TSDL_Rect = (x: 0;   y:   0; w: 400; h: 500);
  Viewport2: TSDL_Rect = (x: 400; y:   0; w: 100; h: 300);
  Viewport3: TSDL_Rect = (x: 400; y: 300; w: 100; h: 200);

  BlackDot:  TSDL_Rect = (x: 10;  y:  10; w:   3; h:   3);

“Viewport1” представляє червоний в'юпорт (зліва), “Viewport2” - жовтий (зверху справа) і “Viewport3” - зелений (знизу-справа) в'юпорти на результуючому зображенні.

Зверніть увагу, як ми просто готуємо один прямокутник “BlackDot” для чорної точки розміром 3 × 3 пікселі в розташуванні (10/10).

Після налаштування SDL2, візуалізатора та вікна, як вже нам відомо, ми починаємо налаштовувати перший (червоний, лівий) в'юпорт.

  //заповнити кожен в'юпорт кольором фону і намалювати в ньому чорну точку
  SDL_RenderSetViewport(sdlRenderer, @Viewport1);
  SDL_SetRenderDrawColor(sdlRenderer, 255, 0, 0, SDL_ALPHA_OPAQUE);
  SDL_RenderFillRect(sdlRenderer, nil);
  SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
  SDL_RenderFillRect(sdlRenderer, @BlackDot);

Це так просто. Використовуйте функцію SDL_RenderSetViewport(візуалізатор, вказівник на прямокутник) для встановлення в'юпорта. Ця функція повертає 0 при успіху або -1 при невдачі.

SDL_RenderSetViewport(renderer: PSDL_Renderer; const rect: PSDL_Rect)

Після того, як ми встановили в'юпорт, ми встановлюємо колір малювання функцією SDL_SetRenderDrawColor(візуалізатор, червоний, зелений, синій, альфа) в червоний (255/0/0/непрозорий). Тоді ми використовуємо SDL_RenderFillRect(візуалізатор, вказівник на прямокутник) щоб заповнити весь в'юпорт не вказуючи прямокутника (nil). Обидві функції відомі з попередніх частин.

Тоді колір встановлюється в чорний і крихітні прямокутники 3×3 пікселя малюються за розміщенням (10/10).

Ця процедура повторюється для двох інших в'юпортів. Знову зверніть увагу, як ми використовуємо цей же прямокутник для чорної точки і де це показано на результуючому зображенні. Чорна точка завжди малюється в позиції (10/10) відносно розміщення відповідного в'юпорта!

Застосовується як загальне правило:

Координати завжди відносно до поточного в'юпорта.

Що ж, решта коду, що залишився, не надає нічого нового, просто візуалізації на 2 секунди і трохи процедур очистки.

Давайте завершимо з кількома корисними зауваженнями.

Для в'юпортів не треба використовувати SDL_RenderClear!

Не використовуйте SDL_RenderClear(візуалізатор). Ця функція ігнорує в'юпорти і очищає ціле вікно кольором малювання.

Скидання в'юпорта

Скидання викоонуєится просто викликом SDL_RenderSetViewport(візуалізатор, nil)як і слід було очікувати.

← попередня частина | наступна частина →

Немає коментарів:

Опублікувати коментар