SFML + Dev-Cpp

В данном разделе раскрываются нюансы использования SFML в IDE Dev-Cpp

Буду благодарен, если поделитесь:

Урок 3.1. EventHandlerWindows – Обработчик событий окон

Почти в каждой современной игре есть окна и кнопки для элементарного взаимодействия с игроком.
Вот пример одной MMORPG c оконной системой
test1
Скажем так, SFML не предоставляет такого функционала, поэтому его придётся делать вручную. В нескольких уроках мы рассмотрим как создавать такую систему практически с 0. Мы будем имитировать работу оконной системы Windows.

1. EventHandlerWindows
2. Window
3. Design
4. Item

В этом уроке рассмотрим всё поверхностно, а в следующем углубимся.


1. EventHandlerWindows – обработчик событий окон.


Это класс, который содержит в себе ссылки на окна и некоторые данные для обработки, а так-же ориентируясь на мышь управляет окнами.

Основные функции нужные в обработчике:

Из комментариев и так понятно для чего нужны эти функции.

Стоит выделить самые важные из них:
1. add(Window* win) – добавляет окно в обработчик окон
2. behavior(int numEvent) – управляет окнами опираясь на входящие события мыши (numEvent)
3. draw() – отображение окон

В цикле обработки игры это будет выглядеть вот так:


2. Window – окно


Класс Window представляет собой набор параметров (например координаты и размеры окна) и объекты (спрайты, кнопки, картинки и т.д.), а так-же набор функций для добавления этих объектов, их обработки и отображения.

Наше окно может перемещаться, закрываться и даже изменять размеры! В файле Window.h описаны доп. структуры которые и образуют окно.

Немного поподробнее:
winSprite – это спрайт, из которого создаётся сама рамка окна
winItem – это базовый класс для последующих элементов, которые будут расположены на нашем окне (winButton, winSlot, winCheckBox, winMcText)
winMcText – тот же mcText только привязанный к окну.
winSave – набор параметров, которые нужны для изменения размеров окна.

Основные функции нужные в окне:

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 – дизайн


Этот класс служит для того чтобы создавать картинки для дизайнов окон, курсора, кнопок и т.д.
Windows8.1Вот такая картинка используется для создания окон в стиле аля Windows 8
image0


4. Item – итем


 

Содержит в себе SFML image, texture, sprite и информацию (позиция и размер). Используется в структуре winItem.

В сумме результат работы всех этих классов выглядит вот так:
image_07012017_1

Подробный разбор классов будет во второй части.

Буду благодарен, если поделитесь:

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

Исходный код

 

Буду благодарен, если поделитесь:

Design

Исходный код

 

Буду благодарен, если поделитесь:

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)

Исходный код

Буду благодарен, если поделитесь:

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.

Пример использования:

 

Буду благодарен, если поделитесь:

Статическая линковка SFML в VS15

Начиная с версии SFML 2.2, при статической линковке нужно контролировать зависимости подключаемых библиотек. Для новичка это может показаться немного сложным, тем более, что для использования почти всех sfml функций, достаточно вставить в нужное поле VS следующий список:

(кликабельно)

Не забываем про SFML_STATIC в опциях препроцессора:
Screenshot_2В некоторых версиях VS, опции препроцессора могут располагаться в одном из подменю компоновщика.

В большинстве случаев достаточно понимать: сверху идут главные, зависимые от расположенных ниже библиотек. Таблицу зависимостей можно найти в официальном туториале. Обратите внимание на winmm.lib. От нее зависят многие библиотеки, она же не зависит ни от кого, посему находится в самом снизу, сразу после sfml-system-s.lib, которой она так же требуется. Для статической debug версии, к имени библиотеки модуля нужно добавить -s-d, например sfml-system-s-d.lib. В принципе это все, разве что напомню о \include и \lib путях, частенько при создании нового пресета о них забывают.

Немного о том, зачем это нужно. На выходе после сборки у вас будет один исполняемый файл, не требующий прилинкованых библиотек. В плане итогового размера программы, вы платите только за то, что используете. Для конечного релиза, статическая версия в большинстве случаев лучше. Так же для релиза желательно убрать консоль, игрока она лишь напугает (подумает вирус какой, закроет, уничтожив при этом sfml окно).

Из заметных минусов: несколько дольше компиляция, чуть сложнее настройка проекта. Хотя последнее спорно, учитывая что при динамике, для запуска приложения в папку с игрой нужно подкладывать либы. Непосредственно для разработки в этом особо нет смысла, разве что наблюдение за размерами папки проекта для душевного спокойствия.

Буду благодарен, если поделитесь: