LibGDX BitmapFont не перестанет дрожать
У меня есть BitmapFont, который отображает счет игрока, когда он перемещается по экрану с постоянной скоростью. Поскольку игрок всегда движется, я должен пересчитать, в какой позиции я рисую шрифт в каждом кадре. Я использую этот код.
scoreFont.setScale(4f, 4f);
scoreFont.draw(batch, "" + scoreToShow, playerGhost.pos.x + 100f, 600f);
playerGhost.render(batch);
Эта проблема? Шрифт не перестанет дрожать. Это всего лишь несколько пикселей вибрации, но это немного заметно. Это более заметно, когда я запускаю его на своем планшете.
Это известная ошибка?
- Как я могу заставить его перестать трястись?
3 ответа
Вызов scorefont.setUseIntegerPositions(false);
поэтому он не будет округлять позицию шрифта до ближайшего целого числа. Возможно, вы также захотите установить минимальную фильтрацию шрифта на Linear или MipmapLinearNearest, а максимальную фильтрацию на Linear.
Причиной поведения по умолчанию является то, что конфигурация по умолчанию предназначена для текста с идеальным разрешением в пикселях, для области просмотра, установленной с единицами измерения, равными размеру пикселя. Если ваш видовой экран имеет размеры, точно совпадающие с размерами экрана в пикселях, эта конфигурация поможет сохранить слегка размытый текст.
Это может быть факт, что вы масштабируете свой шрифт.
У меня была эта проблема, и это довольно сложно понять (и также исправить).
В основном, когда вы масштабируете шрифты, BitmapFont изменяет значения внутри BitmapFontData путем деления / умножения. Если вы выполняете большое масштабирование с большим количеством различных значений (или неудачной комбинацией значений), это может привести к ошибкам округления, которые могут вызвать мерцание по краям шрифта.
Решение, которое я реализовал в конце, заключалось в написании Fontholder, в котором хранятся все исходные значения BitmapFontData. Затем я сбрасываю данные шрифта к этим исходным значениям в начале каждого кадра (то есть в начале метода render()).
Вот код...
package com.bigcustard.blurp.core;
import com.badlogic.gdx.graphics.g2d.*;
public class FontHolder {
private BitmapFont font;
private final float lineHeight;
private final float spaceWidth;
private final float xHeight;
private final float capHeight;
private final float ascent;
private final float descent;
private final float down;
private final float scaleX;
private final float scaleY;
public FontHolder(BitmapFont font) {
this.font = font;
BitmapFont.BitmapFontData data = font.getData();
this.lineHeight = data.lineHeight;
this.spaceWidth = data.spaceWidth;
this.xHeight = data.xHeight;
this.capHeight = data.capHeight;
this.ascent = data.ascent;
this.descent = data.descent;
this.down = data.down;
this.scaleX = data.scaleX;
this.scaleY = data.scaleY;
}
// Call this at start of each frame.
public void reset() {
BitmapFont.BitmapFontData data = font.getData();
data.lineHeight = this.lineHeight;
data.spaceWidth = this.spaceWidth;
data.xHeight = this.xHeight;
data.capHeight = this.capHeight;
data.ascent = this.ascent;
data.descent = this.descent;
data.down = this.down;
data.scaleX = this.scaleX;
data.scaleY = this.scaleY;
}
public BitmapFont getFont() {
return font;
}
}
Я не в восторге от этого, так как он немного хакерский, но это неизбежное зло, и он полностью и правильно решит проблему.
Правильный способ справиться с этим - использовать две разные камеры и две разные spriteBatches, одну для самой игры и одну для пользовательского интерфейса. Вы называете update()
метод на обеих камерах, и использовать spriteBatch.setProjectionMatrix(camera.combined);
на каждой партии, чтобы сделать их одновременно каждый кадр.