(4.5.9) Extra Lives Tiles, Game Over and Continues!

TolerantX

Active member
(4.5.9) Extra Lives Tiles, Game Over and Continues! (oh my!)
Lives Continues Game Over.jpg7fcd7ff304c606906ecf1dee9507cf82.jpg

Maybe you want a tile that gives an extra life in a game using a lives system, maybe you want a way to continue the game after running out of lives, or maybe you just want the game to warp to a specific screen when you have no lives left. If any of these might be in your game, then you've come to the right place!

Introducing: Extra Life Tiles!

Step 1: Your "myLives" variable is represented in the HUD (*In this script, it will be HUD Element #1*)
(see picture on step #2)

Step 2: Your "myLives" variable is a max value 1 in your HUD. (lives will be 0-9 or you may use a var tile (the max is 8)
Screenshot 2022-02-02 184942.png

The Tile Script:

Code:
;;; Extra_Life tile

CPX player1_object                    ;; checks for player collision, so weapons and monsters, etc don't trigger this tile ;;
BEQ +isPlayer                        ;; if it's the player object, go to +isPlayer, if not go to next line. ;;
    JMP +notPlayer                    ;; jump to subroutine label +notPlayer ;;

    +isPlayer                        ;; This is what happens if it is a player object collision. ;;
  
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BELOW WILL CHANGE TILE AT COLLISION. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  
    ChangeTileAtCollision #$00, #$00        ;; this macro changes the tile to null collision, tile changes to look like location 00. ;;

        LDA myLives                    ;; loads the variable myLives into the accumulator. ;;
        CMP #$09                       ;; max of 9 for single digit lives. if var_tile in HUD use up to #$08. This depends on what your var_tiles are. ;;
        BNE +increaseLives         ;; if not 9 lives then increaseLives. if var_tile in HUD use up to #$08. This depends on what your var_tiles are. ;;
            JMP +notPlayer           ;; instead of picking up the extra life, it will just ignore you ;;

        +increaseLives:
            INC myLives                ;; increase lives by 1 ;;
            UpdateHudElement #$01    ;; update the Hud element associated with myLives, which is "Element 1" currently ;;
;            PlaySound #sfx_LivesPickup   ;;uncomment for sfx to be activated on pickup ;;
            JMP +notPlayer
      
  
    +notPlayer

(also available: https://drive.google.com/file/d/1-nDS5FA00Oo_MlNYFTQrzNZX2HgE_UxW/view?usp=sharing )

I understand that tile could have been a standalone script download, but wanted to make sure it's used properly because the next steps have similar "elements" ;) (I know, it's a bad pun.)

The Game Over System with Continues!

First, ask yourself what you want it to do when you are hurt... do you get stunned and/or lose health or do you die automatically?
In Arcade Platformer Module (I used as a basis on which this system was made, though this is "compatible" with other modules.) you touch an enemy and you lose a life and go to previous checkpoint and when you lose all lives it resets the game.
What if you want the player to, when hurt lose a life (or if adventure module, myHealth)?
Code example would be: DEC myLives (or in adventure module DEC myHealth)
Keep in mind when using Adventure Script or any script that has: GetActionStep temp / CMP #$07 defined already. (example below is a no-no)
Screenshot 2022-02-02 193138.png
In the example above, you would want ideally the CMP to be for #$06 or something other than #$07 because in the Game Over system Action Step 7 is player Death Animation.

In Adventure Module script for hurtPlayer you may see something like "playerHealthIsZero"
The entry for that is where it tells the game to do things when you die (aka game over, because it has 1 life by default).
You there would want to comment out that portion below it before +skipHurt (don't ever mess with the skipHurt)

using PlayerHurtHealth.asm as a base to make this script:

Code:
;; untested by me currently ;;

    LDA gameHandler
    AND #%10000000
    BEQ +canHurtPlayer
        JMP +skipHurt
+canHurtPlayer:
    TXA
    STA temp
    GetActionStep temp
    CMP #$06                ;; this cannot be #$07 if you use stunned/hurt action step;;
    BNE +canHurtPlayer
        JMP +skipHurt
    +canHurtPlayer
    ;;; will presume there is a variable myHealth
    ;;; and that player hurt state is action state 7.
    GetActionStep player1_object
    CMP #$06 ;; hurt state.     ;; this cannot be #$07 if you use stunned/hurt action step;;
    BEQ +notAlreadyInHurtState
        DEC myHealth
      
        BMI +healthBelowZero
        BEQ +healthBelowZero
            JMP +notDeadYet
        +healthBelowZero
            JMP +playerHealthIsZero
        +notDeadYet
        UpdateHudElement #$02
        ChangeActionStep player1_object, #$06            ;; stun / hurt step, not your death step ;;
            ;; recoil
            LDA #$00
            STA Object_h_speed_hi,x
            STA Object_h_speed_lo,x
            STA Object_v_speed_hi,x
            STA Object_v_speed_lo,x
            LDA xPrev
            STA Object_x_hi,x
            LDA yPrev
            STA Object_y_hi,x
    +notAlreadyInHurtState
        LDA Object_x_hi,x
        CLC
        ADC self_center_x
        STA tempA
        LDA Object_y_hi,x
        CLC
        ADC self_center_y
        STA tempB
        TXA
        PHA
            LDX otherObject
            LDA Object_x_hi,x
            CLC
            ADC other_center_x
            STA tempC
            LDA Object_y_hi,x
            CLC
            ADC other_center_y
            STA tempD
        PLA
        TAX
  
        ;;; RECOIL
        ;;; find the center.
        LDA tempA
        SEC
        SBC tempC
        bpl +gotAbs ;; if positive, this is abs value
            EOR #$FF
            CLC
            ADC #$01
        +gotAbs
            STA temp
          
        LDA tempB
        SEC
        SBC tempD
        bpl +gotAbs
            EOR #$FF
            CLC
            ADC #$01
        +gotAbs
            ;;; now abs of y is in A
            CMP temp
            BCC +recoilHor
                ;; recoil vert
                LDA tempB
                CMP tempD
                BCS +recoilDown
                    LDA Object_direction,x
                    AND #%00001111
                    ORA #%00100000
                    STA Object_direction,x
                    JMP +skipHurt
                +recoilDown
                    LDA Object_direction,x
                    AND #%00001111
                    ORA #%00110000
                    STA Object_direction,x
                    JMP +skipHurt
            +recoilHor
                LDA tempA
                CMP tempC
                BCS +recoilRight
                    LDA Object_direction,x
                    AND #%00001111
                    ORA #%10000000
                    STA Object_direction,x
                    JMP +skipHurt

                +recoilRight
                    LDA Object_direction,x
                    AND #%00001111
                    ORA #%11000000
                    STA Object_direction,x
                    JMP +skipHurt
  
        JMP +skipHurt
+playerHealthIsZero:

    ChangeActionStep player1_object, #$07     ;; set the player action in step 7 to "gotoContinue" ;;
        LDA #$00             
        STA Object_h_speed_hi,x
        STA Object_h_speed_lo,x
        STA Object_v_speed_hi,x
        STA Object_v_speed_lo,x


;LDA continueMap
;STA warpMap
  
;LDA continueScreen
;STA currentNametable
  
;LDX player1_object
;STA Object_screen,x
  
;LDA #$02 ;; this is continue type warp.
;STA screenTransitionType ;; is of warp type

  
;LDA gameHandler
;ORA #%10000000
;STA gameHandler ;; this will set the next game loop to update the screen.
;LDA myMaxHealth
;STA myHealth

+skipHurt

(also available: https://drive.google.com/file/d/1WY8sgAGjeLGp9rqrYqB7b3LW6Ejge8EK/view?usp=sharing )

END OF PART 1...
 
Last edited:

TolerantX

Active member
PART 2.....


In Arcade Platformer Module script for hurtPlayer you may see something like "myLivesNotZero"
The entry for that is where it tells the game to do things when you are game over.
You there would want to comment out that portion below it before +skipHurt (don't ever mess with the skipHurt)

using hurtPlayer_ArcadePlatformer.asm as a base to make this script:

Code:
    ;;;;;;;;;;;;;;;;;; Presumes there is a variable called myLives defined in user variables.
    ;;;;;;;;;;;;;;;;;; You could also create your own variable for this.

    LDA gameHandler
    AND #%10000000
    BEQ +canHurtPlayer
        JMP +skipHurt
+canHurtPlayer:
    ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; ;;;;;;;;;; is the monster below our feet?
    ; ;;;;;;;;;; and are we moving downward?
   
    ; LDA Object_v_speed_hi,x
    ; BEQ +doHurtPlayer ;; equal to zero
    ; BMI +doHurtPlayer ;; or negative
     ; ;; here we are moving downward.
    ; TXA
    ; PHA
        ; LDX otherObject
        ; DestroyObject
    ; PLA
    ; TAX

     ; ;; Do a hop
     ; LDA #$FC
     ; STA Object_v_speed_hi,x
   

     ; JMP +skipHurt
   
+doHurtPlayer  
    LDA Object_direction,x
    AND #%00001111
    STA Object_direction,x
   
    Dec myLives
;    LDA myLives
;    BNE myLivesNotZero
;        JMP RESET ;; game over.
        ;;;; also could warp to game over screen here instead.
;myLivesNotZero:
   
    ChangeActionStep player1_object, #$07     ;; set the player action in step 7 to "gotoContinue" ;;
        LDA #$00              
        STA Object_h_speed_hi,x
        STA Object_h_speed_lo,x
        STA Object_v_speed_hi,x
        STA Object_v_speed_lo,x

;    LDA continueMap
;    STA warpMap
   
;    LDA continueScreen
;    STA currentNametable
;    AND #%00001111
;    STA camX_hi
   
;    LDX player1_object
;    STA Object_screen,x
   
;    LDA #$02 ;; this is continue type warp.
;    STA screenTransitionType ;; is of warp type

   
;    LDA #$00
;    STA camX
   
;    LDA gameHandler
;    ORA #%10000000
;    STA gameHandler ;; this will set the next game loop to update the screen.

+skipHurt

(also available: https://drive.google.com/file/d/1fM4S3bSJfHcKB1z4uOrux4QN1iLC_orC/view?usp=sharing )


Next, If you want a Hurt Player / Death Tile, it needs to operate by the same rules as the player hurt script...
for an Arcade Platformer Module death tile using the hurt script above, all you would need is something like this:

Code:
;;; Player_Death Tile
    ;; check to see if object colliding is a player.
    ;; if not, do not put player in action step 7 and subtract a life.
    CPX player1_object
    BNE dontDoTileReset
    TXA
    STA temp ;; assumes the object we want to move is in x.
    GetActionStep temp
    CMP #$07                ;; death is set to step 7 for player. this keeps it from an instant game over. ;;
    BNE +canHurtPlayer
        JMP +dontDoTileReset

+canHurtPlayer:
        LDA Object_direction,x
        AND #%00001111
        STA Object_direction,x
   
        Dec myLives

        ChangeActionStep player1_object, #$07     ;; set the player action in step 7 to "gotoContinue" ;;
                ;; The settings for 'gotoContinue" are located in timerendscripts.asm ;;
            LDA #$00              
            STA Object_h_speed_hi,x
            STA Object_h_speed_lo,x
            STA Object_v_speed_hi,x
            STA Object_v_speed_lo,x

dontDoTileReset:

Your Death Animation should be in step 7 for this script set up as in the picture below: (having EndAction or End Animation gotoContinue)
Screenshot 2022-02-02 201553.png

The most important parts are next:

Step 1: Create a new variable and name it "myContinues" and set it as the number you want (0 or 1 most likely, for testing)

Screenshot 2022-02-02 203340.png

Because the Death Animation is set to gotoContinue, you will need to change some things.

Step 2: You are going to need to edit your TimerEndScripts.asm. These are located in your subroutines folder (always backup original scripts) .
On Line 151 it handles Warps. If you want your player to default to action step 0 on warp in instead of possibly being stuck in aciton step 7 perpetually you will need this edit:

Code:
;;; 07 = Go To Warp
goToWarp_action:
    WarpToScreen warpToMap, warpToScreen, #$01
    ChangeActionStep player1_object, #$00
    RTS

you'll notice all that was changed was adding line: ChangeActionStep player1_object, #$00

at line 159 or 160 you may see Go To Continue. around here we will do our edit. This part is important because ALL the death information after you lose your health/life is located here.

In the default you will see:

Code:
;;; 09 = Go To Continue
goToContinue_action:
    LDA continueMap
    STA warpMap
   
    LDA continueScreen
    STA currentNametable
   
    LDX player1_object
    STA Object_screen,x
   
    LDA #$02 ;; this is continue type warp.
    STA screenTransitionType ;; is of warp type

   
    LDA gameHandler
    ORA #%10000000
    STA gameHandler ;; this will set the next game loop to update the screen.
    ChangeActionStep player1_object, #$00
    LDX player1_object
    LDA #$00000000
    STA Object_direction,x
    RTS


we will be changing all of this to:

Code:
;;; 09 = Go To Continue
goToContinue_action:

;; Insert EDIT to this action BELOW ;;

    LDA gameHandler
    ORA #%10000000
    STA gameHandler ;; this will set the next game loop to update the screen.
    ChangeActionStep player1_object, #$00
    LDX player1_object
    LDA #$00000000
    STA Object_direction,x

    LDA myLives        ;; load the data of variable myLives into the accumulator ;;
    BEQ +myLivesZero        ;; if my lives are zero go to +myLivesZero if not, continue to next line. ;;
        JMP +myLivesNotZero ;; my lives is not zero go to +myLivesNotZero ;;

+myLivesZero:

;; Zero Lives Check for Continues and Warp To Continue Screen ;;

        LDA myContinues            ;; load data of variable myContinues into the accumulator. ;;
        BNE +myContinuesNotZero ;; if myContinues variable is NOT zero, go to +myContinuesNotZero if not, continue to next line. ;;
            JMP +myGameOver        ;; if no continues left, go to +myGameOver. ;;

+myContinuesNotZero:

;;    What Happens When there are Continues Here ;;

    LDA #$E6             ;; the screen number you want to warp to that asks to continue? ;;
    STA warpToScreen
    LDA #$01                ;; the map to warp to (overworld/underworld)
    STA warpToMap

    WarpToScreen warpToMap, warpToScreen, #$02
     RTS

+myGameOver:
;;    What Happens When Game Over (no Continues Left) Here ;;

    LDA #$E7             ;; the screen number you want to warp to for GAME OVER ;;
    STA warpToScreen
    LDA #$01                ;; the map to warp to (overworld/underworld)
    STA warpToMap

    WarpToScreen warpToMap, warpToScreen, #$02
     RTS

+myLivesNotZero:

;; End EDIT of this action ABOVE ;;

    LDA continueMap
    STA warpMap
   
    LDA continueScreen
    STA currentNametable
   
    LDX player1_object
    STA Object_screen,x
   
    LDA #$02 ;; this is continue type warp.
    STA screenTransitionType ;; is of warp type
     RTS

TimerEndScripts.asm file download: https://drive.google.com/file/d/1W8jMbL5V0U39NrXfPumPkF9tfQWp4Fmq/view?usp=sharing


in the script you'll see the lines:
LDA #$E6 ;; the screen number you want to warp to that asks to continue? ;;
STA warpToScreen
LDA #$01 ;; the map to warp to (overworld/underworld)
STA warpToMap

and another below for #$E7

those are the map coordinates of your continue screen (E6) and game over screen (E7)
THE BOTTOM RIGHT TWO SCREENS ON 8x8 TILES
on my game I use underworld (LDA #$01, above) and 8x8 tile screens for my continue and game over screens:

Screenshot 2022-02-02 204613.png

End of Part 2 .....
 

TolerantX

Active member
Part 3 ADDING CONTINUES to INPUTS...


Follow the first two parts you should now have a variable for myContinues.
Step 1: If you do not have a Game State for GAME OVER create one now...
Screenshot 2022-02-02 205510.png

This state can and will obviously be used for our game over and continue screens. Yeah, the way we have the code set up both can use the same screen, and as an added bonus, because JMP RESET is a code line EVERYONE should know by now, I put that as a "default action when you're on the Game Over screen with no continues, it will JMP RESET your game. (of course if you don't want this, you can comment it out on line 7.)


LDA myContinues
BNE +doContinue
; JMP RESET


*NEW INPUT SCRIPT* Continue_Game.asm :

Code:
;;; This script can be used as a restart game from screen input script.
;;; It will take you to the previous screen and set up new continue points based on
;;; that screen's info.

    LDA myContinues
    BNE +doContinue      
        JMP RESET
      
+doContinue:
;;;; THE PART HERE RESETS YOUR SCORE 8 DIGITS;;;;

LDA #$00
STA myScore
STA myScore+1
STA myScore+2
STA myScore+3
STA myScore+4
STA myScore+5
STA myScore+6
STA myScore+7

;;;; THE PART ABOVE RESETS YOUR SCORE 8 DIGITS;;;;
;;;; THE LINE BELOW IS EDITED FOR IF YOU USE A VARIABLE FOR CONTINUES/CREDITS ;;;;

DEC myContinues

LDA screenUpdateByte
ORA #%00000100
STA screenUpdateByte

    LDA continueMap
    STA warpMap
  
    LDA continueScreen
    STA currentNametable
  
    LDX player1_object
    STA Object_screen,x
  
    LDA #$02 ;; this is continue type warp.
    STA screenTransitionType ;; is of warp type

    LDA #$03
    STA myLives

;    LDA #$02        ;; in my game you start with 2 ammo ;;
;    STA myAmmo

    LDA gameHandler
    ORA #%10000000
    STA gameHandler ;; this will set the next game loop to update the screen.

    StopMoving player1_object, #$FF
    ChangeFacingDirection player1_object, #FACE_RIGHT

+EndofScript:

   RTS

(also available at : https://drive.google.com/file/d/1toJXx8LgPRfYBls4VMhlMBX-rPHIyCCZ/view?usp=sharing )

In this code you will notice various things that are game specific:
myScore in my game has 8 places, hence the resets on each place.
it DEC myContinues (decrement / decrease by 1)
LDA #$03 ;; starts player with 3 lives ;;
STA myLives

; LDA #$02 ;; in my game you start with 2 ammo ;;
; STA myAmmo ;; myAmmo variable ;;

StopMoving player1_object, #$FF ;; stops the player from moving if moving when dying ;;
ChangeFacingDirection player1_object, #FACE_RIGHT ;; makes the player face right ;;

These may all be different in your game... perhaps you use maxHealth or myHealth variables, perhaps you want to face left when you spawn, or maybe you don't use myAmmo. for simplicity sake I will comment out myAmmo segment. IF you use ammo, perhaps you will uncomment it.

Okay now we want to use the script. Since it's an input script you load it in like the other inputs...
Screenshot 2022-02-02 211440.png

In my game I have it in my games Inputs folder, but essentially its just like adding movement scripts in any project.
Next is the input linker for the controller... You want it so when you're in GAME OVER game state when you press START the continueGame.asm happens. like below:
Screenshot 2022-02-02 211854.png

As stated above, it will do the continue script after checking if you have any. if you have 0, it will reset your game. (This is handled on lines 5-7 of the script)

I understand this script is not adapted for anything other than Arcade Platformer at the moment, and with my notes and yours, you should be able to easily adapt it to other games. Adventure Module will have trouble with this, but hopefully someone will add their own scripts to these.

If you're a fan of LIVE DIE REPEAT concept from that Tom Cruise movie, where you can continue indefinitely:

(Link to continueGameInfinite.asm : https://drive.google.com/file/d/1GJY1w7nZNxX5cj27-2jr3k1YW4JcT4Xx/view?usp=sharing )

Lastly, I am including a youtube video link of the Game Over System and Scripts in action:

View: https://youtu.be/QAYZvnfkbaw


d0d.jpg

Thank you, and have a nice day!
 
Last edited:

TolerantX

Active member
Part 3 ADDING CONTINUES to INPUTS...


Follow the first two parts you should now have a variable for myContinues.
Step 1: If you do not have a Game State for GAME OVER create one now...
View attachment 5904

This state can and will obviously be used for our game over and continue screens. Yeah, the way we have the code set up both can use the same screen, and as an added bonus, because JMP RESET is a code line EVERYONE should know by now, I put that as a "default action when you're on the Game Over screen with no continues, it will JMP RESET your game. (of course if you don't want this, you can comment it out on line 7.)


LDA myContinues
BNE +doContinue
; JMP RESET


*NEW INPUT SCRIPT* Continue_Game.asm :

Code:
;;; This script can be used as a restart game from screen input script.
;;; It will take you to the previous screen and set up new continue points based on
;;; that screen's info.

    LDA myContinues
    BNE +doContinue     
        JMP RESET
     
+doContinue:
;;;; THE PART HERE RESETS YOUR SCORE 8 DIGITS;;;;

LDA #$00
STA myScore
STA myScore+1
STA myScore+2
STA myScore+3
STA myScore+4
STA myScore+5
STA myScore+6
STA myScore+7

;;;; THE PART ABOVE RESETS YOUR SCORE 8 DIGITS;;;;
;;;; THE LINE BELOW IS EDITED FOR IF YOU USE A VARIABLE FOR CONTINUES/CREDITS ;;;;

DEC myContinues

LDA screenUpdateByte
ORA #%00000100
STA screenUpdateByte

    LDA continueMap
    STA warpMap
 
    LDA continueScreen
    STA currentNametable
 
    LDX player1_object
    STA Object_screen,x
 
    LDA #$02 ;; this is continue type warp.
    STA screenTransitionType ;; is of warp type

    LDA #$03
    STA myLives

;    LDA #$02        ;; in my game you start with 2 ammo ;;
;    STA myAmmo

    LDA gameHandler
    ORA #%10000000
    STA gameHandler ;; this will set the next game loop to update the screen.

    StopMoving player1_object, #$FF
    ChangeFacingDirection player1_object, #FACE_RIGHT

+EndofScript:

   RTS

(also available at : https://drive.google.com/file/d/1toJXx8LgPRfYBls4VMhlMBX-rPHIyCCZ/view?usp=sharing )

In this code you will notice various things that are game specific:
myScore in my game has 8 places, hence the resets on each place.
it DEC myContinues (decrement / decrease by 1)
LDA #$03 ;; starts player with 3 lives ;;
STA myLives

; LDA #$02 ;; in my game you start with 2 ammo ;;
; STA myAmmo ;; myAmmo variable ;;

StopMoving player1_object, #$FF ;; stops the player from moving if moving when dying ;;
ChangeFacingDirection player1_object, #FACE_RIGHT ;; makes the player face right ;;

These may all be different in your game... perhaps you use maxHealth or myHealth variables, perhaps you want to face left when you spawn, or maybe you don't use myAmmo. for simplicity sake I will comment out myAmmo segment. IF you use ammo, perhaps you will uncomment it.

Okay now we want to use the script. Since it's an input script you load it in like the other inputs...
View attachment 5905

In my game I have it in my games Inputs folder, but essentially its just like adding movement scripts in any project.
Next is the input linker for the controller... You want it so when you're in GAME OVER game state when you press START the continueGame.asm happens. like below:
View attachment 5906

As stated above, it will do the continue script after checking if you have any. if you have 0, it will reset your game. (This is handled on lines 5-7 of the script)

I understand this script is not adapted for anything other than Arcade Platformer at the moment, and with my notes and yours, you should be able to easily adapt it to other games. Adventure Module will have trouble with this, but hopefully someone will add their own scripts to these.

If you're a fan of LIVE DIE REPEAT concept from that Tom Cruise movie, where you can continue indefinitely:

(Link to continueGameInfinite.asm : https://drive.google.com/file/d/1GJY1w7nZNxX5cj27-2jr3k1YW4JcT4Xx/view?usp=sharing )

Lastly, I am including a youtube video link of the Game Over System and Scripts in action:

View: https://youtu.be/QAYZvnfkbaw


View attachment 5907

Thank you, and have a nice day!
View: https://youtu.be/PJ1P50uh2Kk
 

TolerantX

Active member
I needed to add this in my game for some reason it had a conflict with my pause script...
A check for game state in the beginning of the input.

Code:
;;; This script can be used as a restart game from screen input script.
;;; It will take you to the previous screen and set up new continue points based on
;;; that screen's info.

;;; GAME STATE CHECK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
    LDA gameState         ;; CHECK GAMESTATES             ;;
    CMP #$03              ;; GAME OVER GAME STATE         ;;
    BEQ +onGameOver        ;; EQUAL TO GAME OVER STATE    ;;
        RTS

+onGameOver
    LDA myContinues
    BNE +doContinue    
        JMP RESET
     
+doContinue:
;;;; THE PART HERE RESETS YOUR SCORE 6 DIGITS;;;;

LDA #$00
STA myScore
STA myScore+1
STA myScore+2
STA myScore+3
STA myScore+4
STA myScore+5

;;;; THE PART ABOVE RESETS YOUR SCORE 8 DIGITS;;;;
;;;; THE LINE BELOW IS EDITED FOR IF YOU USE A VARIABLE FOR CONTINUES/CREDITS ;;;;

DEC myContinues

LDA screenUpdateByte
ORA #%00000100
STA screenUpdateByte

    LDA continueMap
    STA warpMap
 
    LDA continueScreen
    STA currentNametable
 
    LDX player1_object
    STA Object_screen,x
 
    LDA #$02 ;; this is continue type warp.
    STA screenTransitionType ;; is of warp type

    LDA #$03
    STA myLives

    LDA gameHandler
    ORA #%10000000
    STA gameHandler ;; this will set the next game loop to update the screen.

    StopMoving player1_object, #$FF
    ChangeFacingDirection player1_object, #FACE_RIGHT
    RTS

Above code is my finished code for Continue_Input.asm
GAME OVER / CONTINUE GAME STATE IS #$03 in my Project/Game.

Also, I know I could have changed my Pause input to also have the check like this :

Code:
;;; GAME STATE CHECK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    LDA gameState         ;; CHECK GAMESTATES             ;;

    BEQ +onMainGame        ;; EQUAL TO MAIN GAME STATE AKA #$00   ;;

        RTS

+onMainGame

and did so, just for good measure. WHY NOT?
 
Last edited:

SciNEStist

Well-known member
Instead of warping to an all red screen, then warping again, why not change the sprite palletes to all black and the tile pallettes to all red, then warp after? (thats how zelda 2 did it)
 
(4.5.9) Extra Lives Tiles, Game Over and Continues! (oh my!)
View attachment 5896View attachment 5893

Maybe you want a tile that gives an extra life in a game using a lives system, maybe you want a way to continue the game after running out of lives, or maybe you just want the game to warp to a specific screen when you have no lives left. If any of these might be in your game, then you've come to the right place!

Introducing: Extra Life Tiles!

Step 1: Your "myLives" variable is represented in the HUD (*In this script, it will be HUD Element #1*)
(see picture on step #2)

Step 2: Your "myLives" variable is a max value 1 in your HUD. (lives will be 0-9 or you may use a var tile (the max is 8)
View attachment 5898

The Tile Script:

Code:
;;; Extra_Life tile

CPX player1_object                    ;; checks for player collision, so weapons and monsters, etc don't trigger this tile ;;
BEQ +isPlayer                        ;; if it's the player object, go to +isPlayer, if not go to next line. ;;
    JMP +notPlayer                    ;; jump to subroutine label +notPlayer ;;

    +isPlayer                        ;; This is what happens if it is a player object collision. ;;
 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BELOW WILL CHANGE TILE AT COLLISION. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
    ChangeTileAtCollision #$00, #$00        ;; this macro changes the tile to null collision, tile changes to look like location 00. ;;

        LDA myLives                    ;; loads the variable myLives into the accumulator. ;;
        CMP #$09                       ;; max of 9 for single digit lives. if var_tile in HUD use up to #$08. This depends on what your var_tiles are. ;;
        BNE +increaseLives         ;; if not 9 lives then increaseLives. if var_tile in HUD use up to #$08. This depends on what your var_tiles are. ;;
            JMP +notPlayer           ;; instead of picking up the extra life, it will just ignore you ;;

        +increaseLives:
            INC myLives                ;; increase lives by 1 ;;
            UpdateHudElement #$01    ;; update the Hud element associated with myLives, which is "Element 1" currently ;;
;            PlaySound #sfx_LivesPickup   ;;uncomment for sfx to be activated on pickup ;;
            JMP +notPlayer
     
 
    +notPlayer

(also available: https://drive.google.com/file/d/1-nDS5FA00Oo_MlNYFTQrzNZX2HgE_UxW/view?usp=sharing )

I understand that tile could have been a standalone script download, but wanted to make sure it's used properly because the next steps have similar "elements" ;) (I know, it's a bad pun.)

The Game Over System with Continues!

First, ask yourself what you want it to do when you are hurt... do you get stunned and/or lose health or do you die automatically?
In Arcade Platformer Module (I used as a basis on which this system was made, though this is "compatible" with other modules.) you touch an enemy and you lose a life and go to previous checkpoint and when you lose all lives it resets the game.
What if you want the player to, when hurt lose a life (or if adventure module, myHealth)?
Code example would be: DEC myLives (or in adventure module DEC myHealth)
Keep in mind when using Adventure Script or any script that has: GetActionStep temp / CMP #$07 defined already. (example below is a no-no)
View attachment 5900
In the example above, you would want ideally the CMP to be for #$06 or something other than #$07 because in the Game Over system Action Step 7 is player Death Animation.

In Adventure Module script for hurtPlayer you may see something like "playerHealthIsZero"
The entry for that is where it tells the game to do things when you die (aka game over, because it has 1 life by default).
You there would want to comment out that portion below it before +skipHurt (don't ever mess with the skipHurt)

using PlayerHurtHealth.asm as a base to make this script:

Code:
;; untested by me currently ;;

    LDA gameHandler
    AND #%10000000
    BEQ +canHurtPlayer
        JMP +skipHurt
+canHurtPlayer:
    TXA
    STA temp
    GetActionStep temp
    CMP #$06                ;; this cannot be #$07 if you use stunned/hurt action step;;
    BNE +canHurtPlayer
        JMP +skipHurt
    +canHurtPlayer
    ;;; will presume there is a variable myHealth
    ;;; and that player hurt state is action state 7.
    GetActionStep player1_object
    CMP #$06 ;; hurt state.     ;; this cannot be #$07 if you use stunned/hurt action step;;
    BEQ +notAlreadyInHurtState
        DEC myHealth
     
        BMI +healthBelowZero
        BEQ +healthBelowZero
            JMP +notDeadYet
        +healthBelowZero
            JMP +playerHealthIsZero
        +notDeadYet
        UpdateHudElement #$02
        ChangeActionStep player1_object, #$06            ;; stun / hurt step, not your death step ;;
            ;; recoil
            LDA #$00
            STA Object_h_speed_hi,x
            STA Object_h_speed_lo,x
            STA Object_v_speed_hi,x
            STA Object_v_speed_lo,x
            LDA xPrev
            STA Object_x_hi,x
            LDA yPrev
            STA Object_y_hi,x
    +notAlreadyInHurtState
        LDA Object_x_hi,x
        CLC
        ADC self_center_x
        STA tempA
        LDA Object_y_hi,x
        CLC
        ADC self_center_y
        STA tempB
        TXA
        PHA
            LDX otherObject
            LDA Object_x_hi,x
            CLC
            ADC other_center_x
            STA tempC
            LDA Object_y_hi,x
            CLC
            ADC other_center_y
            STA tempD
        PLA
        TAX
 
        ;;; RECOIL
        ;;; find the center.
        LDA tempA
        SEC
        SBC tempC
        bpl +gotAbs ;; if positive, this is abs value
            EOR #$FF
            CLC
            ADC #$01
        +gotAbs
            STA temp
         
        LDA tempB
        SEC
        SBC tempD
        bpl +gotAbs
            EOR #$FF
            CLC
            ADC #$01
        +gotAbs
            ;;; now abs of y is in A
            CMP temp
            BCC +recoilHor
                ;; recoil vert
                LDA tempB
                CMP tempD
                BCS +recoilDown
                    LDA Object_direction,x
                    AND #%00001111
                    ORA #%00100000
                    STA Object_direction,x
                    JMP +skipHurt
                +recoilDown
                    LDA Object_direction,x
                    AND #%00001111
                    ORA #%00110000
                    STA Object_direction,x
                    JMP +skipHurt
            +recoilHor
                LDA tempA
                CMP tempC
                BCS +recoilRight
                    LDA Object_direction,x
                    AND #%00001111
                    ORA #%10000000
                    STA Object_direction,x
                    JMP +skipHurt

                +recoilRight
                    LDA Object_direction,x
                    AND #%00001111
                    ORA #%11000000
                    STA Object_direction,x
                    JMP +skipHurt
 
        JMP +skipHurt
+playerHealthIsZero:

    ChangeActionStep player1_object, #$07     ;; set the player action in step 7 to "gotoContinue" ;;
        LDA #$00            
        STA Object_h_speed_hi,x
        STA Object_h_speed_lo,x
        STA Object_v_speed_hi,x
        STA Object_v_speed_lo,x


;LDA continueMap
;STA warpMap
 
;LDA continueScreen
;STA currentNametable
 
;LDX player1_object
;STA Object_screen,x
 
;LDA #$02 ;; this is continue type warp.
;STA screenTransitionType ;; is of warp type

 
;LDA gameHandler
;ORA #%10000000
;STA gameHandler ;; this will set the next game loop to update the screen.
;LDA myMaxHealth
;STA myHealth

+skipHurt

(also available: https://drive.google.com/file/d/1WY8sgAGjeLGp9rqrYqB7b3LW6Ejge8EK/view?usp=sharing )

END OF PART 1...
Very good. my game was made in 4.1. Does it work?
 

Peter Schmitz

Active member
Instead of warping to an all red screen, then warping again, why not change the sprite palletes to all black and the tile pallettes to all red, then warp after? (thats how zelda 2 did it)
interesting approach. How would someone do that? And can you also just change the sprite color of your player and no monster objects?
 

SciNEStist

Well-known member
anything sharing the same subpalette as your player would change, but you can change the subpalette one at a time, so if only the player is using the first subpalette and thats all you change, the enemies will stay the same.

background palette can be changed with "LoadBackgroundPalettes"

sprite palettes can be changed with "LoadObjectSubPalettes"

keep in mind that next time a fresh screen is loaded, all those palettes will default back to the screen settings. To prevent this, you will need to alter the doloadscreen script I believe.
 

NightMusic

Member
@dale_coop I was trying to make it draw sprite to the screen when you press a button. I have the gameobjecttiles with the numbers and everything there
I dont understand why it wont draw it to the screen.
When I createobject onscreen it works, but i have trouble destroying the object to replace it with another object (number of continues)
when I DestroyObject it destroys the player... when I try to store the object created in a variable or something then recall the variable to destroy it still destroys the player... please help me I made a video and have my scripts included...

View: https://youtu.be/0qgqaorhYy4


scripts : https://drive.google.com/drive/folders/1nQ2l4f198tWQif43cF2lz35yvhIMN6qI?usp=sharing
 

dale_coop

Moderator
Staff member
You can't "draw a sprite" on a button press. You can create an object or you can set a user variable to a certain value and check that variable in a hud predraw script (for example) and draw a sprite if that variable has the value expected.

Also, if you use the CreateObject macro in a AI action or tile script, ... make sure to use TXA PHA / PLA TAX around it to prevent the X register corruption.
Like
Code:
TXA
PHA
    CreateObject ...
PLA
TAX
 
Top Bottom