LibGDX调整窗口大小 - 缩放字体

3

我正在编写一个简单的“Hello World”程序,它会在屏幕上显示当前的名字日。我希望确保文本在调整窗口大小后仍然能够清晰可读。

在我的创建方法中,我尝试使用这段代码(根据这篇文章:https://github.com/libgdx/libgdx/wiki/Viewports

public void create () {

        //if(_isLandscape)
        //    Gdx.graphics.setDisplayMode(1920, 1080, false);

        if(_isLandscape)
            Gdx.graphics.setDisplayMode(960, 540, false);

        camera = new PerspectiveCamera();
        //viewport = new FillViewport(960, 540, camera); - I have also tried to use this
        viewport = new ScreenViewport(camera);
....

在resize(int, int)方法中,我有这段代码:
public void resize(int width , int height){
        try {
           viewport.update(width, height);
            System.out.println(width + " " + height);
            if (height > width) {
                _isLandscape = false;
                System.out.println("Portrait");
            } else {
                _isLandscape = true;
                System.out.println("Landscape");
            }
        }catch(Exception ex){
        }
    }

但是,调整大小后仍然会出现拉伸或无法读取的文本。 拉伸的文本 缩小的文本 请注意,我希望文本按比例缩放,如果窗口很小,文本仍然相同,但某些部分将“在”边框后面。 如果窗口很大(例如全屏),文本将位于相同位置而不是拉伸。
这是我现在拥有的全部代码:
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.loaders.FileHandleResolver;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.viewport.*;

import com.badlogic.gdx.graphics.OrthographicCamera;

import java.io.File;
import java.util.List;

//import com.badlogic.gdx.tools.imagepacker.TexturePacker2;
//import com.badlogic.gdx.tools.texturepacker.TexturePacker;

/**
 * Created by Martin on 30.9.2014.
 */
public class NameDayExampleApp extends HostedGame{
    private Viewport viewport;
    private Camera camera;
    private OrthographicCamera _ortocamera;

    private SpriteBatch _spriteBatch;
    private Texture background;
    private Texture backgroundLandscape;
    private boolean _isLandscape;

    private String name = "";

    private TextureAtlas textureAtlas;

    private static final String TAG = "NameDayExampleApp";
    private static final int VERSION = 1;
    private static final int FONT_SIZE = 30;
    private static final float CLEAR_COLOR = 0.1f;

    private static final int MAX_FONT_SIZE = 40;
    private static final int MIN_FONT_SIZE = 8;

    private IServiceProvider _serviceProvider;
    private ILog _log;
    private BitmapFont _font;
    String _language;

    private int currentFontSize;

    private int currentHeight;
    private int currentWidth;

    boolean isDebugged = true;

    @Override
    public void initialize(IServiceProvider serviceProvider, List<SocialFeedDefinition> feeds, boolean isLandscape, String language)
    {
        _serviceProvider = serviceProvider;
        _log = serviceProvider.getLog().getSubLog(TAG);


        _isLandscape = isLandscape;
        _language = language;

        _serviceProvider.getAppStatusListener().onStateChanged(AppState.Ready);

    }

    @Override
    public void create () {

        _serviceProvider.getLog().log(LogLevel.Info, "[NameDay]: Start creating screen");


        if(_isLandscape)
            Gdx.graphics.setDisplayMode(Gdx.graphics.getHeight(), Gdx.graphics.getWidth(), false);//Gdx.graphics.setDisplayMode(960, 540, false);

        currentHeight = Gdx.graphics.getHeight();
        currentWidth  = Gdx.graphics.getWidth();


       // _ortocamera = new OrthographicCamera(currentWidth, currentHeight);
        //viewport = new ExtendViewport(currentWidth, currentHeight, _ortocamera);
        viewport = new StretchViewport(currentWidth, currentHeight);
        currentFontSize = FONT_SIZE;

        try
        {
            _spriteBatch = new SpriteBatch();


            background = new Texture(_serviceProvider.getAssetHandleResolver().resolve("nameday-portrait.jpg").file().getName());
            backgroundLandscape = new Texture(_serviceProvider.getAssetHandleResolver().resolve("nameday-landscape.jpg").file().getName());

            //FreeTypeFontGenerator generator = new FreeTypeFontGenerator(new FileHandle("fonts/DroidSans_Bold.ttf"));
            // _serviceProvider.getFontGenerator().generateExistenceFont(20,  FontType.NORMAL);

            _font = _serviceProvider.getFontGenerator().generateDefaultFont(currentFontSize,  FontType.NORMAL); //generator.generateFont(40);
            _font.setColor(0,0,0,1);
            //generator.dispose();
        }
        catch(GdxRuntimeException e)
        {
            _log.error("Exception on create: " + e);
            _serviceProvider.getAppStatusListener().onStateChanged(AppState.Error);
        }
    }

    @Override
    public void render () {

        try
        {

            Gdx.gl.glClearColor(1, 0, 0, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

            //background draw
            if(isDebugged) {
                _log.log(LogLevel.Info, "currentWidth: " + currentWidth + " currentHeight: " + currentHeight);
                _log.log(LogLevel.Info, "Window width: " + Gdx.graphics.getWidth() + " Window height: " + Gdx.graphics.getHeight());
                _log.log(LogLevel.Info, "Background width: " + background.getWidth() + " Background height: " + background.getHeight());
                isDebugged = false;
            }


            if(!_isLandscape) {
                _spriteBatch.begin();
                //_spriteBatch.draw(background, 0, 0, currentWidth, currentHeight);
                _spriteBatch.draw(background,0,0);
                _spriteBatch.end();
            }else{
                _spriteBatch.begin();
                //_spriteBatch.draw(backgroundLandscape, 0, 0, currentWidth, currentHeight);
                _spriteBatch.draw(backgroundLandscape, 0, 0);
                _spriteBatch.end();
            }


            //content draw
            _spriteBatch.begin();

            NameDaySAX nameDaySAX = new NameDaySAX();

            //Choose XML according to language
            FileHandle _fileHandle = null;
            File _file = null;
            _fileHandle = _serviceProvider.getAssetHandleResolver().resolve("namesday_" + _language + ".xml");
            _file = _fileHandle.file();
            if(_file.exists()){
              name = nameDaySAX.getCurrentName(_file);
            }else {
                _fileHandle = _serviceProvider.getAssetHandleResolver().resolve("namesday.xml");
                _file = _fileHandle.file();
                name = nameDaySAX.getCurrentName(_file);
            }

            if(!_isLandscape) {
                BitmapFont.TextBounds bounds = _font.getBounds(_serviceProvider.getLocalizer().get("Today celebrates"));//_font.getBounds("Happy Name Day");
                _font.draw(_spriteBatch, _serviceProvider.getLocalizer().get("Today celebrates"), (Gdx.graphics.getWidth()-bounds.width) / 6.0f, Gdx.graphics.getHeight() - 35);
                bounds = _font.getBounds(_serviceProvider.getLocalizer().get("nameday") + " " + name);
                _font.draw(_spriteBatch, _serviceProvider.getLocalizer().get("nameday") + " " + name, (Gdx.graphics.getWidth()-bounds.width) / 5.0f, Gdx.graphics.getHeight() - 70);
            }else{
                BitmapFont.TextBounds bounds = _font.getBounds(_serviceProvider.getLocalizer().get("Happy Name Day"));
                _font.draw(_spriteBatch, _serviceProvider.getLocalizer().get("Today celebrates"), (Gdx.graphics.getWidth()-bounds.width) / 14.0f, Gdx.graphics.getHeight() / 1.7f);
                bounds = _font.getBounds(_serviceProvider.getLocalizer().get("nameday") + " " + name);
                _font.draw(_spriteBatch, _serviceProvider.getLocalizer().get("nameday") + " " + name, (Gdx.graphics.getWidth()-bounds.width) / 11.0f, Gdx.graphics.getHeight() / 2.0f);
            }
        }
        catch(RuntimeException e)
        {
            _log.error("Exception on render: " + e);
            _serviceProvider.getAppStatusListener().onStateChanged(AppState.Error);
        }
        finally {
            _spriteBatch.end();
        }
    }

    @Override
    public void resize(int width , int height){
        try {

            viewport.update(width, height);
            //_ortocamera.update();
            isDebugged = true;
            //Set Landscape flag
            if (height > width) {
                _isLandscape = false;
                _log.log(LogLevel.Info, "Portrait");
            } else {
                _isLandscape = true;
                _log.log(LogLevel.Info, "Landscape");
            }

            float scale = 1.0f, scale1, scale2;
            scale1 = (width * 1.0f) / (currentWidth * 1.0f);
            scale2 = (height * 1.0f) / (currentHeight * 1.0f);

            if(currentWidth<width || currentHeight<height){
                if(scale1>scale2){
                    scale = scale1;
                }else{
                    scale = scale2;
                }
            }

            if(currentWidth>width || currentHeight>height){
                if(scale1<scale2){
                    scale = scale1;
                }else{
                    scale = scale2;
                }
            }

            if(scale<0.9)
                scale=0.9f;
            if(scale>1.2){
                scale=1.2f;
            }

            //Font Scaling
            /*if(!_isLandscape) {
                scale = (width * 1.0f) / (currentWidth * 1.0f);
            }else {
                scale = (height * 1.0f) / (currentHeight * 1.0f);
            }*/

            currentWidth = width;
            currentHeight = height;

            _log.log(LogLevel.Info, "New width: " + width + " New height: " + height);
            _log.log(LogLevel.Info, "Scale: " + scale);

            float fontsize = currentFontSize;
            float fcurrentFontSize;
            _font.dispose();
            fcurrentFontSize = fontsize * scale;

            if(fcurrentFontSize > MAX_FONT_SIZE)
                fcurrentFontSize = MAX_FONT_SIZE;
            if(fcurrentFontSize < MIN_FONT_SIZE)
                fcurrentFontSize = MIN_FONT_SIZE;

            currentFontSize = (int)fcurrentFontSize;
            _font = _serviceProvider.getFontGenerator().generateDefaultFont(currentFontSize,  FontType.NORMAL);
            _font.setColor(0,0,0,1);

            _log.info("Fontsize: " + currentFontSize);
            _log.info(width + "x" + height);
            //End of font scaling


        }catch(Exception e){
            _log.error("Exception on resize: " + e);
            _serviceProvider.getAppStatusListener().onStateChanged(AppState.Error);
        }
    }

    public int getVersion()
    {
        return VERSION;
    }

    @Override
    public void dispose()
    {
        super.dispose();
        _font.dispose();
        background.dispose();
        backgroundLandscape.dispose();
    }
}

你应该使用正交相机(OrthographicCamera)而不是透视相机(PerspectiveCamera)来渲染文本。如果你需要背景是3D的,你可以使用两个独立的相机,并且只在正交相机上渲染文本。 - Tenfour04
请问您是否有设置正交相机的示例代码? - Martin Fedy Fedorko
使用Viewport类来处理正交相机(OrthographicCamera)。阅读此处的文档以决定哪种类型的Viewport适用于您的目的。https://github.com/libgdx/libgdx/wiki/Viewports - Tenfour04
我还有点迷茫,因为我尝试了所有的视口,在屏幕大小调整后,字体仍然变形了。 - Martin Fedy Fedorko
我的代码:@Override public void create() {_serviceProvider.getLog().log(LogLevel.Info, "[NameDay]: 开始创建屏幕"); if (_isLandscape) Gdx.graphics.setDisplayMode(960, 540, false); OrthographicCamera(viewport.getScreenWidth(), viewport.getScreenHeight()); _ortocamera = new OrthographicCamera(960, 540); viewport = new FitViewport(960, 540, _ortocamera);} - Martin Fedy Fedorko
显示剩余6条评论
1个回答

1
你应该尝试使用Libgdx的FreeType扩展来绘制文本...
如果你想在游戏中绘制文本,通常会使用BitmapFont。然而,它有一个缺点:BitmapFonts依赖于图像,因此如果你想要不同大小的字体,就必须对它们进行缩放,这可能看起来很丑陋。
你可以只保存一个你的游戏需要的最大尺寸的BitmapFont,然后你永远不需要再进行放大,只需缩小,是吗?嗯,这是真的,但这样的BitmapFont很容易占用比相应的TrueType字体(.ttf)多两倍的硬盘空间。现在想象一下,如果你必须在你的游戏中装载所有大型的BitmapFonts,而你的游戏使用了十种不同的字体...在一个Android设备上。
你问题的解决方案是gdx-freetype扩展:
- 只用轻量级的.ttf文件来装载你的游戏 - 在运行时生成你所需大小的BitmapFont - 用户可以将自己的字体放入你的游戏中
引用自: https://github.com/libgdx/libgdx/wiki/Gdx-freetype

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接