Reputation: 17
I am working on my final project which is a game wrote in assembly language. Therefore, I have question about how to make a timer while the game running.
My game is a simple Maze that working with W S A D, I am already using that command to run the program until the buffer will get any char.
WaitForData:
mov ah, 1
int 16h
jz WaitForData
mov ah, 0
int 16h
Now, all I need its just a timer working with the WATCH and not by Delay.
Upvotes: 0
Views: 3054
Reputation: 10371
The timer is made by reading time from system, then comparing seconds (for example) with previous seconds, if both have changed, one second has passed and you do something. Next example is a snake game I made (it's in spanish because I'm costarrican). The timer part starts in the comment ";OBTENER HORA DEL SISTEMA.". You may copy-paste next code in EMU8086 and run it.
.MODEL SMALL
.STACK 1024
.DATA
; 0 1 2 3 4 ...
; |----|----|----|----|----|
; X | 40 | 40 | 40 | 39 | 38 |
; Y | 10 | 11 | 12 | 12 | 12 |
;DIRECCION | A | A | D | D | D |
; |----|----|----|----|----|
;
; *
; *
; ***
ARRAY_X DB 100 DUP(0)
ARRAY_Y DB 100 DUP(0)
ARRAY_DIRECCIONES DB 100 DUP(0)
CUANTOS DW 3
SEGUNDOS DB ?
ASTERISCO DB 219,'$'
BLANCO DB ' $'
MINIMO DW ?
MAXIMO DW ?
SEMILLA DW ?
RAND DB ?
COLUMNA DB ?
FILA DB ?
ALIMENTO DB 1,'$'
.CODE
;INICIALIZAR DS.
MOV AX,@DATA
MOV DS,AX
;INICIALIZAR SNAKE CON TRES ELEMENTOS.
;1.
MOV SI,OFFSET ARRAY_X + 0
MOV AL,40
MOV [SI],AL
MOV SI,OFFSET ARRAY_Y + 0
MOV AL,12
MOV [SI],AL
MOV SI,OFFSET ARRAY_DIRECCIONES + 0
MOV AL,'D'
MOV [SI],AL
;2.
MOV SI,OFFSET ARRAY_X + 1
MOV AL,39
MOV [SI],AL
MOV SI,OFFSET ARRAY_Y + 1
MOV AL,12
MOV [SI],AL
MOV SI,OFFSET ARRAY_DIRECCIONES + 1
MOV AL,'D'
MOV [SI],AL
;3.
MOV SI,OFFSET ARRAY_X + 2
MOV AL,38
MOV [SI],AL
MOV SI,OFFSET ARRAY_Y + 2
MOV AL,12
MOV [SI],AL
MOV SI,OFFSET ARRAY_DIRECCIONES + 2
MOV AL,'D'
MOV [SI],AL
;OBTENER HORA DEL SISTEMA.
MOV AH,2CH
INT 21H
MOV SEGUNDOS,DH
CALL COMIDA
LABEL_MOVIMIENTO:
;VERIFICAR Q.
MOV AH,0BH
INT 21H
CMP AL,0
JE HORA
MOV AH,0
INT 16H
CMP AL,'Q'
JNE NO_TERMINAR
JMP TERMINAR_PROGRAMA
NO_TERMINAR:
CMP AL,0
JNE HORA
CMP AH,72
JE LABEL_SUBIR
CMP AH,80
JE LABEL_BAJAR
CMP AH,75
JE LABEL_IZQUIERDA
CMP AH,77
JE LABEL_DERECHA
JMP HORA
LABEL_SUBIR:
MOV SI,OFFSET ARRAY_DIRECCIONES
MOV AL,'A'
MOV [SI],AL
JMP HORA
LABEL_BAJAR:
MOV SI,OFFSET ARRAY_DIRECCIONES
MOV AL,'B'
MOV [SI],AL
JMP HORA
LABEL_IZQUIERDA:
MOV SI,OFFSET ARRAY_DIRECCIONES
MOV AL,'I'
MOV [SI],AL
JMP HORA
LABEL_DERECHA:
MOV SI,OFFSET ARRAY_DIRECCIONES
MOV AL,'D'
MOV [SI],AL
;MOVIMIENTO.
HORA:
MOV AH,2CH
INT 21H
CMP DH,SEGUNDOS
JE LABEL_MOVIMIENTO
MOV SEGUNDOS,DH
;EXAMINAR DIRECCION.
MOV BP,0 ;CONTADOR DEL FOR.
FOR:
;TERMINAR FOR.
CMP BP,CUANTOS
JB SIGUE ;JUMP IF BELOW.
JMP LABEL_MOVIMIENTO
SIGUE:
MOV SI,OFFSET ARRAY_DIRECCIONES
ADD SI,BP
MOV AL,[SI]
CMP AL,'D'
JE MOVIMIENTO_DERECHA
CMP AL,'A'
JE MOVIMIENTO_ARRIBA
CMP AL,'B'
JE MOVIMIENTO_ABAJO
CMP AL,'I'
JE MOVIMIENTO_IZQUIERDA
MOVIMIENTO_DERECHA:
CALL BORRAR
;AVANZA.
MOV SI,OFFSET ARRAY_X
ADD SI,BP
MOV AL,[SI]
CMP AL,79
JB DERECHA_BIEN
JMP TERMINAR_PROGRAMA
DERECHA_BIEN:
INC AL
MOV [SI],AL
CALL DESPLEGAR
JMP FOR
MOVIMIENTO_ARRIBA:
CALL BORRAR
;AVANZA.
MOV SI,OFFSET ARRAY_Y
ADD SI,BP
MOV AL,[SI]
CMP AL,0
JA ARRIBA_BIEN
JMP TERMINAR_PROGRAMA
ARRIBA_BIEN:
DEC AL
MOV [SI],AL
CALL DESPLEGAR
JMP FOR
MOVIMIENTO_ABAJO:
CALL BORRAR
;AVANZA.
MOV SI,OFFSET ARRAY_Y
ADD SI,BP
MOV AL,[SI]
CMP AL,24
JB ABAJO_BIEN
JMP TERMINAR_PROGRAMA
ABAJO_BIEN:
INC AL
MOV [SI],AL
CALL DESPLEGAR
JMP FOR
MOVIMIENTO_IZQUIERDA:
CALL BORRAR
;AVANZA.
MOV SI,OFFSET ARRAY_X
ADD SI,BP
MOV AL,[SI]
CMP AL,0
JA IZQUIERDA_BIEN
JMP TERMINAR_PROGRAMA
IZQUIERDA_BIEN:
DEC AL
MOV [SI],AL
CALL DESPLEGAR
JMP FOR
TERMINAR_PROGRAMA:
MOV AX,4C00H
INT 21H
DESPLEGAR PROC
;GOTOXY.
MOV SI,OFFSET ARRAY_X
ADD SI,BP
MOV DL,[SI]
MOV SI,OFFSET ARRAY_Y
ADD SI,BP
MOV DH,[SI]
MOV AH,2
MOV BH,0
INT 10H
;DISPLAY.
MOV AH,9
MOV DX,OFFSET ASTERISCO
INT 21H
;VERIFICAR SI HA COMIDO.
MOV SI,OFFSET ARRAY_X
ADD SI,BP
MOV AL,[SI]
MOV SI,OFFSET ARRAY_Y
ADD SI,BP
MOV AH,[SI]
CMP AL,COLUMNA
JNE CAMBIO
CMP AH,FILA
JNE CAMBIO
CALL COMIDA
;OBTENER DATOS DEL ULTIMO ELEMENTO.
MOV SI,OFFSET ARRAY_X
ADD SI,CUANTOS
DEC SI
MOV AL,[SI]
MOV SI,OFFSET ARRAY_Y
ADD SI,CUANTOS
DEC SI
MOV AH,[SI]
MOV SI,OFFSET ARRAY_DIRECCIONES
ADD SI,CUANTOS
DEC SI
MOV BL,[SI]
;NUEVO ULTIMO ELEMENTO.
CMP BL,'A'
JE POQUITO_ABAJO
CMP BL,'B'
JE POQUITO_ARRIBA
CMP BL,'D'
JE POQUITO_IZQUIERDA
POQUITO_DERECHA:
INC AL
JMP GUARDAR_DATOS
POQUITO_IZQUIERDA:
DEC AL
JMP GUARDAR_DATOS
POQUITO_ARRIBA:
DEC AH
JMP GUARDAR_DATOS
POQUITO_ABAJO:
INC AH
GUARDAR_DATOS:
MOV SI,OFFSET ARRAY_X
ADD SI,CUANTOS
MOV [SI],AL
MOV SI,OFFSET ARRAY_Y
ADD SI,CUANTOS
MOV [SI],AH
MOV SI,OFFSET ARRAY_DIRECCIONES
ADD SI,CUANTOS
MOV [SI],BL
INC CUANTOS
CAMBIO:
MOV SI,OFFSET ARRAY_DIRECCIONES
ADD SI,BP
MOV BL,[SI]
MOV BL,'A'
CMP [SI],BL
JE VERTICAL
MOV BL,'B'
CMP [SI],BL
JE VERTICAL
HORIZONTAL:
MOV DI,OFFSET ARRAY_Y
ADD DI,BP
MOV AL,[DI]
INC DI
CMP [DI],AL
JNE FIN
MOV AL,[SI]
INC SI
MOV [SI],AL
JMP FIN
VERTICAL:
MOV DI,OFFSET ARRAY_X
ADD DI,BP
MOV AL,[DI]
INC DI
CMP [DI],AL
JNE FIN
MOV AL,[SI]
INC SI
MOV [SI],AL
FIN:
INC BP
RET
ENDP
BORRAR PROC
;GOTOXY.
MOV SI,OFFSET ARRAY_X
ADD SI,BP
MOV DL,[SI]
MOV SI,OFFSET ARRAY_Y
ADD SI,BP
MOV DH,[SI]
MOV AH,2
MOV BH,0
INT 10H
;DISPLAY.
MOV AH,9
MOV DX,OFFSET BLANCO
INT 21H
RET
ENDP
COMIDA PROC
;COLUMNA ALEATORIA.
MOV MINIMO,0
MOV MAXIMO,79
CALL ALEATORIO
MOV AL,RAND
MOV COLUMNA,AL
;FILA ALEATORIA.
MOV MINIMO,0
MOV MAXIMO,24
CALL ALEATORIO
MOV AL,RAND
MOV FILA,AL
;GOTOXY.
MOV DL,COLUMNA
MOV DH,FILA
MOV AH,2
MOV BH,0
INT 10H
;DISPLAY.
MOV AH,9
MOV DX,OFFSET ALIMENTO
INT 21H
RET
ENDP
ALEATORIO PROC
REPETICION:
MOV AH,0
INT 1AH
ADD SEMILLA,DX
MOV AX,SEMILLA
MOV BX,2053
MOV DX,0
MUL BX
MOV BX,13849
CLC
ADD AX,BX
ADC DX,0
MOV BX,65535
DIV BX
MOV AX,DX
MOV SEMILLA,DX
MOV AH,0
SHR AL,1
CMP AX,MINIMO
JB REPETICION
CMP AX,MAXIMO
JA REPETICION
MOV AH,0
CMP AL,RAND
JE REPETICION
MOV AH,0
MOV RAND,AL
RET
ENDP
END
I was told that the previous code was too big, so I'm posting a small timer. All it does is display a text every second. The algorithm is simple : get system time, detect if one second has passed, then display the text :
.stack 100h
.data
text db 'text$'
seconds db 99
.code
;INITILIZE DATA SEGMENT.
mov ax, @data
mov ds, ax
while:
;GET SYSTEM TIME.
mov ah, 2ch
int 21h ;RETURN SECONDS IN DH.
;CHECK IF ONE SECOND HAS PASSED.
cmp dh, seconds
je no_change
;IF NO JUMP, ONE SECOND HAS PASSED. VERY IMPORTANT : PRESERVE SECONDS TO
;USE THEM TO COMPARE WITH NEXT SECONDS. THIS IS HOW WE KNOW ONE SECOND
;HAS PASSED.
mov seconds, dh
;DISPLAY TEXT EVERY SECOND.
mov ah, 9
mov dx, offset text
int 21h
no_change:
jmp while
;FINISH THE PROGRAM PROPERLY.
mov ax, 4c00h
int 21h
With a timer like this it's possible to control the ghosts with the timer, while the pacman is controlled by the keyboard (for example).
Upvotes: 1