§2 Рисование фигур (класс Shape)

Класс Shape

Более высокоуровневый (по сравнению с VertexArray) базовый класс Shape (форма) предназначен для отображения текстурированных форм с контуром. Наследниками этого класса являются классы CircleShape (рисование окружностей и правильных многоугольников), RectangleShape (рисование прямоугольников) и ConvexShape (рисование полигональных фигур). Поэтому эти классы имеют с базовым классом большинство общих методов. Некоторые мы рассмотрим в этом уроке, остальные – при решении прочих задач в других уроках. К общим методам, например, относятся следующие:

  • setOutlineColor(Color(R,G,B,A)) – цвет рамки
  • setOutlineThickness(N) – толщина рамки (в пикселях)
  • setFillColor(Color(R,G,B,A)) – цвет заливки

Класс CircleShape

Этот класс предназначен для отображения окружности. Однако, с помощью этого класса можно получать и правильные фигуры. Связано это с тем, что конструктор класса имеет два параметра:

CircleShape (float radius=0, std::size_t pointCount=30)
  • radius – радиус окружности (расстояние всех точек от барицентра)
  • pointCount – количество точек окружности (или количество углов в многоугольние)
И то, и другое можно установить не только в конструкторе, но и с помощью методов:
  • void setRadius (float radius)
  • void setPointCount (std::size_t count)
Построим с помощью этого класса несколько правильных фигур. Продемонстрируем использование альфа-канала (прозрачности) на примере пересекающихся окружностей.
Программа 2.2

#include  <SFML/Graphics.hpp>
using namespace sf;

int main() {
    RenderWindow window(VideoMode(750, 200), "lesson-2-2");
    //======================================================
    // Конструктор 1 объекта (треугольник)
    //======================================================
    CircleShape Crc1;
    // Установка радиуса
    Crc1.setRadius(80);
    // Установка количества точек
    Crc1.setPointCount(3);
    // Цвет рамки
    Crc1.setOutlineColor(Color(255, 0, 0));
    // Толщина рамки
    Crc1.setOutlineThickness(5);
    // Установка позиции
    Crc1.setPosition(20, 40);
    // Цвет заливки
    Crc1.setFillColor(Color(65, 105, 225));
    //======================================================
    // Конструктор 2 объекта (квадрат)
    //======================================================
    CircleShape Crc2;
    Crc2.setRadius(85);
    Crc2.setPointCount(4);
    Crc2.setOutlineColor(Color(46, 139, 87));
    Crc2.setOutlineThickness(5);
    Crc2.setPosition(280, -20);
    Crc2.setFillColor(Color(255, 255, 0));
    // Поворот
    Crc2.rotate(45);
    //======================================================
    // Конструктор 3 объекта (шестиугольник)
    //======================================================
    CircleShape Crc3;
    Crc3.setRadius(60);
    Crc3.setPointCount(6);
    Crc3.setOutlineColor(Color(128, 0, 128));
    Crc3.setOutlineThickness(5);
    Crc3.setPosition(380, 40);
    Crc3.setFillColor(Color(175, 238, 238));
    //======================================================
    // Конструктор 4 объекта (окружность1)
    //======================================================
    CircleShape Crc4;
    Crc4.setRadius(60);
    Crc4.setOutlineColor(Color(0, 128, 0));
    Crc4.setOutlineThickness(5);
    Crc4.setPosition(540, 40);
    Crc4.setFillColor(Color(218, 165, 32));
    //======================================================
    // Конструктор 5 объекта (окружность2)
    //======================================================
    CircleShape Crc5;
    Crc5.setRadius(60);
    Crc5.setOutlineColor(Color(178, 34, 34, 128));
    Crc5.setOutlineThickness(5);
    Crc5.setPosition(600, 40);
    // Цвет заливки RGBA
    Crc5.setFillColor(Color(30, 144, 255, 128));

    //======================================================
    // Главный цикл программы
    //======================================================
    while (window.isOpen()) {
    	// Конструктор обработчика событий
        Event event;
        while (window.pollEvent(event)) {
            if (event.type == Event::Closed)
                window.close();
        }
        // Вызовы функций
        window.clear();
        window.draw(Crc1);
        window.draw(Crc2);
        window.draw(Crc3);
        window.draw(Crc4);
        window.draw(Crc5);
        window.display();
    }
    return 0;
}


Класс RectangleShape

Пример использования этого класса (для рисования линии) мы рассмотрели на прошлом уроке. Данный класс имеет собственный метод задающий размер прямоугольника. Остальные методы имеют свои особенности, например, вращение осуществляется не вокруг центра фигуры, а вокруг левой верхней вершины. Относительно неё задается и положение фигуры.

  • setSize(Vector2f(W, H)) – размеры прямоугольника (в пикселях: ширина, высота)
  • setPosition(X, Y) – позиция прямоугольника (от левого верхнего угла окна программы)
  • rotate(deg) – вращение вокруг левой верхней вершины (значение в градусах)
Составим программу в которой параметры фигуры изменяются в цикле, а сами фигуры последовательно выводятся поверх друг друга.
Программа 2.3

#include  <SFML/Graphics.hpp>
using namespace sf;

int main() {
    RenderWindow window(VideoMode(500, 500), "lesson-2-3");
    //======================================================
    // Конструктор прямоугольника
    //======================================================
    RectangleShape rect;
    rect.setSize(Vector2f(400, 400));
    rect.setOutlineColor(Color(255, 0, 0));
    rect.setOutlineThickness(5);
    rect.setPosition(50, 50);
    rect.setFillColor(Color(65, 105, 225));

    //======================================================
    // Главный цикл программы
    //======================================================
    while (window.isOpen()) {
        Event event;
        while (window.pollEvent(event)) {
            if (event.type == Event::Closed)
                window.close();
        }
       window.clear();
    	window.draw(rect);
    	// Изменяем параметры в цикле
        for (int i = 1; i <= 10; i++) {
            rect.setPosition(50 + 20 * i, 50 + 20 * i);
            rect.setSize(Vector2f(400 - 40 * i, 400 - 40 * i));
            rect.setFillColor(Color(65 + 10 * i, 105 - 10 * i, 225 - 10 * i));
            rect.setOutlineColor(Color(255, 0 + 15 * i, 0 + 15 * i));
           	window.draw(rect);
        }
        window.display();
    }
    return 0;
}

Класс ConvexShape

Специальный класс для рисования выпуклых многоугольников. При создании многоугольника нужно иметь ввиду два важных факта.

  1. Фигура должна быть выпуклой (т. е. линия проведенная из барицентра до вершины не должна пересекать какую-либо сторону фигуры);
  2. Вершины назначаются последовательно по часовой стрелке.

Примечание. Из положения 1 следует, что звезды рисовать можно.
Вначале определяется общее количество вершин с помощью метода setPointCount(). Далее определяется позиция каждой вершины с помощью метода setPoint():

sf::ConvexShape polygon;
polygon.setPointCount(3);
polygon.setPoint(0, sf::Vector2f(0, 0));
polygon.setPoint(1, sf::Vector2f(0, 10));
polygon.setPoint(2, sf::Vector2f(25, 5));
polygon.setOutlineColor(sf::Color::Red);
polygon.setOutlineThickness(5);
polygon.setPosition(10, 20);

Случайные числа в программе

В программе 2.3 прорисовку квадратов мы выполнили в главном цикле. Это не есть правильное решение, поскольку в цикле, каждый раз, вычислялись параметры квадратов. В дальнейшем, мы будем помещать такие вещи в собственный класс или структуру. Необходимость этого наглядно демонстрирует программа использующая случайные числа. Если какие-то параметры создаются случайным образом, то их значения должны быть записаны до входа в главный цикл (иначе мы бы получили “цветомузыку”). Для этих целей мы использовали контейнер array. В массиве rect будут записаны 20 объектов класса RectangleShape. В этой программе создается гистограмма, в которой высота столбов, цвет заливки и цвет контура задается случайным образом.
Программа 2.4

#include <SFML/Graphics.hpp>
#include <random>
#include <chrono>
#include <array>
using namespace sf;
using namespace std;
using namespace chrono;

int main() {
    int H = 500, W = 500;
    int s = 30; // смещение слева
    RenderWindow window(VideoMode(H, W), , "lesson-2-4");
    long seed = system_clock::now().time_since_epoch().count();
    default_random_engine rnd(seed);
    // Высота столба
    uniform_int_distribution<int> d1(5, 400);
    // Цвет (светлые оттенки исключили)
    uniform_int_distribution<int> d2(0, 200);
    // Создаем массив объектов RectangleShape
    array<RectangleShape, 20> rect;
    for (auto &r : rect) {
        r.setOutlineThickness(2);
        r.setOutlineColor(Color(d2(rnd), d2(rnd), d2(rnd)));
        r.setFillColor(Color(d2(rnd), d2(rnd), d2(rnd)));
        r.setSize(Vector2f(20, d1(rnd)));
        r.setPosition(s, H - 50);
        r.rotate(180);
        s += 24; // с учетом обводки
    }

    while (window.isOpen()) {
        Event event;
        while (window.pollEvent(event)) {
            if (event.type == Event::Closed)
                window.close();
        }
        window.clear();
        for (int i = 0; i < 20; i++)
            window.draw(rect[i]); // а здесь рисуем уже готовые
        window.display();
    }
    return 0;
}


Задания для самостоятельной работы

  1. Нарисуйте шахматную доску
  2. Нарисуйте пятиконечную звезду
  3. Нарисуйте ракету (части композиции: сопло, иллюминатор, крылья)

Оцените материал
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...

Print Friendly, PDF & Email

Comments are closed.