Copyright © 2020 by Víctor Parada
This is a little game for the 2020 NOMAM's BASIC 10-liners Contest. This program fits in the EXTREM-256 category, and it was written using FastBasic 4.3 for the 8-bits ATARI XL/XE. Development started on 2019-07-19, and it took 1+6 days. The final version's date is 2020-03-06.
UPDATE: It obtained the 1st place of 25 entries in the category.
Your personal trainer Simona teachs you a series of exercises, and you must memorize and repeat them.
Simona is your personal trainer in pink, and she'll invite you to do some exersizes. | |
There are 3 different levels: EASY: There are only 4 different basic movements to remember, one for each joystick direction (up, down, left and right). REGULAR: There are 4 extra movements in addition to the 4 basic ones, but you only have to move the joystick in the same 4 directions, and the extra ones will be automatically selected for the series. HARD: You have to press the trigger to select the extra movements along with the joystick, giving real 8 different movements to remember. |
|
Each time you finish a series, a new one will start. | |
The first series is a short one, and the next ones will be longer. | |
The game is over when you fail a single series. No chances to try the same series again! | |
If you complete all 10 series, you win the game. |
Thinking about a game with a simple animation, it came to me an idea of an animated Simon-like game: instead of colors and sounds, the player might remember positions, and the most practical way to do that should be gymastics or aerobics. It took me many days to design the game in my mind, performing some calculations about the RAM requirements and which should be a good graphic resolution. I also thought about the name of the game: "Simona's Fitness Club", and obviously Simona would be the character for the game. But I had to start with something and that could by some drawings, so I used Paint program in zoom mode and started to put pixels to draw a girl in sport clothes from the 80's. After some minutes, I had a nice toon of her that it was detailed enough, but not so big for a tenliner. Then, I drawed some other positions and also the transitions from the resting one. The next day I completed full sequences for 8 movements and the corresponding transitions. I decided to have 2 different movements for each side in order to introduce difficulty to the game.
Initial design of the character
The whole series
I had to transfer this design to the Atari, but instead of convert the whole bitmap to be used in some graphics mode of the Atari, I decided to send it already sliced and ready to use from the BASIC program, and I selected FastBasic for this project. I picked every different image and put them in a row. Each image has a height of 18 pixels and a width of 11 pixels. As any 4 colour graphics mode uses a byte every 4 pixels, I'd need 3 bytes per line, and a total of 54 bytes per image. The grand total would be 918 bytes for the whole 17 images, and that is 40% of the available coding space in the EXTREM-256 category, or 75% in PUR-120. I was sure I'd need to compress the images, so I deliberately designed the images with portions of it in a static position, in order to reuse the bytes, and those were the legs. It won't make any difference in the amount of storage if a graphics mode or a text mode (in ANTIC 5) would be used. A redefined charset would require 9 chars per image: 3 bytes height (3x8=24 lines) and 3 chars width (3x4=12 pixels), and I didn't try to find how to split the images to get the common characters from different images. To simplfy, I just bet for a graphics mode and defined only 6 tiles per image, and the height of each of them was 9 pixels. I wrote a script that read the picture, splitted every image into tiles, found the duplicated ones, and wrote the bitmap of the selected tiles and an index to the required tiles for every image. The result was only 62 tiles instead of 159, with a total of 558 bytes, less than 22% of the coding space in EXTREM-256 category. The index used 17x6=102 aditional bytes, and the unpack routine used about 120 bytes more, but it did it directly into the precached buffers. A simple loop modifying the memory pointer of a GRAPHICS 5 screen pointing to the buffers showed me the animation for whole exercises sequence, and I liked it.
All 17 images of Simona
Animation in the Atari
In the bottom of the screen was displayed the next cache buffer, and that gave me the idea of two ladies in the playfield at the same time: one for Simona and one for the player, but they shouldn't be the same image, at least the color of the clothes should be different, and I already was using all 3 colors and the background. I could had a 4th color if I had used ANTIC text mode 4, and used inverse video in the chars of one of the ladies, but the images would be much smaller. By those days, I was talking with DMSC about adding display list interrupts (DLI) to his FastBasic language. With a single DLI it would be possible to have 2 completely different color sets, one for each character. But the development of DLI in FastBasic took too much time trying to find the best way to add such powerful feature to the language that it could manage many interruptions in the same screen and be simple to use at the same time, and the developement of this game got frozen for many months... During this stand-by period, I thought about a variation of the game: instead of a Simon-like game, make a reflex game, trying to react as fast as possible. When the call for the 2020 contest arrived, I had to decide which of the variations to try first, and the reflex version won over the memory one, and what happened next was documented in "Follow Simona" documentation.
After I finished the reflex version of the game, I resumed the original idea of a Simon-like memory game. At this time, I've already had a game engine, selected the colors for Simona, included a messages routine, and defined 3 difficulty levels. So I started changing the colors for the player and removing most of the game loop even when I tried to reuse most of the variables for the equivalent function. Without too much effort, I could code the backbone of the repeating game.
Simona performing Simon-like series.
The next day I included the routine to repeat what Simona played in a series. Having two ladies in the screen, allowed me to play the repetition with both of them, and Simona showing the fail after a miss. Besides the rythm sound, I included the same 4 tones from "Uncle Simon", but it was too much sound, so I removed the rythm. Changing Simona's messages for the game, I included different gameover messages based on the reached level.
In this version of the game, all 10 lines and a bit more were used, and I had to change some things to reacomodate the code in only 10 lines. After I finished the optimizations, I merged them into the reflex version of the game, having two equivalent final versions.... still without docs!!!
Final version of "Repeat after Simona".
Final version of "Follow Simona".
Get the SIMONAR.ATR file and set it as drive 1 in a real Atari (or emulator). Turn the computer on and the game should start after the loading completes. A joystick in port 1 is required.
The abbreviated BASIC code is the following:
The full and expanded BASIC listing is:
graphics 0 poke 710,0 poke 752,1 poke 82,0 |
Set up screen |
|
GR 5: SCR=$BBA0 GR 0: SCR=$BC40 |
? ? "Repeat after Simona" ? ? "Setting up..." |
|
j=adr("{binary data}")+1 |
Joystick movements |
|
Prepare Simona's movements |
mset $8000,$3800,0 |
Clean frames buffer |
a=adr("{binary data}")+1 |
Tiles needed for each frame (17 frames of 3x2 tiles) |
move adr("{binary data}")+1,$8000,225 |
Bitmap data for every tile (4x9) |
move adr("{binary data}")+1,$80E1,225 |
|
move adr("{binary data}")+1,$81C2,108 |
|
for k=0 to 16 s=$840A+k*512 for b=0 to 5 x=$8000+9*peek(a+b+k*6) for c=0 to 8 poke s+(b/2)+180*(b&1)+c*20,peek(x+c) next c next b next k |
Unpack frames |
? "{binary data}" |
Clean the text screen |
move adr("{binary data}")+1,708,4 |
Set up colors (hair,skin,clothing,text) |
dli set u = $CA into $D019, $96 into $D016, $16 into $D017, $4A into $D018 dli u |
|
move adr("{binary data}")+1,$BB6A,54 dpoke 560,$BB6A |
Set up the display list |
pause 50 |
Wait for a second |
q=$BB6E |
Frame vector for Player |
p=$BB86 |
Frame vector for Simona |
a=adr("{binary data}")+1 |
Frames for sequences, 4 frames each |
d=adr("{binary data}") |
List of messages |
n=1 exec m |
Display welcome message |
do |
Main loop |
n=35 exec m |
Display difficulty selection message |
repeat |
|
n=56 exec m until x<7 |
Display get ready message |
? "{binary data}" position 20,0 ? "{binary data}" |
Reset on-screen scoreboard |
z=4+4*(x<>5) |
Number of movements, 8 for normal and hard, 4 for easy |
y=x=3 |
Trigger is needed in hard |
n=95 exec m |
Display count down... |
data o() byte = 121,85,60,173,121,85,60,173 |
Tones for steps |
dim h(15) byte, w(15) byte |
Sequence of a series |
r=1 |
Round number |
g=600 |
Delay for speed control |
s=0 |
Current player movement |
repeat |
Game loop |
position 27,0 ? r |
Display series number |
e=0 repeat |
Loop for the series |
position 37,0 ? e+1;" " |
Display current steps number in the series |
b=rand(z) h(e)=b*4+4 w(e)=o(b) |
Select next movement |
f=0 repeat |
Show the excercise series |
for i=0 to 3 |
Iterate through frames of the step |
sound 0,w(f),10,9-i*2 |
Play the sound for that step |
k=$8400+peek(a+h(f)+i)*512+4 pause 0 dpoke p,k |
Simona's next step |
for c=0 to g next c |
Delay (each time a shorter one) |
next i |
|
sound pause 2 |
Stop the tones |
inc f |
Next step |
until f>e |
Last step of the series? |
f=0 repeat |
Repeating the excercise series |
repeat s=peek(j+stick(0))*4 until s if y |
Wait for a joystick movement |
s=s+16*(strig(0)=0) else |
2nd type of movement is get when the trigger was pressed |
s=s+16*(h(f)>16) endif |
Automatic selection of 2nd type of movement |
t=s<>h(f) |
Is the same movement than the series? |
for i=0 to 3 |
Iterate through frames of the step |
if t and i=2 |
Plays a sound at the second frame |
sound 3,200,12,8 pause 80 sound 3 else |
Plays a buzzer |
sound 0,o((s-4)/4),10,9-i*2 endif |
Play the sound for that step |
k=$8400+peek(a+h(f)+i)*512+4 |
Simona's next step |
l=$8400+peek(a+s+i)*512 |
Player's next step |
pause 0 dpoke q,l dpoke p,k |
Refresh movements |
c=0 repeat inc c |
Delay between steps |
until c>g or (c>30 and stick(0)=15) |
Quits delay if the joystick was released |
next i |
Back to the next step |
sound pause 2 |
Stop the tones |
inc f until f>e or t |
Last step? |
pause 30 poke 77,0 |
Wait for a moment and disable attract mode if it was active |
inc e until e>r+3 or t |
End of steps for the round? |
if t=0 for c = 600 to 0 step -1 sound 0,c/3,10,8 next c sound endif |
Plays a sound when the series was finished successfully |
pause 50 |
|
g=g-25 inc r |
Decrease delay time for the next series |
until r>10 or t |
End of series? Failed? |
sound |
Stop sounds |
n=125+55*(r<11)+24*(r<6) exec m |
Display game over message 137=Excelent 192=Good 215=Bad |
loop |
Back to game loop |
proc m |
Procedure to display a group of messages |
c=d+n x=7 |
Find text of the message |
while peek(c) and x=7 |
Repeat for every word(s) of the list, or until a key is pressed |
v=peek(c) position 7-v/2,0 pause 0 ? $(c) |
Print next word(s) centered in text area |
b=0 repeat x=peek(53279) inc b pause 1 until b>25 or x<7 |
Wait for a moment or a key press |
mset $BC40,20,0 pause 8 |
Clean message area |
c=c+v+1 wend endproc |
Move to next line |
Return to my 10-liners page.
© 2020 by Víctor Parada - 2020-03-15 (updated: 2020-08-15)