Aegidius
 Plüss   Aplulogo
     
 www.aplu.ch      Print Text 
© 2021, V10.4
 
  JGameGrid
 
 

The source code of all examples is included in the JGameGrid distribution.

Ex13: Button Actors

For simple games, user interaction by pressing a mouse or keyboard key is enough. More sophisticated game layouts may require a full GUI application with controls like buttons, menus, more than one game grid window, sliders, etc. To develop such application a GUI builder is necessary and the GameGrid bean feature provides the power to add one or more game windows like any other bean component. When you need just a few user interactions, using a GUI builder is an overkill. It is enought to insert a few GUI controls like push, toggle, check or radio buttons directly into the game window like any other actors. We call them "button actors". To simplify the handling of button actors, the Actor class is subclassed by the abstract class GGButtonBase that defines all common properties ot button actors. The special button types are concrete subclasses of this common class. Once again, this is a typical object oriented program design and shows one of the main reasons of its success. Moreover, all JGameGrid buttons are handled by mouse events and provides an ideal learning playground for event driven programs.

The most common type of a button is a push button that may be pressed and released by the mouse left or right key. A push button triggers event callback methods when the button is pressed and released. When the button area is left while the mouse button is pressed, the button returns to the released state and when reentered by holding down the mouse button, the button shows its pressed state. If the button is released now, the action is not considered to be a button click. Therefore it is necessary to distinguish between a press/release and a click event, where the button is pressed and released while the mouse cursor stays inside the button area. Under modern graphical OS, button changes their appearance when the mouse cursor moves over the button area. This mouse-over or rollover effect gives an additional feedback to the user telling him that the mouse cursor is actually over a button area and clicking now will have an impact on the program execution. In JGameGrid the GGButton and GGToggleButton classes provides both, classical buttons without rollover and more fancy buttons with rollover.

Because a GGButton is also an instance of the Actor class, its graphical appearance is determined by the actor sprite images. Therefore you may design its release, press or rollover shape with no limits to your imagination. We use the multiple sprite feature of JGameGrid actors and consider the three different shapes as sprites with spriteId = 0 for the release, 1 for the press and 2 for the rollover state. If you use a mouse listener in your application, the mouse action may interfere with the button action, because buttons are actors too. To disable normal mouse interaction when the mouse cursor is inside a button, use GGButtonBase.isInsideAnyButton(). Be aware to return false from the mouseEvent() callback, because the mouse event is needed for the buttons too.

The following program demonstrates how the GGButton class is used. The GameGrid window uses a grid of 400 x 200 pixels with no navigation bar and a gray background. A strip in the upper part serves as a button bar. An GGButton is shown that has the same background color as the strip in order to demonstrate clearly the advantage of the rollover effect. The event callbacks displays the event type in the lower part of the window using a text actor.

import ch.aplu.jgamegrid.*;
import java.awt.Color;

public class Ex13 extends GameGrid implements GGButtonListener
{
  private GGButton infoBtn = new GGButton("sprites/infobutton.gif"true);
  private int lineNb = 0;

  public Ex13()
  {
    super(400, 200, 1, false);
    setBgColor(new Color(180, 180, 180));
    addActor(new Actor("sprites/buttonbar.gif"), new Location(200, 25));
    addActor(infoBtn, new Location(100, 25));
    infoBtn.addButtonListener(this);
    show();
  }

  public void buttonPressed(GGButton button)
  {
    display("Pressed");
  }

  public void buttonReleased(GGButton button)
  {
    display("Released");
  }

  public void buttonClicked(GGButton button)
  {
    display("Clicked");
  }

  private void display(String text)
  {
    if (lineNb > 10)
      erase();
    addActor(new TextActor(text), new Location(50, 70 + 10 * lineNb++));
  }

  private void erase()
  {
    removeActors(TextActor.class);
    refresh();
    lineNb = 0;
  }

  public static void main(String[] args)
  {
    new Ex13();
  }
}

The following sprite images are used (extracted from Windows 7 GUI):

infobutton_0 infobutton_1 infobutton_2 buttonbar
infobutton_0.gif
infobutton_1.gif
infobutton_2.gif
buttonbar.gif

Execute the program locally using WebStart.

The implementation of all JGameGrid button classes uses an own internal thread to invoke the button callbacks. Every button actor has its own MouseListener that feeds the events into a unique Fifo queue. The button thread takes them out one by one and inovokes the corresponding callback method until the queue is empty. Then the button thread is put in a wait state until a new event arrives. This ensures that no events are lost even if a button callback lasts somewhat longer.

If you want to disable a button btn, call btn.enable(false). This will freeze the button image and inhibit button callbacks. If you wish to display a special button image (grayed image) for the disabled button, create an actor btnGrayed with a special sprite image and call btn.hide() and btnGrayed.show() to display the grayed button.

 

Ex13a: Hotspot Area, GGButtonOverListener

Normally the area of a button or toggle button where mouse actions take place corresponds to the bounding rectangle of the button image. You can change this hotspot area to any other rectangle relative to the button image using setHotspotArea(). This is a nice feature for non-standard buttons, especially when rollover is active. Moreover you may register a rollover event listener, to change the cursor type like in the following example. Again three sprite images buttonman_0.gif, buttonman_1.gif and buttonman_2.gif are used, the first for the released state, the second for the pressed state and the third for the rollover state.

import ch.aplu.jgamegrid.*;
import
 java.awt.*;

public
 class Ex13a extends GameGrid
  
implements GGButtonListener, GGButtonOverListener
{
  
private TextActor ta = new TextActor("Java is great");
  
private Cursor stdCursor;

  
public Ex13a()
  
{
    
super(400, 200, 1, false);
    
setBgColor(Color.white);
    GGButton buttonMan 
= new GGButton("sprites/buttonman.gif"true);
    
addActor(buttonMan, new Location(200, 100));
    buttonMan.
addButtonListener(this);
    buttonMan.
addButtonOverListener(this);
    buttonMan.
setHotspotArea(new Point(25, -30), 25, 25);
    
addActor(ta, new Location(240, 40));
    ta.
hide();
    stdCursor 
= getCursor();
    
show();
  }

  
public void buttonPressed(GGButton button)
  
{
    ta.
show();
    
refresh();
  
}

  
public void buttonReleased(GGButton button)
  
{
    ta.
hide();
    
refresh();
  
}

  
public void buttonClicked(GGButton button)
  
{
  
}

  
public void buttonEntered(GGButton button)
  
{
    
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
  
}

  
public void buttonExited(GGButton button)
  
{
    
setCursor(stdCursor);
  
}

  
public static void main(String[] args)
  
{
    
new Ex13a();
  
}
}

Execute the program locally using WebStart.

jgamegridex13a

 

Ex14: ToggleButton Actors

Toogle buttons have two distinct states like a electrical switch (pressed/released, on/off). A mouse click, more precisely a mouse release event while the cursor is inside the button area, toggles the state. A toggle button behaves like a check button, but looks more like a normal push button. In JGameGrid the GGToggleButton class resembles to the GGButton class, both are derived from GGButtonBase which has Actor as a superclass. Unlike a GGButton a GGToggleButton uses 4 sprite images, spriteId = 0 for the released, 1 for the pressed, 2 for the released rollover and 3 for the pressed rollover state.

In the following demonstration each of the two lamps has its own switch to turn the light on or off. In the callback method buttonToggled() the button reference is used to distinguish between the two switches.

import ch.aplu.jgamegrid.*;

public class Ex14 extends GameGrid implements GGToggleButtonListener
{
  private Actor lamp1 = new Actor("sprites/lamp.gif"2);
  private Actor lamp2 = new Actor("sprites/lamp.gif"2);
  private GGToggleButton tb1 = 
    new GGToggleButton("sprites/commutator.gif"true);
  private GGToggleButton tb2 = 
    new GGToggleButton("sprites/commutator.gif"true);

  public Ex14()
  {
    super(4963251false);
    addActor(lamp1, new Location(124162));
    addActor(lamp2, new Location(372162));
    addActor(tb1, new Location(124270));
    addActor(tb2, new Location(372270));
    tb1.addToggleButtonListener(this);
    tb2.addToggleButtonListener(this);
    show();
  }

  public void buttonToggled(GGToggleButton button, boolean toggled)
  {
    if (button == tb1)
      lamp1.show(toggled ? 1 : 0);
    if (button == tb2)
      lamp2.show(toggled ? 1 : 0);
    refresh();
  }

  public static void main(String[] args)
  {
    new Ex14();
  }
}

Execute the program locally using WebStart.

 

First lamp turned on. Mouse cursor outside switch hotspot area.

jgamegridex14

 

First lamp turned on. Mouse cursor inside switch hotspot area.

jgamegridex14