Classic Computer Magazine Archive COMPUTE! ISSUE 30 / NOVEMBER 1982 / PAGE 160

A Shape Generator For The Commodore 64

Donald A Pitts Houston

With this program it's much easier to generate sprites on the Commodore 64. You can draw a shape, examine it, modify it, and then save it in DATA statements ready to use anywhere.

The sprite graphics of the Commodore 64 is an attractive feature. It allows you to create rapid movement of complex shapes with one shape disappearing behind another in an apparent three dimensional display. The sprite is a 24 by 21 grid with each grid element being one bit. Three bytes are positioned side by side to make up the 24 bits. To manually build a sprite, a user would have to construct the grid on graph paper, draw the desired figure, and then determine the value of each byte according to the bits which are enabled (see Figure 1). Although Commodore set up the sprite system in a way that is very logical, the shape generator program makes the job of generating sprites easier and much faster.

The program, Shape Gen, allows you to draw a shape on a 24 by 21 grid on the screen, preview what the sprite will look like, modify the sprite further, and finally save the sprite information in BASIC DATA statements. To the left of the grid is a menu of available commands. Below that is a space for the sprite to be displayed, in both normal and enlarged sizes. This allows the user to determine the exact way the sprite will be displayed prior to saving it. When the shape is deemed perfect, pressing the "←" key will erase the Shape Gen program and leave behind the data statements that describe the sprite you have just drawn.

Drawing The Shape

Four keys (I = up, J = left, K = right, M = down) are used to move the Shape Gen cursor. Either shift key may be pressed to draw while the cursor is either moving or stationary. The Commodore key works the same way, except its function is to delete pixels on the grid. When you have finished drawing the shape or want to see what the shape would look like as a sprite, press F1 (located in the upper right of the keyboard).

The program will tell you it is compiling the shape at this point. In a few moments the cursor will reappear, and two shapes will appear at the left side of the screen. At this point you may either change the shape or transform the shape into DATA statements. Should you desire to start over, you may depress the CLR/HOME key.

Once you have compiled the shape for the last time, press "←"; a warning will appear because this option erases the Shape Gen program leaving behind the DATA statements with the data necessary to re-create the sprite in other programs. Press "Y" or "N" in response to "continue?". If you respond "Y" the DATA statements will be listed to the screen, and Shape Gen will end execution. Now you are free to add your own program to the DATA statements to manipulate the shapes on the screen. To do this, it will be helpful to read section six of the Commodore 64 User's Guide.

The following is an example of a group of DATA statements generated by the Shape Gen program together with a BASIC program that will move this sprite from the upper middle to the lower left of the screen.

1 REMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
2 REMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
3 REMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
4 REMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
50 REM
60 REM
100 PRINT CHR$ (147): FOR X = 5529 TO 56295 : POKE X, 3 : NEXT
105 PRINT CHR$ (145) ; TAB(13); CHR$ (18); "SHAPE GEN 1.0" CHR$ (146)
107 PRINT : PRINT" "; CHR$ (18); "I" CHR$ (146); " ˜ = UP"
109 PRINT" "; CHR$ (18); "M" CHR$ (146);" = DOWN"
111 PRINT" "; CHR$ (18); "J" CHR$ (146);" = LEFT"
113 PRINT" "; CHR$ (18); "K" CHR$ (146);" = RIGHT"
114 PRINT" "; CHR$ (18); "COM" CHR$ (146);" = DELETE"
115 PRINT" "; CHR$ (18); "SHFT" CHR$ (146);" = DRAW"
116 PRINT" "; CHR$ (18); "__" CHR$ (146);" = DATA"
117 PRINT" "; CHR$ (18); "F1" CHR$ (146);" = SHAPE"118 PRINT" "; CHR$ (18); "HOME"; CHR$ (146);" = CLEAR"
119 PRINT : PRINT : PRINT : " SMALL" : PRIMT" SHAPE"
120 PRINT : PRINT : PRINT : PRINT : " LARGE" : PRINT" SHAPE"
121 PRINT : PRINT : PRINT : PRINT : PRINT TAB (13); CHR$
    (18); "DRAWING MODE "; CHR$(146);
129 DIMG (62): V = 53248: UL = 1078: FOR X = 0 TO 25 : POKE
    UL + X,42: POKE UL + 22 * 40 + X, 42: NEXT
130 FOR X = 0 TO 22 : POKE UL + X * 40, 42: POKE UL + 25 X * 40, 42: NEXT
140 PT = UL + 41
150 SL = PEEK (PT): POKE PT, 81 : FOR X = 0 TO 80 : NEXT : POKE PT, SL
160 A = PEEK (197): C = PEEK (653)
162 IF C = 1 THEN POKE PT, 160
164 IF C = 2 THEN POKE PT, 32
170 IF A = 33 THEN M = -40: GOTO 300
180 IF A = 34 THEN M = -1: GOTO 300
190 IF A = 37 THEN M = -1: GOTO 300
200 IF A = 36 THEN M = 40: GOTO300
210 IF A = 51 THEN PRINT CHR$ (147): POKE V + 21, 0: RUN 105
220 IF A = 4 THEN 400
225 IF A = 57 THEN 500
230 GOTO 150
300 IF PEEK (PT + M) = 42 THEN 150
310 PT = PT = M: GOTO 150
400 FOR X = 1 TO 15: PRINT CHR$ (157);: NEXT: PRINT
    CHR$ (18); "COMPILLING SHAPE"; CHR$ (146);
401 N = 0: Z = 8 FOR Y = 1 TO 21: FOR X = 1 TO 24; P = PEEK
    (UL + Y * -40 + X): Z = Z - 1
410 IF Z = -1 THEN C = 0: Z = 7: N = N + 1
420 IF P = 160 THEN C = C + 2^Z
425 IF Z = 0 THEN POKE 832 + N, C: G (N) = C
430 NEXT: NEXT
440 POKE V + 21, 12 : POKE 2042, 13 : POKE 2043, 13 : POKE
    V + 4, 90 : POKEV + 5, 150
445 POKE V + 6, 80 : POKE V + 7, 180: POKE V + 23, 8: POKE
    V + 29, 8
450 FOR X = 1 TO 15 : PRINT CHR$ (157) = : NEXT
460 PRINT CHR$ (18); "DRAWING MODE "; CHR$ (146); : GOTO 150
500 DT = 0 : CU = PEEK (43) + PEEK (44) * 256 + 4 : POKE V + 21, 0
501 FOR X = 1 TO 25 : PRINR CHR$ (157); : NEXT
502 PRINT" DATA WILL ERASE PROGRAM -- CONTINUE?"; : POKE 198, 0
503 GET A$ : IF A$ < > "Y" AND A$ < > "N" THEN 503
504 IF A$ = "N" THEN FOR X = 1 To 26 : PRINT CHR$ (157); : NEXT
505 IF A$ = "N" THEN FOR X = 1984 TO 2023 : POKE X, 32 : NEXT : GOTO 460
506 PRINT CHR$ (147); TAB (13); "PUTTING SHAPE INTO"
507 PRINT TAB (13); "DATA STATEMENTS"
510 POKE CU, 131 : CN = 1
530 D$ = STR$ (G(DT)) : FOR X = 2 TO LEN (D$) : C = ASC (MID$(D$, X, 1))
532 POKE CU + CN, C : CN = CN + 1 : NEXT
535 DT = DT + 1 : IF DT = 63 THEN 560
540 IF CN >71THEN FOR X = CN TO 75 : POKE CU + X, 32 : NEXT
    : POKE CU = 76, 0 : CU = CU + 81 : GOTO 510
550 POKE CU + CN, 44 : CN = CN + 1 : GOTO 530
560 FOR X = CN T075 : POKE CU + X, 32 : NEXT : FOR X = 76 TO 78
    : POKE CU + X, 0 : NEXT : LIST : END

Should you desire to save the DATA statements and merge them with other programs, you should refer to Jim Butterfield's article in the June 1982 COMPUTE! (p. 158) on merging VIC-20 programs. His technique will work with one addition. After you have saved the program on tape and are trying to merge it, you will be unable to clear the screen as Butterfield tells you to do. At that point hit the Commodore key and continue with the rest of the commands.

A Note On Entering The Program

  1. The first four REM statements must be typed in, in order to use the data option of the program. They must be typed in with no spaces, exactly as they appear in the listing. Seventy-five A's should follow each REM.
  2. When writing the program, I specifically used CHR$ statements in place of cursor control characters embedded within print statements. I hope this will aid new Commodore 64 users in typing in the program.
  3. Please save the program at least once before running it for the first time since the program is designed to erase itself when certain options are exercised.

Program Description

Line no.

1-4 REM statements that will contain the shape DATA statements. These four lines must be typed in with no blanks anywhere including between the line # and REM and also between REM and the first A. There must be 75 A's in each line.
100 Clears screen; clears color to cyan.
105 Moves cursor up one line; turns on reverse print; prints title; turns off reverse print
107-118 Print command keys in reverse lettering with a very brief accompanying description.
119-120 Print labels at the places where the shape will be shown if compiled.
121 Prints current mode in reverse lettering.
129 Sets up array G to store shape data. V is starting memory location in the video chip; UL is upper left of shape drawing region. Draws upper and lower horizontal lines of asterisks to indicate the boundaries of the shape drawing region.
130 Draws left and right vertical line of asterisks.
140 PT is the cursor position within the drawing region.
150 SL is the character underlying the cursor; displays cursor; time delay; redisplays character.
160 Looks at keyboard; looks at status of Shift and Commodore keys.
162 Fills in area under cursor if either Shift key is pressed.
164 Erases area under cursor if Commodore key is pressed.
170 Moves up if I key is pressed.
180 Moves left if J key is pressed.
190 Moves right if K key is pressed.
200 Moves down if M key is pressed.
210 Erases screen and shapes if CLR/HOME key is pressed.
220 Compiles shape if F1 key is pressed.
225 Takes shape data and puts into DATA statements if the left arrow key is pressed. This command will erase the program, so make sure that you copy the program before using this option.
300 If area cursor is to move to is an asterisk, then do not move cursor.
310 Adds movement value to cursor pointer and reenters main routine.
400 Moves cursor left until at beginning of mode message; changes message.
401 N is the counter for shape data; Z is the bit position within the current byte of shape data being compiled. Scans along shape drawing region, from left to right each row, starting at the top moving toward the bottom. P is the character at the present scan position. Decrements bit position. If finished compiling current byte, then sets bit position to bit 7 and increments shape data count.
410 If finished compiling current byte, then resets shape data byte to zero.
420 If character at the present scan position is a solid box, then sets current bit position to 1.
425 If current byte finished, then POKEs it into memory block 13 and also saves it in array G.
440 Activates sprites 2 and 3; sets sprite 2's data pointer to memory block 13; sets sprite 3's data pointer to block 13; sets sprite 2 to coordinates (90,150).
445 Sets sprite 3's coordinates to (80, 180); expands sprite 3 in both X and Y direction.
450 Moves cursor left to start of mode message.
460 Changes mode message.
500 DT is the count of data stored in BASIC program. Erases any sprites on screen.
501 Moves cursor left to beginning of bottom line.
502 Prints warning message that only the data statements that are generated will be left.
503 Gets response in A$.
504 Moves cursor back to start of mode message.
505 Clears bottom line of screen and branches to 460.
506-507 Clear screen; print message indicating action.
510 POKEs DATA token; CU is position within BASIC line.
530–532 Set shape data to string; POKE string character by character into BASIC line while increasing CN.
535 Increases data count; if all data finished, then branches to 560.
540 If current BASIC line hasn't enough space for any more data, then fills remaining bytes with spaces, adds a zero to the end, and sets BASIC line pointer to next BASIC line.
550 Puts comma in line; increases pointer within line.
560 Fills remaining locations in last DATA line with spaces; adds three zeroes to end; LISTs program; ends program.

Sprite Bit Map

Sprite Byte Map

0 0 0
0 0 0
0 0 0
0 0 0
0 62 0
0 193 128
1 255 192
3 128 224
3 93 96
5 42 80
5 73 80
5 127 80
5 73 80
5 42 80
3 93 96
3 128 224
1 255 192
0 193 128
0 62 0
0 0 0
0 0 0