Предыдущая тема

Продолжая тему построение графических объектов используя мультимедийную библиотеку SFML, рассмотрим интересный класс VertexArray (массив вершин).

Точки

#include <SFML/Graphics.hpp>

using namespace sf;

int main()
{
    srand(time(NULL));  
    RenderWindow window(VideoMode( 1500, 900 ), L"Titul", Style::Default);

    //Массив точек
    VertexArray mypoint(Points, 10000);
    for (int i = 0; i < 10000; i++) 
        mypoint[i].position=Vector2f(rand()%1500, rand() % 900);

       while (window.isOpen())
    {
        
        Event event;
        while (window.pollEvent(event))
        {
            if (event.type == Event::Closed) window.close();                
        }
        
        window.clear(Color::Blue);
        window.draw(mypoint); // Точка
        window.display();
    }
    return 0;
}

VertexArray mypoint(Points, 10000) в параметрах объекта mypoint указываем тип объекта Points - точка и этих точек должно быть 10000. Через цикл for обращаемся к каждой точке и устанавливаем случайные координаты для неё mypoint[i].position=Vector2f(rand()%1500, rand() % 900), не забываем в начале запустить генератор случайных чисел srand(time(NULL)).

Линии

// Массив линий
    VertexArray myLines(Lines, 40);
    for (int i = 0,y=0; i < 40; i+=2,y+=10)
    {   myLines[i].position = Vector2f(100, 100+y);
        myLines[i+1].position = Vector2f(500, 100+y);
     }

Объект myLines содержит в параметрах тип Lines - линия и количество точек 40, так как для построения линии необходимо две точки, указав 40 точек, получаем 20 линий. Как и ранее для каждой точки с помощью цикла for устанавливаем координаты места положения в графическом окне. Незабываем в конце цикла while (window.isOpen()) рисовать данный объект window.draw(myLines).

Ломаная линия

// Ломаная линия
    VertexArray myLinesStrip(LineStrip, 20);
    for (int i = 0, y = 0; i < 20; i += 2, y += 50) {
        myLinesStrip[i].position = Vector2f(600, 100 + y);
        myLinesStrip[i + 1].position = Vector2f(1200, 100 + y);
    }

Массив треугольников

// Массив треугольников
    VertexArray myTriangles(Triangles, 9);
    myTriangles[0].position= Vector2f(150, 350); 
    myTriangles[1].position = Vector2f(250, 250);
    myTriangles[2].position = Vector2f(350, 350);
    myTriangles[0].color = Color(255, 0, 74);
    myTriangles[1].color = Color(255, 0, 74);
    myTriangles[2].color = Color(255, 0, 74);

    myTriangles[3].position = Vector2f(400, 200);
    myTriangles[4].position = Vector2f(600, 300);
    myTriangles[5].position = Vector2f(400, 400);
    myTriangles[3].color = Color(153, 255, 70);
    myTriangles[4].color = Color(153, 255, 70);
    myTriangles[5].color = Color(153, 255, 70);

    myTriangles[6].position = Vector2f(600, 400);
    myTriangles[7].position = Vector2f(800, 100);
    myTriangles[8].position = Vector2f(800, 400);
    myTriangles[6].color = Color(255, 255, 0);
    myTriangles[7].color = Color(255, 255, 0);
    myTriangles[8].color = Color(255, 255, 0);
Рисунок №1
Рисунок №1

Для отображения треугольников в параметрах объекта myTriangle указываем тип фигуры треугольник (Triangle) и обозначив 9 точек, рисуем три треугольника. Для корректного отображения фигур, необходимо следовать установленному порядку обозначения координат вершин треугольников.

Порядок определения координат вершин треугольников обозначен на рисунке №1.

Используя функцию Color разукрашиваем точки треугольников (myTriangles[8].color = Color(255, 255, 0)) в формате RGB.

Массив соединённых треугольников.

VertexArray myTriangleStrip(TriangleStrip, 10);
    myTriangleStrip[0].position = Vector2f(100, 200);
    myTriangleStrip[1].position = Vector2f(100, 400);
    myTriangleStrip[2].position = Vector2f(300, 200);
    myTriangleStrip[0].color = Color(0, 181, 99);
    myTriangleStrip[1].color = Color(0, 181, 99);
    myTriangleStrip[2].color = Color(102, 0, 99);

    myTriangleStrip[3].position = Vector2f(300, 400);
    myTriangleStrip[4].position = Vector2f(500, 300);
    myTriangleStrip[5].position = Vector2f(500, 500);
    myTriangleStrip[3].color = Color(102, 0, 99);
    myTriangleStrip[4].color = Color(255, 255, 0);
    myTriangleStrip[5].color = Color(255, 255, 0);

    myTriangleStrip[6].position = Vector2f(700, 300);
    myTriangleStrip[7].position = Vector2f(700, 500);
    myTriangleStrip[8].position = Vector2f(900, 400);
    myTriangleStrip[9].position = Vector2f(900, 600);
    myTriangleStrip[6].color = Color(126, 221, 54);
    myTriangleStrip[7].color = Color(126, 221, 54);
    myTriangleStrip[8].color = Color(0, 0, 205);
    myTriangleStrip[9].color = Color(0, 0, 205);

В массиве соединённых треугольников, каждый треугольник разделяет две свои последние вершины со следующим.

Массив треугольников соединённых с центральной точкой

VertexArray myTriangleFan(TriangleFan, 12);
    myTriangleFan[0].position = Vector2f(250, 200);
    myTriangleFan[1].position = Vector2f(350, 250);
    myTriangleFan[2].position = Vector2f(300, 300);
    myTriangleFan[0].color =Color::Yellow;
    myTriangleFan[1].color = Color::White;
    myTriangleFan[2].color = Color::White;

    myTriangleFan[3].position = Vector2f(250, 315);
    myTriangleFan[4].position = Vector2f(200, 300);
    myTriangleFan[5].position = Vector2f(140, 250);
    myTriangleFan[3].color = Color::Red;
    myTriangleFan[4].color = Color::Red;
    myTriangleFan[5].color = Color::Magenta;

    myTriangleFan[6].position = Vector2f(130, 200);
    myTriangleFan[7].position = Vector2f(140, 150);
    myTriangleFan[8].position = Vector2f(200, 100);
    myTriangleFan[9].position = Vector2f(250, 80);
    myTriangleFan[10].position = Vector2f(300, 100);
    myTriangleFan[11].position = Vector2f(350, 150);
    myTriangleFan[6].color = Color::Magenta;
    myTriangleFan[7].color = Color::Green;
    myTriangleFan[8].color = Color::Green;
    myTriangleFan[9].color = Color::Cyan;
    myTriangleFan[10].color = Color::Cyan;
    myTriangleFan[11].color = Color::Yellow;

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

Массив четырёхугольников

VertexArray myQuads(Quads, 12);
    myQuads[0].position = Vector2f(400, 300);
    myQuads[1].position = Vector2f(400, 200);
    myQuads[2].position = Vector2f(500, 200);
    myQuads[3].position = Vector2f(500, 300);
    myQuads[0].color = Color(255, 102, 255);
    myQuads[1].color = Color(255, 102, 255);
    myQuads[2].color = Color(255, 102, 255);
    myQuads[3].color = Color(255, 102, 255);
    
    myQuads[4].position = Vector2f(600, 300);
    myQuads[5].position = Vector2f(600, 200);
    myQuads[6].position = Vector2f(800, 200);
    myQuads[7].position = Vector2f(800, 300);
    myQuads[4].color = Color(102, 0, 99);
    myQuads[5].color = Color(102, 0, 99);
    myQuads[6].color = Color(102, 0, 99);
    myQuads[7].color = Color(102, 0, 99);
    
    myQuads[8].position = Vector2f(500, 500);
    myQuads[9].position = Vector2f(600, 400);
    myQuads[10].position = Vector2f(800, 400);
    myQuads[11].position = Vector2f(700, 500);
    myQuads[8].color = Color(255, 88, 0);
    myQuads[9].color = Color(255, 88, 0);
    myQuads[10].color = Color(255, 88, 0);
    myQuads[11].color = Color(255, 88, 0);

В массиве четырёхугольников, 4 вершины каждого четырёхугольника должны быть определены последовательно, либо по часовой стрелки, либо против часовой стрелки.

Прототип симулятора солнечной системы

Используя знания предыдущей и этой темы создадим симулятор солнечной системы.

В основе программного кода будем использовать формулу нахождения координат точки на окружности.

x = x0 + round(rad*cos(a*PI/180));
y = y0 + round(rad * sin(a * PI / 180))*vector;

где, x и y - координаты вращающегося объекта, x0 и y0 - координаты центра вращения, round() - функция округления до ближайшего целого, rad - расстояние от центра вращения до объекта вращения, cos() и sin() - тригонометрические функции, a - изменяемый угол при вращении от 0 до 360 градусов, PI - число 3.14, vector - направление вращения равен 1 или -1. Процесс вычисления координат вращающегося объекта поместим в отдельный класс Planets. Который будет состоять из двух конструкторов:

Planets(int startx, int starty, int r, int v);
Planets(int r, int v);

где, переменные int startx, int starty - координаты центра вращения, int r - расстояние от центра вращения до объекта вращения, int v - направление вращения.

Методы int getx(), int gety() - будут возвращать координаты вращающегося объекта. Метод void move(double s) - будет изменять угол вращения с шагом указанным в переменной double s. Метод void setposition(int startx, int starty) служит для изменения центра вращения.

Ниже привожу код с подробным описание каждого блока.

#include <SFML/Graphics.hpp>
#include <math.h>

using namespace sf;
using namespace std;

// Класс для вычисления кооординат вращающегося объекта
class Planets
{
    public:
    Planets(int startx, int starty, int r, int v);
    Planets(int r, int v);
    int getx();
    int gety();
    void move(double s);
    void setposition(int startx, int starty);
    private:
    int x0=0,y0=0,rad=0,x=0,y=0,vector=1;
    double a = 0;
    const double PI = acos(-1.0);
};

Planets::Planets(int startx, int starty, int r, int v)
{
    if (v > 1) v = 1;
    if (v < -1 || v == 0) v = -1;
    vector = v;
    x0 = startx;
    y0 = starty;
    rad = r;
}

Planets::Planets(int r, int v)
{
    if (v > 1) v = 1;
    if (v < -1 || v == 0) v = -1;
    vector = v;
    rad = r;
}

int Planets::getx()
{
    return x;
}

int Planets::gety()
{
    return y;
}

void Planets::move(double s)
{
    a += s;
    if (a > 360) a = 0;
   x = x0 + round(rad*cos(a*PI/180));
   y = y0 + round(rad * sin(a * PI / 180))*vector;

}

void Planets::setposition(int startx, int starty)
{
    x0 = startx;
    y0 = starty;
}

int main()
{
    // Запускаем генератор случайных чисел
    srand(time(NULL));
    // Создаём графическое окно
    RenderWindow window(VideoMode(1500, 900), L"Солнечная система", Style::Default);
    // Вертикальная синхронизация кадров анимации
    window.setVerticalSyncEnabled(true);
    // Объявление планет солнце, меркурий, венера, земля, марс, луна
    CircleShape sun(100.f), merk(1), vener(6), earth(10), mars(4), moon(4);   
    // Задаём параметры для солнца
    sun.setPosition(750, 450);           
    sun.setOrigin(100,100);
    Texture texsun;
    texsun.loadFromFile("sun.png");
    sun.setTexture(&texsun);
    //Задаём параметры для звезд
    VertexArray stars(Points, 50);
    for (int i = 0; i < 49; i++) {stars[i].color = Color(255, 255, 255);
    stars[i].position = Vector2f(rand() % 1500, rand() % 900);}
    //Задаём параметры для земли
    Texture texearth;
    texearth.loadFromFile("erd.png");
    earth.setTexture(&texearth);
    earth.setOrigin(5,5);
   //Задаём параметры для венеры
    vener.setFillColor(Color(208, 159, 46));
    vener.setOrigin(3, 3);
    //Задаём параметры для марса
    mars.setFillColor(Color(223, 54, 16));
    mars.setOrigin(2, 2);
    //Задаём параметры для меркурия
    merk.setFillColor(Color(208, 159, 46));
    //Задаём параметры для луны
    Texture texmoon;
    texmoon.loadFromFile("luna.png");
    moon.setTexture(&texmoon);
    moon.setOrigin(2, 2);
    // Создаём объекты определения координат планет
    Planets merkxy(750,450,150,-1),venerxy(750,450,200,-1), marsxy(750,450,300,-1), earthxy(750,450,250,-1);
    Planets moonxy(30,-1);

    while (window.isOpen())
    {
        Event event;
        while (window.pollEvent(event)) if (event.type == Event::Closed)window.close();
        // Каждую итерацию изменяем угол положения планеты на 1       
        merkxy.move(1);
        //Устанавливаем текущие координаты объекта
        merk.setPosition(merkxy.getx(), merkxy.gety());
         // Каждую итерацию изменяем угол положения планеты на 0.5  
        venerxy.move(0.5);
        //Устанавливаем текущие координаты объекта
        vener.setPosition(venerxy.getx(), venerxy.gety());
        // Каждую итерацию изменяем угол положения планеты на 1.5  
        marsxy.move(1.5);
        //Устанавливаем текущие координаты объекта
        mars.setPosition(marsxy.getx(), marsxy.gety());
         // Каждую итерацию изменяем угол положения планеты на 0.8 
        earthxy.move(0.8);
        //Устанавливаем текущие координаты объекта
        earth.setPosition(earthxy.getx(), earthxy.gety());
        // Определяем центр вращения, так как земля меняет своё положение 
        moonxy.setposition(earth.getPosition().x, earth.getPosition().y);
        // Каждую итерацию изменяем угол положения планеты на 3 
        moonxy.move(3);
        //Устанавливаем текущие координаты объекта
        moon.setPosition(moonxy.getx(), moonxy.gety());
        // Вращаем солнце        
        sun.rotate(-1);
               
        window.clear();
        window.draw(stars);
        window.draw(sun);
        window.draw(merk);
        window.draw(vener);
        window.draw(earth);
        window.draw(mars);
        window.draw(moon);
        window.display();
    }
    return 0;
}

Более подробную инструкцию по 2D примитивам мультимедийной библиотеки SFML вы можете увидеть посмотрев видео "2D примитивы SFML C++".

Предыдущая тема

Комментарии (2)


  1. sci_nov
    28.11.2022 22:44

    Кажется, Вы реализовали мою юношескую мечту :).


    1. Troyy Автор
      29.11.2022 11:12

      Очень рад ))