Pong was exciting when it came out back in 1972 but it hasn’t aged very well. By modern standards it’s kind of boring. Luckily in microM8 we can do two things to improve it: first, we can render the graphics as cubes and move the OpenGL camera around. Second, we can automate this independently by using a “control program” which executes in a parallel instance of a customised Applesoft BASIC interpreter. Using those features we can do something like this:
By “spinning” the playfield we can make it a little more interesting (and challenging), and we can do it without changing any code in the original Integer BASIC Pong program.
The control program is doing all the work here. Line 10 tells the program to “redirect” all @ functions (special additional microM8 functions, which are prefixed with @ to maintain compatibility since Applesoft and Integer BASIC cannot distinguish between commands and variables with the same prefixes.) Line 11 resets the camera (in case it’s already been moved somewhere) and Line 12 zooms in the camera and puts it in a slightly offset position.
The remaining lines contain the a loop which rotates the camera around the playfield. It uses the absolute @CAMERA.ORBIT function to position the camera based on a FOR/NEXT loop. The first parameter varies the vertical position slightly (using B) while the second specifies the horizontal position, which is specified in degrees by A. Also, every time it loops completely around, the time it takes to do it is increased or decreased to vary the speed of the rotation and add some variation to the movement. This is done by varying the P value specified to @SYSTEM.PAUSE. Q is used to toggle whether P is being increased or decreased.
This action repeats forever.
But that’s very repetitive and passive. What if we turned the Pong playfield on its side and then flipped perspective from one player to the other whenever the ball changed direction? This would place the paddle currently attempting to deflect the ball at the bottom of the screen. But we couldn’t just use a passive control program to accomplish this, because it would need to be aware of what was going on inside of the running Pong game. What we can do is use memory locations to communicate between the Pong program and the control program.
First we need to put some triggers into the original Pong code. Line 5 POKEs a 1 into memory address 37002 to indicate the program has (re)started (so that we can ensure the control program returns the camera back to its starting position). Line 10 clears the memory locations we’re going to use to signal which direction the ball is travelling in. 37000 indicates which direction the ball is travelling during play, and 370001 indicates which direction it’s moving in first (so we know which player’s paddle to position at the bottom of the screen.)
Line 28 clears the starting indicator address and at line 50 the program jumps to 3000, which is the subroutine that moves the ball.
We need to make a couple of changes in the subroutine at 3000 to set the indicator at 37000 whenever the ball changed direction, by using two IF statements at 3025 and 3026. Those are all the changes we need to make in order for the control program to work – now we just have to write it.
This control program is pretty well documented. When @VM.REDIRECT is in force, the BASIC PEEK command (or @MEM.PEEK) can be used to read memory locations in the target “virtual machine” – in this case the executing Pong game. Unlike the “spinner” control program, which used @CAMERA.ORBIT, this control program uses @CAMERA.ROTATE, which is relative and moves the camera incrementally. @CAMERA.MOVE shifts the camera’s location arbitrarily relative to its position, and not around a central point the way @CAMERA.ROTATE and @CAMERA.ORBIT do. Line 45 checks to see if the Pong game has reset, and if so resets the control program.
Lines 50-65 add an additional “sway” to the camera movement when the playfield is not being flipped, to keep the scene moving. Line 70 changes the colour used by the ball (index 2) randomly – this would change the colour of all pixels set while COLOR=2 but in the case of the Pong game that’s only the ball.
The flip routine at 3000 splits the overall “flip” into a thousand smaller movements in order to create a smooth, fluid action. We also move the camera slightly up or down so that the 3D model stays towards the top of the screen (if we didn’t, it would “flip” toward the bottom).
The rest of the control program. The subroutine at 4000 does the same as the subroutine at 3000, just in reverse. The subroutine at 5000 “walks back” the sway to the centre before executing a flip (because if we didn’t do that there would be a gradual offset created every time a flip occurred.)
To package the combined game and control program for distribution, we place them inside a microPAK file:
We create a microPAK file by pressing shift-control-P while the primary program or disk to be executed is highlighted in the microM8 File Manager. Inside the PAK file are a number of configuration files which can be edited to provide all sorts of customisation, but we’re using a control program and so we’re not concerned with them at present. We paste in our control program (control.apl), and then to execute both the pongflip.int program and the control program we just select the pak file in the file manager thusly:
As you can see from this example, microM8’s ability to execute parallel code that can communicate and act upon the environment of another program can be quite powerful, and has all kinds of potential.
You can find the pongflipper (and the pongspinner) microPAK file(s) in the micropaks folder at the root of the microM8 File Manager (accessible at any time using shift-control-~) Copy it to your local directory and play around with it (you can venture inside the PAK file by using control-shift-O(pen).
Let us know what you come up with!
You can download microM8 from its download page. There are versions for Windows, macOS and Linux.