📄 plane.asm
字号:
TITLE PLANE
;******************************************************************************************
;GALLERY.ASM
;******************************************************************************************
;Arcade-type game program using timed pluse and interactive animation
;The code has the following system requiremnts:
;1. VGA graphics system
;2. MS DOS 3.0 or LATER
;3. IBM PS/2 ,Microsoft, or compatible MOUSE, and installed driver;
;******************************************************************************************
;声音频率和持续时间
HIT_DELAY EQU 1000
HIT_FREQ EQU 500
MISS_DELAY EQU 30
MISS_FREQ EQU 6000
;鼠标移动区域的限制
CUR_LIM_RIGHT EQU 620
CUR_LIM_LEFT EQU 5
CUR_LIM_UP EQU 362
CUR_LIM_DOWN EQU 465
;射击命中范围的判定
ON_X EQU 10
ON_X2 EQU 20
ON_Y EQU 08
ON_Y2 EQU 16
PLANE_SPEED EQU 6 ;飞机移动的速度
;******************************************************************************************
CODE SEGMENT BYTE
ASSUME CS:CODE,DS:DATA,SS:SSEG
START:
MOV AX,DATA ;Initialize
MOV DS,AX
MOV AX,SSEG
MOV SS,AX
LEA SP,SS:STACK_TOP ;使SP指向栈顶k
;Initialize mouse
MOV AX,0 ;鼠标复位,BX中存放鼠标的键数
INT 33H
CMP AX,0 ;Test for error during reset
JNZ OK_MOUSE ;No problem
;Mouse initialization error
LEA DX,BAD_MOUSE_MS ;Test message to signal error
MOV AH,9 ;Display error message
INT 21H
JMP DOS_EXIT ;出错则结束程序
;设置显示方式,VGA模式18,640×480,16色
OK_MOUSE:
MOV AH,0
MOV AL,18
INT 10H
;******************************************************************************************
;重置timer interrupt
;------------------------------------------------------------------------------------------
;保存参数
CLI
MOV AX,0H ;
MOV ES,AX ;清空AX、ES
;保存原来的中断1CH
MOV AH,35H ;功能号设置为35H,取中断向量
MOV AL,1CH ;要取的中断类型号
INT 21H
;
MOV SI,OFFSET OLD_VECTOR_1C
MOV [SI],BX ;存储原来中断的偏移地址
MOV [SI+2],ES ; 和段地址
;设置中断向量
MOV AH,25H ;功能号设置为25H,设置中断向量
MOV AL,1CH ;中断向量号
PUSH DS
PUSH CS
POP DS
MOV DX,OFFSET HEX1C_INT
INT 21H
POP DS
;------------------------------------------------------------------------------------------
;初始化显示缓存器地址
MOV AX,0A000H
MOV ES,AX
;图像显示设置写模式2
MOV AL,2 ;模式号
CALL SET_WRITE_MODE
;填充整个屏幕为白色
MOV CH,0 ;从0行开始
MOV CL,0 ;从0列开始
MOV DH,80 ;需要填充的列数
MOV DL,60 ;需要填充的行数
MOV AL,00000111B ;用白色填充
CALL COARSE_FILL
;画游戏界面中的各区域分界线
MOV AH,0
MOV CL,44
MOV DH,80
MOV DL,16
MOV AL,00001000B ;灰色
CALL COARSE_FILL
;
MOV CH,46 ;CH中存放要填充区域的开始行
MOV CL,0 ;CL中存放要填充区域的开始列
MOV DH,1 ;DH中存放要填充的列数
MOV DL,29 ;DL中存放要填充的行数
MOV AL,00000001B ;AL中存放填充色
CALL COARSE_FILL
;画三条横线
MOV CH,0
MOV CL,29
MOV DH,80
MOV DL,1
MOV AL,00000001B
CALL COARSE_FILL
;
MOV CH,0
MOV CL,44
MOV DH,80
MOV DL,1
MOV AL,00100110B
CALL COARSE_FILL
;
MOV CH,0
MOV CL,59
MOV DH,80
MOV DL,1
MOV AL,11010100B
CALL COARSE_FILL
;
MOV CH,20
MOV CL,30
MOV DH,1
MOV DL,14
MOV AL,10001001B
CALL COARSE_FILL
;
MOV CH,60
MOV CL,30
MOV DH,1
MOV DL,14
MOV AL,1
CALL COARSE_FILL
;
MOV CH,21
MOV CL,30
MOV DH,39
MOV DL,14
MOV AL,1 ;蓝色
CALL COARSE_FILL
;设置写模式0用来显示文本
MOV AL,0 ;Write mode
CALL SET_WRITE_MODE
;显示文本信息
LEA DI,GALL_MS ;指针指向文本信息
CALL GRAPHIC_TEXT ;显示在屏幕右上角
LEA DI,MOU_MS
CALL GRAPHIC_TEXT
LEA DI,TOP_MS
CALL GRAPHIC_TEXT
LEA DI,BOT_MS
CALL GRAPHIC_TEXT
CALL SCOREBOARD
;==========================================================================================
;设置鼠标中断,设置点击鼠标左、右键的中断响应事件
;==========================================================================================
CLI ;Interrupts off
PUSH ES ;Save video buffer segment
PUSH CS ;Program's segment
POP ES ;To ES
MOV AX,0CH ;Mouse service number 0CH
;Interrupt mask bit map
MOV CH,0 ;Unused bits
MOV CL,00001010B ;设置响应鼠标左、右键的中断
MOV DX,OFFSET MOUSE_BUT
INT 33H ;调用鼠标中断
POP ES
STI ;开中断
;游戏开始
START_GAME:
MOV FIRE_CNT,10 ;每次游戏开始时设置最大射击次数为10次
MOV GUN_FIRED,0 ;每次游戏开始时设置已经射击次数为0次
MOV PLANE_OFF,1 ;游戏开始时不显示飞机
MOV FIRST_PLANE,1 ;设置第一只飞机出现
MOV PLANE_X,0 ;游戏初始时飞机和十字箭头的坐标
MOV PLANE_Y,410
MOV CROSS_X,320
MOV CROSS_Y,CUR_LIM_UP
CALL XOR_XHAIR ;显示十字准星符号
;允许玩家在游戏开始时读取上一次游戏的得分
;鼠标右键被点击后正式开始游戏
;在游戏进行过程中检测ESC键是否被点击,若被点击则退出游戏
START_WAIT:
CALL KBR_STATUS ;若有键被按下,设置CF=1
JNC NO_KEY_READY ;若CF=0,说明没有键被按下,转至NO_KEY_READY执行
JMP READ_KEY ;读入键盘缓冲区中的值
NO_KEY_READY:
CMP PLANE_OFF,0 ;;PLANE_OFF=0由鼠标右键按下时设置
JNE START_WAIT ;;若鼠标右键没有被按下则PLANE回START_WAIT执行
;若PLANE_OFF=0S说明鼠标右键被按下,则开始一个新游戏
INC GAME_CNT ;使游戏次数计数器增加一
MOV SCORE_CNT,0 ;分数计数器重置为0
CALL GET_SCORE ;调用计算游戏次数和分值并显示的函数
CALL SCOREBOARD ;更新显示记分板
MONITOR:
CALL KBR_FLUSH ;清空键盘缓冲区
GET_STROKE:
CALL KBR_STATUS ;若键盘被敲击,CF=1
JC READ_KEY ;读键盘
;若玩家射击了,则更新记分板和游戏的控制变量
CMP GUN_FIRED,1 ;若左键被按动变量值将被设置为1
JNE MOUSE_MOVE ;若没有射击则游戏继续进行
;若玩家射击了,则更新记分板和游戏的控制变量
DEC FIRE_CNT ;已射击次数减1
MOV GUN_FIRED,0
CMP HIT_SW,1 ;检测射击是否命中
JNE SHOT_MISSED ;射击未命中时转至SHOT_MISSED执行
ADD SCORE_CNT,10 ;若命中则游戏分值计数器增加10分做为给玩家的奖励
CALL GET_SCORE ;更新分值
SHOT_MISSED:
CMP FIRE_CNT,0 ;所剩射击次数是否为0
JE GAME_OVER ;若是,说明玩家已使用了全部射击机会,游戏结束
CALL SCOREBOARD ;若所剩射击次数不为0,更新记数板显示
JMP MOUSE_MOVE ;游戏继续进行
GAME_OVER:
;擦除最后屏幕上显示的最后一只飞机
MOV PLANE_OFF,1 ;没有飞机显示
CMP DS:PLANE_X,0
JZ BUCA
CALL XOR_PLANE
;Erase last cross-hair symbol
BUCA:
CALL XOR_XHAIR ;擦除十字准星符号
CALL GET_SCORE ;计算得分和游戏次数
CALL SCOREBOARD ;更新记分板显示
JMP START_GAME ;开始新游戏
READ_KEY:
CALL KBR_WAIT ;从缓冲区中读取字符
CMP AX,011BH ;检测ESC键是否被敲击
JE PROGRAM_EXIT ;若敲击的是ESC键则转至PROGRAM_EXIT退出游戏
CMP PLANE_OFF,0
JNE NO_KEY_READY
MOUSE_MOVE:
MOV AX,0BH ;Service request to read counters
INT 33H ;鼠标中断
MOV AL,CL ;Horizontal counter to AL
MOV AH,DL ;Vertical counter to AH
CMP AX,0 ;If AX is 0 then no mouse movement
JE GET_STROKE ;Go if no movement
CALL MOVE_CURSOR ;Update cursor position
JMP GET_STROKE ;Wait for kestroke
;
PROGRAM_EXIT: CLI ;Interrupts off
;Restore INT 1CH
MOV SI,OFFSET OLD_VECTOR_1C
;Set DS:DX to original segment and offset of keboard interrput vector
MOV DX,[SI] ;DX -> offset
MOV AX,[SI+2] ;AX -> segment
MOV DS,AX ;Segment to DS
MOV AH,25H ;DOS service request
MOV AL,1CH
INT 21H
;Reset video system
MOV AL,0 ;Write mode 0
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
CALL SET_WRITE_MODE ;Procedure from 10.3.1.3
CALL DATA_NORMAL ;Reset normal write mode, see 10.4.1.2
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
MOV AL,3 ;Set alphanumeric mode 3
MOV AH,0
INT 10H
;
DOS_EXIT: MOV AX,4C00H ;DOS service request mode
INT 21H ;Exit to DOS
;==========================================================================================
;Set the Graphics Controller's Graphics Mode register to the desired write mode
;On entry:
; AL = write mode requested
;Also set default bit mask
;==========================================================================================
SET_WRITE_MODE PROC NEAR
PUSH AX ;Save mode
MOV DX,3CEH ;Graphics Controller Address register
MOV AL,5 ;Offset of the Mode register
OUT DX,AL ;Select this register
JMP SHORT $+2
MOV DX,3CFH ;Point to data register
POP AX ;Recover mode in AL ;///////////////
OUT DX,AL ;Selected
JMP SHORT $+2
;Set Bit Mask register to default setting
MOV DX,3CEH ;Graphics controller latch
MOV AL,8
OUT DX,AL ;Select data register 8
JMP SHORT $+2
MOV DX,3CFH ;To 3CFH
MOV AL,0FFH ;Default mask
OUT DX,AL ;Load bit mask
JMP SHORT $+2
RET
SET_WRITE_MODE ENDP
;==========================================================================================
;Purpose: Fill a screen area on a byte boundary base
;On entry:
; CH = pillar address of start point(range 0 to 79)
; CL = rank address of start point(range 0 to 59)
; DL = total ranks to fill(1 to 60)
; DH = total pillars to fill(1 to 80)
; AL = IRGB color to use in fill area
;==========================================================================================
COARSE_FILL PROC NEAR
PUSH CX ;Save entry registers
PUSH DX
PUSH AX
;
MOV AH,0FFH ;Bit pattern for all bits set
PUSH AX
CALL COARSE_ADD
;Byte offset into video ROM is now set in BX
;Next set up column counter in CX and row counter in DX
MOV CL,DH ;Horizontal fill
MOV CH,0 ;CX = horizontal counter
PUSH CX ;Save temporarily
;Row counter = DL*8
MOV AX,DX
MOV AH,0 ;Clear high-order byte
MOV CL,8
MUL CL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -