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