SDL2

SDL2 SDL2

Створення простого SDL2-додатку з нуля

На цій сторінці я покажу, як з нуля визначити та створити графічний додаток SDL2, використовуючи лише улюблений текстовий редактор. Документ написаний для у Linux, оскільки це найкраща платформа для вивчення програмування.

Створення зразка програми

Тепер нам потрібно створити файл вихідного коду та файл визначення збірки cmake. Ми взагалі не будемо використовувати SDL, а почнемо з простої програми, яка лише друкує певний текст. Як тільки вона запрацює, ми зможемо розширити її для відображення графіки. Вихідний код зберігається у файлі main.cpp та має такий вміст:

#include <iostream>

int main(int argc, char **argv) {
  std::cout<<"App is running.\n";
  return 0;
}

Визначення збірки зберігається у файлі з назвою CMakeLists.txt та виглядає так:

cmake_minimum_required(VERSION 3.11)

project(sdlprog)

add_executable(${PROJECT_NAME} src/main.cpp)

Після цього ми можемо розпочати збірку за допомогою наступної команди:

cmake -B builddir -G="Unix Makefiles"

Ось builddir каталог збірки , все, що генерується під час збірки, поміщається в цей каталог. Після запуску це має виглядати ось так.

IMG

Програма компілюється з такою командою:

cmake --build builddir -j$(nproc)

Програма буде знаходитися в каталозі збірки та може бути запущена таким чином:

./builddir/sdlprog

Вихід має виглядати ось так.

IMG

Оновлення програми для використання SDL

Код, необхідний для запуску SDL, трохи складніший, і ми не будемо вдаватися в деталі його роботи. Просто замінимо вміст main.cpp на наступне:

#if defined(__linux)
#include <SDL2/SDL.h>

#elif defined(WIN32)
#include <SDL.h>
#endif

#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>

struct SDL_Guard {
  SDL_Guard(Uint32 flags) {
    if (0 > SDL_Init(flags))
      throw std::runtime_error("Couldn't initialize SDL:" +
                               std::string(SDL_GetError()));
  }
  ~SDL_Guard() { SDL_Quit(); }
};

using UniqueWindow = std::unique_ptr<SDL_Window, void (*)(SDL_Window *)>;

#if defined(_WIN32)
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow)
#elif defined(__APPLE__)
int main(int argc, char **argv)

#elif defined(__linux)
int main(int argc, char **argv, char **env)

#else
int main(int argc, char **argv)
#endif
    try {
  SDL_Guard sdl_guart(SDL_INIT_EVERYTHING);

  const int WINDOW_WIDTH = {320}, WINDOWS_HEIGHT = {240};

  UniqueWindow the_window{SDL_CreateWindow("Example", SDL_WINDOWPOS_UNDEFINED,
                                           SDL_WINDOWPOS_UNDEFINED,
                                           WINDOW_WIDTH, WINDOWS_HEIGHT,
                                           SDL_WINDOW_SHOWN),
                          SDL_DestroyWindow};

  if (!the_window)
    throw std::runtime_error("Error creating window: " +
                             std::string(SDL_GetError()));

  SDL_Surface *winSurface{SDL_GetWindowSurface(the_window.get())};

  if (!winSurface)
    throw std::runtime_error("Error getting surface: " +
                             std::string(SDL_GetError()));

  SDL_FillRect(winSurface, NULL,
               SDL_MapRGB(winSurface->format, 0x00, 0x00, 0x00));

  SDL_UpdateWindowSurface(the_window.get());

  SDL_Event e;

  bool quit = {false};

  do {
    SDL_UpdateWindowSurface(the_window.get());
    while (SDL_PollEvent(&e)) {
      switch (e.type) {
      case SDL_QUIT:
        quit = true;
        break;
      default:
        break;
      }
    }
  } while (!quit);

  return EXIT_SUCCESS;
}

catch (const std::exception &e) {
  std::cout << e.what() << std::endl;
  return EXIT_FAILURE;
}

catch (...) {
  std::cout << "Something wrong\n";
  return -EXIT_FAILURE;
}
cmake_minimum_required(VERSION 3.11)

project(sdlprog)

find_package(SDL2 REQUIRED)

add_executable(${PROJECT_NAME} src/main.cpp)

target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES})