Welcome to Atari 7800 Basic Make-a-Thing lesson
Yes, I’m back.
Look at me.
That intro was done 2 years ago, and I look 10 years older now.
So, I guess I will have to do something about that.
Here is my new Youtube hat!
This is my new look, for better or worse.
Now I feel like I can continue
You might notice that these new videos look different than the ones from the first 3 lessons. That is because, back in 2023, a hard drive crash destroyed most of the support material I used to create these lessons.
When I tried to look at videos they were all corrupted.
So I had to start over from scratch.
So now, I’m getting back on track and starting again from scratch.
Thanks for your patience, I know it’s been a long time.
See lessons 1-3 here:
Atari 7800 Basic Lessons 1-3 – Generation Atari
See the GithubRepo Here:
makeathing/Atari7800/Atari7800Basic/Tutorial at main · intotheverticalblank/makeathing · GitHub
Introduction
First, a bit of an update.
In the last lesson I mentioned that one of my long suffering unfinished games did not have a title screen. That game is Last stand Halloween which was last updated in 2020. Well, after saying that, I went ahead and made a title screen for it, and also tweaked the game a tiny bit. It’s still a failed game, but at least I’m pleased with the title screen now.
You can a link to it in the notes, or if you are reading the on the web site, click this link below:
Last Stand Halloween : Holiday Nightmare by Into The Vertical Blank
Part 1: Designing The Orb
Okay, So let’s start this lesson with another sprite:
The Orb.
The Orb is the object the UAP needs to collect to open-up the next portal to exit the level.
You have to collect enough of them to power the wormhole, and get out of your Quantum Lay-Over.
Open up the sprite editor and create a new sprite file called “orbs.spe”.
Let’s make the Orbs three colors of blue, and look like spheres they stand-out, against the black background.
Create an 8×8 3+1 color sprite and let’s get moving!
First choose 3 colors of different shades of blue so we can create something that looks a bit 3D.
Now, I am not that good at sprite design, but I’ll try my best.
It takes me sometime to figure out what to do when I’m making sprites, and you will see here that at first I thought I’d make some cool 3D orb in 3 frames of animation.
However, my first attempt was not that great.
So I start over, change colors a bit, and it starts to get a little better (to me anyway).
When I’m done, I copy the sprite and edit it to make it look like it’s rotating.
At some point I decided to make it 5 frames instead of 3 because I think it will look better.
But you know what, I think 6 frames might be better, and maybe we need to make the top and bottom look like they are rotating too.
When I’m done, I save the file as orb.spe and then I export each file as ob1.png -> orb6.spe
We are also going to create a “Portal”.
It will be formed by two 32×16 sprites to create a 32×32 sized portal.
We will create two frames so that it will animate kind of like an old NEON sign.
Save all fours parts as:
portal1_top.png
portal1_bottom.png
portal2_top.png
portal2_bottom.png
Part 2: Put the Orb on the screen
Now load-in the orb sprites.
incgraphic images/orb1.png 160A 0 1 2 3
incgraphic images/orb2.png 160A 0 1 2 3
incgraphic images/orb3.png 160A 0 1 2 3
incgraphic images/orb4.png 160A 0 1 2 3
incgraphic images/orb5.png 160A 0 1 2 3
incgraphic images/orb6.png 160A 0 1 2 3
And then make a similar set of variables like we made for the player to keep track of the orb.: X location, Y location, the current animation frame, and the count we have before the orb animates. This should look very familiar
dim orbX =var9
dim orbY = var10
dim orbAnimFrame = var11
dim orbAnimWait = var12
Now let’s initialize these variables and set the orb to display at 50, 50 on the screen
orbX = 50
orbY = 50
orbAnimFrame = 0
orbAnimWait = 0
Next we will set a color palette for the orb based on the colors we used in the sprite editor.
rem orb colors
P2C1 = $92
P2C2 = $94
P2C3 = $99
We will set the palette #2 to the colors of the orb sprite.
I did this manually instead of pulling the color constants because it appears that the color constants only work for the last sprite loaded.
I’m not sure why this is. I only know that the color constant did not work, so I did it manually.
plotsprite orb1 2 orbX orbY orbAnimFrame
orbAnimWait = orbAnimWait +1
if orbAnimWait > 1 then orbAnimFrame = orbAnimFrame + 1 : orbAnimWait = 0
if orbAnimFrame > 5 then orbAnimFrame = 0
So now we are ready to test.
Compile the code, and it launches. Press the fire button [z] to get through the title screen.
You should see the orb rotating at x,y 50,50
Lesson4_1.78b
But something is wrong. It looks like the colors are swapped in palette.
Let’s move those around a bit.
incgraphic images/orb1.png 160A 0 3 2 1
incgraphic images/orb2.png 160A 0 3 2 1
incgraphic images/orb3.png 160A 0 3 2 1
incgraphic images/orb4.png 160A 0 3 2 1
incgraphic images/orb5.png 160A 0 3 2 1
incgraphic images/orb6.png 160A 0 3 2 1
Now test it again:
Lesson4_2.78b
There we go. If that had not been right, we would have kept trying until we got it.
Part 3: Just How Many Objects Can You Get?
If you use the link to download the Atari 7800 Basic package from Github, you will find a number of sample programs in the /samples folder.
Atari 7800 Basic Github: Releases · 7800-devtools/7800basic (github.com)
One of them is called OneHundredOne which I believe was written by RevEng Mike Saarna.
You will find it in the examples folder.
Go ahead and load the file, then examine the code.
rem ** 101 sprites double-buffered display. This routine and 7800basic can handle
rem ** more, but Maria runs out of DMA time when too many of the sprites drift
rem ** into the same zone. As it stands, this demo intentionally spreads the
rem ** sprites out vertically, to help Maria out.
rem ** Make the rom a 128k cart with ram, b
My version has a .bas extension, so it does not compile correctly.
I needed to change , file extension to .78b before it will compile and run properly.
This is a fun program to examine and execute because it shows over 100 objects moving n an Atari 7800 screen, with little slow-down or corruption.
It’s fascinating to see, and gives us some ideas on how many objects we will get on the screen or UAP.
Part 4: Randomly Place The Orb
We really don’t want the orb to be at 50,50 on the screen, we want it randomly placed.
Here is the code to do that.
Rand will create a random number between 0 and 255.
Of course the Atari 7800 mode A screen is less than 255 x 255, so we must limit the random values so it is placed on the visible screen.
orbX = rand
orbY = rand
if orbX > 151 then orbX = 151
if orbY > 183 then orbY = 183
We also need to actually draw the orb on the screen, which looks alot like how we drew the player
Notice we use the “2” for the palette in the plotsprite command, to match the palette we defined for the orb.
plotsprite orb1 2 orbX orbY orbAnimFrame
orbAnimWait = orbAnimWait +1
if orbAnimWait > 1 then orbAnimFrame = orbAnimFrame + 1 : orbAnimWait = 0
if orbAnimFrame > 5 then orbAnimFrame = 0
(lesson4_3.78b)
Now test this.
Now test it again.
And again.
See that orb is placed “randomly” but since the random number sequence is the same every time, the game is the same every time, so it’s placed in the same place every time. This is not an accident.
Think of a game like River Raid or Pitfall on the Atari 2600
The only way a game like this with seemingly so many levels on the endless river could be shoved into an Atari 2600 cartridge was to make use of some kind of repeated number sequence. David Crane once told me it was a “polynomial sequence” .
He started with random numbers, found a sequence that worked, and then built the game off that sequence. If the sequence was always random, the games would be unpredictable.
However, for our game, we’d like an unpredictable random number.
To this we will use the a “seed” value that will starts the random number generator at an unpredictable place.
dim randomSeed = var13
randomSeed = randomSeed + 1
if randomSeed > 254 then randomSeed = 1
rand = randomSeed
orbX = rand
orbY = rand
if orbX > 151 then orbX = 151
if orbY > 183 then orbY = 183
(lesson4_4.78b)
Now test this version.
And then test it again.
See that by using randomseed, we can achieve our desired result of having the orb placed (somewhat) randomly on the screen each time the program is executed.
Part 5: Pick Up The Orb
So good, we have two independent objects on the screen, but that’s still not a game. To make this game we need those objects to interact.
First, let’s update the score.
First we made a score variable, but we don’t need it so let’s comment that out.
The basic predefined variables in Atari 7800 basic can only hold 0-255, but scores are usually much more than that.
rem dim score = var4
Instead we will use score0, which is a special variable defined by Atari 7800 Basic that can hold a 24-bit value.
Initialize it like this
score0 = 0
The score0 variable is BCD, binary coded decimal, which means it can’t be easily used in operations with other Atari 7800 variables. But we CAN add numbers to it, which we will do when we test a collision
We will print the score on the screen using the plotvalue function
plotvalue command which lets you plot numeric variables as text
One this thing that is tricky about plotvalue the 4th parameters, which in his example is “6”. That is the number of characters to print on the screen. In general, since score0 is 24-bit number, I always just print all 6 numbers.
plotvalue font 1 score0 6 124 0
Recall that when we set up this game we added this line of code:
set plotvalueonscreen on
This directive allows numeric values to be displayed on an Atari 7800 Basic game screen.
Now we will create a new subroutine named _randomOrb and use that function to create the new orb every time we need it.
gosub _randomOrb
It looks just like the code we’ve a;ready made, but now it’s reusable!
_randomOrb
orbX = rand
orbY = rand
if orbX > 151 then orbX = 151
if orbY > 183 then orbY = 183
return
Okay, now we are ready to test to see if objects collide.
The simplest and easiest way to do this in Atari 7800 basic is by using boxcollision.
This function tests to see if the bounding box of each object is overlapping, and if so, it returns a positive value.
Of course box collisions are not always the best and most efficient way to perform collision detection, but they will work fine for our game.
boxcollision has 8 parameters:
- The X,Y location of the player
- The width and height of the player
- The X,Y location of the orb
- The width and height of the orb.
We will also make another new subroutine named _testCollisions
gosub _testCollisions
This call will come right before we plot the score on the screen in the gameLoop routine.
In our code, if we test a collision between the orb and the UAP, we will simply create new random values for orbX and orbY, and keep going.
In this subroutine, we use boxcollision to test the collision between the player and the orb.
If we detect a collision, we will add 10 to score 0 and call _randomOrb
If not we will use a goto (shock!) to skip this code
_testCollisions
if boxcollision(playerX, playerY, 16, 16, orbX, orbY, 8, 8) then goto _doCollide
goto _skipCollide
_doCollide
score0 = score0 + 10
gosub _randomOrb
_skipCollide
Now let’s test this version and see what we have.
You can collect random orbs all day and wrack up your score!
(Lesson4_5.78b)
Part 6: Managing A Lot Of Sprites
So now I know you are saying to yourself, “sure, one collectible seems simple, but what about having 32 all, zipping around the screen. at the same time?
How do you manage that?
Well, honestly, in a very similar way.
Display and move 32 orbs
(lesson4_6.78b)
First let’s comment out this code that defines the variables for the single orb we randomly placed on the screen. We will not need them any more.
rem dim orbX =var9
rem dim orbY = var10
rem dim orbAnimFrame = var11
rem dim orbAnimWait = var12
Instead we will create a set of variables to hold temp values that we will use in our code.
dim tempX =var9
dim tempY = var10
dim tempAnimFrame = var11
dim tempAnimWait = var12
We will also create a few new variables.
First and X ands Y velocity variables to hold the current speed of the orbs so we can move them around the screen.
dim tempXVelocity = var13
dim tempYVelocity = var14
And also a maxOrbs variable that will limit the number if orbs on the screen on level
dim maxOrbs = var16
Now comes the interesting part.
We need to define the space to hold the data for our orbs.
We want to have a lot of orbs to collect.
Let’s say we want 32 orbs, each one with separate X,Y location, X,Y velocity, animation variables, and a variable to track if it has been collected or not.
If we use one byte for each of these values that would be 256 variables!
But we only have 126 predefined single byte variables in Atari 7800 Basic, so how on earth will we track up to 32 orbs like this?
Well, besides the 126 predefined variables, the Atari 7800 also has about 1.5K of usable memory for a game. We can make use of this memory to store the values for the orbs.
This memory starts at $2200 and ends at $27FF.
(You can also access an additional 16K of memory, if available in the memory map.)
We start by writing dim orbX = $2200
This defines the variable orbX to the memory location $2200
We then count 32 bytes (in HEX not decimal)
Then define the next variable as dim orbY = $2220
And so on with orbXVelocity, orbYVelocity, orbAminFrame, orbAnimWait, and orbCaptured.
Each time counting 32 in HEX from the last variable location for the next one.
rem orbs space for 32
dim orbX = $2200
dim orbY = $2220
dim orbXVelocity = $2240
dim orbYVelocity = $2260
dim orbAnimFrame = $2280
dim orbAnimWait = $22A0
dim orbCaptured = $22C0
We have now effectively defined the space for all the data we need to hold the orb data.
Now what stops you from defining the variable wrong, counting by HEX wrong, or defining other variables on top of these?
NOTHING.
You need to keep track of all of that yourself.
So be careful.
Now we initialize all the temp variables to 0.
tempOrbX = 0
tempOrbY = 0
tempOrbAnimFrame = 0
tempOrbAnimWait = 0
tempOrbXVelocity = 0
tempOrbYVelocity = 0
Next, in the _initGame function we will set maxObs to 32 so we can draw 32 orbs on the screen.Then we will create all the orbs to display by calling the new makeOrbs subroutine (that does not exist yet)
_initGame
. . .
maxOrbs = 32
. . .
gosub makeOrbs
So let’s make the makeOrbs routine.
This is the heart of the solution to tracking up to 32 orbs at once.
First we create a for:next loop that counts up the number of orb in maxOrbs (minus one because we start at 0).
Then we use rand to get random numbers between 0 and 255.
We use these values so that some of the orbs start off the visible screen.
We place those random numbers in orbX[i] and orbY[i] .
The [i] after the variable is array notation for index of the array.
We use it to access all those spaces in memory we skipped when we defined these variables.
That means each one of those variables will hold the data for all orbs, accessed by this [i] index notation.
That makes orbX and orbY parallel arrays.
Since we can’t easily define structs or objects in memory in 7800 Basic, we can instead use parallel arrays, which will make working with large sets of similar on-screen objects much easier..
rem ************************************
rem * fill up orbs to display
rem ************************************
makeOrbs
m = maxOrbs – 1
for i = 0 to m
orbX[i] = rand
orbY[i] = rand
Now we will set some random velocities for the orbs so they will start by moving in different directions on the screen. The values between -1 and 1 are the number of pixels the orb will move in the X or Y direction on each frame. This means orbs will move in 8 different directions.
We also set orbAnimFrame, orbAnimWait and orbCaptured to zero.
r = rand
if r < 255 then orbXVelocity[i] = 0 : orbYVelocity[i] = -1
if r < 228 then orbXVelocity[i] = 1 : orbYVelocity[i] = -1
if r < 196 then orbXVelocity[i] = 1 : orbYVelocity[i] = 0
if r < 164 then orbXVelocity[i] = 1 : orbYVelocity[i] = 1
if r < 128 then orbXVelocity[i] = 0 : orbYVelocity[i] = 1
if r < 96 then orbXVelocity[i] = -1 : orbYVelocity[i] = 1
if r < 64 then orbXVelocity[i] = -1 : orbYVelocity[i] = 0
if r < 32 then orbXVelocity[i] = -1 : orbYVelocity[i] = -1
orbAnimFrame[i] = 0
orbAnimWait[i] = 0
orbCaptured[i] = 0
next
return
Now we will update the _gameLoop function.Instead of moving and displaying the single orb on the screen, we will run through a similar for:next loop to the one in makeOrbs, using the temp variables to store the values in the parallels arrays as we iterate through them
We need the temp variables because 7800 Basic doesn’t do well trying to use the values in the arrays directly using index notation.
Also, we use m as the iterator set maxOrbs -1 because the first index of maxOrbs is zero.
_gameLoop
clearscreen
rem *******
rem * Update & Draw Orbs
rem *******
m = maxOrbs – 1
for i = 0 to m
tempX = orbX[i]
tempY = orbY[i]
tempAnimFrame = orbAnimFrame[i]
tempAnimWait = orbAnimWait[i]
tempXVelocity = orbXVelocity[i]
tempYVelocity =orbYVelocity[i]
tempX = tempX + tempXVelocity
tempY = tempY + tempYVelocity
plotsprite orb1 2 tempX tempY tempAnimFrame
tempAnimWait = tempAnimWait +1
if tempAnimWait > 1 then tempAnimFrame = tempAnimFrame + 1 : tempAnimWait = 0
if tempAnimFrame > 5 then tempAnimFrame = 0
orbX[i] = tempX
orbY[i] = tempY
orbAnimFrame[i] = tempAnimFrame
orbAnimWait[i] = tempAnimWait
next
Let’s also delete the randomOrb subroutine.
_randomOrb
orbX = rand
orbY = rand
if orbX > 151 then orbX = 151
if orbY > 183 then orbY = 183
return
And then comment out the code that calls it in _testCollisions.
_testCollisions
. . .
rem gosub _randomOrb
We should now be ready to test the code!
Here is what it looks like running.
Part 7 : Collect 32 Orbs
(lesson4_7.78b)
Next we will let the player capture the orbs.
To do this, we will first create two new variables: tempCaptured and playerSpeed.
dim tempCaptured = var15
dim playerSpeed =var17
In the _initGame subroutine we will set the player;s speed to 2.
Thai way we have the option to increase or decrease speed later instead of it always being a constant
_initGame
playerSpeed = 2
We will then use it rightaway in the _gameLoop subroutine, by removing the discrete values we had before, and using the variable to update the location of the player when the joystick is pressed.
We also call a new subroutine named _testCollisions so we can have the UAP collect the orbs.
_gameLoop
. . .
if joy0left then playerX=playerX – playerSpeed
if joy0right then playerX=playerX + playerSpeed
if joy0up then playerY=playerY – playerSpeed
if joy0down then playerY=playerY + playerSpeed
gosub _testCollisions
So now we will build the test collisions subroutine.
We will iterate through the array of orbs, very much like how we displayed them on the screen.
We test orbCaptured[[i] to see if the current orb has already been collected. If so we skip the rest of the code by jumping to _skipCollide.
Next we are ready for the collision check.
We have to be careful because this code checks boxcollision up to 32 times per frame depending on how many orbs are left to collect.
This will work fine, but if we keep adding more and more checks of this size into text collisions we may need to optimize the further to make sure all can run inside a single frame.
Back in lesson 2 (two years ago, sorry) we talked about the doublebuffer flip 2 command in Atari 7800 Basic that we are using to draw the screen. This gives us an effective frame rate of 30 fps, but also allows us extra time to complete all of these checks.
_testCollisions
m = maxOrbs – 1
for i = 0 to m
tempCaptured = orbCaptured[i]
if tempCaptured = 1 then goto _skipCollide
tempX = orbX[i]
tempY = orbY[i]
if boxcollision(playerX, playerY, 13, 9, tempX, tempY, 8, 8) then goto _doCollide
goto _skipCollide
_doCollide
score0 = score0 + 10
orbCaptured[i] = 1
_skipCollide
next
return
If we do find a collision, we update the score0 variable with 10 points, and set orbCaptured for the orb to “1” which means it’s true.
Now let’s test this and capture some orbs!!
Part 8: Why Can’t We Get Them All?
(lesson4_8.78b)
So you may notice that not all the orbs display on the screen at the beginning, and some may actually be assigned movement that makes them nearly never appear on the screen.
To help with this, let’s make sure the orbs always start on the visible screen.
We do this by making sure that tempX is always between 0 and 152 and tempY is always between 0 and 184. We will get random numbers for each, then loop back to a label (_getX and _getY) until we find a number within that range.
makeOrbs
rem ************************************
rem * fill up orbs to display
rem ************************************
m = maxOrbs – 1
for i = 0 to m
_getX
tempX = rand
if tempX > 152 then goto _getX
_getY
tempY = rand
if tempY > 184 then goto _getY
orbX[i] = tempX
orbY[i] = tempY
Okay, let’s test this one.
Try it a couple times.
You will see that more orbs appear on the visible screen now before they fly off into the ether.
(lesson4_8.78b)
Part 9: Display Portal
(lesson4_9.78b)
So now we will end the level and display the interdimensional portal so the UAP and travel beyond the current ranch to the next “ranch” when a level is complete.
Here is the portal we designed way back at the beginning.
We will load the sprites in like this.
incgraphic images/portal1_top.png 160A 0 1 2 3
incgraphic images/portal2_top.png 160A 0 1 2 3
incgraphic images/portal1_bottom.png 160A 0 1 2 3
incgraphic images/portal2_bottom.png 160A 0 1 2 3
Then we create a new variable named level that will hold the current game level
Now we will define a similar set of variables for the portal that we defined for our single orb (now deleted): The X, Y, animation frame and animation wait.
We will also define a new variable named “orbsLeft” that will help us keep track of when the level has been completed.
dim level = var19
dim portalX =var20
dim portalY = var21
dim portalAnimFrame = var22
dim portalAnimWait = var23
dim orbsLeft = var24
So now we define the level as 0 and set the colors for the portal into palette 3.
_initGame
. . .
level = 0
. . .
rem portal colors
P3C1 = $55
P3C2 = $63
P3C3 = $60
Next we will remove the call to gosub makeOrbs from _initGame and move it to a new sub routine named _initLevel.
This is because we will want to remake the orbs before every level, so there is no need to do it initGame
We increase the level in initLevel because it is set to 0 when we start.
Now we can call this subroutine every time we want to start a level
Then set orbsLeft to the 32 and an X,Y position for where the portal will be displayed.
_initLevel
level = level + 1
maxOrbs = 32
orbsLeft = 32
portalX = 64
portalY = 80
gosub makeOrbs
Now we will add the code to display the portal when all the orbs we have collected.
We will test the orbsLeft variable to see if we should display the portal. If the number is 0, we call a new sub youtube named _displayPortal.
We will also test to see if the player has collided with the portal. If so, call that new function we created _initLevel to start a new level.
We do not want to change levels if the player touches any one part of the portal.
Insead we add 10 pixels to the x and y location, and then only test a 6 x 6 region inside. We want this so that the player needs to actually ENTER the portal to go the next level.
_gameLoop
tempX = portalX + 10
tempY = portalY + 10
if orbsLeft = 0 then gosub _displayPortal
if orbsLeft = 0 && boxcollision(playerX, playerY, 13, 9, tempX, tempY, 6, 6) then goto _initLevel
gosub _testCollisions
Also in _gameLoop we will add some new code to where we display the score.
We will add some text for ‘orbs left’.
We will then use the converttobcd function, that converts the HEX byte variable into a decimal number.(0-99) which is good for displaying stuff like percentages. In this case it will be used to display the number of orbs left.
We put the converted value into the k variable, then display it on the screen.
plotchars ‘orbs left’ 2 20 0
k = converttobcd(orbsLeft)
plotvalue font 1 k 2 60 0
plotvalue font 1 score0 6 124 0
Next we will add some code to the _testCollisions subroutine.
We will add one line of code here to update the number if orbs left after the player collects one of them: orbsLeft = orbsLeft – 1
_testCollisions
. . .
_doCollide
score0 = score0 + 10
orbCaptured[i] = 1
orbsLeft = orbsLeft – 1
Finally, we will create a brand new subroutine called _displayPortal.
This is very similar to other places where we have displayed sprites.
The difference here is that the portal is 2 separate sprites.
_displayPortal
tempY = portalY + 16
plotsprite portal1_top 3 portalX portalY portalAnimFrame
plotsprite portal1_bottom 3 portalX tempY portalAnimFrame
portalAnimWait = portalAnimWait +1
if portalAnimWait > 2 then portalAnimFrame = portalAnimFrame + 1 : portalAnimWait = 0
if portalAnimFrame > 1 then portalAnimFrame = 0
return
Wow, that was a lot.
Let’s test this version and see what happens.
We should see the portal appear and the player should be able to enter it to move to the next level
Part 10: Cleaning Up Again!
(lesson4_10.78b)
Okay, finally, some clean-up at the end of this lesson.
I noticed that some of the label names are confusing.
We need to rename the subroutines to be different from goto labels.
Let make sure all the goto labels have an underscore at the beginning _
And all the subroutines no not
_setTitleColors change to setTitleColors
_titleLoop change to titleLoop
Make sure the call to titleLoop is updated at the end of that subroutine:
goto titleLoop
_initGame change to initGame
In the titleLoop we need to update this line:
initGam
if joy0fire0 || joy0fire1 then goto initGame
_initLevel change to initLevel
Then update this line of code in _gameLoop (which will soon be gameLoop)
if orbsLeft = 0 && boxcollision(playerX, playerY, 13, 9, tempX, tempY, 6, 6) then goto initLevel
Also in initLevel change the call to _makeOrbs to makeOrbs
gosub makeOrbs
_gameLoop change to gameLoop_ma
On the last line of gameLoop change this line of code to call the correct subroutine
goto gameLoop
Change _testCollisions to testCollisions
Then change this line in gameLoop
gosub testCollisions
Change _displayPortal to displayPortal
Then change this line of code in gameLoop that calls displayPortal
if orbsLeft = 0 then gosub displayPortal
This is good chance to practice your skills debugging 7800 Basic, As will probably not get all of this right the first time Truthfully, it might just be easier for you to pull the lesson4_10.78b file from the GitHub repo and start there
Now let’s add a couple more little things just to finish-up.
First let’s add random values to the orbAnimFrame (from 0 to 5) so that the orbs will display with a different start frame, and will not look all uniform on the screen.
The last lines in the for:next loop in the makeOrbs subroutine should look like this now:
r = rand
if r < 255 then orbAnimFrame[i] = 0
if r < 213 then orbAnimFrame[i] = 1
if r < 170 then orbAnimFrame[i] = 2
if r < 127 then orbAnimFrame[i] = 3
if r < 84 then orbAnimFrame[i] = 4
if r < 42 then orbAnimFrame[i] = 5
orbAnimWait[i] = 0
orbCaptured[i] = 0
Finally,. Let’s limit the player’s UAP to so it stays on the visible screen:
Add the following for lines of code (ignore the first one, it’s just there for illustration) right under the place you test the joystick in the gameLoop.
if joy0down then playerY=playerY + playerSpeed
if playerX > 144 && playerX < 160 then playerX = 144 ; went off right
if playerX <= 255 && playerX > 144 then playerX = 0 ;went off left
if playerY > 183 && playerY < 199 then playerY = 183 ; went off bottom
if playerY <= 255 && playerY > 239 then playerY = 0 ; went off top
Now test it!
Wow, that was a lot this time, but I think after a 2 year break, you deserved a bit more meat for this lesson.
Next time we turn this UAP sighting into a full-on, battle in the sky!!
And there you go, we MADE A THING!
See lessons 1-3 here:
Atari 7800 Basic Lessons 1-3 – Generation Atari
See the GithubRepo Here:
makeathing/Atari7800/Atari7800Basic/Tutorial at main · intotheverticalblank/makeathing · GitHub
Atari 7800 Basic Guide:

Leave a comment