(4.5.9) Character Selection Screen

NightMusic

Member
* This method uses only choosing between two characters on the screen. It is fairly basic and has much room for improvement. *



1. open extraScreenLoad (where your screen flags are located)
If you followed my tutorial for an overworld map you'll notice a gamestate check (around line 72 or so)
Copy that part of the code until +afterCheck (line 137 or so)

Code :

Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    LDA gameState
    CMP #3                ;; #3 or #$03 Is this OverWorld Map ;;
    BEQ canSwitchPlayer             ;; this is what happens when you're on the overworld ;;
        JMP doneSwitchingPlayer        ;; this is normal script stuff ;;

canSwitchPlayer:
    TXA
    PHA
    LDX player1_object
        LDA Object_x_hi,x        ;; the current horizontal position
        ; CLC
        ; ADC #$04
        STA tempA
        LDA Object_y_hi,x        ;; the current vertical position
        ; CLC
        ; ADC #$04
        STA tempB
        LDA Object_direction,x    ;; the current facing and movements
        ; AND #%00000111
        STA tempC
     
        ;; now, depending of the current object used by the player:
        ;; we can switch to the new object, or switch back the normal one
 
        DestroyObject                            ;; we destroy the current object
                    ;;;       OBJECT NUMBER   ;;;  #$0F For object 15
                    ;;;                \/          ;;;
        CreateObject tempA, tempB, #$0F, #$00    ;; and create the new one
        TXA
        STA player1_object                        ;; store that new created object in the Player 1 var
        STA camObject
        LDA tempC                                ;; set back the player directions
        STA Object_direction,x
    PLA
    TAX

        JMP +afterCheck
doneSwitchingPlayer:

    TXA
    PHA
    LDX player1_object
        LDA Object_x_hi,x        ;; the current horizontal position
        ; CLC
        ; ADC #$04
        STA tempA
        LDA Object_y_hi,x        ;; the current vertical position
        ; CLC
        ; ADC #$04
        STA tempB
        LDA Object_direction,x    ;; the current facing and movements
        ; AND #%00000111
        STA tempC
   
        DestroyObject                            ;; we destroy the current object
        CreateObject tempA, tempB, #$00, #$00    ;; and create the new one
        TXA
        STA player1_object                        ;; store that new created object in the Player 1 var
        STA camObject
        LDA tempC                                ;; set back the player directions
        STA Object_direction,x
    PLA
    TAX
  
+afterCheck

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

create a variable .....

User Variable : charSelect

0 - main
1 - alternative character

------------------------------------------
Selection Inputs :

startGame.asm

THIS IS THE CURRENT START GAME SCRIPT :


Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; SELECTION  MODE :
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; curSelection is 0 (normal) or curSelection is 1 (hard):
    LDA curSelection
    CMP #$01
    BNE +
    ;; Start in HARD mode:
    LDA #$01
    STA myLives
    JMP ++
    +
    ;; ELSE:
    ;; Start in NORMAL mode :
    ;LDA #$03        ;; commented out, here, in order to use the value specified in the NESMaker tool itself
    ;STA myLives    ;; commented out, here, in order to use the value specified in the NESMaker tool itself
    ++

LDA screenUpdateByte
ORA #%00000100
STA screenUpdateByte

    LDA warpToMap

    STA warpMap
  
    LDA warpToScreen
    STA currentNametable
  
    LDX player1_object
    STA Object_screen,x
  
    LDA #$01
    STA screenTransitionType ;; is of warp type

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

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



SINCE WE ARENT HAVING ANY OTHER OPTIONS , WE DONT NEED TO CHANGE MUCH...
We can still have this AND do a character select screen OR We would edit this part of the script
WE ARE WARPING TO THE CHARACTER SELECT SCREEN THEN increasing a VARIABLE TO SELECT THE CHARACTER.

1. normal whatever start screen
(If you want ot edit this right now , you can but your char select would be on the title screen)
2. warps/start to your charSelect screen
3. that screen will have two character portraits or sprites side by side...
a. you select the sprite with the similar to start screen but it moves left and right.
b. this is only one screen so we don't need to add a variable for cursor location/we can just put it in manually
c. the variable charSelect can be used to move the cursor but you would have to write a lot more code.
d. because we are doing two selections not 3 or 4 different characters we will just use the gamestate
We will use Gamestate 4

Code:
  LDA gameState
    CMP #4                ;; #4 or #$04 Is this CharSelect screen? ;;


View: https://youtu.be/w7jaTx-aCsc




THIS IS MY CURRENT SCRIPT AFTER EDITING IT:

Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

LDA gameState  
    CMP #$01                  ;; GAME STATE FOR START SCREEN ;;
    BNE +checkCharScreen    ;; check if on character select screen ;;
        JMP +doSelector

+checkCharScreen

    LDA gameState
    CMP #4                ;; #4 or #$04 Is this Character Select? ;;
    BEQ +isCharSelectScreen
        JMP +notStartOrSelect
+isCharSelectScreen

    LDA #100
    STA temp1
    LDA #60
    STA temp2
    LDX #$00
 
startScreenSelectorLoop2:
    CPX curSelection
    BCS +drawSprite
    LDA temp1
    CLC
    ADC #0              
    STA temp1
    LDA temp2
    CLC
    ADC #120              
    STA temp2
    INX
    JMP startScreenSelectorLoop2
+drawSprite:
    DrawSprite temp2, temp1, #STARTSCREEN_CURSOR_TILE, #%00000000, #$00    ;; replace #STARTSCREEN_CURSOR_TILE with #you want for your tile ;;
 
    JMP +notStartOrSelect        ;; it needs to jump over the other position at least ;;
  
+doSelector:
  
    LDA #SELECTION_POS_Y
    STA temp1
    LDA #SELECTION_POS_X
    STA temp2
    LDX #$00
 
startScreenSelectorLoop:
    CPX curSelection
    BCS +drawSprite
    LDA temp1
    CLC
    ADC #SELECTION_STEP_Y
    STA temp1
    LDA temp2
    CLC
    ADC #SELECTION_STEP_X
    STA temp2
    INX
    JMP startScreenSelectorLoop
+drawSprite:
    DrawSprite temp2, temp1, #STARTSCREEN_CURSOR_TILE, #%00000000, #$00
 
+endCheckingStartScreenSelector:
+notStartOrSelect
    ;;; END OF SCRIPT UNLESS YOU ADD MORE PREDRAWS ;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


YOU CAN TEST THIS AND SEE IT MANUALLY PLACED THE TILE AND IT MOVES RIGHT THEN RESETS BACK
it's using curSelect currently so its max number is also the max that is set to.


NEXT :

under the line ( endCheckingSelection: )


LDA gameState
CMP #4 ;; Is this Character Select Screen? ;;
BNE +notSelect
LDA charSelect
BNE +
INC charSelect
JMP +notSelect
+
DEC charSelect
+notSelect

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;[/CODE]


Though...

STILL KEEP THE LINES :


Code:
LDX tempx
    RTS


at the end of the script.


I added in POST SCREEN LOAD SOME GAME STATE CHECKS
SO NOW check your post screenload script...
mine looks like this :
Code:
    LDA gameState
    CMP #$01
    BNE +
        JMP ++
+
LoadObjectSubPalettes charSelect, #$00

;; arg0 = index of palette in bank 16
;; arg1 = starting point of sub palette, 0,4,8,12
;; Max Helsing ~ #$00
;; Anne Helsing ~ #$01
++
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    LDA #$00
    STA curSelection
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    LDA gameState
    BEQ +isMainGameCheck
        JMP +isOther

+isMainGameCheck

    LDA charSelect
    CMP #1                ;; #4 or #$04 Is this Character Select? ;;
    BEQ +isAnne
        JMP +isMax

+isAnne

   TXA
    PHA
    LDX player1_object
        LDA Object_x_hi,x        ;; the current horizontal position
        ; CLC
        ; ADC #$04
        STA tempA
        LDA Object_y_hi,x        ;; the current vertical position
        ; CLC
        ; ADC #$04
        STA tempB
        LDA Object_direction,x    ;; the current facing and movements
        ; AND #%00000111
        STA tempC
     
        ;; now, depending of the current object used by the player:
        ;; we can switch to the new object, or switch back the normal one
 
        DestroyObject                            ;; we destroy the current object
                    ;;;       OBJECT NUMBER   ;;;  #$0F For object 15
                    ;;;                \/          ;;;
        CreateObject tempA, tempB, #$01, #$00    ;; and create the new one
        TXA
        STA player1_object                        ;; store that new created object in the Player 1 var
        STA camObject
        LDA tempC                                ;; set back the player directions
        STA Object_direction,x
    PLA
    TAX

+isMax
+isOther


;;;;;;;;;;;;;;;
 
Last edited:

NightMusic

Member
View: https://youtu.be/0wGPWzjMHn4


NEXT EDIT YOUR INPUTS
----------------------------
All Inputs need to load the Player1object into X
Once that is done, things should work properly.
(* Projectile_ammo and possibly ladder_up ladder_down has this in it by default.)

LDX player1_object ;; get player1_object load into x ;;


After this make sure all your inputs read and there aren't duplicates...

After all inputs have the extra line and are working you must now test your alt player.

;;;;;;;;;;;;;;;;;;;;;;

If your overworld map isnt detecting the alt you must add it to the script.
if following my tutorials it shoudl be in extraScreenLoad around line 72 or so...

I personally for my own safety put my added lines of code after ( canSwitchPlayer: )

Code:

Code:
;; Checks charSelect variable 0 is Max and 1 is Anne ;;

    LDA charSelect
    BNE +isAnneHelsing
        JMP +isMaxHelsing

+isAnneHelsing   
    TXA
    PHA
    LDX player1_object
        LDA Object_x_hi,x        ;; the current horizontal position
        ; CLC
        ; ADC #$04
        STA tempA
        LDA Object_y_hi,x        ;; the current vertical position
        ; CLC
        ; ADC #$04
        STA tempB
        LDA Object_direction,x    ;; the current facing and movements
        ; AND #%00000111
        STA tempC
      
        ;; now, depending of the current object used by the player:
        ;; we can switch to the new object, or switch back the normal one
 
        DestroyObject                            ;; we destroy the current object
                    ;;;       OBJECT NUMBER   ;;;  #$0E For object 14
                    ;;;                \/          ;;;
        CreateObject tempA, tempB, #$0E, #$00    ;; and create the new one
        TXA
        STA player1_object                        ;; store that new created object in the Player 1 var
        STA camObject
        LDA tempC                                ;; set back the player directions
        STA Object_direction,x
    PLA
    TAX

        JMP +afterCheck

+isMaxHelsing
;;;;;;;;;;;;;;;;;;;;



AFTER THIS CODE IS WHERE THE REST OF THE CODE SHOULD BE CONTINUING...
(it looks almost identical.. I rewrote a lot of code you probably could shorten this yourself.)


I think its complete... we can customize the alternative (alt) player in some future tutorials.
 
Last edited:
Top Bottom