§1 Первая программа. Рисование линий и фигур (класс VertexArray)

Знакомство с примитивами SFML

Графический модуль (Graphics module) содержит весь арсенал для рисования в области окна, а также функции для отрисовки самого окна. Создадим окно первого приложения. В начале программы (1.1) включим графический модуль и определим пространство имен SFML. В главной функции программы создадим объект окна window как экземпляр класса RenderWindow. Конструктор принимает несколько аргументов. Первый – это разрешение окна VideoMode, а второй строка-заголовок.
Программа 1.1

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

int main() {
	//======================================================//
	// Конструктор окна                                     //
	//======================================================//
    RenderWindow window(VideoMode(500, 500), "lesson-1-1");

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

Программа содержит два обязательных (т. е. их нельзя удалять) вложенных цикла, обеспечивающих работу приложения. Эти циклы – событийного характера. Обработчики событий мы рассмотрим позднее. Внешний цикл, контролирующий закрытие окна, содержит вызовы различных функций. За отображение окна отвечает метод display(), он должен быть последним в череде вызовов.
В пределах созданного окна нарисуем две линии диагонально к окну. Обычные линии создаются классом VertexArray. Графические примитивы этого класса создаются путем введения массива точек, которые (если это не Points) соединяются линиями.
Система координат – обычная экранная система: центр координат находится в левом верхнем углу. Положительные значения по иксу откладываются вправо, а положительные значения по игреку откладываются вниз.
Толщину линий этого класса изменить нельзя, она всегда фиксирована, но можно определить их цвет. При этом цвет определяется к элементу массива, а не ко всему массиву. Это позволяет рисовать градиентные линии.
Для того, чтобы нарисовать линию с заданной толщиной необходимо использовать другой класс, например (как в программе ниже), – RectangleShape. В этом классе используются иные методы рисования: setPosition для определения начальной позиции, setFillColor – цвета и rotate – направления.
Программа 1.2. Линии

#include  <SFML/Graphics.hpp>
#include <cmath> // для hypot
using namespace sf;

int main() {
    RenderWindow window(VideoMode(500, 500), "lesson-1-2");
    //======================================================
    // Конструктор линии
    //======================================================
    VertexArray line(Lines, 2);
    line[0].position = Vector2f(0, 0);
    line[0].color = Color::Blue;
    line[1].position = Vector2f(500, 500);
    // линия будет с градиентом
    line[1].color = Color::Cyan;

    //======================================================
    // Конструктор линии с изменяемой толщиной
    //======================================================
    RectangleShape line2(Vector2f(hypot(500, 500), 5));
    // Устанавливаем позицию откуда начинать рисовать
    line2.setPosition(0, 500);
    line2.setFillColor(Color(255, 0, 0));
    // минус рисует вверх
    line2.rotate(-45);

    while (window.isOpen()) {
    	// Конструктор обработчика событий
        Event event;
        while (window.pollEvent(event)) {
            if (event.type == Event::Closed)
                window.close();
        }
        // Вызовы функций
        window.clear();
        window.draw(line);
        window.draw(line2);
        window.display();

    }
    return 0;
}


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

#include <SFML/Graphics.hpp>
#include <cmath> //для sin
using namespace sf;

int main() {
	int W = 500; // Ширина и высота окна
	int H = 500;
    RenderWindow window(VideoMode(W, H), "lesson-1-3");
    //======================================================
    // Рисуем синусоиду с помощью Points
    //======================================================
    VertexArray point(Points, W);
    double x = 0.0;
    int n = 2; // плотность кривой
    int h = H / 2 - 30; // высота кривой
    double d = 0.05; // плотность точек
    for (int i = 0; i < W; i++) {
    	point[i].position = Vector2f(i * n, H / 2 - h * sin(x));
    	int clr = (i < 256 ? i : i % 255);
    	point[i].color = Color(255 - clr, 0, clr);
    	x += d;
    }
    //======================================================
    // Главный цикл программы
    //======================================================
    while (window.isOpen()) {
    	// Конструктор обработчика событий
        Event event;
        while (window.pollEvent(event)) {
            if (event.type == Event::Closed)
                window.close();
        }
        // Вызовы функций
        window.clear();
        window.draw(point);
        window.display();
    }
    return 0;
}

Фигуры класса VertexArray

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

  • LineStripLines создает неконтактные линии, LineStrip, напротив, создает контактные линии (последовательно в массиве)
  • Triangles – Создает неконтактные треугольники
  • TriangleStrip – Последовательно в массиве создает контактные треугольники
  • TriangleFan – Последовательно в массиве создает контактные треугольники имеющие общую вершину
  • Quads – Создает неконтактные прямоугольники (устаревшее, не работают с OpenGL ES)
Как видно из приведенного выше списка, примитивы подразделяются на контактные и неконтактные, что позволяет создавать не только правильные, но и неправильные фигуры. Как и линии, фигуры могут быть залиты цветом. Для цвета можно задавать альфа-канал. Порядок точек имеет большое значение. Для выпуклых фигур – точки устанавливаются последовательно, по часовой стрелке. Для TriangleFan – в центре находится точка 0 (общая вершина для всех треугольников), остальные по часовой стрелке. В нашей программе фигура не закончена умышленно, чтобы было видно, что она собирается из треугольников. Аналогично, из треугольников собираются ломаные фигуры. Для TriangleStrip – четные точки (или вершины, начиная с 0) по одной стороне, нечетные по другой, последовательно. Обратите внимание, что цвет должен быть присвоен каждой вершине (по умолчанию фон имеет черный цвет, а точка белый). Если не используется градиент, то нужный цвет массиву вершин можно присвоить в цикле, что мы и сделали.
Программа 1.4

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

int main() {
    RenderWindow window(VideoMode(500, 500), "lesson-1-4");
    //======================================================
    // Градиентный треугольник
    //======================================================
    VertexArray tri(Triangles, 3);
    tri[0].position = Vector2f(30, 30);
    tri[0].color = Color::Blue;
    tri[1].position = Vector2f(130, 30);
    tri[1].color = Color::Green;
    tri[2].position = Vector2f(30, 200);
    tri[2].color = Color::Red;
    //======================================================
    // Градиентный прямоугольник
    //======================================================
    VertexArray qua(Quads, 4);
    qua[0].position = Vector2f(160, 30);
    qua[1].position = Vector2f(280, 30);
    qua[1].color = Color::Blue;
    qua[2].position = Vector2f(280, 100);
    qua[2].color = Color::Blue;
    qua[3].position = Vector2f(160, 100);
    //======================================================
    // Неправильный многоугольник
    //======================================================
    VertexArray way(sf::TrianglesStrip, 16);
    way[0].position =  Vector2f(440, 20);
    way[1].position =  Vector2f(350, 20);
    way[2].position =  Vector2f(480, 60);
    way[3].position =  Vector2f(390, 60);
    way[4].position =  Vector2f(400, 150);
    way[5].position =  Vector2f(310, 150);
    way[6].position =  Vector2f(460, 190);
    way[7].position =  Vector2f(370, 190);
    way[8].position =  Vector2f(460, 280);
    way[9].position =  Vector2f(370, 280);
    way[10].position =  Vector2f(430, 350);
    way[11].position =  Vector2f(340, 350);
    way[12].position =  Vector2f(430, 400);
    way[13].position =  Vector2f(340, 400);
    way[14].position =  Vector2f(490, 480);
    way[15].position =  Vector2f(400, 480);
    for (int i = 0; i < 16; i++)
    	way[i].color = Color::Yellow;
    //======================================================
    // "Неполный" восьмиугольник
    //======================================================
    VertexArray octa(sf::TrianglesFan, 9);
    octa[0].position =  Vector2f(200, 300);
    octa[1].position =  Vector2f(300, 300);
    octa[2].position =  Vector2f(280, 380);
    octa[3].position =  Vector2f(200, 400);
    octa[4].position =  Vector2f(130, 380);
    octa[5].position =  Vector2f(100, 300);
    octa[6].position =  Vector2f(130, 230);
    octa[7].position =  Vector2f(200, 200);
    octa[8].position =  Vector2f(280, 230);
    for (int i = 0; i < 9; i++)
        octa[i].color = Color::Magenta;

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

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

  • Нарисуйте лабиринт
  • Нарисуйте радугу (спектральную полоску, приблизительно)
  • Нарисуйте график функции f(x) = ax3 + bx2. Используйте переменные a и b для изменения внешнего вида графика функции, а также переменные W и H для управления окном программы и отображением графика. Помимо графика, выведите оси координат.
Оцените материал
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...

Print Friendly, PDF & Email

Comments are closed.