Wednesday, 28 August 2019

Animating Chars

When I first designed the church interior layout for level 2, one of the little background features I added to "fill the gaps" was a flaming wall torch.  I say flaming, but originally as designed, the flame was static (see gif's in previous diary entry).

This has now been bugging me for a few weeks; nagging away in the back of my head somewhere has been a little voice muttering, "You want that torch animating really, don't you?".  Being new to 6510 coding, I didn't want to start bogging myself down with extras (feature creep?) but it REALLY has been annoying me that the flames don't move.  So today the investigation/research into character animation started.

And I wish I'd done it earlier because it turned out to be rather easy!  First, here is the code I came up with to "fan the flames" so to speak...

 ; background animations subroutine ---------------           
   
 process_bkgd_anims  
             
           ldy bkgd_timer           ; load up the bkgrd anim timer  
           iny                      ; increase it by '1'  
           cpy #$04                 ; is the timer equal to '4' yet?  
           bne bkgrd_anim_skip      ; no? don't update animation!  
                                    ; yes? better do some animation then!  
           ldx #$00                 ; zero x register  
 flame_ror  
           lda $2390,x              ; load mem location of the flame char  
           lsr  
           lsr  
           lsr  
           ror $2390,x              ; shift char to the right a pixel (bit)  
           ror $2390,x              ; and shift again 
           ror $2390,x              ; and again               
           inx  
           cpx #$08                 ; all 8 bytes done?  
           bne flame_ror            ; no? do the next byte then!
                                    ; yes?  
           ldy #$00                 ; load y register with '0'  
 bkgrd_anim_skip                    ; to reset bkgrd anim timer and...       
           sty bkgd_timer           ; store y register to bkgrd anim timer  
   
           rts                      ; return to main loop


The code above includes a timer (bkgd_timer) that slows the animation so it only executes once every 4 (TV / screen refresh) frames otherwise it animates rather too quick to be visible!  How does the rest of it work?


First, where is the flame in memory?  Well, when assembling my code, my character set is loaded to $2000 in memory.  My flame character is number "114" ($72) in the charset - the blue boxed char in the image above, also shown larger in the magnified section in the right hand side of the above image.  Each char is made of 8 bytes (8 rows, or bytes, of 8 pixels, or bits), so 114 x 8 = 912 ($390).  Therefore, my flame char should be at $2000 + $390 = $2390 in memory.

In the 6502 instruction set there are a few handy commands called LSR, ASL, ROL and ROR.  These basically allow you to shift bits of a byte left or right.  When it comes to character sets, this has the effect of "scrolling" a char block left or right 1 pixel, while "wrapping" around within itself.

This is something I'm still coming to terms with; being a graphics person originally, I still think of images (pixels) moving up, down, left, right and so on.  But as a coder, you need to thing of bits and bytes of memory moving around, which is what is really happening.

And it's as easy as that!  In my code you can see the starting memory location of the flame char being loaded, then the starting location is LSR'd / ROR'd 3 times to shift the char (memory) 3 pixels (bits) right.  This is done 8 times overall so each row (byte) of the char is shifted.  Why 3 times?  Well, that was just experimentation.  After pixelling my flame, the overall shape of it suggested that it should be "moved" 3 pixels right every 4 TV frames (screen draws/refreshes) to get the best "flickering" effect.  I did try other combinations, but the above worked best for my flame char.

And what does it look like?  Savour the animated gif below (disclaimer, the animation looks better than the gif suggests, honest!)...


Next diary entry...