Some Java Game Ideas


<<Previous | ToC | Next >>

This is a list of some ideas that you might program in GameEngine. We don't tell you how to write your code, you do that! But we do give you some implementation details that might be helpful.

Game Ideas

Squares Falling from the Sky
Tetris
Snake

New Widgets

Several of these games require new game elements appearing throughout the game. Probably the easy way to do this is have one of each kind of widget you want to create on the fly, then use it as a prototype you send to the NewGameWgt method to clone. Say you made a square widget named "BaseSquare" in GameMaker. Then when your game requires a new square like it, do something like this:
GameWgt myNewWgt = myGame.NewGameWgt(-1,top,left, 0,0,0, color,velo, null,BaseSquare);
GameWgt parentWgt = JavaGame.GetIxWgt(BaseSquare.GetParent());
parentWgt.AddElemt(myNewWgt.GetRefNum());
where top and left are the position of the new widget, color and velo are the new color and (packed) velocity to use, or 0 if you want the same. If your BaseSquare is hidden, the new widget will become visible when you give it a new vertical position top.

The first line creates a clone widget, but it will not be drawn on the game board unless it is in the widget hierarchy from the game board. The second line there finds who is the parent of the BaseSquare, and the third line adds your new widget as a child of that parent.
 

Squares Falling from the Sky

(Sorry, no graphic) Most of what you learned in Pong can be used in this game. Instead of a ball moving back and forth, you have individual colored squares falling from the top (like the Pong ball, only they are square, use the "SkyRec" tool), and the paddle on the bottom that you can slide left or right to catch (or miss) the falling squares. If you have only a small number of squares visible at a time, create them all in GameMaker and hide the ones you are not using.

If you want them to pile up or otherwise hang around, you can make new widgets on the fly.

Tetris

You might want to Google this name for the rules, but the basic idea is that you have these "tetronimos" (4-square shapes) falling from the sky and sticking to the ground or whatever previous shapes they bump into. I would do one falling tetronimo by ganging together four SkyRec widgets with a fixed downward velocity until they Bump into the board edge or a fixed tetronimo square. Once it stops, replace the tetronimo sprite widgets with four simple squares the same color (created on the fly), the re-use the sprite widgets for a new falling tetronimo, a new color.

The rules for shifting or rotating the falling tetronimo are a little complicated, but not insurmountable.

Because Tetris is a fixed game board size, another way to do it is to hand-edit a list of square widgets for every possible square position on the board (two or three hundred at most, see "Widget Specification Text"). This has actually been tried and is known to work, and has the advantage of working in the first versions of JavaScript (when it becomes available).
 

Your Own Sprites

The GameEngine has a Sprite widget type, but it is not (yet) fully supported in the GameMaker edit window. You can use what you have by creating (for example) a Ball sprite in GameMaker, then adding components to it in your Startup code. If you want fancy shapes, you can replace the pixel map of the ball with a pattern of your own choosing. Alternatively, you can hide the circle and add rectangles of whatever sizes and colors you need. Be sure to set the sprite size big enough to show them, and make it the parent of any subwidgets you add.

Assume that you created a Ball sprite in GameMaker named "Tsprite" and two rectangles "Rone" and "Rtwo", here's the Java code to turn them into the purple "L" Tetris sprite in the image above:

int sRfNo = Tsprite.GetRefNum(), // the sprite refnum
    tmpint = Tsprite.AddElemt(Rone.GetRefNum())+Tsprite.AddElemt(Rtwo.GetRefNum());
GameWgt tmpWgt = JavaGame.GetIxWgt(Tsprite.GetIxData(0,0)); // gets the circle icon
if (tmpWgt != null) tmpWgt.HideSho(false); // hide it
Rone.SetParent(sRfNo);
Rtwo.SetParent(sRfNo);
Rone.SetPosn(0,0); // position relative to sprite
Rtwo.SetPosn(20,0);
Rone.SetSize(20,10); // assume 10x10 grid..
Rtwo.SetSize(10,20);
Rone.SetColor(0x9900FF); // = purple
Rtwo.SetColor(0x9900FF);
Tsprite.SetSize(40,40); // big enough for any tetronimo inside


Snake

I think the original version of this just adds colored squares to the board attached to the previous "head" in the direction of the arrow key most recently pressed. Look up the rules online, I don't think this is too hard for the time we have.

I sometimes tell people "I write games, I don't play them," but this one I think bit me. It is rumored (like I wouldn't know) that the snake doesn't grow past some defined length, which means that most of the time the squares on the tail are disappearing as fast as they are added at the head. The only way you can know what square to erase is to memorize the whole snake in some kind of array, then effectively slide the widgets from the front to the tail, where they are deleted. This is separate from hiding the squares on the board, but the widget reference in this array tells you which widget to erase next.

First-In-First-Out

The data structure you need to save this information in is called a FIFO (First-In, First-Out) queue, and the most efficient (minimal moving the data around) way to do it is called a "circular" buffer, which is an array with two index pointers, one indicating where the next entry is added (that would be the head of your snake), and the other indicating where to delete (at the tail). When either pointer reaches the end of the array, it is effectively restarted at the front. The usual way to do this is to make the length of the array a power of two so you can use the & operator (which is faster than the modulus = remainder operator % on most hardware) to trim the current count to the size of the buffer. If this is an array of widgets, then when you pop off the tail widget, you know everything you need to know to hide the widget (= shorten the tail).

The approved way to do this is with its own class, but for something this small, you can just put these two methods and three variables in your code where they will be used. You need to decide what's the longest your snake needs to grow, then allocate an array to accommodate it. For example, if you decide you want snakes to grow to the full  size of a 20x20 game board, you would need 20*20=400 units in your array, rounded up to the next power of two = 512.

final int maxQ = 512;
int front = 0, back = 0;
GameWgt[] theQ = new GameWgt[maxQ];

void Add2Front(GameWgt me) {
  if (front==back+maxQ) CrashAndBurn(); // array is full (do whatever you need to do)
  myAry[front&(maxQ-1)] = me;
  front++;} //~Add2Front

GameWgt GetFromBack() {
  int there = back;
  if (back==front) return null; // nothing there
  back++; // gotta do this before exit
  return myAry[there&(maxQ-1)];} //~GetFromBack

Then when you  add a widget whom to the front of your snake, you also call Add2Front(whom); and when the snake has grown long enough, you call  GetFromBack().HideSho(false);  Of course these little snippets are incomplete, you need to count the number of widgets inside your snake, and maybe do something with the widget you took off the back (besides hide it).

One version of snake I saw had a rounded head and tail that moved as a unit, and it got longer only as it ate apples. You could overlap Ball widgets for the head and tail with square "SkyRec" widgets for the body, all moving the same speed. Turning corners would require another Ball widget stopped on the corner. This is pretty tricky, and probably too hard for the summer workshop, but you can keep working on it after the workshop is over. I (Tom Pittman) would be available to answer questions by email if you decide to do this.
 

Others TBA


<<Previous | ToC | Next >>

Revised: 2021 September 21