Урок 12 SFML Работа с текстом

В этом уроке немного поработаем с текстом sfml. Текст встречается во многих играх, поэтому к нему мы еще будем возвращаться и в следующих уроках

Видеоверсия: http://www.youtube.com/watch?v=56rmko7OMtI

рассмотрим простой пример:

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

Добавьте побольше камней на карте, заменив символы ‘ ‘, на ‘s’

Добавим новую переменную playerScore в классе игрока:

Инициализируем её в конструкторе класса Игрока: ( туда же запихнул направление и скорость, поскольку был на форуме такой случай )

 

В функции взаимодействия с картой убираем телепортацию и пишем так:

 

Затем:

В папку с проектом там же где и файл main.cpp (можете создать рядом папку и кидать потом туда подобные файлы) закинем файл шрифта CyrilicOld.ttf
Этот шрифт похож на старые славянские письмена, я специально когда-то такой искал :-) можете поискать и другие шрифты под свой вкус и учтите , что не все из них поддерживают русский язык.
Ссылка на мой шрифт: https://yadi.sk/d/_rD7mjInf4pSr

 

В ф-ции int main() мы пишем:

 

Теперь нам нужно вывести текст в какую то позицию. Можно вывести его в позицию на карте, или же привязать к окну, чтобы текст бегал вместе с камерой и оставался на экране. Сделаем второй вариант:

Перед draw(p.sprite) напишем:

И теперь если запустим, увидим по центру надпись, а лев поверх неё. Поэтому – если текст будет по центру и вы хотите сделать его поверх льва – вы должны рисовать после draw(p.sprite).

Разница есть:

sfml текст
sfml текст

Это может показаться не важным, но если у вас сложное меню или интерфейс программы – вы сразу вспомните эту простую вещь.

Чтобы передвинуть текст, например, левее и выше, следует написать:

Теперь давайте выведем количество собранных камней. Если мы напишем по привычке:

То это не прокатит , поскольку это значение будет обозначать индекс символа, с которого надо забивать строку.  Вместо “Собрано” будет написано “брано”, например. Поэтому нам необходимо немного извратиться:

подключаем в main.cpp:

и тогда наша фиговина внизу примет такой вид:

нам на помощь пришла вспомогательная библиотека c++, которая позволяет работать со строками в потоке. Эта штука дает возможность сделать преобразование типов, см строку:

и мы можем заносить число из этой строки в переменную числовую (integer , например). вот пример (взято отсюда):

как видим для обратной операции >> требуется stringstream. в нашем случае это не нужно и мы добавляем ‘o’ , что означает output . Видна похожесть с “cin и cout”. Конечно, ведь все они друзья iostream’а, потоковые братья ввода-вывода.

Теперь если мы запустим программу – камни можно будет собирать и это выводится на экран.

Этот метод вам нужен только если вы работаете с числовыми операциями (в нашем случае мы увеличивали переменную)

Когда проект ваш будет серьезен – для читаемости кода подобные вещи лучше выпиливать вне ф-ции main и в отдельные классы/файлы

В заключении хотелось бы сказать, что текст можно двигать, как и спрайт. у него так же есть метод ‘move’. помимо этого у него есть setPosition, вращение и многое другое. Этим инструментом можно пользоваться.

Как видим у нас есть один глюк, который при ходьбе, например вверх – съедает камень раньше, чем лев до него доходит. Почему? Потому что существует пустота на нашем тайле, которая воспринимается игрой как персонаж, поскольку входит в его ширину и высоту.  Смотрите на картинке

hero

, например последняя строка – видно, что вверху пустое пространство. (один тайл 96*96). Есть два выхода – грамотно и ровненько обрезать в редакторе эту пустую область и переделать немного код, обновив координаты вывода тайла. Или же в самом коде, в зависимости от направления движения персонажа, попробовать уменьшать w и h вывода тайла соответственно в зависимости от стороны движения.




На примере кнопки up покажу:

textureempty

 

Смотрим координату одного пикселя до головы по игреку: 306 , соответственно нам надо написать:

Кто сделает остальные кнопки – скиньте код в комментарий, я поправлю у себя:) Этот глюк стал заметен только после взаимодействия с картой, хотя и изначально был очевиден. Мы видим, что до этого персонаж не до конца упирался головой в стенку при ходьбе вверх, или брал камень не до конца доходя до него. А еще хуже – если бы в нас стреляли враги – они могли бы нас убить рядом пролетевшей пулей :) И я нашел еще один глюк, он тоже легко исправим, тему создал на форуме . И вобще – пользуйтесь форумом:) Когда там будет много записей, человеку, имеющему такую же проблему, как у вас когда-то, – будет проще её решить, посмотрев вашу тему.

Следующий урок будет коротким – мы выведем время игры на экран. В очень многих играх это используется – игрок проиграл и игра вывела ->”рекорд времени”, “время игры” или что-то вроде этого.

Листинг main.cpp

 

Буду благодарен, если поделитесь:
SFML вопросы, прошу, задавайте на форуме.
  1. Сделал простой таймер. кому то пригодится.

    <code class="

    Вложение: Таймер

    1. тут мой косяк) никак не доделаю для комментариев)я отредактирую за тебя. ‘< pr e>код< / pre>‘ только без пробелов, но лучше на форум выложи ещё, в раздел “готовые решения”. там не затеряется. спасибо!
      там есть кнопка code

  2. Есть вопрос интересный. Вот представим что есть большой текст, его нужно вывести в ограниченом по .х блоке. Как автоматически сделать перенос на новую строку когда текст достигнет границы блока? или нужно в ручную редактировать текст и вставлять “\n”  везде где нужен перенос?

    1. может нужно снимать ширину этого блока и взять за ноль его левый край. просчитать при этом сколько приходится букв на ширину например 100, размера шрифта 10. и получится что первый символ занимает 10 пикселей(например), тогда 10 символов 100 пикселей. положим , что ширина блока 100. вот и получается, что можно после определенного номера символа (9ого) ставить перенос строки. или может покопать методы и там найдется пересечение. может можно узнать длину текста(не символов, а именно текста). посмотри методы text. что они дают.
      сильно не искав нашел это на оф сайте:
      sf::Vector2f Position = Text.GetCharacterPos(4);
      позволяет получить позицию символа в строке. а позиция это и есть координата. а координату спрайта свитка (блока) ты тоже знаешь . координата правого края свитка это Х+его ширина. или Х+его ширина/2 (это если использовал setOrigin и смещал начало координат в центр спрайта). вобщем вот от сюда тоже можно плясать.

      1. метод GetCharacterPos описан в Documentation of SFML 1.6 и в версии 2.2 не распознается. даже заголовочный файл не принимает #include .
        Хочу сделать игру типа кто хочет стать миллионером и вся загвоздка в выводе текста строго в блоке. Ведь вариантов вопросов будет много и каждый вручную редактировать как-то не професионально :)

  3. Координаты доделал, а так же заменил if на else if

     

  4. Я не разобрался с координатами спрайтов. Поэтому взять координаты предыдущего комментатора: tkir

    если персонаж идет вниз, то левая стенка “трется” по персонажу, а если идти наверх то от персонажа остается место.

    Вложение: проб1

  5. внесу свои пять копеек. если ты вдруг под linux и у тебя выводятся злоедучии квадраты вместо кириллицы. то тебе может помочь следующий кусок кода

    как-то так

    1. Это справедливо и для Windows. У меня например именно так – если не поставить букву L перед литералом, то выводится абракадабра либо квадраты вместо кириллицы.

  6. Вот код для преобразования любого типа в string

  7. У кого проблемы при использовании sf::Text::getColor () решение:

  8. Я конечно ничего против потока не имею против, но в силу своего недостатоного понимания его(потока) просто немного изменил 1 строку и все норм)

     

  9. Добрый день.

    При запуске игры спрайт персонажа находиться в одном положении, но при нажатии клавиш движения спрайт сначала перемещается в другую позицию и уже оттуда начинает свое движение.

    Скорее всего проблема в функции void update или в задании координат setPosition(x, y)

    Подскажите пожалуйста как это можно исправить?

Добавить комментарий