怎么做游戏中的装配计时器?

时间:2015-03-25 20:35:48

标签: assembly timer x86

我正在研究我的最终项目,这是一个用汇编语言编写的游戏。 因此,我对游戏运行时如何制作计时器有疑问。

我的游戏是一个简单的迷宫,使用W S A D,我已经使用该命令运行程序,直到缓冲区获得任何字符。

WaitForData:
mov ah, 1
int 16h
jz WaitForData
mov ah, 0 
int 16h

现在,我只需要一个使用WATCH而不是延迟的计时器。

1 个答案:

答案 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则由键盘控制(例如)。