JaVa
   

Integrating Mouse Events with the Main Loop

The first two examples in this chapter have been kept relatively simple to get you familiar with the use of event listeners. They are event-driven programs, where an event occurs and then we update the state of the program accordingly. This is why they are simple (with respect to app programmers, that is), because there is no main game loop handling logic and updating the display on its own periodically. Instead, an event occurs causing an event method to be invoked, which then in turn handles the event and calls a repaint method, updating the display with the new event information. This method is fine when your program is only altered by a user-caused event but not for real-time gaming. The main problem lies in the fact that these events are registered in a separate thread from your main loop thread (the Event Dispatch Thread), interrupting it at random times—whenever an event occurs. This can become a problem when you create another thread (in our case, the main loop thread of execution, like we created in ). The problem arises that we cannot predict when the event will occur in terms of where we are in the main loop, similar to problems we discussed with passive rendering in the main loop in . For example, we could have an object in our game, say a Monster object, that moves about in the game. This movement code could be executed in the main loop, as follows:

while(mainLoopRunning)
{
 if(myMonster!=null)
 myMonster.move();
// Update display
}


We may then have a mouse listener method that can lead to the possibility of killing the monster and removing the object completely, as follows:

public void mousePressed(MouseEvent e)
{
 if(monsterKilledFromEvent())
 {
 myMonster = null;
 }
}


Our program could crash, caused by a NullPointerException exception, however unlikely. It is still possible though.

We can handle thread synchronization problems such as this in a number of ways, like controlling when code in separate threads executes relative to another. One way we could handle this problem is by using the keyword synchronized with an object to protect the threads from performing their code at dangerous times relative to one another. We could do this, as follows, in both our main loop and the keyPressed event method:

while(mainLoopRunning)
{
 synchronized(myMonster)
 {
 if(myMonster!=null)
 myMonster.move();
 }
 // Update display
}
 public void mousePressed(MouseEvent e)
{
 if(monsterKilledFromEvent)
 {
 synchronized(myMonster)
 {
 myMonster = null;
 }
 }
}


The synchronized(myMonster) code block acts as a lock for the code in its thread. If we enter the synchronized code block in the main loop, we cannot enter the synchronized block in the mousePressed method at the same time. One thread must wait until the other is no longer executing in the synchronized block, which is controlled using the myMonster object as the lock; hence they are synchronized with one another. This means that our NullPointerException exception can no longer occur. For a detailed explanation on thread synchronization issues, please refer back to , "Threads."

JaVa
   
Comments