我正在研究我的最终项目,这是一个用汇编语言编写的游戏。 因此,我对游戏运行时如何制作计时器有疑问。
我的游戏是一个简单的迷宫,使用W S A D,我已经使用该命令运行程序,直到缓冲区获得任何字符。
WaitForData:
mov ah, 1
int 16h
jz WaitForData
mov ah, 0
int 16h
现在,我只需要一个使用WATCH而不是延迟的计时器。
答案 0 :(得分:1)
计时器是通过从系统读取时间,然后将秒数(例如)与之前的秒数进行比较,如果两者都已经改变,一秒钟已经过去并且你做了一些事情。接下来的例子是我制作的一个蛇游戏(它是西班牙语的,因为我是cosarrican)。计时器部分从注释&#34 ;; OBTENER HORA DEL SISTEMA开始。"。您可以在EMU8086中复制粘贴下一个代码并运行它。
.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
我被告知以前的代码太大了,所以我发布了一个小计时器。它所做的只是每秒显示一个文本。算法很简单:获取系统时间,检测是否已经过了一秒,然后显示文本:
.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
使用这样的计时器可以用计时器控制重影,而pacman则由键盘控制(例如)。