Here's a video of it in action.
The code is on my GitHub.
Since doing this, I've joined the FujiNet development team to make something cooler.
Some posts about my random techo projects at home - some Arduino, Atari, 3D printing, RPi, etc ....
Excerpt of the schematic showing the Atari 8-bit cartridge edge connector, address and data buses, and decoder logic. |
reactorX - 2019 BASIC 10 Liner Contest |
data D() WORD = -1,1,2,2,1,-1,-2,-2,-1,1,2 | Array to store info to draw an octagon. The drawing routine is at the bottom of the listing. |
data x() WORD =
0,10,0,-10,0 data y() WORD = -20,20,20,20,0 |
Arrays to store X and Y positions of sprites with initial positions. Fifth index is the origin so I can reuse physics code. |
dim alive(4), colsnX(4), colsnY(4) | Arrays that store alive/dead state of PM's and changes in position due to collisions. |
numkilled = 0 numlives = 5 score=0 rate = 15 counter = rate-1 |
Initialize some counters. |
graphics 7 poke 752,1 |
Use 4 color 160x80 mode Turn off cursor in text window |
PM=$A000
mset $a000,1024,0 poke 54279,PM/256 poke 53277,3 poke 559,46 |
Clear out some RAM Tell ANTIC where PM RAM is' Enable PM display Enable PM DMA with 2-line res |
dpoke 704,$440F dpoke 706,$4444 dpoke 709,$404F |
Set colors for players 0 and 1, players 2 and 3, and the text window |
x0=80 y0=40 color 1 radius = 19 exec octagon |
Store the coordinates for the center of the screen. Pick color 1, default is orange Set the radius to draw the large octagon. Call the routine at the end of the listing. |
?"Push FIRE" WHILE STRIG(0):WEND CLS | Wait for player to start the game. |
WHILE numkilled < 3 AND numlives> 0 | This begins the main game loop |
alive(0) = 0 | Reset the player is still alive flag. |
inc counter setcolor 1,counter,15 if counter MOD rate = 0 color 2 radius = counter/rate exec octagon endif |
Take care of the background graphics. Increment a counter to rotate the colors using the SETCOLOR command. Draw a larger octagon to enlarge the core every RATE game loop cycles. The EXEC OCTAGON jumps to the drawing routine at the end of the listing. |
poke
53248,x0+44+X(0) move adr(" -stuff-")+1, PM+$200 + y0 + 9 + Y(0), 17 |
Move player location. Poke the X coordinate and MOVE memory for the Y coordinate. The sprite is defined by the string, which starts at one byte higher than the address in FastBasic. |
for i=1 to 3 move adr(" ball " ) + 1, PM + $200 + i*128 + y0 + 9 + Y(i), 14 poke 53248+i,(x0+43+X(i))*(alive(i)=0) next i |
Loop to move each particle location. If particle is dead, keep it off the screen. |
poke 53278,1 PAUSE 1 |
Clear collision register and paint the screen once to record collisions. |
for i=0 to 3 | Loop through all the PM's |
colsnX(i) = 0 colsnY(i) = 0 |
Initialize the collision accumulators... |
PiPF = peek(53252+i) | Check the player-player collision register. |
if PiPF&1 = 1 alive(i) = 1 |
Someone hit the wall! Set the alive/dead flag. |
if i = 0 X(i) = 0 Y(i) = -2*radius dec numlives mset PM+$200,128,0 exit |
It was the player's ship. Reset it's position and take away a life. Exit the collision detection loop. |
else X(i) = -43-x0 inc numkilled endif |
It was a particle. Kill it and remove it from the screen. |
elif PiPF&2 = 2 freq = 80 j=4 exec bounce endif |
Something hit the core. Make it bounce and get ready to play a tone. |
PiPj = peek(53260+i) | Now check for player collisions. The 'i' value is subject player and 'j' value is player that was hit. |
if PiPj > 0 | Act if there was a collision. |
if PiPj&1 = 1 freq = 40 j = 0 score=score+5 |
The ship made a hit. Get some points and get ready to play a high-pitched tone. |
elif PiPj&2 = 2 j = 1 elif PiPj&4 = 4 j = 2 elif PiPj&8 = 8 j = 3 endif |
Check for collisions with the particles. |
exec bounce | Compute bounce position change. |
endif next i |
Close the loop. |
if freq>0 sound 0,freq,10,15 else sound endif freq = 0 |
Play a tone or stop the tone, if needed. |
for i=1 to 3 X(i)=X(i) - SGN((X(i)-X(0))/10) + colsnX(i) + RAND(3)-1 -(X(i)/33) Y(i)=Y(i) - SGN((Y(i)-Y(0))/10) + colsnY(i) + RAND(3)-1 -(Y(i)/33) next i |
Update particle locations: attract to player, add in the bounce, do a little random walk, and stay away from the walls. |
P.657,2 ? score, numlives; |
Update the scoreboard. The POKE command positions the cursor before printing to the screen. |
S=STICK(0) LR=(S&4=4)-(S&8=8) UD=(S&1=1)-(S&2=2) Y(0) = Y(0) + colsnY(0) + UD+UD X(0) = X(0) + colsnX(0) + LR+LR |
Get joystick input and move the player. Also add in the player bounce move. |
WEND | End of game loop. |
SOUND | Game over. Stop the sound. |
if numkilled=3 and
alive(0)=0 ?;"You Win!"; else ?;"/MELTDOWN\"; endif |
Figure out the result. |
do loop |
Wait forever. |
proc bounce colsnX(i) = colsnX(i) + 2*SGN(X(i)-X(j)) colsnY(i) = colsnY(i) + 2*SGN(Y(i)-Y(j)) endproc |
Procedure to add in bounce motion. The motion is towards the ith particle and away from the jth particle. When j=4, the motion is away from the origin. |
proc octagon plot x0-radius, y0 + 2*radius for p = 1 to 8 drawto x0 + D(p)*radius, y0 + D(p+2)*radius next p endproc |
Procedure to draw an octagon. Loop through the vertices and draw lines. Scale the size by 'radius.' |