Question

I'm currently in the process of making a 2D turn based strategy game in Java. At this stage in development I am testing out different varieties of AIs.

The AIs interact with the game by sending a x and y variable to a function called gameLoop, which would would normally be called by a mouseClicked function. This allows them to directly emulate a human user which has made having them interact with the game much easier. Below is an overview for some of my code:

paintComponent() {
    drawTiles();
    drawUnits();
    if(unitSelected && gameState == DISP_MOVE)
        drawMoveSpots();
}

gameLoop(int x, int y) {
    // various logic based
    // on the values of x and y
    // logic may set unitSelected to true or false
    // may also change gameState bteween normal and displayMoveSpots
    repaint();
}

My issue right now stems from the fact that the AI is executing code faster than repaint happens. When this happens, I start getting errors such as NullPointerException's and ConcurrentModificationException's in my various drawing functions because the logic inside of gameLoop is changing variables faster than repaint can happen. If I add in a manual delay to how often the AI calls gameLoop or only have 2 humans playing, the errors disappear.

From my research and reading of the Java docs, I understand that repaint returns immediately and all the graphics calls are put onto the EventQueue until Java decides that there are enough calls to warrant an actual repaint. The only solution I have been able to find so far is putting the logic code that happens in gameLoop into a anonymous runnable class and call the code using SwingUtilities.invokeAndWait, but this is not a valid solution for me, because this causes actual human interaction from clicking to bug out. I have considered using a lock to provide mutual exclusion to gameLoop's logic section/repaint (so only one can execute at a time), but I'm not sure if this is a good practice when dealing with Java graphics.

At this point I'm open to any suggestions on what I can do to alleviate my problem.

Thanks.

Was it helpful?

Solution

My advise is that you should use a swing timer

  import javax.swing.Timer;

  public static void main(String[] args) {
                             /*this is 1 sec/ 1000ms*/
    Timer aiTimer = new Timer(1000, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            //move AI
            //repaint
        }
    });
    aiTimer.start();

}

By doing that you will not repaint so often. Hope that helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top