SFML - Рисуем в 2D
Рисуем в 2D
Введение ===
Как было сказано в предыдущих статьях, модуль SFML, отвечающий за окна, предоставляет простой способ создания окна с OpenGL-контекстом и управления его событиями, но не помогает нам что-либо нарисовать. Он дает единственную возможность, но довольно-таки мощную - рисование с помощью OpenGL API напрямую.
К счастью, SFML предоставляет графический модуль, который вам поможет нарисовать различные 2D объекты более простым способом, чем если бы вы использовали OpenGL.
Окно рисования ===
Для рисования разных вещей нам предоставляется графический модуль, вместе с которым вам нужно использовать специальный класс окна sf::RenderWindow. Этот класс получен от класса sf::Window и содержит все его функции. Все, что вы уже знаете об sf::Window (создание, управление событиями, управление частотой кадров, использование OpenGL), также применимо и к sf::RenderWindow.
В добавок к этому, sf::RenderWindow дает высоко-уровневые функции, которые помогут вам очень просто рисовать разные вещи. В этой статье мы остановимся на двух из этих функций : очищении и рисовании. Они напрямую соответствуют своим названиям : функция очистки экрана очищает всё окно и заливает заданным цветом, а функция рисования рисует любой переданный ей объект.
Ниже представлен типичный главный цикл с окном рисования:
#include <SFML/Graphics.hpp> int main() { // создаем окно sf::RenderWindow window(sf::VideoMode(800, 600), "My window"); // приложение будет работать, пока окно открыто while (window.isOpen()) { // проверяем все события окна, которые были запущены с предыдущей итерации цикла sf::Event event; while (window.pollEvent(event)) { // сработало событие закрытия окна - закроем его if (event.type == sf::Event::Closed) window.close(); } // очищаем окно и заливаем черным цветом window.clear(sf::Color::Black); // рисуем что-нибудь здесь // window.draw(...); // конец текущего кадра - отображаем window.display(); } return 0; }
Вызов очистки перед рисование чего-либо является обязательным, иначе то, что было отображено предыдущим кадром будет нарисовано позади нового кадра и смешается. Исключением является, если вы перерисовываете окно полностью так, что ни один пиксель из предыдущего кадра не будет показан. В этом случае вы можете не вызывать функцию очистки (хотя это и не будет иметь большого влияния на производительность).
Вызов функции рисования также обязателен, он принимает то, что нужно рисовать и отображает это в окне. На самом деле оно не отображается напрямую сразу в окно, а сохраняется в скрытом буфере. Затем этот буфер отображается на экран, когда вы вызываете функцию отображения окна - это называется Двойной буферизацией.
Этот цикл очистки\рисования\отображения - единственный хороший способ рисования различных вещей. Не используйте другую стратегию отрисовки, такие, как сохранение пикселей из предыдущего кадра, перебора пикселей, или одиночного вызова рисования и множественного вызова отображения. Вы получите странные результаты, благодаря двойной буферизации.
Современное графическое оборудование и API создано для постоянных циклов очистки\рисования\отображения, в которых всё полностью очищается на каждой итерации главного цикла. Не бойтесь рисовать 1000 спрайтов 60 раз в секунду, это все равно намного меньше рисования миллионов треугольников, которые ваш компьютер может обработать.
Что мы теперь можем нарисовать? ===
Сейчас, когда главный цикл готов для рисования, давайте посмотрим что и как мы можем в нем нарисовать.
SFML дает возможность рисования 4 разных объектов : 3 из них готовы для рисования (спрайты, текст и фигуры), последний - это всего-лишь блок для строительства ваших собственных объектов (буфер вершин).
Хотя они имеют некоторые общие свойства, каждый из этих объектов поставляются с собственными нюансами, которые описаны в специальных учебных пособиях, которые постепенно будут мной переводиться и ссылки буду даны ниже.
Рисование вне окна ===
SFML также предоставляет способ рисования в текстуру или в окно. Для этого используйте класс sf::RenderTexture, вместо sf::RenderWindow. Он имеет такие же функции для рисования, наследованные от общего класса sf::RenderTarget.
// создаем render-texture размерами 500х500 пикселей sf::RenderTexture renderTexture; if (!renderTexture.create(500, 500)) { // ошибка при создании } // все тот же цикл рисования renderTexture.clear(); renderTexture.draw(sprite); // or any other drawable renderTexture.display(); // получаем текстуру, в которую все было отрисовано const sf::Texture& texture = renderTexture.getTexture(); // и рисуем её в окне sf::Sprite sprite(texture); window.draw(sprite);
Функция getTexture возвращает текстуру "только для чтения", это значит, что вы можете только использовать её, не изменяя. Если вы хотите её изменить, перед использованием, вы можете скопировать её в собственную sf::Texture и изменять её.
Класс sf::RenderTexture также имеет такие же функции, как и sf::RenderWindow для управления видом и OpenGL. Если вы используете OpenGL для рисования в render-texture, вы можете запросить создания буфера глубины с помощью передачи третьего параметра в функцию создания текстуры.
renderTexture.create(500, 500, true); // включаем буфер глубины
Рисуем из потоков ===
SFML поддерживает рисование из нескольких потоков, и вам не потребуется никаких дополнительных усилий, чтобы это работало. Единственная вещь, которую вам следует запомнить - это необходимость деактивировать окно перед использованием в другом потоке. Причиной этой необходимости является то, что окно (благодаря контексту OpenGL) не может быть активно в более, чем одном потоке, в один момент времени.
void renderingThread(sf::RenderWindow* window) { // цикл отрисовки while (window->isOpen()) { // рисуем // конец текущего кадра window->display(); } } int main() { // создаем окно sf::RenderWindow window(sf::VideoMode(800, 600), "OpenGL"); // деактивируем контекст OpenGL window.setActive(false); // запускаем поток sf::Thread thread(&renderingThread, &window); thread.launch(); // обрабатываем события,логику и всё, что угодно, в этом цикле while (window.isOpen()) { ... } return 0; }
Как вы можете видеть, вам не требуется возиться с активацией окна в потоке рисования, SFML делает это за вас автоматически, когда это требуется.
Смотрите также:
Комментарии
а вы можете показать что из этого получится ?
а вы можете показать что из этого получится ?
Из чего именно? Просто цикла рисования? Или рисования в текстуру, с последующим натягиванием на спрайт?
А что с полноэкранным режимом и ресайзом окна?
специальный класс окна sf::RenderWindow. Этот класс получен от класса sf::Window и содержит все его функции. Все, что вы уже знаете об sf::Window (создание, управление событиями, управление частотой кадров, использование OpenGL), также применимо и к sf::RenderWindow.
Kozinaka,
http://devtribe.ru/p/programming/sfml-window
Вот отрисовка обычная
И рендер в текстуру 250х250,затем в спрайт,а спрайт красим в зеленый и рисуем
CollectableItemData.cs
[CreateMenuItem(fileName = "newItem", menuName = "Data/Items/Collectable", order = 51]