В данном разделе раскрываются нюансы использования SFML в IDE Dev-Cpp
Архивы: Справочники
Урок 3.1. EventHandlerWindows – Обработчик событий окон
Почти в каждой современной игре есть окна и кнопки для элементарного взаимодействия с игроком.
Вот пример одной MMORPG c оконной системой
Скажем так, SFML не предоставляет такого функционала, поэтому его придётся делать вручную. В нескольких уроках мы рассмотрим как создавать такую систему практически с 0. Мы будем имитировать работу оконной системы Windows.
1. EventHandlerWindows
2. Window
3. Design
4. Item
В этом уроке рассмотрим всё поверхностно, а в следующем углубимся.
1. EventHandlerWindows – обработчик событий окон.
Это класс, который содержит в себе ссылки на окна и некоторые данные для обработки, а так-же ориентируясь на мышь управляет окнами.
Основные функции нужные в обработчике:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// Добавлякт окно в обработчик окон void add(Window* window); // Обработчик событий (поведение окон) void behavior(int numEvent); // Сортировка окон void sort1(int j); // Установить видимость окна под номером num в положение flag bool setVisibleWin(int num, bool flag); // Заменить на противоположное значение видимости окна void switchVisibleWin(int num); // Отрисовка во входящем окне void draw(sf::RenderWindow* window); void draw(); |
Из комментариев и так понятно для чего нужны эти функции.
Стоит выделить самые важные из них:
1. add(Window* win) – добавляет окно в обработчик окон
2. behavior(int numEvent) – управляет окнами опираясь на входящие события мыши (numEvent)
3. draw() – отображение окон
В цикле обработки игры это будет выглядеть вот так:
1 2 3 4 5 6 7 8 9 10 |
mouse->behavior(); int num = mouse->getEventButton(sf::Mouse::Left); EHW->behavior(num); window.clear(sf::Color::White); EHW->draw(); mouse->draw(); window.display(); |
2. Window – окно
Класс Window представляет собой набор параметров (например координаты и размеры окна) и объекты (спрайты, кнопки, картинки и т.д.), а так-же набор функций для добавления этих объектов, их обработки и отображения.
Наше окно может перемещаться, закрываться и даже изменять размеры! В файле Window.h описаны доп. структуры которые и образуют окно.
1 2 3 4 5 6 7 |
struct winSprite; struct WinItem; struct winMcText; struct winButton; struct winSave; struct winSlot; struct winCheckBox; |
Немного поподробнее:
winSprite – это спрайт, из которого создаётся сама рамка окна
winItem – это базовый класс для последующих элементов, которые будут расположены на нашем окне (winButton, winSlot, winCheckBox, winMcText)
winMcText – тот же mcText только привязанный к окну.
winSave – набор параметров, которые нужны для изменения размеров окна.
Основные функции нужные в окне:
1 2 3 4 5 6 7 |
void setDesign(DesignWindow* desWin); void save(vec2i, int); void changeSize(Mouse*); void changePosition(Mouse*); void setPosition(int x, int y); void draw(sf::RenderWindow*); void addItem(int type, sf::String filename, vec2f vec); |
setDesign(DesignWindow* desWin) – меняет все winSprite основываясь на входящем дизайне. Об этом позже.
save(vec2i, int) – сохраняет информацию из обработчика окон в winSave
changeSize(Mouse*) – изменение размеров окна
changePosition(Mouse*) – изменение положения окна
setPosition(int x, int y) – установка координат окна и компонентов
addItem(int type, sf::String filename, vec2f vec) – добавление элемента в окно (кнопок, слотов, чекБоксов, картинок)
3. Design – дизайн
Этот класс служит для того чтобы создавать картинки для дизайнов окон, курсора, кнопок и т.д.
Вот такая картинка используется для создания окон в стиле аля Windows 8
4. Item – итем
Содержит в себе SFML image, texture, sprite и информацию (позиция и размер). Используется в структуре winItem.
В сумме результат работы всех этих классов выглядит вот так:
Подробный разбор классов будет во второй части.
Window v1.0
Название: Window – окно
Предназначение: служит вспомогательным классом для класса Windows, так-же может использоваться как самостоятельный класс.
Возможности:
1. отрисовка во входящем sf::RenderWindow окне
2. менять дизайн окна
3. перемещаться
4. проверяться на события
5.* менять свои размеры
Исходный код:
#include "stdafx.h" #include "Image.h" #include "DesignWindow.h" #include "Mouse.h" #pragma once class Window { protected: std::vector<DesignWindow*> vecDesign; // Вектор для 1 дизайна sf::Image imageWindow; // Результирующая картинка окна sf::Texture texture; sf::Sprite sprite; int width_current; int width_min; int width_max; int height_current; int height_min; int height_max; int height_x; //================= bool flag1; int mXc; int mYc; int wXc; int wYc; //================= bool isMove; // Можно перемещать окно? bool isConsiderBorder; // Учитывать границы? bool isChangeSize; // Можно изменять размеры? public: Window(int width, int height); ~Window(void); void setSize(int width, int height); // Установить дизайн окна bool setDesign(sf::String filename); void update(void);void data(); void move(int dx, int dy); void setPosition(int x, int y); int getPositionX(); int getPositionY(); bool check1(int* x, int* y); // Входит ли в окно bool check2(int* x, int* y); // Входит ли в верхнюю часть, за которую перетаскивают void behavior(Mouse* mouse); sf::Image getImage(); void draw(sf::RenderWindow *window); };
#include "Window.h" Window::Window(int width, int height) { data(); width_current = width; height_current = height; } Window::~Window(void) { // } bool Window::setDesign(sf::String filename) { DesignWindow* dw = new DesignWindow(filename); vecDesign.push_back(dw); update(); return true; } void Window::setSize(int width, int height) { width_current = width; height_current = height; update(); } void Window::update(void) { //imageWindow.create(width_current, height_current, sf::Color(0, 0 , 0, 255)); imageWindow.create(width_current, height_current, sf::Color(255, 255, 255, 255)); std::vector<int> w; // вектор ширин std::vector<int> h; // вектор высот for(int i=0; i<9; i++) { int width = vecDesign[0]->getImage(i).getSize().x; w.push_back(width); int height = vecDesign[0]->getImage(i).getSize().y; h.push_back(height); } height_x = h[4]; sf::Image img; // 1. рисуем полотно int h8 = height_current - h[4] - h[7]; int w8 = width_current - w[5] - w[6]; img = vecDesign[0]->getImage(8, w8, h8); imageWindow.copy(img, w[5], h[4]); // 3. вставляем уголки // 3.1 Лев Верх img = vecDesign[0]->getImage(0); int w0 = img.getSize().x; int h0 = img.getSize().y; imageWindow.copy(img, 0, 0); // 3.2 Прав Верх img = vecDesign[0]->getImage(1); imageWindow.copy(img, width_current - w0, 0); // 3.3 Лев Низ img = vecDesign[0]->getImage(2); int w2 = img.getSize().x; int h2 = img.getSize().y; imageWindow.copy(img, 0, height_current - h2); // 3.4 Прав Низ img = vecDesign[0]->getImage(3); imageWindow.copy(img, width_current - w2, height_current - h2); // 2. вставляем границы // 2.1. Верхняя img = vecDesign[0]->getImage(4, width_current -2*w0, 1); int h4 = img.getSize().y; imageWindow.copy(img, w0, 0); // 2.2. Левая img = vecDesign[0]->getImage(5, 1, height_current-h0-h2); int w5 = img.getSize().x; int h5 = img.getSize().y; imageWindow.copy(img, 0, h0); // 2.3. Правая img = vecDesign[0]->getImage(6, 1, height_current-h0-h2); imageWindow.copy(img, width_current-w5, h0); // 2.4. Нижняя img = vecDesign[0]->getImage(7, width_current-w[2]-w[3], 1); imageWindow.copy(img, w[2], height_current-h[7]); texture.loadFromImage(imageWindow); sprite.setTexture(texture); sprite.setTextureRect(sf::IntRect(0,0,width_current,height_current)); // фича 2.04.2016. 0:41 - убирает лишнее при изменении размеров окна (уберите, увидите) } sf::Image Window::getImage() { return imageWindow; } void Window::data(void) { vecDesign.reserve(1); width_min = 0; width_max = 0; height_min = 0; height_max = 0; height_x = 0; flag1 = false; mXc = 0; mYc = 0; wXc = 0; wYc = 0; isMove = true; isConsiderBorder = true; isChangeSize = false; sprite.setPosition(0, 0); } void Window::move(int dx, int dy) { sprite.move(dx, dy); } void Window::setPosition(int x, int y) { sprite.setPosition(x, y); } int Window::getPositionX() { return sprite.getPosition().x; } int Window::getPositionY() { return sprite.getPosition().y; } void Window::draw(sf::RenderWindow *window) { window->draw(sprite); } void Window::behavior(Mouse* mouse) { int x = (*mouse).getX(); int y = (*mouse).getY(); switch((*mouse).getEventButton(sf::Mouse::Left)) { case 0: break; case 1: if(check1(&x, &y)) { // Если клик мыши был в окне // запоминаем координаты мыши mXc = x; mYc = y; // запоминаем координаты окна wXc = sprite.getPosition().x; wYc = sprite.getPosition().y; if(check2(&x, &y)) { // Если клик мыши был по перетаскиваемой зоне flag1 = true; } } break; case 2: if(flag1 == true) { int dx = x - mXc; int dy = y - mYc; setPosition(wXc + dx, wYc + dy); } break; case 3: flag1 = false; // отпущено break; } } bool Window::check1(int* x, int* y) { if( (sprite.getPosition().x <= *x) && (*x <= sprite.getPosition().x + sprite.getTexture()->getSize().x) && (sprite.getPosition().y <= *y) && (*y <= sprite.getPosition().y + sprite.getTexture()->getSize().y) ) return true; return false; } bool Window::check2(int* x, int* y) { if( (sprite.getPosition().x +1 <= *x) && (*x <= sprite.getPosition().x + width_current -1) && (sprite.getPosition().y +1 <= *y) && (*y <= sprite.getPosition().y + height_x -1) ) return true; return false; }
DesignWindow
Исходный код
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//DesignWindow.h //v1.0 05.04.2016 //by DSL.legozaur #ifndef DSL_DESIGNWINDOW_H #define DSL_DESIGNWINDOW_H #include "Design.h" class DesignWindow : public Design { public: DesignWindow(void); DesignWindow(sf::String filename); void data(void); bool load(sf::String filename); ~DesignWindow(void); }; #endif DSL_DESIGNWINDOW_H |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
//DesignWindow.cpp //version 03.04.2016 17:10 //by DSL.legozaur #include "stdafx.h" #include "DesignWindow.h" DesignWindow::DesignWindow() { // } // Конструктор DesignWindow::DesignWindow(sf::String filename) { // } void DesignWindow::data(void) { for(int i=0; i<9; i++) { sf::Image image; vecImage.push_back(image); } } bool DesignWindow::load(sf::String filename) { if(loadImage(filename)) { data(); // Расположение картинок в векторе // 0 4 1 // 5 8 6 // 2 7 3 // Режем image и заполняем картинки vecImage[0-8] designToImage(&image, &vecImage[0], 0, 0, 32); if(!designToImage(&image, &vecImage[1], 2, 0, 32)) { designToImage(&image, &vecImage[1], 0, 0, 32); vecImage[1].flipHorizontally(); } designToImage(&image, &vecImage[2], 0, 2, 32); if(!designToImage(&image, &vecImage[3], 2, 2, 32)) { designToImage(&image, &vecImage[3], 0, 2, 32); vecImage[3].flipHorizontally(); } designToImage(&image, &vecImage[4], 1, 0, 32); designToImage(&image, &vecImage[5], 0, 1, 32); if(!designToImage(&image, &vecImage[6], 2, 1, 32)) { designToImage(&image, &vecImage[6], 0, 1, 32); vecImage[6].flipHorizontally(); } designToImage(&image, &vecImage[7], 1, 2, 32); designToImage(&image, &vecImage[8], 1, 1, 32); return true; } return false; } // Деструктор DesignWindow::~DesignWindow(void) { // } |
Design
Исходный код
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
//Desigh.h //v1.0 05.04.2016 //by DSL.legozaur #ifndef DSL_DESIGN_H #define DSL_DESIGN_H #include "stdafx.h" class Design { protected: sf::String filename; // Имя файла дизайна sf::Image image; // картинка целого дизайна std::vector<sf::Image> vecImage; // Обрезанные картинки // Набор функций, которые нужны для getImage(int numCell, int factorX, int factorY) //sf::Image getNewImage1(int numCell, int factorX, int factorY); //sf::Image getNewImage2(int numCell, int factorX, int factorY); //sf::Image getNewImageX(int numCell, int factor); //sf::Image getNewImageY(int numCell, int factor); public: Design(void); ~Design(void); bool loadImage(sf::String filename); // Основная функция преобразующая дизайн в набор картинок bool designToImage(sf::Image* image1, sf::Image* image2, int numImageW, int numImageH, int sideImage); // Возвращает картинку дизайна sf::Image getImage(); // Возвращает обрезанную картинку дизайна под номером sf::Image getImage(int numCell); // Возвразает обрезанную картинку дизайна под номером увеличенную по Х в factorX раз, по Y в factorY раз //sf::Image getImage(int numCell, int factorX, int factorY); //Возвращает имя дизайна sf::String getFilename(); }; #endif DSL_DESIGN_H |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
//Desigh.cpp //v1.0 05.04.2016 //by DSL.legozaur #include "Design.h" // Конструктор по умолчанию Design::Design(void) { vecImage.reserve(0); } bool Design::loadImage(sf::String filename) { vecImage.reserve(0); this->filename = filename; if(image.loadFromFile(filename)) return true; return false; } Design::~Design(void){} sf::Image Design::getImage() { return image; } sf::Image Design::getImage(int numCell) { int numberImage = vecImage.size(); if(numCell < numberImage) return vecImage[numCell]; } sf::String Design::getFilename() { return filename; } // designToImage - режет дизайн, на картинки // *image1 - ссылка на Целый дизайн // *image2 - ссылка на картинку, в которую будет вставлена часть дизайна // numCellWidth - положение картинки в дизайне по ширине [начиная с 0] // numCellHeight - по высоте [начиная с 0] // sideCell - размер ячейки (обычно 32) bool Design::designToImage(sf::Image *image1, sf::Image *image2, int numCellWidth, int numCellHeight, int sideCell) { // Если в ячейке будет картинка, то W и H её ширина и высота соответственно int W = -1; // ширина int H = -1; // высота int imin = numCellWidth * sideCell; int imax = imin + sideCell; int jmin = numCellHeight * sideCell; int jmax = jmin + sideCell; for(int j = jmin; j < jmax; j++) { for(int i = imin; i < imax; i++) { if(image1->getPixel(i, j) != sf::Color(255,255,255,0)) {// Если пиксель не пустой if( W < i-imin) W++; if( H < j-jmin) H++; } } } if(W != -1 && H != -1) { W++; H++; // Фича 31.03.2016 8:40 МСК // нужная поправка на 1 пиксель image2->create(W, H, sf::Color(255, 255, 255, 255)); image2->copy(*image1, 0, 0, sf::IntRect(imin,jmin, imin+W,jmin+H)); return true; } return false; } /* // Возвращает картинку под номером numCell увеличенную по ширине в factorX раз и по высоте в factorY раз sf::Image Design::getNewImage1(int numCell, int factorX, int factorY) { sf::Image img0 = getNewImageX(numCell, factorX); // Растягиваем картинку до нужной нам ширины (factorX) int h = img0.getSize().y; // высота полосы (необходимо для расчётов) sf::Image img; // Создаём картинку которую будем возвращать img.create(factorX, factorY, sf::Color(0,0,0,0)); // Задаём её размеры int a = int(float(factorY)/h); // а - это количество полос в высоту if(a*h <= factorY) // Если не всё пространство занято полосами a++; // добавляем 1 полосу, она всё равно обрежется for(int i=0; i<a; i++) // делаем "а" раз нижеуказанное img.copy(img0, 0, i*h, sf::IntRect(0,0,factorX,h)); // вставляем (каждая следующая ниже на величину h) return img; // возвращаем картинку } // Возвращает картинку под номером numCell увеличенную по ширине в factorX раз и по высоте в factorY раз sf::Image Design::getNewImage2(int numCell, int factorX, int factorY) { sf::Image img0 = getNewImageY(numCell, factorY); // Растягиваем картинку до нужной нам ширины (factorX) int w = img0.getSize().x; // ширина полосы (необходимо для расчётов) int h = img0.getSize().y; // высота полосы (необходимо для расчётов) sf::Image img; // Создаём картинку которую будем возвращать img.create(factorX, factorY, sf::Color(0,0,0,0)); // Задаём её размеры for(int i=0; i<factorX; i++) // делаем "а" раз нижеуказанное img.copy(img0, i*w, 0, sf::IntRect(0,0,w,h)); // вставляем (каждая следующая ниже на величину h) return img; // возвращаем картинку } // Возвращает картинку под номером numCell увеличенную по ширине в factor раз sf::Image Design::getNewImageX(int numCell, int factor) { int w = vecImage[numCell].getSize().x; // ширина исходной картинки int h = vecImage[numCell].getSize().y; // высота исходной картинки sf::Image img; // создаём картинку, которую будем возвращать img.create(w*factor, h, sf::Color(0,0,0,0)); // Задаём ей форму и цвет for(int i=0; i<factor; i++) // Делаем нижеуказанное factor раз img.copy(vecImage[numCell], i*w, 0, sf::IntRect(0,0,w,h)); // вставляем картинку на 1 пиксель правее return img; // возвращаем картинку } // Возвращает картинку под номером numCell увеличенную по высоте в factor раз sf::Image Design::getNewImageY(int numCell, int factor) { int w = vecImage[numCell].getSize().x; // ширина исходной картинки int h = vecImage[numCell].getSize().y; // высота исходной картинки sf::Image img; // создаём картинку, которую будем возвращать img.create(w, h*factor, sf::Color(0,0,0,0)); // Задаём ей форму и цвет for(int i=0; i<factor; i++) // Делаем нижеуказанное factor раз img.copy(vecImage[numCell], 0, i*h, sf::IntRect(0,0,w,h)); // вставляем картинку на 1 пиксель правее return img; // возвращаем картинку } */ /* // Возвращает картинку под номером numCell из vecImage в зависимости от factorX и factorY (factor - множитель) sf::Image Design::getImage(int numCell, int factorX, int factorY) { // Если размер изменять не нужно, вызываем getImage(...) // Иначе если нужно изменить картинку в обе стороны, вызываем getNewImage2(...) // Иначе если нужно изменить картинку по ширине, вызываем getNewImageX(...) // Иначе нужно изменить картинку по высоте, вызываем getNewImageY(...) if(factorX <= 1 && factorY <= 1) return getImage(numCell); else if(factorX > 1 && factorY > 1) return getNewImage2(numCell, factorX, factorY); else if(factorX > 1) return getNewImageX(numCell, factorX); else return getNewImageY(numCell, factorY); } */ |
DesignCursor
DesighCursor – Дизайн курсора
Исходный код:
//DeignCursor.h //v1.0 05.04.2016 //by DSL.legozaur #pragma once #include "Design.h" class DesignCursor : public Design { private: void data(void); public: DesignCursor(sf::String filename); ~DesignCursor(void); };
//DeignCursor.cpp //v1.0 05.04.2016 //by DSL.legozaur #include "DesignCursor.h" #include "stdafx.h" DesignCursor::DesignCursor(sf::String filename) { data(); this->filename = filename; if(image.loadFromFile("images/DesignCursor/" + filename)) { designToImage(&image, &vecImage[0], 0, 0, 32); // Курсор designToImage(&image, &vecImage[1], 1, 0, 32); // Перемещение designToImage(&image, &vecImage[2], 2, 0, 32); // Вертикальные designToImage(&image, &vecImage[3], 3, 0, 32); // Горизонтальные designToImage(&image, &vecImage[4], 4, 0, 32); // Лево-верх <-> Право-низ designToImage(&image, &vecImage[5], 5, 0, 32); // Лево-низ <-> Право-верх } } DesignCursor::~DesignCursor(void) { // } void DesignCursor::data(void) { vecImage.reserve(6); for(int i=0; i<6; i++) { sf::Image img; vecImage.push_back(img); } }
Design v2.0 (23.12.2016)
1. классы Design, DesignWindow, DesignCursor объединены в Design
2. добавлена структура DesignButton (для winButton из Window)
Исходный код
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
//Desigh.h //v1.0(05.04.2016) #ifndef DSL_DESIGN_H #define DSL_DESIGN_H #include "stdafx.h" class Design { protected: sf::String filename; // Имя файла дизайна sf::Image image; // картинка целого дизайна std::vector<sf::Image> vecImage; // Обрезанные картинки // Набор функций, которые нужны для getImage(int numCell, int factorX, int factorY) //sf::Image getNewImage1(int numCell, int factorX, int factorY); //sf::Image getNewImage2(int numCell, int factorX, int factorY); //sf::Image getNewImageX(int numCell, int factor); //sf::Image getNewImageY(int numCell, int factor); public: Design(void); ~Design(void); void reserve(int num); bool loadImage(sf::String filename); // Основная функция преобразующая дизайн в набор картинок bool designToImage(sf::Image* image1, sf::Image* image2, int numCellWidth, int numCellHeight, int sideImage); bool designToImage(sf::Image* image1, sf::Image* image2, int numCellWidth, int numCellHeight, int sizeX, int sizeY); // Возвращает картинку дизайна sf::Image getImage(); // Возвращает обрезанную картинку дизайна под номером sf::Image getImage(int numCell); // Возвразает обрезанную картинку дизайна под номером увеличенную по Х в factorX раз, по Y в factorY раз //sf::Image getImage(int numCell, int factorX, int factorY); sf::String getFilename(); int size(); }; struct DesignWindow : public Design { DesignWindow() { reserve(9); } DesignWindow(sf::String filename) { reserve(9); load(filename); } bool load(sf::String filename) { if(loadImage(filename)) { // Расположение картинок в векторе // 0 4 1 // 5 8 6 // 2 7 3 // Режем image и заполняем картинки vecImage[0-8] designToImage(&image, &vecImage[0], 0, 0, 32); if(!designToImage(&image, &vecImage[1], 2, 0, 32)) { designToImage(&image, &vecImage[1], 0, 0, 32); vecImage[1].flipHorizontally(); } designToImage(&image, &vecImage[2], 0, 2, 32); if(!designToImage(&image, &vecImage[3], 2, 2, 32)) { designToImage(&image, &vecImage[3], 0, 2, 32); vecImage[3].flipHorizontally(); } designToImage(&image, &vecImage[4], 1, 0, 32); designToImage(&image, &vecImage[5], 0, 1, 32); if(!designToImage(&image, &vecImage[6], 2, 1, 32)) { designToImage(&image, &vecImage[6], 0, 1, 32); vecImage[6].flipHorizontally(); } designToImage(&image, &vecImage[7], 1, 2, 32); designToImage(&image, &vecImage[8], 1, 1, 32); return true; } return false; } }; struct DesignCursor : public Design { DesignCursor() { reserve(6); } DesignCursor(sf::String filename) { reserve(6); load(filename); } bool load(sf::String filename) { if(loadImage(filename)) { designToImage(&image, &vecImage[0], 0, 0, 32); // Курсор designToImage(&image, &vecImage[1], 1, 0, 32); // Перемещение designToImage(&image, &vecImage[2], 2, 0, 32); // Вертикальные designToImage(&image, &vecImage[3], 3, 0, 32); // Горизонтальные designToImage(&image, &vecImage[4], 4, 0, 32); // Лево-верх <-> Право-низ designToImage(&image, &vecImage[5], 5, 0, 32); // Лево-низ <-> Право-верх return true; } return false; } }; struct DesignButton : public Design { DesignButton() { reserve(3); } DesignButton(sf::String filename, int num, bool flag) { reserve(num); load(filename, num, flag); } bool load(sf::String filename, int num, bool flag) { int sizeX, sizeY; if(loadImage(filename)) { sf::Vector2u size = image.getSize(); if(flag) { sizeX = size.x / num; sizeY = size.y; for(int i=0; i<num; i++) designToImage(&image, &vecImage[i], i, 0, sizeX, sizeY); } else { sizeX = size.x; sizeY = size.y / num; for(int i=0; i<num; i++) designToImage(&image, &vecImage[i], 0, i, sizeX, sizeY); } return true; } return false; } }; #endif DSL_DESIGN_H |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
//Desigh.cpp //v2.0(23.12.2016) #include "Design.h" // Конструктор по умолчанию Design::Design(void) { vecImage.reserve(0); } void Design::reserve(int num) { vecImage.reserve(num); for(int i=0; i<num; i++) { sf::Image img; vecImage.push_back(img); } } bool Design::loadImage(sf::String filename) { vecImage.reserve(0); this->filename = filename; if(image.loadFromFile(filename)) return true; return false; } Design::~Design(void){} sf::Image Design::getImage() { return image; } // Возвращает sf::Картинку под номером numCell. Если такого номера нет, вернёт первую. sf::Image Design::getImage(int numCell) { if(numCell < vecImage.size()) return vecImage[numCell]; else return vecImage[0]; } // //Возвращает имя дизайна // Используется в eventHandlerWindows.h >> struct designWindows >> int checkDesName(sf::String filename){...} sf::String Design::getFilename() { return filename; } int Design::size() { return vecImage.size(); } // designToImage - режет дизайн, на картинки // *image1 - ссылка на Целый дизайн // *image2 - ссылка на картинку, в которую будет вставлена часть дизайна // numCellWidth - положение картинки в дизайне по ширине [начиная с 0] // numCellHeight - по высоте [начиная с 0] // sideCell - размер ячейки (обычно 32) bool Design::designToImage(sf::Image *image1, sf::Image *image2, int numCellWidth, int numCellHeight, int sideCell) { // Если в ячейке будет картинка, то W и H её ширина и высота соответственно int W = -1; // ширина int H = -1; // высота int imin = numCellWidth * sideCell; int imax = imin + sideCell; int jmin = numCellHeight * sideCell; int jmax = jmin + sideCell; for(int j = jmin; j < jmax; j++) { for(int i = imin; i < imax; i++) { if(image1->getPixel(i, j) != sf::Color(255,255,255,0)) {// Если пиксель не пустой if( W < i-imin) W++; if( H < j-jmin) H++; } } } if(W != -1 && H != -1) { W++; H++; // Фича 31.03.2016 8:40 МСК // нужная поправка на 1 пиксель image2->create(W, H, sf::Color(255, 255, 255, 255)); image2->copy(*image1, 0, 0, sf::IntRect(imin,jmin, imin+W,jmin+H)); return true; } return false; } bool Design::designToImage(sf::Image* image1, sf::Image* image2, int numCellWidth, int numCellHeight, int sizeX, int sizeY) { // Если в ячейке будет картинка, то W и H её ширина и высота соответственно int W = -1; // ширина int H = -1; // высота int imin = numCellWidth * sizeX; int imax = imin + sizeX; int jmin = numCellHeight * sizeY; int jmax = jmin + sizeY; for(int j = jmin; j < jmax; j++) { for(int i = imin; i < imax; i++) { if(image1->getPixel(i, j) != sf::Color(255,255,255,0)) {// Если пиксель не пустой if( W < i-imin) W++; if( H < j-jmin) H++; } } } if(W != -1 && H != -1) { W++; H++; // Фича 31.03.2016 8:40 МСК // нужная поправка на 1 пиксель image2->create(W, H, sf::Color(255, 255, 255, 255)); image2->copy(*image1, 0, 0, sf::IntRect(imin,jmin, imin+W,jmin+H)); return true; } return false; } /* // Возвращает картинку под номером numCell увеличенную по ширине в factorX раз и по высоте в factorY раз sf::Image Design::getNewImage1(int numCell, int factorX, int factorY) { sf::Image img0 = getNewImageX(numCell, factorX); // Растягиваем картинку до нужной нам ширины (factorX) int h = img0.getSize().y; // высота полосы (необходимо для расчётов) sf::Image img; // Создаём картинку которую будем возвращать img.create(factorX, factorY, sf::Color(0,0,0,0)); // Задаём её размеры int a = int(float(factorY)/h); // а - это количество полос в высоту if(a*h <= factorY) // Если не всё пространство занято полосами a++; // добавляем 1 полосу, она всё равно обрежется for(int i=0; i<a; i++) // делаем "а" раз нижеуказанное img.copy(img0, 0, i*h, sf::IntRect(0,0,factorX,h)); // вставляем (каждая следующая ниже на величину h) return img; // возвращаем картинку } // Возвращает картинку под номером numCell увеличенную по ширине в factorX раз и по высоте в factorY раз sf::Image Design::getNewImage2(int numCell, int factorX, int factorY) { sf::Image img0 = getNewImageY(numCell, factorY); // Растягиваем картинку до нужной нам ширины (factorX) int w = img0.getSize().x; // ширина полосы (необходимо для расчётов) int h = img0.getSize().y; // высота полосы (необходимо для расчётов) sf::Image img; // Создаём картинку которую будем возвращать img.create(factorX, factorY, sf::Color(0,0,0,0)); // Задаём её размеры for(int i=0; i<factorX; i++) // делаем "а" раз нижеуказанное img.copy(img0, i*w, 0, sf::IntRect(0,0,w,h)); // вставляем (каждая следующая ниже на величину h) return img; // возвращаем картинку } // Возвращает картинку под номером numCell увеличенную по ширине в factor раз sf::Image Design::getNewImageX(int numCell, int factor) { int w = vecImage[numCell].getSize().x; // ширина исходной картинки int h = vecImage[numCell].getSize().y; // высота исходной картинки sf::Image img; // создаём картинку, которую будем возвращать img.create(w*factor, h, sf::Color(0,0,0,0)); // Задаём ей форму и цвет for(int i=0; i<factor; i++) // Делаем нижеуказанное factor раз img.copy(vecImage[numCell], i*w, 0, sf::IntRect(0,0,w,h)); // вставляем картинку на 1 пиксель правее return img; // возвращаем картинку } // Возвращает картинку под номером numCell увеличенную по высоте в factor раз sf::Image Design::getNewImageY(int numCell, int factor) { int w = vecImage[numCell].getSize().x; // ширина исходной картинки int h = vecImage[numCell].getSize().y; // высота исходной картинки sf::Image img; // создаём картинку, которую будем возвращать img.create(w, h*factor, sf::Color(0,0,0,0)); // Задаём ей форму и цвет for(int i=0; i<factor; i++) // Делаем нижеуказанное factor раз img.copy(vecImage[numCell], 0, i*h, sf::IntRect(0,0,w,h)); // вставляем картинку на 1 пиксель правее return img; // возвращаем картинку } */ /* // Возвращает картинку под номером numCell из vecImage в зависимости от factorX и factorY (factor - множитель) sf::Image Design::getImage(int numCell, int factorX, int factorY) { // Если размер изменять не нужно, вызываем getImage(...) // Иначе если нужно изменить картинку в обе стороны, вызываем getNewImage2(...) // Иначе если нужно изменить картинку по ширине, вызываем getNewImageX(...) // Иначе нужно изменить картинку по высоте, вызываем getNewImageY(...) if(factorX <= 1 && factorY <= 1) return getImage(numCell); else if(factorX > 1 && factorY > 1) return getNewImage2(numCell, factorX, factorY); else if(factorX > 1) return getNewImageX(numCell, factorX); else return getNewImageY(numCell, factorY); } */ |
Design v1.0 (05.04.2016)
sf::Text
Графический текст, который может быть обращен на цель визуализации.
#include <Text.hpp>
Публичные типы
enum –
Style {
Regular = 0, – регулярный
Bold = 1 << 0, – жирный
Italic = 1 << 1, – курсив
Underlined = 1 << 2, – подчёркнутый
StrikeThrough = 1 << 3 – зачёркнутый
}
Перечень стилей строки рисования
Функции связанные с sf::Text
Text () Конструктор по умолчанию. |
|
Text (const String &string, const Font &font, unsigned int characterSize=30) Конструктор текста из строки, шрифта и размера. |
|
void | setString (const String &string) Установить строку текста |
void | setFont (const Font &font) Установить шрифт текста |
void | setCharacterSize (unsigned int size) Установить размер символа |
void | setStyle (Uint32 style) Установить стиль текста |
void | setColor (const Color &color) Установить цвет текста |
const String & | getString () const Получить строку текста |
const Font * | getFont () const Получить шрифт текста |
unsigned int | getCharacterSize () const Получить размер символа |
Uint32 | getStyle () const Получить стиль текста |
const Color & | getColor () const Получить цвет текста |
Vector2f | findCharacterPos (std::size_t index) const Возвращает позицию индексного символа |
FloatRect | getLocalBounds () const Получить локальный ограничивающий прямоугольник объекта |
FloatRect | getGlobalBounds () const Получить глобальный ограничивающий прямоугольник объекта |
Функции связанные с sf::Transformable
void | setPosition (float x, float y) |
void | setPosition (const Vector2f &position) |
void | setRotation (float angle) |
void | setScale (float factorX, float factorY) |
void | setScale (const Vector2f &factors) |
void | setOrigin (float x, float y) |
void | setOrigin (const Vector2f &origin) |
const Vector2f & | getPosition () const |
float | getRotation () const |
const Vector2f & | getScale () const |
const Vector2f & | getOrigin () const |
void | move (float offsetX, float offsetY) |
void | move (const Vector2f &offset) |
void | rotate (float angle) |
void | scale (float factorX, float factorY) |
void | scale (const Vector2f &factor) |
const Transform & | getTransform () const |
const Transform & | getInverseTransform () const |
Что делают вышеуказанные функции и так понятно.
Подробное описание
Графический текст, который может быть обращено на цели визуализации.
sf::Text представляет собой рисуемый класс, который позволяет легко отображать текст с пользовательского стиля и цвета на цели визуализации.
Он наследует все функции от sf::Transformable: положение, вращение, масштабирование, происхождение. Он также добавляет текстовые специфические свойства, такие как шрифт, чтобы использовать, размер символов, стиль шрифта (полужирный, курсив, подчеркнутый, пронзаешь), глобальный цвет и текст для отображения конечно. Он также предоставляет удобные функции для расчета графический размер текста, или получить глобальную позицию данного символа.
sf::Text работает в сочетании с классом sf::Font, который загружает и обеспечивает глифы (визуальные символы) данного шрифта.
Разделение sf::Font и sf::Text обеспечивает большую гибкость и лучшую производительность: действительно sf::Font тяжелый ресурс, и любая операция на нем медленная (часто слишком медленная для приложений реального времени). С другой стороны, sf::Text представляет собой легкий объект, который может объединить данные глифы и метрики в sf::Font, чтобы отобразить любой текст на цели визуализации.
Важно отметить, что экземпляр sf::Text не копирует шрифт, который он использует, он только сохраняет ссылку на него. Таким образом, sf::Font не должен быть уничтожен, пока он используется в sf::Text (т.е. никогда нельзя писать функцию, которая использует локальный экземпляр sf::Font для создания текста).
Смотрите также записку о координатах и неискаженной рендеринга в sf::Transformable.
Пример использования:
1 2 3 4 5 6 7 8 9 10 |
// Объявляем и загружаем шрифт sf::Font font; font.loadFromFile("arial.ttf"); // Создаём текст sf::Text text("hello", font); text.setCharacterSize(30); text.setStyle(sf::Text::Bold); text.setColor(sf::Color::Red); // Рисуем это window.draw(text); |
Статическая линковка SFML в VS15
Начиная с версии SFML 2.2, при статической линковке нужно контролировать зависимости подключаемых библиотек. Для новичка это может показаться немного сложным, тем более, что для использования почти всех sfml функций, достаточно вставить в нужное поле VS следующий список:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
"sfml-graphics-s.lib" "freetype.lib" "jpeg.lib" "opengl32.lib" "sfml-window-s.lib" "gdi32.lib" "sfml-audio-s.lib" "flac.lib" "vorbisenc.lib" "vorbisfile.lib" "vorbis.lib" "ogg.lib" "openal32.lib" "sfml-system-s.lib" "winmm.lib" |
(кликабельно)
Не забываем про SFML_STATIC в опциях препроцессора:
В некоторых версиях VS, опции препроцессора могут располагаться в одном из подменю компоновщика.
В большинстве случаев достаточно понимать: сверху идут главные, зависимые от расположенных ниже библиотек. Таблицу зависимостей можно найти в официальном туториале. Обратите внимание на winmm.lib. От нее зависят многие библиотеки, она же не зависит ни от кого, посему находится в самом снизу, сразу после sfml-system-s.lib, которой она так же требуется. Для статической debug версии, к имени библиотеки модуля нужно добавить -s-d, например sfml-system-s-d.lib. В принципе это все, разве что напомню о \include и \lib путях, частенько при создании нового пресета о них забывают.
Немного о том, зачем это нужно. На выходе после сборки у вас будет один исполняемый файл, не требующий прилинкованых библиотек. В плане итогового размера программы, вы платите только за то, что используете. Для конечного релиза, статическая версия в большинстве случаев лучше. Так же для релиза желательно убрать консоль, игрока она лишь напугает (подумает вирус какой, закроет, уничтожив при этом sfml окно).
Из заметных минусов: несколько дольше компиляция, чуть сложнее настройка проекта. Хотя последнее спорно, учитывая что при динамике, для запуска приложения в папку с игрой нужно подкладывать либы. Непосредственно для разработки в этом особо нет смысла, разве что наблюдение за размерами папки проекта для душевного спокойствия.