МЕТОДЫ РАЗРАБОТКИ ВИДЕОИГР ВВЕДЕНИЕ В SFML
• SFML (англ. Simple and Fast Multimedia Library — простая и быстрая мультимедиа библиотека) — свободная кроссплатформенная мультимедиа библиотека. Написана на C++, но доступна также для C, D, Java, Python, Ruby, OCaml, . Net и Go. Представляет из себя объектноориентированный аналог SDL.
• В настоящее время доступны следующие модули: • System — управление временем и потоками. • Window — управление окнами и взаимодействием с пользователем. • Graphics — делает простым отображение графических примитивов и изображений. • Audio — предоставляет интерфейс для управления звуком. • Network — для сетевых приложений. • Все модули могут быть использованы независимо, кроме модуля Graphics, который зависит от Window.
ЧАСТЬ 1 • Создание и настройка SFML проекта
1: СКАЖЕМ КОМПИЛЯТОРУ ГДЕ НАЙТИ ЗАГОЛОВОЧНЫЕ ФАЙЛЫ SFML
2: ПРИСОЕДИНЯЕМ БИБЛИОТЕКИ К ВАШЕМУ ПРИЛОЖЕНИЮ
"SFML-XXX-D. LIB" FOR DEBUG "SFML-XXX. LIB" FOR RELEASE. • System — управление временем и потоками. • Window — управление окнами и взаимодействием с пользователем. • Graphics — делает простым отображение графических примитивов и изображений. • Audio — предоставляет интерфейс для управления звуком. • Network — для сетевых приложений.
ОПРЕДЕЛИМ МАКРОС SFML_STATIC
ОФИЦИАЛЬНЫЙ САЙТ • Главная: • http: //sfml-dev. org/index. php • Tutorials for SFML 2. 1 • http: //sfml-dev. org/tutorials/2. 1/
ПРИСТУПАЕМ К РАЗБОРУ SFML КОДА НА С++
ПРОСТРАНСТВО ИМЕН • Объявим что мы будем работать с пространством имен sfml • using namespace sf; • Это позволит нам напрямую пользоваться фунционалом sfml • Render. Window window(Video. Mode(800, 600), "Pong"); • вместо • sf: : Render. Window window(sf: : Video. Mode(800, 600), "Pong");
СОЗДАЕМ ГЛАВНОЕ ОКНО ПРИЛОЖЕНИЯ • Render. Window window(Video. Mode(800, 600), "Pong"); КЛАСС ОБЬЕКТ КЛАССА РАЗМЕР ОКНА ЭТО ТОЛЬКО ОДИН ИЗ ВАРИАНТОВ ВЫЗОВОВ НАЗВАНИЕ ОКНА
ГЛАВНЫЙ ЦИКЛ ПРИЛОЖЕНИЯ • While(window. is. Open()) • ПОКА ОБЬЕКТ ОКНО ОТКРЫТ
ОБРАБАТЫВАЕМ СОБЫТИЯ В ЦИКЛЕ Event event; while(window. poll. Event(event)) { // Кроме обычного способа наше окно будет закрываться по нажатию на Escape if(event. type == Event: : Closed || (event. type == Event: : Key. Pressed && event. key. code == Keyboard: : Escape)) window. close() }
• // Очистка • window. clear(); //может принемать параетр цвета на который будет очищен экран • ЗДЕСЬ БУДУТ ВЫЗЫВАТЬСЯ ФУНКЦИИ ГРАФИКИ • // Отрисовка • window. display();
ИЗМЕРЕНИЕ ВРЕМЕНИ • У SFML есть простой и удобный класс для измерения времени • Clock • У класса есть два метода • get. Elapsed. Time // узнать прошедшее время • restart // перезапустить
СОБЫТИЯ Все не внутри игровые события (нажатия клавиш , изменения размера окна и т. д. ) должны происходить в цикле обработчика событий (EVENTS)
ТИПЫ СОБЫТИЙ • Event: : Closed - срабатывает когда пользователь хочет закрыть окно. (window. close() – типичная реакция на этот евент ) • Event: : Resized – срабатывает когда меняется размер окна. • Event: : Lost. Focus и Event: : Gained. Focus - потеря фокуса и фокусирование на окне. Полезно при остановке считывания действий , если окно свернуто. • Event: : Key. Pressed и sf: : Event: : Key. Released – клавиша нажата/отпущена. (event. key. code)
ПРОРИСОВКА
OFF-SCREEN DRAWING РИСОВАНИЕ В ПАМЯТИ • SFML предоставляет возможность прорисовывать как в памяти так и напрямую на экране. • Для прорисовки в памяти нужно использовать объект класса Render. Texture.
ПРИМЕР РИСОВАНИЯ В ПАМЯТИ // create a 500 x 500 render-texture Render. Texture render. Texture; if (!render. Texture. create(500, 500)) { // error. . . } // функции прорисовки для класса Render. Window и Render. Texture //одинаковые render. Texture. clear(); render. Texture. draw(sprite); render. Texture. display(); // создадим ссылку на текстуру(где мы проводили прорисовку в памяти) const Texture& texture = render. Texture. get. Texture(); // Выведем нашу заготовленную текстуру на экран Sprite sprite(texture); window. draw(sprite);
РИСОВАНИЕ ИЗ ПОТОКА • SFML предоставляет возможность мультипотоковой рисовки , и вам ничего особо не нужно делать чтобы оно заработало. Все что нужно это деактивировать окно , поскольку окно не может быть активным в нескольких потоках одновременно.
ПРИМЕР void rendering. Thread(sf: : Render. Window* window) { // the rendering loop while (window->is. Open()) { // draw. . . // end the current frame window->display(); } } int main() { // create the window (remember: it's safer to create it in the main thread due to OS limitations) sf: : Render. Window window(sf: : Video. Mode(800, 600), "Open. GL"); // deactivate its Open. GL context window. set. Active(false); // launch the rendering thread sf: : Thread thread(&rendering. Thread, &window); thread. launch(); // the event/logic/whatever loop while (window. is. Open()) {. . . } return 0; }
СПРАЙТЫ И ТЕКСТУРЫ
ТЕКСТУРА • Текстура – это изображение , которое будет в дальнейшем наносится на какой либо игровой объект. текстура
СПРАЙТ • Спрайт – это прямоугольник с нанесенным на него текстурой или частью текстуры. (Чаще всего — растровое изображение, свободно перемещающееся по экрану. [)
ЗАГРУЗКА ТЕКСТУРЫ Мы загружаем нашу текстуру в класс Texture С помощью метода load. From. File(“…”) при загрузке с носителя. Пример: sf: : Texture texture; if (!texture. load. From. File("image. png")) { // error. . . }
ТАК ЖЕ МОЖНО ЗАГРУЗИТЬ СПРАЙТ В ОПРЕДЕЛЕННОМ ДИАПАЗОНЕ // загружаем квадрат размером 32 x 32 пикселя начиная с точки(10, 10) if (!texture. load. From. File("image. png", sf: : Int. Rect(10, 32, 32))) { // error. . . }
НЕМНОГО О ДВУХМЕРНОЙ ДЕКАРТОВОЙ ПЛОСКОСТИ 0 У 0 Х Обычная двухмерная система координат Х У двухмерная система координат в SFML
• Текстуры можно не только грузить файла , но и просто создать пустую текстуру. • // создаем пустую текстуру размером 200 x 200 • if (!texture. create(200, 200)) • { // error. . . }
ОБНОВЛЕНИЕ ТЕКСТУРЫ • Текстуру можно обновлять с помощью соответствующих перегруженных функций // обновить по массиву пикселей sf: : Uint 8* pixels = new sf: : Uint 8[width * height * 4]; // * 4 потому-что пиксель имеет 4 компонента(RGBA) texture. update(pixels); // обновить текстуру по sf: : Image image; texture. update(image); // обновить текстуру по текущему окну sf: : Render. Window window; . . . texture. update(window);
СГЛАЖИВАНИЕ ТЕКСТУРЫ • SFML предоставляет инструмент для сглаживания текстур. • texture. set. Smooth(true);
// inside the main loop, between window. clear() and window. display() window. draw(sprite); СОЗДАНИЕ СПРАЙТ sf: : Sprite sprite; sprite. set. Texture(texture); Рисуем спрайт // в основном цикле , между window. clear() и window. display() window. draw(sprite);
ЕСЛИ ВАМ НЕ ТРЕБУЕТСЯ ЗАГРУЖАТЬ ВСЮ ТЕКСТУРУ , МОЖНО ЗАГРУЗИТЬ ЛИШЬ ЕЕ ЧАСТЬ • sprite. set. Texture. Rect(sf: : Int. Rect(10, 32, 32)); Верхняя левая позиция размеры
ИЗМЕНЕНИЕ ЦВЕТА СПРАЙТА sprite. set. Color(sf: : Color(0, 255, 0)); // зеленый sprite. set. Color(sf: : Color(255, 128)); // полу-прозрачный R G B T
СПРАЙТ ТАКЖЕ МОЖЕТ БЫТЬ ТРАНСФОРМИРОВАН // позиция sprite. set. Position(sf: : Vector 2 f(10, 50)); //перемещение относительно абсолютная позиция sprite. move(sf: : Vector 2 f(5, 10)); // перемещение относительно текущей позиции // поворот sprite. set. Rotation(90); // относительно абсолютного угла sprite. rotate(15); // относительно текущего угла // маштаб sprite. set. Scale(sf: : Vector 2 f(0. 5 f, 2. f)); // относительно абсолютного значения sprite. scale(sf: : Vector 2 f(1. 5 f, 3. f)); // относительно текущего значения Важно!!! По умолчанию центральная точка поворота – левый верхний угол спрайта. Это можно изменить sprite. set. Origin(sf: : Vector 2 f(25, 25));
ПРОЕКТИРОВАНИЕ СОБСТВЕННЫХ ОБЪЕКТОВ И МАССИВОВ ВЕРШИН
ПРОСТОЙ МАССИВ ВЕРШИН // создать новую вершину sf: : Vertex vertex; // задать ей позицию vertex. position = sf: : Vector 2 f(10, 50); // задать ей цвет vertex. color = sf: : Color: : Red; // задать ей координаты на текстуре vertex. Coords = sf: : Vector 2 f(100, 100); Или использовать соответствующий конструктор sf: : Vertex vertex(sf: : Vector 2 f(10, 50), sf: : Color: : Red, sf: : Vector 2 f(100, 100));
ТЕПЕРЬ, ДАВАЙТЕ ОПРЕДЕЛИМ ПРИМИТИВНЫЙ // создадим массив из 3 вершин которые определят треугольник sf: : Vertex. Array triangle(sf: : Triangles, 3); // зададим вершины треугольника triangle[0]. position = sf: : Vector 2 f(10, 10); triangle[1]. position = sf: : Vector 2 f(100, 10); triangle[2]. position = sf: : Vector 2 f(100, 100); // зададим цвета в этих точках triangle[0]. color = sf: : Color: : Red; triangle[1]. color = sf: : Color: : Blue; triangle[2]. color = sf: : Color: : Green; // и если мы не зададим текстуру , то получим
Прорисовка происходит по той же команде window. draw(triangle);
ТОЧКА sf: : Points Набор несоединённых между собой точек. (размер всегда в один пиксель)
ЛИНИИ sf: : Lines Набор из несоединённых между собой линий. (размер всегда один пиксель)
СОЕДИНЕННЫЕ ЛИНИИ (ЛОМАНАЯ) sf: : Lines. Strip Набор соединенных между собой линий. Конец одной линии это начало другой.
ТРЕУГОЛЬНИКИ sf: : Triangles Набор несоединенных между собой треугольников.
ПОЛОСА ИЗ ТРЕУГОЛЬНИКОВ sf: : Triangles. Strip Набор соединенных между собой треугольников. Последние две вершины первого треугольника принадлежат и следующему треугольнику.
ТРЕУГОЛЬНИКИ С ОБЩЕЙ ЦЕНТРАЛЬНОЙ ТОЧКОЙ sf: : Triangles. Fan Набор треугольников с общей точкой в центре. Первая вершина является центром , каждая последующая определяет новый треугольник.
ЧЕТЫРЕХУГОЛЬНИК sf: : Quads Набор несоединенных между собой четырехугольников. Вершины должны быть объявлены или по часовой или против часовой стрелки.
ТЕКСТУРИРОВАНИИЕ ПРИМИТИВОВ
// создаем четырехугольник sf: : Vertex. Array quad(sf: : Quads, 4); // определим его как квадрат, расположенный в (10, 10) и с размером 100 x 100 quad[0]. position = sf: : Vector 2 f(10, 10); quad[1]. position = sf: : Vector 2 f(110, 10); quad[2]. position = sf: : Vector 2 f(110, 110); quad[3]. position = sf: : Vector 2 f(10, 110); // определим наносимую текстуру размером 25 x 50 начиная с точки (0, 0) quad[0]. tex. Coords = sf: : Vector 2 f(0, 0); quad[1]. tex. Coords = sf: : Vector 2 f(25, 0); quad[2]. tex. Coords = sf: : Vector 2 f(25, 50); quad[3]. tex. Coords = sf: : Vector 2 f(0, 50); В отличие от open. GL текстура задается в пикселях , а не в диапазоне от 0 до 1