So I've started to work with gamestates and indirect jumping. I have 3 game state loops and 3 game state NMI loops right now.
The game starts out at the title screen, with a cursor that moves to either "START” or “CONTINUE”. When START is selected, the player is then free to move around in all four directions. When the player presses start, the game goes into pause mode and stays there until start is pressed again, from with the game goes back to the play state.
That all works, except I don't understand how things are initialized, like adding a new background and changing sprites once the game is started. (Right now once "START" is selected, the cursor sprite just moves around like the player) These obviously only need to happen once, and not be in the main loop. But I don't know where they'd go.
Here's an excerpt what I have right now.
(Mod edit: koitsu: fixed typo in Subject (Gamesates --> Gamestates))
The game starts out at the title screen, with a cursor that moves to either "START” or “CONTINUE”. When START is selected, the player is then free to move around in all four directions. When the player presses start, the game goes into pause mode and stays there until start is pressed again, from with the game goes back to the play state.
That all works, except I don't understand how things are initialized, like adding a new background and changing sprites once the game is started. (Right now once "START" is selected, the cursor sprite just moves around like the player) These obviously only need to happen once, and not be in the main loop. But I don't know where they'd go.
Here's an excerpt what I have right now.
Code:
.rsset $0000
Main_Pointer .rs 2
NMI_Pointer .rs 2
.rsset $0400
GameState .rs 2
GameStateOld .rs 1
sleeping .rs 1
updating_background .rs 1
screen .rs 1 ;what metatile screen should be loaded
buttons .rs 1
buttons_old .rs 1
buttons_pressed .rs 1
sprite0RAM = $0200 ;later change to sprite1 when implementing sprite0 hit
TitleState = $00
PlayState = $01
PausedState = $02
; (Initialize tital screen, load palettes, load cursor sprite, etc.)
Main_Loop:
inc sleeping
.loop
lda sleeping
bne .loop
jsr SetUpController
jsr GameStateIndirect
lda GameState
cmp GameStateOld
beq .next
jsr UpdateGameState
.next
jmp Main_Loop
;(NMI is normal and just calls the NMI code for each game state)
GameStateIndirect:
jmp [Main_Pointer]
GameStateNMIIndirect:
jmp [NMI_Pointer]
GameStates:
.word Title, Play, Paused
GameStateNMIs:
.word TitleNMI, PlayNMI, PausedNMI
UpdateGameState:
lda GameState
sta GameStateOld
asl a
tax
lda GameStates,x
sta Main_Pointer
lda GameStates+1,x
sta Main_Pointer+1
lda GameStateNMIs,x
sta NMI_Pointer
lda GameStateNMIs+1,x
sta NMI_Pointer+1
rts
Title:
lda buttons_pressed
and #%00100000
beq .readselectdone
lda sprite0RAM
eor #%00010000 ;adds or subtracts 16 pixelds from the y-position, moves the cursor from "START" to "CONTINUE"
sta sprite0RAM
.readselectdone
lda buttons_pressed
and #%00010000
beq .readstartdone
lda sprite0RAM
cmp #$88
beq .start
;otherwise, load password code, which hasn't been programmed yet
jmp .readstartdone
.start
lda GameState
sta GameState+1
lda #PlayState
sta GameState
.readstartdone
rts
TitleNMI:
rts
Play:
jmp handle_input ;No need for a jsr returning to an rts
PlayNMI:
rts
Paused:
lda buttons_pressed
and #%00010000
beq .done
;unpause the game
lda GameState+1
sta GameState
.done
rts
PausedNMI:
rts
SetUpController:
; (basic controller reading scheme)
rts
handle_input:
ReadStart:
lda buttons_pressed
and #%00010000
beq ReadStartDone
lda GameState
sta GameState+1
lda #PausedState
sta GameState
ReadStartDone:
; .......
rts
Main_Pointer .rs 2
NMI_Pointer .rs 2
.rsset $0400
GameState .rs 2
GameStateOld .rs 1
sleeping .rs 1
updating_background .rs 1
screen .rs 1 ;what metatile screen should be loaded
buttons .rs 1
buttons_old .rs 1
buttons_pressed .rs 1
sprite0RAM = $0200 ;later change to sprite1 when implementing sprite0 hit
TitleState = $00
PlayState = $01
PausedState = $02
; (Initialize tital screen, load palettes, load cursor sprite, etc.)
Main_Loop:
inc sleeping
.loop
lda sleeping
bne .loop
jsr SetUpController
jsr GameStateIndirect
lda GameState
cmp GameStateOld
beq .next
jsr UpdateGameState
.next
jmp Main_Loop
;(NMI is normal and just calls the NMI code for each game state)
GameStateIndirect:
jmp [Main_Pointer]
GameStateNMIIndirect:
jmp [NMI_Pointer]
GameStates:
.word Title, Play, Paused
GameStateNMIs:
.word TitleNMI, PlayNMI, PausedNMI
UpdateGameState:
lda GameState
sta GameStateOld
asl a
tax
lda GameStates,x
sta Main_Pointer
lda GameStates+1,x
sta Main_Pointer+1
lda GameStateNMIs,x
sta NMI_Pointer
lda GameStateNMIs+1,x
sta NMI_Pointer+1
rts
Title:
lda buttons_pressed
and #%00100000
beq .readselectdone
lda sprite0RAM
eor #%00010000 ;adds or subtracts 16 pixelds from the y-position, moves the cursor from "START" to "CONTINUE"
sta sprite0RAM
.readselectdone
lda buttons_pressed
and #%00010000
beq .readstartdone
lda sprite0RAM
cmp #$88
beq .start
;otherwise, load password code, which hasn't been programmed yet
jmp .readstartdone
.start
lda GameState
sta GameState+1
lda #PlayState
sta GameState
.readstartdone
rts
TitleNMI:
rts
Play:
jmp handle_input ;No need for a jsr returning to an rts
PlayNMI:
rts
Paused:
lda buttons_pressed
and #%00010000
beq .done
;unpause the game
lda GameState+1
sta GameState
.done
rts
PausedNMI:
rts
SetUpController:
; (basic controller reading scheme)
rts
handle_input:
ReadStart:
lda buttons_pressed
and #%00010000
beq ReadStartDone
lda GameState
sta GameState+1
lda #PausedState
sta GameState
ReadStartDone:
; .......
rts
(Mod edit: koitsu: fixed typo in Subject (Gamesates --> Gamestates))