📄 snake.asm
字号:
;****************************************************************
; 设计进程 ;
;2006-01-02:实现了基本的图像框架,蛇的初始化 ;
;2006-01-04:增加了蛇的移动,食物的随机出现,取得系统日期、时间。;
;2006-01-04:增加了计分,显示速度,显示系统日期、时间,游戏进行时;
; 间和相关版本信息 ;
;2006-01-05:增加了菜单功能 ;
;2006-01-06:增加了文件系统和显示排名 ;
;2006-01-07:增加了鼠标功能,鼠标改变方向在设计中 ;
;2006-01-08:增加了鼠标改变方向的功能 ;
; 修改了蛇身抖动问题 ;
; 增加了自动导航功能 ;
; 所有程序注释使用中文 ;
; 程序部分总行数2600行 ;
; ;
; 开放源码,共同学习,共同进步! ;
; 在别处引用\发表请注明出处,谢谢! ;
; ;
; ;
; 2006-01-08 ;
; 悠落 ;
;****************************************************************
title Snake Game
;贪吃蛇游戏
;***********************************
data segment
;游戏分数
even
Gscore dw 0
;===================================
;记录蛇身体坐标的数组
even
snake_B dw 1000 dup(4)
;记录数组snake_B的偏移地址
even
temp dw snake_B
;记录组成蛇身体的方格数
even
count dw 24
;记录蛇头坐标
even
snake_H dw ?,?
;===================================
;方向控制变量
;****Directive =01h,to left
;**** =02h,to right
;**** =03h,to top
;**** =04h,to bottom
;默认值是03h,向上
Directive db 03h
;单击鼠标的位置相对蛇头的方位控制
DirectiveM dw ?
;判断蛇头是不是和蛇身体相遇
;****Comparison=00h,没有相遇
;**** =11h,相遇
Comparison db 00h
;===================================
;食物的坐标
even
Food dw 18,16
;生成食物横坐标的随机种子,有百分之一秒数生成
Foodt db ?
;===================================
;前进速度
even
Speed dw ?
;===================================
;半个方格的宽度
even
HalfPoint dw 2
;用于在游戏中改变方格的大小
TempHalf dw 2
;用于记录当前坐标-HalfPoint之后的值
;在绘制方格的时候用到
TempPoint dw ?
;方格的颜色
PointColor db 10
;===================================
;系统时间
even
SysYear dw ?
SysData db ?,?
SysTime db ?,?,?,?
;游戏时间
;开始时间,用dl确定Foodt的初值
StartTime db ?,?,?,?
GameTime dw 0
;===================================
;二进制到十进制转换并输出函数的参数
even
;记下要转换并输出的数据
BTD dw 0
;用于控制转换的上限
;Ctr_Jmp=0时转换输出5位的十进制数
; 1时转化输出2位的十进制数
Ctr_Jmp db 0
;控制输出的位置
H_value db 0
L_value db 0
;===================================
;记录系统间的秒数,用于和当前系统时间的秒数相比较
;如果相同,则游戏时间不增加,否则游戏时间增加一秒并显示
Time_temp db ?
;===================================
;菜单控制变量,默认只显示主菜单
;控制进入主菜单的4号功能下一层
Direct_set1 db 0
;控制进入主菜单的4号功能下一层的下一层
Direct_set2 db 0
;控制进入排名察看菜单
Direct_set3 db 0
;控制在4号功能菜单中,是设置count还是color
Ctrl_set db 0
;===================================
;File_Name_ASC文件名
;File_Area向文件存取的空间大小
;Rank_ABC存放历史最高三位分数
;File_Handle文件句柄
File_Name_ASC db 7 dup(0)
File_Area dw 9 dup(?)
Rank_ABC dw 3 dup(0)
File_Handle dw ?
;===================================
;当前鼠标坐标(X,Y)
;Mouse_Point的大小是HalfPoint两倍,在鼠标控制的
;CX_DX函数中用到
;鼠标左键按下时的(X,Y)
;蛇移动时的指定位置的坐标
Mouse_X dw ?
Mouse_Y dw ?
Mouse_Point dw ?
Mouse_Down_X dw ?
Mouse_Down_Y dw ?
;判断鼠标左键按下的坐标是否和蛇头的坐标不远
Mouse_Snake_Meet db ?
;===================================
;鼠标键盘控制判断变量
;****Control_Kind=0,键盘
;****Control_Kind=1,鼠标
Control_Kind db 0
data ends
;***********************************
code segment
assume cs:code,ds:data,es:data
main proc far
;set the DS And ES
mov ax,data
mov ds,ax
mov es,ax
start:
call draw_the_game_area
call Show_Menu
;取得游戏环境初始化信息
call Get_some_information
call Get_time
call draw_the_snake
call Creat_a_random_mark
call draw_the_food
;显示相关信息
call Print_score
call Print_speed
call Print_data
call Print_time
call Print_SysTime
call Print_GameTime
call Print_Copyright
;游戏开始,蛇在游戏区域移动
call move_the_snake
exit:
mov ax,4c00h
int 21h
main endp
;***********************************
;信息取得和游戏环境初始化
Get_some_information proc near
;获取游戏开始时间,初始化Foodt和Time_temp
;为产生一随机坐标的横坐标和记录有戏时间做准备
mov ah,2ch
int 21h
mov StartTime,ch
mov StartTime+1,cl
mov StartTime+2,dh
mov StartTime+3,dl
mov Time_temp,dh
mov Foodt,dl
;取得系统年月日信息
mov ah,2ah
int 21h
mov SysYear,cx
mov SysData,dh
mov SysData+1,dl
;取得当前游戏速度,并显示在界面上
mov bx,Speed
mov ax,0ffffh
sub ax,bx
mov BTD,ax
mov H_value,9
mov L_value,66
mov Ctr_Jmp,0
call Bin_to_Dec
;在每局游戏开始的时候设置方格的大小
;由上一局中按M和N键控制
mov ax,TempHalf
mov HalfPoint,ax
;设置控制的方式,默认为键盘
mov Control_Kind,0
;在界面上显示游戏分数
mov ax,Gscore
mov BTD,ax
mov H_value,3
mov L_value,66
mov Ctr_Jmp,0
call Bin_to_Dec
ret
Get_some_information endp
;***********************************
;绘制游戏界面
draw_the_game_area proc near
;设置显示方式,640*480,16色
mov ah,0
mov al,12h
int 10h
;画游戏界面的框架,范围(10,10)-(630,470)
;边框颜色使用10 ,翠绿色
mov ah,0ch
mov al,10
mov bh,0
;顶部横线
mov cx,10
mov dx,8
top1: int 10h
inc cx
cmp cx,630
jnz top1
;底部横线
mov cx,10
mov dx,470
buttom2:
int 10h
inc cx
cmp cx,630
jnz buttom2
;左边竖线
mov cx,10
mov dx,8
left3: int 10h
inc dx
cmp dx,470
jnz left3
;右边竖线
mov cx,630
mov dx,8
right4: int 10h
inc dx
cmp dx,470
jnz right4
;中间分割线,左边游戏区域,右边信息区域
;游戏区域(10,10)-(470,470)
mov cx,470
mov dx,8
mid5: int 10h
inc dx
cmp dx,470
jnz mid5
;信息区域分割线
mov cx,470
mov dx,102
line1:
int 10h
inc cx
cmp cx,630
jnz line1
mov cx,470
mov dx,194
line2:
int 10h
inc cx
cmp cx,630
jnz line2
mov cx,470
mov dx,286
line3:
int 10h
inc cx
cmp cx,630
jnz line3
mov cx,470
mov dx,378
line4:
int 10h
inc cx
cmp cx,630
jnz line4
ret
draw_the_game_area endp
;*******************************************
;初始化蛇在游戏中出现的位置
draw_the_snake proc near
mov ah,0ch
mov al,10
mov bh,0
mov di,offset snake_B
;每次蛇头在游戏区域中出现的位置(210.280)
mov cx,210
mov dx,280
mov snake_H,cx
mov snake_H+2,dx
;蛇头坐标就是蛇身体的第一个方块的坐标
mov [di],cx
add di,2
mov [di],dx
add di,2
call draw_one_point
ret
draw_the_snake endp
;***********************************
;绘制食物
draw_the_food proc near
mov ah,0ch
mov al,12
mov bh,0
mov cx,Food
mov dx,Food+2
call draw_one_point
ret
draw_the_food endp
;************************************
;蛇的移动
move_the_snake proc near
move_to_next:
;将原来的蛇像擦除
mov di,offset snake_B
add di,count
re_move:
call Remove_the_old_body
sub di,4
cmp di,temp
jg re_move
;设定蛇身体的坐标
mov di,offset snake_B
add di,count
go_forward_one_point:
mov si,[di-4]
mov [di],si
mov si,[di-2]
mov [di+2],si
sub di,4
cmp di,temp
jg go_forward_one_point
;在新的位置绘制蛇像
mov di,offset snake_B
add di,count
re_draw:
call Redraw_the_new_body
sub di,4
cmp di,temp
jg re_draw
;扫描键盘按键,检测鼠标信息
call KeyBoard_Control
call Scan_Mouse
;输出当前速度
mov bx,Speed
mov ax,0ffffh
sub ax,bx
mov BTD,ax
mov H_value,9
mov L_value,66
mov Ctr_Jmp,0
call Bin_to_Dec
;输出时间
call Get_time
call Print_SysTime
;判断蛇是否吃到食物
call Judeg_meet
;一段时间延迟
push cx
mov cx,Speed
call Draw_Mouse
call Waitf
call Clear_Mouse
pop cx
call draw_the_food
;CX增减表示蛇在水平方向有移动
;DX增减表示蛇在垂直方向有移动
;CX增加----向右 CX减小----向左
;DX增加----向下 DX减小----向上
;判断当前是由键盘控制还是由鼠标控制
;Control_Kind=0,键盘控制
;Control_Kind=1,鼠标控制
cmp Control_Kind,0
jnz Together_CX_DX
call Set_the_CX_and_DX
jmp fffff
Together_CX_DX:
call Set_the_CX_and_DX_Together
fffff:
;判断蛇是否死亡
call Judge_dead
ret
move_the_snake endp
;***********************************
;设置键盘控制方向的时候,CX,DX的增减情况
Set_the_CX_and_DX proc near
mov cx,snake_H
mov dx,snake_H+2
cmp Directive,01h
jz left1
cmp Directive,02h
jz right2
cmp Directive,03h
jz up3
cmp Directive,04h
jz down4
jmp exit_set
;这里减两次HalfPoint才是一个方块的单位
left1: sub cx,HalfPoint
sub cx,HalfPoint
jmp exit_set
right2: add cx,HalfPoint
add cx,HalfPoint
jmp exit_set
up3: sub dx,HalfPoint
sub dx,HalfPoint
jmp exit_set
down4: add dx,HalfPoint
add dx,HalfPoint
exit_set:
;设置此时的蛇头坐标
mov snake_H,cx
mov snake_H+2,dx
mov snake_B,cx
mov snake_B+2,dx
ret
Set_the_CX_and_DX endp
;***********************************
;蛇像擦除函数
Remove_the_old_body proc near
mov ah,0ch
mov al,00h
mov bh,0
mov cx,[di]
mov dx,[di+2]
call draw_one_point
ret
Remove_the_old_body endp
;***********************************
;蛇像绘制函数
Redraw_the_new_body proc near
mov ah,0ch
mov al,PointColor
mov bh,0
mov cx,[di]
mov dx,[di+2]
call draw_one_point
ret
Redraw_the_new_body endp
;************************************
;80x86 PC的时间延迟函数
;参见清华大学<<IBM-PC汇编语言程序设计>>第二版
;第390页
Waitf proc near
push ax
waitf1:
in al,61h
and al,10h
cmp al,ah
je waitf1
mov ah,al
loop waitf1
pop ax
ret
Waitf endp
;************************************
;键盘扫描函数
KeyBoard_Control proc near
push ax
mov dl,0ffh
mov ah,06h
int 21h
;扫描键盘
cmp al,'a'
jz left
cmp al,'d'
jz right
cmp al,'w'
jz up
cmp al,'s'
jz down
jmp next_cmp1
;判断方向键
;按下方向键的时候,设置控制标志变量Control_Kind
;为0,关闭鼠标右键功能
;设置方向控制变量Directive的时候,首先判断当向蛇
;的运动方向时候和现在要设置的方向相反.
;避免失误按下反方向键造成死亡
left: mov Control_Kind,0
cmp Directive,02h
jz exit_control0
mov Directive,01h
jmp exit_control0
right: mov Control_Kind,0
cmp Directive,01h
jz exit_control0
mov Directive,02h
jmp exit_control0
up: mov Control_Kind,0
cmp Directive,04h
jz exit_control0
mov Directive,03h
jmp exit_control0
down: mov Control_Kind,0
cmp Directive,03h
jz exit_control0
mov Directive,04h
jmp exit_control0
exit_control0:
jmp exit_control
;继续判断其他控制键
next_cmp1:
cmp al,'+'
jz faster
cmp al,'-'
jz slower
cmp al,'p'
jz Pause
cmp al,'m'
jz Max_er
cmp al,'n'
jz Min_er
;Q为保存当前游戏环境设置并退出游戏到菜单界面
cmp al,'q'
jz exit_main
jmp exit_control0
exit_main:
call Quit_Msg
call Save_File
;保存设置后初始化新游戏的数据
mov Speed,16572
mov GameTime,0
mov Gscore,0
mov count,24
jmp far ptr start
;"+"增加前进速度
faster: mov ax,Speed
sub ax,1000
mov Speed,ax
jmp exit_control
;"-"减小前进速度
slower: mov ax,Speed
add ax,1000
mov Speed,ax
jmp exit_control
;"p"暂停游戏,直到再次按下"p"
Pause: mov ah,08h
int 21h
cmp al,'p'
jnz Pause
jmp exit_control
;"m","n",设计下一局游戏中方块的大小
;由大\中\小三种设置
Max_er: mov ax,HalfPoint
cmp ax,1
jz To_2
cmp ax,2
jz To_4
jmp exit_control
Min_er: mov ax,HalfPoint
cmp ax,4
jz To_2
cmp ax,2
jz To_1
jmp exit_control
To_1: mov TempHalf,1
jmp exit_control
To_2: mov TempHalf,2
jmp exit_control
To_4: mov TempHalf,4
jmp exit_control
exit_control:
pop ax
ret
KeyBoard_Control endp
;************************************
;判断蛇时候死亡的函数
Judge_dead proc near
;判断蛇头的坐标是否超出了游戏区域(10,10)-(470,470)
mov cx,snake_H
mov dx,snake_H+2
cmp cx,470
jae exit_move
cmp cx,10
jbe exit_move
cmp dx,10
jbe exit_move
cmp dx,470
jae exit_move
mov di,offset snake_B
add di,count
;判断当前游戏由鼠标还是键盘控制方向
;为了降低鼠标控制方向时的难度
;设置 鼠标控制 的时候,蛇遇到自己身体时候不死亡
cmp Control_Kind,0
jz cmp_body
jmp move_to_next
;键盘控制的时候,蛇遇到自己的身体时死亡
cmp_body:
;逐个比较蛇头坐标和身体坐标
Compar: cmp cx,[di]
jnz Reset
;当横坐标相同的时候Comparison和10H相或,继续比较纵坐标
;不同的时候,和下一组坐标比较
or Comparison,10h
cmp dx,[di+2]
jnz Reset
;当纵坐标相同的时候Comparison和01H相或
;不同的时候,和下一组坐标比较
or Comparison,01h
;判断Comparison的值
;若为11H,表示蛇头坐标和身体的某个坐标相同
;则推出游戏到菜单界面
;否则设置Comparison为0,继续比较下一组坐标
;直到和蛇身坐标比较完毕
;比较从蛇尾向蛇头进行
cmp Comparison,11h
jz exit_move
Reset: and Comparison,00h
sub di,4
cmp di,temp
jg Compar
jmp move_to_next
exit_move:
;退出游戏到菜单界面的时候显示结束信息
;发出结束警报声音
;当前的游戏分数和历史游戏分数比较,排名
;初始化下一次游戏数据
call Soundf
call Dead_Msg
call Set_Rank
mov Speed,16572
mov GameTime,0
mov Gscore,0
mov count,24
call Save_File
jmp far ptr start
ret
Judge_dead endp
;************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -