About:
maze game using zero-page variables for efficient memory access and execution speed. These variables include ROW, COL, DRAWN_ROW, MAZE_L, MAZE_H, PLAYER_L, PLAYER_H, TARGET_L, and TARGET_H. ROW and COL track the player's current position in the maze, while DRAWN_ROW counts the drawn rows on the screen. MAZE_L and MAZE_H point to where the maze is drawn, and PLAYER_L and PLAYER_H point to the player's position. TARGET_L and TARGET_H point to the target position the player aims to reach. Zero-page variables optimize memory usage and speed up access to critical data during execution, crucial for game performance. The code initializes the game, manages player movements, checks for collisions, and handles game completion. It uses ROM routines for screen initialization and displays instructions and completion messages. Maze data, help text, and completion messages are provided in the code. The game loop continuously updates the player's position, receives user input, checks for collisions, and displays appropriate messages upon game completion. By leveraging zero-page variables, the code enhances memory management and execution efficiency, essential for smooth gameplay in assembly-based maze games.
Code:
; zero-page variables
define NEW_ROW $20 ; current row
define NEW_COL $21 ; current column
define NEW_DRAWN_ROW $22 ; number of drawn rows
define NEW_MAZE_L $14 ; a pointer that points to where the maze will
define NEW_MAZE_H $15 ; be drawn
define NEW_PLAYER_L $10 ; a pointer that points to the player in the
; screen
define NEW_PLAYER_H $11
define NEW_TARGET_L $12 ; a pointer that points to the target position
define NEW_TARGET_H $13 ; where the player wants to proceed
; constants
define PATH $03 ; path color
define PLAYER $0e ; player color
define HEIGHT 7 ; height of the maze
define WIDTH 7 ; width of the maze
; ROM routine
define SCINIT $ff81 ; initialize/clear screen
jsr printHelp
jsr drawMaze
jsr gameInit
jsr gameLoop
printHelp: ldy #$00 ; print instructions on the screen
pHelpLoop: lda help,y
beq done
sta $f000,y
iny
bne pHelpLoop
gameInit: lda #$01 ; initialize ROW, COL to make the player
sta NEW_ROW ; starting at $0221 of the screen
sta NEW_COL
rts
gameLoop: jsr updatePosition
jsr getkey
jsr checkCollision
ldx #$00 ; clear out the key buffer
stx $ff
jmp gameLoop
updatePosition: ldy NEW_ROW ; load PLAYER pointer with ROW
lda table_low,y
sta NEW_PLAYER_L
lda table_high,y
sta NEW_PLAYER_H
ldy NEW_COL ; place the player at (POINTER + COL)
lda #PLAYER
sta (NEW_PLAYER_L),y
rts
getkey: lda $ff ; get the input key
cmp #$80 ; allow arrow keys only
bmi getkey
cmp #$84
bpl getkey
pha ; save the accumulator
lda #PATH ; set color of the current position to PATH
sta (NEW_PLAYER_L),y
pla ; restore accumulator
cmp #$80 ; check key is up
bne checkRight
dec NEW_ROW ; ... if yes, decrement ROW
rts
checkRight: cmp #$81 ; check if key is right
bne checkDown
inc NEW_COL ; ... if yes, increment COL
rts
checkDown: cmp #$82 ; check if key is down
bne checkLeft
inc NEW_ROW ; ... if yes, increment ROW
rts
checkLeft: cmp #$83 ; check if key is left
bne done
dec NEW_COL ; ... if yes, decrement COL
rts
done: rts ; break out of a loop or subroutine
checkCollision: ldy NEW_ROW ; load TARGET pointer with ROW
lda table_low,y
sta NEW_TARGET_L
lda table_high,y
sta NEW_TARGET_H
ldy NEW_COL ; load the color from the target
lda (NEW_TARGET_L),y; at (POINTER + COL)
cmp #$01
beq done
cmp #$03
beq done
cmp #$0a
beq gameComplete
lda #$00
sta (NEW_TARGET_L),y
lda $ff
cmp #$80 ; if input key was up...
bne ifRight
inc NEW_ROW ; ... if yes, increment ROW
rts
ifRight: cmp #$81 ; if input key was right...
bne ifDown
dec NEW_COL ; ... if yes, decrement COL
rts
ifDown: cmp #$82 ; if input key was down...
bne ifLeft
dec NEW_ROW ; ... if yes, decrement ROW
rts
ifLeft: cmp #$83 ; if input key was left...
bne done
inc NEW_COL ; ... if yes, increment COL
rts
gameComplete: jsr SCINIT
ldy #$00 ; print game completion message on the screen
pGameComplete: lda complete,y
beq done
sta $f000,y
iny
bne pGameComplete
brk
drawMaze: lda #$21 ; a pointer pointing to the first pixel
sta NEW_MAZE_L ; of the screen
lda #$02
sta NEW_MAZE_H
lda #$00 ; number of drawn rows
sta NEW_DRAWN_ROW
ldx #$00 ; maze data index
ldy #$00 ; column index
draw: lda maze_data,x
sta (NEW_MAZE_L), y
inx
iny
cpy #WIDTH ; compare with the number of WIDTH
bne draw ; if not, keep drawing the column
inc NEW_DRAWN_ROW ; increment the number of row
lda #HEIGHT
cmp NEW_DRAWN_ROW ; compare with the number of HEIGHT
beq done
lda NEW_MAZE_L
clc
adc #$20 ; add 32(0x0020) to increment the row
sta NEW_MAZE_L ; of the pixel
lda NEW_MAZE_H
adc #$00
sta NEW_MAZE_H
ldy #$00 ; reset the column index for the new row
beq draw
; help text message
help:
dcb "P","l","a","y",32,"w","i","t","h",32,"a","r","r","o","w"
dcb 32,"k","e","y","s",32,"t","o",32,"c","o","n","t","r","o","l",10
dcb 00
; game complete message
complete:
dcb "Y","o","u",32,"c","o","m", "p", "l", "e", "t", "e", "d", 32
dcb "t","h","e",32,"g","a","m","e","!"
dcb 00
; maze map data
maze_data:
dcb 01,00,01,00,01,01,01
dcb 01,01,01,00,00,00,01
dcb 00,00,01,00,01,00,01
dcb 01,00,01,00,01,01,01
dcb 01,00,01,00,01,00,01
dcb 01,00,01,00,01,00,01
dcb 01,01,01,01,01,00,10
; these two tables contain the high and low bytes
; of the addresses of the start of each row
table_high:
dcb $02,$02,$02,$02,$02,$02,$02,$02
dcb $03,$03,$03,$03,$03,$03,$03,$03
dcb $04,$04,$04,$04,$04,$04,$04,$04
dcb $05,$05,$05,$05,$05,$05,$05,$05
table_low:
dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
User input: keyboard keys
Finished: the red mark changes to green
Output:
Summary:
It was a very fun lab. I have made maze before but with python and using assembly language was a game changer for me. This could be made with more difficult mazes and level up with time.
Top comments (0)