I'm trying to call a draw function using repaint inside a while loop. I'm not very familiar with how exactly repaint works.
The research I've done on repaint says it waits for the actions to be completed before it calls the draw method which may be the issue as I'm in a while loop.
However I've also read that the way I'm attempting to call repaint should work as well so I'm confused at this moment in time. throwing some system outs into my code it doesn't appear to kick off any of my draw functions.
What would cause this? My code is listed below.
gamewindow.java
package Game;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;
import Game.Login;
//our window class that will set up the framework of the game
public class GameWindow {
public static boolean stillLoading = true;
public static GridBagConstraints gBC = new GridBagConstraints();
public static JFrame frame = new JFrame();
private static boolean useFullScreen = false;
public GameWindow() {
//Set game Title
frame.setTitle("Gaian Empires");
frame.setLayout(new GridBagLayout());
//set size of the frame
if(useFullScreen) { // full screen
// Disable decorations for the frame.
frame.setUndecorated(true);
//put frame to full screen.
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
} else { // windowed mode
// set size of the frame
frame.setSize(1024,768);
// put frame to center of screen
frame.setLocationRelativeTo(null);
// make it so frame can not be resized
frame.setResizable(false);
}
//Exit the application when user closes frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create instance of the framework so that it extends the canvas
// class and puts it to frame
Login.CreateLogin();
frame.setVisible(true);
frame.add(new Framework());
stillLoading = false;
}
public static void main(String[] args) {
// Use the event dispatch to build UI for safety.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new GameWindow();
}
});
}
}
game.java
package Game;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;
import Game.Login;
public class Game {
public static boolean login = true;
public static boolean loginDone = false;
public Game()
{
Framework.gameState = Framework.GameState.GAME_CONTENT_LOADING;
Thread threadForInitGame = new Thread() {
@Override
public void run(){
// Sets variables and objects for the game.
Initialize();
// Load game files (images, sounds, ...)
LoadContent();
Framework.gameState = Framework.GameState.PLAYING;
}
};
threadForInitGame.start();
}
/**
* Set variables and objects for the game.
*/
private void Initialize()
{
}
/**
* Load game files - images, sounds, ...
*/
private void LoadContent()
{
}
/**
* Restart game - reset some variables.
*/
public void RestartGame()
{
}
/**
* Update game logic.
*
* @param gameTime gameTime of the game.
* if the game is using the mouse for something. @param mousePosition current mouse position.
*/
public void UpdateGame(long gameTime)
{
if (GameWindow.stillLoading) {
return;
}
//System.out.println("UPDATE!");
if (login == true) {
Login.showLogin();
login = false;
}
}
/**
* Draw the game to the screen.
*
* @param g2d Graphics2D
* @param mousePosition current mouse position.
*/
public void Draw(Graphics2D g2d, Point mousePosition)
{
System.out.println("drawing!");
}
}
canvas.java
package Game;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import javax.swing.*;
public abstract class Canvas extends JPanel implements KeyListener, MouseListener {
// Keyboard states - Here are stored states for keyboard keys - is it down or not.
private static boolean[] keyboardState = new boolean[525];
// Mouse States - here are the stored mouse states for mouse key being down or not
private static boolean[] mouseState = new boolean[3];
private static boolean noMouse = false; // removes mouse pointer from game.
public Canvas() {
// use double buffer to draw the screen
this.setDoubleBuffered(true);
this.setFocusable(true);
//this.setBackground(Color.black);
// If you will draw your own mouse cursor or if you just want that mouse cursor disappear,
// insert "true" into if condition and mouse cursor will be removed.
if (noMouse) {
BufferedImage blankCursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(blankCursorImg, new Point(0, 0), null);
this.setCursor(blankCursor);
}
// adds keyboard listener to receive events from jpanel
this.addKeyListener(this);
// adds mouse listener to receive events from jpanel
this.addMouseListener(this);
}
// This method is Override in Framework.java and is used for drawing to the screen
public abstract void Draw(Graphics2D g2d);
// i think this needs @Override but the system won't allow it.
public void paintComponenet(Graphics g) {
System.out.println("painting");
Graphics2D g2d = (Graphics2D)g;
super.paintComponent(g2d);
Draw(g2d);
}
// Keyboard
/**
* Is keyboard key "key" down?
*
* @param key Number of key for which you want to check the state.
* @return true if the key is down, false if the key is not down.
*/
public static boolean keyboardKeyState(int key) {
return keyboardState[key];
}
// Methods of keyboard listener
@Override
public void keyPressed(KeyEvent e) {
keyboardState[e.getKeyCode()] = true;
}
@Override
public void keyReleased(KeyEvent e) {
keyboardState[e.getKeyCode()] = false;
keyReleasedFramework(e);
}
@Override
public void keyTyped(KeyEvent e){
}
public abstract void keyReleasedFramework(KeyEvent e);
// Mouse
/**
* Is mouse button "button" down?
* @param button Number of mouse button for which you want to check the state.
* @return true if the button is down, false if the button is not down.
*/
public static boolean mouseButtonState(int button)
{
return mouseState[button - 1];
}
// Sets mouse key status.
private void mouseKeyStatus(MouseEvent e, boolean status)
{
if(e.getButton() == MouseEvent.BUTTON1)
mouseState[0] = status;
else if(e.getButton() == MouseEvent.BUTTON2)
mouseState[1] = status;
else if(e.getButton() == MouseEvent.BUTTON3)
mouseState[2] = status;
}
// Methods of the mouse listener.
@Override
public void mousePressed(MouseEvent e)
{
mouseKeyStatus(e, true);
}
@Override
public void mouseReleased(MouseEvent e)
{
mouseKeyStatus(e, false);
}
@Override
public void mouseClicked(MouseEvent e) { }
@Override
public void mouseEntered(MouseEvent e) { }
@Override
public void mouseExited(MouseEvent e) { }
}
Framework.java
package Game;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
public class Framework extends Canvas {
// frame width and height
public static int frameWidth;
public static int frameHeight;
//time variables
public static final long secInNanosec = 1000000000L;
public static final long milisecInNanosec = 1000000L;
// FPS
private final int GAME_FPS = 60;
// pause between update cycles
private final long GAME_UPDATE_PERIOD = secInNanosec / GAME_FPS;
// states of game
public static enum GameState{STARTING, VISUALIZING, GAME_CONTENT_LOADING, MAIN_MENU, OPTIONS, PLAYING, GAMEOVER, DESTROYED}
// current game state
public static GameState gameState;
// game time
private long gameTime;
// help calc game time
private long lastTime = 0;
// The actual game
private Game game = new Game();
public Framework ()
{
super();
gameState = GameState.VISUALIZING;
//start game in new thread
Thread gameThread = new Thread() {
@Override
public void run(){
GameLoop();
}
};
gameThread.start();
}
/**
* Set variables and objects.
*/
private void Initialize()
{
}
/**
* Load files - images, sounds, ...
*/
private void LoadContent()
{
}
/**
* In specific intervals of time (GAME_UPDATE_PERIOD) the game/logic is updated and then the game is drawn on the screen.
*/
private void GameLoop()
{
// wait some time so that we get correct frame/window resolution.
long visualizingTime = 0, lastVisualizingTime = System.nanoTime();
// calculate the time for how long we should put threat to sleep to meet FPS.
long beginTime, timeTaken, timeLeft;
while(true)
{
beginTime = System.nanoTime();
switch (gameState)
{
case PLAYING:
gameTime += System.nanoTime() - lastTime;
game.UpdateGame(gameTime);
lastTime = System.nanoTime();
break;
case GAMEOVER:
//...
break;
case MAIN_MENU:
//...
break;
case OPTIONS:
//...
break;
case GAME_CONTENT_LOADING:
//...
break;
case STARTING:
// Sets variables and objects.
Initialize();
// Load files - images, sounds, ...
LoadContent();
// When all things that are called above finished, we change game status to playing or main menu
gameState = GameState.PLAYING;
break;
case VISUALIZING:
// this.getWidth() method doesn't return the correct value immediately
// So we wait one second for the window/frame to be set to its correct size. Just in case we
// also insert 'this.getWidth() > 1' condition in case when the window/frame size wasn't set in time,
// so that we get approximately size.
if(this.getWidth() > 1 && visualizingTime > secInNanosec)
{
frameWidth = this.getWidth();
frameHeight = this.getHeight();
// When we get size of frame we change status.
gameState = GameState.STARTING;
}
else
{
visualizingTime += System.nanoTime() - lastVisualizingTime;
lastVisualizingTime = System.nanoTime();
}
break;
case DESTROYED:
break;
default:
break;
}
// Repaint the screen.
repaint();
// calculate the time for how long we should put threat to sleep to meet FPS.
timeTaken = System.nanoTime() - beginTime;
timeLeft = (GAME_UPDATE_PERIOD - timeTaken) / milisecInNanosec; // In milliseconds
// If the time is less than 10 milliseconds, then we will put thread to sleep for 10 millisecond so that some other thread can do some work.
if (timeLeft < 10)
timeLeft = 10; //set a minimum
try {
//Provides the necessary delay and also yields control so that other thread can do work.
Thread.sleep(timeLeft);
} catch (InterruptedException ex) { }
}
}
/**
* Draw the game to the screen. It is called through repaint() method in GameLoop() method.
*/
@Override
public void Draw(Graphics2D g2d)
{
System.out.println("Paint!");
switch (gameState)
{
case PLAYING:
System.out.println("we are firing draw");
game.Draw(g2d, mousePosition());
break;
case GAMEOVER:
//...
break;
case MAIN_MENU:
//...
break;
case OPTIONS:
//...
break;
case GAME_CONTENT_LOADING:
//...
break;
case DESTROYED:
break;
case STARTING:
break;
case VISUALIZING:
break;
default:
break;
}
}
/**
* Starts new game.
*/
@SuppressWarnings("unused")
private void newGame()
{
// We set gameTime to zero and lastTime to current time for later calculations.
gameTime = 0;
lastTime = System.nanoTime();
game = new Game();
}
/**
* Restart game - reset game time and call RestartGame() method of game object so that reset some variables.
*/
@SuppressWarnings("unused")
private void restartGame()
{
// We set gameTime to zero and lastTime to current time for later calculations.
gameTime = 0;
lastTime = System.nanoTime();
game.RestartGame();
// We change game status so that the game can start.
gameState = GameState.PLAYING;
}
/**
* Returns the position of the mouse pointer in game frame/window.
* If mouse position is null than this method return 0,0 coordinate.
*
* @return Point of mouse coordinates.
*/
private Point mousePosition()
{
try
{
Point mp = this.getMousePosition();
if(mp != null)
return this.getMousePosition();
else
return new Point(0, 0);
}
catch (Exception e)
{
return new Point(0, 0);
}
}
/**
* This method is called when keyboard key is released.
*
* @param e KeyEvent
*/
@Override
public void keyReleasedFramework(KeyEvent e)
{
}
/**
* This method is called when mouse button is clicked.
*
* @param e MouseEvent
*/
@Override
public void mouseClicked(MouseEvent e)
{
}
}