Harry Wilhelm:
(source: https://atariage.com/forums/topic/273248-ti-basic-sprite-games/?do=findComment&comment=3928758 )

I have been doing a considerable amount of fine tuning on my method for using moving sprites in plain TI BASIC. The program lines that enable the sprites and sprite motion are now located within the same program that uses the sprites. There is no longer a need to load and run one program to set up the sprites and then load and run another program to use the sprites. When it starts, the routine will automatically position the first four unused sprites off the screen, with their motions all set to zero so they stay off the screen. After the 4 usable sprites all the rest are automatically turned off. The only setup is that you must define character 159 before activating the sprites.

Earlier I had opined that being able to use auto sprite motion was probably not all that useful. Here's a demo that proves me wrong. The little marching man from Notwhoyouthink's demo has been set into motion by manually updating the sprite table. (CALL COLOR(1...) and CALL COLOR(2,...)) The subroutine that updates the column looks for a keypress and if it finds one it jumps the little guy ahead. He does not land exactly where he should but it is close enough, and you just need to update the row and column to get him exactly where he should be. You can see that here sprite motion is quite useful despite the inability to use CALL LOCATE from XB. (This should be used on the latest version of Classic99. Some earlier ones seem to be slow at handling interrupts, so that sound lists and sprite motions happen too slowly.)

I just tried this in Win994a and found that it simply exits Win99.. No colorful screen - it just closes the window. So either Win994a or Classic99 is not behaving properly. I will look into it a little more and maybe transfer it to my real TI to see what happens there. @Casey - if you want to test this you would need to change the 55,215 in line 12 to 55,207.

2 FOR I=1 TO 128
4 READ X
6 F$=F$&CHR$(X)
8 NEXT I
10 DATA 0,0,0,0,226,0,215,224,1,40,215,204,216,32,131,78,131,212,215,224,131,212,215,224,1,245,4,224
12 DATA 131,196,2,12,67,0,16,17,7,248,55,215,158,142,0,0,0,64,0,21,8,159,212,0,0,3,33,111
14 DATA 0,0,0,0,0,0,0,0,25,202,81,5,77,0,215,224,131,249,215,204,143,60,212,224,0,5,2,140,67,16,17
16 DATA 247,215,224,0,51,215,204,16,0,212,224,0,166,215,224,0,63,215,224,1,153,115,12,212,204,6,12
18 DATA 22,253,4,91,53,103,0,0,131,80,2,4,5,255
110 CALL CHAR(146,"0")
120 CALL CHAR(147,"0")
135 CALL CHAR(152,"1122334455667788")
136 CALL CHAR(153,"99AABBCCDDEEFF10")
140 CALL CHAR(154,"1010101010101010")
150 CALL CHAR(155,"1010101010101010")
155 CALL CHAR(159,"0")
160 CALL CHAR(96,"0F1F1C1C1E1F0F03")
170 CALL CHAR(97,"0303070702020203")
180 CALL CHAR(98,"84C4241424C4841F")
190 CALL CHAR(99,"C43C040480804070")
200 CALL CHAR(100,"0F1F1C1C1E1F0F03")
210 CALL CHAR(101,"0303070703030303")
220 CALL CHAR(102,"80C0201020C18204")
230 CALL CHAR(103,"A8502840000080E0")
240 CALL CHAR(104,"0F1F1C1C1E1F0F03")
250 CALL CHAR(105,"030307070305080E")
260 CALL CHAR(106,"80C0201020C08000")
270 CALL CHAR(107,"0040FF4080008070")
280 CALL CLEAR
290 CALL SCREEN(2)
292 OPEN #1:F$
294 CALL HCHAR(18,1,168,192)
300 CALL COLOR(1,8,
310 CALL COLOR(2,1,1)
320 CALL COLOR(4,1,16)
330 REM    sprite walking below            
340 MSB=1
350 LSB=1
360 CALL COLOR(2,MSB,LSB)
370 CALL COLOR(3,13,1)
380 GOSUB 490
390 CALL COLOR(2,MSB,LSB)
400 CALL COLOR(3,13,5)
410 GOSUB 490
420 CALL COLOR(2,MSB,LSB)
430 CALL COLOR(3,13,9)
440 GOSUB 490
450 CALL COLOR(2,MSB,LSB)
460 CALL COLOR(3,13,5)
470 GOSUB 490
480 GOTO 360
490 MSB=MSB-(LSB=16)
500 LSB=LSB+1+16*(LSB=16)
510 CALL KEY(0,K,S)
520 IF S=0 THEN 560
530 CALL CHAR(146,"F008")
531 CALL CHAR(146,"FA08")
532 CALL CHAR(146,"0608")
533 CALL CHAR(146,"1008")
534 CALL CHAR(146,"0")
535 CALL COLOR(1,8,
550 MSB=MSB+1
560 MSB=MSB+16*(MSB>16)
570 RETURN

The sprite magnification can be changed in the first DATA line - the 227 can be a value from 224 to 227 for sprite magnifications 1-4.
These are the BASIC lines needed to create the string that does all the magic. Put these at the beginning of your program, then OPEN #1:F$ at the point where you want the sprites to be activated. Remember to CALL CHAR(159,...) before activating the sprites. In the videos I started with F$ already created which is faster, but it uses values that cannot be pasted.

1 FOR I=1 TO 128
2 READ X
3 F$=F$&CHR$(X)
4 NEXT I
5 DATA 0,0,0,0,227,0,215,224,1,40,215,204,216,32,131,78,131,212,215,224,131,212,215,224,1,245,4,224
6 DATA 131,196,2,12,67,0,16,17,7,248,55,215,158,142,0,0,0,64,0,21,8,159,212,0,0,3,33,111
7 DATA 0,0,0,0,0,0,0,0,25,202,81,5,77,0,215,224,131,249,215,204,143,60,212,224,0,5,2,140,67,16,17
8 DATA 247,215,224,0,51,215,204,16,0,212,224,0,166,215,224,0,63,215,224,1,153,115,12,212,204,6,12
9 DATA 22,253,4,91,53,103,0,0,131,80,2,4,5,255
...
390 OPEN #1:F$

Here is a method that gives you up to 4 moving sprites using standard TI BASIC, using nothing but BASIC statements. It is similar to the earlier method that offers 32 sprites but no sprite motion. The challenge in making this work is that if you want to use automatic sprite motion the sprite attribute list must start at v0300. The only way TI BASIC can modify those memory locations is via CALL COLOR. In the color table, the first four sprite definitions cannot be accessed but sprites 5-8 can be. So there will be 8 sprites in all; the first 4 are invisible, the next 4 can move automatically, and the ninth has its row set to >D0 to hide the remaining sprites.

Four character definitions from 144 to 147 are used for the sprite motion table. Since the program is using the color table for sprites then there has to be a new color table. I put it so it can be modified by changing the character definitions from 152 to 155.
As with the previous program that gives you 32 sprites, this one exploits a bug in OPEN that allows 128 bytes to be loaded into the scratchpad. This loads some assembly code that waits for an interrupt and then sets the appropriate registers and VDP memory.
The programs above give examples showing how to set up the sprites and I will also give a short description below.
-----------------------------------------------------------------
CALL COLOR is used to define a sprite.
Sprite 1 is defined with COLOR 1-4
Sprite 2 is defined with COLOR 5-8
Sprite 3 is defined with COLOR 9-12
Sprite 4 is defined with COLOR 13-16
It helps to think in hexadecimal for this. For row and column add 1 to each nybble. For Sprite #1
For a row of >83 it should be CALL COLOR(1,9,4)
For a row of >AB it should be CALL COLOR(1,11,12)
For a column of >83 it should be CALL COLOR(2,9,4)
To set the pattern to use, add 7 to the first nybble and 1 to the second.
To use the pattern for “A” (>41) it should be CALL COLOR(3,11,2)
To set the color of the sprite use the normal color value for BASIC. The first nybble should be 1 if you do not want to use the “early clock” or 9 if you want to set the early clock.
To set the color to white (16) it should be CALL COLOR(4,1,16)
To set the color to dark red with early clock on it should be (CALL COLOR(4,9,7)
If you do not wish to use all 4 sprites you can turn off the first unwanted sprite with a row of >D0 which will hide it and all higher sprites
-------------------------------------------------------------------
CALL CHAR 144 to 147 are used to set the sprite velocities.
144 and 145 are set to zero when “OPEN #1:F$ is executed.
For the sprites we care about:
CALL CHAR(146,”0503000007F9”) sets sprite 1 to row velocity=5 and col velocity=3.
Sprite 2 has row velocity=7 and col velocity=-7
CALL CHAR(147,”FCF4”) sets sprite 3 row velocity=-4 and col velocity=-12
(If the row velocity is positive then motion is downward and if the column velocity is positive then motion is to the right.)
---------------------------------------------------------------------
The new color table is set with CALL CHAR 152-155
I recommend using the values that are in the demo:
310 CALL CHAR(152,"1122334455667788")
320 CALL CHAR(153,"99AABBCCDDEEFF10")
330 CALL CHAR(154,"1010101010101010")
340 CALL CHAR(155,"1010101010101010")
The relocated color table lets you define the colors of all 256 characters. Characters 154 and 155 contain the colors of character sets 1 to 16. Above they are set to black on transparent. (You have to subtract 1 from the TI BASIC color codes.) In the example above the unused characters from 0 to 23 and 160 to 255 have their foreground and background colors set to the same color and that gives you an 8x8 block of all possible colors without using any of the normal characters. You can display these on the screen with HCHAR and VCHAR.
The first character of each character set is:
160 Black
168 Medium Green
176 Light Green
184 Dark Blue
192 Light Blue
200 Dark Red
208 Cyan
216 Medium Red
224 Light Red
232 Dark Yellow
240 Light Yellow
248 Dark Green
0 Magenta
8 Gray
16 White

When programming, do not use characters 144 - 147 or 152 – 155 for graphics because they are needed by the sprite routines and color table.
One thing that might cause some head scratching is that I use a scroll routine in the console ROM to kill some time until the TI comes to the interrupt routine. This happens when OPEN #1:F$ is performed. If you are printing a screen you can use a semicolon at the end of the second to last line, then OPEN #1:F$ and then print the last line.