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, 26 December 2019

Xmas Demo Released

The Xmas demo was emailed to Freeze64 subscribers on Christmas Eve, so I guess it's fine to post this here now, doubly so since it has appeared in 'cracked' from on CSDb!




If you would like to play the demo, you can download it here...

If you want to play a 'cracked' version by TRIAD, with some built-in cheats, you can grab that from CSDb here...

Next diary entry...

Thursday, 19 December 2019

Xmas Demo Complete

Since the last entry, I've been working on a couple of entries for the 'Intro Creation Competition' over at CSDb (see here and here), so work on the Chiller 2 Xmas demo for Freeze64 came to a bit of a standstill.

To make up for this, the last few days have been spent preparing the demo for Vinny.  All that really needed doing was working out some coordinate locations for the cross to move to once collected.  I ended up doing this in work on a printed screen grab of the demo level.  The photo below shows the scrappy piece of paper with the screen coordinates on!


As an afterthought and in the sprit of making things extra Christmassy, I edited the charset to include some holly for the title screen and a snowman for the demo level.  Those look a little like this...



Also, in last post I apologised for the short, repetitive music.  Gone!  I've written a short piece of music especially for this Xmas demo based on 'God Rest You Merry, Gentlemen', also know as 'Tidings of Comfort and Joy'.  I did try to make it sound 'scary' in keeping with the game theme; hey, it was the best I could do in the short time I had!

In not wanting to give away too much of the game early on, I've taken the decision to only include 1 enemy type, the ghost which moves along very simple paths.  All other enemy sprites have been removed from the sprite bank!  I've also only included the boy as a playable character along with removing some 'dangerous' scenery.  I've taken the liberty of adding a simple demo complete message as well, should you collect all 20 crosses.

The demo has been tested on a real C64c, with the game engine holding up quite well in the demo.  It appears I have learned how to code 6502 to some extent this year!

Vinny should be emailing out a special subscribers only 16 page Freeze64 email issue on Christmas Eve, with the Chiller 2 demo attached!  The announcement for this can be found on Twitter here...

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

Saturday, 31 August 2019

Level 3 Origins

It's felt like time to work on another level design because I've been a bit tired of looking at the forest and the church levels for the last month.  Since the first level was exterior and the second interior, I guess it makes sense for the next level to be exterior again?  That wasn't planned at all, but that's how it seems to be panning out...

In the original "Chiller", there was a level called "The Ghetto" and I wanted to do a "call-back" to this, so I spent this morning starting the design for a level that I'm calling "The Apartments".  Using the word ghetto these days would seem a little non-politically correct.



When I say starting the design, it ended up being an almost complete design for the level, save some modifications that will probably need to be made to platform spacings, mushroom locations and some other embellishments (once I've thought of them).

The original brief to myself (i.e. what I dreamt up 5 minutes before pixelling commenced) stated that the window ledges were to act as the platforms and there was to be a couple of different coloured buildings for contrast on screen.  Drawing the the fence, brick and window chars took no time at all and I had a basic layout within half and hour.  However, it did look a bit plain with an all black background, even with my star, moon and cloud chars drawn in.

Then I had a brainwave, well as about as wavy as my ageing brain gets these days.  Make the sky a different colour to previous levels and since this game is supposed to be set at dusk/night, dark blue made sense.  I copied and reverse some existing chars (clouds, stars) to set on the night sky and then, as another "call-back" to the games of yore, used black chars to pixel in some silhouette skyscrapers in the background.  What old games inspired this?  Think "Ocean Software" and "Robocop".  Consider this level, therefore, my "love letter" to those Ocean games that gave me hours of pleasure as a young teen.

Here is the level as it exists at the moment in "ChillED", my screen editor.


My Grandson did give it an initial thumbs up when I showed him this afternoon and wanted to "play" it straight away, but I still need to export the screen and colour RAM data and add it to my level data "includes" file.  And then code the level set-up.  That will be another day.

On a side note, after giving the initial level 3 design the thumbs up, my Grandson asked to play a few games on my C64mini, so we transferred the latest build of game over as well for a quick test.  Chiller 2 seems to be C64mini compatible so far as well!  ;)


Next diary entry...

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

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


Wednesday, 10 July 2019

Initial Title Screen

I've decided to work on the title screen today.

That may seem a little odd so early on in the project, but since so much code is needed right at the start to display anything at all (screen set-up and printing, splits and so on) and so much of it will be used for the title and in-game screens, I thought I may as well do it now and have something to show for it.  I'm too impatient!

I first completed a rough layout in my screen editor, 'ChillED'.



I then exported the screen RAM and colour RAM data into the game assembly file. I had previously written some screen display code for another C64 project (Unused Shmup Tunes, see here...), so surgically removed the code and inserted it into Chiller 2.

After a few changes to the layout in ChillED and a further export of data, the title screen ended up being displayed in the game.  Here is a screen dump using WinVICE...

Rather plain at the moment, but I have managed to include some previously pixelled sprites that spell out the game name.  The sprite "plotter" for this resides in split 1 on the screen and was written so that it won't just handle the the title screen sprites, but eventually the in-game sprite player and meanies too!  Double plus good!

I cannot tell a lie - this sprite plotting code was also written for and grabbed from the Unused Shmup Tunes release and since it's my code, it's allowed!  Here is the sprite plotter code for Chiller 2 that handles the x-y position (including MSB) and colour of all 8 sprites, as well as being able to pluck the correct sprite definition from the sprite bank...

 ; in-game sprite plotter!            
             
 sprite_plotter            
           ldx #$00  
           ldy #$00  
 sprite_plot  
           lda sprite_x,x  
           asl  
           ror $d010  
           sta $d000,y  
           lda sprite_y,x  
           sta $d001,y  
           iny  
           iny  
           lda sprite_col,x  
           sta $d027,x  
           lda sprite_def,x  
           sta $07f8,x            
           inx  
           cpx #$08  
           bne sprite_plot  


Now the basic title screen is in place, I fancy adding some colour washes to the text as well as making the logo sprites bounce up and down.  The grassy ground in the screen dump above will eventually have a scrolling message of sorts above it.

Next diary entry...



Tuesday, 9 July 2019

Other Projects

If things have seemed a little quiet on the Chiller 2 front recently, it's because I've been working on other projects!

What?  Why?  Quite simply, I'm still learning 6502 assembler and the best way to learn is by actually doing something.  When doing a longer term project like a game, there are so many other things to do as well, such as design, graphics, sound and so on and as a result you're not coding all the time, which is something I NEED to do to learn!

Just to prove it, here are some links to CSDb that contain two of my recently completed projects from which I can borrow steal code for Chiller 2!

PETSCII Doctors

Unused Shmup Tunes

Going forward, I can now dedicate more time to Chiller 2!

Next diary entry...


Monday, 13 May 2019

Level 1 Design

After a couple of false starts, I've spent the last few days off and on using my screen editor 'ChillED' to construct a level for the game, set in the forest - since the original game starts in a forest, it seems appropriate for the sequel to as well?

No doubt the layout will change considerably due to circumstances I've not foreseen yet (probably to do with code or gameplay restrictions), but I'm fairly happy with what I've come up with.

Here is a little animation of how the level was built up; most of the stages are here, with only a few left out that only had minor differences from a previous save.


EDIT:  After posting this, I decided to use Photoshop to overlay some of the sprites on the current final version of level 1 and post on Twitter.  There seems to have been some pretty good feedback, with some nice responses!  Anyway, the image that was posted on Twitter is below and a link to the actual Tweet is here...



Next diary entry...

Tuesday, 23 April 2019

ChillED Copy & Paste

While still toying with level backgrounds for "Chiller 2", I've come to the realisation that I will need a select/copy/paste function in "ChillED", my screen editor.  I was hoping to get away without having this feature since I'm spending more time on the editor than the game at the moment!

Having said that, if a copy/paste function makes life easier, then the editor shall have it!  So guess what I've been doing for the last few days while on a break away?

That's correct!  Select, copy and paste is now in!  Still a few small bugs that need ironing out, but here it is in action while I was pixelling a quick version of Yoda!


Next diary entry...

Friday, 19 April 2019

Joystick Detection

I fancy a mini-break from ChillED; it's occupying too much of my head-space at the moment and I need to do something different!

Thus, I've decided to write and slot into place the joystick detection code.  At the moment, the code is very general since it's not being called by any other routine or not actually doing anything itself other than detecting the joystick move.

To be honest, I've meddled with joystick code before in a previous project (Super Galax-I-Birds), so this new code is a modification of that projects code for Chiller 2 and it all starts with memory location $dc00.


; check joystick left, right and button press 

joy_check
   
           lda $dc00  
           sta joystick  
             
 joy_left  
           lda joystick  
           and #$04  
           bne joy_right  
             
           jmp joy_end     ; jsr to another routine in future!
             
 joy_right  
           lda joystick  
           and #$08  
           bne joy_fire  
             
           jmp joy_end     ; jsr to another routine in future!
        
 joy_fire       
           lda joystick  
           and #$10  
           bne joy_end
                           ; jst to another routine in future!
joy_end
           jmp joy_check


Memory location $dc00 can detect various joystick inputs by 'and'ing in various values as above.  In the code, if an input isn't detected, it skips and checks the next input, but if an input is detected some other code can be run, but here it just jumps down to the end at the moment.

Note, there is no detection for up or down because Chiller 2 won't be using those movements, otherwise it would be simple to add more code to the above for those movements also.

And it's that simple in assembly language to detect joysticks!

Next diary entry...

Friday, 12 April 2019

ChillED Data Export

Been building to this, a feature for "ChillED", my screen editor, that will enable me to put screens/levels straight into the game with ease: screen and colour RAM data export!

The data format is simple text, but it includes a "byte!" label at the start of each line to copy and paste straight into my ACME formatted source.

Here is the feature in action:


To be honest, the export has been working for the last few days and I've been using the editor to pixel some PETSCII screens and have been exporting them to some hastily written display code which has then been tested on my C64mini.  Here is a very quick version of R2D2 pixelled in ChillED, data exported to my rough code and being display on my spare TV using the 64mini...


All appears to be working nicely!

Next diary entry...


Friday, 29 March 2019

ChillED Testing

Work continues on ChillED, my screen editor that will be used to produce levels for the game.

It's been in a fit state to pixel screens for a couple of weeks now and I've been doing some thorough testing by actually using it!

Here are some examples of the editor in action:





Next diary entry...

Sunday, 17 March 2019

Project Set-Up

While continuing to work on my screen editor, ChillED, I've decided to set-up a work project folder containing everything needed for the game.  My usual way of saving things means direct to my (paid for) Dropbox folder, so I get automatic backups with version history in case as well as being able to access all my files from any computer I sign in to - I can code in work too!

The project folder will contain all code, data and work files (sprites, charsets, music, ChillED screens), a copy of both ACME cross assembler and Exomizer (for assembling and compressing the game) and a .bat file that turns my source text file into a C64 executable by calling the afore-mentioned ACME.

While doing this, I also started a new source code file (thus begins the code for the game) and copied in my usual set-up code that, for Chiller 2, looks a little like this...


 ; the name and file format for the assembled program  
   
           !to "chiller2.prg",cbm  
   
 ; position of the raster interrupt(s) on-screen  
 ; 'rp' is short for 'raster position'! duh!  
   
 raster_1_pos     = $00       ; start of screen  
 
 ; some zp label assignments (variables)  
   
 raster_num       = $50       ; raster counter stores which split we are working in  
 sync             = $51       ; interupt sync variable  
   
 ; add a BASIC startline (SYS 16384) for auto-run after loading  
   
           * = $0801  
           !word code_entry-2  
           !byte $00,$00,$9e  
           !text "16384"  
           !byte $00,$00,$00  
   
 ; entry point for the code  
   
           * = $4000          ; hence sys 16384!  
                       
 code_entry  
   
 ; stop interrupts, disable the roms and set up nmi and irq interrupt pointers
   
           sei                ; disable maskable IRQs  
             
           lda #$35           ; kill EVERYTHING (MWHAHA!) except $f000-$ffff
           sta $01  
             
 ; setup nmi  
   
           lda #<nmi       ; some nmi stuff  
           sta $fffa  
           lda #>nmi  
           sta $fffb  
             
 ; setup irq's  
   
           lda #<int       ; some irq stuff  
           sta $fffe  
           lda #>int  
           sta $ffff  
   
           lda #$7f  
           sta $dc0d          ; disable timer interrupts which can be generated by the two CIA chips
           sta $dd0d          ; the kernal uses such an interrupt to flash the cursor and scan
                              ; the keyboard, so we better stop it  
   
           lda $dc0d          ; by reading this two registers we negate any pending CIA irqs
           lda $dd0d          ; if we don't do this, a pending CIA irq might occur after we
                              ; finish setting up our irq. we don't want that to happen
   
           lda #raster_1_pos  ; starting point of raster on screen ($00)  
           sta $d012  
   
           lda #$1b           ; as there are more than 256 rasterlines, the topmost bit of $d011 serves as
           sta $d011          ; the 9th bit for the rasterline we want our irq to be triggered  
             
           lda #$01  
           sta $d019          ; clear interupt bit  
           sta $d01a          ; tell vicii to generate interupt  
   
           lda #$35           ; turn off basic and kernal rom thus  
           sta $01            ; c64 now sees RAM everywhere except at $d000-$e000  
             
           lda #$18           ; use our custom font charset  
           sta $d018  
   
           cli


What on earth is all that?!?!

Quite simply, it's some code that tells the ACME cross-assembler to set the C64 up and that we're taking full control of the machine so that we will have all 64K available for the project.  This code does things like wiping out all the ROM characters and disabling the C64's internal routines (Kernal) that detects and controls things like I/O functions (keyboard detections and so on).

This code is also setting up a couple of labels/variables for controlling the raster, as well as generating an SYS call so that future builds will create an executable that will autorun when loaded.

Other than that, the code is fairly well commented already!  It is missing some things such as memory locations assignements for where the charset. music, sprites and so on will be, but since I haven't decided on this yet, the code isn't in!

I must give credit to Jason 'T.M.R' Kelk who showed me how to set this up originally and Jon 'Moloch' Mines for providing further explanations.

Next diary entry...


Saturday, 9 March 2019

Screen Editor

A few days ago, I was on IRC chatting to Jon "Moloch" Mines about my game project again and have showed him some initial screen mock-ups.

I have begun experimenting with a background layout using the Arkanix Lab map editor, "CartographPC", or at least an early unreleased rewrite of it that I've been working on.  Since the original game "Chiller" started in a forest, I've decided that so should the sequel!  Here is a *very* early version...


While working within the "CartographPC" unreleased rewrite, I decided to "fork" the PureBasic code and create a new tool specifically to create single screen levels for my game.  The intention is that the new tool will have features such as the ability to export screen and colour RAM to use directly within the ACME based code used to create my sequel to "Chiller".

Thus, my new screen editor "ChillED" is born.  See what I did with the name there?!  The editor looks a little like this...


I've begun using it already to recreate the background I was working on in "CartographPC", but there is still a lot of work to be done on the editor till it's ready to begin creating "real" levels!


Therefore, if the diary appears to be updated very infrequently over the coming weeks, its because I'm coding "ChillED" for my own needs!

Next diary entry...


Saturday, 23 February 2019

Initial Game Plan

Still giving lots of thought to the game idea.

Definitely want it to be an unofficial sequel to "Chiller" by Mastertronic.  Was writing down some initial thoughts and ideas on a piece of paper in work yesterday.  These were all random thoughts/ideas that spilled out and no doubt will change/be revised, but the list went something like this...

  • Single screen levels to avoid scrolling.
  • Hires screens to keep things simple.
  • Cartoon type sprites so looks a little more "jolly" than original game.
  • Player can move/jump quicker than in original game.
  • No lives, just energy bar like original.
  • First level to be in forest, like original.
  • 5 levels like original. Go backwards when complete?
  • Can play as boy or girl, unlike original where boy saves girl.
  • Slightly different player attributes for the boy and girl.
  • Girl quicker, boy slower, but boy takes less energy hit?
  • Use my own "Thriller" music cover as title music - unlikely I'll be sued? ;)
  • 2 channel in game level music, maybe a couple of effects on 3rd channel?

I also highlighted some problems I may encounter...


  • How to create levels and include in code?
  • Collision detection. Use hardware? Software method?
  • Investigate how to do gravity in a game!
  • Tackle sprites in the MSB. Easy to do?
  • Status panel on side to avoid MSB?

Decided to try out pixelling a simple background level design to get a feel of what the game may look like and give myself my inspiration.

Next diary entry...


Wednesday, 20 February 2019

The Beginning

Have been thinking about making a game for the last few days and mentioned it to Jon "Moloch" Mines on IRC.  I also mentioned I'd like to make a sequel to the Mastertronic game "Chiller".

So I guess this is the official start of the project, although the next few weeks and/or months is likely to entail lots of reading and research...

Next diary entry...