Wednesday, 31 July 2019

Status Bar Score

I gave myself the afternoon off work today so had a little extra time for coding; this time was welcome as there are lots of little background routines that need to be written before the code transitions from being little more than a demo into an actual playable game.

Since the sprite to sprite collision code was written recently along with the energy bar, I thought I'd write a couple of routines to handle the scoring and the cross counter to complement the energy bar.

I did actually tweak the collision detection code the other night so that my yellow cross sprite didn't deplete the energy bar as it was doing; it was originally part of the main enemy check that did remove energy.  As a temporary measure for testing purposes, I made collision with the yellow cross change the background colour so I knew the code was executing in the right order.  My Grandson is doing some testing for me and he made a noise equal to "Urgh!" when he first saw the background change, hence my decision to do some code that increases the score and cross counter.

I've had it in my head for a while now that collecting crosses will score the player 100 points and that 20 yellow crosses will need to be collected to complete a level.  The code keeps this in mind, but this could change in the future.

Here is the code in action; at the moment the yellow cross sprite doesn't change position when "collected" so that multiple collisions can be registered to test the status bar.



How does it work?  When a collision with a yellow cross is detected, a flag is set which then makes the main code loop jump to a subroutine that increase the score by 100 and the cross counter by 1.  Well, that's what it looks like in practise, but I learned a trick a few months ago from Jason 'T.M.R' Kelk: no "real" score is actually ever used.  All that's really happening is that score digits are being checked and manipulated in a table.

Eh?  Well, keeping in mind that my score is six digits long, collecting a cross adds a 1 to the fourth column along from the left (hundreds).  This keeps happening until the column reaches a maximum of 9, at which point that column resets to 0 and the third column along from the left (thousands) increases by 1.

The same happens to the cross counter as well.  When a cross is touched, the units column is increased by 1 until it reaches 9, at which point the tens increases by 1.  No "real" scoring in the sense that humans think of it.

This method has the benefit of using RAM to store the score instead of space in the zeropage.  Also, it's now going to be quite easy to check the end of the level.  All I will need to do is load up the tens column of the cross counter and see if it's equal to 2.  If so, "20" crosses have been collected and the level is complete!

Anyway, here is the score code that increases by 100.  It is flexible so that I can very easily add an increase of, for example, 1000 on level completion in the future.

 ; score accrue subroutine ------------------------------------                 
   
 score_accrue_100  
           ldx #$03  
             
 sa_loop  
           lda score,x  
           clc  
           adc #$01  
           cmp #$0a  
           beq sa_cnt  
           sta score,x  
   
           jmp score_compare  
   
 sa_cnt       
           lda #$00  
           sta score,x  
           dex  
           cpx #$ff  
           bne sa_loop  
   
 ; now compare current score to high score  
   
 score_compare  
           ldx #$00  
 score_chk  
           lda score,x  
           cmp high_score,x  
           beq score_chk_cnt  
           bcc score_chk_end  
           bcs hi_score_update  
 score_chk_cnt       
           inx  
           cpx #$06  
           bne score_chk  
 score_chk_end  
   
           rts  
   
 ; current score is a high score???  
   
 hi_score_update  
           ldx #$00  
 hi_up_loop  
           lda score,x  
           sta high_score,x  
           inx  
           cpx #$06  
           bne hi_up_loop  
             
           rts  
   

If you've just read that code block, you may just see that a high score comparison routine is included for good measure.  I thought at first that the high score would only be updated at the end of a game, but instead decided to update it on the fly should, during play, the player accrues a current score equal to or greater than the current high score.

The cross counter routine works on a similar principle, with the current amount being stored in a "cross_score" table after digit manipulation.  It's shorter because there is no high score check obviously!

 ; cross accrue subroutine ------------------------------------                 
             
 cross_accrue  
           ldx #$01  
 ca_loop  
           lda cross_score,x  
           clc  
           adc #$01  
           cmp #$0a  
           beq ca_cnt  
           sta cross_score,x  
             
           rts  
             
 ca_cnt       
           lda #$00  
           sta cross_score,x  
           dex  
           cpx #$ff  
           bne ca_loop  
             
           rts  
   

Once all this digit manipulation is complete, I have a subroutine that prints the contents of the score, high score and cross tables into the correct places on the screen.

And that's scoring done for now!

Next diary entry...



No comments:

Post a Comment