Частина 8 - Прямокутники, переміщення зображення та масштабування

Екрани та зображення мають прямокутну форму, тому ця форма має особливе значення для SDL2 та, зокрема, для програмування графіки.

Прямокутники: TSDL_Rect та PSDL_Rect в SDL 2.0

Часто функції вимагають аргументу типу PSDL_Rect. Це аналог вказівника на TSDL_Rect. Він оголошений наступним чином:

PSDL_Rect = ^TSDL_Rect;
TSDL_Rect = record
  x,y: SInt32;
  w,h: SInt32;
end;

Просто цей запис описує прямокутник (rectangle), звідси і назва. Змінні x і y відповідають координатам x/y лівого верхнього кута прямокутника, що відносяться до початку координат 0/0, який є лівим верхнім кутом, наприклад, текстура, вікно,… Змінна w - це ширина, а h - висота прямокутника. Це воно. Наступним кроком є ​​визначення прямокутника шляхом присвоєння деяких значень для x, y, w і h.

Якщо Ви користуєтесь PSDL_Rect, Вам потрібно виділити необхідну пам'ять процедурою Pascal new як для будь-якого простого вказівника на запис.

Використання прямокутників для руху та масштабування

Наступний код демонструє основний принцип того, як створити враження руху зображень (спрайтів) і як працює масштабування. Ви будете вражені, наскільки це насправді просто.

program SDL_RectanglesScaling;

uses SDL2;

var
  sdlWindow1: PSDL_Window;
  sdlRenderer: PSDL_Renderer;
  sdlSurface1: PSDL_Surface;
  sdlTexture1: PSDL_Texture;
  sdlRectangle: TSDL_Rect;

begin

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

  if SDL_CreateWindowAndRenderer(500, 500, SDL_WINDOW_SHOWN, @sdlWindow1, @sdlRenderer) <> 0
    then Halt;

  // встановити якість масштабування
  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, 'nearest');

  // create surface from file
  sdlSurface1 := SDL_LoadBMP('fpsdl.bmp');
  if sdlSurface1 = nil then
    Halt;

  // завантажити файл зображення
  sdlTexture1 := SDL_CreateTextureFromSurface(sdlRenderer, sdlSurface1);
  if sdlTexture1 = nil then
    Halt;

  // підготувати прямокутник
  sdlRectangle.x := 12;
  sdlRectangle.y := 25;
  sdlRectangle.w := 178;
  sdlRectangle.h := 116;

  // візуалізувати текстуру
  SDL_RenderCopy(sdlRenderer, sdlTexture1, @sdlRectangle, nil);
  SDL_RenderCopy(sdlRenderer, sdlTexture1, nil, @sdlRectangle);

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

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

  //завершити SDL2
  SDL_Quit;

end.

В результаті ми отримаємо ось це.

Creative Commons License Це зображення від https://www.freepascal-meets-sdl.net ліцензовано за Creative Commons Attribution 4.0 International License.
Результат програми-прикладу (вікно 500 × 500 пікселів). Частина повного зображення розтягується у фоновому режимі, тоді як повне зображення також стискається в область над словом "Free".

Для порівняння, ось оригінальне зображення розміром 200 × 200 пікселів.

Free Pascal meets SDL sample image bmp format
Оригінальне зображення (200×200 px).

Давайте розберемо код.

var
  sdlWindow1: PSDL_Window;
  sdlRenderer: PSDL_Renderer;
  sdlTexture1: PSDL_Texture;
  sdlRectangle: TSDL_Rect;

В розділі var ми оголошуємо відомі змінні для вікна, візуалізатора та текстури. Також у нас є нова змінна типу TSDL_Rect.

  // підготувати прямокутник
  sdlRectangle.x := 12;
  sdlRectangle.y := 25;
  sdlRectangle.w := 178;
  sdlRectangle.h := 116;

Після ініціалізації SDL2 та налаштування вікна та візуалізатора, як вже відомо, прямокутник отримує деякі значення. Він просто включає слова “Free Pascal meets SDL” оригінальному зображенні (див. вище).

Масштабування в SDL2

Якість масштабування

Безпосередньо перед створенням поверхні та текстури в коді є цей рядок.

  // встановити якість масштабування
  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, 'nearest');

Це встановлює якість візуалізації. Його потрібно встановити перед створенням текстури. Функція SDL_SetHint(назва підказки, значення підказки) не є спеціальною функцією для встановлення якості масштабування, але тут ми використовуємо її саме для цього. Можливі значення

  1. nearest або 0
    • вибірка найближчого пікселя
  2. linear або 1
    • лінійна фільтрація
    • підтримується в OpenGL і Direct3D
  3. best або 2
    • анізотропна фільтрація
    • підтримується в Direct3D.

Всі значення повинні бути встановлені як рядкові значення, тобто „nearest” або „0”. Ось порівняння найближчого та лінійного фільтрів.

Анізотропний фільтр не робить для мене нічого, навіть якщо я використовував Direct3D.

Масштабування за допомогою прямокутників

  // візуалізація текстури
  SDL_RenderCopy(sdlRenderer, sdlTexture1, @sdlRectangle, nil);
  SDL_RenderCopy(sdlRenderer, sdlTexture1, nil, @sdlRectangle);

У цей момент відбувається магія, яка веде до результуючого зображення. До речі, оскільки функція SDL_RenderCopy() вимагає, щоб аргументи прямокутника були типу PSDL_Rect, ми використовуємо тут оператор @ (оператор покажчика).

 SDL_RenderCopy(sdlRenderer, sdlTexture1, @sdlRectangle, nil);

Це означає: скопіюйте область, описану “sdlRectangle”, з джерела (тут “sdlTexture1”) на всю область (через nil) пункту призначення, отже, вікно.

Оскільки вікно має ширину та висоту по 500 пікселів, вихідний прямокутник лише ширину 178 пікселів та висоту 116 пікселів, SDL2 автоматично масштабує зображення, щоб воно відповідало більшим (або меншим) розмірам пункту призначення.

  SDL_RenderCopy(sdlRenderer, sdlTexture1, nil, @sdlRectangle);

Це означає: скопіюйте ціле джерело (через значення nil) у область, описану “sdlRectangle”. Джерелом є зображення розміром 200 × 200 пікселів, яке потрібно стиснути до прямокутника 178 × 116 пікселів у положенні (12/25). Це саме те, що Ви бачите на отриманому зображенні (вгорі), де ціле зображення стискається в цю область.

Рух зображень (спрайтів)

Хоча це не охоплено безпосередньо в наведеному прикладі коду, Ви отримуєте уявлення про те, як працює рух. Для кожного кадру Ви налаштовуєте (x/y) координати прямокутника для пункту призначення, щоб спрайт рухався.

Після очищення пам'яті програма завершується.

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

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

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