;; ICARUS Sprite HUD
;; version 1.0.2
;; by Kevin Skeen (chronosv2)
;;Constants -- These will eventually be modifiable in-engine via a plugin.
;;Configuration Constants -- These control conditional assembly. Anything turned off will NOT be part of your assembled code.
NUM_HPBAR_STEPS = $08 ;;The number of steps in each HP sprite Valid values are #$08, #$04 and #$02.
SPRITE_HUD_DRAW_HPBAR = 1 ;;Set this to 0 to skip drawing HP Bar.
SPRITE_HUD_DRAW_SCORE = 1 ;;Set this to 0 to skip drawing Score.
SPRITE_HUD_DRAW_ICON = 1 ;;Set this to 0 to skip drawing Score Icon. (Automatically skipped if SPRITE_HUD_DRAW_SCORE = 0)
;;Set these to the variable names you want the Sprite HUD to use. Be sure to leave the '#' because these are pointing to variable addresses!
HP_VARIABLE = #playerHP
HP_MAX_VARIABLE = #playerHPMax
CURRENCY_VARIABLE = #playerScore
;;Conditional Assembly -- these IF statements are evaluated DURING the assembly process. Only the code corresponding to a
;; condition that returns true will be assembled into your final code.
;;This code handles how many steps your HP Bar has.
IF NUM_HPBAR_STEPS == #$08
SPRITE_HUD_HPBAR_EMPTY = $67 ;;The empty HP bar on your GameObject Sprite Sheet (each following sprite is filled 1 pixel more)
ELSEIF NUM_HPBAR_STEPS == #$04
SPRITE_HUD_HPBAR_EMPTY = $6B ;;The empty HP bar on your GameObject Sprite Sheet (each following sprite is filled 2 pixel more)
ELSEIF NUM_HPBAR_STEPS == #$02
SPRITE_HUD_HPBAR_EMPTY = $6D ;;The empty HP bar on your GameObject Sprite Sheet (each following sprite is filled 4 pixel more)
ELSEIF NUM_HPBAR_STEPS == #$01
SPRITE_HUD_HPBAR_EMPTY = $6E ;;The empty HP bar on your GameObject Sprite Sheet (each following sprite is filled 8 pixel more)
ELSE
ERROR "Invalid NUM_HPBAR_STEPS value. Valid values are #$02, #$04, #$08."
ENDIF
SPRITE_HUD_SCORE_ICON = $66 ;;The icon for "hearts" (currency) on your sprite sheet.
SPRITE_HUD_NUMBER_0 = $76 ;;The number 0 on your GameObject Sprite Sheet - all numbers must be in order (012..789)
SPRITE_HUD_START_X = $08 ;;The starting X coordinate (in pixels) for the HUD
SPRITE_HUD_HPBAR_START_Y = $10 ;;The starting Y coordinate (in pixels) for HP
SPRITE_HUD_SCORE_START_X = $08 ;;The starting X coordinate (in pixels) for "hearts"
SPRITE_HUD_SCORE_START_Y = $08 ;;The starting Y coordinate (in pixels) for "hearts"
SPRITE_HUD_PALETTE = %00000001 ;;The sprite attributes -- the last 2 bits represent the palette to use
;; XXXXXX00 = Player Palette 1
;; XXXXXX01 = Player Palette 2
;; XXXXXX10 = Monster Palette 1
;; XXXXXX11 = Monster Palette 2
CURRENCY_NUMBER_OF_DIGITS = $03 ;;The number of digits in the Currency display
IF SPRITE_HUD_DRAW_HPBAR == 1
LDA HP_MAX_VARIABLE
IF NUM_HPBAR_STEPS == #$08
LSR ;;\
LSR ;;-- Divide by 8
LSR ;;/
ELSEIF NUM_HPBAR_STEPS == #$04
LSR ;;\
LSR ;;-- Divide by 4
ELSEIF NUM_HPBAR_STEPS == #$02
LSR ;;-- Divide by 2
ELSE
ERROR "Invalid NUM_HPBAR_STEPS value. Valid values are #$02, #$04, #$08."
ENDIF
TAX ;;Store in X
LDA HP_VARIABLE ;;We need the player's current HP stored in a temp variable so we can do math on it.
STA temp ;;So we store it in temp1
LDA #SPRITE_HUD_START_X ;;We need the starting X-coordinate stored in a variable too.
STA temp2 ;;So let's use temp2 for that.
;; This is the main loop.
SpriteHUDDrawLoop:
CPX #$00 ;;We have the number of bars we need to draw in X. If this is 0, we're done.
BEQ endPredraw ;;So BRANCH to endPredraw
LDA temp ;;Load what's left of player HP into Accumulator
BMI emptyBar ;;If the number is negative then we need an empty bar.
CMP #NUM_HPBAR_STEPS ;;If we have NUM_HPBAR_STEPS HP or more left, we need a full bar.
BCS fullBar ;;So BRANCH to fullBar
JSR drawPartialBar ;;If none of these are true, jump to the drawPartialBar subroutine
JMP afterSpriteCalc ;;Jump to the end of the loop where we do some housekeeping on HP temp and X-coord temp2.
fullBar: ;;We need to draw a full bar, so
JSR drawFullBar ;;Jump to drawFullBar Subroutine
JMP afterSpriteCalc ;;Jump to housekeeping
emptyBar: ;;We need to draw an empty bar, so
JSR drawEmptyBar ;;Jump to drawEmptyBar Subroutine
afterSpriteCalc: ;;Housekeeping starts here
;;We just drew NUM_HPBAR_STEPS HP, so we need to subtract NUM_HPBAR_STEPS from temp so we can calculate for the next bar.
LDA temp ;; Load temp into Accumulator for this.
SEC ;;Don't forget to set Carry.
SBC #NUM_HPBAR_STEPS ;;Now we do the subtraction
STA temp ;;And store it back in temp.
LDA temp2 ;;Now we load the X-coordinate
CLC ;;Clear carry (I forgot to do this once and got a weird 1px space between bar 1 and 2! This is why you CLC!)
ADC #$08 ;;Add the width of a bar (8)
STA temp2 ;;Store the number back in temp2.
DEX ;;We just drew a bar so subtract 1 from X.
JMP SpriteHUDDrawLoop ;;And start again.
endPredraw:
JMP afterHPPredraw ;;We need to declare these subroutines but we don't want to run them yet, so jump over them.
drawEmptyBar: ;;Draws an empty bar using the usual Predraw sprite macro template.
DrawSprite temp2, #SPRITE_HUD_HPBAR_START_Y, #SPRITE_HUD_HPBAR_EMPTY, #SPRITE_HUD_PALETTE, spriteOffset
inc spriteOffset
inc spriteOffset
inc spriteOffset
inc spriteOffset
RTS ;;This is a SUBROUTINE so RTS sends us back to where we came from -- one command after JSR drawEmptyBar
drawFullBar: ;;Draws an empty bar using the usual Predraw sprite macro template.
LDA #SPRITE_HUD_HPBAR_EMPTY ;;We need the address of the empty bar sprite
CLC ;;Don't forget to clear carry like I always do!
ADC #NUM_HPBAR_STEPS ;;Add NUM_HPBAR_STEPS (the number of increments in the bar)
STA temp3 ;;Store it in a variable so we can feed it to the sprite draw macro.
DrawSprite temp2, #SPRITE_HUD_HPBAR_START_Y, temp3, #SPRITE_HUD_PALETTE, spriteOffset
inc spriteOffset
inc spriteOffset
inc spriteOffset
inc spriteOffset
RTS ;;This is a SUBROUTINE so RTS sends us back to where we came from -- one command after JSR drawFullBar
drawPartialBar: ;;Draws a partial bar
LDA HP_VARIABLE ;;We need the player's actual HP, not the number we're playing with in temp.
IF NUM_HPBAR_STEPS == #$08
AND #%00000111 ;;We only care if the number is between 0 and 7 so and out the rest.
ELSEIF NUM_HPBAR_STEPS == #$04
AND #%00000011 ;;We only care if the number is between 0 and 7 so and out the rest.
ELSEIF NUM_HPBAR_STEPS == #$02
AND #%00000001 ;;We only care if the number is between 0 and 7 so and out the rest.
ELSE
ERROR "Invalid NUM_HPBAR_STEPS value. Valid values are #$02, #$04, #$08."
ENDIF
;;D #%00000111 ;;We only care if the number is between 0 and 7 so and out the rest.
CLC ;;You know the drill. Clear carry before an add!
ADC #SPRITE_HUD_HPBAR_EMPTY ;;Add the memory address of the empty bar.
STA temp3 ;;Store it somewhere so we can use it in the sprite draw macro.
DrawSprite temp2, #SPRITE_HUD_HPBAR_START_Y, temp3, #SPRITE_HUD_PALETTE, spriteOffset
inc spriteOffset
inc spriteOffset
inc spriteOffset
inc spriteOffset
RTS ;;This is a SUBROUTINE so RTS sends us back to where we came from -- one command after JSR drawPartialBar
ENDIF
afterHPPredraw: ;;Done doing the health bar, now for the score/currency.
IF SPRITE_HUD_DRAW_SCORE == 1
LDA #SPRITE_HUD_SCORE_START_X ;;We need the starting X-coordinate for currency.
STA temp2 ;;Store it in Temp2.
;DEX
IF SPRITE_HUD_DRAW_ICON == 1
DrawSprite temp2, #SPRITE_HUD_SCORE_START_Y, #SPRITE_HUD_SCORE_ICON, #SPRITE_HUD_PALETTE, spriteOffset ;;Draw the ICON.
inc spriteOffset
inc spriteOffset
inc spriteOffset
inc spriteOffset
LDA temp2 ;;We need to add the width of a number to temp2
CLC ;;So clear carry
ADC #$08 ;;Add 8
STA temp2 ;;Store the number.
ENDIF
LDX #CURRENCY_NUMBER_OF_DIGITS
currencyLoop:
DEX
LDA CURRENCY_VARIABLE,x ;;We need to draw a digit. Grab each one in descending order (Thousands, hundreds, tens, etc)
CLC ;;Clear carry
ADC #SPRITE_HUD_NUMBER_0 ;;Add the address of our "0" number and we have the number ready to draw!
STA temp ;;Just gotta' store it in a variable for the DrawSprite macro.
DrawSprite temp2, #SPRITE_HUD_SCORE_START_Y, temp, #SPRITE_HUD_PALETTE, spriteOffset
inc spriteOffset
inc spriteOffset
inc spriteOffset
inc spriteOffset
LDA temp2 ;;Increasing X by 8 again.
CLC
ADC #$08
STA temp2
CPX #$00
BEQ doneCurrency
JMP currencyLoop
doneCurrency:
ENDIF