📄 game.asm
字号:
; Copyleft (c) 2007,God reserved all rights.
;
; 文件名称:game.asm
;
; 当前版本:0.13
; 作 者:邹伟
; 摘 要:各主要子程序都在此间
; 说 明:程序中用于输出字符的位置未加说明则默认为相对于游戏区域左上角即(GM_LEFT,GM_TOP)
public setDSAndES , GA_gameInit , GA_gameCircle , stackPoint
extern main_quit:far,restart_the_game:far
include game.h
;设置块坐标的宏
assignPos macro x,y
mov (Brick ptr [si]).b_sPos.pos_bX,x
mov (Brick ptr [si]).b_sPos.pos_bY,y
add si,size Brick
endm
assignBase macro x,y
mov (ManyBrick ptr [di]).mb_sPos.pos_bX,x
mov (ManyBrick ptr [di]).mb_sPos.pos_bY,y
endm
assume cs:GameCode,ds:MainData,ss:StackSpase
GameCode segment
;游戏循环---不断获取输入,根据与定义规则合理的转化为输出
GA_gameCircle proc far
GA_gameCircle_again:
mov dir,KEY_WRONG_DIR
lea bx,levelFPS
mov di,level
add di,challenge
cmp di,LEVEL_LIMITT
jbe level_ok
mov di,LEVEL_LIMITT
level_ok:
shl di,1
mov cx,[bx+di]
wast_time:
call delay
cmp dir,KEY_WRONG_DIR
je may_be_life_is_long
call Brick_goNext
mov dir,KEY_WRONG_DIR
call ManyBrick_drawSelf
may_be_life_is_long:
loop wast_time
cmp dir,KEY_WRONG_DIR
jz user_press_no_dir_key
call Brick_goNext
user_press_no_dir_key:
mov dir,DIR_DOWN
call Brick_goNext
cmp game.ga_state,GS_OVER
jz GA_over
call ManyBrick_drawSelf
jmp GA_gameCircle_again
GA_over:
call doGameOver
ret
GA_gameCircle endp
;每次游戏开始时的初始化调用
GA_gameInit proc far
call clrScreen
;hide the cursor
mov ch,020h
mov cl,020h
mov ah,01h
int 10h
;初始化随机序列的第一个数,读取BIOS提供的当前秒
xor al,al
out 70h,al
in ax,71h
mov seed,ax
;初始化,如:得分,游戏状态,游戏地图
mov challenge,0
mov game.ga_score,0
mov game.ga_state,GS_RUNNING
lea di,game.ga_map
mov cx,GM_HEIGHT
cld
xor ax,ax
rep stosw
mov nextNO,0
call MB_gernicNext
call MB_gernicNext
call drawNextBrick
call moreBeautiful
;show some strings
mov si,offset scoreStr
mov dl,X_SCORE_STR
mov dh,Y_SCORE_STR
mov cx,6
call showStr
mov si,offset levelStr
mov dl,X_LEVEL_STR
mov dh,Y_LEVEL_STR
mov cx,6
call showStr
mov si,offset levelDeltStr
mov dl,X_adjustLevelDelt_STR
mov dh,Y_adjustLevelDelt_STR
mov cx,10
call showStr
mov si,offset modeStr
mov dl,X_MODE_STR
mov dh,Y_MODE_STR
mov cx,10
call showStr
mov si,offset usageStr
mov dl,-GM_LEFT
mov dh,-4
mov cx,usageStrCNT
call showStr
mov si,offset usageStrEx
mov dl,-GM_LEFT
mov dh,-3
mov cx,usageStrExCNT
call showStr
mov si,offset linkToCoderStr
mov dl,-GM_LEFT
mov dh,-2
mov cx,linkToCoderCNT
call showStr
;show some digitials
call showScore
call calcLevel
call showadjustLevelDelt
call showMode
ret
GA_gameInit endp
;全局初始化,调用一次,设置DS,ES指向同一个数据段,程序运行过程中不再改变
setDSAndES proc far
mov ax,MainData
mov ds,ax
mov es,ax
ret
setDSAndES endp
;判断游戏区域(dl,dh)位置是否为空
;in : dl-->x, dh-->y
;out : flag register
isPosNotEmpty proc
push dx
push bx
push ax
push cx
push di
push si
mov si,curMB
mov si,(ManyBrick ptr [si]).mb_bCnt
;ax--mask,第dl位置1
mov ax,1
mov cl,dl
shl ax,cl
lea di,game.ga_map
;map+2*dh
xor bh,bh
mov bl,dh
shl bl,1
only_one_brick:
and ax,[bx+di]
je is_pos_empty_out
cmp si,1
jne is_pos_empty_out
cmp bx,(2*GM_HEIGHT-2)
je is_pos_empty_out_pre
add bx,2
jmp only_one_brick
;ensure the result is correct
is_pos_empty_out_pre:
cmp bx,0
is_pos_empty_out:
pop si
pop di
pop cx
pop ax
pop bx
pop dx
ret
isPosNotEmpty endp
;判断游戏是否结束
isGameOver proc
push bx
mov bx,curMB
cmp (ManyBrick ptr [bx]).mb_sPos.pos_bY,Y_START
jne still_alive
;游戏的确结束了
mov game.ga_state,GS_OVER
call doGameOver
still_alive:
pop bx
ret
isGameOver endp
;游戏结束后,调用此过程,显示一些提示信息,待等用户下一步指示,重玩或退出
doGameOver proc
call clrScreen
call moreBeautiful
mov si,offset gameOverStr
mov cx,45
mov dl,X_GAME_OVER ;x
mov dh,Y_GAME_OVER ;y
call showStr
mov ax,game.ga_score
mov cx,43
call AXModCX
and ax,3
mov di,ax
shl di,1
mov cx,judgeCnt[di]
mov si,judgeTable[di]
mov dl,X_JUDGE_STR
mov dh,Y_JUDGE_STR
call showStr
mov al,CHAR_BRICK
wait_for_restart:
call randomDraw
call delay
jmp wait_for_restart
ret
doGameOver endp
;in : ax--ax0, cx--cx0
;out: ax=ax0/cx0, cx=ax0%cx0
AXModCX proc
push dx
xor dx,dx
div cx
mov cx,dx
pop dx
ret
AXModCX endp
;信手涂鸦
randomDraw proc
push dx
push bx
push ax
call getRand
mov cx,GM_WIDTH
call AXModCX
mov dl,cl
call getRand
mov cx,GM_HEIGHT
call AXModCX
mov dh,cl
call getRand
and al,7
or al,8
mov bl,al
pop ax
call drawBrick
pop bx
pop dx
ret
randomDraw endp
;游戏暂停时调用此过程,显示提示信息,按任意键继续
doGamePaused proc
push si
push cx
push dx
push ax
mov si,offset gamePausedStr
mov cx,46 ;46 chars
mov dl,0 ;x
mov dh,GM_HEIGHT/2;y
call showStr
call waitForKeyPress
mov game.ga_state,GS_RUNNING
mov dl,0
mov dh,GM_HEIGHT/2
mov al,CHAR_CLEAR
mov cx,46 ;46 chars
erase_paused_words:
mov bl,COLOR_CLEAR
call drawBrick
inc dl
loop erase_paused_words
call moreBeautiful
call drawMap
call ManyBrick_drawSelf
pop ax
pop dx
pop cx
pop si
ret
doGamePaused endp
;clear the screen
clrScreen proc
push ax
mov ah,00h
mov al,03h
int 10h
pop ax
ret
clrScreen endp
;游戏完成时跳转到此,表示对极富耐心者的景仰^_^,并退出游戏
doGameFinished:
call clrScreen
call moreBeautiful
mov si,offset gameFinishedStr
mov cx,58 ;58 chars
mov dl,-GM_LEFT+5
mov dh,-2
call showStr
dGF_keybuf_empty:
call getRand
call randomDraw
mov ah,1
int 16h
jz dGF_keybuf_empty
jmp main_quit
;等待直到有键被按下
waitForKeyPress proc
push ax
key_buf_empty:
mov ah,1
int 16h
jz key_buf_empty
;ignore the key just press
mov ah,0
int 16h
pop ax
ret
waitForKeyPress endp
;方块下落停止时,设置当前下落方块所占用的地图位置,并消除满行
lastBattle proc
call ManyBrick_setMap
call checkFull
ret
lastBattle endp
;若map数组相应为置位 则在相应位置显示一个方块
drawMap proc
push ax
push dx
push bx
push cx
push si
push di
lea si,game.ga_map
mov cx,GM_HEIGHT
xor dh,dh
drawMap_outer:
push cx
mov cx,GM_WIDTH
xor dl,dl
mov di,1
push si
mov si,[si]
mov ah,3
drawMap_inner:
mov bl,3
sub bl,ah
mov ah,bl
test si,di
jz clear_it
;draw a brick
mov al,CHAR_BRICK
mov bl,COLOR_DIED_BRICK
jmp draw_map_over
clear_it:
cmp mode,2
jne ignor_background
mov al,'|'
mov bl,ah
jmp draw_map_over
ignor_background:
mov al,CHAR_CLEAR
mov bl,COLOR_CLEAR
draw_map_over:
call drawBrick
inc dl
shl di,1
loop drawMap_inner
pop si
pop cx
add si,2
inc dh
loop drawMap_outer
pop di
pop si
pop cx
pop bx
pop dx
pop ax
ret
drawMap endp
;检查是否有满行的情况,满则消除,并增加得分...
checkFull proc
push ax
push bx
push cx
push dx
xor dx,dx ;此次能消除的行数
lea bx,game.ga_map
add bx,2*(GM_HEIGHT-1)
mov cx,GM_HEIGHT
check_full_again:
mov ax,[bx]
cmp ax,GM_MASK
jne brick_not_full
inc dx
call mapScrollDown
loop check_full_again
brick_not_full:
sub bx,2
loop check_full_again
test dx,dx
jz get_zero_score
;此次得分:2*行数-1
shl dx,1
dec dx
add game.ga_score,dx
call calcLevel
call showScore
get_zero_score:
pop dx
pop cx
pop bx
pop ax
ret
checkFull endp
;根据得分计算当前关数
calcLevel proc
push ax
push bx
push cx
mov bx,offset levelScoreLast
xor ah,ah
mov cx,LEVEL_LIMITT
add_level_again:
mov al,[bx]
cmp game.ga_score,ax
jae calc_level_out
dec bx
loop add_level_again
calc_level_out:
mov level,cx
cmp level,LEVEL_LIMITT
jb game_unfinished
add sp,6
jmp doGameFinished
game_unfinished:
call showLevel
pop cx
pop bx
pop ax
ret
calcLevel endp
;显示当前关
showLevel proc
push dx
push bx
push ax
mov bl,COLOR_NUMBER
mov dl,X_LEVEL_POS
mov dh,Y_LEVEL_POS
mov ax,level
call showInt
pop ax
pop bx
pop dx
ret
showLevel endp
;显示当前得分
showScore proc
push dx
push bx
push ax
mov bl,COLOR_NUMBER
mov dl,X_SCORE_POS
mov dh,Y_SCORE_POS
mov ax,game.ga_score
call showInt
pop ax
pop bx
pop dx
ret
showScore endp
;显示当前自动提升的关数
showAdjustLevelDelt proc
push dx
push bx
push ax
mov bl,COLOR_NUMBER
mov dl,X_adjustLevelDelt_POS
mov dh,Y_adjustLevelDelt_POS
mov ax,challenge
call showInt
pop ax
pop bx
pop dx
ret
showAdjustLevelDelt endp
showMode proc
push dx
push bx
push ax
mov bl,COLOR_NUMBER
mov dl,X_MODE_POS
mov dh,Y_MODE_POS
mov ax,mode
call showInt
call drawMap
pop ax
pop bx
pop dx
ret
ret
showMode endp
;在(dl,dh)为起始的位置显示ax中的一个整数
;in : ax--the integer to be show
; dl--x , dh--y;
showInt proc
push cx
push si
push di
xor di,di
mov cx,10
show_int_again:
inc di
push dx
xor dx,dx
;dx:ax /cx, ax ,dx
div cx
mov si,ax
mov al,dl
pop dx
add al,30h
call drawBrick
dec dl
mov ax,si
cmp ax,0
jnz show_int_again
cmp di,1
jne no_need_to_clear
mov al,CHAR_CLEAR
push bx
mov bl,COLOR_CLEAR
call drawBrick
pop bx
no_need_to_clear:
pop di
pop si
pop cx
ret
showInt endp
;在(X_NEXT_BRICK,Y_NEXT_BRICK)处显示下一个将要下落的方块s
drawNextBrick proc
push bx
push dx
;first clear the last draw
mov bx,curMB
mov dx,WORD ptr (ManyBrick ptr [bx]).mb_sPos.pos_bX
mov (ManyBrick ptr [bx]).mb_sPos.pos_bX ,X_NEXT_BRICK
mov (ManyBrick ptr [bx]).mb_sPos.pos_bY ,Y_NEXT_BRICK
call ManyBrick_clearCur
mov WORD ptr (ManyBrick ptr [bx]).mb_sPos.pos_bX,dx
;second draw the next-brick
mov bx,nextMB
mov dx,WORD ptr (ManyBrick ptr [bx]).mb_sPos.pos_bX
mov (ManyBrick ptr [bx]).mb_sPos.pos_bX ,X_NEXT_BRICK
mov (ManyBrick ptr [bx]).mb_sPos.pos_bY ,Y_NEXT_BRICK
xchg bx,curMB
call ManyBrick_drawSelf
xchg curMB,bx
mov WORD ptr (ManyBrick ptr [bx]).mb_sPos.pos_bX,dx
pop dx
pop bx
ret
drawNextBrick endp
;游戏区域对应map数组在bx行处下卷,即清除bx所在行
;in: bx --the line to be clear
mapScrollDown proc
push bx
push ax
push cx
dec cx
je scroll_over
push si
push di
mov di,bx
lea si,[di-2]
std
rep movsw
pop di
pop si
scroll_over:
mov game.ga_map,0
call drawMap
pop cx
pop ax
pop bx
ret
mapScrollDown endp
;根据当前下落的方块所在位置设置游戏区域所代表的map数组
ManyBrick_setMap proc
push ax
push bx
push cx
push dx
push si
push di
push bp
lea di,game.ga_map
mov bx,curMB
mov cx,(ManyBrick ptr [bx] ).mb_bCnt
lea si,(ManyBrick ptr [bx] ).mb_sBrick
lea bp,(ManyBrick ptr [bx]).mb_sPos
setMap_again:
mov dh,(Brick ptr [si]).b_sPos.pos_bY
add dh,ds:(Pos ptr[bp]).pos_bY
mov dl,(Brick ptr [si]).b_sPos.pos_bX
add dl,ds:(Pos ptr[bp]).pos_bX
call isPosLeagel
js setMap_ignore
cmp dh,0
js setMap_ignore
;map[dh]
mov bl,dh
shl bl,1
xor bh,bh
;bx--&map[dh]
lea bx,[bx+di]
mov ax,1
push cx
mov cl,dl
shl ax,cl
pop cx
or [bx],ax
setMap_ignore:
add si,size Brick
loop setMap_again
cmp mode,0
jz color_stay
call drawMap
color_stay:
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -