The issue I am having is very simple-I am using Java AWT (and Swing) to make a game, but the initial Graphics.drawString(String str, int x, int y)
call takes way too long. I am not setting a custom font or anything. I am not setting any rendering hints. I am using Mac Sierra 10.12.4 in a MacBook Air-I didn't get to test my program in Windows yet. If that matters at all.
In case you don't want to spend time reading the minimal example, I have a class called GamePanel that extends JPanel (and implements runnable) that I add to a JFrame in the main method. I initialize the game thread in the constructor and start the game loop in the run()
method. The game loop then repeats itself using Swing Timers. In the game loop, I call paintComponent(Graphics g)
through redraw()
-the text is drawn in the paintComponent
method. This isn't really necessary information since the problem is reproducible without a game loop, just with the game thread and the paintComponent
method, but I put this here just incase.
Any help is appreciated.
Game class (JFrame)
public class Game {
public static JFrame frame;
public static JPanel gamePanel;
public static void main(String[] args) {
frame = new JFrame("");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLayout(new BorderLayout());
gamePanel = new GamePanel();
frame.add(gamePanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
GamePanel class (Panel)
public class GamePanel() extends JPanel implements Runnable {
public static Thread thread;
public GamePanel() {
super();
setPreferredSize(new Dimension(640, 480));
setFocusable(true);
requestFocus();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void run() {
while (! Game.frame.isVisible()) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
EventQueue.invokeLater(new Runnable() {
public void run() {gameLoop();}
});
}
public void GameLoop() {
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
gameLoop();
}
public void paintComponent(Graphics g) {
super.paintComponent();
g.drawText("Hello World", 10, 10);
}
}
I know the game loop in the minimal example's speed would be ever-changing (and thats exactly the opposite of what a good game loop should do). But what does that matter in a minimal example?
I had the same problem. My solution is to save the fonts I use in a resource folder and then load the font. In Eclips you create a folder most easily through "New / Source Folder". The name of the folder does not matter if you follow my example. My font that I have saved in the resource folder is called "DroidSans-Bold.ttf"
Font font = null;
try {
font = Font.createFont(Font.TRUETYPE_FONT, new File(getClass().getResource("/DroidSans-Bold.ttf").getFile()));
font = font.deriveFont(32f); // Set size to 32
} catch (FontFormatException | IOException e) {
e.printStackTrace();
}
JFrame jf = new JFrame();
jf.setSize(800, 600);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
Graphics2D g = (Graphics2D)jf.getGraphics();
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setFont(font);
g.drawString("Hello", 100, 100);