2013-08-16 4 views
5

Я ищу способ отображения текста постепенно с помощью libgdx, но я не могу найти способ сделать это именно так, как я хочу. Вот что я сделал:Показать текст с помощью libgdx

  • У меня есть текстовая метка, которая периодически обновляется, чтобы отобразить другой текст. Метка устанавливается на setWrap(true); и setAlignment(Align.center);
  • Каждый раз, когда я изменить текст метки я использую пользовательское действие, которое я построил как этот

    public class DisplayTextAction extends TemporalAction{ 
        private CharSequence completeText; 
    
        @Override 
        protected void update(float percent) { 
         ((Label)actor).setText(
          completeText.subSequence(
           0, 
           (int)Math.round(completeText.length()*percent)); 
        } 
    
        public void setText(String newText){ 
         completeText = newText; 
        } 
    } 
    
  • Каждый текст обновления, я называю действие из пула, измените текст и добавьте действие к метке.

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

Это происходит, когда текст не по центру (точки представляют собой пространство):

|h........| 
|hel......| 
|hello....| 

(Работы по назначению)

Это то, что происходит, когда текст центрируется:

|....h....| 
|...hel...| 
|..hello..| 

И вот как я хочу себя вести:

|..h......| 
|..hel....| 
|..hello..| 

Моя первоначальная идея исправить это состояла в том, чтобы использовать 2 набора строк, один из которых является видимым текстом, и один невидимый, который действует как «заполнение». Я придумал что-то вроде этого:

CharSequence visibleText = completeText.subSequence(
    0, 
    (int)Math.round(completeText.length()*percent)); 
CharSequence invisibleText = completeText.subSequence(
    (int)Math.round(completeText.length()*percent), 
    completeText.length()); 

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

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

EDIT:

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

себе этот текст:

|all those lines are| 
|..for a very long..| 
|........text.......| 

И он должен отображаться как этот

|all th.............| 
|...................| 
|...................| 

|all those line.....| 
|...................| 
|...................| 

|all those lines are| 
|..for a ve.........| 
|...................| 

|all those lines are| 
|..for a very long..| 
|........text.......| 

раствора Jyro117 дают либо

|all those lines are| 
|for a very long....| 
|text...............| 

отображается правильно.

или

|...................| 
|......all tho......| 
|...................| 

|...................| 
|...all those lin...| 
|...................| 

|all those lines are| 
|......for a v......| 
|...................| 

ответ

4

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

Вам придется явно адаптировать код к вашему, но это дает вам ссылку на код, что я имею в виду.

Вот фрагмент кода на один из способов сделать это:

stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false); 
Gdx.input.setInputProcessor(stage); 

uiSkin = new Skin(Gdx.files.internal("skin/uiskin.json")); 

Table fullScreenTable = new Table(); 
fullScreenTable.setFillParent(true); 

final String message = "hello"; 
final Label progressLabel = new Label(message, this.uiSkin); 
final TextBounds bounds = progressLabel.getTextBounds(); // Get libgdx to calc the bounds 
final float width = bounds.width; 
final float height = bounds.height; 
progressLabel.setText(""); // clear the text since we want to fill it later 
progressLabel.setAlignment(Align.CENTER | Align.TOP); // Center the text 

Table progressTable = new Table(); 
progressTable.add(progressLabel).expand().size(width, height).pad(10); 

final float duration = 3.0f; 

final TextButton button = new TextButton("Go!", this.uiSkin); 
button.addListener(new ClickListener() { 
    @Override public void clicked(InputEvent event, float x, float y) { 
     progressLabel.addAction(new TemporalAction(duration){ 
      LabelFormatter formatter = new LabelFormatter(message);     
      @Override protected void update(float percent) { 
       progressLabel.setText(formatter.getText(percent)); 
      } 
     }); 
    } 
}); 
stage.addActor(button); 

fullScreenTable.add(progressTable); 
fullScreenTable.row(); 
fullScreenTable.add(button); 

stage.addActor(fullScreenTable); 

Edit:

код Добавлен к центру и сверху Выравнивание текста в метке. Также добавлен код для заполнения пробелов на конце, чтобы обеспечить правильное выравнивание. Примечание. Полезно только для шрифтов с одним интервалом.

class LabelFormatter { 
    private final int textLength; 
    private final String[] data; 
    private final StringBuilder textBuilder; 

    LabelFormatter(String text) { 
     this.textBuilder = new StringBuilder(); 
     this.data = text.split("\n"); 
     int temp = 0; 
     for (int i = 0 ; i < data.length; i++) { 
      temp += data[i].length(); 
     } 
     textLength = temp; 
    } 

    String getText(float percent) { 
     textBuilder.delete(0, textBuilder.length()); 
     int current = Math.round(percent * textLength); 

     for (final String row : data) { 
      current -= row.length(); 
      if (current >= 0) { 
       textBuilder.append(row); 
       if (current != 0) { 
        textBuilder.append('\n'); 
       } 
      } else { 
       textBuilder.append(row.substring(0, row.length() + current)); 

       // Back fill spaces for partial line 
       for (int i = 0; i < -current; i++) { 
        textBuilder.append(' '); 
       } 
      } 

      if (current <= 0) { 
       break; 
      } 
     } 

     return textBuilder.toString(); 
    } 
} 
+0

Спасибо за ваше решение, это работает лучше, но по-прежнему не ведет себя точно так, как я этого хочу. Я отредактирую свой пост с дополнительной информацией о том, что он делает и чего он не делает. – vaati

+0

Я добавил код, соответствующий вашим требованиям. Это потребует от вас использовать шрифт с одним интервалом, чтобы пробелы соответствовали ширине символов. Решение для других типов шрифтов требует больших модификаций самого класса BitmapFont и того, как определяются местоположения глифов, так как вам нужно знать об окончательной компоновке текста. – Jyro117

+0

Я вижу. Думаю, у меня нет выбора, кроме скрипки с битмапфоном. Я отправлю сообщение снова, когда найду решение. – vaati

Смежные вопросы