Создание простых геометрических фигур в C++/SFML

  Дмитрий Бушуев  | 

  |

  Обновл. 22 Фев 2021  | 

 65281

 ǀ   15 

Ты всю жизнь ощущал, что мир не в порядке. Странная мысль, но её не отогнать. Она — как заноза в мозгу. Она сводит с ума, не дает покоя. Это и привело тебя ко мне… Примешь синюю таблетку — и сказке конец. Ты проснешься в своей постели и поверишь, что это был сон. Примешь красную таблетку — войдешь в страну чудес. Я покажу тебе, насколько глубока библиотека SFML кроличья нора.

Круги

Предлагаю для начала потренироваться на простых геометрических фигурах типа Михаила круга. В этом деле большую помощь нам окажет класс CircleShape:

   конструктор данного класса принимает в качестве параметра радиус нашей будущей фигуры (например, circle(50.f));

   закрасить фигуру можно с помощью метода setFillColor(), который очень похож на уже знакомый нам метод window.clear();

   ну и для отображения круга в окне используется метод window.draw().

Например:

Результат выполнения программы:

Наша фигура может иметь контур. Для его создания используется метод setOutlineThickness(), а для цвета контура — setOutlineColor():

Результат выполнения программы:

Как уже знаем из предыдущего урока, при закрашивании фигур или фона можно еще указать значение прозрачности. Например, строкой setOutlineColor(Color(80, 220, 50, 150)) мы устанавливаем 150 в качестве значения прозрачности контура:

А теперь с помощью строки setOutlineColor(Color(80, 220, 50, 50)) мы установим 50 в качестве значения прозрачности контура:

Вы уже наверняка заметили, что наш круг выходит за границы окна, а это не совсем хорошо. Нужно его немного подвинуть, а поможет нам в этом метод move():

Результат выполнения программы:

Регулярные полигоны


-Welcome to the real world!

Отлично! Сейчас мы рассмотрим, как нарисовать и другие фигуры. Теперь ты готов узнать истину. Она заключается в том, что, на самом деле, ложки не существует, Нео твой круг — это немножко не круг, а многоугольник. Да-да, самый обычный многоугольник с большИм количеством вершин. Всё дело в том, что у конструктора класса CircleShape есть еще и второй параметр (помимо радиуса), который отвечает за количество вершин у создаваемой фигуры, и он по умолчанию равен 30. Именно при значениях близких к 30, многоугольник становится мало отличимым от круга. В то же время, задавая этот параметр самостоятельно, мы можем получить абсолютно другие геометрические элементы. Не трудно догадаться, что 3 вершины — это треугольник, 4 вершины — квадрат, 5 вершин — пятиугольник, ну а 8 вершин — восьмиугольник (октагон).

Ниже приведен полный код матрицы программы, которая наглядно покажет создание данных фигур:

Результат выполнения программы:

Выпуклые многоугольники

Теперь рассмотрим создание выпуклого многоугольника через координаты его вершин. Для работы с такими фигурами в SFML имеется класс ConvexShape, который содержит методы setPointCount() и setPoint(). Метод setPointCount() устанавливает количество вершин будущего многоугольника, а метод setPoint() устанавливает сами вершины, принимая в качестве параметров порядковый номер (индекс) создаваемой вершины и её координаты:

Результат выполнения программы:

Обратите внимание, координаты вершин задаются в виде контейнера Vector2f(a, b). Данный контейнер — это простой шаблонный класс библиотеки SFML.

Примечание: Порядок, в котором вы будете определять точки многоугольника, очень важен. Все они должны быть определены либо по часовой стрелке, либо против часовой стрелки. Если вы будете определять их в несогласованном порядке, то форма многоугольника будет построена неправильно.

Прямоугольники


Для работы с прямоугольниками используется класс RectangleShape, параметрами которого являются геометрические размеры фигуры (ширина и высота). Здесь всё просто:

Результат выполнения программы:

Линии

Для рисования линий в SFML есть класс, который называется… называется… а никак он не называется, потому что специализированного класса для работы с линиями в SFML нет. Но если так подумать: «А нужен ли он вообще?» Ведь линии по своей сути — это те же прямоугольники, только не такие широкие, поэтому вполне логично, что мы можем использовать уже знакомый нам класс RectangleShape.

Сейчас мы создадим линию с заданной толщиной:

Результат выполнения программы:

А теперь линия с нулевой толщиной:

Результат выполнения программы:

Сглаживание


Заметили, какие края у черного многоугольника? Как нет?!?! Да его краями можно деревья пилить! Чтобы избавиться от этого дефекта, нужно включить сглаживание, которое сделает нашу картинку намного более приятной глазу. Сразу отмечу, что в SFML нет возможности включить сглаживание (или «антиалиасинг», от англ. «anti-aliasing») для какой-то одной фигуры. Оно действует глобально для всего окна. При этом учитывайте, что возможность использовать сглаживание зависит от характеристик вашей видеокарты и параметров видеодрайвера:

Результат выполнения программы:

А теперь гифка вам в ленту (смотрите на грани фигур — как было и как стало):

Заключение

-I know Kung Fu!

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

Теперь ты понял, насколько глубока кроличья нора, впереди нас ждет еще очень много интересного…  KNOCK KNOCK NEO.

  GitHub / Создание простых геометрических фигур в C++/SFML — Исходный код

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (108 оценок, среднее: 4,94 из 5)
Загрузка...

Комментариев: 15

  1. Дима:

    "В SFML не реализована возможность рисования линий".

    А как же метод VertexArray? Передаем туда примитив sf::Lines и задаем кол-во вершин 2. Получается VertexArray name(sf::Lines, 2);

  2. Дмитрий:

    Здравствуйте, вопрос не совсем по теме урока, можете подсказать что означает следующая запись "Color::Cyan". Пытался гуглить, но ответа не нашел. "Cyan" это у нас статическая переменная класса "Color", я так понял и через двойное двоеточие мы получаем ее значение? Если можно поясните кто нибудь.

    1. Евгений:

      Да, Вы всё верно поняли, это одна из статических константных переменных цвета, определённых в Color.hpp. Можете посмотреть подробно их в репозитории SFML на Github, ссылка
      есть на оф.сайте библиотеки

  3. Евгений:

    "Для рисования линий в SFML есть класс, который называется… называется… а никак он не называется" -, прошу прощения, но он есть, это sf::Lines) В оф туториале есть отличная статья про примитивные типы sfml : https://www.sfml-dev.org/tutorials/2.5/graphics-vertex-array.php

  4. Егвений:

    Здравствуйте, не совсем понятна конструкция из циклов, точнее назначение второго цикла. Если ясно что первый while бесконечно выполняется и отрисовывает заново каждый раз все фигуры (поправьте, если не так), пока окно не закроется, то со вторым циклом не понятно ничего — что за очередь событий в цикле? Прогнал дебагером — он работает вроде рандомное количество раз даже когда никаких event'ов не происходит, почему мы просто не можем сделать проверку на закрытие без цикла?
    p.s. появился вопрос про отрисувку окна методом display(). В том же самом отладчике увидел что окно рисуется не после применения метода, а после нового захода на цикл.
    Заранее спасибо!

    1. Dmr:

      Ответ — события копятся в очереди, а pollEvent забирает следующее событие, и если оно есть, возвращает true.

      С помощью внутреннего цикла мы гарантированно обрабатываем ВСЕ накопленные события за один цикл работы программы и не засоряем буфер.

  5. Malkavian407:

    А обязательно свойства фигур запихивать именно в цикл?

    1. Фото аватара Дмитрий Бушуев:

      Нет, не обязательно. Их можно определить и вне цикла. 🙂

  6. Виктор:

    Здравствуйте, спасибо за статью, очень помогла освоиться с этой библиотекой:) Такой вопрос: если мне нужно нарисовать 5 звезд, которые отличаются только местоположением и размером, то я должен каждый раз создавать новый ConvexShape или это можно сделать по другому?

    1. Фото аватара Дмитрий Бушуев:

      Добрый день.
      >>…то я должен каждый раз создавать новый ConvexShape…?

      Да. Другого способа я не знаю. 🙂

      1. Kinonik:

        Я когда создавал подсветку краёв поля (т.е. когда мышь подводишь к краю окна и поле сдвигается), я обошёлся 2 локальными прямоугольниками, что меняли своё местоположение и просто рисовались по очереди. А однажды столкнулся с проблемой не поддержки некоторых видеочипов, из-за которых все текстуры становились белыми. Т.е. создать массив пикселей и вывести было невозможно (только второе), экран был белым. Я сделал так, рисовал градиентные линии по оси х на весь экран ну и повторял по y до конца 🙂 мне нужно было то 2-10 кадров в секунду, а так даже 40 получилось (я знаю, что это извращение)
        P.S. я делал 3d движки на этой библиотеке (2 разных типов)

      2. BX400:

        Но вызывать отрисовку для каждого объекта по отдельности накладно.
        Есть кое-что получше: поиск + virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;

    2. Ростислав:

      Если они не будут отличаться размером то просто цикл в котором создаются одни и те же обьекты но каждый раз растояние допустим на 10 пикселей в право. Если они будут отличаться размером и каждая больше другой на 10 пикселей, то вы сами наверно понимаете что можно тоже сделать цикл, рисующий эти звёзды. Иначе сами.

  7. Александр:

    Интересно. На экране какие-то живые объекты появились — не то, что эти угрюмые цифры и буквы.
    Но вопрос. Вот мы нашли эту чудо-библиотеку.
    А как понять, какие там существуют объекты и методы? И вообще с чего начинать?
    откуда CircleShape, window.draw(rectangle), как мы должны догадаться, что нужно еще и window.display()? Где эта информация находится?
    Как мы должны понять, что нужен именно цикл по обработчикам?
    "// Обрабатываем очередь событий в цикле"

    1. Фото аватара Дмитрий Бушуев:

      Как правило, подобную информацию можно найти сайте разработчиков библиотеки.

      В частности, документацию по SFML можно найти здесь:
      Documentation of SFML 2.5.1
      https://www.sfml-dev.org/documentation/2.5.1/annotated.php

      А некоторые базовые примеры использования библиотеки — здесь:
      https://www.sfml-dev.org/tutorials/2.5/

      🙂

Добавить комментарий для Дмитрий Бушуев Отменить ответ

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