- PVSM.RU - https://www.pvsm.ru -
От переводчика: данная статья является восьмой в цикле переводов официального руководства по библиотеке SFML. Прошлую статью можно найти тут. [1] Данный цикл статей ставит своей целью предоставить людям, не знающим язык оригинала, возможность ознакомится с этой библиотекой. SFML — это простая и кроссплатформенная мультимедиа библиотека. SFML обеспечивает простой интерфейс для разработки игр и прочих мультимедийных приложений. Оригинальную статью можно найти тут [2]. Начнем.
1. Приступая к работе
2. Модуль System
3. Модуль Window
4. Модуль Graphics
5. Модуль Audio
6. Модуль Network
В SFML есть классы ресурсов (изображений, шрифтов, звуков и т.д.). Во многих программах эти ресурсы будут загружаться из файлов с помощью функции loadFromFile
. В некоторых ситуациях ресурсы будут непосредственно упакованы в исполняемый файл или в большой файл данных и будут загружаться из памяти с помощью функции loadFromMemory
. Эти функции могут удовлетворить практически любые потребности, но не все.
Вы можете захотеть загрузить файлы из необычного места, такого как сжатый/зашифрованный архив, или, например, из удаленной сетевой папки. Для этих особых ситуаций, SFML предоставляет третью функцию: loadFromStream
. Эта функция считывает данные, используя абстрактный интерфейс sf::InputStream [9], который позволяет вам иметь собственную реализацию класса потока, который будет работать с SFML.
В этой статье будет рассказано, как писать и использовать ваши собственные классы потоков.
Как и многие другие языки, C++ уже содержит класс потока данных: std::istream
. По факту, таких классов два: std::istream
является только front-end решением, абстрактным интерфейсом к данным, получаемым из std::streambuf
.
К сожалению, эти классы не дружелюбны к пользователю — решение нетривиальной задачи с использованием данных классов может стать очень сложным. Библиотека Boost.Iostreams [10] стремится обеспечить простой интерфейс для стандартных потоков, но Boost — это большая зависимость.
По этой причине SFML предоставляет собственный потоковый класс, который, как мы надеемся, более простой и быстрый, нежели перечисленные выше.
Класс sf::InputStream [9] декларирует четыре виртуальные функции:
class InputStream
{
public :
virtual ~InputStream() {}
virtual Int64 read(void* data, Int64 size) = 0;
virtual Int64 seek(Int64 position) = 0;
virtual Int64 tell() = 0;
virtual Int64 getSize() = 0;
};
read должна извлекать size байт из потока и копировать их по предоставленному адресу. Возвращает число прочитанных байтов или -1 при возникновении ошибки.
seek должна изменять текущую позицию в потоке. Аргумент является абсолютным числом байтов для перемещения (отсчет идет от начала области данных, а не от текущей позиции). Возвращает новую позицию или -1 при возникновении ошибки.
tell должна возвращать текущую позицию (число байт от начала области данных) в потоке или -1 в случае возникновения ошибки.
getSize должна возвращать размер (в байтах) блока данных, содержащегося в потоке, или -1 в случае возникновения ошибки.
Чтобы создать ваш собственный работающий поток, вы должны включить в ваш класс потока реализацию каждой из этих четырех функций, которая будет соответствовать описанным выше требованиям.
В SFML 2.3 были добавлены два новых класса, предоставляющих потоки для управления новым модулем аудио. sf::FileInputStream
предоставляет поток для чтения файла, sf::MemoryInputStream
служит для чтения потока данных из памяти. Оба класса разработаны на основе sf::InputStream [9] и могут использоваться полиморфно.
Использовать пользовательский потоковый класс просто: инстанцируйте его и передайте его в качестве аргумента функции loadFromStream
(или openFromStream
) объекта, который вы хотите инициализировать потоком.
sf::FileStream stream;
stream.open("image.png");
sf::Texture texture;
texture.loadFromStream(stream);
Если вам нужна демонстрация работающего кода, и вы не хотите заблудиться в деталях реализации, вы можете взглянуть на классы sf::FileInputStream
и sf::MemoryInputStream
.
Не забудьте проверить форум и вики. Есть шанс, что другой пользователь уже написал класс, который соответствует вашим потребностям. Если вы написали новый класс и считаете, что он может быть полезен другим пользователям, не стесняйтесь поделиться им!
Некоторые классы ресурсов не загружаются полностью после вызова loadFromStream
. Вместо этого, они продолжают читать данные из источника данных так долго, как это требуется. По этой причине класс sf::Music [11] читает аудио примитивы через поток на протяжении их проигрывания, а класс sf::Font [12] загружает глифы, когда в этом возникает необходимость.
Как следствие, поток, используемый вами для загрузки музыки или шрифта, также, как и источник данных, должны существовать так долго, как долго эти ресурсы используются. Разрушение источника информации или класса потока данных приводит к неопределенному поведению (программа может завершить свое выполнение, повредить данные, а может ничего не произойти).
Другим распространенным заблуждением является возврат функцией неверного значения, т.е. значения, возврат которого не ожидается SFML в данной ситуации. Например, для sf::FileInputStream
можно было бы написать функцию поиска следующим образом:
sf::Int64 FileInputStream::seek(sf::Int64 position)
{
return std::fseek(m_file, position, SEEK_SET);
}
Однако этот код не верен, потому что std::fseek
возвращает нуль при успехе, в то время как SFML ожидает возврата новой позиции в потоке.
Автор: HighMem
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/115551
Ссылки в тексте:
[1] тут.: https://habrahabr.ru/post/279653/
[2] тут: http://www.sfml-dev.org/tutorials/2.3/system-stream.php
[3] SFML и Visual Studio: https://habrahabr.ru/post/278977/
[4] SFML и Code::Blocks (MinGW): https://habrahabr.ru/post/279069/
[5] SFML и Linux: https://habrahabr.ru/post/279107/
[6] SFML и Xcode (Mac OS X): https://habrahabr.ru/post/279147/
[7] Компиляция SFML с помощью CMake: https://habrahabr.ru/post/279279/
[8] Обработка времени: https://habrahabr.ru/post/279347/
[9] sf::InputStream: http://www.sfml-dev.org/documentation/2.3/classsf_1_1InputStream.php
[10] Boost.Iostreams: http://www.boost.org/doc/libs/1_49_0/libs/iostreams/doc/index.html
[11] sf::Music: http://www.sfml-dev.org/documentation/2.3/classsf_1_1Music.php
[12] sf::Font: http://www.sfml-dev.org/documentation/2.3/classsf_1_1Font.php
[13] Источник: https://habrahabr.ru/post/279689/
Нажмите здесь для печати.