Showing posts with label sprites. Show all posts
Showing posts with label sprites. Show all posts

Friday, 28 February 2020

More Whoosh Hair

Waaayyyy back in August last year, I added a 'jump' sprite for when the player was jumping left or right (see diary entry here...).

It's always bothered me, however, that when the player jumped straight up and/or fell straight down, only the static 'standing still' sprite was displayed.  Well, I've spent some time today fixing that!  I've pixelled up a jump/fall sprite for both the boy and girl and added a tiny bit of code to check whether the player was jumping/falling (gravity is active or it isn't!) and if the gravity is active, the jump/fall sprite is displayed.

In practise, it looks a little like this; very simple, but quite effective I think...?


I've been intending to do this for a while, but have been concentrating on other things such as level design.  Now the jump/fall is done, I have now also fixed a slight movement issue whereby after a left/right jump, the walking animation didn't reset and the jump left/right sprite remained making it look as though the player was sliding everywhere.

If you're wondering why the sliding issue took so long to fix (it's been this way since August last year!), that's simple because after a joystick movement, the player movement routine checks what current sprite is being displayed and makes decisions on what sprites to display next based on that.  Since the jump up/fall down sprite has only just been done, now was the time to fix it!

I regard the control system in Chiller 2 quite simple, but it's still a bit of a maze of checks and conditions!  Please spare a thought and admire games with much more complex control systems!

Next diary entry...


Wednesday, 1 January 2020

Enemy Movement Delay

A small diary entry to celebrate the New Year!

In my haste when coding the the enemy movement code (see previous diary entry), I didn't think to include a timer to 'activate' the code.  Basically, when the enemy movement routine was called every enemy sprite position was updated *every* frame.  This had the effect of every enemy only being able to move 1 or 2 pixels (set by the sprite speed table) because any bigger movement made the sprite move too fast, which looked rather silly on screen.  Also, because there were only 2 speed choices, the movement looked a little 'unnatural', with too many enemies moving in-sync because of their same speeds.

I've now enclosed the enemy movement routine within a timer, so it only activates every so many frames set within the code.  Currently, the routine now runs every other frame, which means I can now have sprites that move 3 pixels without looking ridiculously fast.  This means that the screen now looks much more 'natural' with enemies moving seemingly at their own pace.

As the game progresses, I'll play more with the timer and enemy speeds to see if I can introduce even more natural looking movements.

Next diary entry...

Friday, 27 December 2019

Enemy Movement

After coding some (very) simple enemy movement patterns for the Freeze64 Xmas Demo a couple of weeks ago, I finally decided to get down to coding the *actual* enemy paths for the game.

This actually began on Christmas Day (who else was coding then??!) when I finally got round to noting down the locations in hex of the enemy sprites in the sprite bank.  This was done using good old fashioned pen and paper while sat in my comfy reclining chair, sipping a nice red Tempranillo!  Here's what my scrappy notes looked like:




Once these hex locations were noted, I got to thinking what information was needed to set up, display and move an enemy sprite.  Obviously, a sprite 'x' and 'y' screen location was needed, but I also need to know colours, the default (start) sprite definition, animation start/end definitions, sprite direction and speed and finally the maximum and minimum screen locations travelled to by the sprite enemy.  To keep things simple, sprites in this game move in straight line paths for now!  The set-up table for level 1 ended up looking like this...

 l1_sprite_x       !byte $19,$20,$4c,$94,$90,$6f,$5a,$0d  
 l1_sprite_y       !byte $cd,$9e,$4f,$a4,$cd,$a8,$54,$85  
 l1_sprite_col     !byte $0a,$07,$0c,$05,$0c,$0c,$0c,$0c  
 l1_sprite_def     !byte $ab,$bf,$ee,$ec,$cf,$c7,$d3,$e8  
 l1_sprite_anims   !byte $ab,$bf,$ee,$ec,$cf,$c7,$d3,$e8  
 l1_sprite_anime   !byte $ac,$c0,$f0,$ee,$d3,$cb,$d7,$eb  
 l1_sprite_dir     !byte $00,$00,$00,$01,$01,$01,$00,$00  
 l1_sprite_spd     !byte $00,$00,$01,$02,$01,$01,$01,$01  
 l1_sprite_min     !byte $00,$00,$53,$53,$19,$5a,$5a,$0d  
 l1_sprite_max     !byte $00,$00,$b8,$a7,$90,$85,$85,$3a  

At first, I was going to have a separate bit of code to handle each enemy, but once I realised that the enemies only move up/down or left/right, I realised I could handle the sprites in a single loop; well two loops actually, one handling vertical movement and the other horizontal. This could be rationalised further into one loop by having another table setting whether each enemy is vertical or horizontal moving, but since the code would be roughly the same, with skips in the loop to handle vertical/horizontal, I decided to keep it simple and have two loops - hopefully this will be easier to read and remember for the future.

I did need to create some more tables holding the sprite animation definitions for each enemy when moving left or right, but I was now ready for some code.  It ended up looking a little like this (note, this is for the horizontally moving enemies only):


; now deal with the horizontal moving enemies  
; zombie, ghost, bat, witch (sprites 4 - 7)            
                       
 enemy_hori_check  
           lda sprite_dir,x  
           cmp #$01  
           beq enemy_hori1  
             
           lda sprite_x,x  
           clc  
           adc sprite_spd,x  
           sta sprite_x,x  
           cmp sprite_max,x  
           bcc next_hori_enemy  
           lda #$01  
           sta sprite_dir,x  
           lda left_enm_def,x  
           sta sprite_def,x  
           sta sprite_anims,x  
           lda left_enm_anime,x  
           sta sprite_anime,x  
           jmp next_hori_enemy  
   
 enemy_hori1  
           lda sprite_x,x  
           sec  
           sbc sprite_spd,x  
           sta sprite_x,x            
           cmp sprite_min,x  
           bcs next_hori_enemy  
           lda #$00  
           sta sprite_dir,x  
           lda rite_enm_def,x  
           sta sprite_def,x  
           sta sprite_anims,x  
           lda rite_enm_anime,x  
           sta sprite_anime,x            
             
 next_hori_enemy  
           inx  
           cpx #$08  
           bne enemy_hori_check
 

Basically all that's happening is the code first checks which direction the sprite should be moving (in my game '0' means down or right and '1' means up or left) and then adds or subtracts from the sprites 'x' position on the screen.  The addition or subtraction can be altered, thus altering the 'speed' of the sprite, by changing the values in the 'speed_spd' table, which the code references in the loop.

Also referenced is each enemies 'max' and 'min' values which determines the end point of the movement path on screen.  Once the max or min is reached, the code switches the 'sprite_dir' so the sprite moves the other way, along with the animation definitions for that direction.

The code for vertical movement is almost identical, save for the sprites 'y' screen value is altered instead.

Once this code is called in the game and the set-up table for level 1 referenced, the enemies ended up doing this (and believe it or not it worked first time!):


I'd call that a successful couple of days and a Merry Christmas indeed!

Next diary entry...

Thursday, 28 November 2019

FREEZE64 Christmas Demo

A few days ago, Vinny, who writes the really rather excellent C64 fanzine 'FREEZE64', messaged me on Twitter asking for a few screen grabs of Chiller 2 in action.  He is going to send an email out to his subscribers on Christmas Eve and will include some information about the game, along with said screen grabs.  He will also publish the URL of this blog to the "wider world".  Up to this point he is one of a very small, select group of trusted people who even know that this humble dev diary exists.

I should say at this point that Vinny has been very supportive "behind the scenes", offering lots of encouragement and interest.  Because of this support, I thought it might be a good idea to offer him an exclusive download as a thank you.

So currently, I'm stripping out all code pertaining to everything other than the title screen, level 1 and any display routines.  The result will be the first playable demo of Chiller 2.  I am limiting some things because I don't want to give too much away in this demo.  Thus, only a partial charset is included with the minimum number of sprites needed.  The music is a very early version of the main title screen music and amounts to about 10 seconds worth on a repeating loop.  If you play the demo and it drives you mad, tough!

As a bit of an afterthought, since this demo is an exclusive Xmas gift from FREEZE64 to it's subscribers and also riffing on the FREEZE title, I've decided to make the text in the demo white and various hues of blue, while adding settled snow and ice to the forest level.  I've also altered the "Chiller 2" sprites on the title screen to read "FREEZE64".  Why am I explaining this? Surely some images would be better!





Next diary entry...

Tuesday, 6 August 2019

Whoosh Hair

It didn't take long for the 'walking in the air' to get on my nerves - see the end of the previous diary entry here!

As a result, I spent an hour today pixelling a 'jump' left/right frame and then modifying my player movement routine to display the frame.  The result has been christened 'Whoosh Hair'!

I will be honest, I was inspired to pixel whoosh hair by a game I used to play on the Amiga called 'Kid Gloves 2', which made locks of the players hair 'stick up' when falling.

The jump now looks much better methinks - no silly mid-air walk!  Oh? What does it look like?  Something like this...



Next diary entry...
 

Monday, 5 August 2019

Jumping

A couple of weeks ago, I asked about people's preferences on Twitter (read here...) for joystick control in relation to 'jumping' a player character and the general consensus seems to be to use the fire button to jump.

Therefore from this day forth, the fire button will activate the jump function in Chiller 2!

After a bout of coding (I won't share the code here because it's so tied into the main control code, it would be too long!), the player can now jump!  At present, no platforms are detected, but these will be coded up in the next few weeks.

The jump looks like this...


The only slight annoyance is that the sprite carries on the walking animation while in the air which to my mind looks rather silly, so I'll probably have to fix that next less my O.C.D. tendencies will play havoc...

Next diary entry...

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



Tuesday, 30 July 2019

Default Player

After showing the title screen dancing player select option on Twitter the other day, someone suggested that perhaps the girl should be the default player!

I debated for a few hours and then decided this was a good idea!  I've not done this as some kind of feminism based altruism, even though it was pointed out that even little choices like this in support of women can go a long way.

The actual reason for making the change is to differentiate Chiller 2 from the original game.  In 1984 you played as the boy out to rescue the girl by collecting blue crosses and after playing through the levels and "rescuing" the girl, you then had to play through the levels backwards as both the boy and the girl, with the girl collecting pink crosses.  Hmmm... does seem a little 1980's to me.

Thus, in 2019 you can select to be either girl or boy at the start and both characters have to collect yellow crosses.  That seems a bit more "modern" to me.  As for playing levels backwards when all levels are complete:  I may still incorporate this in my game.  I may also do a character switch on last level completion so you have to play as both characters anyway.  Since the girl and boy have slightly different in-game characteristics, this will perhaps extend the gameplay, providing a bit more of a challenge?

Someone also suggested using some character names (Tina and Tom) on the title screen instead of "girl" and "boy".  The only problem is the characters are called "Michael" and "Michaela" and that doesn't fit on the screen!  Those names do appear in the brief instructions in the "scrolling" message.

So after a quick code rearrangement, the girl is now selected by default on first load.



Next diary entry...

Friday, 26 July 2019

Dancing Player Select

A couple of weeks ago, I was playing around with the title screen for the game looking for a way to add more movement and/or break up all the text a little.  I added some some extra sprites to the bottom part of the title screen by recycling another 3 sprites in the second raster split.

At the time, I made both the boy and girl player sprites dance in time to the music.  After adding this, I thought it might be a nice idea at a later date to make only the player you select (boy or girl) dance, while the unselected option stood still.

Today was that 'later date' and it's finally in!  On the title title screen, pushing left on the joystick selects the boy to play in the game, while pushing right selects the girl.  Further highlighting the selection is the text next to the boy or girl which is coloured white or dark grey depending on the choice made.

I'll be honest, at the moment pressing fire to enter the first level results in the boy sprite being displayed, even if the girl is selected.  I still need to write the code to copy the right sprites into place.  However, in the background, variables are being copied into place that changes the way the player behaves or is affected by other sprites.  Currently, playing as the boy means that less energy is taken away on contact with a meanie than with the girl, but on the other hand, the girl can move a little quicker than the boy.  These attributes will probably change as more progress is made on the game!

However, here is a screen dump of a small part of the title screen of the the boy/girl select in action:


And the code that switches between the two players...

 ; title screen player select subroutine ------------------------  
             
 boy_select  
           ldx #$d8  
           stx t_sprite_def+$01  
           stx t_sprite_anims+$01  
           ldx #$dc  
           stx t_sprite_anime+$01  
             
           ldx #$dc  
           stx t_sprite_def+$02  
           stx t_sprite_anims+$02  
           ldx #$dd  
           stx t_sprite_anime+$02  
             
           ldx #$00                         ; zero x register  
 boy_sel_loop                                
           lda #$01                         ; load white  
           sta $db51,x                    ; write 'boy' in white  
           lda #$0b                         ; load dark grey  
           sta $db5d,x                    ; write 'girl' in dk grey  
           inx  
           cpx #$05                         ; done 5 writes?  
           bne boy_sel_loop               ; all written? no? loop back!  
             
           lda #$00                         ; make player store 0  
           sta ply_type                    ; so boy is selected  
             
           rts  
             
 girl_select  
           ldx #$d8  
           stx t_sprite_def+$01  
           stx t_sprite_anims+$01  
           ldx #$d9  
           stx t_sprite_anime+$01  
             
           ldx #$dc  
           stx t_sprite_def+$02  
           stx t_sprite_anims+$02  
           ldx #$e0  
           stx t_sprite_anime+$02  
             
           ldx #$00                         ; zero x register  
 girl_sel_loop                                
           lda #$0b                         ; load white  
           sta $db51,x                    ; write 'boy' in white  
           lda #$01                         ; load dark grey  
           sta $db5d,x                    ; write 'girl' in dk grey  
           inx  
           cpx #$05                         ; done 5 writes?  
           bne girl_sel_loop               ; all written? no? loop back!                 
             
           lda #$01                         ; make player store 1  
           sta ply_type                    ; so girl is selected  
             
           rts       


Next diary entry...

Thursday, 25 July 2019

Software Collision Detection

Following on from yesterday, I've decided to move away from using the C64 built-in collision detection almost straight away since I know other routines (such as the energy bar) are working.

The reason the built-in sprite collision detection register ($D01E) isn't used is because it requires a (metric?) tonne more code to work out which sprites are involved in the collision.  This means that I wouldn't have been able to (without wasting time and memory on that extra code) have any of the meanie sprites overlapping without there being issues in detection - they would have had to stay clear of each other to keep things simple and this would limit the game play and level layout somewhat.

Thanks to Jason 'T.M.R.' Kelk for pointing me in the direction of some online GitHub resources which, almost unbelievably, I read and then proceeded to write a software based collision that worked first time.

All that's happening in the detection code is that the x-y coordinates of the main player sprite are grabbed from the sprite table and invisible x-y points are calculated within the sprite and stored in collision variables.  These variables are then tested against the x-y coordinates of the meanie sprites, grabbed from the same sprite table.  When an overlap occurs, there is a virtual 'collision'.

From there, in my code, energy is then taken a away from the player, although I have tweaked the timer so that it's possible to be 'colliding with a meanie for some time without losing too much energy in one go.

Here is the collision code as I finished coding today, which will obviously change quite a bit as new features are added, but for now works fine...

 ; player to enemy sprites subroutine ----------------------------  
   
 ; software based collision detection... no $d01e here!!!  
   
 player_collision  
         lda #$00                 ; set the death flag to 0  
         sta ply_death_flag  
   
         lda sprite_x+$00         ; setup a 'bounding box'  
         sec                      ; around the player sprite  
         sbc #$04                 ; for software collision  
         sta coll_temp+$00        ; detection  
         clc                      ; grab the some x positions  
         adc #$09                 ; for our player sprite which      
         sta coll_temp+$01        ; is sprite 0!      
   
         lda sprite_y+$00         ; and do the same for some y  
         sec                      ; positions of sprite 0  
         sbc #$0a  
         sta coll_temp+$02        ; the x and y positions are  
         clc                      ; stored in the 'coll_temp'  
         adc #$16                 ; labels  
         sta coll_temp+$03  
   
         ldx #$00  
 enem_colls_loop  
         ldy colls_timer          ; first load up the collision timer  
         iny                      ; and increase it by '1'  
         cpy #$08                 ; is the timer equal to '8' yet?  
         bne coll_tmr_skip        ; no? go down to coll_tmr_skip  
                                  ; and skip collision checking  
                                   
         lda sprite_x+$01,x       ; now grab the x postion of each sprite  
         cmp coll_temp+$00        ; from the sprite table  
         bcc enem_colls_skip      ; and check against our 'bounding box'  
         cmp coll_temp+$01        ; coordinates to see if they      
         bcs enem_colls_skip      ; overlap...  
   
         lda sprite_y+$01,x       ; and do the same for the y coordinates  
         cmp coll_temp+$02  
         bcc enem_colls_skip      ; if no coordinates overlap, skip down  
         cmp coll_temp+$03        ; to 'enem_colls_skip'  
         bcs enem_colls_skip  
                                  ; if some coordinates overlap, collision!  
         dec ply_energy           ; decrease the player energy flag by 1  
           
         jsr energy_bar           ; redraw the energy bar  
           
         lda ply_energy           ; is the player out of energy?  
         cmp #$00                 ; yes?  
         beq energy_out           ; skip down to 'energy_out'      
   
 enem_colls_skip  
         inx  
         cpx #$07  
         bne enem_colls_loop      
   
         ldy #$00                 ; load x register with '0'      
 coll_tmr_skip                    ; to reset collision timer and...                  
         sty colls_timer          ; store x register to colls_timer  
           
         rts                      ; go back to main game loop  
               
 energy_out  
         lda #$01                 ; load the player death flag with      
         sta ply_death_flag       ; 1 because all the energy is gone!  
                                  ; then...  
         rts                      ; go back to main game loop where  
                                  ; player will be killed!!!! MWHAAAA!
  

Once compiled and running in WinVICE, it looks a little like this...



Next diary entry...

Wednesday, 24 July 2019

Energy Bar

I've fancied tackling the in-game player energy bar for a while now and have decided to keep it very simple for me to code which may mean inefficient or inelegant, but at this stage, if it works then that's fine by me!

Before tackling the energy bar code though, I needed to code some collision detection so when the player touches a meanie, some energy can be taken away!  As a stop gap measure, I used the C64 built-in sprite hardware collision detection register $D01E, which will be changed in the future for reasons I won't explain right now!

Now a collision between sprites can be detected, it's time to subtract some energy!  The way I've gone about this is to keep the amount of energy stored in a 'variable' which in my code is currently called 'ply_energy' and which is set to '33' or '$21' at the start of the game.  Why such a strange number?  Well the energy bar length represented in blocks at the bottom of the screen after the word energy, is 33 chars wide!  There you go, count the blocks...


Now, being new to C64 coding, I've absolutely no idea if there is a standard way of doing this but my solution to the energy bar has been to set up the colour RAM at the beginning of the level to the red, yellow and green that you can see and which always remains the same, but then replace each block character in the screen RAM with a space character when energy is taken away.

So quite simply, upon the player touching a meanie, the energy in variable 'ply_energy' is subtracted by one, then the whole energy bar is deleted and redrawn to the new value.  This is my delete and redraw the energy bar code:

 ; energy bar drawing subroutine ----------------------------------  
   
 energy_bar  
           ldy #$00              ; update the energy bar!  
           lda #$20  
 clr_energy_loop                 ; clear the row of chars that display the  
           sta $07c7,y           ; energy bar by printing a line of  
           iny                   ; blank spaces!  
           cpy #$21  
           bne clr_energy_loop  
             
           ldy #$00                      
           lda #$40  
 drw_energy_loop                 ; now redraw the energy bar with char $40  
           sta $07c7,y           ; (the block making up the bar)  
           iny                   ; equal to the amount of energy   
           cpy ply_energy        ; remaining  
           bne drw_energy_loop       
             
           rts                   ; go back to wherever this was called from!       


And for now, that'll do because it appears to work just fine and dandy!

Next diary entry...

Saturday, 13 July 2019

More Title Screen

After getting a basic title screen up and running the other day and deciding it needed some extra something or other, I spent some time today adding some colour washing to the text so that there was more colour on the screen.

What the screen dump doesn't show is the text colours "animating" across the screen, left and right.

I had also previously decided it may be quite nice to make the title logo sprites move up and down continuously.


I was quite surprised how easy it was to do the "bounce".  In the mainline title screen loop, I just needed some code that added or subtracted a pixel from each sprites y position and then saved the new position into the sprite table to picked up by the sprite plotter in the interrupt code.

There was an extra table added that kept track of whether the sprite was moving up or down so the code knew whether to move the sprite up/down after checking if each sprite had reached it's top or bottom limit.

Here's the code to do the bounce; it may be possible to refine it in the future, but it works as it stands at the moment!

 ; update title sprites 'y' position to 'bounce' them  
   
           ldx bounce_timer               ; load up the bounce_timer  
           inx                              ; increase it by '1'  
           cpx #$03                         ; is the timer equal to '4' yet?  
           bne bounce_skip               ; no? don't update movement  
                                         ; yes? better do some moving then!  
           ldx #$00  
 t_sprite_y_upd  
           lda t_spr_y_dir,x  
           cmp #$01  
           beq t_sprite_up  
             
           lda sprite_y,x  
           clc  
           adc #$02  
           sta sprite_y,x  
           cmp #$4a  
           bcc t_next_sprite  
           lda #$01  
           sta t_spr_y_dir,x  
           jmp t_next_sprite  
                            
 t_sprite_up  
           lda sprite_y,x  
           sec  
           sbc #$02  
           sta sprite_y,x            
           cmp #$3e  
           bcs t_next_sprite  
           lda #$00  
           sta t_spr_y_dir,x  
           jmp t_next_sprite                 
   
 t_next_sprite  
           inx  
           cpx #$08  
           bne t_sprite_y_upd  
             
           ldx #$00                         ; load x register with '0'  
 bounce_skip                              ; to reset anim_timer and...       
           stx bounce_timer               ; store x register to anim_timer       

I also extracted the text scroller/plotter from "Unused Shmup Tunes" (see previous diary entry) to use on the title screen, so now intro/credit/greeting type text "types" itself on to the screen just above the ground.

As an afterthought, I decided it might be quite nice to have some sprites in the bottom part of the screen, since the screen is already split and therefore it's quite easy to recycle the sprites.  It struck me that it might be cool looking to use the ghost that is already in the sprite bank  and "fly" it across the screen to write and erase the scrolling message.

Again this was quite easy.  When each letter of the message is "plotted" onto the the screen, the ghost moves from left to right by 4 pixels at a time so it appears he is plotting the text.  A cheat really, but visually it works.


Finally, I decided to alter the title screen layout slightly to make more room at the bottom of the screen between "The Boy" and "The Girl" text to include the actual sprites of the boy and girl.  Another afterthought resulted in me making them dance in time to the music (yes, I have been venturing into Goattracker and toying with some sounds).

The decision to dance the sprites did mean a short trip into the sprite editor to adjust the main player sprites to add some dancing frames, but the boy and girl look happy enough having a boogie to an early version of the title screen music now!

Next diary entry...