Continue from Game Over script and How to add credits

TolerantX

Active member
Hey there NESmaker users!
I wrote a script, and with some "help from my friends" it was able to "come together" :)
(*apologies for The Beatles puns)
Below I have two input scripts, both relatively simple and written to explain things clearly (*I hope*)

FIRST: You need to know a few things: This script uses variables such as myLives, (Optional) my Score, and (Optional: see below) myContinues

SECOND: YOU NEED A GAME OVER SCREEN http://nesmakers.com/viewtopic.php?f=36&t=2137&p=26172#p26174
(make one from here or your own way)

PLEASE! MAKE SURE THEY ARE DEFINED! PRETTY PLEASE!

I have commented out the parts of the script pertaining to SCORE and CONTINUES to enable them you can uncomment them or download them already edited (your choice)
You want to assign this script below in inputs to your GAME OVER SCREEN STATE or lacking that, your WIN screen state

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 #$03
STA myLives

;;;; 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 6 DIGITS;;;;


;;;; THE PART BELOW IS EDITED FOR IF YOU USE A VARIABLE FOR CONTINUES/CREDITS ;;;;

;LDA myContinues
;CMP #$00
;BNE +DoContinue
   ; JMP +EndofScript


;+DoContinue:

;DEC myContinues

;;;; THE PART ABOVE IS EDITED FOR IF YOU USE A VARIABLE FOR CONTINUES/CREDITS ;;;;


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 gameHandler
    ORA #%10000000
    STA gameHandler ;; this will set the next game loop to update the screen.
    LDA myMaxHealth
    STA myHealth


+EndofScript:

   RTS

The script below is an input for the Start Screen (or any screen you want to add credits with a button press) This is only needed IF you want LIMITED CONTINUES.
I use press SELECT button on START SCREEN (*I commented out the SFX but you can add them back in*)

Code:
;; simple script adds to a variable myContinues and plays a sound ;;
;; someone else may add an indicator on screen, but for now a simple script ;;

    INC myContinues
    ;PlaySound #SND_GETCOIN
    
RTS


those were the two simple scripts, below is the uncommented version of CONTINUE WITH SCORE RESET AND LIMITED CONTINUES...
LIMITED CONTINUES AND SCORE RESET:

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 #$03
STA myLives

;;;; 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 6 DIGITS;;;;


;;;; THE PART BELOW IS EDITED FOR IF YOU USE A VARIABLE FOR CONTINUES/CREDITS ;;;;

LDA myContinues
CMP #$00
BNE +DoContinue
    JMP +EndofScript


+DoContinue:

DEC myContinues

;;;; THE PART ABOVE IS EDITED FOR IF YOU USE A VARIABLE FOR CONTINUES/CREDITS ;;;;


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 gameHandler
    ORA #%10000000
    STA gameHandler ;; this will set the next game loop to update the screen.
    LDA myMaxHealth
    STA myHealth


+EndofScript:

   RTS


Thank you to Drexegar and ChronosV2 for all your help making this work gentlemen.
I hope this helps some of you out :)
 

mouse spirit

Well-known member
This is great! I dont have livs or continues in my current project, but when i do have em i'll try this for sure!
I like how its adjustable just by uncommenting.
 

vanderblade

Active member
Thanks for this. I was trying to think of a way to build off of this for a particular way of respawning the player. So, I'm making a beatemup with five stages. When players die on a stage and choose to continue, I would like them to have to start at the beginning of that respective stage. But how does one do this?

One way I was thinking was using screentypes. If I label all stage 1 screens with screentype 1, for instance, I can institute some kind of check in a modified version of this script to check for screen type and then respawn players in one of five screens (depending on if they died on stage 1, 2, 3, 4, or 5).

Does this sound like a feasible plan?

What's the code to check against screentype? And, just off the top of my head, I would probably need to store the screentype of the screen players died on (in the playerhurt script) in a variable in order to recall it on the Game Over screen, right? (Sorry, programming just doesn't come naturally to me).

And can anybody break down the arguments below so I can make 5 unique warps to the start of each of my five levels?

WarpToScreen warpToMap, warpToScreen, #$01
 

vanderblade

Active member
Could somebody explain how I can fix the code below?

I'm trying to have a continue code that sends players back to a specific level intro screen based on the level they died on. I have all my level one screens labeled with a screenType of 1. All of my level two screens have a screenType of 2. Etc.

Based on my logic above, I have a variable called myDeathScreen. When players lose all their lives, the game does an LDA screenType and STA myDeathScreen. If I'm right, this stores the number of the screenType to the variable myDeathScreen, right?

Okay, the next thing I'm trying to do is make the below continue code do a series of compare checks on the myDeathScreen variable and, based on the number that comes up, players get sent back to either the start of level 1, 2, 3, 4, or 5.

The problem I'm having is the below works if I comment out all the checks beyond level 2. If I do that, if I lose all my lives in level 1 somewhere, I continue at the level one intro screen. Same for level 2. But once I uncomment out the rest of the checks, the code seems to default to the last available warp code.

*Note: I'm only including the part of my continue script that is relevant to the above issue.

Code:
LDA myDeathScreen
    CMP #$01
    BEQ +WarpLvL1
    +checkIfLevel2
        
+checkIfLevel2
LDA myDeathScreen
CMP #$02
BEQ +WarpLvL2
+checkIfLevel3

+WarpLvL1
WarpToScreen warpToMap, #$D0, #$01
+FinishContinueStuff
    
+checkIfLevel3
LDA myDeathScreen
CMP #$03
BEQ +WarpLvL3
+checkIfLevel4
        
+WarpLvL2
WarpToScreen warpToMap, #$D4, #$01
+FinishContinueStuff
    
+checkIfLevel4
LDA myDeathScreen
CMP #$04
BEQ +WarpLvL4
+checkIfLevel5

+WarpLvL3
WarpToScreen warpToMap, #$D5, #$01
+FinishContinueStuff

+checkIfLevel5
        LDA myDeathScreen
        CMP #$05
        BEQ +WarpLvL5
        +EndofScript
        
+WarpLvL4
WarpToScreen warpToMap, #$D6, #$01
+FinishContinueStuff
    
+WarpLvL5
WarpToScreen warpToMap, #$D8, #$01
+FinishContinueStuff
    
+FinishContinueStuff   
    LDA gameHandler
    ORA #%10000000
    STA gameHandler ;; this will set the next game loop to update the screen.
    LDA myMaxHealth
    STA myHealth
    StopMoving player1_object, #$FF, #$00
    ChangeFacingDirection player1_object, #FACE_RIGHT
    RTS
    
+EndofScript
RTS

I know the logic is sound, but my asm skills are shit (see above), so if anybody can tell me how to fix the above, it would be a godsend. Thanks!
 

CutterCross

Active member
The big problem here is that if one of your myDeathScreen checks doesn't branch, you're not jumping AROUND the code that sets the warp location to the next screen after the frame finishes.

Let's walk through this. So let's say you died on Level 3. It's going to check if myDeathScreen corresponds to Level 1. It doesn't, so it doesn't branch.
It continues into the Level 2 check. myDeathScreen isn't 2, so it also doesn't branch.
It IMMEDIATELY hits the WarpToScreen macro for Level 1, because you didn't jump around it after the last branch check failed. The screen to warp to when the frame finishes is currently Level 1.
It continues into the Level 3 check. It IS Level 3, so it branches to the +WarpLvL3 label, and runs the WarpToScreen macro for Level 3. The screen to warp to when the frame finishes is currently Level 3.
It then checks if its Level 5, because you didn't jump around this code after finishing the WarpToScreen macro for Level 3. It isn't Level 5, so it doesn't branch.
It then immediately hits the WarpToScreen macro for Level 4, because you didn't jump around it after finishing the check for Level 5. The screen to warp to when the frame finishes is currently Level 4.
It then immediately hits the WarpToScreen macro for Level 5, because you didn't jump around it after finishing the WarpToScreen macro for Level 4. The screen to warp to when the frame finishes is currently Level 5.
The stuff under +FinishContinueStuff executes and the subroutine ends.

So basically it comes down to you forgetting to actually jump to these labels you've set up, and instead just made duplicate labels.
 
Last edited:

CutterCross

Active member
This whole setup is largely inefficient and redundant either way. You don't need to create a separate myDeathScreen variable because screenType is still going to hold the same value until the next screen load. [Unless you've deliberately overwritten it with something custom for whatever reason.]

Instead of screenType holding the abstract "level number", you could instead set it to the actual screen coordinate of the first screen in that level, and simply use that as the WarpToScreen argument for the screen number to warp to. [And whatever other screenType checking you do in your game can easily be reworked with this in mind.] This way you don't have to do a bunch of conditional checking for what screen to warp to.

Code:
;;;; Untested:
;;;; Warp to last checkpoint screen based on screenType

WarpToScreen warpToMap, screenType, #$01

    ;LDA gameHandler
    ;ORA #%10000000
    ;STA gameHandler    ;; The WarpToScreen macro already handles this, so it's unnecessary.
    LDA myMaxHealth
    STA myHealth
    StopMoving player1_object, #$FF
    ChangeFacingDirection player1_object, #FACE_RIGHT
    RTS
 
Last edited:

vanderblade

Active member
Thanks, Cutter. I was overthinking it in that code above. But I guess I have to make something clear and explain why I am even trying to do it this way. I use regular checkpoints throughout my levels so when players die (but still have lives) they respawn at the latest checkpoint.

What I am trying to do is have code that executes on a Game Over / Continue screen. The screenType will be updated for that screen (right?), which is why I have to store the screenType of the death screen as a variable. When players lose all their lives and they choose to continue at the continue screen, I want them to instead start at the beginning of whatever stage they died on.

EDIT: Nothing makes me feel dumber than trying to write original code on my own. In any case, thanks to Cutter for reminding me about the JMP command above, I finally landed on code that does what I want. I know this might sound convoluted to some of you, but it's a workaround so I can use checkpoints within levels but also "punish" players for having to continue by sending to the beginning of each level. Thanks again, Cutter.

Code:
LDA myDeathScreen
CMP #$01
BNE +checkIfLevel2
    LDA myMaxHealth
    STA myHealth
    WarpToScreen warpToMap, #$D0, #$01 ;; screen 209/204
    JMP +FinishContinueStuff

+checkIfLevel2
LDA myDeathScreen
CMP #$02
BNE +checkIfLevel3
    WarpToScreen warpToMap, #$D4, #$01 ;; screen 212/D4
    JMP +FinishContinueStuff

+checkIfLevel3
LDA myDeathScreen
CMP #$03
BNE +checkIfLevel4
    WarpToScreen warpToMap, #$D5, #$01 ;; screen 213
    JMP +FinishContinueStuff

+checkIfLevel4
LDA myDeathScreen
CMP #$04
BNE +checkIfLevel5
    WarpToScreen warpToMap, #$D6, #$01 ;; screen 214
    JMP +FinishContinueStuff
    
+checkIfLevel5
;LDA myDeathScreen ;; doesn't need to check, if not the above, must be level 5
;CMP $05
;BNE +EndofScript
    WarpToScreen warpToMap, #$D8, #$01 ;; screen 216
    JMP +FinishContinueStuff
    
+FinishContinueStuff   
    LDA gameHandler
    ORA #%10000000
    STA gameHandler ;; this will set the next game loop to update the screen.
    LDA myMaxHealth
    STA myHealth
    StopMoving player1_object, #$FF, #$00
    ChangeFacingDirection player1_object, #FACE_RIGHT
    RTS

+EndofScript:

RTS
 
Last edited:

CutterCross

Active member
Thanks, Cutter. I was overthinking it in that code above. But I guess I have to make something clear and explain why I am even trying to do it this way. I use regular checkpoints throughout my levels so when players die (but still have lives) they respawn at the latest checkpoint.

What I am trying to do is have code that executes on a Game Over / Continue screen. The screenType will be updated for that screen (right?), which is why I have to store the screenType of the death screen as a variable. When players lose all their lives and they choose to continue at the continue screen, I want them to instead start at the beginning of whatever stage they died on.

EDIT: Nothing makes me feel dumber than trying to write original code on my own. In any case, thanks to Cutter for reminding me about the JMP command above, I finally landed on code that does what I want. I know this might sound convoluted to some of you, but it's a workaround so I can use checkpoints within levels but also "punish" players for having to continue by sending to the beginning of each level. Thanks again, Cutter.
Since you've clarified that you're going to a specific death screen before warping back, then yes it makes sense to store screenType into a separate variable beforehand. But again, a much simpler (and far more efficient) solution would be to use the screenType value as the WarpToScreen argument for what screen to warp to. You don't seem to use it aside from an abstract value to compare against, so there wouldn't be any real sacrifice to use the actual level start screen number as the screenType. Instead of using screenType itself as the argument, use myDeathScreen.

Code:
;;;; Untested:
;;;; Warp to last checkpoint screen based on myDeathScreen / screenType

WarpToScreen warpToMap, myDeathScreen, #$01

    ;LDA gameHandler
    ;ORA #%10000000
    ;STA gameHandler    ;; The WarpToScreen macro already handles this, so it's unnecessary.
    LDA myMaxHealth
    STA myHealth
    StopMoving player1_object, #$FF
    ChangeFacingDirection player1_object, #FACE_RIGHT
    RTS
 

TolerantX

Active member
 
Top Bottom