📄 main.asm
字号:
mov al, byte ptr [esi]
mov byte ptr [edi], al
dec esi
dec edi
inc j
.endw
inc full_num
.endif
add addr_from, 10
add addr_to, 10
add mov_num, 10
inc i
inc edx
.endw
.if full_num > 0
.if full_num == 1
add Score, 100
.elseif full_num == 2
add Score, 300
.elseif full_num == 3
add Score, 600
.elseif full_num == 4
add Score, 1000
.endif
invoke wsprintf, addr StatusBuffer, addr StatusMsg, Score
invoke SendMessage, HStatus, SB_SETTEXT, 0, addr StatusBuffer
.endif
invoke _DrawView
invoke InvalidateRect, HMainWnd, NULL, FALSE
mov Act, XBREAK
invoke SetTimer, HMainWnd, ID_TIMER1, INTERVAL, NULL
ret
_RemoveRow endp
;--------------------------------------
; 方块下落, 返回值eax=TRUE表示可以下落,eax=FALSE表示不可以下落, 停,固定
;--------------------------------------
_Xdown proc uses ebx ecx edx esi edi
local i
local x, y ;将要落下的位置
local CanMove ;是否可以落下
local is_full ;一行中是否已经满了
local full_num ;有多少行满了
;循环判断4个方块都能不能落下
mov CanMove, TRUE
mov esi, offset Dots
mov i, 0
.while i < 4
mov ebx, [esi] ;行
inc ebx ;向下移动一格
add esi, 4
mov ecx, [esi] ;列
add esi, 4
invoke _GetMapChar, ebx, ecx
.if al == 'Q'
mov CanMove, FALSE
.break
.endif
inc i
.endw
;每个方格的位置加1
.if CanMove ;继续向下移动
inc CookyTop ;方块左上角的位置加1
mov esi, offset Dots
mov i, 0
.while i < 4
add dword ptr [esi], 1
add esi, 8
inc i
.endw
invoke _DrawView
invoke InvalidateRect, HMainWnd, NULL, FALSE
.else ;不能向下移动了,把下落的方块写入到游戏矩阵中
mov esi, offset Dots
mov i, 0
.while i < 4
mov ebx, [esi] ;行
add esi, 4
mov ecx, [esi] ;列
add esi, 4
invoke _SetMapChar, ebx, ecx
inc i
.endw
mov IsDrawCooky, FALSE
invoke _DrawView
invoke InvalidateRect, HMainWnd, NULL, FALSE
;分析哪些行可以被消去
mov al, 'N' ;先设置所有行都不能消去
mov edi, offset RowFull
mov ecx, 20
rep stosb
mov esi, offset Dots ;循环刚落下的东西占据的每一行
mov i, 0
mov full_num, 0
.while i < 4
mov eax, dword ptr [esi] ;行号
mov x, eax
mov y, 0
mov is_full, TRUE
.while y < 10 ;循环行中每个位置
invoke _GetMapChar, x, y
.if al == ' '
mov is_full, FALSE
.break
.endif
inc y
.endw
.if is_full ;如果这一行已经满了,把RowFull的标志设成'Y'
inc full_num
mov ebx, x
add ebx, offset RowFull
mov byte ptr [ebx], 'Y'
.endif
add esi, 8
inc i
.endw
.if full_num > 0 ;如果有满的
mov Act, XREMOVEROW ;下一步是消去
;invoke MessageBox, NULL, addr DgMsg, addr DgCaption, MB_OK
;invoke _RemoveRow
.else
mov Act, XNEW ;下一步是下落一个新物件
.endif
.endif
ret
_Xdown endp
;--------------------------------------
; WM_TIMER消息
;--------------------------------------
_OnTimer proc tid
.if tid == ID_TIMER1
.if Act == XNEW ;XNEW --> XDOWN --> XREMOVEROW --> XBREAK --> XNEW
invoke _NewCooky ;产生新物件
.elseif Act == XDOWN
invoke _Xdown
.elseif Act == XREMOVEROW
invoke _RemoveRow
.elseif Act == XBREAK
mov Act, XNEW
.endif
;invoke MessageBox, NULL, addr DgMsg, addr DgCaption, MB_OK
.endif
ret
_OnTimer endp
;--------------------------------------
; 方块左移
;--------------------------------------
_Xleft proc
local i
local x, y ;将要左移的位置
local CanMove ;是否可以左移
;循环判断4个方块都能不能左移
mov CanMove, TRUE
mov esi, offset Dots
mov i, 0
.while i < 4
mov ebx, [esi] ;行
add esi, 4
mov ecx, [esi] ;列
dec ecx ;左移动一格
add esi, 4
.if ecx > 9 ;如果移到外面了
;ecx是无符号数,当它=0时再减1得到一个很大的数,肯定>9
;invoke MessageBox, NULL, addr DgMsg, addr DgCaption, MB_OK
mov CanMove, FALSE
.break
.endif
invoke _GetMapChar, ebx, ecx
.if al == 'Q'
mov CanMove, FALSE
.break
.endif
inc i
.endw
;每个方格的列位置减1
.if CanMove
dec CookyLeft ;方块左上角的位置加1
mov esi, offset Dots
add esi, 4
mov i, 0
.while i < 4
dec dword ptr [esi]
add esi, 8
inc i
.endw
invoke _DrawView
invoke InvalidateRect, HMainWnd, NULL, FALSE
mov eax, TRUE
.else
mov eax, FALSE
.endif
ret
_Xleft endp
;--------------------------------------
; 方块右移
;--------------------------------------
_Xright proc
local i
local x, y ;将要左移的位置
local CanMove ;是否可以右移
;循环判断4个方块都能不能左移
mov CanMove, TRUE
mov esi, offset Dots
mov i, 0
.while i < 4
mov ebx, [esi] ;行
add esi, 4
mov ecx, [esi] ;列
inc ecx ;右移动一格
add esi, 4
.if ecx > 9 ;如果移到外面了
;invoke MessageBox, NULL, addr DgMsg, addr DgCaption, MB_OK
mov CanMove, FALSE
.break
.endif
invoke _GetMapChar, ebx, ecx
.if al == 'Q'
mov CanMove, FALSE
.break
.endif
inc i
.endw
;每个方格的列位置加1
.if CanMove
inc CookyLeft ;方块左上角的位置加1
mov esi, offset Dots
add esi, 4
mov i, 0
.while i < 4
inc dword ptr [esi]
add esi, 8
inc i
.endw
invoke _DrawView
invoke InvalidateRect, HMainWnd, NULL, FALSE
mov eax, TRUE
.else
mov eax, FALSE
.endif
ret
_Xright endp
;--------------------------------------
; WM_CHAR消息
;--------------------------------------
_OnChar proc char
.if char == VK_SPACE ;空格
.if IsTimer
mov IsTimer, FALSE
invoke KillTimer, HMainWnd, ID_TIMER1
.else
mov IsTimer, TRUE
invoke SetTimer, HMainWnd, ID_TIMER1, INTERVAL, NULL
.endif
;invoke MessageBox, NULL, addr DgMsg, addr DgCaption, MB_OK
.elseif char == VK_RETURN ;回车
;invoke MessageBox, NULL, addr DgMsg, addr DgCaption, MB_OK
invoke _NewGame
;invoke Test_NewCooky
.endif
ret
_OnChar endp
;--------------------------------------
; 按上箭头翻转,能翻转eax=TRUE, 不能翻转eax=FALSE
;--------------------------------------
_Xturn proc uses ebx edx esi edi
local x, y ;游戏矩阵上的位置(行,列)
local i, j ;物件4*4方格上的位置
local count ;计数, 达到4个方格就退出
local CanTurn ;是否可以翻转
local new_pose ;新的姿势
local box_start, pose_start ;新的下落物件的地址
mov eax, Pose
mov edx, 0
inc eax
mov ecx, 4
;invoke wsprintf, addr DgBuffer, addr DgMsg, ecx
;invoke MessageBox, NULL, addr DgBuffer, addr DgCaption, MB_OK
div ecx ;这个地方出错了
mov new_pose, edx ;循环下一个姿势
mov eax, new_pose
mov ebx, 16
mul ebx
mov pose_start, eax
mov eax, CookyNo
mov ebx, 64
mul ebx
mov box_start, eax
add eax, pose_start
add eax, offset Box
mov esi, eax ;esi是存放物件结构的数据的地址
mov ebx, CookyTop
mov x, ebx
mov i, 0
mov count, 1
mov edi, offset Dots2 ;把行列位置放到edi指定的地方去,临时位置
.while i < 4
mov j, 0
mov ebx, CookyLeft
mov y, ebx
.while j < 4
mov bl, [esi]
.if bl == 'X'
;先判断矩阵上是否有位置
.if x > 19
mov CanTurn, FALSE ;行越界
jmp @F
.endif
.if y > 9
mov CanTurn, FALSE ;列越界
jmp @F
.endif
invoke _GetMapChar, x, y
.if al == 'Q'
mov CanTurn, FALSE ;该位置已占用
jmp @F
.endif
mov edx, x ;行
mov [edi], edx ;还要这样赋值
add edi, 4
mov edx, y ;列
mov [edi], edx
add edi, 4
inc count
.if count > 4 ;已经够了4个方格, 怕不小心Dots越界
jmp @F
.endif
.endif
inc j
inc y
inc esi
.endw
inc i
inc x
.endw
@@:
.if CanTurn
mov ebx, new_pose
mov Pose, ebx
;串传送,把新Dots2中的位置坐标传送到Dots中去
mov ecx, 8
mov esi, offset Dots2
mov edi, offset Dots
rep movsd
invoke _DrawView
invoke InvalidateRect, HMainWnd, NULL, FALSE
mov eax, TRUE
.else
mov eax, FALSE
.endif
ret
_Xturn endp
;--------------------------------------
; 窗口过程
;--------------------------------------
_OnKeyDown proc key
.if key == VK_LEFT
;invoke MessageBox, NULL, addr DgMsg, addr DgCaption, MB_OK
invoke _Xleft
.elseif key == VK_RIGHT
invoke _Xright
.elseif key == VK_UP
invoke _Xturn
.elseif key == VK_DOWN
invoke _Xdown
.endif
ret
_OnKeyDown endp
;--------------------------------------
; 窗口过程
;--------------------------------------
_ProcWinMain proc hWnd, uMsg, wParam, lParam
mov eax, uMsg
.if uMsg == WM_CREATE
;invoke _OnCreate
.elseif eax == WM_PAINT
invoke _OnPaint
.elseif eax == WM_CLOSE
invoke _OnClose
.elseif eax == WM_CHAR
invoke _OnChar, wParam
.elseif eax == WM_TIMER
invoke _OnTimer, wParam
.elseif eax == WM_KEYDOWN
invoke _OnKeyDown, wParam
.else
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.endif
xor eax, eax
ret
_ProcWinMain endp
;--------------------------------------
;创建主窗口
;--------------------------------------
_WinMain proc
local stWndClass: WNDCLASSEX
local stMsg: MSG
invoke GetModuleHandle, NULL
mov HInstance, eax
; 注册窗口类
invoke RtlZeroMemory, addr stWndClass, sizeof stWndClass
invoke LoadCursor, 0, IDC_ARROW
mov stWndClass.hCursor, eax
push HInstance
pop stWndClass.hInstance
mov stWndClass.cbSize, sizeof WNDCLASSEX
mov stWndClass.style, CS_HREDRAW or CS_VREDRAW
mov stWndClass.lpfnWndProc, offset _ProcWinMain
mov stWndClass.hbrBackground, COLOR_BTNFACE + 1
mov stWndClass.lpszClassName, offset szClassName
invoke RegisterClassEx, addr stWndClass
; 建立并显示窗口
invoke CreateWindowEx, \
WS_EX_CLIENTEDGE, \
offset szClassName, \
offset szCaptionMain, \
WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_VISIBLE, \
300, 0, WndWidth, WndHeight, \
NULL, \
NULL, \
HInstance, \
NULL
mov HMainWnd, eax
;invoke wsprintf, addr DgBuffer, addr DgMsg2, HMainWnd
;invoke MessageBox, NULL, addr DgBuffer, addr DgCaption, MB_OK
invoke _CreateOther
invoke ShowWindow, HMainWnd, SW_SHOWNORMAL
invoke UpdateWindow, HMainWnd
; 消息循环
.while TRUE
invoke GetMessage, addr stMsg, NULL, 0, 0
.break .if eax == 0
invoke TranslateMessage, addr stMsg
invoke DispatchMessage, addr stMsg
.endw
ret
_WinMain endp
;--------------------------------------
;程序开始
;--------------------------------------
start:
call _WinMain
;......................................
;调试
;invoke Test_IndexToCoord
;......................................
invoke ExitProcess, NULL
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -