Reputation: 33
So this is the continuation of my typing word game. I have most it finished but changed a decent part of the code from before. I have almost everything done except for some reason the words print at the top of the screen and stay there. It's supposed to print at the top and slowly fall towards the bottom of the screen but it doesn't.
include Irvine32.inc
BUFMAX EQU 128
SCREEN_WIDTH EQU 80 ; Adjust this value to your desired console width
INITIAL_HEARTS EQU 3
.data
Words BYTE "house", 0 ; List of words to be typed
BYTE "water", 0
BYTE "foods", 0
BYTE "apple", 0
BYTE "cloud", 0
BYTE "eagle", 0
BYTE "jades", 0
BYTE "nacho", 0
BYTE "vegas", 0
BYTE "wacky", 0
BYTE "cable", 0
BYTE "excel", 0
BYTE "cache", 0
BYTE "debug", 0
BYTE "erase", 0
BYTE "image", 0
msElapsed DWORD 0 ; Milliseconds elapsed counter
positionX BYTE 0
positionY BYTE 0
nextWord DWORD 0 ; Index of the next word to display
score DWORD 0
correctKeys DWORD 0
totalKeys DWORD 0
correctWords DWORD 0
hearts DWORD INITIAL_HEARTS
heartsMsg BYTE "Hearts: ", 0
scoreMsg BYTE "Game Over", 0
scoreDisplayMsg BYTE "Score: ", 0
accuracyDisplayMsg BYTE "Accuracy: ", 0
wpmDisplayMsg BYTE "WPM: ", 0
char BYTE ? ; Character input by user
correctBuffer BYTE BUFMAX DUP (0) ; Buffer to store correctly typed characters
incorrectBuffer BYTE BUFMAX DUP (0) ; Buffer to store incorrectly typed characters
correctIndex DWORD 0
incorrectIndex DWORD 0
incorrectFlag BYTE 0 ; Flag to indicate if an incorrect character was typed
wordPlaced BYTE 0 ; Flag to indicate if the word has been placed at a random position
startTime DWORD ? ; Start time for WPM calculation
elapsedTime DWORD ? ; Elapsed time for WPM calculation
debugMsg BYTE "Y: ", 0 ; Debug message prefix
.code
main PROC
call Randomize ; Initialize random number generator
call DrawBottomLine
call InitializeGame
call GameLoop ; Start the game loop
invoke ExitProcess, 0
main ENDP
InitializeGame PROC
call GetTickCount ; Get the current system tick count
mov startTime, eax ; Store the start time
ret
InitializeGame ENDP
GameLoop PROC
gameLoopStart:
call DisplayStats ; Display hearts, score, accuracy, and WPM
call SetRandomPosition ; Set random position for the word if needed
call ClearPreviousWord ; Clear the previous word
call DrawWord ; Draw the word and buffers on the screen
call DelayUpdate ; Delay for input and update position
call ReadKey ; Read a key from the keyboard
jz continueGameLoop ; If no key was pressed, continue the loop
mov char, al ; Store the read character in char
inc totalKeys ; Increment total keys pressed
call ProcessKey ; Process the key pressed
cmp [msElapsed], 2000 ; Compare msElapsed with 2000 (2 seconds)
jl skipIncrementY ; Do not increase y if not 2000ms (2 sec)
inc positionY ; Increment the Y position
mov [msElapsed], 0 ; Reset ms counter
call DebugPrintPositionY ; Print debug message
skipIncrementY:
call CheckWordPosition ; Check if the word has reached the bottom
continueGameLoop:
jmp gameLoopStart ; Continue the game loop
GameLoop ENDP
SetRandomPosition PROC
cmp wordPlaced, 1 ; Check if the word has been placed
je skipRandomPosition
mov eax, SCREEN_WIDTH - 5 ; Subtract 5 to avoid overflow
call RandomRange ; Generate random number in range 0 to (SCREEN_WIDTH - 5)
mov positionX, al ; Set positionX to the random value
mov positionY, 0 ; Set positionY to the top of the screen
mov wordPlaced, 1 ; Set the wordPlaced flag
skipRandomPosition:
ret
SetRandomPosition ENDP
ClearPreviousWord PROC
mov dl, positionX
mov dh, positionY
call Gotoxy ; Move cursor to the specified (X, Y) position
mov eax, black + (black * 16) ; Set text color to black on black background
call SetTextColor
mov edx, OFFSET Words ; Load address of Words array into EDX
add edx, [nextWord] ; Add nextWord index to get the current word
call WriteString ; Clear the current word
ret
ClearPreviousWord ENDP
DrawWord PROC
; Print the new word in white
mov dl, positionX
mov dh, positionY
call Gotoxy ; Move cursor to the specified (X, Y) position
mov eax, white + (black * 16) ; Set text color to white on black background
call SetTextColor
mov edx, OFFSET Words ; Load address of Words array into EDX
add edx, [nextWord] ; Add nextWord index to get the current word
call WriteString ; Print the current word
; Draw the correctly typed characters in green over the original word
mov dl, positionX
mov dh, positionY
call Gotoxy ; Move cursor to the specified (X, Y) position
mov eax, green + (black * 16) ; Set text color to green on black background
call SetTextColor
mov edx, OFFSET correctBuffer ; Load address of correctBuffer into EDX
call WriteString ; Print the correctBuffer string
; Draw the incorrectly typed characters in red over the original word
mov dl, positionX ; Move positionX value to DL register
add dl, BYTE PTR [correctIndex] ; Move cursor position to correct place for incorrect characters
mov dh, positionY ; Move positionY value to DH register
call Gotoxy ; Move cursor to the specified (X, Y) position
mov eax, red + (black * 16) ; Set text color to red on black background
call SetTextColor
mov edx, OFFSET incorrectBuffer ; Load address of incorrectBuffer into EDX
call WriteString ; Print the incorrectBuffer string
ret
DrawWord ENDP
DelayUpdate PROC
mov eax, 10 ; Delay to make words fall at a reasonable speed
add [msElapsed], eax ; Increment msElapsed counter
call Delay ; Delay for the specified time
ret
DelayUpdate ENDP
ProcessKey PROC
; Check if an incorrect character has already been typed
cmp incorrectFlag, 1 ; Check if an incorrect character was typed
je checkCorrectCharacter ; If an incorrect character was typed, check for the correct character
mov esi, OFFSET Words ; Load address of Words array into ESI
add esi, [nextWord] ; Add nextWord index to get the current word
add esi, [correctIndex] ; Add correctIndex value to ESI to point to the current character
movzx ebx, char ; Move char to EBX and zero-extend it
cmp [esi], bl ; Compare current character in Words with char
jne incorrect ; If they are not equal, jump to incorrect
correct:
mov esi, OFFSET correctBuffer ; Load address of correctBuffer into ESI
add esi, [correctIndex] ; Add correctIndex value to ESI to point to the correct position
mov [esi], bl ; Store the correct character in correctBuffer
inc esi ; Increment ESI
mov BYTE PTR [esi], 0 ; Null-terminate the correct buffer
mov incorrectBuffer, 0 ; Clear incorrectBuffer on correct character
mov incorrectFlag, 0 ; Clear incorrect flag on correct character
inc [correctIndex] ; Increment the correctIndex
inc correctKeys ; Increment the number of correct keys
call CheckWordCompletion ; Check if the word is completed
ret
incorrect:
; Store the incorrect character at the start of incorrectBuffer
mov esi, OFFSET incorrectBuffer
mov [esi], bl ; Store the incorrect character
mov BYTE PTR [esi + 1], 0 ; Null-terminate the incorrect buffer
mov incorrectFlag, 1 ; Set the incorrect flag
ret
checkCorrectCharacter:
mov esi, OFFSET Words ; Load address of Words array into ESI
add esi, [nextWord] ; Add nextWord index to get the current word
add esi, [correctIndex] ; Add correctIndex value to ESI to point to the current character
movzx ebx, char ; Move char to EBX and zero-extend it
cmp [esi], bl ; Compare current character in Words with char
je correct ; If they are equal, jump to correct
ret
ProcessKey ENDP
CheckWordCompletion PROC
mov esi, OFFSET Words ; Load address of Words array into ESI
add esi, [nextWord] ; Add nextWord index to get the current word
add esi, [correctIndex] ; Add correctIndex value to ESI to point to the current character
cmp BYTE PTR [esi], 0 ; Compare current character with null terminator
jne returnFromCheckCompletion ; If not the end, return
; If a word is completed, reset indexes and move to the next word
call ClearCurrentWord ; Clear the current word from the screen
mov [correctIndex], 0 ; Reset correctIndex
mov [incorrectIndex], 0 ; Reset incorrectIndex
add [nextWord], 6 ; Move to next word (each word is 5 characters + null terminator)
inc correctWords ; Increment the number of correct words
mov wordPlaced, 0 ; Reset wordPlaced flag
mov incorrectFlag, 0 ; Reset incorrectFlag
cmp [nextWord], 96 ; Check if all words are exhausted (16 words * 6 bytes each)
jl returnFromCheckCompletion ; If not, return
; Reset to the beginning of the array
mov [nextWord], 0
returnFromCheckCompletion:
ret
CheckWordCompletion ENDP
CheckWordPosition PROC
cmp [positionY], 23 ; Compare positionY with 23 (one line above bottom)
jl continueCheckWordPosition ; If positionY is less than 24, continue the game loop
; If the word reaches the bottom of the screen, reduce hearts
call ReduceHearts
mov eax, hearts ; Load hearts into eax
cmp eax, 0 ; Check if hearts are 0
je endGame ; If no hearts left, end the game
; Reset word placement and continue
call ResetWord
continueCheckWordPosition:
ret
endGame:
mov dl, 0 ; Move cursor to the top-left corner
mov dh, 0
call Gotoxy
mov eax, white + (black * 16) ; Set text color to white on black background
call SetTextColor
mov edx, OFFSET scoreMsg ; Load address of scoreMsg into EDX
call WriteString ; Print the score message
ret
CheckWordPosition ENDP
ResetWord PROC
call ClearCurrentWord
mov [correctIndex], 0 ; Reset correctIndex
mov [incorrectIndex], 0 ; Reset incorrectIndex
add [nextWord], 6 ; Move to next word
mov wordPlaced, 0 ; Reset wordPlaced flag
cmp [nextWord], 96 ; Check if all words are exhausted
jl returnFromResetWord ; If not, return
; Reset to the beginning of the array
mov [nextWord], 0
returnFromResetWord:
ret
ResetWord ENDP
ReduceHearts PROC
mov eax, hearts
dec eax ; Decrease the number of hearts by 1
mov hearts, eax
ret
ReduceHearts ENDP
DisplayStats PROC
; Display Hearts
mov dl, 0 ; Set cursor position to top-left corner
mov dh, 0
call Gotoxy
mov eax, white + (black * 16) ; Set text color to white on black background
call SetTextColor
mov edx, OFFSET heartsMsg ; Load address of heartsMsg
call WriteString ; Print the "Hearts: " message
mov eax, hearts
call WriteDec ; Print the number of hearts
; Display Score
mov dl, 0
mov dh, 1
call Gotoxy
mov edx, OFFSET scoreDisplayMsg ; Load address of scoreDisplayMsg
call WriteString ; Print the "Score: " message
mov eax, correctKeys
call WriteDec ; Print the score
; Display Accuracy
mov dl, 0 ; Set cursor position to next line
mov dh, 2
call Gotoxy
mov edx, OFFSET accuracyDisplayMsg ; Load address of accuracyDisplayMsg
call WriteString ; Print the "Accuracy: " message
mov eax, correctKeys
mov ebx, 100
mul ebx ; Multiply correct keys by 100
cdq
cmp totalKeys, 0 ; Check if totalKeys is zero to avoid division by zero
je noKeysPressed
idiv totalKeys ; Divide by total keys pressed
call WriteDec ; Print the accuracy value
mov dl, '%' ; Load '%' character into DL register
call WriteChar ; Print '%'
jmp skipNoKeys ; Skip the no keys pressed handler
noKeysPressed:
mov eax, 0
call WriteDec ; Print 0 for accuracy
mov dl, '%' ; Load '%' character into DL register
call WriteChar ; Print '%'
skipNoKeys: ; Label to skip the no keys pressed handler
; Display WPM
call GetTickCount ; Get the current system tick count
sub eax, startTime ; Calculate elapsed time
mov elapsedTime, eax ; Store the elapsed time
mov dl, 0
mov dh, 3
call Gotoxy
mov edx, OFFSET wpmDisplayMsg ; Load address of wpmDisplayMsg
call WriteString ; Print the "WPM: " message
mov eax, correctWords
mov ebx, 60000
mul ebx ; Multiply correct words by 60000 (milliseconds in a minute)
cdq
cmp elapsedTime, 0 ; Check if elapsedTime is zero to avoid division by zero
je noElapsedTime
idiv elapsedTime ; Divide by elapsed time
call WriteDec ; Print the WPM value
jmp skipNoElapsed ; Skip the no elapsed time handler
noElapsedTime:
mov eax, 0
call WriteDec ; Print 0 for WPM
skipNoElapsed: ; Label to skip the no elapsed time handler
ret
DisplayStats ENDP
DrawBottomLine PROC
mov dl, 0
mov dh, 24 ; Set cursor position to the bottom line (24th row)
call Gotoxy
mov eax, white + (black * 16) ; Set text color to white on black background
call SetTextColor
mov ecx, SCREEN_WIDTH
drawLineLoop:
mov al, '-' ; Use '-' to draw the line
call WriteChar ; Write the character to the screen
loop drawLineLoop
ret
DrawBottomLine ENDP
ClearCurrentWord PROC
; Clear the current word from the screen
mov dl, positionX
mov dh, positionY
call Gotoxy
; Overwrite the word with spaces
mov eax, black + (black * 16) ; Set text color to black on black background
call SetTextColor
mov ecx, 5 ; Each word has 5 characters
clearLoop:
mov al, ' ' ; Load space character into AL
call WriteChar ; Write the space character to the screen
loop clearLoop
; Reset buffers
mov edi, OFFSET correctBuffer
mov ecx, BUFMAX
xor eax, eax
rep stosb ; Clear correctBuffer
mov edi, OFFSET incorrectBuffer
mov ecx, BUFMAX
rep stosb ; Clear incorrectBuffer
ret
ClearCurrentWord ENDP
DebugPrintPositionY PROC
; Debug print for positionY
movzx eax, positionY ; Zero-extend the byte to a 32-bit register
mov edx, OFFSET debugMsg
call WriteString
call WriteDec
call CrLf
ret
DebugPrintPositionY ENDP
END main
I tried to fix the line inc positionY but it didn't really work. It would be greatly appreciated if you could help me out!
Upvotes: 0
Views: 51
Reputation: 924
After these two lines ZF = 1
if user didn't press keys. So loop can go forever msElapsed
and positionY
will not be modified.
call ReadKey
jz continueGameLoop
But if You move label continueGameLoop:
few lines up so the code keep tracking variables this will change positionY
so the word will fall down.
GameLoop PROC
gameLoopStart:
call DisplayStats ; Display hearts, score, accuracy, and WPM
call SetRandomPosition ; Set random position for the word if needed
call ClearPreviousWord ; Clear the previous word
call DrawWord ; Draw the word and buffers on the screen
call DelayUpdate ; Delay for input and update position
call ReadKey ; Read a key from the keyboard
jz continueGameLoop ; If no key was pressed, continue the loop
mov char, al ; Store the read character in char
inc totalKeys ; Increment total keys pressed
call ProcessKey ; Process the key pressed
continueGameLoop:
cmp [msElapsed], 2000 ; Compare msElapsed with 2000 (2 seconds)
jl skipIncrementY ; Do not increase y if not 2000ms (2 sec)
inc positionY ; Increment the Y position
mov [msElapsed], 0 ; Reset ms counter
call DebugPrintPositionY ; Print debug message
skipIncrementY:
call CheckWordPosition ; Check if the word has reached the bottom
jmp gameLoopStart ; Continue the game loop
GameLoop ENDP
Anyway, 3 words touched bottom line, Hearts = 0
and this variable resets to full 32-bit value because CheckWordPosition proc
returns to main game loop
.
Upvotes: 0