1

I'm creating a simple game turn based game in NetBeans. After the initialization of the GUI it calls the function herosTurn() to which waits for the users choice and and creates the outcome of that choice from a separate class Hero. When I step through the code in Debug mode, I get correct outcomes, but if I just run the code nothing is ever appended to the Text Area unless I have the wait function constantly appending text while it waits for input. I've seen other questions similar to this but they all involved multi-threading, and I don't believe that is what I am doing. Any help would be greatly appreciated.

This is the main class:

package Flow;

import Forms.Battleinterface;


/**
 *
 * @author Steemo
 */
public class battle { 
    public static int hAct;
    public static int gLife = 200;

    public static void herosTurn() {
        hAct = 0;

        Forms.Battleinterface.biText.append("What will you do?");
        while (hAct == 0){
            // adding the line below makes code work but is ugly.
            //Forms.Battleinterface.biText.append(".");
            continue;
        }
        if (hAct == 1){
            Entities.Hero.attack();
        }
    }

    public static void main(String args[]) {
        Battleinterface battleinterface = new Forms.Battleinterface();
        Battleinterface.Start();
        while (gLife > 0) {
            herosTurn();
        }


    }
}

And this is the Hero() class that is in a separate package:

package Entities;

import java.util.Random;

/**
 *
 * @author Steemo
 */
public class Hero {
    static Random hGen = new Random(54154454);

    public static void attack() {
        int hAtt = 0;
        hAtt = hGen.nextInt(6) + 15;
        Forms.Battleinterface.biText.append("\nYou swing your axe and do " + hAtt
                + " Damage!!!");
    }

}

I am not attaching the class I use to generate the GUI (Battleinterface) because the GUI generates fine and the only other thing happening there is the passing of the input hAct. If it is needed I can attach it.

kleopatra
  • 51,061
  • 28
  • 99
  • 211
Sevvy325
  • 547
  • 2
  • 7
  • 16
  • In a simple GUI app, you shouldn't ever write code which explicitly "waits for user input" (in a thread-blocking sense). Waiting for user input is the job of the GUI framework, and you shouldn't usually write your own code to do that. – Mike Clark Mar 13 '12 at 18:09
  • please learn java naming conventions and stick to them – kleopatra Mar 14 '12 at 12:21

4 Answers4

1

Replace this code...

while (hAct == 0){
  continue;
}

...with this instead:

while (hAct == 0){
  try {
    Thread.yield();
  } catch (InterruptedException interruptedEx) {
    // Log the interruption somewhere.
  }
}

Assuming you're using AWT/Swing on some level? This is an infinite loop, preventing other threads from ever running. By doing this you never let the UI thread actually do any updating, which means it appears to hang. You may not be doing any threading on your own, but AWT/Swing comes with Threads built in to do various functions, and they need to periodically get CPU time to do their work.

The reason this works in debugging is because the debugger is pausing the herosTurn method as you're stepping through it, allowing the UI thread to do its updates (including getting input from the user), but when simply running your game, the herosTurn method never pauses, and that method is occupying 100% of the available CPU time for your app.

Finally, as Mike Clark mentions, you typically shouldn't write UI with infinite loops. Instead you define components, which trigger events. Your code is notified of those events and reacts appropriately. This is what is known as the UI's event model. If you're using Swing, the introductory info on working within the event model is covered here.

I also wouldn't typically use AWT/Swing for games, because of the complications of UI coding, rendering performance, and several other reasons relating to the reality that AWT/Swing were not built to be good tools for games. That being said, a turn-based game can work fine this way (because the rendering performance requirements are often much lower) if you're willing to delve into the UI code to get it done, in addition to a few other reasons which I've outlined in a previous answer.

Community
  • 1
  • 1
jefflunt
  • 33,527
  • 7
  • 88
  • 126
  • Yes I am using Swing I tried our fix but it threw this Error at me: Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - exception java.lang.InterruptedException is never thrown in body of corresponding try statement – Sevvy325 Mar 13 '12 at 18:30
  • After reading the input here and doing some more research, I've decided to abandon this project using Java. I'm looking into QML/C++ and using Qt Creator as my IDE. Seems like a much more viable option. – Sevvy325 Mar 15 '12 at 15:38
  • In reference to your first comment, if the InterruptedException is never thrown, then you can just remove the try/catch block that references it. In reference to your second comment - good luck with your new approach. – jefflunt Mar 15 '12 at 15:49
0

Hmm, there might be an issue with flushing your text buffer to the text area. Try explicitly flushing your text buffer after every print to see if that makes a difference.

ScottShamus
  • 415
  • 5
  • 6
0

It seems to me that your program is stuck in a while loop in the method herosTurn() As long as that function has not returned, nothing is going to update if you program this game as a single thread application.

It works when you uncomment the Forms.Battleinterface.biText.append("."); line cos then you send a signal to the GUI every iteration which causes it to update.

Games usually have a main game loop from which all elements of the program are controlled. Maybe a change of your implementation strategy will help?

len
  • 335
  • 1
  • 5
0

I'm not a games programmer, so this might not be the best approach, but why don't you try setting up a javax.swing.Timer that runs every, say, 100 milliseconds. In inside the timer action, you can write all the code which checks and advances the game state and generates output to the user.

I'd suggest collecting the user's input in a JTextField that is separate from the place where the game output is printed. If you want to know when the user presses enter to send what they've typed, you can register an ActionListener on the JTextField.

textField.addActionListener(yourListener);
Mike Clark
  • 10,027
  • 3
  • 40
  • 54