lwjgl freezes on creation of Font object

265 views Asked by At

I am making a simple game of snake, because I can, and I stumbled across an interesting bug. I am trying to use Slick-Util to draw some text on the screen, but whenever I try to create a font object the game freezes. Here is my code. The highlighted section only prints 'a' once.

package tlf.snake.main;


import tlf.snake.main.game.helper.Pos;
import tlf.snake.main.game.input.Input;

import java.awt.Font;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWWindowPosCallback;
import org.lwjgl.glfw.GLFWWindowSizeCallback;
import org.lwjgl.glfw.GLFWvidmode;
import org.lwjgl.opengl.GLContext;

import org.newdawn.slick.TrueTypeFont;

import static org.lwjgl.glfw.Callbacks.glfwSetCallback;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.NULL;

/**
 * @author thislooksfun
 */
public class SnakeGame
{
    private static final Game game = new Game();

    private int WIDTH = game.gameWidth*15;
    private int HEIGHT = game.gameHeight*15;

    private static final int MINWIDTH = game.gameWidth*10;
    private static final int MINHEIGHT = game.gameHeight*10;

    private Pos lastPos;

    private int size = 10;
    private boolean resized = false;

    private boolean running = false;

    private long window;

    private static SnakeGame instance;

    public TrueTypeFont font;

    public SnakeGame()
    {
        instance = this;
    }

    private void init()
    {
        if (glfwInit() != GL_TRUE) {
            System.out.println("Error initializing");
            //TODO handle
            return;
        }

        glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

        window = glfwCreateWindow(WIDTH, HEIGHT, "NEAT Snake", NULL, NULL);

        if (window == NULL) {
            System.out.println("Error creating window");
            //TODO handle
            return;
        }

        ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
        glfwSetWindowPos(window, (GLFWvidmode.width(vidmode) - WIDTH) / 2, (GLFWvidmode.height(vidmode) - HEIGHT) / 2);
        initCallbacks();
        glfwMakeContextCurrent(window);
        glfwShowWindow(window);

        GLContext.createFromCurrent();

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glDepthFunc(GL_NEVER);
        glDisable(GL_DEPTH_TEST);

        setOrtho();
        glDisable(GL_TEXTURE_2D);

        initFonts();

        running = true;
        resized = true;

        game.start();
    }

    private void initCallbacks()
    {
        glfwSetCallback(window, GLFWWindowSizeCallback(new GLFWWindowSizeCallback.SAM()
        {
            @Override
            public void invoke(long window, int width, int height)
            {
                resized = true;
                WIDTH = width;
                HEIGHT = height;

                if (width < MINWIDTH && height >= MINHEIGHT) {
                    glfwSetWindowSize(window, MINWIDTH, height);
                    glfwSetWindowPos(window, lastPos.x-10, lastPos.y);
                } else if (width >= MINWIDTH && height < MINHEIGHT) {
                    glfwSetWindowSize(window, width, MINHEIGHT);
                    glfwSetWindowPos(window, lastPos.x-10, lastPos.y);
                } else if (width < MINWIDTH && height < MINHEIGHT) {
                    glfwSetWindowSize(window, MINWIDTH, MINHEIGHT);
                    glfwSetWindowPos(window, lastPos.x-10, lastPos.y);
                } else
                    lastPos = getWindowPos();

                render();
                setOrtho();
            }
        }));

        glfwSetCallback(window, GLFWWindowPosCallback(new GLFWWindowPosCallback.SAM()
        {
            @Override
            public void invoke(long window, int xpos, int ypos)
            {
                lastPos = new Pos(xpos, ypos);
            }
        }));

        glfwSetKeyCallback(window, new Input());
    }

    private Pos getWindowPos()
    {
        IntBuffer xbuf = BufferUtils.createIntBuffer(4);
        IntBuffer ybuf = BufferUtils.createIntBuffer(4);
        glfwGetWindowPos(window, xbuf, ybuf);

        return new Pos(xbuf.get(0), ybuf.get(0));
    }

    private void setOrtho()
    {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, WIDTH, HEIGHT, 0, 1, -1);
        glMatrixMode(GL_MODELVIEW);
    }

    private void initFonts()
    {
        System.out.println("a");
        Font awtFont = new Font("Default", Font.BOLD, 24);
        System.out.println("a");
        font = new TrueTypeFont(awtFont, true);
        System.out.println("a");
    }

    public void start()
    {
        init();
        while (running)
        {
            update();
            render();
            if (glfwWindowShouldClose(window) == GL_TRUE) {
                running = false;
            }
        }
    }

    private void update()
    {
        glfwPollEvents();
        game.tick();
    }

    private void render()
    {
        if (resized) {
            setOrtho();
            calcTileSize();
            resized = false;
        }

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        game.render();

        glfwSwapBuffers(window);
    }

    public static SnakeGame instance()
    {
        return instance;
    }

    private void calcTileSize()
    {
        int sh, sw;
        sh = (int)Math.floor((1.0f*HEIGHT)/game.gameHeight);
        sw = (int)Math.floor((1.0f*WIDTH)/game.gameWidth);

        size = sh > sw ? sw : sh;
    }

    public int tileSize()
    {
        return size;
    }

    public void stop()
    {
        running = false;
    }
}

Any ideas?
Thanks,
-tlf

2

There are 2 answers

3
Alex S. Diaz On

Have you tried with another font like "Arial" or "Serif"? I guess "Default" is not a valid name for a font in windows.

Try something like this:

Font awtFont = new Font("Times New Roman", Font.BOLD, 24);
font = new TrueTypeFont(awtFont, false);

Or, if you have the .ttf file try something like this:

try {
    InputStream inputStream = ResourceLoader.getResourceAsStream("anotherfont.ttf");
    Font awtFont = Font.createFont(Font.TRUETYPE_FONT, inputStream);
    awtFont = awtFont2.deriveFont(24f);
    font = new TrueTypeFont(awtFont2, false);      
} catch (Exception e) {
    e.printStackTrace();
}   
5
thislooksfun On

I figured it out. For some reason, if you try to call new Font(...) after calling glfwCreateWindow, it hangs indefinitely. Creating the Font object before creating the window works just fine though.

Credit goes to @JackWhiteIII for suggesting that.

EDIT: I found out why! (and how to fix it)