<<Previous | ToC | Next >>
This page lists some ideas that you might program in GameEngine. You may have other ideas -- Tell us! -- if we think you can do it in the time you have, we'll add it to the list.
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.
More important, we want you to succeed, so we will insist that you think hard about how your game needs to work, and write your Design down, and then follow your Design. This is so important, you will not receive any credit for working on this game unless you do that.
Not to worry, we want you to succeed. If you have trouble organizing your thoughts into a coherent Design, a Mentor will work with you. If you can code to the Design, you will be a competent programmer anybody will want to hire, and you can make lots of money and have lots of fun doing it. After you learn to create a good Design without our help, you can be the Lead Programmer and make even more money
The game ideas below are mostly things you can do in the GameEngine.
We recently learned that Replit is throttling larger programs like the
GameEngine (they want you to pay extra to make your program run faster),
so if sitting around waiting for the little circle to spin isn't your bag,
we are also trying to get some text-only options up too. The first of these
is a game where you play the king of a mythical country. I wrote a "tiny"
version so long ago, I can't remember how all the details work, but much
later I learned that the original program is called "Hammurabi" and it's
available in Basic on the internet. Jaxon Simmons reverse-engineered it,
which you can work from, here. Isaac Perkins
did a variation on the ancient text Adventure game, which you can work
from, here.
Squares Falling from the Sky
Tic-Tac-Toe
Snake
Tetris
Card Games
GameWgt myNewWgt = myGame.NewGameWgt(-1,top,left, 0,0,0, color,velo, null,BaseSquare);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.
GameWgt parentWgt = JavaGame.GetIxWgt(BaseSquare.GetParent());
parentWgt.AddElemt(myNewWgt.GetRefNum());
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 same parent.
If you want them to pile up or otherwise hang around, you can make new widgets on the fly.
Design First
This is an easy game to start with. Think about what you want to do, then build your Design and get it approved.
The advantage is that (unlike the other programs in this page) everything is explained here, and it's pretty impressive to show off, especially when you do it in the Game Engine -- but you can also do it in ASCII graphics or even in English!
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.
Design First
I think this is a mid-level game, the simple (all squares) version is not too hard to start with and it gives you an opportunity to learn an important FIFO data structure. Think about what you want to do, then build your Design and get it approved.
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;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).
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++;} //~Add2FrontGameWgt GetFromBack() {
int there = back;
if (back==front) return null; // nothing there
back++; // gotta do this before exit
return myAry[there&(maxQ-1)];} //~GetFromBack
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
a term project.
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).
Design First
Managing the tetronimos is rather tricky, you might want to save this for a second game. Think about what you want to do, then build your Design and get it approved.
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
Design First
We suggest you decide on a card game that is not too complicated, and then focus first on letting the computer keep score while humans play the game. After you get that working, you might consider how to have the computer play one side, but that is pretty hard, don't even try until the scorekeeping is working well. Think about what you want to do, then build your Design and get it approved.
The 52 cards can be numbered sequentially (0 to 51, or if you include
jokers, to 52 or 53), then the card number (1 for ace, 11 for jack, etc)
and the suit are fixed static attributes of that card number, so the undealt
deck and each player's hand (and any discard piles, if significant) are
simple arrays of numbers. No complicated data structures are needed. The
52 images can be kept in an array of GameWgt (if you use complicated
icons) or a String[] array of card names if you are doing an ASCII
(text) version.
The number of the card (1to 13 with 0=joker) and suit are easily extracted by any of several simple algorithms. If you number the suits alphabetically (as defined for most games) or switch diamond to be lowest so that the colors alternate in the sequence (the other common ranking, which is useful when alternating colors is desirable: odd is black, even is red) then you have a single number (1 to 4, or computationally simpler 0 to 3) for the suit and another simple integer (1 to 13, or 0 to 13 including jokers) and a simple multiply-add (number*4+suit) gives you the card number (offset by +2 or +4, which is easily subtracted). Going the other way is fast and simple (see Bit Operations and Packed Numbers), or if the math is too intimidating, maintain a final (constant) 53-element array for each attribute you want to extract (name, number, suit). Don't let the OOPS bigots persuade you to build some fancy class structure for the cards, all it does is add extra unnecessary code and complexity and execution time to the simplest part of your game.
Shuffling the deck is probably the least obvious thing you need to do, so there are a zillion websites eager to tell you how. The best will make 52 calls on Random to pick a card number to exchange the next card with. Some suggest making a second array, but every time you use new to create an array or object, it uses more system resources than almost anything you could do with inline code, perhaps even worse than a bubble* sort. For a card game that extra time is probably smaller than the impatience factor in the human players, but it's a bad habit to get into -- unless of course the data structure is absolutely essential for the game (or other application) you are designing.
* Bubble Sort -- During the 2008 Presidential campaign Obama made a campaign stop at Google, and during the Q&A session, some shill in the audience asked "What is the most efficient way to sort a million 32-bit integers?" To which the politician was obviously prepped to reply "I think the bubble sort would be the wrong way to go." You can Google a video of the exchange, or why the bubble sort is generally considered the worst possible sort (except for less than a few dozen elements it's far simpler, and therefore faster than the others).
The Bubble Sort is simple enough to understand: run through the array
in order, exchanging every pair that is out of order, repeating until no
exchanges happen. In the worst case it's slightly under N2
exchanges; the theoretical best is NlogN. For a million elements
NlogN is 20 million exchanges (compared to almost a trillion); for
32 elements it's 160 compared to 475, still a 3x difference, but partly
compensated by less code per exchange (and far less programming time to
get it right).
<<Previous | ToC | Next >>
Revised: 2023 May 3