SFML и C++ Уроки \ Разработка игр › Форумы › SFML Graphics › Трансформация изображения (а так же его адаптивность под разные разрешения)
В этой теме 23 ответа, 7 участников, последнее обновление Mihail 6 года/лет, 4 мес. назад.
-
АвторСообщения
-
Вообщем решил попрактиковаться на создании уровня из UMK3. Планирую сделать так, что при запуске приложения, пользователь укажет разрешение экрана, а при загрузке уровня, background займет часть экрана, в зависимости от разрешения. В интернете пытался найти что-то вроде: как сделать трансформацию объекта sfml; как увеличить картинку sfml; и др. Ничего не нашел. Захожу на cyberforum.ru, и всегда находится Simillar, который крутейший эксперт, и все его ответы: попробуйте посмотреть, и вообще левые ссылки скидывает на вопросы с форума, в которых сам же и отвечает другими ссылками. Короче решил я закрыть в браузере круговорот ссылок, и написать сюда. Вообщем, хотя бы скиньте ссылку на описание и примеры применений всех операций связанных с image, texture, sprite (русифицированных). Направьте на верный путь. В заранее спасибо
Вот держи, должно помочь.
GetScr1() = 1% наименьшей стороны экрана, в основном это Y.
C++123456789101112131415161718192021222324252627#pragma once#include"SFML/Graphics.hpp"#include<Windows.h>#define PI 3.14159265ftypedef sf::Vector2f vec2f;class Resolution{protected:int m_scrx;int m_scry;int m_scrMain;float m_scr1;bool m_wideScr;public:virtual int GetScrWidth();virtual int GetScrHeight();virtual int GetScrMain();virtual float GetScr1();virtual bool GetWideScr();virtual sf::FloatRect GetVisibleCamera(sf::View cam);virtual vec2f GetScrSize();Resolution(void);};C++1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556#include "Resolution.h"int Resolution::GetScrWidth(){return m_scrx;}sf::FloatRect Resolution::GetVisibleCamera(sf::View cam){return sf::FloatRect(cam.getCenter().x - GetScrWidth()/2.f,cam.getCenter().y - GetScrHeight()/2.f,(float)GetScrWidth(),(float)GetScrHeight());}int Resolution::GetScrHeight(){return m_scry;}int Resolution::GetScrMain(){return m_scrMain;}float Resolution::GetScr1(){return m_scr1;}bool Resolution::GetWideScr(){return m_wideScr;}vec2f Resolution::GetScrSize(){return vec2f((float)m_scrx, (float)m_scry);}Resolution::Resolution(void){m_scrx = GetSystemMetrics(0), m_scry = GetSystemMetrics(1);if(m_scrx == 1280 || m_scrx == 1360 || m_scrx == 1366 || m_scrx == 1920){if(m_scry == 720 || m_scry == 768 || m_scry == 800 || m_scry == 1080) m_wideScr = true;else m_wideScr = false;}if(m_scrx > m_scry) m_scrMain = m_scry;else m_scrMain = m_scrx;m_scr1 = (float)m_scrMain / 100.f;}Smykov, здравствуйте.
Для масштабирования объектов, унаследованных от sf::Transformable (коими и являются sf::Sprite и sf::Text) используется метод setScale(const sfVector2f& scale). По факту, setScale растягивает изображение до размеров <размер спрайта по умолчанию> * scale. Например, если указать scale = sf::Vector2f(0.5F, 0.5F), то изображение уменьшится вдвое по обеим координатным осям.
Впрочем, едва ли Вы найдете этот метод подгонки графики пригодным. Он порождает большое количество дефектов, например зубчатость контуров и сильная пикселизация (что естественно).
Для написания игр под разные разрешения экранов используются другие приемы.
Ну так поделитесь этими приёмами, откройте нам сие тайну)
Heisenberg, если Вам интересно, создайте соответствующую тему на форуме Может быть и поделюсь. Одна тема – один вопрос.
Так эта тема и есть вопрос по этой теме.
Хорошо, благодарю вас за ваши ответы
Heisenberg, а я вот смотрю на название темы и вижу, что это не так
Вообще, эта тема достойна отдельной статьи. Вы не находите? Но чтобы не разводить срач, так и быть, изложу свои соображения:
Как сделать игру “разрешение-независимой”?
Вариант I(A). Как уже было сказано, масштабировать спрайты. Выбираем некоторое опорное разрешение (например, 1600х900) и рисуем текстурки под него. А далее уже меняем их размеры setScale‘ом.
C++1234const Vector2f defaultResolution = Vector2f(1600.0F, 900.0F); // Разрешение по умолчанию (под которое рисовались текстуры)RenderWindow window(VideoMode::getDesktopMode(), "SFML Test", Style::Fullscreen); // Окно в полный экранsprite.setScale(static_cast<float>(window.getSize().x) / defaultResolution.x,static_cast<float>(window.getSize().y) / defaultResolution.y); // Так считаем размер спрайтовСпособ, конечно, допустим, но далеко не идеален. На экране 800х600, например, изображение будет сплюснутым, а на 1920х1080 – пикселизированным.
Вариант I(B). То же самое, но с некоторой модернизацией: масштабировать изображение только когда разрешение монитора значительно отличается от дефолтного. Например, ширина экрана игрока в 2 раза меньше ширины разрешения по умолчанию, значит уменьшаем текстуры в два раза (и по оси ‘x’, и по оси ‘y’). А если разница невелика (например, монитор 1920х1080), то пренебречь масштабированием. Очевидно, что такой способ неточен, но зато даст недеформированную картинку. Тоже не рекомендовал бы им пользоваться (хотя, не возьмусь утверждать наверняка, кажется в Starbound используется именно этот метод).
Вариант II. Радикальный вариант: чтобы не масштабировать спрайты можно просто менять View под размер окна. Тогда на экране будет меняться количество тайлов, “попадающих” в экран. Этот метод из Террарии. Минусы: на больших экранах будет слишком много деталей, и они будут слишком мелкие; фон на большинстве мониторов будет не полностью умещаться на экран (а еще он должен быть достаточно большого размера).
Вариант III. Рисовать текстуры для нескольких разрешений:) Тут ничего комментировать не буду – и так все ясно.
Вариант IV. Комбинирование нескольких вариантов. Например, I(B) и III. Это обеспечит реальные размеры текстур близкие к требуемым и масштабирование не слишком исказит картинку, и в то же время рисовать придется меньше.
А вообще, смотрите сами, по ситуации. Идеального рецепта, как всегда, нет
P.S. Heisenberg, как Вы думаете, я разумно изложил?
Smykov, “палец вверх – лучшее спасибо” 😉
А вообще, рисуйте пиксел-арт, как Pixel Dungeon, например! Там вообще все эти артефакты незаметны 😀
Да это прям надо в FAQ на sfml-wiki копировать :))
Я не совсем понял как тут объяснили, поэтому спрошу.
Разрешение окна и формат в полноэкранном режиме устанавливается пользователем из имеющихся вариантов(800×600, 1024×768 и т.д.).
Как сделать чтобы изображение растягивалось до столкновения с одним из краев окна(и на весь экран)? (Что-то в духе функции “Fit” в настроках программы “CDisplay”.)
Как сделать так чтобы он растянулся до столкновения с другим объектом?
И последний нубский вопрос: как отцентрировать изображение?
P.S. В некоторых программах при увеличении разрешения даже кнопка выхода уходила за край монитора. Как этого избежать? (C++ 2013 на всякий случай)
Смотри второй пост этой темы. Используй процентное соотношение от разрешение экрана.
А вторую часть кода куда вставлять?
Добавлять новые элементы .cpp или .h и в них вставлять или что-то другое?
Просто он не может найти “Resolution.h”(или открыть) если помещать всё в один элемент. Или его нужно отдельно создать?Первая часть это объявление класса, вторая часть это его реализация.
Подробнее см. многофайловую разработку. -
АвторСообщения
Для ответа в этой теме необходимо авторизоваться.