Event-Driven Calculator

(Using GameEngine)

<<Previous | ToC | Next

This page introduces the GameEngine and uses it for a platform to build a 4-function calculator, as part of a course on programming in Java (which starts here). If you have not yet programmed the text/console version of the calculator, you might want to go back and do that.

If you have not yet programmed anything in GameEngine, you might want to begin reading the tutorial on GameMaker, at least to the point that you have it downloaded and unzipped and running, and know how to add widgets to your game board. You can skim over the tutorial on Pong -- although Pong is a good game to start with -- then come back here.
 

Design

As always, we begin by thinking about what this program needs to do. This is different from what the text-based calculator did, because the computer is relinquishing control to the (human) user, where it belongs. Some programmers might be tempted to think they are smarter than the users -- I personally don't believe it, only that some programmers make better use of the God-given smarts that other people do, but we all are born with approximately the same number of brain cellsm we just deploy them differently -- but whether that is true or not, no machine is smarter than the human trying to use it. As far as I know (and this is related to the Entropy laws of physics, meaning it ain't gonna change in your lifetime or mine) nobody can design, construct, or program a machine to be as smart as themselves, let alone smarter.

All that to say, we give deference to the user, who knows more about what they want to do with our program than we do.

We also acknowledge the 60+ years legacy of calculator design. Here is what our users expect to see. I scraped this tiny image off the internet, and it's a little blurry, but basically we have ten numeral buttons, a decimal point, four function buttons on the side, and one of those smudges is probably a clear button, another an equal. Most of these "4-function" calculators also have four memory keys and a power button -- usually smaller buttons across the top -- but we'll ignore them for now. It was nice of them to number the digits in their display, so we know it's eight digits. We can do that with a single text line widget, wide enough to take whatever Java throws at us.

So here is what we did in the text/console version of the calculator, with the parts we won't need redlined, the added parts in blue, and one line moved in green:

while (true) { // (now each user click is an event)
  /// b. accept a command letter:
  /// c. if 'q' quit
  /// d. if 'c' clear
  /// e. accept a value (one digit at a time)
  /// f. if command is '+' add
  /// g. else if '-' subtract
  /// h. else if '*' multiply
  /// i. else if '/' divide
  /// a. display the current result (initially =0)
  /// j. otherwise print error message
  } // end of main loop
There is no repeat, when we get an event, we process it and update the result display, then exit. There is no way for the user to press any buttons that result in invalid data, so no error message is necessary. Even divide by zero gives a quasi-valid result (provided by the Java floating-point support software), which the user can see on the display. I moved the display line (a) to the end to pick up the result of every command, since we no longer repeat. We still need to initialize the display at the start, but we can do that with a line in the Startup method.

Most cheap calculators, the "C" button serves as a backspace key, deleting one input digit at a time, or if none have been entered, it clears the result to zero. That's a little tricky, we'll save it for later.

The hard part is that we need to take the button presses in the order the human clicks them, and do something reasonable with them when they arrive. Generally the user will press the buttons roughly in the order that our text-based calculator asked for input, but without the spaces and returns. If the user presses a function key, it generally means they plan to follow it with a number to apply that function to (combined with the current value on the display). Your program can know that they finished the number when they press another function key (like another + or whatever) or else an equal. That means you need to remember both the function key that is pending, and also the fact that they started a number. We use instance variables (class variables, which hang around for the methods to set and then use later) for the function key -- I called mine optor, same as in the text version -- and for the digit String being input -- I called mine aWord, same as in the text version -- as well as the (double) current result value -- as in the text version, I called mine res. Don't write any code yet, wait for GameMaker to generate a template to do it in.
 

In GameMaker

If you read the GameMaker tutorial, you already know how to open up GameMaker and (if necessary) start a new "game" project. Download and unzip (if necessary) the GameEngine file (folder) into your BlueJ folder. Then drag GameEngine folder onto the BlueJ program icon there. This opens up a new BlueJ project for your game. You should see three yellow boxes named "JavaGame", "GameWgt" and "GameEvent" which are the three public classes for GameMaker. If you have already made other games in GameMaker, you will see their yellow rectangles too. You can click the Compile button, and then choose the "main()" from the popup menu when you right-click JavaGame. This opens up a GameMaker window that looks something like this:
On the left side of the window is a (green) game board, which you can resize or change the basic color to anything you like in the right panel using the color box at the top and the size entry panels below it. You should pick a suitable Java class name for your calculator -- I called mine "CalcGE" -- and type it into the place for the name of the game board. This version of GameEngine does not let you drag-select, so you must click to the right of the name that is already there and backspace over it before typing in a new name. You should probably plan on doing this layout two or three times before you are satisfied with it. I threw my first and second cuts away and started over, after I had a better idea what I wanted. Click on the game board or its name in the widget list to select the game board, which also shows a "Start Over (New)" button you can click to discard all your changes.

I started by dragging a rectangle widget (the dark blue tool) onto the board to outline the display text and the buttons. Place the top left corner about where you want it, then give it Tall and Wide dimensions in the tool panel. In mine, I left the height at the default, but changed the width to something like 140 pixels. This version of GameEngine does not let you drag-select, so you must click to the right of whatever number is already there and backspace over it before typing in a new value. I like round numbers -- it's easier for the calculator to look professional if the spacing is consistent -- so you might also adjust (change) the Vertical and Horizontal positions of this panel to something memorable. Click the OK button in the upper right corner of the tool panel to transfer these changes to your widget.

Double-click the little blue color swatch to open up a dialog for entering a new color. You are learning Java here, so you might as well do the color in hexadecimal like a full-blooded programmer. You can experiment with different 2-digit color components (00 is dark, FF is light, the order is 0xRRGGBB). Initially it shows 0xFF0000 (blue), but you can click to the right of the number, backspace over the four zeroes and replace them with "FFFF" (0xFFFFFF is hexadecimal for RGB white), or any other color you like. I chose a dark gray (0x666666) to match the image I scraped off the internet. Click the OK button in the dialog to set the color of the color swatch, then the OK button in the corner again for it to be copied to the widget.

When you are doing several items with the same attributes on a single tool it helps to set them up on the tool itself. In this program I wanted the button labels and the result display text to be the larger font so I clicked the Text tool to select it, then chose the "Large" size and clicked the OK button to set it. I also double-clicked the tool text to replace the default "Text" with a single digit "0" and clicked OK again. Then I dragged the tool onto the display rectangle and positioned the text at the left of the display, then set its width to be almost (not quite) as wide as the background frame. I double-clicked the "0" and replaced it with ten digits so I could see how well I had positioned it -- it was terrible, I needed to tweak the position and size several times before I was satisfied with it. Don't forget to click OK (or press the Enter key on the keyboard) to accept your changes.

We have ten digit keys, four function keys, a decimal point, Clear, and Equal buttons, all the same size and color. I decided I was happy with the default size of the rectangle, but I wanted a medium dark button color, so I clicked the rectangle tool once to select it, then double-clicked the color swatch to change its default color to 0x666666 (OK and again OK) before I started dragging the buttons into place. The Rectangle widget has a user-set Identification field, which I used to enter the numeric value of each of the ten digit buttons (a single digit 0 to 9) and OK again. (When you come back to look, the 0 will show blank, which is OK, zero is the default.) The other buttons, I typed in a single descriptive character surrounded by apostrophes, like '+' or 'C'. GameMaker changes this to the ASCII numreric value of that character, but in your code you can change it back for testing. Google "ASCII chart" to see a complete list of all the numeric character codes.

The button labels are all white text, so I selected the text tool again and changed the color to white (0xFFFFFF) before dragging the tool onto the top of each button that was already there. Once in place, I double clicked the text where it was to change the text to the different digits, or to the function key symbols.

I keep forgetting, the button rectangles will be what the user clicks to operate your calculator, so you need to make each of the rectangles Clickable. Click once on the rectangle, or if that's fully covered by the text label, click on its name in the widget list, then click on the "Click" checkbox, then OK to accept it. Confirm that the Identifier value on the rectangle matches the (text) button label. Each button will be two widgets, a rectangle to see and click on, and a text label on top of it.

Here is what I had, with the rectangle behind the decimal point selected. I had given it the Identifier value '.' which it retains as the ASCII value 46. Notice the red checkmark in the Clik checkbox.

Each widget you drag onto the game board gets its own unique name, which is listed in the widget list by name in the order created. These are numbered with a period , which means it's not a valid Java variable name. If you want access to any of these widgets in your Java code, you probably need to give them proper Java names. The button clicks can be identified by that identifier number -- you did make them all different, right? -- so you don't need to call them up by name, but the text item of the display needs to have good a Java variable name, so you can access it to put the current result there when your program is running. I chose "DisplayTx" which is a little hard to read on the third line of the shrunken screen shot here. GameMaker will create and initialize these variables for you, but you must give good names to the ones your program needs access to. Right now that is only the display text, everything else happens behind the curtain.

When you are satisfied with the appearance of your calculator, click OK (actually, you should hit OK often, because it saves the current state, and if you crash -- I hope not, but you never know for sure and this is a huge program -- it will recover to the most recent OK) and then click Build and close the GameMaker window.

In the next page we will write the Java code for this calculator.

<<Previous | ToC | Next >>

Revised: 2020 November 4