河北联合大学汇编课设报告正文.docx
《河北联合大学汇编课设报告正文.docx》由会员分享,可在线阅读,更多相关《河北联合大学汇编课设报告正文.docx(34页珍藏版)》请在冰豆网上搜索。
河北联合大学汇编课设报告正文
一、软件背景介绍
1.1背景知识
俄罗斯方块原本是前苏联科学家阿列克谢·帕基特诺夫所开发的教育用软件,之后开始提供授权给各个游戏公司,造成各平台上软件大量发行的现象。
GameBoy版的俄罗斯方块在日本卖出424万套,是GameBoy史上卖最好的游戏。
海湾战争时,也是前线美军最常拿消磨时间的游戏之一。
由于俄罗斯方块具有的数学性、动态性与知名度,也经常拿来作为游戏程序设计的练习题材。
俄罗斯方块曾经造成的轰动与带来的经济价值,可以说是世界游戏史上的一个奇迹。
它看似简单却又变化无穷,令人上瘾。
相信大多数用户都还记得为它痴迷得“茶不思饭不想”的那个俄罗斯方块时代。
俄罗斯方块上手极其简单,但是要熟练地掌握其中的操作与摆放技巧,难度却不低。
作为家喻户晓老少皆宜的大众游戏,其普及程度可以说是史上任何一款游戏都无法相比的。
俄罗斯方块(Tetris,俄文:
Тетрис)是一款风靡全球的电视游戏机和掌上游戏机游戏,它由俄罗斯人阿列克谢·帕基特诺夫发明,故得此名。
俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。
由于上手简单、老少皆宜,从而家喻户晓,风靡世界。
俄罗斯方块原名是俄语Тетрис(英语是Tetris),这个名字来源于希腊语tetra,意思是“四”,而游戏的作者最喜欢网球(tennis)。
于是,他把两个词tetra和tennis合而为一,命名为Tetris,这也就是俄罗斯方块名字的由来。
1.2基本功能
部分游戏有单格方块,可以穿透固定的方块到达最下层空位。
其他的改版中出现更多特别的造型。
方块会从区域上方开始缓慢继续落下。
玩家可以做的操作有:
以90度为单位旋转方块,以格子为单位左右移动方块,让方块加速落下。
方块移到区域最下方或是着地到其他方块上无法移动时,就会固定在该处,而新的方块出现在区域上方开始落下。
当区域中某一列横向格子全部由方块填满,则该列会消失并成为玩家的得分。
同时删除的列数越多,得分指数上升。
当固定的方块堆到区域最上方而无法消除层数时,则游戏结束。
1.3运行截图
图1运行截图
图2运行截图
图3运行截图
二、核心算法思想
游戏区域由许多等面积的小方块构成,这些区域状态只有满或空两种。
将空间以静态二维数组实现,并预先定义其状态值。
满为1,空为0,以此来完成游戏地图区域的空间分配。
小方块的实现是由一个4*2的小数组表示,用四个存储单位空间存储当前下坠物的每一个子块的位置来对整个下坠物件的位置进行标识,每个存储空间的大小就是一个点的坐标。
每个方块都有其对应的编号,编号按由上到下,由左到右的顺序编排。
有了这些编号,方块的变换实现起来就方便多了。
再由一个宏去标识下坠物的位置。
游戏进程需要定时器的驱动,所以很有必要在程序当中加入一个定时器机制。
如此对游戏的开始,暂停,结束控制便能够得到实现。
游戏开始后便开始掉落方块,并且会在游戏区域上方出现下一个下坠物的形态,因此有随机物件产生这个操作。
此时用户可根据需要来变换方块,向左或向右移动来调整方块位置,然后通过按下使方块加速下落。
这就涉及到了四个主要操作。
当方块向左或向右移动时,需要判定方块是否达到了游戏区域的边界;当方块下落时需要判定方块是否到了游戏区域的底部,或是碰到了别的方块。
这样游戏内部便引入众多相关函数。
对这些函数进行实现和细化之前,需要对整个游戏运行期间的概要流程有所了解。
本游戏界面简洁明了,没有什么花哨的东西。
菜单栏功能并不复杂,仅有游戏控制和选项设置两项。
进入游戏后的窗口背景是黑色调,游戏区域是灰色调,这些都可以通过选项进行调整。
游戏区域有20列,10行,这样设计是为了让方框有足够的高度,可以让玩家有充足的反应时间来处理掉落的方块。
游戏开始后默认的方块是具有立体感的红色方块,其颜色和质感都是经过精心设计的。
而在上方会显示将要落下的方块,让玩家做好迎接挑战的心理准备,下方则显示分数。
游戏的操作主要由鼠标和键盘来完成。
鼠标点击开始后便可用键盘上的“上下左右”来对方块进行操作。
方块的实现七种下坠物都有一个共同点,就是它们占据的空间一样,都是由四个等面积的小方块构成,因此用一个整型的数组来存储每个下坠物的四个小方块的坐标位置。
每个下坠物中的方块都有编号,编号按从左到右,从上到下的顺序排列。
从代码中可以看出程序首先获取了当前下坠物的四个小方块坐标,然后所有纵坐标递减一格,由函数计算出改变数据的区域。
这样便可完成左移命令。
右移和下移的道理也是一样。
但是这里涉及到一个问题,就是要对移动是否到达游戏区域的边界做出判断。
左、右移的限制原理是一样的,只是方向和坐标数据有点区别。
根据各种不同形态的下坠物最左边的小方块的正左(右)方区域是否为非被占用状态来判断它是否可以移动。
而下移的限制涉及到消行判断,这些将在后面做具体分析。
方块的旋转操作需要考虑到两个问题,一个是如何实现旋转,另一个是判断能否旋转。
为了实现旋转,首先获取当前下坠物的四个小方块的坐标位置。
由于每种方块变形后的状态都不同,因此需要对下坠物的不同形态进行编号。
3、核心算法流程图
进入程序后先进行屏幕初始化,之后显示调用显示边框函数,再显示新方块。
检测按键状态,之后再度检测键盘状态。
图4流程控制算法流程图
为了保证整个程序结构性能良好,不会出现与其他函数体同时用一个寄存器而使得程序跑飞。
在进入程序后先将几个主要寄存器推入堆栈,当程序退出时,又将寄存器值从堆栈中送回。
堆栈采用的是先进后出的算法,所以应当注意顺序。
这样接口,便于向后兼容,使用起来方便。
图5流程控制算法流程图
四、源代码
下面给出的是用俄罗斯游戏实现程序的源代码:
;游戏状态
GS_RUNNINGequ0
GS_PAUSEDequ1
GS_OVERequ2
;最高可达到的关数
LEVEL_LIMITTequ15
;游戏区域起始位置及大小
GM_LEFTequ25
GM_TOPequ4
GM_WIDTHequ12
GM_HEIGHTequ20
GM_MASKequ(1SHLGM_WIDTH-1)
;功能键扫描码
KEY_ESCequ1h;ESC
KEY_LEFTequ4bh;LEFT
KEY_RIGHTequ4dh;RIGHT
KEY_ROLATEequ48h;UP
KEY_DOWNequ50h;DOWN
KEY_QUICKLYequ3dh;F3
KEY_SLOW_DOWNequ3ch;F2
KEY_TURNequ4fh;End
KEY_PAUSEequ53h;Delete
KEY_CHANG_MODEequ3bh;F1
CHAR_CLEARequ'';擦除字符,ascii
CHAR_BRICKequ2;方块外形,ascii
;0黑1深蓝2绿3蓝4红5紫6黄7灰白,最高位置1则高亮显示
COLOR_CLEARequ0h
COLOR_DIED_BRICKequ08h
COLOR_TITTLEequ7;
COLOR_NUMBERequ3or8
;屏幕上各说明文字或装饰物的坐标,皆为相对游戏场地左上角
X_NEXT_BRICKequ-5
Y_NEXT_BRICKequ3
Y_LBOUND_CHARequ17
Y_RBOUND_CHARequ16
Y_BOUND_COLORequ2or8;blue
X_UBOUND_CHARequ15
X_DBOUND_CHARequ15
X_BOUND_COLORequ2or8;green
X_STARTequ(GM_WIDTH-1)/2
Y_STARTequ-1
X_SCORE_STRequ-10
X_LEVEL_STRequX_SCORE_STR
X_adjustLevelDelt_STRequX_SCORE_STR-4
X_MODE_STRequX_SCORE_STR-4
Y_SCORE_STRequ5
Y_LEVEL_STRequY_SCORE_STR+2
Y_adjustLevelDelt_STRequY_LEVEL_STR+2
Y_MODE_STRequY_adjustLevelDelt_STR+2
X_SCORE_POSequ-3
X_LEVEL_POSequX_SCORE_POS
X_adjustLevelDelt_POSequX_SCORE_POS
X_MODE_POSequX_SCORE_POS
Y_SCORE_POSequY_SCORE_STR+1
Y_LEVEL_POSequY_LEVEL_STR+1
Y_adjustLevelDelt_POSequY_adjustLevelDelt_STR+1
Y_MODE_POSequY_MODE_STR+1
X_GAME_OVERequ-10
X_JUDGE_STRequX_GAME_OVER+5
X_GAME_NAMEequGM_WIDTH/2-4
Y_GAME_NAMEequ-1
Y_GAME_OVERequ-3
Y_JUDGE_STRequY_GAME_OVER+1
;判断游戏区域(dl,dh)位置是否为空
;in:
dl-->x,dh-->y
;out:
flagregister
isPosNotEmptyproc
pushdx
pushbx
pushax
pushcx
pushdi
pushsi
movsi,curMB
movsi,(ManyBrickptr[si]).mb_bCnt
;ax--mask,第dl位置1
movax,1
movcl,dl
shlax,cl
leadi,game.ga_map
;map+2*dh
xorbh,bh
movbl,dh
shlbl,1
only_one_brick:
andax,[bx+di]
jeis_pos_empty_out
cmpsi,1
jneis_pos_empty_out
cmpbx,(2*GM_HEIGHT-2)
jeis_pos_empty_out_pre
addbx,2
jmponly_one_brick
;ensuretheresultiscorrect
is_pos_empty_out_pre:
cmpbx,0
is_pos_empty_out:
popsi
popdi
popcx
popax
popbx
popdx
ret
isPosNotEmptyendp
;判断游戏是否结束
isGameOverproc
pushbx
movbx,curMB
cmp(ManyBrickptr[bx]).mb_sPos.pos_bY,Y_START
jnestill_alive
;游戏的确结束了
movgame.ga_state,GS_OVER
calldoGameOver
still_alive:
popbx
ret
isGameOverendp
;游戏结束后,调用此过程,显示一些提示信息,待等用户下一步指示,重玩或退出
doGameOverproc
callclrScreen
callmoreBeautiful
movsi,offsetgameOverStr
movcx,45
movdl,X_GAME_OVER;x
movdh,Y_GAME_OVER;y
callshowStr
movax,game.ga_score
movcx,43
callAXModCX
andax,3
movdi,ax
shldi,1
movcx,judgeCnt[di]
movsi,judgeTable[di]
movdl,X_JUDGE_STR
movdh,Y_JUDGE_STR
callshowStr
moval,CHAR_BRICK
wait_for_restart:
callrandomDraw
calldelay
jmpwait_for_restart
ret
doGameOverendp
;in:
ax--ax0,cx--cx0
;out:
ax=ax0/cx0,cx=ax0%cx0
AXModCXproc
pushdx
xordx,dx
divcx
movcx,dx
popdx
ret
AXModCXendp
randomDrawproc
pushdx
pushbx
pushax
callgetRand
movcx,GM_WIDTH
callAXModCX
movdl,cl
callgetRand
movcx,GM_HEIGHT
callAXModCX
movdh,cl
callgetRand
andal,7
oral,8
movbl,al
popax
calldrawBrick
popbx
popdx
ret
randomDrawendp
;游戏暂停时调用此过程,显示提示信息,按任意键继续
doGamePausedproc
pushsi
pushcx
pushdx
pushax
movsi,offsetgamePausedStr
movcx,46;46chars
movdl,0;x
movdh,GM_HEIGHT/2;y
callshowStr
callwaitForKeyPress
movgame.ga_state,GS_RUNNING
movdl,0
movdh,GM_HEIGHT/2
moval,CHAR_CLEAR
movcx,46;46chars
erase_paused_words:
movbl,COLOR_CLEAR
calldrawBrick
incdl
looperase_paused_words
callmoreBeautiful
calldrawMap
callManyBrick_drawSelf
popax
popdx
popcx
popsi
ret
doGamePausedendp
;clearthescreen
clrScreenproc
pushax
movah,00h
moval,03h
int10h
popax
ret
clrScreenendp
;游戏完成时跳转到此,表示对极富耐心者的景仰^_^,并退出游戏
doGameFinished:
callclrScreen
callmoreBeautiful
movsi,offsetgameFinishedStr
movcx,58;58chars
movdl,-GM_LEFT+5
movdh,-2
callshowStr
dGF_keybuf_empty:
callgetRand
callrandomDraw
movah,1
int16h
jzdGF_keybuf_empty
jmpmain_quit
;等待直到有键被按下
waitForKeyPressproc
pushax
key_buf_empty:
movah,1
int16h
jzkey_buf_empty
;ignorethekeyjustpress
movah,0
int16h
popax
ret
waitForKeyPressendp
;方块下落停止时,设置当前下落方块所占用的地图位置,并消除满行
lastBattleproc
callManyBrick_setMap
callcheckFull
ret
lastBattleendp
;若map数组相应为置位则在相应位置显示一个方块
drawMapproc
pushax
pushdx
pushbx
pushcx
pushsi
pushdi
leasi,game.ga_map
movcx,GM_HEIGHT
xordh,dh
drawMap_outer:
pushcx
movcx,GM_WIDTH
xordl,dl
movdi,1
pushsi
movsi,[si]
movah,3
drawMap_inner:
movbl,3
subbl,ah
movah,bl
testsi,di
jzclear_it
;drawabrick
moval,CHAR_BRICK
movbl,COLOR_DIED_BRICK
jmpdraw_map_over
clear_it:
cmpmode,2
jneignor_background
moval,'|'
movbl,ah
jmpdraw_map_over
ignor_background:
moval,CHAR_CLEAR
movbl,COLOR_CLEAR
draw_map_over:
calldrawBrick
incdl
shldi,1
loopdrawMap_inner
popsi
popcx
addsi,2
incdh
loopdrawMap_outer
popdi
popsi
popcx
popbx
popdx
popax
ret
drawMapendp
;检查是否有满行的情况,满则消除,并增加得分...
checkFullproc
pushax
pushbx
pushcx
pushdx
xordx,dx;此次能消除的行数
leabx,game.ga_map
addbx,2*(GM_HEIGHT-1)
movcx,GM_HEIGHT
check_full_again:
movax,[bx]
cmpax,GM_MASK
jnebrick_not_full
incdx
callmapScrollDown
loopcheck_full_again
brick_not_full:
subbx,2
loopcheck_full_again
testdx,dx
jzget_zero_score
;此次得分:
2*行数-1
shldx,1
decdx
addgame.ga_score,dx
callcalcLevel
callshowScore
get_zero_score:
popdx
popcx
popbx
popax
ret
checkFullendp
;根据得分计算当前关数
calcLevelproc
pushax
pushbx
pushcx
movbx,offsetlevelScoreLast
xorah,ah
movcx,LEVEL_LIMITT
add_level_again:
moval,[bx]
cmpgame.ga_score,ax
jaecalc_level_out
decbx
loopadd_level_again
calc_level_out:
movlevel,cx
cmplevel,LEVEL_LIMITT
jbgame_unfinished
addsp,6
jmpdoGameFinished
game_unfinished:
callshowLevel
popcx
popbx
popax
ret
calcLevelendp
;显示当前关
showLevelproc
pushdx
pushbx
pushax
movbl,COLOR_NUMBER
movdl,X_LEVEL_POS
movdh,Y_LEVEL_POS
movax,level
callshowInt
popax
popbx
popdx
ret
showLevelendp
;显示当前得分
showScoreproc
pushdx
pushbx
pushax
movbl,COLOR_NUMBER
movdl,X_SCORE_POS
movdh,Y_SCORE_POS
movax,game.ga_score
callshowInt
popax
popbx
popdx
ret
showScoreendp
;显示当前自动提升的关数
showAdjustLevelDeltproc
pushdx
pushbx
pushax
movbl,COLOR_NUMBER
movdl,X_adjustLevelDelt_POS
movdh,Y_adjustLevelDelt_POS
movax,challenge
callshowInt
popax
popbx
popdx
ret
showAdjustLevelDeltendp
showModeproc
pushdx
pushbx
pushax
movbl,COLOR_NUMBER
movdl,X_MODE_POS
movdh,Y_MODE_POS
movax,mode
callshowInt
calldrawMap
popax
popbx
popdx
ret
ret
showModeendp
;在(dl,dh)为起始的位置显示ax中的一个整数
;in:
ax--theintegertobeshow
;dl--x,dh--y;
showIntproc
p