Requesting tips, comments
To: comp.lang.java.gui
I recently saw a thread about the Swing EDT in the CLJP, and it made
me wonder whether my general game architecture was thread safe or not.
EDT, and threading in general, are one of my weaker points in Java. Is
this general design okay? Are there things which I've put into the EDT
which I shouldn't have? Are there things which are outside of the EDT that
should be in it?
<SSCCE>
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.geom.AffineTransform;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
private static final int DEFAULT_RENDERING_WIDTH = 640;
private static final int DEFAULT_RENDERING_HEIGHT = 480;
private static JFrame mainWindow;
/*
* the mainPanel is where most of the drawing happens. I draw onto a
panel
* instead of directly onto the JFrame to avoid messing around with
* getInsets().
*/
private static JPanel mainPanel;
/*
* Returns true if the game is in the process of shutting down and
quitting.
* If it's in the middle of a game-loop iteration, it'll finish that
* iteration (potentially drawing 1 more frame of animation, and then
quit.
*/
private static boolean timeToQuit = false;
/*
* True if the player pressed the "action" key since the last iteration
* through the game loop, false otherwise. In a real game, I'd probably
have
* many of these booleans (e.g. an "up" key, a "down" key, etc., and move
it
* into a seperate class for organization purposes.
*/
private static boolean pressedActionKey = false;
public static void main(String[] args) throws InterruptedException,
InvocationTargetException {
/*
* This first invokeAndWait initializes all the GUI components, and
* registers the appropriate listeners to hook into the main game
* engine.
*/
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
mainWindow = new JFrame("My game");
mainWindow.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
mainWindow.addWindowListener(new WindowListener() {
@Override
public void windowActivated(WindowEvent e) {
// Does nothing.
}
@Override
public void windowClosed(WindowEvent e) {
// Does nothing
}
@Override
public void windowClosing(WindowEvent e) {
timeToQuit = true;
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
synchronized (mainWindow) {
mainWindow.setVisible(false);
mainWindow.dispose();
}
}
});
}
@Override
public void windowDeactivated(WindowEvent e) {
// Does nothing.
}
@Override
public void windowDeiconified(WindowEvent e) {
// Does nothing.
}
@Override
public void windowIconified(WindowEvent e) {
// Does nothing.
}
@Override
public void windowOpened(WindowEvent e) {
// Does nothing.
}
});
mainWindow.addKeyListener(new KeyListener() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
pressedActionKey = true;
}
}
@Override
public void keyReleased(KeyEvent e) {
// does nothing.
}
@Override
public void keyTyped(KeyEvent e) {
// does nothing.
}
});
mainPanel = new JPanel();
mainPanel.setPreferredSize(new Dimension(
DEFAULT_RENDERING_WIDTH, DEFAULT_RENDERING_HEIGHT));
mainWindow.add(mainPanel);
mainWindow.pack();
mainWindow.setVisible(true);
}
});
/*
* This while loop is the main game loop. It basically iterates through
* 3 stages forever: getting the player input, reacting to it, and
* drawing the results on screen.
*/
while (!timeToQuit) {
getPlayerInput();
processGameLogic();
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
synchronized (mainWindow) {
Graphics2D g = (Graphics2D) mainPanel.getGraphics();
g.setTransform(AffineTransform.getScaleInstance(
(double) mainPanel.getWidth()
/ (double) DEFAULT_RENDERING_WIDTH,
(double) mainPanel.getHeight()
/ (double) DEFAULT_RENDERING_HEIGHT));
updateScreen(g);
}
}
});
Thread.sleep(1);
}
}
public static void processGameLogic() {
/*
* Check if pacman touched a ghost, stuff like that. Doesn't touch any
* Swing components.
*/
}
public static void getPlayerInput() {
/*
* Doesn't touch any Swing components.
*/
if (pressedActionKey) {
/* make mario jump */
System.out.println("Mario jumps.");
pressedActionKey = false;
}
}
public static void updateScreen(Graphics2D g) {
assert SwingUtilities.isEventDispatchThread() : "Don't call updateScreen
from outside the EDT.";
g.setColor(Color.BLACK);
g.fillRect(0, 0, 640, 480);
/*
* TODO: Draw all sorts of amazing eye-candy.
*/
}
}
</SSCCE>
- Oliver
---
* Synchronet * The Whitehouse BBS --- whitehouse.hulds.com --- check it out free usenet!
--- Synchronet 3.15a-Win32 NewsLink 1.92
Time Warp of the Future BBS - telnet://time.synchro.net:24