Overriding GameEvent

Contents

Understanding GameEngine Events
Overriding Event Methods
Method Summary
  Override These
  Useful Access
  Others

Related Documents

The Itty Bitty GameEngine -- Overview
Your Own Java Game -- Step by step tutorial to build a simple "Pong" game
Converting Your Game to JavaScript -- What you need to know to run your game in a web browser
Class GameWgt -- The visual components of a GameEngine game
Overriding GameEvent -- The programmatic components of a GameEngine game (You are here)

Understanding GameEngine Events

When you go through the "Your Own Java Game" tutorial to build a "Pong" game, the "Pong.java" text file you opened is already generated to be a subclass of the GameEvent class. GameMaker did that for you, but you could do it by hand if you wanted to. Most programmers, that's how they do it. See how much easier and faster it is to have the computer do what it knows best? Then you can spend your cognitive efforts inventing new things for the computer to do, instead of repeating what some other programmer already did. But it helps if you understand what they did.

GameEvent is a class that JavaGame already knows about, so when the game engine needs to tell you that your ball widget collided with your paddle widget, there's already a subroutine ("method") defined in the GameEvent base class that knows what to do with collision events. Of course the base class doesn't know anything at all about what to do with collisions, but when you subclass it, then your new Pong object has your own code that does know, right? You programmed it, it does just exactly what you told it to do -- even if you didn't want to tell it to do that. Computers are like that, obedient to a fault. They read your mind, but only when your mind told your fingers to type into the computer the instructions you were thinking. It helps when your fingers do what your mind told them to do, but that works most of the time. So does the computer, so when it isn't working, we spend most of our effort finding and fixing the problems where everything started: what we thought we were doing. The biggest benefit that OOPS gives to programmers is a type-safe way for the main program (the GameEngine) to call subroutines that don't even exist when the main program is written and compiled -- that would be your collision code in your subclass of GameEvent -- and not have the computer crash because you made a mistake.

But before you get too far into how to process widget events, you probably should know something about widgets, in the "Class GameWgt" page. Start there, then come back. Jumping back and forth is OK.

The basic idea is that the widgets you defined in GameMaker (as you did in the "Your Own Java Game" tutorial) do all the display work of your game, and your GameEvent subclass (think: Pong.java) handles all their interactions, and the GameEngine just sits there and does what you told it to.

Did you work through the "Your Own Java Game" tutorial? Even if you didn't understand everything you did, it helps to see what happened, so you know what to look for when you look under the hood. After all, if you get in a car and step on the gas -- all without knowing anything about automotive drive trains -- and it lunges forward, then when you look under the hood, you would not be looking for a squirrel cage or a wind-up rubber band connected to the driveshaft, squirrels and rubber bands just aren't that strong.

You made five widgets in the Pong game, so when you start to think about collisions -- when you actually saw the ball bounce off the paddle (or fail to bounce) -- you can reasonably expect that the code you typed into the Collided method has something to do with it. Especially if you tried to run the partial game before you put any code in. This kind of cause-and-effect reasoning is very important when debugging your code. It's also very important when you think about what code to write.
 

Overriding Event Methods

There are three categories of subroutines/methods in GameEvent: Most of them are event handlers, which you override to get control of the game when one of those events happens. Pretty much all of them showed up in your Pong.java file ready to override the default response, but commented out. The block comment in front of each one says a little about how to use them. In the section below we'll try to say a little more about why you would want to.

Some of these event handlers are one-time handlers, mostly at the beginning of the game (but one at the end, if I can get it working).

Then there are some access methods for getting and setting the class data. There isn't much of that, so there are few of these. Most of the utility functions you need to use access the game data, which is in the JavaGame class. You need to use those methods for most of the game-general stuff your game needs to do.
 

Method Summary

These 24 methods are available for you to override for startup and event handling:
 
BlurEv CancelDrag ClickEvt Collided
DoOften Dragging Dropped FocusEv
GameEnding GameEvent GameList GotArrowKey
GotEnterKey GotEscKey GotTabKey KeyData
KeyFld MouseDn MouseUp RollIn
RollOut RollOver StartDrag StartUp
These four methods get access to GameEvent data:
 
DefaultKeyFocus GetClickLoc GetRefWgt SetRefWgt

Override These

Game Control
Collidable
Keyboardable
Clickable
Dragable
Rolloverable
Useful Access
Others

Override These (Game Control)

String GameList(JavaGame whom)
 
Parameters
whom A reference to the host JavaGame, which is kept in theGame
Returns The generated text string
GameList returns a text descriptor of all the specified widgets in a game. The code is normally generated when you click the "Build" button in GameMaker. It is called once before StartUp, and then it builds the widgets from this text descriptor list. You must call the super to preserve the reference to the host JavaGame.

Normally you don't need to be concerned with the meaning of the numbers in the text string returned by this method, it is created by the Build button in GameMaker. However, some of the widget creation features of GameMaker are not yet working, so you might need to create your own widgets by hand to go in this list. See "Widget Specification" for the details about how to do that.


void StartUp()

After the initial widgets have been created, StartUp is called to do any other initialization the client game may have. StartUp is normally overridden in the client subclass. If you gave Java-correct names to any widgets in GameMaker, those variables are assigned values by the generated code here. You may also include here any game-specific startup code you deem appropriate to your game.


void DoOften()

DoOften is called once each frame to do whatever game processing needs to be done often. You should get in and get out, so that the animation flows smoothly. Omit overriding this method if unneeded.


void GameEnding()

GameEnding is called once when the game window is about to close, so you can do whatever needs to be done at the end. Omit overriding this method if unneeded. [GameEnding is not known to work]


Override These (Collidable)

boolean Collided(GameWgt whom, GameWgt hitt)
 
Parameters
whom reference to the sprite widget,
hitt reference to the widget it Collided with, or null of it ran off the board edge
Returns true to stop looking (for more collisions on whom)
Collided is called when a Bump-enabled (Collidable) sprite overlaps another Bump-enabled widget, or if it runs off the edge of the game board (if it is also Bump-enabled).

You should override Collided when your game wants to respond to collisions between sprite widgets (which have their own velocity and are designated Bumpable) and other widgets that have been designated Bumpable. It is best when you can identify a class of response for recognizable widget types, so the number of different tests in minimal.

In the Pong example, there is only one Bumpable sprite widget and two other widgets it can collide with. Ten billiard balls on a pool table would have 90 possible interactions (not counting the edges of the table itself) so you might try to have a single kind of interaction when two balls hit, so that your code does not spend a lot of time deciding what to do.


Override These (Keyboardable)

void BlurEv(GameWgt whom)
 
Parameters
whom The widget losing focus, or null if unknown by caller 
BlurEv is called for a widget when it loses focus. Your code may also call BlurEv to unconditionally terminate focus for any other reason. You should call super to do the default defocussing (including telling the widget that it is losing focus) unless you want to cancel the blur. If you cancel a blur that is called before another widget is about to gain focus, then that focus is also cancelled. Mostly you should avoid overriding BlurEv, because it's too easy to get caught in infinite recursion (the computer -- or at least your game -- crashes).


void FocusEv(GameWgt whom, int vert, int horz)
 
Parameters
whom The widget to be given focus 
vert The vertical offset into this widget where it was clicked 
horz The horizontal offset into this widget 
FocusEv is called for any widget that is "Focusable" when the user clicks on it. Your code may also call FocusEv to give focus to a widget for any other reason. You must call super to do the default focus processing unless you choose to cancel it. The base class calls the whom.SetFocus method for this widget, and the widget also has the opportunity to cancel (refuse) the focus. Whatever widget has focus, the class variable FocusWgt receives a reference to that widget, and your program can get that reference using the access method GetRefWgt.

Only one widget at a time can have focus, so BlurEv is called for any previous widget with focus before any other widget can get it. If BlurEv (or the widgent it calls) refuses to give up focus, then the new widget does not receive focus.

When a user types on the keyboard -- there is nominally only one keyboard to a computer -- the keystrokes are sent to a particular widget to handle them. In a game like Pong this may not have any significance, your core game code is responsible for dispatching the activities invoked by keystrokes, but if you have text fields that the user can type new text into, the computer must know which text field this key code should be sent to; that widget is said to have the focus, and the FocusEv is the way to shift the focus from one widget to another. See also DefaultKeyFocus which ensures that your program can catch keystrokes when no widget has focus.

When GameTxLn widgets receive the focus, a caret (blinking vertical bar) at the current selection point starts blinking to tell the user where the typed keystrokes will go. In GameMaker, widgets that have the focus but without an obvious place to receive text, a dotted line of "marching ants" follows the outline of that widget to show the focus. Typing the EnterKey will typically open up a dialog to change the widget's color or text.


void KeyData(GameWgt whom, char info)
 
Parameters
whom The widget that has focus 
info The key that was pressed 
KeyData is called to dispatch keystrokes if FocusWgt is not null, or else if DefaultFocus is not null, and that widget accepts keystrokes. The KeyData method in the base class separates out the control keys to call their specified event methods, so if you override KeyData, you should call super if you want that to happen and this keystroke is not yours.


void GotArrowKey(GameWgt whom, char info)
 
Parameters
whom The widget that has focus 
info The arrow key that was pressed, one of the constant values JavaGame.Arro_UP, JavaGame.Arro_DOWN, JavaGame.Arro_LEFT, or JavaGame.Arro_RIGHT
GotArrowKey is called for any widget that has focus when the user types one of the arrow keys. If FocusWgt is null and DefaultFocus is null, or if that widget does not accept keystrokes, then GotArrowKey is not called. The base class uses GotArrowKey to move a dragable widget one pixel at time, so you should call super if this is not yours.


void GotEnterKey(GameWgt whom)
 
Parameters
whom The widget that has focus 
Returns true if taken (by alert or input dlog)
GotEnterKey is called when the user types the EnterKey, if FocusWgt is not null, or else if DefaultFocus is not null, and that widget accepts keystrokes. If a standard dialog is open, it is closed and returns true. If your game can open a standard alert or input dialog, you should call super so it can get its OK clicked. Your subclass can return either true or false, because the first caller doesn't care.

When you override this method, you should first call super and check its return value; if true, you should do whatever you had the alert or input dialog open for.


void GotEscKey(GameWgt whom)
 
Parameters
whom The widget that has focus 
GotEscKey is called when the user types the EscapeKey, if FocusWgt is not null, or else if DefaultFocus is not null, and that widget accepts keystrokes. The base class uses GotEscKey to cancel an outstanding drag and to terminate any focus, so you should call super if you want that effect and this is not yours.


void GotTabKey(GameWgt whom)
 
Parameters
whom The widget that has focus 
GotTabKey is called when the user types the TabKey, if FocusWgt is not null, or else if DefaultFocus is not null, and that widget accepts keystrokes. There is no default behavior in the base class.


void KeyFld(GameWgt whom, char info)
 
Parameters
whom The widget that has focus 
info The key that was typed 
KeyFld is called for any widget that has focus when the user types any other key. If FocusWgt is null and DefaultFocus is null, or if that widget does not accept keystrokes, then KeyFld is not called. The base class uses KeyFld to insert keystrokes in an entry text field, so you should call super if this is not yours.


Override These (Clickable)

void ClickEvt(GameWgt whom, int vert, int horz)
 
Parameters
whom The widget that was clicked 
vert The vertical offset into this widget where it was clicked 
horz The horizontal offset into this widget 
ClickEvt is called for a widget that is "Clickable" when the user clicks on it (mouse down followed by mouse up on the same widget). FocusEv has already been called for this widget. The base class uses ClickEvt to detect and process double-click events, so you should call super if you want that to happen and this is not yours. You would normally override ClickEvt to process button clicks.

The vertical and horizontal offsets are relative to the top-left corner of the widget whom. Call whom.AddPrntsPos(whom.GetPosn()) to get the position relative to the window.

A click event is defined to be when the user presses the mouse button on a widget and releases it before moving off that widget, and before moving very far if the widget is also Draggable. Your code can be notified separately for the mouse down and the mouse up events if the widget is Draggable. If you don't really want the widget to be dragged, you can override StartDrag and return null.


Override These (Dragable)

GameWgt StartDrag(GameWgt whom, int vert, int horz)
 
Parameters
whom The widget that was clicked 
vert The vertical offset into this widget where it was clicked 
horz The horizontal offset into this widget 
Returns The widget being dragged, or null if cancelled 
After a MouseDn is called for a widget that is "Dragable" and the user moves the mouse at least eight pixels with the button still pressed, then it becomes a drag and StartDrag is called. If you override this method, you can either cancel the drag by returning null (without calling super), or else substitute another (possibly new) widget for (in the same location as) the clicked widget when you call super, and the replacement will be what is dragged. If you do this, there is some additional code needed in your MouseUp override so that the Dropped event works correctly.

The vertical and horizontal offsets are relative to the top-left corner of this widget. Call whom.AddPrntsPos(whom.GetPosn()) to get the position relative to the window.


void Dragging(GameWgt whom, int vert, int horz)
 
Parameters
whom The widget that is being dragged 
vert The vertical offset into this widget before it moves 
horz The horizontal offset into this widget 
After a StartDrag has been called for a Dragable widget and the user continues to move the mouse, Dragging is called for the same widget. Override this method to do something with the dragged widget's new position. Dragging in the base class updates the dragged widget's position, so call super before you try to use that position.

The vertical and horizontal offsets are relative to the top-left corner of this widget before its position has been adjusted by super. To get the position relative to the window, you should calculate whom.AddPrntsPos(whom.GetPosn())  before calling super.


void Dropped(GameWgt whom)
 
Parameters
whom The widget that was dragged 
After a StartDrag has been called for a Dragable widget and the user releases the mouse button, Dropped is called for the same widget. If you override this method and do something with the Dropped widget that could invalidate further drags on it using the arrow keys, you should also call BlurEv for it, or else make sure it cannot take focus. The base class does nothing with Dropped, so it is not necessary to call super.


void CancelDrag(GameWgt whom)
 
Parameters
whom The widget being dragged 
CancelDrag is called to cancel (terminate without effect) a drag. The default CancelDrag replaces the WgtBeingDrug (if non-null and matches the parameter) to its starting location as specified in class variable DrugWgtBase.


void MouseDn(GameWgt whom, int vert, int horz)
 
Parameters
whom The widget that was clicked 
vert The vertical offset into this widget where it was clicked 
horz The horizontal offset into this widget 
MouseDn is called for a widget that is "Dragable" when the user presses the (right) mouse button down on some widget. If the button is released without moving the mouse, then it is just a ClickEvt and no drag is attempted.

The vertical and horizontal offsets are relative to the top-left corner of this widget. Call whom.AddPrntsPos(whom.GetPosn()) to get the position relative to the window.


void MouseUp(GameWgt whom, int vert, int horz)
 
Parameters
whom The widget that was clicked 
vert The vertical offset into this widget where it was clicked 
horz The horizontal offset into this widget 
MouseUp is called for a widget that is "Dragable" when the user releases the mouse button over the same widget that was clicked or dragged. If the mouse is moved away from the clicked widget (and there is no drag in process) then MouseUp is not called (and there is no consequent ClickEvt). If your StartDrag override supplied an alternate widget to be dragged, then there is some additional coded needed here (a later release will move this to the base class where it belongs, but it's not working there yet).

The vertical and horizontal offsets are relative to the top-left corner of this widget. Call whom.AddPrntsPos(whom.GetPosn()) to get the position relative to the window.


Override These (Rolloverable)

void RollIn(GameWgt whom, int vert, int horz)
 
Parameters
whom The widget that has focus and the mouse is over it 
vert The vertical offset of the mouse in this widget 
horz The horizontal offset of the mouse in this widget 
RollIn is called when the user first rolls the mouse over a widget that accepts rollover events. [This has not been tested]


void RollOut(GameWgt whom, int vert, int horz)
 
Parameters
whom The widget that has focus and the mouse is not over it 
vert The vertical offset of the mouse relative to this widget but now outside its rectangle 
horz The horizontal offset of the mouse relative to this widget but outside its rectangle 
RollOut is called the first frame that the mouse is no longer over a widget that was sent a RollIn event. [This has not been tested]


void RollOver(GameWgt whom, int vert, int horz)
 
Parameters
whom The widget that has focus and the mouse is over it 
vert The vertical offset of the mouse in this widget 
horz The horizontal offset of the mouse in this widget 
RollOver is called each subsequent frame that the mouse is over a widget that was sent a RollIn event. [This has not been tested]


Useful Access

void DefaultKeyFocus(GameWgt whom)

DefaultKeyFocus defines a widget to receive keystrokes when no widget has focus. Pass it null to cancel the setting.


int GetClickLoc()

GetClickLoc returns the vertical and horizontal offsets (16 bits each) into the FocusWgt where it was clicked, or -1 after the mouse is released or the widget has lost its focus. ClickLocn is set by FocusEv, and cleared (to -1) by BlurEv.


GameWgt GetRefWgt(int why)
 
Parameters
why A number used to select which widget you want:
  -1=FocusWgt, 0=RollyWgt, 1=ClickWgt, 2=WgtBeingDrug
Returns The selected widget, or null if none. 
GetRefWgt can be called at any time to determine which widget has focus (is being clicked or dragged or typeable). Use SetRefWgt to set them.

Four widget references are maintained by the GameEngine to support these events:

FocusWgt is generally set by FocusEv and cleared by BlurEv, but a widget can refuse to give up focus (or BlurEv can refuse for it), in which case FocusEv will fail. FocusEv can also refuse to grant focus, or the widget can refuse to accept it, or it can be flagged as "no-focus" (see GameScro) and the low-level mouse event handler won't even try. You should avoid overriding the default GameEngine focus behavior unless you really need it, because it's very easy to make the rules so complicated as to be inconsistent, which will make your game hard to play.

ClickWgt is generally set by mouse-down and cleared by mouse-up, and is used to determine if a mouse click should be reported as a ClickEvt. It is also used to decide when to start a drag. If you change the default behavior, these operations may misbehave.

RollyWgt is generally set for a widget that accepts rollover events, and cleared when the mouse exits the rollover. If you change the default behavior, widget rollover may misbehave.

WgtBeingDrug is generally set by StartDrag and cleared by MouseUp or CancelDrag, and is used to control dragging behavior. If you change the default behavior, widget dragging may misbehave.



void SetRefWgt(int why, GameWgt whom)
 
Parameters
why A number used to select which widget you want to set:
  -1=FocusWgt, 0=RollyWgt, 1=ClickWgt, 2=WgtBeingDrug
whom Thed widget you want to set it to, or else null. 
SetRefWgt can be called at any time to set which widget has focus (is being clicked or dragged or typeable). Use GetRefWgt to get the current settings.

Four widget references are maintained by the GameEngine to support these events:

FocusWgt is generally set by FocusEv and cleared by BlurEv, but a widget can refuse to give up focus (or BlurEv can refuse for it), in which case FocusEv will fail. FocusEv can also refuse to grant focus, or the widget can refuse to accept it, or it can be flagged as "no-focus" (see GameScro) and the low-level mouse event handler won't even try. You should avoid overriding the default GameEngine focus behavior unless you really need it, because it's very easy to make the rules so complicated as to be inconsistent, which will make your game hard to play.

ClickWgt is generally set by mouse-down and cleared by mouse-up, and is used to determine if a mouse click should be reported as a ClickEvt. It is also used to decide when to start a drag. If you change the default behavior, these operations may misbehave.

RollyWgt is generally set for a widget that accepts rollover events, and cleared when the mouse exits the rollover. If you change the default behavior, widget rollover may misbehave.

WgtBeingDrug is generally set by StartDrag and cleared by MouseUp or CancelDrag, and is used to control dragging behavior. If you change the default behavior, widget dragging may misbehave.



Others

int GetValue(int why)
void SetValue(int why, int whom)

You can override GetValue/SetValue in your subclass if you need access to something we didn't think of.


Rev. 2020 July 17