If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Program in Infinite Loop Unable to Handle User Input

Hi all,

I am working on a simple game in which the player moves a paddle up and down to keep a bouncing ball from going out of bounds. The user moves the paddle by the pressing and dragging on the paddle (graphically shown as a rectangle) with the mouse. To keep the ball in constant motion, I created an Alarm class which notifies the top-level class in the program when the ball needs to be moved.

The problem is that when the method setEndlessAlarm() is called, the paddle can no longer be moved. In fact, no user input is handled. The window cannot even be closed; to end the program, I must use Eclipse's Terminate button.
To deal with the problem, I tried to use threading, since I hear that multithreading allows several events to run simultaneously. So, I set up a thread to initialize the listener, and a thread to keep the ball moving. The output was the same. I also tried using yield(), wait(), sleep(), and other Thread methods to give an opportunity for the user input to be handled. It could just be that I do not know how to properly implement threading.
So, the bottom line is, how can I receive and handle user input while still having the ball moving?

the code above is an endless loop, which will eat up the full processor time and thus not allow anyone to do anything.
try sthg like this. it will set your actual thread to sleep for a while
allowing user interactions etc.

package paddle;
/**A general-purpose timer, written originally for timing different sorting
* methods. The class has start and stop methods for starting and stopping
* the timing. It also has a method which returns the time elapsed during the
* last timing. Time is returned in milliseconds, but is stored in the class as
* nanoseconds.*/
public class Timer
{
/**Points to the value of the time of the System in nanoseconds when the
* start() method was called, or to the value of the static constant
* NO_START_TIME.*/
private long startTime;
/**Points to the value of the time of the System in nanoseconds when the
* stop() method was called.*/
private long stopTime;
/**This is the value assigned to the data member startTime in the
* constructor.*/
private static final byte NO_START_TIME = -1;
/**This is the value assigned to the data member stopTime in the
* constructor.*/
private static final byte NO_STOP_TIME = -1;
/**Constructor*/
public Timer()
{
super();
startTime = NO_START_TIME;
stopTime = NO_STOP_TIME;
}
/**Starts the timing.*/
public void start()
{
startTime = System.nanoTime();
}
/**Stops the timing, if timing has been initiated with the start() method;
* if no such timing has been started, an exception is thrown.
* @return The difference between the starting time and the ending time,
* or the time elapsed.*/
public double stop() throws TimerNotStartedException
{
if (startTime == NO_START_TIME)
{
String message = "The timer cannot be stopped because it has not" +
"been started";
throw new TimerNotStartedException(message);
}
else
{
stopTime = System.nanoTime();
double timeElapsed = (stopTime - startTime) / 1E6;
return timeElapsed;
}
}
/**Returns the reading of the last timing, if timer has been previously
* set and stopped.*/
public double getLastTime()
{
if (startTime == NO_START_TIME)
{
String message = "No time can be given because the timer was" +
"never started.";
throw new TimerNotStartedException(message);
}
else if (stopTime == NO_STOP_TIME)
{
String message = "No time can be given because the timer was" +
"never stopped.";
throw new TimerNotStartedException(message);
}
else
{
double timeElapsed = (stopTime - startTime) / 1E6;
return timeElapsed;
}
}
}

Btw, I have tried using the Timer class that comes with the java.util package; with that class, I was able to move the paddle, but there was a very long delay before the paddle moved, making the game very impractical. Additionally, the paddle moved more than it is supposed to; this problem also occurs when I call the setAlarm() method once, not the setEndlessAlarm() method. Once the ball has moved at all, the paddle cannot be moved properly.

your timer should implement runnable or extend thread an run as a seperate thread.
if not, as you did, it will use the same thread as the main application and thus block the main application when it waits.
when the timer is a seperate thread, it can wait for it's own while the main thread works on.
but that's just a guess, since i'm not shure how the rest of your app works.
let me resume: you have a class with a gui, where the user can press buttons or keys to do interaction.
how is the interaction of the user evaluated? usually, you should have some kind of mvc pattern. the interaction should modify the model. the model should notify the view and the view should be updated.
as you say, the ball keeps bouncing without userinteraction.
this means, that there should be a seperate thread, that modifies the model automatically at his own. i guess that's the timer.
for this purpose you will have to use at least:
1 thread for the automatic manipulation of the model (ball keeps bouncing)
1 thread for the userinteraction
as multiple threads will access your model synchronously, the model has to be synchronized, eg the methods will have to be synchronized.

OK, I tried to implement your suggestions. but I wasn't sure how to make the user interface have its own thread. I made my UserInterface class extend Thread; was there more that you meant about that?
I haven't tried to follow the mvc pattern. Basically, UserInterface (which implements the appropriate listener interfaces) notifies the GameFrame (which is a subclass of JFrame and has the main() method and the paint() method) what to do based on user actions. GameFrame often modifies other classes which come under the category of Model. Perhaps, my bad design is causing problems? Should the controller (i.e. UserInterface) have the main method, so that the main thread sticks with user input? Or should the main method be in a separate class that is neither Model nor View nor Controller?

well, the view usually has it's own thread, since visual updates to swing are handled by a seperate thread the jvm automatically creates. you will have to create a seperate thread for the bouncing.

lets try a simple mvc like pattern to refactor your application:

the datamodel

the datamodel should have some methods to manipulate the balls state as [CODE]well as the variables for the state themself:

Code:

public BallModel{
private int speed; // the speed of the ball
private double direction; // the direction of the ball
private Point location; // however, you can use
public synchronized void setSpeed(....)
public synchronized int getSpeed(....)
public synchronized void setDirection(....)
public synchronized double getDirection(....)
// the method should be synchronized, since multiple threads will access it
public synchronized void moveBall(){
// sets the location of the ball corresponding
// to the variables, eg speed and direction.
// also checks, if the bounds have been reached, eg position.x<0 and so on
}
// the new point is returned to avoid that the coordinates of this object
// are changed outside of the class
public Point getPosition(){
return new Point(position.x, position.y);
}
}

now we need another pattern,through which the model can notify the view (or any other listener) about changes. that's the observer pattern. the model is the observable and the view is the observer that observes. for this purpose the observable needs to know the observer to notify him about changes that occured. in the java classes this are usualy the fireEvent and listeners (actionlistener).
to make it not too compicated, we give the model a reference to the view.

Code:

public BallModel{
...
private BallView view;
public void setView(BallView view){
this.view = view;
}
private void notifyView(){
view.notifyBallChange();
}
public synchronized void moveBall(){
...
notifyView(); // after some changes were made to the position of the ball,
// the view has to be notified
}
}

now we need a seperate thread, that will update the movement of the ball. in the model i assumed, that the userinteraction only will change the speed and direction. the movement will be triggered by the seperate thread:

at this point, the ball should start to move, and the view should start painting it.

if you ask where the controller of mvc is:
that is the keylistener of your BallView, or any buttons you add to the same frame as the view. on action, you invoke the setSpeed/direction methods of the model.
since i don't have the time to test all of my examplecode, i'm not shure, if there is still a blocking issue.
let me know and we can trace it.

graviton, thanks for your help. I restructured my program from scratch in the way you suggested, and I am now able to move the paddle while the ball is moving! Thanks a lot!
However, there are a couple of smaller problems:
1) the paddle movement is somewhat choppy (i.e., there are brief delays)
2) when the paddle is moved, the ball slows down

i guess you used the same structure for the paddle as for the ball, with some model, view and the mvc.
the delays on the paddle movement can come from different sources:
repainting the view can be too slow.
some speed gaining can be achieved, when you draw your views per hand and don't extend the jpanel or jbutton.
feg you have a view panel for both, ball and paddle. let's call it gameview. then you can draw your objects within the paintComponent method by hand, eg drawing images for the objects or drawing them by graphics primitives (circles, lines, rectangles etc).
this can speed up the reaction of the view, since jpanels and jbuttons are quite complex and big.
also you can include some clipping support. when you're within the paintComponent method, you get the actual graphics object. on this object, you can invoke the getClip() method. this is a rectangle which tells you which part of the display has to be redrawn. usually, when some other window overlaps your gamewindow, the clip contains the intersection of both windows and thus the are, which has to be redrawn. if you only repaint the clipping area instead of the full display area this will speed up the display and the reactiontime at all. you also can set the clipping area by yourself.
when the view is beeing notified by the model, you don't invoke repaint() but repaint(rectangle(cliparea)). the cliparea you can determine by the bounds of the object that just moved, eg the balls previous and actual bounds merged.

then the keylistener for the paddle can be an other problem:
when the keylistener invokes the move method on the ball/paddle, it will only return after all the painting and processing within the moveBall/paddle method have been processed.
for this purpose you should start a seperate thread on each keyaction, which then asynchronously can invoke and process the rest, which will "free" the swingthread, which usually works down the code in a listener.
there are good explainations on this at http://spin.sourceforge.net/ which also has a simple api that takes care of this problem.