Sdl rect как двигать
Перейти к содержимому

Sdl rect как двигать

  • автор:

SDL 2: Основы

Сегодня мы напишем простенькую программу выводящую на экран фон и зумируемый спрайт персонажа перемещающегося с помощью WASD и стрелок. + разберемся как в SDL работать с мышкой.

Для работы нам понадобится:

  • SDL2.h
  • SDL2_image.h>
  • SDL2_mixer.h>

Все это можно легко найти на просторах интернета.

Начнем с самого начала:

Инициализация SDL

Начнем, пожалуй, с создания объекта класса SDL_DisplayMode.
Он нам очень пригодится, если мы хотим иметь приложение на весь экран.
Этот объект нужно создать до инициализации самого SDL.

После этого нужно проинициализировать сам SDL:

Флаг SDL_INIT_EVERYTHING инициализирует все подсистемы SDL. Если вам нужно только что то конкретное, то на вики можно найти их полный перечень.

Теперь нам нужно получить параметры монитора с которым мы работаем.
Для этого мы создаем интовую переменную, в которую будет возвращен 0, если все прошло успешно и приравниваем ее функции SDL_GetDesktopDisplayMode(*int displayIndex, SDL_DisplayMode* mode) .
Если в первый аргумент записать 0, то функция обратиться к главному монитору. Все полученные параметры мы сможем считать с объекта displayMode .

Пришло время заняться нашим окном!
Тут все предельно просто, создаем указатель на объект класса SDL_Window и вызываем функцию

Тут все конечно и так ясно, но на всякий случай объясню что к чему.

  • title — имя окна.
  • x,y — координаты окна. Если хотим открыть на весь экран, то нужно ставить 0,0
  • w,h — размеры окна. Что бы открыть на весть экран обращаемся к объекту displayMode .
  • flags — тут выставляем флаги инициализации окна. Вы можете сказать, что я тупой не прав и существует флаг SDL_WINDOW_FULLSCREEN , и я тут изобретаю велосипед своим DisplayMode , но нет!
    Путем научного тыка продуктивных экспериментов, я заметил что такой способ гораздо быстрее и на него не реагируют антивирусники. На тот же SDL_WINDOW_FULLSCREEN аваст кричал, что меня пытаются взломать.

SDL_WINDOW_SHOWN — делает окно видимым.

В итоге на выходе получаем такой код:

Теперь нам нужно создать рендер:

  • window — окно в котором мы будем работать.
  • index — индекс драйвера который будет использовать рендер. Если поставить -1 , то рендер будет использовать первый подходящий драйвер.
  • flags — флаги рендера. Полный список как всегда на вики.
    Я буду использовать SDL_RENDERER_ACCELERATED отвечающий за аппаратное ускорение и SDL_RENDERER_PRESENTVSYNC отвечающий за вертикальную синхронизацию.

Собираем все вместе и получаем:

Теперь SDL готов с нами сотрудничать!

Вывод на экран

Пришло время заняться изображениями.
Для начала нам нужно создать 2 объекта класса SDL_Rect .
Этот объект будет содержать физические параметры наших текстур, таких как ширину, высоту и положение в окне.

И еще пару строк, чтобы чуть позже мы смогли зумировать нашего персонажа:

И вот мы добрались до загрузки текстур.
Я покажу 2 способа:

Но для начала небольшое отступление!
Думаю те кто раньше работали с SDL1.x в объяснениях не нуждаются, но я все же расскажу от том как устроен SDL, вдруг (ну мало ли) тут кто то с ним не знаком.
В SDL есть 4 основных класса/структуры участвующих в выводе изображения на экран: SDL_Texture , SDL_Surface , SDL_Rect , SDL_Render .

Про последние 2 мы уже поговорили, давайте теперь вкратце обсудим оставшиеся.

    SDL_Surface — работая с SDL_mixer.h о нем вы можете забыть. Но глупо с чем то работать не имея ни малейшего представления о том как оно устроено.

Как пример: чистый SDL работает только с BMP, которое поддерживает альфа-канал, только в 32-битном цвете, а он поддерживается для этого формата далеко не на каждой ОС. А тут уже теряется вся польза от кроссплатформенности SDL.

После этого этот объект отправляется в рендер:

Ну вот, с теорией разобрались, пора к практике!

Вариант номер РАЗ:
Этот метод завязан на библиотеках SDL_mixer.h и SDL_Image.h , так что не орите на меня удивляйтесь, когда на вас польются ошибки подключив только SDL2.

Его особенность в том, что он без велосипедов передает альфа-канал.

Теперь у нас есть текстура персонажа готовая показаться на экране. Но перед этим нам нужно еще создать фон.

Вариант номер ДВА:
Фон мы создадим с использованием чистого SDL. Просто потому, что мы можем!

Работая с чистым SDL никогда нельзя забывать делать проверки на ошибки!

И вот наконец то, УРА, пришло время вывести это на экран!

События

Думаю не стоит объяснять что из 2-х картинок игры не выйдет.
Время добавить немного динамики к нашему чуду!

Для начало нужно создать парочку бесконечных циклов, которые работают пока есть события и нет выхода:

Пора заняться непосредственно событиями.
В SDL есть 2 способа считывать события с контроллеров:

    Первым способом мы реализуем работу с мышкой.
    Но для начала добавим пару строк перед циклами:

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

Думаю это не требует пояснений, если вы внимательно читали и занимаетесь программированием больше 21 дня, но все же уточню, что event.button.button ждет специальный флаг SDLя, который вы сможете легко найти на вики, а event.type ждет флага о типе события, полный список которых находится все там же!

Мы уже можем закрыть окно кликом по левому верхнему углу экрана! И даже более того, мы можем убрать и вернуть персонажа когда захотим просто кликнув по нему!
Да, я тоже чувствую, как ощущение власти начинает нас захлестывать, но не время останавливаться, впереди еще клавиатура!

Она нужна что бы отслеживать состояния кнопок.

Еще вне нашей главной функции надо добавить много-много кода, который сделает нашу программу более структурированной.
(Вижу кто то уже начал писать о том, что нужно пользоваться классами и библиотеками, но я хочу напомнить, что это туториал и будет не хорошо, если человек запутается собирая код, поэтому будем писать все максимально просто. Приношу свои извинения тем, чьи чувства я задел!)

И теперь возвращаемся во внутренний цикл и добавляем еще много-много кода:

Осталось вывести полученный результат на экран. Для этого добавляем в цикл:

Закрываем цикл!
И в итоге нам осталось только завершить нашу программу.

Занавес!

Перед тем как все закончить нам нужно удалить наши текстуры из памяти.

И теперь можно смело завершать работу SDL и программы:

Финал, овации! Мы написали первую программу на SDL2! С чем я нас поздравляю!

P.S.

Что бы создать такую элементарную программу у меня ушло 2 дня. В интернете настолько мало мануалов по SDL2, что проще застрелиться чем что то найти.
Очень надеюсь, что Вам эта статья была полезна и этот монстр не отберет у вас так много времени, как у меня.

Rectangles, Image Movement and Scaling

Screens and Images are rectangular, so this shape has a special importance to SDL2 and graphics programming in particular.

Rectangles: TSDL_Rect and PSDL_Rect in SDL 2.0

Often functions require an argument of PSDL_Rect type. This is the pointer counterpart to TSDL_Rect. It is declared as follows.

Simply, this record describes a rectangle, hence the name. The variables x and y correspond to the x/y coordinates of the left upper corner of the rectangle, related to the origin 0/0 which is the left upper corner of, e.g. a texture, window,… The variable w is the width and h the height of the rectangle. That’s it. The next step is to define the rectangle by assign some values for x, y, w and h.

If you use PSDL_Rect, you free the required memory by Pascal’s new procedure as you would for any simple record pointer.

Using Rectangles for Movement and Scaling

The following code demonstrates the basic principle how to achieve the impression of movement of images (sprites) and how scaling works. You will be impressed how simple it actually is.

We will get this as a result.

alt=»Creative Commons License» width=»» /> This image by https://www.freepascal-meets-sdl.net is licensed under a Creative Commons Attribution 4.0 International License.
The result of the example program (500×500 px window). A part of the full image is stretched in the background while the full image is also squeezed into an area above the word “Free”.

For comparison, here is the original 200×200 px image.

Original image (200×200 px).

Let’s disect the code.

In the var clause we declare the known variables for window, renderer and a texture. Also we have a new variable of TSDL_Rect type.

After initializing SDL2 and setting up the window and renderer as known, the rectangle is getting some values. It just encloses the words “Free Pascal meets SDL” in the original image (see above).

Scaling in SDL2

Scaling Quality

Right before creating the surface and texture, there is this line in code.

It sets the render quality. It has to be set before creating the texture. The SDL_SetHint(hint name, hint value) function is no specific function for setting scaling quality, but here we use it for exactly that. Possible values are

  1. nearest or 0
    • nearest pixel sampling
  2. linear or 1
    • linear filtering
    • support by OpenGL and Direct3D
  3. best or 2
    • anisotropic filtering
    • support by Direct3D.

All of the values have to be set as string values, so ‘nearest’ or ‘0’. Here is a comparision of the nearest- and the linear filter.

  • Result image of the code.Nearest pixel sampling filter for scaling.
  • Result of code with linear filter.Linear filter for scaling.

The anisotropic filter doesn’t do anything for me, even if I used Direct3D.

Scaling by using Rectangles

At this point happens the magic that leads to the resulting image. By the way, since the SDL_RenderCopy() function requires the rectangle arguments to be of PSDL_Rect, we use the @-operator (pointer operator) here.

This means, copy the area described by “sdlRectangle” from the source (“sdlTexture1” here) to the whole area (because of nil value) of the destination, hence the window.

Since the window has a width and height of 500 px each, the source rectangle just a width of 178 px and a height of 116 px, SDL2 automatically scales the image to fit into the larger (or smaller) dimensions of the destination.

This means, copy the whole source (because of nil value) to the area described by “sdlRectangle”. The source is the 200×200 px image, which has to squeezed to the 178×116 px rectangle at position (12/25). This is just what you see in the resulting image (above) where the whole image is squeezed into this area.

Movement of Images (Sprites)

Although not covered directly by this code example, you get the picture how movement works. Every frame you adjust the (x/y) coordinates of the rectangle for the destination to bring the sprite about to move.

How to rotate a rect in SDL2?

I plan on making a game, and I want to create some background animations for said game. One of these animations is a rotating rectangle. I’ve looked all over, and I cannot find any form of math or logic that allows me to rotate a rectangle (SDL_Rect to be specific, but you might have already known that).

I can’t figure out the math for myself, I really don’t have any working code for this, so I can’t show anything.

Essentially I’m looking for some type of logic that I can apply the rectangle’s coordinates so that whenever the main game loop loops, it will rotate the rectangle some amount of degrees.

C — SDL (Simple Directmedia Layer) — Creating a rectangle and moving it

We are going to see, with this tutorial, how to create a shape on a window and how to move it with keyboard arrows.

We need, for this example, three files that we are going to create to dispatch the code:

  • main.c
  • manager_sdl.c
  • h.h

Of course, you can add a Makefile to easily compile and link files.
But to link the .o, you need to add the -lSDL command.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *