Creating a game menu

Hello all ,
I got a question … the 2 games I made up to now did not need a menu and were overall quite simple.The one I am working on now though has the need for a menu.By menu I mean a menu which will appear when the game starts and not the menu on the window , I know how to do that :).

So I guess since before the game main loop I call the initWorld() method I should put it in there.Also thought I should put an image with the name of the game and some scenery from the game or something and then the images of new game , load game and exit game.
How can I make those new images JButtons?I mean … when I checked the JButton class it had a constructor with an image butthat just put the image in it … but did not use the image for being a button.So basically my question , assuming my above theory for creating a menu is correct , is how can I make an image to act as a button ? :smiley:

draw an image and use mouse listener on it to detect cliks… you could use .contains(x,y) method, at least that’s what I used.
I used curvy text so I created GeneralPath around the text and I detect clicks on it … and this is interesting thing becouse you don’t need to draw GeneralPath object on screen, you can just create it with some coordinats and .contains() will work on them.
This with GeneralPath and contains() I did completely myself by looking through java api so if someone has better way to do it, please, I’m interested in it also.

Aha , I saw an example like that in my book about Java in general only with boxes and ticks … now that I think of it I could add a lighted version of the image of the menu when the mouse is over it too :o like … most menus do :stuck_out_tongue:

That’s what I use for my game. It’s a JButton with rollover effect. Just pass in the 3 images (normal, selected, rollover) for the three states of the button. Checkout my game to find out how it looks/behaves. All buttons in the game use this class.


import java.awt.FontMetrics;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import javax.swing.JButton;

/**
 * Represents a nice looking button with rollover effect. Pass in the 3 images for the different
 * states of the button. 
 *
 * @author    king 
 * @since     March 8, 2005
 */
public class FancyButton extends JButton {
  
  /** Image for normal state. */
  private Image normalImage;
  /** Image for rollover state. */
  private Image rolloverImage;
  /** Image for selected state. */
  private Image selectedImage;
    
  /**
   * Constructor for the button.
   * 
   * @param normalImage  The image for the normal state.
   * @param rolloverImage  The image for the rollover state.
   * @param selectedImage  The image for the selected state.
   */
  public FancyButton(Image normalImage, Image rolloverImage, Image selectedImage) {
    this.normalImage = normalImage;
    this.rolloverImage = rolloverImage;
    this.selectedImage = selectedImage;
    
    // set transparent
    setOpaque(false);
    setBorderPainted(false);
    
    // set text color
    setForeground(NORMAL_TEXT_COLOR);
    
    // set the size based on image
    Dimension size = new Dimension(normalImage.getWidth(this), normalImage.getHeight(this));
    setSize(size);
    setPreferredSize(size);
    setMinimumSize(size);
    setMaximumSize(size);
    
    // Enable rollover
    setRolloverEnabled(true);
  }
  
  /**
   * Draws this component.
   *
   * @param g  Graphics context.
   */
  public void paintComponent(Graphics g) {
    // highlight depending on rollover or button pressed
    if (model.isPressed() || isSelected()) {
      g.drawImage(this.selectedImage, 0, 0, this);
    }
    else if (model.isRollover()) {
      g.drawImage(this.rolloverImage, 0, 0, this);
    }
    else {
      g.drawImage(this.normalImage, 0, 0, this);
    }
    
    // Use antialiased text
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

    
    if (getIcon() != null) {
      int width = getSize().width;
      int height = getSize().height;
      int iconWidth = getIcon().getIconWidth();
      int iconHeight = getIcon().getIconHeight();
      getIcon().paintIcon(this, g, (width - iconWidth) / 2, (height - iconHeight) / 2);
    }
    else {
      // Draw the button text
      int width = getSize().width;
      int height = getSize().height;
      FontMetrics metrics = g.getFontMetrics();
      int fontHeight = metrics.getHeight();
      int fontWidth = metrics.stringWidth(getText());
      int x = (width - fontWidth) / 2;
      int y = (height + fontHeight) / 2 - 3;
      if (isEnabled()) {
        g.setColor(getForeground());
      }
      else {
        g.setColor(DISABLED_TEXT_COLOR);
      }
      g.drawString(getText(), x, y);
    }
  }  
}


Well, you coudl try sub-classing JButton and overriding the paintCOmponent method.

Most games do all their menuing with the same game-loop they use tio animate the game and artwork for the states.

shrug

Well since it is extending the JButton , then that’s it :slight_smile: .Hm and I guess rollover means when your mouse is in the area of the button eh?
And Jeff …hmm… why not put it in the initWorld() method?I mean , it is only needed in the start of the game anyway.Unless there is an option to exit to game menu or something.So I could make the menu as a method and have it appear again in the game loop if this option is selected .

what hard about implenting your own plaf?

Because mixing GUI librarys with game-drawing tend sto be problematic and not worth the hassle. Witness the dialogs Im using right now in BattleTrolls (well okay, shortly witness them) that arent clickable under Win32 unless you minimize the game frame first…

To Mr_Light : What is a plaf ?
To Jeff : Ok noted , I will fix it then , thanks for the comments :slight_smile: .It is through our mistakes that we learn :wink: ( or at least I hope so :stuck_out_tongue: )

pluggable look and feel
the plaf classes do the current painting is done in swing.

but as jeff mentions active rendering and mixing the stuff up will be trouble.

Well Mr_Light I don’t even know what pluggable look and feel is :-X
All I know is that the look and feel is how the windows and the menus above are and that you can get the look and feel thje user has e.t.c. , now what pluggable is I have no idea

Anyway though , thanks for the info I will try to make the best out of it

'tis from memory but a good hands on thing was this:
http://java.sun.com/products/jfc/tsc/articles/sce/index.html
however the basic sematics of plaf should probebly be kown.

pluggable is somthing that sounds fancy for something fairly simple. All media (flobby usbstick cd-rom) is pluggable in the sence that you don’t need to alter your pc to make it work. thus you can simply swap them. same goes for your processor and other countless things. surely wenn programming tis a tad more abstract. but the basic holds true you don’t need to alter your code/classes to change the look of your button. this decoupling(posibility to separate) is posible because the color of the button doesn’t really change what the button does; create an event wenn the user clicks.

looks is about appearance.
feel is about stuff like open on double click vs single click and for example hlding down the mouse wenn dragging instead of making it stick on click.

because those two are useally in relation with one an other. they are sticked togetter. anyways I’, kinda gettign off topic.

A no no don’t worry about being offtopic :slight_smile: , it all came from my question ! And thank you very much for explaining it in detail , it helped me understand plaf a lot better :slight_smile:

That well-known article basically says:

You could do this. Only we’re not going to tell you how

There is also NO documentation on the entire PLaF (unless some has miraculously appeared recently - last time I checked was about a year ago).

The vast majority of intelligent, skilled, experienced coders run away screaming when they see the big fat mess of undocumentedness that is PLaF.

YMMV, but for most people, until Sun writes some docs, the cost in time to reverse-engineer the system is greater than the time saved compared to writing your own GUI system from scratch.

Yes, I am bitter. Like many other people, it seems a ridiculous waste of time and effort for Sun to have bothered, but make the technology unusable for the people who would benefit from using it.

Here is some code for using JButton with an image and only have the image drawn:


import java.awt.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;

public class Test extends JPanel {
    public Test() {
        try {
            JButton b = new JButton(new ImageIcon(ImageIO.read(new FileInputStream("test.gif"))));
            b.setMargin(new Insets(0, 0, 0, 0));
            b.setBorderPainted(false);
            b.setContentAreaFilled(false);
            b.setFocusPainted(false);
            add(b, BorderLayout.CENTER);
        }
        catch(FileNotFoundException e) {
            e.printStackTrace();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String args[]) {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new Test());
        f.pack();
        f.setVisible(true);
    }
}

You can also set various icons for rollover, pressed, etc…

[Off-topic]
if you think thats annoying try looking at select all on focus with a JFormattedField.

you’ll find some annoying call with respect to the order of listeners overriding the class works and doesn’t look awefull at all. but then you decide you want to use it in some more advanced stuff like tables and pulldown boxes wich are compound components who use JFormattedField you can’t override them easly. AAAAH.
[/Off-topic]
I could document a fair bit, but yeah there are other annoyences and the lack of time.