Table of Contents
Sprite
Intro
Gli sprite nel C64 sono degli oggetti grafici facilmente programmabili, utili per creare giochi. Sono gestiti via hardware dal chip grafico VIC-II, tramite una serie di registri.
Registri
Schema
Di seguito uno schema che elenca le locazioni di memoria, specificate più sotto, che definiscono gli sprite:
Sprite X | Sprite Y | Sprite Pointer | Sprite Colore | |
---|---|---|---|---|
Sprite 0 | $D000 | $D001 | $07F8 | $D027 |
Sprite 1 | $D002 | $D003 | $07F9 | $D028 |
Sprite 2 | $D004 | $D005 | $07FA | $D029 |
Sprite 3 | $D006 | $D007 | $07FB | $D02A |
Sprite 4 | $D008 | $D009 | $07FC | $D02B |
Sprite 5 | $D00A | $D00B | $07FD | $D02C |
Sprite 6 | $D00C | $D00D | $07FE | $D02D |
Sprite 7 | $D00E | $D00F | $07FF | $D02E |
Attivazione
Per attivare gli sprite c'è il registro 53269 ($D015); ciascuno degli 8 bit attiva uno sprite:
bit 0 | sprite 0 |
bit 1 | sprite 1 |
bit 2 | sprite 2 |
…
bit 7 | sprite 7 |
In Basic si può quindi usare:
POKE 53269,3 : REM ATTIVA GLI SPRITE 0 e 1 POKE 53269,255: REM ATTIVA TUTTI E 8 GLI SPRITE
Posizionamento
I registri da 53248 ($D000) a 53263 ($D00F) controllano il posizionamento X,Y, rispetto all'angolo in alto a sinistra. Ciascun registro controlla una coordinata per ciascuno sprite:
Registro | Descrizione |
---|---|
53248 | sprite 0 X |
53249 | sprite 0 Y |
53250 | sprite 1 X |
53251 | sprite 1 Y |
…
I valori possibili sono quindi 0-255. Mentre la coordinata Y copre tutti i valori visibili a schermo, la coordinata X viene anche gestita dal registro 53264 ($D010) (valido per tutti gli sprite) che consente di estendere gli sprite oltre la coordinata X 255 (visibile a video solo fino al 343).
Colore
Gli sprite possono essere monocolore (risoluzione max 24×21) oppure multicolore (risoluzione max 12×21).
Multicolore
La modalità multicolore prevede, oltre al colore principale dello sprite, anche due colori aggiuntivi, condivisi da tutti gli sprite. Si usano i registri 53285 ($D025), 53286 ($D026) e 53276 ($D01C):
POKE 53285,1: REM MULTICOLOR 1 (BIANCO) X TUTTI GLI SPRITE POKE 53286,0: REM MULTICOLOR 2 (NERO) X TUTTI GLI SPRITE POKE 53276,3: REM MULTICOLOR X SPRITE 0 E 1
Colore principale
Il colore principale si setta nei registri 53287-53294 ($D027-$D02E), separatamente per ogni sprite.
Definizione
La definizione (forma) dello sprite avviene in questo modo. Sono presenti delle locazioni di memoria, ognuna dedicata ad uno sprite:
Locazione. | Descrizione |
---|---|
2040 ($7F8) | puntatore sprite 0 |
2041 ($7F9) | puntatore sprite 1 |
…
2047 ($7FF) | puntatore sprite 7 |
Ciascuna locazione non è abbastanza capiente per contenere la definizione di uno sprite (63 byte per i monocolore: 24 bit x 21); quindi ogni locazione è un puntatore ad un gruppo di locazioni di 63 byte. Ad es:
POKE 2040,200 POKE 2041,201
Le righe sopra stabiliscono che lo sprite 0 è definito (nella sua forma) al gruppo di locazioni che iniziano alla memoria 200×64 (12800); lo sprite 1 invece è definito al gruppo di locazioni che iniziano alla memoria 201×64 (12864).
Sarà necessario quindi riempire le locazioni che iniziano da 12800 e 12864 con i dati per formare gli sprite; conviene utilizzare un tool come il seguente, che facilita l'operazione di disegno:
Aiuta soprattutto quando si tratta di disegnare sprite multicolore. Le righe sottostanti riempiono le locazioni con i dati degli sprite (ottenuti dal tool sopra):
70 FOR X=12800 TO 12800+127: READ Y: POKE X,Y: NEXT X: REM SPRITE DATA 1000 :: rem pac_0 / multicolor / color: 3 1010 data 0,0,0,0,0,0,0,40,0,2,170,128,10,170,160,42 1020 data 170,168,42,170,168,41,106,88,165,89,84,165,249,124,165,249 1030 data 126,169,106,90,170,170,170,170,170,170,170,170,170,170,170,170 1040 data 170,170,170,170,170,170,170,170,170,162,130,138,128,130,2,131 1050 :: rem pac_1 / multicolor / color: 3 1060 data 0,0,0,0,0,0,0,40,0,2,170,128,10,170,160,42 1070 data 170,168,42,170,168,41,106,88,165,89,84,165,249,124,165,249 1080 data 126,169,106,90,170,170,170,170,170,170,170,170,170,170,170,170 1090 data 170,170,170,170,170,170,170,170,170,162,130,138,34,0,136,131
Le definizioni degli sprite sono due animazioni di un fantasma di PacMan; entrambe sono associate a due sprite. Si capisce quindi che ogni sprite può avere più definizioni/animazioni, che, come in questo caso, sono associate a sprite distinti:
POKE 2040,200 ... POKE 2040,201
Qui lo stesso sprite (un fantasma) ha prima una definizione/animazione, quella alla locazione 200×64=12800, poi una definizione alla locazione 201×64=12864.
In fondo alla pagina c'è il sorgente completo, che come risultato dà due fantasmini di PacMan che si spostano da sinistra a destra:
10 print chr$(147) 20 print "w commodore!" 40 poke 53285,1: rem multicolor 1 x tutti sprite 50 poke 53286,0: rem multicolor 2 x tutti sprite 60 poke 53269,255 : rem attiva tutti e 8 sprite 62 poke 53276, 3: rem multicolor sprite 0 e 1 64 poke 53277, 0: rem non allargare tutti sprite 66 poke 53271, 0: rem non alzare tutti sprite 67 poke 53287,2: rem color sprite 0 68 poke 53288,3: rem color sprite 1 70 for x=12800 to 12800+127: read y: poke x,y: next x: rem sprite data 85 for x=24 to 255 90 :: rem pac_0 100 poke 2040,200: rem pointer sprite 0 110 poke 53248, x: rem x pos sprite 0 120 poke 53249, 120: rem y pos sprite 0 130 poke 2040,201: rem pointer sprite 0 140 poke 53248, x: rem x pos sprite 0 150 poke 53249, 120: rem y pos sprite 0 160 :: rem pac_1 180 poke 2041,200: rem pointer sprite 1 190 poke 53250, x: rem x pos sprite 1 200 poke 53251, 150: rem y pos sprite 1 210 poke 2041,201: rem pointer sprite 1 220 poke 53250, x: rem x pos sprite 1 230 poke 53251, 150: rem y pos sprite 1 240 next x 1000 :: rem pac_0 / multicolor / color: 3 1010 data 0,0,0,0,0,0,0,40,0,2,170,128,10,170,160,42 1020 data 170,168,42,170,168,41,106,88,165,89,84,165,249,124,165,249 1030 data 126,169,106,90,170,170,170,170,170,170,170,170,170,170,170,170 1040 data 170,170,170,170,170,170,170,170,170,162,130,138,128,130,2,131 1050 :: rem pac_1 / multicolor / color: 3 1060 data 0,0,0,0,0,0,0,40,0,2,170,128,10,170,160,42 1070 data 170,168,42,170,168,41,106,88,165,89,84,165,249,124,165,249 1080 data 126,169,106,90,170,170,170,170,170,170,170,170,170,170,170,170 1090 data 170,170,170,170,170,170,170,170,170,162,130,138,34,0,136,131
Sprite animation e collision
Il seguente esempio è tratto dal libro Commodore 64 Graphics and Sound; è diverso rispetto al listato sopra, perché non ridefinisce gli sprite con un altro disegno, ma visualizza alternativamente due sprite, con due definizioni diverse per creare l'animazione, relative alla stessa figura (un alieno).
Definizione sprite
Vengono definiti i dati di 5 sprite, usando alcune locazioni di memoria a partire da (13*64=)832. Questa area è in realtà il cassette buffer, per cui se si usa il registratore, i dati degli sprite verrebbero soprascritti
130 poke2040,13:poke2041,14 140 poke2042,13:poke2043,14 150 poke2044,15
Spostamento e animazione
Si tratta quindi di 4 sprite 'alieni' più l'ultimo (2044) che rappresenta una esplosione. In realtà vengono visualizzati solo 2 sprite alla volta, all'inizio gli sprite 0 e 2 (definiti in 2040 e 2042), uno da un lato, l'altro dal lato opposto, con un'animazione 'a gambe aperte':
255 rem move sprites 0 and 2 260 pokevc,x:pokevc+4,255-x ... 285 rem display sprites 0 and 2 290 pokevc+21,5 300 for t=1 to 200:next
I registri nel VIC-II per le posizioni X degli sprite 0-3 (vc=53248, vc+2=53250, vc+4=53252 e vc+6=53254):
Il registro 'vc+21=53269' tramite il quale vengono visualizzati solo gli sprite abilitati:
Poi vengono visualizzati gli sprite 1 e 3 (2041 e 2043) con un'animazione 'a gambe chiuse', un po' più avanti nella direzione 'x':
305 rem move sprites 1 and 3 310 pokevc+2,x+4:pokevc+6,251-x ... 335 rem display sprites 1 and 3 340 pokevc+21,10 350 for t=1 to 200:next
L'effetto è quello di dare un'animazione a due alieni che si avvicinano, per poi scontrarsi. Di seguito il listato completo:
100 rem sprite movement and collisions 105 rem clear screen 110 print chr$(147) 115 rem vic chip start address 120 vc=53248 125 rem set sprite pointers 130 poke2040,13:poke2041,14 140 poke2042,13:poke2043,14 150 poke2044,15 155 rem read sprite data 160 for n=0 to 191 170 read a:poke832+n,a 180 next 185 rem set y positions 190 poke vc+1,150:pokevc+3,150 200 poke vc+5,150:pokevc+7,150 205 rem set sprite colors 210 pokevc+39,4:pokevc+40,4 220 pokevc+41,3:pokevc+42,3 230 pokevc+43,7:pokevc+21,0 240 for n=1 to 10 241 print chr$(147) 242 print"sp0,x:","sp2,x:" 243 print"sp1,x:","sp3,x:" 244 print "cont:";n"/10" 250 for x=0 to 130 step 8 255 rem move sprites 0 and 2 260 pokevc,x:pokevc+4,255-x 261 print "sq]]]]]]";x 262 print "sq]]]]]]]]]]]]]]]]";255-x 265 rem check for collision 270 cd=peek(vc+30) 280 if cd<>0 then 370 285 rem display sprites 0 and 2 290 pokevc+21,5 300 for t=1 to1000:next 305 rem move sprites 1 and 3 306 print "sqq]]]]]]";x+4 307 print "sqq]]]]]]]]]]]]]]]]";251-x 310 pokevc+2,x+4:pokevc+6,251-x 315 rem check for collision 320 cd=peek(vc+30) 330 if cd<>0 then 370 335 rem display sprites 1 and 3 340 pokevc+21,10 350 for t=1 to1000:next 360 next x 365 rem display explosion sprite 4 370 pokevc+8,x:pokevc+9,130 380 pokevc+23,16:pokevc+29,16 390 pokevc+21,16 400 for t=1 to 1000:next 410 pokevc+21,0:cd=peek(vc+30) 420 for t=1 to 500:next 430 next n 440 end 400 for t=1 to 1000:next 410 pokevc+21,0:cd=peek(vc+30) 420 for t=1 to 500:next 430 next n 440 end 795 rem sprite 0 and 2 data 800 data 0,102,0,1,255,128 810 data 15,255,240,31,255,248 820 data 63,255,252,63,60,252 830 data 63,60,252,63,255,252 840 data 31,255,248,15,255,240 850 data 3,0,192,6,0,96 860 data 12,0,48,24,0,24 870 data 48,0,12,96,0,6 880 data 192,0,3,0,0,0 890 data 0,0,0,0,0,0 900 data 0,0,0,0 905 rem sprite 1 and 3 data 910 data 0,102,0,1,255,128 920 data 15,255,240,31,255,248 930 data 63,255,252,63,60,252 940 data 63,60,252,63,255,252 950 data 31,255,248,15,255,240 960 data 3,0,192,6,0,96 970 data 12,0,48,24,0,24 980 data 12,0,48,6,0,96 990 data 3,0,192,0,0,0 1000 data 0,0,0,0,0,0 1010 data 0,0,0,0 1015 rem sprite 4 data 1020 data 96,24,12,48,24,24 1030 data 24,24,48,12,24,96 1040 data 6,24,192,3,25,128 1050 data 1,155,0,0,255,0 1060 data 0,102,0,255,231,255 1070 data 0,102,0,0,255,0 1080 data 1,155,0,3,25,128 1090 data 6,24,192,12,24,96 1100 data 24,24,48,48,24,24 1110 data 96,24,12,0,0,0 1120 data 0,0,0,0