8-way Smooth Scrolling
9:58
2 ай бұрын
Smooth Scrolling Verticale
9:27
4 ай бұрын
Vertical Smooth Scrolling
9:27
4 ай бұрын
Sprite collision detection
6:42
6 ай бұрын
C64 Sprite Multiplexing (EN)
12:34
C64 Sprite Multiplexing (IT)
12:34
Newsstand
1:26
Жыл бұрын
Teaser Trailer NewsStand
2:30
Жыл бұрын
C64 Graphics Maker (part I)
54:49
3 жыл бұрын
C64 Graphics Maker (part II)
16:37
3 жыл бұрын
Planet Balls for C64
5:32
3 жыл бұрын
C64 Planets Ball Intro
1:39
3 жыл бұрын
C64EMU
2:16
4 жыл бұрын
Planet balls
2:54
7 жыл бұрын
Пікірлер
@Phaze101
@Phaze101 7 күн бұрын
Hi excellent video. I have watched this video many times. Left you a comment earlier but not sure I save it so here it is again. Tried to get in touch with you in the past since I would like to know if you share such code on github. Anyway thanks for your work and these great videos.
@Phaze101
@Phaze101 6 күн бұрын
Please Please continue to make such videos
@agpxnet
@agpxnet 2 күн бұрын
Hi, thanks. Usually you can found the code in the description of every video, but in this specific one there's no code to share in addition to the one showed in the video.
@kraftwerk974
@kraftwerk974 20 күн бұрын
Great tutorial. Now I need to convert something similar to 6510 assembly 😑
@francescocarandina3982
@francescocarandina3982 27 күн бұрын
Ciao Sono nuovo, Mi sono appena avvicinato a questo linguaggio e avrei tanta voglia di imparare. Scusa le domande un po' profane, hai creato tu questo software? Ha le stesse funzionalità di charpad e Sprite pad? Quando si fa un disegno sul foglio e si decide di mettere le tile si può fare anche un misto ovvero disegno con un mono carattere per parte più dettagliate il contorno usare delle tile?
@agpxnet
@agpxnet 27 күн бұрын
Ciao, sì, ho creato io questo software. Non ho confrontato con gli altri tool che menzioni, l'ho creato per scopi personali e poi ho deciso di renderlo pubblico. Se scegli un colore per il singolo carattere della tile compreso tra 0 e 7, lo vedrai monocolore.
@francescocarandina3982
@francescocarandina3982 27 күн бұрын
@@agpxnet purtroppo non ho windows 64 bit per installarlo
@puzzud
@puzzud Ай бұрын
Am I correct in saying this approach works because the screen will scroll regardless of player input? Conversely, if the camera is directly or indirectly controlled by the player, the screen must be scrolled on command. What are solutions for this condition? Edit: I thought about it a bit. If a hardware scroll gets close to 0, it can start to build the backbuffer preemptively, even if it is never realized due to the camera being moved in the opposite direction before the buffers should be swapped. In my case, the background graphics can change. I guess I need to ensure changes get propagated to both the front and back buffer.
@agpxnet
@agpxnet Ай бұрын
The approach works even if totally controlled by the user also because the scrolling direction in this example is only one (you can download the demo and check the result). However, in the video I made about horizontal scrolling, I added the ability to go back and forth. In that case it works because when I go back, if I don't have enough pixels left to fill the backbuffer, at the last pixel, I update what's left in the backbuffer. Could be expensive, but it only happens when changing direction and is not noticeable (as you can see from the downloadable demo). There also other alternative approaches, like the one I used in my video on 8-way scrolling, which is used by many games like Turrican. Yes, if the background changes you must update it carefully. In my game Planet Balls, I have free-directional scrolling with double buffer and the background graphics change (since there are a maximum of 12 balls, 7 are hardware sprites and 5 are "software" sprites made with redefined characters).
@igork3522
@igork3522 2 ай бұрын
Thank you for your videos and code access!
@c64cosmin
@c64cosmin 2 ай бұрын
This is purely incredible, amazing work and thank you for sharing <3
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 2 ай бұрын
Now I understand “operation wolf” . It has the status icons at the side. So it can use the full 320px horizontal resolution with scrolling. This may also hide the sprite pointers at the bottom. Of course for most games it makes more sense to use sprites for game objects. I should check how they managed the colors. On C64 you have to use multiple sprites per game object just to pull in another palette entry.
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 2 ай бұрын
With 2px speed the counting of the directions becomes a bit cumbersome. There is a video about an NES game where the position of the player figure is calculated using 16.8 fixed point math. Now add some camera smoothing and remember that we update at 60 Hz. Then no discernible directions will be recognisable by the player. Like Asteroids.And you check the button stage twice per frame for uh, more directions. Ah, the controls are the limit. I coded a bit on my C16 with 64k last month. To really follow your video I feel like I have to write something myself. Of course I am a bit anti NES and want to show of the 8x8 color attribute resolution of the commodores. So maybe 4x4 super tiles are just not for me. With TED I thought I just use quad buffer. I am not Creative. Now way I will overflow memory. But then this waste hurts. You got me thinking about sticking to a double buffer. At least TED cannot VSP, so I don’t need to defend the memCopy. Uh, but then my coding on real hardware was about vertical borders. TED has an y register which I can write to, but it only affects the borders, it doesn’t scroll. On both VIC-II and TED you can crunch the first character line to delay memcopy for vertical. So the backbuffer will be a shifted up or down version only if the smooth X scroll register is at 3 or 4. Otherwise the backbuffer contains something shifted a character left or right (and possibly also up or down). Is there a part in the video where you talk about “abort and revert” . Like when a scrolling routine after one of 4 frames recognized that it has to undo its work? I tried to find the word: gradually. Like a boundary is stored and two scroll states for both sides. I only played Super Mario Maker, but all this discussion about bounding boxes pushed me to this: I want to see Sonic the Hedgehog with ramps, slides, and looping made of 8px long segments. So 2d vector graphics and physics. Just make the level so that the fast sonic can escape our 2px camera. Also, how to play with only one button? Run button, and jumps are “up”?
@rwxdesigns
@rwxdesigns 3 ай бұрын
Suggestion - the text colour of yellow on the grey background didn't really stand out and it made it difficult to read. Try another colour for better contrast in your next video. Thanks. 👍
@gaming.brain.gameplay
@gaming.brain.gameplay 3 ай бұрын
Bellissimo!
@FabioOttaviani
@FabioOttaviani 3 ай бұрын
A conoscere tutte queste tecniche, soprattutto lo sprite multiplexing nel 1990… Ma ero giovane e non trovavo la documentazione da nessuna parte. 😢😢 Ho dovuto fare moltissimi compromessi nei miei videogiochi. 😢😢😢
@agpxnet
@agpxnet 3 ай бұрын
A chi lo dici, era davvero difficile reperire informazioni e senza internet (né sufficiente familiarità con la lingua inglese) la conoscenza era per pochi privilegiati.
@carlosimetti2319
@carlosimetti2319 4 ай бұрын
Ottimi contenuti molto tecnici come sempre :-)
@andreal2023
@andreal2023 4 ай бұрын
Mito.
@thumper5555
@thumper5555 4 ай бұрын
AI voices suck. Thumbs down.
@agpxnet
@agpxnet 4 ай бұрын
I'm sorry, but my english pronunciation is unlistenable (see, for example, my video tutorial in English on the C64 Graphics Maker).
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 4 ай бұрын
AI gets better all the time. KZfaq in on mute for me most of the time so I wouldn’t know.
@SK83RJOSH
@SK83RJOSH 4 ай бұрын
​​​@@agpxnet I think your accent is fine! I work with games here in Europe, and I've met Italians that are far far worse. I think you'd benefit greatly from a condenser microphone through - the audio quality was the worst part about that video, but I felt you were very intelligible otherwise. Keep up the great work, and do it however you feel is best 😊
@Rothron
@Rothron 4 ай бұрын
@@agpxnet I think your pronunciation is less of an issue than the quality of the microphone and the reverb/echo in the room you record in. English with accent is preferable to this AI voice to me at least.
@meatbleed
@meatbleed 4 ай бұрын
more like classic tts. been here for decades. not everyone speaks your shitty language
@giuseppeazzarello8426
@giuseppeazzarello8426 4 ай бұрын
buongiorno agpxnet , come sempre spegazione è video impeccabili
@networkg
@networkg 4 ай бұрын
Excellent video tutorial. One concept per video. Makes learning easy.
@jadermonari2272
@jadermonari2272 4 ай бұрын
Non ho parole... bravissimo, mi piacerebbe avere un mentore come te!
@agpxnet
@agpxnet 4 ай бұрын
Addirittura, grazie 🙂. Se vi piacciono questi contenuti e volete vederne ancora, vi prego di condividere questo video (magari anche su social networks). Grazie!
@maxmuster7003
@maxmuster7003 4 ай бұрын
For many years i used smooth scrolling on C64 screen, but then an UFO beamed me up and ejected me on the x86 alien planet with a new command prompt. After learning the alien language i made a new vertical smoot scroller for the vga text screen with 8x16 font size for up and down scrolling.
@ZombieGamer80
@ZombieGamer80 4 ай бұрын
Complimenti, è fluidissimo. Il sistema delle TILES per risparmiare memoria c'é anche nel SEUCK... ;)
@agpxnet
@agpxnet 4 ай бұрын
Grazie, sì, le tile sono molto usate. Nel SEUCK sono grandi 8x8 e secondo me è un po' troppo (rende più difficile creare le schermate), inoltre tutti i 64 caratteri hanno un solo possibile colore di primo piano (e questo, oltre a risparmiare memoria, accelera la loro routine di scrolling del colore), mentre nella mia implementazione i 16 caratteri di una tile possono avere ognuno un colore diverso (nel SEUCK non puoi fare una tile con lo stesso cartello AGPX visto nel mio demo, dove ogni lettera ha un colore diverso ;-).
@Mark-pr7ug
@Mark-pr7ug 4 ай бұрын
If I recall correctly on the Amiga for smooth horizontal scrolling you had to create 2 additional screens. One either side of the main display in order for the hardware scroll to work. (All 3 displaying the same image) I once tried one screen which was 16 pixels larger on both sides. Both sides hidden behind the border. When scrolled and a fresh column of 16x16 were drawn behind the border, the scroll went crazy.
@agpxnet
@agpxnet 4 ай бұрын
I don't know how Amiga works, I've never had it. We'll see with the Commodore 64...
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 4 ай бұрын
The Amiga documentation talks a lot about modulo. The screen can have modulo 320px or 640px, but I could not find out what a bitplane can have .. or a playfield. The blitter can deal with any modulo in all channels. Why would you need something on “either side”. Instead of borders intruding the screen, on the Amiga you have a bit to load a word early ( but then smooth scroll delay it , so I guess they mean that you can smooth scroll the whole range 0..16 , though 0=16 ? Or you have to set an additional bit when you smooth scroll 1-15 ?? EGA and VGA with their dedicated memory just always loaded more pixels. Chunky VGA would throw away only 4 of them. 8 bit per plane EGA would only throw away 4 bytes.
@syedrizvi2469
@syedrizvi2469 4 ай бұрын
Hi there! I cannot seem to open the ScrollDown.gmk64 file, which Assembler is it compatible with?
@agpxnet
@agpxnet 4 ай бұрын
Hi, you can open it with a free software made by me called "C64 Graphics Maker", that's a graphic editor for C64. From there you can export "data" in a format suitabile for your project. You can found it here (with other software of mine): agpx.itch.io/
@syedrizvi2469
@syedrizvi2469 4 ай бұрын
Hi, I was more after the scrolling assembly code to accompany the graphics. If you could please provide Code for scrolling the graphics vertically! Thanks
@agpxnet
@agpxnet 4 ай бұрын
The assembly code is inside the Scrolling.bas file (inline assembly).
@MarkWernsdorfer
@MarkWernsdorfer 4 ай бұрын
the ai voice is awful :(
@agpxnet
@agpxnet 4 ай бұрын
Sorry for that, mine is worst. I've published subtitles.
@giuseppeazzarello8426
@giuseppeazzarello8426 4 ай бұрын
i tuoi video sono spettacolari, bellissimo, spero che ci siano molte persone interessate, in modo che ti stimolano a proseguire, sarebbe un peccato, non approfittarne. comuqneui auguri per il tuo superamento in cosi poco tempo dei 1000 iscritti
@agpxnet
@agpxnet 4 ай бұрын
AGGIORNAMENTO: ho aggiornato il codice per ottimizzare la routine che copia il buffer nella memoria colore. NOTE sul buffer dei colori: Nel video ho dimenticato di menzionare la ragione per la quale durante lo scrolling dei 7 pixel, copio la memoria colore in un buffer (anziché scrollarla direttamente all'ottavo). La ragione è che, altrimenti, dovrei scrollare i colori dal basso verso l'alto. Senza il buffer, se facessi il contrario, dovrei ad esempio copiare la riga 1 nella 2 e poi la riga 2 nella 3, ecc... Ma copiando la riga 1 nella 2, quest'ultima viene sovrascritta e quindi nel passo successivo (2 -> 3) copierò dati sbagliati! Se invece parto dal basso copiando la 22 nella 23 e poi la 21 nella 22, non c'è nessun problema. Vi chiederete, ma perché copiare dal basso verso l'alto non va bene? Il motivo è che il pennello ottico è uno tsunami che corre come il vento! Sfortunatamente, quando esso ricomincia a disegnare lo sfondo, la CPU non avrà ancora completato tutto il lavoro di scrolling dei colori! Tuttavia, scrollandoli dall'alto al basso, ed essendo partita in anticipo sul pennello ottico (quando quest'ultimo si trovava all'inizio del bordo inferiore), le prime righe che incontrerà saranno già state completate e la CPU riuscirà comunque a completare l'ultima riga prima che venga raggiunta! Questa tecnica si chiama "gareggiare con il pennello ottico" che non è applicabile se invertissimo l'ordine di scrolling dei colori perché la prima riga raggiunta da quest'ultimo, verrà aggiornata per ultima dalla CPU!
@agpxnet
@agpxnet 4 ай бұрын
UPDATE: I updated the code to optimize the routine that copies the buffer into color memory. Thanks to @ArneChristianRosenfeldt for pointing out some naiveties of my previous implementation. NOTE on color buffer: In the video, I forgot to mention the reason why, during the scrolling of the 7 pixels, I copy the color memory into a buffer (instead of scrolling it directly at the eighth pixel). The reason is that, otherwise, I would have to scroll the colors from bottom to top. Without the buffer, if I did the opposite (for example) copying row 1 into row 2 and then row 2 into row 3, etc., by copying row 1 into row 2, the latter gets overwritten, and therefore in the next step (2 -> 3), I would copy incorrect data! On the other hand, if I start from the bottom by copying row 22 into row 23 and then row 21 into row 22, there is no problem. You might wonder, why is it not okay to copy from bottom to top? The reason is that the raster beam is like a tsunami that rushes like the wind! Unfortunately, when it restarts drawing the background, the CPU has not yet completed all the work of scrolling the colors! However, by scrolling them from top to bottom and starting ahead of the raster beam (when it is at the beginning of the bottom border), the first rows it encounters will have already been completed, and the CPU will still manage to complete the last row before it's reached! This technique is called "racing with the raster beam," which is not applicable if we were to reverse the order of scrolling the colors because the first row reached by the raster beam will be updated last by the CPU!
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 4 ай бұрын
What I like about this method is that it works even better on TED (plus4). There you have a 1.8 MHz CPU in the lower/upper border and 4 useful pages for both the characters and colors. So for all direction scrolling we can waste a lot of memory and have 3 other pages half prepared if the camera moves close to a point where both scrollX and scrollY can wrap around... We should really squeeze every cycle out of the memCpy to at least bring this down to filling thirds of the other page with the scrolled versions. Then we only have to copy 3/2 characters. This is probably the reason why many games have a character status bar at the bottom: This thing just reduces the character count in the scrolling area to just make it work. So no need to use sprites for this as in non-scrolling games. I admired the status overlay using sprites on NES, but really it is just due to the limitation of the hardware. If you scroll on NES, the status appears in the playfield. EGA is similarly stupid. Status screen at 0 can appear on the lower edge of the screen, but then you have to place your Xenon2 playfield besides it and waste half of the video memory .. although EGA would store sprites there, like in a time when the ISA bus was considered fast and games actually read from vram ...
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 4 ай бұрын
I wonder if the repeated lda {ColBuf}+40*0,x sta {COLMEM}+40*0,x inx could be generated at runtime, like we do for webpages or Wolf3d did for the column renderer. Also why waste 2 cycles on inx here, but not here: lda {VIDMEM0}+40*0,x sta {VIDMEM1}+40*1,x lda {VIDMEM0}+40*1,x sta {VIDMEM1}+40*2,x ah got it. The second example does not fit into one byte. But a general generator would probably generate code without INX for both. I wonder why you don't align to 256 byte pages for the color buffer scrolling to save another cycle? Like you would copy 216 bytes inside a page and 40 bytes cross a page with x starting at 0 again to prevent the carry. Is the 6 important here? This does not seem to be Sonic the Hedgehog. You scroll max 8 pixel per frame.
@agpxnet
@agpxnet 4 ай бұрын
Good points. If you try to replace lda/sta/inx with something like: scroll: lda {ColBuf}+40*0,x sta {COLMEM}+40*0,x lda {ColBuf}+40*1,x sta {COLMEM}+40*1,x lda {ColBuf}+40*2,x sta {COLMEM}+40*2,x lda {ColBuf}+40*3,x sta {COLMEM}+40*3,x lda {ColBuf}+40*4,x sta {COLMEM}+40*4,x lda {ColBuf}+40*5,x sta {COLMEM}+40*5,x lda {ColBuf}+40*6,x sta {COLMEM}+40*6,x ...(repeat until line 22)... inx cpx #40 bne scroll It shows artifacts. The reason is that you copy by columns and not by rows. Copying by columns is bad because you can't race the raster beam: the main reason why I need the ColBuf is because it allows me to scroll the colors from top to bottom (I've posted details in my pinned comment). I forget to mention this important fact in the video, my fault. Btw, we can reduce cycles like the following: ldy #0 ldx #0 scroll: lda {ColBuf}+40*0,x sta {COLMEM}+40*0,x lda {ColBuf}+40*0+1,x sta {COLMEM}+40*0+1,x lda {ColBuf}+40*0+2,x sta {COLMEM}+40*0+2,x lda {ColBuf}+40*0+3,x sta {COLMEM}+40*0+3,x lda {ColBuf}+40*0+4,x sta {COLMEM}+40*0+4,x lda {ColBuf}+40*0+5,x sta {COLMEM}+40*0+5,x lda {ColBuf}+40*0+6,x sta {COLMEM}+40*0+6,x lda {ColBuf}+40*0+7,x sta {COLMEM}+40*0+7,x ldx {add8},y ; lookup table to add 8 to x iny cpx #240 bne scroll add8: !byte 8, 16, 24, 32, ....., 240 Finally, yes, it's definitely better to align the color buffer to 256 to avoid the extra penalty of crossing the boundary. I will update the code. Thanks for pointing them out.
@agpxnet
@agpxnet 4 ай бұрын
Done. Source code updated. Thanks again.
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 4 ай бұрын
@@agpxnet ah, so it would have to be done in two parts at least (top and bottom). So using the full pages the unrolled loop would only do two copies. With more unrolling, x never becomes large and carry doesn’t happen often.
@networkg
@networkg 4 ай бұрын
Thank you so much for the English language version. You are just brilliant at explaining Commodore 64 programming.
@agpxnet
@agpxnet 4 ай бұрын
If you like these videos, please share! Thanks!
@kimyona5274
@kimyona5274 4 ай бұрын
A very good explanation. Thanks a lot for the time and effort you put into these tutorial-videos!
@agpxnet
@agpxnet 4 ай бұрын
If you like these videos, please share them and you will help me produce more! Thank you!
@gamesgonenuts
@gamesgonenuts 5 ай бұрын
cool to see how this is done smashed the like
@agpxnet
@agpxnet 5 ай бұрын
Happy to hear that. If you liked my video, please share it so I can make more. Thanks in advance.
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 5 ай бұрын
RLE Leads to this distribution of lengths. Either let the compressor find out max length and number of bits needed or add a Huffman coder. Maybe even length 0 can be included and very long spans are coded repeatedly? Can of worms.
@agpxnet
@agpxnet 5 ай бұрын
Yes, I definitely need a better compression scheme and Huffman is the natural choice. I used RLE just because it's very simple to implement and the decompression is very fast.
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 5 ай бұрын
@@agpxnet yeah and it works. I just mean that RLE has a natural choice for length and that is 8 bits. But that feels so arbitrary. It sure works great for platforms! Windows bitmap format offers RLE, but nobody seems to use it. All I know is gif and jpeg.. I think that jpeg uses RLE with Huffman. Huffman has this connection to entropy coding / arithmetic coding and Shannon information theory. Would be interesting to see an arithmetic codec on a C64. Maybe a background task to complete level loading?
@giuseppeazzarello8426
@giuseppeazzarello8426 5 ай бұрын
Ciao, ho provato a realizzare, quando da te egregiamente spiegato, per quando riguarda la collisione sprite/sfondo, utilizzando le coordinate, che apparentemente mi sembravano di aver capito tutto , e di facile applicazione , , ma sto avendo delle difficolta., non volevo disturbarti, ma la volonta di imparare e forte ed allora chiedo supporto. Al momento non sto usando xcbasic. In quando a causa di un prolema forse un virus al sistema operativo , ho dovuto formattare il pc , adesso pero ho difficolta ad installare xcbasic , ho instalato anche il tools for visual studio ma niente. Pertanto ho pensato di realizzare un piccolo programma in basic , per mettere in pratica le nuove procedure di programmazione viste nel tuo tutorial , cerco di realizzare il programma in basic, poiche è il modo migliore per imparare ed analizzazione il codice , e successivamente convertirlo in assembly o altro, sempre nei limiti della mia capacita. Pertanto , in base a quello che ho capito, ho cercato di realizzarlo , ma senza ottenere alcun risultato, apparentement sembra corretto, ma sicuramente ce del codice erraro. Applicando le formule da te descritte, le collisione non avvengono, o meglio una collisione avviene solo in quella frontale , lo sprite si ferma solo dopo aver attraversato completamente la parete (codice 165), ho visti e rivisto il codice e il tuo video, ma non riesco a venirne fuori . Pertanto chiedevo, un tuo supporto , per risolvere e capire dove sta l errore , naturalmente con spiegazione , grazie. 10 print chr$ (147) 20 poke 53280,7 :poke53281,1 :rem colore bordo/schermo 30 V=53248 :rem Inizializza area video Chip II 40 x=80: y=90 :rem Impostazione iniziale coordinata X e Y 50 poke 650,128 :rem ripetiz automativa tasti 60 POKE53287,5 :rem colora lo sprite 0 (5=verde) 70 pokev+21,1 :rem abilita sprite 0 (valore 1) 80 REM PUNTATORIA AREA DISEGNO SPRITE E CARICARICAMENTO 90 poke2040,192 100 for n=12288 to 12350: readq :poken,q: next 110 REM CARATTERI CON CUI COLLIDERE 120 PRINT "{home}{down*3} {cyan}{185}{185}{185}{185}{185}{185}{185}" 130 PRINT " {165}" 140 PRINT " {165}" 150 PRINT " {165}" 160 PRINT " {165}" 170 PRINT " {165}" 180 PRINT " {165} EEEEEEEEE" 190 PRINT " {165}" 200 PRINT " {165}" 210 PRINT " {165}" 220 PRINT " {165}" 230 PRINT " EEEEEEEEE" 240 REM COORDINATE POSIZIONE INIZIALI SPRITE 250 pokev+0,x :rem coordinata X dello sprite 0 260 pokev+1,y :rem coordinata Y dello sprite 0 270 xx=x:yy=y 280 REM GESTIONE TASTIERA 290 GETa$ 300 if a$=chr$( 29) then x=x+2 :rem con "r" sposta lo sprite a destra 310 if a$=chr$(157) then x=x-2 :rem con "l" sposta lo sprite a sinistra 320 if a$=chr$( 17) then y=y+2 :rem con "d" sposta lo sprite in giu 330 if a$=chr$(145) then y=y-2 :rem con "u" sposta lo sprite in su 340 REM SALTO 350 if a$=chr$(88) then s=4 :gosub 520 :rem con "x" SALTO DESTRA 360 if a$=chr$(90) then s=-4 :gosub 520 :rem con "z" SALTO SINISTRA 370 REM POSIZIONE CARATTERE 380 cx=int((x-24)/8) 390 cy=int((y-50)/8) 400 REM FORMULE COLLISIONE 430 q=peek(1024+cx+cy*40) 450 if (q=101) or(q=165) or (q=185) then x=xx and y=yy :goto 110 460 REM CONFINI 470 if x=<24 then x=24 :rem limita il bordo sinistro 480 if x=>255 then x=255 :rem limita il bordo destro 490 if y=<50 then y=50 :rem limita il bordo > 500 if y=>229 then y=229 :rem limita il bordo < 510 goto 110 520 REM SALTO DESTRA E SINISTRA 530 for H=-12 to 12 step2 550 x=x+s :rem > valore >distanza 560 y=y+H*.5 :rem > valore > altezza(.5),utilizzare valori <= .5 570 pokev,x 580 pokev+1,y 590 next 600 return 620 DATA 3,192,0,3,128,0,3,192,0,3,192,0,1,128,0,1,128,0,1,192 630 DATA 0,1,224,0,3,240,0,3,240,0,7,248,0,13,239,128,9,224,0,17 640 DATA 224,0,3,240,0,7,248,0,15,220,0,62,12,0,48,12,0,32,6,0 650 DATA 0,7,0
@agpxnet
@agpxnet 5 ай бұрын
Ciao, non ti preoccupare, sono felice di rispondere al tuo quesito. Nel video non sono stato probabilmente molto chiaro, ma la coordinata X e Y alla riga 380 e 390 non dev'essere quella dell'angolo in alto a sinistra dello sprite, ma quella del punto di possibile contatto (il quadratino verde dal minuto 1:23, vedi anche da 4:53). Nel caso dell'urto a destra, nel tuo caso, è data dalla coordinata X dello sprite più una costante, che nel caso del tuo sprite potrebbe essere 15. Quindi cambia la riga 380 con la seguente: 380 CX=INT(((X+15)-24)/8) o se vuoi semplificarla: 380 CX=INT((X-9)/8) poiché 15-24 fa -9. Questo solo per la collisione verso destra. Dovrai ripetere il test per sinistra, sopra e sotto con costanti specifiche (nelle posizioni sopra e sotto dovrai ovviamente agire sulla riga 390 anziché la 380). I punti da testare, in pratica, stanno ai confini dello sprite nelle 4 direzioni: è la che devo vedere con quale carattere sto urtando. Alcuni consigli. E' preferibile usare il joystick anziché la tastiera per leggere l'input, poiché il joystick ha una risposta molto più veloce e non ha un buffer come la tastiera. Se non sai come fare, puoi vedere i vari esempi che ho postato (dal Pac-Man a "The Runner"). Se non risultasse chiaro, ti posso spiegare come fare. Alla riga 510 è meglio non saltare alla 110, ma alla 240: 510 GOTO 240 così eviti di tracciare continuamento lo schermo (che non è cambiato) e questo accelera un po' l'esecuzione. Il ciclo principale del gioco fa le seguenti azioni: 1. Leggi input (tastiera o joystick) 2. Muove player (di un passo solo) e testa collisioni 3. Muove nemici (di un passo solo) e testa collisioni 4. ripeti dal punto 1 Ho visto che nel salto esegui un ciclo FOR. Questo va bene se non c'è altro che si muove nella scena, in caso contrario tutto il resto resterebbero fermo finché il ciclo non si completa. Per ovviare a questo problema è necessario eseguire, ad ogni ciclo, un piccolo movimento per ognuno degli "agenti" in gioco. Quindi se stai saltando, ti muoverai di un pixel verso destra e uno verso l'alto (o in movimento parabolico). Se c'è un nemico che si sta muovendo verso sinistra, ne decrementerai la coordinata di 1 pixel. E così via frame per frame. In questo modo si avrà la sensazione che tutti gli oggetti si muovano contemporaneamente. Un modo semplice di gestire questa cosa è implementare una macchina a stati per ogni agente (vedi video e codice sorgente di "The Runner"). Infine, ti consiglio vivamente di usare un linguaggio compilato come XC=BASIC 3, anziché il BASIC interpretato. Io utilizzo Visual Studio Code, se vuoi posso spiegarti un modo semplice per utilizzarlo con XC=BASIC. Per semplici giochi va più che bene e ti eviti la fatica di scrivere in assembly. Se hai altri dubbi, chiedi pure.
@giuseppeazzarello8426
@giuseppeazzarello8426 5 ай бұрын
video e spiegazione impeccabile, con questi video si riesce a capire anche la dinamica di ogni azione nei minimi paicolari
@Chick2Disk
@Chick2Disk 5 ай бұрын
This is a series of great videos! Thanks for the effort you put!
@agpxnet
@agpxnet 5 ай бұрын
If you find them useful, please share these videos so I can make more. Thank you.
@Chick2Disk
@Chick2Disk 5 ай бұрын
​@@agpxnetDone😊
@WolfgangS
@WolfgangS 5 ай бұрын
Well, this information comes 40 years too late ... But thank you anyway ...
@DoomRater
@DoomRater 5 ай бұрын
I remember theorizing about multiplexing while I owned my C64 as a kid but never got the chance to try and implement it. I didn't know if any game I could write would have enough speed to attempt it either. But my tools were as crude as my understanding, and self written too, so I can't be too hard on myself
@carlosimetti2319
@carlosimetti2319 5 ай бұрын
Ottima spiegazione , complimenti per il video! Una curiosità a che età hai iniziato a mettere mano sull'assembly del 6510?
@agpxnet
@agpxnet 5 ай бұрын
Ciao, grazie. Intorno ai 10 anni, ma a 16 sono passato al PC. Ho ripreso il C64 nel 2020, 28 anni dopo.
@agpxnet
@agpxnet 5 ай бұрын
Update: in the description you can find a second version of the formula implementation, which requires only 50 bytes instead of 512, spending 12 more clock cycles. It depends on the circumstances: whether you need maximum performance or to save memory. And speaking of performance, you can also avoid subtracting 24 and 50 in the formula and instead do it directly in the coordinates of the contact points.
@agpxnet
@agpxnet 5 ай бұрын
Aggiornamento: nella descrizione potete trovare una seconda versione dell'implementazione della formula, che richiede solo 50 bytes anziché 512, spendendo 12 cicli macchina in più. Dipende dalle circostanze: se vi serve avere le massime performance oppure risparmiare memoria. E a proposito di performance, si può anche evitare di sottrarre 24 e 50 nella formula e farlo invece direttamente nelle coordinate dei punti di contatto.
@jadermonari2272
@jadermonari2272 5 ай бұрын
Grazie !!! Molto utile!!!
@MichaelBattaglia
@MichaelBattaglia 5 ай бұрын
Great explanation and demos!
@mityaboy4639
@mityaboy4639 5 ай бұрын
my only comment on this would be that for such a simple platformer (and such limited memory and cpu power) one contact(check) point would be perfectly enough. To make the game work smoother, the collision reference point needs to be reallocated when the character turns around (so that it always looks like its under the feet in front) In an environment where the movement is more refined, and needs more precision i tend to use 3 points (left, center, right) and depending on the game mechanics, check for the relevant ones to determine whether the character needs to fall, continue to fall or stop. but thats also because i am too lazy to recalculate the positions :D with wall (door) detection i tend to use a more or less acceptable collision box - but here i think the whole sprite would only need maybe 4 points to calculate front, back, feet and head bumps and then act accordingly. Also also: i don't think we need to check constant collisions while we are walking / running - what we need is check into the next move to determine if our next step would land on the filed or not - if it does, then do nothing - if it will fail then trigger a fall sequence. jump also only need to test for collision under the feet while falling (which makes the logic the same thus the code smaller) (falling and finishing off a jump is the same process) And lastly while on the commodore you have to be careful with memory, normally we shouldn't track the video memory - but rather keep an internal status of where a platform is on the screen. (this is a comment for whoever decides to do this on any more modern hardware) for example if you try to do this on a canvas in Javascript (its a good platform to practice these concepts) - reading back from the canvas comes with huge cost on performace - it makes more sense to not to :) On a C64 it has some clear advantage - as the system memory and screen memory is the same from a technical point of view, just on a different address - but all handled by the CPU therefore no performance loss there anyway, good material :)
@agpxnet
@agpxnet 5 ай бұрын
The contact points with the floor shown are purely indicative. Of course, in the demo I don't use two points for a single foot, but for a larger segment. In my experience, one point of contact is not enough. Especially, if the player lands very close to the end of a platform. In any case, I calibrated the test points empirically. In the demo I use 3 test points: 1 front and 2 for the feet (which are flipped together with the player). I don't need the rear, in my case the front is enough. A point for the head could be added, but currently the demo does not take this into account. I check the 3 points for each frame and if there is nothing under my feet, I activate the fall procedure. When I jump, I also test the front point because I might hit the key or another object and I prefer it to be caught by the player. However, how many and which points to use is a choice, it depends on what you want to achieve. As for accessing video memory, obviously this tutorial is designed for Commodore machines, I would never dream of reading the video memory of a GPU, it's a huge bottleneck. Thanks for the comment.
@Icelink256
@Icelink256 5 ай бұрын
@@agpxnet In my experience, one point of collision really only works, when slopes are involved...
@agpxnet
@agpxnet 5 ай бұрын
​@@Icelink256Depends on the scene. In that showed in the demo, after some tests, I see that 2 points work better. In any case slopes require a special treatment. I will try to investigate it, thanks for the suggestion.
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 5 ай бұрын
Why do we need to supply contact points? I thought that they are the result of a collision, and used to confine to sliding and rotation. So your sprite moves 2px per frame max? Then do two game steps. So you detect any stick after one px and just go back a game step .. even at angles. Fast games like Sonic the Hedgehog are more difficult. Good explanation while sprite tile collision doesn’t work. If at least this was limited to mines and spikes .. like char >= $B0 or so Do we need a real z coordinate to jump onto platforms from the front? SuperMario bounces his head.
@agpxnet
@agpxnet 5 ай бұрын
Perhaps the term contact points is not very suitable, I should have called them test points, but the substance does not change (contact points in the video are the points where, we suppose, the sprite can potentially have contact with a character). The video simply shows a way to determine what characters a sprite is colliding with, or to be more precise, what characters we have in the test points. We are talking about discrete (not continuous) collisions: the continuous, on slow processors like the 6502, are difficult to implement in real time. I don't understand what you mean when you say the collision system doesn't work. In the demo the speed (i.e. the number of pixels) with which the player moves is almost constant, but it's a choice, not a limitation, it could be variable. Up to a certain step size (but this depends on the background) the system works perfectly (it depends also on how you implement the response to the collision, which we will see in the next video), beyond some value there may be the "tunnel effect", which can cause the sprite to skip a wall (however there are some solutions to alleviate this problem).
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 5 ай бұрын
@@agpxnet I mean, a step size over 1px needs vectors. DIV and MUL. 6502 has super fast bit test. Maniac Miner had the walking animation aligned to bit shift. Otherwise shift takes two branches. We could call the points the Minkowski sum of the sprite and the 8x8 block. I may need to rewatch what you said about other background tiles. Now I come back to open borders ( top and bottom ). Set the whole palette to the background color. Clear idle byte. Copy the surrounding background of the player into one or two sprites. Good thing is that we don’t need the zero page for this ( unlike the CPU method ). Then test 6 position/animation frames before the screen starts: “bounce back” before the racing electron beams sees us in the wall. With 4 sprites for background incremental all directions update is possible. Looks like 2*21 sprites can be stacked in the top. 8 scanlines ( none of which is bad ) should be enough to bounce. Put the background sprite in slot 0..3 so that they don’t steal cycles from the CPU. I would not waste memory on look up for your formula. SEC SBC 50 SHR SHR SHR is like 10 cycles? The sprite method allows to 2x zoom the monochrome collision map to match multicolor resolution. Maybe your game allows to hide an area in the background. ( sky , earth , status display) and then try collisions there. Can use chars , but it is all hires then.
@agpxnet
@agpxnet 5 ай бұрын
@@ArneChristianRosenfeldt Subtracting 50 and dividing by 8 is not enough, we also have a product (* 40), for which I would use a look-up table. Anyway, the implementation shown tries to be as efficient as possible, but the tradeoff between speed and memory depends on how many resources are left. In any case, by spending 12 more clock cycles I can reduce the table from 512 bytes to 50 bytes which I think is acceptable in the end. I've added another implementation in the comment that uses this more memory efficient table. Thanks for the comment.
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 5 ай бұрын
As efficient as possible. Ah okay. I think this is why I cannot appreciate Demo coding. I strive a middle ground in my first pass ( so: only minimal slow BASIC and almost no look-up. Then profile. For C64 games I have seen raster bars in the border used for profiling. I read that the C64 is too slow for super Mario. codingSecrets showed how coders struggled with the CPU even on the NES. If the hardware manufactures just would have given us more power from the start. Consoles are so low on memory, so there is even more pressure to solve everything in the CPU. You may guess that I like the genesis. Z80 is probably the lesser evil than all those SID registers. So times 40 is like you don't divide by 8, but only AND the top bits. Then STA, SHL, SHL, ADC. (Carry should be clear because we don't expect a carry in SHL ). @@agpxnet
@agpxnet
@agpxnet 5 ай бұрын
​@@ArneChristianRosenfeldt Unfortunately the raster beam runs very fast (or the CPU is too slow...), especially in NTSC, so personally I prefer to give a little more weight to computational efficiency. Anyway, I think you need a little more instructions because the product result is 16 bits and therefore you have to handle the carry. An easy way to increase speed is to completely eliminate the subtraction of 24s and 50s and do it directly at the contact points.
@giuseppeazzarello8426
@giuseppeazzarello8426 5 ай бұрын
buongiorno agpxnet finalmenteuna una spiegazione anche nei minimi particolari, video e spiegazione SUPER, oggi faro delle prove utilizzando le tue informazioni grazie
@andreal2023
@andreal2023 5 ай бұрын
Sei molto chiaro nelle spiegazioni e si vede quanto ti appassioni il lavorare bit per bit !!! Anche io sono appassionato di tutte quelle regole sul sistema binario (tipo lo shift di 3 bit che equivale alla divisione/moltiplicazione per 8). Una "chicca" appassionante per me è nella scomposizione in fattori primi. Sappiamo infatti che un numero è divisibile per 3 nel sistema decimale se la somma delle cifre dà un numero divisibile per 3. (ad esempio 33 è divisibile per 3 perché 3+3 fa 6 che è divisibile per 3). Ora 3 in binario è 11. Tornando nel sistema decimale sappiamo che un numero è divisibile per 11 decimale se la somma delle cifre pari meno quelle dispari da 0 oppure 11. Quindi un numero binario è divisibile per 3 binario se la somma delle cifre pari meno quelle dispari dà 0 o 11. 33 decimale in binario è 100001 ((1+0+0)-(0+0+1))=(1-1)=0 quindi 100001 è divisibile per 11 decimale (3 binario). Scriviamo un numero binario con coppie di 1 e 0. Ad esempio 11001100 sappiamo (...) che sarà divisibile per 3. Infatti si tratta del numero (128+64+8+4=204 che è 68x3, quindi in effetti divisibile per 3). Se ci pensi spostandosi da un sistema con una certa base ad un altro si possono scoprire una serie di regole interessanti ... Complimenti per il video e sono curioso di vedere la prossima puntata !