⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.asm

📁 俄罗斯方块用汇编语言编写 (1)执行的命令: ---------------------------------- ML /c /coff /Cp main.asm Link /subsy
💻 ASM
📖 第 1 页 / 共 2 页
字号:
                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 + -