How to develop a GUI in my game
Hi,
I'm working on a multiplayer game in Java 1.4. This is more like a prototype than a commercial quality game, and since the focus of my work is on the networking capabilities of the game, I want to spend the least possible time with mundane things like how to type information and select things on my game...in other words, having a GUI that can provide the game with a menu/submenus, buttons, textfields and the like.
I've done several Swing applications before but this is different, since the event loop is provided by me (as any other game) and I'm using "active rendering" to display the graphics on screen.
Does anyone knows how can I use the Swing (or AWT) components in my game?
Thanks in advance.
Gabriel
Hi,
Thanks for the ansewr. I've been doing an example and I could get my Swing dialog to appear in the screen.
Below is thesource code of my example. It works but it seems to me that the animation of the square is flickering somehow (I think is double buffered) and the frame rate is somewhat low.
I would like to know how to improve those things in the example so I could use it in my game.
Regards,
Gabriel
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import com.sun.j3d.utils.timer.*;
public class ActiveSwingTest implements Runnable {
static final int VEL = 1;
// Number of frames with a delay of 0 ms before the animation thread yields
// to other running threads.
private static final int NO_DELAYS_PER_YIELD = 16;
// no. of frames that can be skipped in any one animation loop
// i.e the games state is updated but not rendered
private static int MAX_FRAME_SKIPS = 5; // was 2;
JFrame f;
JPanel panel;
Image backBuffer;
JDialog dialog;
private long gameStartTime;
private long prevStatsTime;
private boolean running;
private Graphics2D graphics;
private long period;
private long framesSkipped = 0;
int x = 0;
int y = 0;
int vx = VEL;
int vy = VEL;
public ActiveSwingTest() {
initGraphics();
}
public void initGraphics() {
panel = new JPanel();
panel.setPreferredSize(new Dimension(800, 600));
panel.setFocusable(true);
panel.requestFocus();
panel.setIgnoreRepaint(true);
readyForTermination();
f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(panel);
f.setIgnoreRepaint(true);
f.setResizable(false);
f.pack();
backBuffer = createBackBuffer();
if(backBuffer == null) {
return;
}
f.setVisible(true);
}
public void run() {
long timeDiff = 0;
long overSleepTime = 0L;
int noDelays = 0;
long excess = 0L;
gameStartTime = J3DTimer.getValue();
prevStatsTime = gameStartTime;
long beforeTime = gameStartTime;
running = true;
graphics = (Graphics2D) backBuffer.getGraphics();
while(running) {
update(timeDiff);
render(graphics);
paintScreen();
long afterTime = J3DTimer.getValue();
timeDiff = afterTime - beforeTime;
long sleepTime = (period - timeDiff) - overSleepTime;
if(sleepTime > 0) { // some time left in this cycle
try {
Thread.sleep(sleepTime / 1000000); // nano -> ms
}
catch(InterruptedException ex) {}
overSleepTime = (J3DTimer.getValue() - afterTime) - sleepTime;
}
else { // sleepTime <= 0; the frame took longer than the period
excess -= sleepTime; // store excess time value
overSleepTime = 0L;
if(++noDelays >= NO_DELAYS_PER_YIELD) {
Thread.yield(); // give another thread a chance to run
noDelays = 0;
}
}
beforeTime = J3DTimer.getValue();
/* If frame animation is taking too long, update the game state
without rendering it, to get the updates/sec nearer to
the required FPS. */
int skips = 0;
while((excess > period) && (skips < MAX_FRAME_SKIPS)) {
excess -= period;
update(timeDiff); // update state but don't render
skips++;
}
framesSkipped += skips;
}
System.exit(0); // so window disappears
}
private void showDialogo() {
if ( dialog == null ) {
dialog = new JDialog(f, "Example dialog", true);
final JTextField t = new JTextField("hello");
JButton bok = new JButton("OK");
bok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("text="+t.getText());
dialog.setVisible(false);
dialog.dispose();
dialog = null;
}
});
JButton bcancel = new JButton("Cancel");
bcancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
}
});
final Container c = dialog.getContentPane();
c.setLayout(new BorderLayout());
c.add(t, BorderLayout.CENTER);
final JPanel buttonPanel = new JPanel();
buttonPanel.add(bok);
buttonPanel.add(bcancel);
c.add(buttonPanel, BorderLayout.PAGE_END);
dialog.pack();
dialog.setLocationRelativeTo(f);
dialog.setVisible(true);
}
else {
dialog.setVisible(true);
}
}
private void paintScreen() {
// use active rendering to put the buffered image on-screen
try {
final Graphics g = panel.getGraphics();
if(g != null) {
g.drawImage(backBuffer, 0, 0, null);
}
g.dispose();
}
catch(Exception e) {
System.out.println("Graphics context error: " + e);
}
}
private Image createBackBuffer() {
final Image dbImage = panel.createImage(800, 600);
if(dbImage == null) {
System.out.println("could not create the backbuffer image!");
}
return dbImage;
}
private void readyForTermination() {
panel.addKeyListener(new KeyAdapter() {
// listen for esc, q, end, ctrl-c on the canvas to
// allow a convenient exit from the full screen configuration
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if((keyCode == KeyEvent.VK_ESCAPE) || (keyCode == KeyEvent.VK_Q) ||
(keyCode == KeyEvent.VK_END) ||
((keyCode == KeyEvent.VK_C) && e.isControlDown())) {
running = false;
}
else if ( keyCode == KeyEvent.VK_D ) {
showDialogo();
}
}
});
}
private void update(long dt) {
x += vx;
y += vy;
if ( x < 0 ) {
x = 0;
vx = VEL;
}
else if ( x > 700 ) {
x = 700;
vx = -VEL;
}
if ( y < 0 ) {
y = 0;
vy = VEL;
}
else if ( y > 500 ) {
y = 500;
vy = -VEL;
}
}
private void render(Graphics2D g) {
g.setColor(Color.RED);
g.fillRect(0, 0, 800, 600);
g.setColor(Color.WHITE);
g.fillRect(x, y, 100, 100);
}
public static void main(String[] args) {
ActiveSwingTest test = new ActiveSwingTest();
new Thread(test).start();
}
}