Follow Simona

Copyright © 2020 by Víctor Parada

Follow Simona

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 6+5 days. The final version's date is 2020-03-06.

UPDATE: It obtained the 11 place of 25 entries in the category.


Description

Your personal trainer Simona does some exercises with you, and you must follow her as fast as you can.


Instructions

SIMONAF start Simona is your personal trainer in pink, and she'll invite you to do some exersizes.
SIMONAF levels 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.
SIMONAF hits If you perform the same movement than her before she returns to the neutral position, you will score a hit.
SIMONAF fails If you don't do the same movement at time, yow will score a fail.
SIMONAF speed Simona will increase difficulty during the exercises by speeding up a bit every time.
SIMONAF end The game is over when you fail 100 movements!

Development of 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.

SIMONA design 1

Initial design of the character

SIMONA design 2

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.

SIMONA design 3

All 17 images of Simona

SIMONA prototype

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.

The first thing I did when I resumed the programming, was to split the screen with a custom display list (over text mode 0) with the DLI using a FastBasic prototype. I liked very much the colors I selected for the second lady, and she immediately became Simona.

SIMONAF prototype 1

Prototype of the game using a prototype of DLI in FastBasic's beta version.

The next step was to be able to control the other lady with the joystick, because Simona would be controlled by the computer. There were 8 different movements, but the controls were only 4 (up, down, left and right), each with two movements, so I added the trigger as a selector of the variation for the same joystick direction for the tests. During the game, the trigger should not be required, because the variation would be selected automatically to be the same than Simona's, but during this tests, I thought that it could be nice to have different difficulties, the original and the triggered version with all 8 commands. I found that there were no simple way to recognize which was the base and which was the extended movement for each direction, so I changed the order of the series and grouped the movements that used extended arms as the alternate ones.

SIMONAF prototype 2

The player can move to any direction while Simona is performing a series.

For the game dynamics, I used loop with a circular timer. At given values of the counter, Simona whould change the position: at zero, she would select a direction and display the transition to that movement, at the quarter she whould show the selected direction, at the half she would display the transition again, and at the last quarter she would be again in the rest mode. For the player, the sequence should be the same, but it will use its own timer that it would start when the user moves the joystic. To score a hit, the timer for the player should start before the first half of Simona's timer. To have a continuous movement of the player, it won't be able to move the joystick for a new selection during the first half of the own cycle (timer). It won't be an endless game, so a fail counter was included: you can hit or miss a movement, and the game would finish at some misses count. To add difficulty, I introduced continuos increase of speed during the game loop.

SIMONAF prototype 3

Scoring hits and misses.

The game was almost ready, and as it was using about 70% of the available coding space, I decided to add some messages using another new feature of FastBasic that it was available in its beta prototype. To select each of the two difficulty levels, just 2 flag variables should be selected, and this messages allowed a simple way to select one of the difficulty levels. Then, a third game difficulty was included: the use of only the first set of movements. It was just a different combination of the same 2 flag variables.

SIMONAF prototype 4

Introducing a messages system (without DLI).

With the official release of FastBasic 4.3, I could include the DLI feature using its final syntax, and the game was ready to be sent to the contest with only 9 lines of code, but I had no documentation of it, because I used the available time to try the original concept of the game: a memory game like in Simon.

SIMONAF prototype 5

Final version using the brand new release of FastBasic with DLI.


Download and try

Get the SIMONAF.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 code

The abbreviated BASIC code is the following:

The full and expanded BASIC listing is:

Restore initial position
graphics 0
poke 710,0
poke 752,1
poke 82,0
Set up screen

GR 5: SCR=$BBA0
GR 0: SCR=$BC40
?
? "Follow 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}
Set up the display list
")+1,$BB6A,54
dpoke 560,$BB6A
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
r=adr("{binary data}")+1
Tones for the rhythm, 1 per frame
d=adr("{binary data}")
List of messages
n=1
exec m
Display welcome message
do
Main loop
  n=47
  exec m
Display difficulty selection message
  repeat
    n=68
    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
  f=0
Fails count
  h=0
Hits count
  w=16
Delay for speed control
  g=0
Current delay counter, forces a movement at start
  i=3
Current movement step
  e=63
Current step counter for player movement
  s=0
Current player movement
  v=0
Timming to decrease delay
  n=107
  exec m
Display count down...
  repeat
Game loop
    if g=0
Time to move?
      c=10
Set volume for tone
      i=(i+1)&3
Next step for the movement
      g=w
Set the next delay
      if i=0
Time to a new move?
        t=rand(z)*4+4
Select next movement
        inc v
        if v>15
          v=0
          w=w-(w>7+y*5)
        endif
Time to speed up?
        o=w*3-2
      endif
Set response timer
      k=$8400+peek(a+t+i)*512+4
    endif
Simona's next step
    sound 0,peek(r+i),8,c
Play the tone
    c=c-2*(c>0)
Decrease the volume for the next loop
    if e>3*w+2
Player can move if is not moving or if it is finishing the previous one
      s=peek(j+stick(0))*4
Select players movement
      if s
Player moves?
        e=0
Start player's sequence
        if y
Hard routine?
          s=s+16*(strig(0)=0)
        else
2nd type of movement is get when the trigger was pressed
          s=s+16*(t>16)
        endif
      endif
    endif
    l=$8400+peek(a+s+e/w)*512
Automatic selection of 2nd type of movement
    pause 0
    dpoke q,l
    dpoke p,k
Refresh movements
    if o=0
Check for a hit or miss
      if t=s
        if h<9999
          inc h
          position 35,0
          ? h
        endif
Hit!
      else
        inc f
        position 26,0
        ? f
      endif
    endif
Miss...
    dec g
Decrease delay time for the next series
    dec o
Decrease response timer
    e=e+(e<4*w-1)
Increase players counter
    poke 77,0
Disables attract mode
  until f>=100
Game ends at 100 misses!!!
  sound
Stop sounds
  dpoke p,$8404
  dpoke q,$8400
  n=131
  exec m
Display game over message
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-20 (updated: 2020-08-15)