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

时间:2014-10-13 07:43:12

标签: java opengl-es fonts libgdx draw

我正在撰写简单的" Hello World"风格的程序,它在屏幕上写下当前的名字日。 我想确保,在调整窗口大小后,该文本也是可读的和正确的。

在我的create方法中,我尝试使用此代码(根据本文: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){
        }
    }

但是调整大小后结果仍然是拉伸或不可读的文本。 Streched texts

Minimized texts

请,我希望实现,文本将按比例缩放,如果窗口很小,文本仍然相同,但某些部分将在"背后"边界。如果窗口很大(例如全屏),则文本将位于未拉伸的相同位置。

以下是我现在的完整代码:

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();
    }
}

1 个答案:

答案 0 :(得分:1)

你应该尝试使用Libgdx的FreeType扩展...

  

如果您想在游戏中绘制文字,通常使用BitmapFont。但是,有一个缺点:    BitmapFonts依赖于图片,因此如果您想要不同尺寸,则必须缩放它们,这可能看起来很丑陋。

     

你可以保存你游戏中所需的最大尺寸的BitmapFont然后你就不必放大,只是向下,对吧?嗯,这是真的,但是这样的BitmapFont可以很容易地占用硬盘驱动器上两倍的空间作为相应的TrueType字体(.ttf)。现在想象一下,您必须将所有大型BitmapFonts与您的游戏一起发布,并且您的游戏在Android设备上使用十种不同的字体。

     

问题的解决方案是gdx-freetype扩展名:

     
      
  • 在您的游戏中只发送轻量级.ttf文件
  •   
  • 动态生成所需大小的BitmapFont
  •   
  • 用户可能会将自己的字体添加到游戏中
  •   

引用:https://github.com/libgdx/libgdx/wiki/Gdx-freetype