By Mikey Walters / May 15, 2017
This is the sixth in a series of articles about programming in Atari BASIC. The previous installments are here. Space Assault source code and references can be found here. BAS files for use with Atari emulators of the original program and enhanced program can be found here.
240 PRINT “Targeting Computer”
In Lesson Five, we learned about Space Assault’s “main loop” and how game events quickly occur in succession to give the appearance of happening simultaneously. We also handled the actions of our human player, such as moving the crosshair via joystick and firing the Fission Gun Tower. Now it’s time to give the Clovis Aliens their due, so let’s code their relentless, earthshaking attack!
The first subroutine we’ll examine is called each time an enemy ship is needed, such as when the game begins after initialization, or when a ship is destroyed by the Fission Gun Tower or moves horizontally off the screen.
First we set the SHIP variable to a random number between 1 and 3, which will select either a Combat Saucer, Devastation Satellite, or Purple Marauder, respectively (line 1280). Next we set the DIR variable to a random direction, either 1 for left to right or 2 for right to left (line 1290). Our next task is to determine the starting position of the enemy ship. We set the YSHIP variable to a random “altitude” or vertical coordinate between 15 and 50, since the alien ships fly across the upper half of our playfield, and set the XSHIP variable to either the far left (20) or far right (210) depending on the direction the ship will be flying (lines 1310-1320). Finally, we use the SOUND statement to begin a ship-specific background noise. (We’ll cover sound generation with Atari BASIC in our next lesson.) The last thing our subroutine does is call another subroutine to determine which base will be the ship’s target.
We begin by generating a random number between 1 and 7, since there are seven Vegetation Processing Plants (VPPs), or bases. Then we use that number as an index into the BUILDING array and store that value in the TARGET variable (line 1240). The BUILDING array was set up during initialization, and it stores the horizontal coordinate of each of our seven bases that we drew way back in Lesson Two. After a base has been selected, TARGET will be set to the horizontal position of the base that the current enemy ship is attempting to reach—if the human player doesn’t shoot it down first.
As we’ll see later, after a base has been destroyed, we change the number in the appropriate index of BUILDING to 999 to signify the base is out of commission. When we’re selecting a new target, we need to be sure not to choose a base that has already been destroyed. If our random selection turns out to be a destroyed base, we simply try again (line 1250). As the game progresses and there are fewer bases left as valid targets, this could take several tries. Theoretically, this code could get “stuck” if the random number generator continues to choose destroyed bases, but in practice this never happens. Eventually TARGET will be set to a coordinate that is not 999, and the enemy ship will have an unlucky base as its objective.
Our “Random Ship” subroutine is able to call our “Random Target” subroutine since the GOSUB and RETURN statements support any number of “levels” of code calling other code. In other words, each RETURN statement knows to go back to the previous GOSUB statement that actually called the subroutine. When subroutines call other subroutines, the Atari BASIC interpreter can remember which RETURN goes with which GOSUB by using a common data structure called a stack, which is a general purpose “last in, first out” mechanism. Each time a GOSUB jumps to a subroutine, the location of the executing code is pushed onto the stack, and each time a RETURN is encountered, the location to jump back is popped from the stack. The use of GOSUB and RETURN allows a programmer to structure code into small, manageable blocks that call each other as needed, with very little code duplication. Although the BASIC language was famously criticized for its unstructured nature, it’s still possible to write structured code with some forethought by an organized programmer.
250 PRINT “Aliens on the Move”
As you’ll see from taking a look at Space Assault in action, enemy ships travel horizontally high above our bases, randomly moving up and down to make them difficult to hit with the Fission Gun Tower. To accomplish this, the main loop calls the “Move Enemy Ships” subroutine each time through the loop.
First, we randomly decide if the enemy ship should move up, down, or stay at the same altitude using the ON-GOTO statement. This handy function allows us to jump to different lines of code based on a number, essentially combining several IF-THEN-GOTO statements into one line of code. So, based on a random number between 1 and 3, we can skip over one or more of the next lines of code (line 1100). If the random number is 1, YSHIP is increased so the enemy ship moves down. If the random number is 2, YSHIP is decreased so the enemy ship moves up. And if the random number if 3, then these lines are completely skipped, so the value of YSHIP does not change.
Next, we enforce vertical boundaries to be sure the enemy ship doesn’t fly too high (and disappear from the visible playfield) or too low, so it will stay above the bases and our starry sky (lines 1130-1140). This check is similar to the way we enforced boundaries on crosshair movement in Lesson Five. After that, we increase or decrease the horizontal position in the XSHIP variable depending on the direction the enemy ship is traveling (lines 1150-1160). Now that the new horizontal and vertical coordinates of the ship are known, we use the machine language Player/Missile movement routine discussed in Lesson Four to position the enemy ship in the correct location, depending on the type of enemy ship attacking, with code stored in SHIP (lines 1170-1190).
You’ll notice that enemy ships move in increments of three, and, if you remember from Lesson Five, the crosshair moves in increments of four. This was done to give the human player a slight edge against the aliens, so the crosshair has a chance of “catching up” when chasing an enemy ship across the playfield.
After the enemy ship has moved, there are two more checks to make. If an enemy ship reaches the extreme left or right of the playfield, then the ship has managed to fly by without being hit and we need to get a new enemy ship underway by calling our “Random Ship” subroutine (line 1200). And, unfortunately for the human player, the final check is to see if the enemy has reached its predetermined target. Since Player/Missile coordinates are somewhat different from the playfield coordinates stored in the BUILDING array and the TARGET variable, and also because enemy ship movement is made in increments of three, XSHIP is checked to see if it falls within a five-pixel range of TARGET, which handles the coordinate conversion. If XSHIP is close enough to TARGET, we call a subroutine that will handle the alien fire and destruction of a base. After all of this, we RETURN to the main loop where the game proceeds with crosshair movement, and so on, over and over.
All of this relatively simple logic actually gives the aliens the appearance of intelligence. They switch up their direction of flight to confuse the human player, and even make evasive maneuvers that seem to avoid the crosshair. Each enemy ship has an objective in mind which is unknown to the player, making it difficult to predict where they will strike. And of course, the enemy is smart enough to know not to attack a base that has already been destroyed.
260 PRINT “Earthshaking Destruction”
When an enemy reaches its predetermined target without being hit by the Fusion Gun Tower, it’s time for the alien ship to open fire! This action is handled by the “Destroy VPP” (Vegetation Processing Plant) subroutine.
The first step is to fire the alien laser from our enemy ship down to the base below. After selecting our purple color, we start at the horizontal TARGET coordinate and the vertical YSHIP (minus 10 for Player/Missile graphics to playfield graphics conversion) and draw directly down to the base (line 1820). Then we use two nested FOR loops and the SOUND statement to create five dramatic laser sound effects (line 1830), and then erase the laser we drew by drawing it again with the background color (line 1840). This “draw and erase” technique is the same way we handled the blast from the Fusion Gun Tower is Lesson Five.
The firepower of the Clovis aliens is so intense that it shakes the surface of the planet Kala, so the next few lines of code use an interesting technique to simulate an earthquake, which was my favorite part of the program back when I wrote Space Assault as a 16-year-old. After a little research, I’m almost certain I discovered this method in Games for the Atari (1983), a pretty obscure book by Winfried Hofacker that was part of my fairly extensive programming library.
The first task is determining where in memory the Atari is storing a description of the contents of the screen, which is called a display list. We’ll learn much more about display lists in a future lesson, but for now just think of it as a list of commands that the ANTIC chip uses to handle playfield graphics. The memory location containing the start of the display list can be found by peeking into registers 560 and 561 and applying a formula to translate two 8-bit numbers into a 16-bit address, which we call SCR (for screen). We then PEEK that location, which gives us the actual location of the display list, and keep it in the variable B for use later (line 1850).
The magic happens in the next line of code, but first we need to know about the handy register 53770, which returns a random number between 0 and 255 every time it’s PEEKed. We could certainly use the RND statement we have seen before for this purpose, but PEEKing this register is actually faster. In this case, we divide the random number by 200, which gives us a random number between 0 and 1, and we add this to the B variable and POKE this back into the SCR variable that stores the location of the display list. When the ANTIC chip refreshes the playfield, it sees that the display list has changed by just a few bytes, so it dutifully “shifts” the entire screen a few pixels. This happens quickly 50 times in a FOR loop, along with some rumbling sound effects, and creates a convincing earthquake effect.
Once the earthquake is over, we need to reduce our base to rubble. This is done by using our background color to draw vertical lines of random length across the entire base that we worked so hard to draw back in Lesson Two. Since TARGET contains the horizontal coordinate of the middle of the base, we loop from TARGET minus 5 to TARGET plus 5 and draw from the top of the base down to nearly the bottom, randomly stopping up to 5 pixels short, which makes the remains of the base look like rubble (line 1870). Of course, this is also accompanied by more sound effects.
To finish off the effect, we strobe the background color by using SETCOLOR to quickly switch between white and black again just as we did for the alien ship explosion in Lesson Five (line 1880), and finally we stop the sound effects and restore the value of SCR back to the original value B, since we want to be sure the screen doesn’t remain shifted depending on how our earthquake ended.
The last few lines of this subroutine keep track of destroyed bases and the game’s progress. First we increment the HITS variable (line 1900). If HITS reaches 7, we know all bases have been destroyed, so we turn off the alien background sound, pause a moment in a short FOR loop, POKE all of the Player/Missile horizontal location registers with 0 to be sure all players are offscreen, and then jump to our “Game Over” code (line 1910), which we’ll discuss in a future lesson. If HITS is less than 7, we change the number in the BUILDING array to 999 for the base that was just destroyed, which prevents the aliens from targeting it again, and then call our “Get Random Target” subroutine again to start the next round of attacks.
270 PRINT “Raising Shields”
This lesson’s variations on the original code add a completely new element to Space Assault. Each base now has an invisible shield that can protect it against a single alien attack, essentially making it necessary for the aliens to hit each base twice before it’s destroyed. Keeping the shields invisible (until they are hit) adds a bit of suspense to the gameplay, and certainly makes it possible to achieve higher scores. This new feature slightly modifies several sections of the original code, but I’ll only cover the major changes here.
In addition to the BUILDING array we’ve already discussed, I’ve added a SHIELD array to keep track of which shields are active using simple flags (1 for active, 0 for non-active). When the enemy ship has reached its target, we use the SHIELD array with an ON-GOSUB statement (similar to the ON-GOTO statement covered above). If the shield is non-active, we call our “Destroy VPP” subroutine; but if the shield is active, we call the new “Shield” subroutine (line 1210).
Our goal for this subroutine is to cause a glowing shield to appear over the base to stop the alien fire. This is done by repurposing the crosshair (player 0), since the human player can’t move the crosshair during an alien attack anyway. I’ve initialized a simple “arc” shaped player image using what we learned in Lesson Three and stored the address of the player image string in the variable PMS (Player/Missile Shield). Now we can use our machine language Player/Missile movement routine to move player 0 over the base, but instead use PMS for the image (line 3020). This makes the crosshair disappear during the shield effect since a player can’t be two places at the same time, but I think the effect is worth it. We also use our random number register 53770 to quickly change the color of the shield player, which adds a wonderful glowing effect (line 3040).
After the shield is used, we change the appropriate flag in the SHIELD array, get a new target for the enemy, and gameplay proceeds as usual. Adding this new feature was relatively easy and didn’t require much code, as you can see, reminding me of the power of Atari BASIC and the joy of tweaking code to continuously evolve a game into something more fun and interesting.
We’ve now covered all of Space Assault’s “action code,” but there’s still more to learn. Next time, we’ll build the title screen and finally explore the sound capabilities of Atari home computers with exciting effects and even music!
Mikey Walters lives in Austin, Texas, and has an entire room devoted to toys, including Mego figures, Japanese kaiju, and over 1,000 PEZ dispensers. He spends his time thinking about how great it is to be a geek who grew up in the 1970s.
Pingback: Adventures in Atari BASIC: Lesson Seven – Music and Mission Briefings
Hello,
I’ve been following along with this adventure using an Atari 800. However, I keep getting Error 9 at Line 1240, which to the best of my (very limited!) knowledge has to do with a string error. I’ve tried to learn Basic many, many times in my life. This is the closest I’ve come to understanding what’s really going on, thanks to your website, but I am still very much stuck. Do you have any suggestions?
Thanks very much,
Pete