Your Own Java Game


Download -- (Managed Chromebook, see here)
Part #0: Appropriate Tools
  Design First
  Getting Started with the Java GameEngine
Part #1: Laying Out Your First GameEngine Game
Part #2: GameEngine Classes
  Collisions in GameEngine
Part #3: Keyboard Input
Part #4: Text Display
Part #5: Your Own Game

Related Documents

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

Part #0: Appropriate Tools

Commercial games are written by large teams, a dozen or more creative people, over the course of a year or more. You will not write that kind of game in one week or one term in school.

Many, perhaps most, games are written in layers, where the rules of play and the actual playing and board design happen at a very high level, then these are interpreted in a game engine that is designed to make that high-level design happen easily and naturally at game speed. The result is that the game designers, the ones doing rules of play and look&feel, they can spend their effort thinking about what they want the game to be like, not how to make the pixels on the screen work. Other programmers do that low-level programming. There are several commercial game engines on the market, which you can use to design your own game according to their (low-level) rules. If you want a different underlying engine, buy a different product, or make your own. But it's a lot of work. The point is, the creative game designers don't need to do that work.

This week you get to do your own high-level game design without worrying about the low-level pixels, but you still get to work in Java. I wrote a simplistic game engine you can use and it does the low-level pixel stuff. But the game engine is itself written in Java, and you can actually go in and change it. But I wouldn't recommend that for your first couple games. Get some experience, then you will know what you want to change and maybe even what you don't need to change. Work at the highest level possible, you will waste a lot less time re-inventing tools other people did better.

For a complete description of GameEngine and how to use it, see the GameEngine web page. This version of GameEngine still has some user interface problems because I ran out of time, but usually there are work-arounds described in the reference page(s).

Previously (in Hello) you wrote Java programs that ran in a subroutine called "main()" because in the old days of C and Fortran, that was the magic name that the operating system knew to call to run your program. Today interactive software is smarter than that, and yes there is still a main() to start things up, but then everything happens by means of events, and you will write code that responds to particular events like mouse clicks, keys typed, or the passage of time. OOPS lets the system spell out the names and parameters for the subroutines (methods) that respond to each event type, and all you need to do it fill in the Java code to do whatever needs doing.

Design First

The most important thing in building any game (or any software) is to decide and understand what it needs to do and how it should do it. If you just take off in a random direction, you will get a random game that isn't fun to play.

Don't get too creative on your first GameEngine game. Learn the tool, then get creative.

To give you an idea of how to design your program using GameEngine, I will walk you through the steps for a very simple video game, which we will call "Pong" because it resembles an early video game by that name. I saw the original game when it came out, so I have this idea in my head, but it helps to draw a picture of what you think it should look like:

Basically it's a simplified ping-pong game, a rectangular game table with a movable paddle at each end that slides up or down under user control, and a ball that moves back and forth. If it hits the paddle, it reverses direction and goes the other way. If it misses the paddle, it runs off the end, then comes back on going the other direction, but the other player's score goes up. We can give the ball some "English" if it hits the edge of the paddle. I think the original game has joysticks or something to move the paddles, but we will play it using a couple keys on each end of the keyboard to move each paddle.

Every program should have a Top-Down Design document, but as I pointed out elsewhere, event-driven software like the GameEngine-based programs all have basically the same top level:

"Any Event-Driven Program"
  Initialize & Greetings
  Handle Events
We will get to the initialization part shortly -- mostly it is generated automatically from your specifications in GameMaker -- so let's think about the events part. The GameEngine does all the animation we need, so we have only two kinds of events to be concerned with, collisions (ball on paddle, and ball on game edge) and keystrokes to move the paddle up or down:
"Handle Events"
The GameEngine has separate subroutines that do these two kinds of things, and (when we get there) you will fill in the code for these two subroutines. So our TDD is finished.

This is an early version of GameEngine and this tutorial, so if it's not clear what to do, or why the Java compiler doesn't like what you gave it, that's probably my fault, not yours. If you are in a classroom environment, summon a Mentor, and two things happen:

1. Somebody will come and work with you to get past the problem.

2. I will make the documentation better -- maybe next week, more likely next term. We need your help. Really.

-- or use the "Ask" feature in Zoom.
Otherwise send an email to "submit(at)" and we'll try to get back to you, hopefully with the same effect.

Getting Started with the Java GameEngine

If you are doing this on Replit, see special instructions here.
Otherwise (in BlueJ), Download and unzip (if necessary) the BluGame1 file (folder) into your BlueJ folder. Then drag BluGame1 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. You can click the Compile button, and then choose the "main()" from the popup menu when you right-click JavaGame. Earlier versions of BlueJ kindly placed that item near the top of their popup menu, but the latest version (as of this writing) you need to hunt for it, possibly near the end of the menu.
This opens up a GameMaker window that looks something like this:
Take a little time to become familiar with what you see here. 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 and the size entry panels. Not in this version, but eventually you will also be able to drag the corner to resize it. You should give your game a name in the Name field (or leave the default for now). This name becomes the Java class name of your game, so you must choose a name that is a valid Java class name. Let's call it "Pong". [Sorry, the text entry fields do not let you select the whole text for retyping, you need to use the backspace key; Real Soon Now.]

Also in the right panel are some widget icons that you can click to select, and/or drag onto your game board. Here are a couple full-size screen shots of the tool panel, on the left with the text tool selected, and on the right the ball tool. You can click on any tool and change (some of) its parameters for subsequent usage, or you can click on any widget already on the board to reposition it by dragging, or else to change its color, position or size (and in the case of a Text widget, also its font and text) in place using the entry fields in the tool panel.

On the first line below the "BYOG" (Build Your Own Game) title is the name of the selected tool (or the type of widget already on the game board, if you selected that (the same name as the tool that created it) and a colored box showing the basic color of whatever tool or widget is selected, and maybe an OK button to accept any changes you made. You can double-click the color swatch to bring up a dialog, and you can type into it (this is Java, right?) the hexadecimal code for the color. When you click OK in the input dialog, the color swatch will change to that color. Any time you make any changes to the tool panel, an OK button will appear, which you can use to accept the changes you made. [Sorry, no way to cancel or undo your changes yet, but you can save a copy of the text file "Pong.txt" (or whatever your game name is) from time to time, then revert to a previous copy, all in your computer's (or Replit's) file manager.]

Every widget has a name, and if you choose a valid Java variable name, that becomes the name of the variable you can use to manipulate that widget in your program. Below the name are four entry fields, the vertical and horizontal position of a widget on the game board, and its size (tall and wide).

Next are five checkboxes, which control what kinds of events this widget will respond to. When the game board is selected, there is one more checkbox, which if checked, it means you can call up alert messages that the user must dismiss to continue, and input dialogs like the one you use to change the color. If a sprite widget or tool is selected, that space is occupied by another pair of input fields which you can use to preset the speed (positive is down and/or right). The text widget puts up some radio buttons so you can choose one of seven simple fonts. Not so obvious, you can 2-click the text itself and it opens up an input dialog box for you to enter a line of text. Changes you make to the tools will be reflected in all subsequent widgets you create from them, or you can change the created widgets one at a time.

GameEngine will remember what you have done in a text file "GameMaker.txt" (and also in an identical file "Pong.txt" or whatever your game name is) but you can start over by clicking the Start Over button (or else by quitting out of the GameEngine, deleting or renaming the "GameMaker.txt" file, then restarting JavaGame). After you have designed the appearance of your game, you can click on the Build button and it will create (or update, if it already exists) the Java file "" (or whatever you named your game). All the rest of your game development will be in Java inside this class. You do not want to be changing the three existing classes, at least not for the first few games.

Part #1: Laying Out Your First GameEngine Game

Start off with a clean game board -- if you have already added widgets or made other changes, click the Start Over button with the game board selected, then confirm the discard, then click the OK button (the final OK shouldn't be needed, but I had some trouble with it; you may also need to quit and restart JavaGame = close the GameMaker window) -- and give the game board a name like "Pong". We will do a simple 2-player game in black and white, somewhat like the original Atari Pong game. Double-click the color swatch and type in "0x0" (no quotes) for a black background color in the entry dialog. [Sorry, the entry dialog doesn't let you select the whole text for retyping, you need to use the backspace key; Real Soon Now.] Click OK or type the Enter key to dismiss the dialog, then again to apply the new color to the game board. If you want your game board to be some other size than the default, this would be a good time to set it. Be sure to click the OK button to accept your change, if any. The OK button is replaced by a Build button when there are no unaccepted changes. You can click the Build button any time you want, but it makes more sense to do it after you are satisfied with the appearance.

Now we add a ball sprite (the red circle in the tools stack). Drag it to the middle of the game board. The original Pong game was pure black and white, so for historical consistency we will (if necessary, click on the ball you just dropped on the game board to select it, then) 2-click the color swatch and type in 0xFFFFFF for a white ball. Notice that we are using Java hexadecimal constants for the color entry (see "Useful Tech Issues: Color by the Numbers"). This is good practice for you: the first pair "FF" (255) is the red component, the next is green, the third is blue, all max (255) values, which is white (try different numbers and see what colors you get). With the ball still selected, click in the name field and type in a Java-compliant name (no period!) so that you can access the ball from your code; I used "theBall" but you can name it anything you want. You also want to check the Bump checkbox so that your code will know when the ball runs into a paddle or off the edge. In the velocity entry line, you might give the ball a constant horizontal velocity of 2.0 (pixels per frame, which is 10 frames per second, for a net ball velocity of 20 pixels per second. I added a slight downward drift 0.1 pixels per frame. Click OK to accept your changes.

Speaking of running off the edges, the GameEngine collision detector only reports collisions involving widgets that are tagged collidable, so to catch when the ball runs off the edge you need to reselect the game board (you can click on its name in the widget list, or on the board itself) then check Bump and click OK. A collision in this game engine is defined when the rectangles of any two widgets that are checked Bump overlap, except that at least one of them must be a sprite so it can move. If the game board itself is checked Bump the collision is defined to be when the sprite runs off any edge. In the next chapter we will see how to code Java to respond to collisions.

Now we need two paddles, for which we will use rectangle widgets. You can drop both rectangles, one at each end, then go back and set their respective properties, or you can do them one at a time. I made my paddles 50 pixels tall and eight pixels wide. The left paddle I placed at the middle of the board (subtract 50 from the board height, then divide that in half, for the vertical position), eight pixels from the left edge, and the right paddle similarly at a horizontal position 16 pixels less than the width of the board (after you add on the 8-pixel paddle width, the right edge of the paddle ends up eight pixels from the edge). You can make your paddles any color you like, but I made mine white for historical authenticity. Give them good Java names like "LeftP" and "RightP" or anything you like, and click the OK button each time to accept your design.

Then click the Build button to create a "" file (or whatever name you gave your game) in the BlueJ (or Replit) project folder, then close the "Build Game" (GameMaker) window. Back in the [BlueJ or Replit] control panel: In BlueJ it's the window with the three yellow boxes, choose the "Edit->Add Class from File..." menu and select your new file. This makes a new yellow rectangle, which you can double-click to edit the code. Each time you do a new Build, you should close and re-open the (or whatever game name you are working on) tab/window so BlueJ knows you made changes. In Replit you click the document icon on the left margin to see the files in this Repl (project) then just click the file name to open it in the code panel.

In BlueJ you can also choose "Delete" from the popup menu when you right-click your new yellow box, but it both removes it from BlueJ, and deletes the text file, so if you want to keep it, make a copy somewhere else first. It's OK to leave it there after you change the name of your game (and get another yellow box), it will not be a part of any game you build that you did not open it specifically. I would try not to delete your game file in a file browser like Windows Explorer or OSX Finder, it might confuse BlueJ; use the BlueJ Delete menu to do it.

Part #2: GameEngine Classes

In Java, a class is a named collection of data and subroutines (called methods) to act on that data. It is useful for collecting into a single place all of the things you might want to do with some data that should be thought of together, and to tell the compiler what you want to do with that data so it can help you not to make mistakes when you are doing it. Classes are like subroutines, they are a way to gather some code and the data it works on into a box and put a name on it. Your game will be one of those boxes (yellow in the BlueJ dashboard), with everything you know about your game in that class.

In GameEngine we have two basic classes, one "GameWgt" for the visible elements (sometimes called widgets) of the game board (including the board itself), and a second "GameEvent" to tell GameEngine how the game plays. There are several different kinds of widgets, so we have several subclasses, each one defining a different kind of widget. Because in Java everything is a class, we also have a larger class "JavaGame" for the whole program. You mostly will not be creating more widget types, but using the existing classes and the subroutines already there to work with them. You will, however, define your own GameEvent subclass. In this example, it's named "Pong". You don't change GameEvent itself, you change only your own named subclass. It keeps your code together without messing with working (GameEngine) code.

The most important benefit you get from OOPS (Object-Oriented Programming Systems) is a type-safe way for a program -- in this case, the GameEngine -- to call subroutines in other programs that have not been written yet -- that would be your game. By defining a class (GameEvent) with all the subroutines the main program (JavaGame) wants to call, then when your game subclasses GameEvent, all those subroutines that you override now become accessible. In the Bad Old Days of C and assembly language, you could still do that kind of thing, but there was no protection from easily made mistakes, and the whole computer crashed. Now with OOPS the compiler tells you about your mistake, and you fix it, no harm done (nobody knows but you, if you care).

For a detailed description of all the methods you can rewrite ("override") in your GameEvent subclass see "Overriding GameEvent". For now I'll discuss only the changes you need to make for Pong to work. First you can look at the code GameMaker generated for you, in the file/window you just opened.

You will notice some lines with dollar signs "$" on them. The GameMaker Build button looks for those lines when it inserts the generated code from your widget placement, so DO NOT MODIFY ANY LINE WITH "$" ON IT, or the next time you click Build, it will complain and ask you to delete your Java file. If you change the generated code between matching "$" tags, your changes will be lost the next time you click Build. Computers are stupid, and I didn't have time to make it smarter. You can be smart for both of us: Be careful with the generated code file.

Each of the widgets you gave a Java-compatible name to, there is a variable of type GameWgt with that name at the front of the class. It is initially set to be a reference to an instance of the GameWgt class, populated with the data for that widget type. The game board itself is also a widget, but its name is used for the class name, so the reference variable has a prefix "my" as in "myPong". There is a generated line of Java code in the Startup() method to initialize each such variable. And there is a large text string in the GameList() method which is delivered to the game engine to tell it what widgets to create and where to put them. This is all described in the "Overriding GameEvent" page. If you do nothing else but compile this class and run it, it will put up your game board in a window, with the ball moving off to the right until it runs off the screen, because there is no code to tell GameEngine what to do when that happens, or what happens when it hits a paddle. Let's do that now.

Collisions in GameEngine

Scroll down to the Collided method. Notice that all three of its lines of Java code (after the JavaDoc block quote at the front) are commented out. You will uncomment them (remove the "//" from the front of each line). If this is the first time you opened this file, and the three lines are not commented out, you probably have the wrong file. Make sure it has your own game name on the tab at the top of the window.

The Collided method takes two parameters, both of them widgets. The first one "whom" is the sprite widget (the ball, it's moving) and the second one is what it bumped into (one of the paddles), or else null (no widget) if the ball ran off the edge. In both cases we will consider only the first thing the ball bumps into, so delete the middle line (of the three).

If the ball ran off the top or bottom edge, we want to reverse the vertical velocity for a ricochet effect; if it ran off the left or right edge, we want to reverse the horizontal velocity. The top edge is easily tested because the vertical position of the ball goes zero or negative. Similarly, the left edge can be detected when the ball's horizontal position goes negative. To get the same relative positions on the bottom and right, we need to add the ball diameter to its position, or equivalently, subtract the diameter from the game board edge. To decide if this is a game board edge collision, we need a local integer variable for the ball size, a couple more for the ball's vertical and horizontal positions, and a fourth to hold the window size, initially height:

public boolean Collided(GameWgt whom, GameWgt hitt) {
  int ball, horz, vert, scrn = JavaGame.GameWinTall();

The velocity can be fractional, so we use a couple double variables for its vertical and horizontal components. Bouncing the ball off the game board edge always reverses only the one component for the edge it bounced off. For example, if the ball is going mostly right but slightly down (the initial starting condition), and it hits the bottom of the game board, it should bounce up, so that it is now still going mostly right but now slightly up. Similarly, when it hits the back wall (the right edge) the horizontal component reverses, but the up-ness or down-ness continues in that direction. Two variables hold those two directions:

  double down = 0.0, rite = 0.0;
A reference to the ball widget is given in parameter whom, which is used to get the ball's size, position, and velocity:
  if (whom==null) return false; // probably can't happen, but test anyway
  ball = whom.GetTall(); // ball diameter
  horz = whom.GetHposn();
  vert = whom.GetVposn();
  down = whom.GetDnVelo();
  rite = whom.GetRtVelo();
We also calculate the position of the bottom edge of the board for testing the ball against:
  scrn = scrn - ball;
Now we can test if the ball is bouncing off the top or bottom:
if (hitt==null) { // the ball is off some edge..
  if (vert<0) // off the top..
    if (down<0) down = -down;
  if (vert>scrn) // off the bottom..
    if (down>0) down = -down;
Notice that I checked that the ball is still moving up (or down) before reversing its direction. There could be minor discrepancies (we call it round-off error) in position, so that we might get two off-edge events, one of them after we already changed direction, and we don't want to change it again. OK, the same for horizontal, still within the condition that hitt==null:
  scrn = JavaGame.GameWinWide()-ball; // now look at width..
  if (horz<0) // off the left..
    if (rite<0) { // ..and still moving left..
      rite = -rite;
      // (scoring goes here)
  if (horz>scrn) // off the right..
    if (rite>0) { // ..and still moving right..
      rite = -rite;
      // (scoring goes here)
  } // (done with board edge)
Next, we test for the ball hitting a paddle:
else if (hitt==LeftP) { // ball hit left paddle..
  if (rite<0) { // still moving left..
    // ("English" goes here)
    rite = -rite;}}
else if (hitt==RightP) { // ball hit right paddle..
  if (rite>0) { // still moving right..
    // ("English" goes here)
    rite = -rite;}}
Finally we put any calculated change in direction back into the ball widget:
whom.SetDnVelo(down); // put it back into the widget
return true;} //~Collided

This will now do something credible if you compile and run it: the ball will bounce back and forth off the paddles, and when it misses a paddle or hits the side of the game board, it will ricochet off that edge too.

Part #3: Keyboard Input

We need some way to move the paddles up and down. I chose a couple of keys on each end of the keyboard, 'A' and 'Z' on the left and 'K' and 'M' on the right. 'A' and 'K' move their respective paddles up maybe 5 pixels, 'Z' and 'M' similarly move them down. We need a widget to take the keyboard focus, so I picked the ball because we already have a reference to it. Near the end of the StartUp method (after the generated lines, because we need them to execute first) we insert a single line:
    /// [..$] End generated StartUp code [$] (do not modify this line)
    } //~StartUp
Be careful not to change the (existing) line with "$"s on it.

The ball needs to be able to accept keystrokes, so save and close the window and restart the GameMaker window, then select the ball, and check the Key checkbox, then OK and Build. When you re-open the window your changes are still there, but one of the numbers in the GameList() method is different.

To capture keystrokes in your Java program you need to override some kind of keyboard listener. This happens inside the GameEngine, and those keystrokes are forwarded to the GameEvent class, which you have overridden, so all you need to do is provide code for its KeyFld method (or the others, if you are expecting enter/escape/tab or arrow keys). We replace the one-line stub with code to accept one of our four move-paddle keys:
public void KeyFld(GameWgt whom, char info) {
  if (info == 'A') MovePaddle(LeftP,-5);
  else if (info == 'Z') MovePaddle(LeftP,5);
  else if (info == 'K') MovePaddle(RightP,-5);
  else if (info == 'M') MovePaddle(RightP,5);} //~KeyFld
We don't really care which widget had focus when the character arrived (it was the ball, right?) and we don't care about any of the other possible keys that might be typed. Later you might consider recognizing escape to start a new game (you would override the GotEscKey method for that). Or you can just close the window and start over.

We still need a MovePaddle subroutine (method) to actually move the paddle. We could put the same code in all four places, but that's too much work. Not all programming languages require it, but it's a good habit to put the definition of your variables and subroutines before they are used. This subroutine takes a widget and a number of pixels (negative for up, positive for down) to move it. The paddles are just static rectangles, so there's no velocity; each time you hit the key the paddle moves five pixels in that direction. It's probably a good idea to check for going off-screen -- we did that with the ball, this is the same, except we test before moving too far. Something like this, just above the KeyFld method should do it:

public void MovePaddle(GameWgt whom, int howfar) {
  int posn, vnew, tall, scrn = JavaGame.GameWinTall();
  if (whom==null) return; // always a good idea to validate your data
  posn = whom.GetVposn();
  tall = whom.GetTall(); // we don't need to know how wide it is here
  vnew = posn+howfar; // this is the new position, if valid..
  if (vnew<0) return; // nope, off the top
  if (vnew+tall >= scrn) return; // nope, off the bottom
  whom.SetVposn(vnew);} // otherwise move the paddle to there

This game should now be playable. Try it. Oh wait, I wrote it to respond to capital letters only. You need to set the CapsLock key on the keyboard or it will not notice your keypresses. Or you can add code so that it recognizes either caps or lower case. When I did this, the ball seemed to move too slow. Do you know how to make it go faster? I decided that 8 pixels per frame is much more reasonable.

Part #4: Text Display

There's nothing here for scoring, let's add that. First we think about what it must do (design). If the ball goes off the right edge of the screen, the left player scores, and similarly if it goes off the left, the right player scores. We need a couple text widgets to display the score, and a couple integer variables to hold the current score. Note that the scores are numbers (integers) which we will be incrementing (adding +1), and the text widgets display text, not numbers. These are different data types, but Java (usually) converts readily from numbers to text. Going the other way is slightly harder, so we won't try. GameEngine has a parse function to do that, but we don't need to use it if we keep the scores as integer variables.

Back in GameMaker, we will add a couple text widgets to the board. If you just drag the black text over to the black game board, it will disappear. You can click on its name in the widget list, and the "marching ants" box will show where it is, but there's an easier way to do this. Click on the Text tool to select it, then change the color to white. Double-click the text on the tool and you can change the default "Text" to a zero. [Sorry, the entry dialog doesn't let you select the whole text for retyping, you need to use the backspace key; Real Soon Now.] For a score panel we'd like the numbers to be bigger, so also click the Large radio button and then OK. Now when you drag it to the game board, it's already the right color and size. You  still need to give it a Java-compatible name so your code can access the score. I chose "Lscore" and "Rscore" but you are not limited to my choices. Build it again.

Reopen so we can add code to manage the score. First we need two integer variables declared near the top of the Pong class. They need to be different from the widget names, so I chose "LeftSco" and "RightSco" and initialized them to zero, like this:

  /// (..$) End generated class variables ($)
    int LeftSco = 0, RightSco = 0;
Every time the ball runs off the right end of the game board, the left score is incremented (LeftSco++;) and similarly when it runs off the left end. Do you know where to do that? Right, the same place where we changed the direction of the ball. I left comments there so you can find it.

That counts the score, but it doesn't update the display. To do that you must set the text in the score widgets. First convert the number to text (see "Useful Tech Issues: Data Type Conversion") then set the text of the score widgets, after confirming that the reference is not null:

    if (horz<0) // off the left..
      if (rite<0) {
        rite = -rite;
        if (Rscore != null)
Do you think you can do the same thing for the other direction?

That might work in C (and unfortunately also in Java, where the compiler could but didn't help you to remember there's a result you are discarding, see "Useful Tech Issues: Data Type Conversion"). I always insist on using that result, even if it is only to put it into an otherwise unused variable, I called it "tmp" here:

public boolean Collided(GameWgt whom, GameWgt hitt) {
  int tmp, ball, horz, vert, scrn = JavaGame.GameWinTall();
        if (Rscore != null)
          tmp = Rscore.PutTextLn(JavaGame.CvInt2Str(RightSco));}
        if (Lscore != null)
          tmp = Lscore.PutTextLn(JavaGame.CvInt2Str(LeftSco));}}

Finished! Well, you could add some "English" to the ball if it hits the corner of the paddle. Think of the "corner" as anywhere within about 8 pixels (you already have the ball size, use that) from the end -- if you make the region too narrow, the game will be unplayable: I know, because I made that mistake when I wrote my Tennis game 40 years ago (see "Tennis"). Basically you want to add some vertical velocity, down (increased) if it hits the lower end of the paddle, up (negative) if it hits the upper end. I'll leave that as an exercise. Read up on the sprite velocity in the "Using Widgets" page to get the encoding right.

Part #5: Your Own Game

After you understand Pong, you are ready to start on something else, perhaps a little harder. There are three programs (two of them games, all using the GameEngine) with instructive commentary listed at the bottom of the introduction to Event-Driven Software.

After you have mastered one or more of these tutorials, you might be ready to define your own game. First and most important, think about what you want it to look like, and more important what it will do. Keep it simple, and talk your idea over with the instructor(s). They will know if it's too hard to finish in the time you have. We are working on getting some resources up to help you do this by the time you are ready to start.

It's all up to you...

You might start by reading the GameEngine web page for a better understanding of how it works.

Tom Pittman
Rev: 2022 November 18