Game Over text when health is 0 (NESmaker 4.5.9)

baardbi

Well-known member
game_014.png

This will write the text "GAME OVER" in the middle of the screen when myHealth is 0. It is important to understand that this does nothing else. It just writes that text on the screen. So you need to include other mechanics to warp to the start screen or whatever you want to happen when it's game over.

I have tested this in the MetroVania module, but it should at least work perfectly well in the platformer module as well.

PS! Backup your asm files before you make changes to them.

0.
You need to have the letters G A M E O V E R as sprite tiles in your gameObjects graphics file. You also need to make a note of what tile each letter is in, So if for example the letter "G" was in the first tile of the game objects, then that's tile number 0. If the letter A is in the second sprite tile in gameObjects, then that's sprite tile 1, and so on.

1.
Put this at the bottom of the file ExtraTables_PlatformerBase.asm :

gameOverText:
.db 10 ; G
.db 11 ; A
.db 12 ; M
.db 13 ; E
.db 0 ; END TEXT: "GAME"
.db 14 ; O
.db 15 ; V
.db 13 ; E
.db 47 ; R
.db 0 ; END TEXT: "OVER"
Make sure that the numbers after .db correspond with the number of the sprite tiles for each letter (in the gameObjects graphics file).

2.
Put this in the file doSpritePreDraw.asm right below .include SCR_DRAW_SPRITE_HUD :

;;;;;;;;;;;;;;;;;;;;;;;; GAME OVER TEXT ;;;;;;;;;;;;;;;;;;;;;;;;

GAME_OVER_TEXT_X = 112
GAME_OVER_TEXT_Y = 111

LDA gameState ;;;; Only do this check on gameplay screens
BEQ +checkIfGameOver
JMP +doneGameOver
+checkIfGameOver:

LDA myHealth ;;;; If health is zero we draw the Game Over text
BEQ +gameOver
JMP +doneGameOver
+gameOver:

LDA #GAME_OVER_TEXT_X
STA tempA
LDA #GAME_OVER_TEXT_Y
STA tempB

LDY #0

gameOverTextLoop1:
LDA gameOverText,y
BEQ +doneTextGame ;; Done writing text: "GAME"
STA temp
DrawSprite tempA, tempB, temp, #%00000001
LDA tempA
CLC
ADC #8
STA tempA
INY
JMP gameOverTextLoop1
+doneTextGame:

INY ; Go to next text character

; Set X position back to start for the next line of text
LDA #GAME_OVER_TEXT_X
STA tempA

;; One line down (+ 1 pixel offset)
LDA tempB
CLC
ADC #9
STA tempB

gameOverTextLoop2:
LDA gameOverText,y
BEQ +doneTextOver ;; Done writing text: "OVER"
STA temp
DrawSprite tempA, tempB, temp, #%00000001
LDA tempA
CLC
ADC #8
STA tempA
INY
JMP gameOverTextLoop2
+doneTextOver:

+doneGameOver:

3.
Make sure you save the files and test your game. You should now see the text "GAME OVER" in the middle of the screen when myHealth is 0.

That's it!
 

baardbi

Well-known member
Will this work in the Maze module?
I haven't worked with the Maze module in a long time. I'm guessing yes, but I can't guarantee it. You could try. Just remember two things; this is based on myHealth (not myLives) and this script does not warp anywhere or anything like that. So there needs to be some additional code to handle that stuff.
 

gabeswarr

Member
This doesn't seem to work for me at all. Nothing happens at all. Weird.

How does it determine that the game is over? Shouldn't it read Game Over when myLives are at zero instead of myHealth?
 

baardbi

Well-known member
This doesn't seem to work for me at all. Nothing happens at all. Weird.

How does it determine that the game is over? Shouldn't it read Game Over when myLives are at zero instead of myHealth?
I don't know what module you're using, but this tutorial is not set up for handling myLives. You will have to adapt the code for that. Like I said in the beginning of this tutorial, this does not do anything else than write the text. So make sure your hurtPlayer script is compatible with this. If for example you're using the arcade platform module, then it resets the game the moment myLives is zero.
 

gabeswarr

Member
So, I finally got this to work, but now my normal sprite hud is hidden through the entire game except when Game Over is being displayed. Can someone please help?

Thanks so much!

Here's my doDrawSpriteHud_metroidvania.asm

Code:
CPX player1_object  ;; is it the player 1 object?
BNE +notPlayer  ;; not the player
  LDA ScreenFlags00
  AND #%01000000 ;Hide player
  BEQ +dontHidePlayer
    RTS
  +dontHidePlayer:
+notPlayer


;;; start screen;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    LDA gameState
    CMP #$00
    BNE +startscreen
    JMP +maingame
    +startscreen
    
    ;;;display lives
    
    LDA myLives
    CLC
    ADC #$60
    ;; now we have the number 40 + how many prizes we have.
    ;; so the resulting graphic will be 0-9.
    STA temp
    DrawSprite #116, #180, temp, #$01 ;x,y
    
    ;;;display butterflies
    
    LDA myButterflies
    CLC
    ADC #$60
    ;; now we have the number 40 + how many prizes we have.
    ;; so the resulting graphic will be 0-9.
    STA temp
    DrawSprite #116, #197, temp, #$01
    
    RTS

;;;hud during game;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


    +maingame

DrawSpriteHud #16, #16, #$78, #$05, #$76, myHealth, #%00000001  ;;;; this draws health
;;;;display gnats

    DrawSprite #16, #26, #$74, #%00000001 ;; draws the gnat
    DrawSprite #24, #26, #$6A, #$01 ;; draws the x 8 pixels to the right of it.
    
    LDA myPrizes
    CLC
    ADC #$60
    ;; now we have the number 40 + how many prizes we have.
    ;; so the resulting graphic will be 0-9.
    STA temp
    DrawSprite #32, #26, temp, #$01

    RTS
 

dale_coop

Moderator
Staff member
Some mistakes in that script.
First.... that code :
Code:
CPX player1_object  ;; is it the player 1 object?
BNE +notPlayer  ;; not the player
  LDA ScreenFlags00
  AND #%01000000 ;Hide player
  BEQ +dontHidePlayer
    RTS
  +dontHidePlayer:
+notPlayer
Should be in the "Handle Drawning Sprite" script (not the Handle Drawing Sprite Hud one).

Then, if you want to have different "section" in your sprite hud script for each game state (start screen, main game, game over, ...), it should be something like:
Code:
    LDA gameState  
    CMP #$00
    BNE +skip
        JMP +maingame
    +skip:
    CMP #$01
    BNE +skip
        JMP +startscreen
    +skip:
    ;; CMP #$02
    ;; BNE +skip
    ;;    JMP +winscreen
    ;; +skip:

    ;; or you can something like

    ;; LDA currentNametable  ;; if the current screen
    ;; CMP #$08  ;; is the Y=0, X=8 (if that one is the game overs screen)
    ;; BNE +skip
    ;;    JMP +gameoverscreen
    ;; +skip:
   
    ;; etc

    RTS

How do you identify your Game Over screen? Does it has a different game state ? or you just identify it by it's x,y coords?
 

gabeswarr

Member
Oh! Thanks! That makes a lot more sense. I removed the first part of the script from doDrawSpriteHud and added it to doDrawSprite_PlatformBase.

Unfortunately, there's no change. I still have no Sprite Hud when I incorporate the Game Over. I abandoned this method. I just built out a branch in the Timer End Script for my dead state and for my "instadeath" tile.

I just need to know how to get to the game over screen (5,2), this seems to take me somewhere else: WarpToScreen #$00, #$52, #$01

Also, is there any tutorial that mentions how to write script that utilizes the Game Timer? I couldn't find any.

Thanks!
 

dale_coop

Moderator
Staff member
I am not sure to follow what is not working for you.
Can you re explain precisely (illustrated maybe) your current remaining issue?

Your HUD is not nor working on your Game Over screen (a dedicated screen, when no more lives, the game warped to that screen, like in a lot of games) ?
Or you want to write "game over" on the screen when the player dies (like the subject of this topic)?



About the WARP:
If your game over screen is X=5 and Y=2, then the warp should be
Code:
WarpToScreen #$00, #$25, #$01
(the rule is #$YX fro the screen id... each value in hex)
 
Last edited:

gabeswarr

Member
I've abandoned the idea of using the Game Over. I'm moving on with my life and just trying to get to my game over screen.

Now, I have an even crazier problem. When I reach 0 lives it just restarts despite this script in the TimerEndScripts:

Code:
goToContinue_action:

;;;;game over?;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

LDA myLives 
    CMP #$00
    BNE +skip
        JMP +gameover
    +skip:
    
;;;continue;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    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

    ; Set the player's starting position to the middle of the screen
    LDA currentNametable ; Get the current screen's nametable index
    ASL ; Multiply by 2 to convert it to tile coordinates
    STA tempX ; Store the result in tempX
    LDA tempX ; Load tempX into A
    CLC ; Clear carry flag
    ADC #$08 ; Add 8 (half of the screen width) to get the center X position
    TAX ; Store the result in X
    
    LDA #$06 ; Assuming the screen height is 12 tiles, set the Y position to the center (6)
    STA Object_y_hi,x ; Set the player's Y position high byte
    LDA #$00 ; Set the player's Y position low byte to 0
    STA Object_y_lo,x
    
    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
    
;;;game over ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
 +gameover
 
    WarpToScreen #$00, #$52, #$01
    
    RTS

I don't know if it matters. but this is where I'm trying to go (5,2):

Screenshot 2023-07-04 at 3.57.04 PM.png

I just don't get it...?
 

Attachments

  • Screenshot 2023-07-04 at 3.57.04 PM.png
    Screenshot 2023-07-04 at 3.57.04 PM.png
    29.4 KB · Views: 0

dale_coop

Moderator
Staff member
Maybe your myLives variable is negative ? hmmm

Instead of:
Code:
    LDA myLives
    CMP #$00
    BNE +skip
        JMP +gameover
    +skip:

You could try:
Code:
    LDA myLives
    BPL +skip
        JMP +gameover
    +skip:
    BNE +skip
        JMP +gameover
    +skip:
 

gabeswarr

Member
Yeah, there is no change. It just resets. This makes no sense to me. I guess I can never get to my game over screen?!
 

gabeswarr

Member
Ok, so I finally got this working! The thing that was throwing everything off was the fact that I had all the first two rows enabled as detailed screens. I still have no idea how to find locations of those screens or any of the screens in the following rows. So, after moving them down to the bottom, everything works great.

For anyone who are new to NESmaker (like myself) trying to figure out out to warp to a screen the code should look like this:

Code:
WarpToScreen #$00, #$00, #$01

I highly recommend watching this part of baardbi tutorial:

View: https://youtu.be/MEc0s4r2jVg?t=3777


Hope this helps someone.
 

dale_coop

Moderator
Staff member
Also to find the screen value, it's quite easy.
Move the mouse over the screen, it will display the X and Y coords of the screen, the screen value is #$YX (in hex).
For example,
if X=5, Y=2, the screen value is #$25
if X=2, Y=12, the screen value is #$C2 ("C" is "12", in hex)
 
Top Bottom