没啥子技术含量。。。但绝对是本人原创,道理很简单,网上的博客我发过这个帖子,不过.inc文件没有发布,所以只有我有
http://images.cnblogs.com/cnblogs_com/originality/rgame.jpg
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 俄罗斯方块 by Originality
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap : none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include rgame.inc
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 定时器测试
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DwonTest proc _hWnd, _uMsg, _idEvent, _dwTime

    pushad
 
    mov    eax, curState
    .if    eax        ;下落结束
     
        mov    curState, 0
        invoke    InitControl1
     
    .else
     
        invoke    Control1Down
     
    .endif
 
    popad
    ret

DwonTest endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain proc uses ebx edi esi hWnd, uMsg, wParam, lParam
    local    @stPs : PAINTSTRUCT
    local    @stRect : RECT
    local    @hDc

    mov    eax, uMsg
;********************************************************************
    .if    eax == WM_PAINT 
 
        invoke    BeginPaint, hWnd, addr @stPs
        invoke    InitContainer
        invoke    ShowControl, 1
        invoke    Control1Down
        invoke     EndPaint, hWnd, addr @stPs     

    .elseif    eax == WM_CREATE
         
        invoke    GetDC, hWnd
        mov    hGame, eax
        ;【此处定时器为测试所用】
        invoke    SetTimer, NULL, NULL, 1000, offset DwonTest

    .elseif    eax == WM_CLOSE
         
        invoke    ReleaseDC, hWnd, hGame
        invoke     DestroyWindow, hWinMain
        invoke     PostQuitMessage, NULL
         
    .elseif    eax == WM_SIZE
     
        invoke    ValidateRect, hWnd, offset gameArea

    .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    ;以0填充WNDCLASSEX结构体

********************************************************************
; 注册窗口类
;********************************************************************
    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_WINDOW + 3    ;设置窗体背景色
    mov    @stWndClass.lpszClassName, offset szClassName    ;保存窗体类名
    invoke     RegisterClassEx, addr @stWndClass        ;注册窗口类
;********************************************************************
; 建立并显示窗口
;********************************************************************
    invoke     CreateWindowEx, WS_EX_TOOLWINDOW, offset szClassName, offset szCaptionMain,\
                   WS_OVERLAPPEDWINDOW,\
                   100, 100, 400, 456,\
                   NULL, NULL, hInstance, NULL            ;建立窗口
    mov    hWinMain, eax                    ;保存窗口句柄 
    invoke     ShowWindow, hWinMain, SW_SHOWNORMAL        ;显示窗口
    invoke     UpdateWindow, hWinMain                ;更新窗口
;********************************************************************
; 消息循环
;********************************************************************
    .while    TRUE                        ;消息循环
         
        invoke     GetMessage, addr @stMsg, NULL, 0, 0        ;获取消息并填充MSG结构体
     
            .break .if    eax == 0                ;判断是否退出
            invoke     TranslateMessage, addr @stMsg        ;消息装换
            invoke     DispatchMessage, addr @stMsg        ;分发消息
         
        .endw
        ret

_WinMain endp

;********************************************************************
; 初始化游戏容器
;********************************************************************
InitContainer proc
    local @lpRect : RECT
 
    pushad
 
    ;建立游戏容器边框
    invoke    CreatePen, PS_SOLID, 5, 8000FFh
    push    eax
    invoke    SelectObject, hGame, eax
    invoke    DeleteObject, eax
    pop    eax
    invoke    FrameRect, hGame, offset gameArea,  eax
 
    popad
    ret

InitContainer endp

;********************************************************************
; 显示方块控件
; type:控件类型1为4格横条,2为田字形,3..4..
;********************************************************************
ShowControl proc cType : DWORD

    pushad
 
    .if    cType == 1    ;4格横条■■■■
     
        invoke    InitControl1
     
    .endif
 
    popad
    ret
 
ShowControl endp

;********************************************************************
; 初始化■■■■图形
;********************************************************************
InitControl1 proc

    pushad
 
    ;设置方块颜色
    invoke    SetColor, 0FF80FFh, 400040h
    ;创建方块并排列方块
    mov    ecx, 60        ;左上角起始位置
    mov    edx, 90        ;右下角起始位置
    xor    esi, esi
    lea    ebx, curControl
@@:
    cmp    ecx, 180
    jz    @F        ;4个方块都初始化完毕
    push    ebx
    push    ecx
    push    edx
    invoke    Rectangle, hGame, ecx, 5, edx, 30
    pop    edx
    pop    ecx
    pop    ebx
    mov    [ebx + esi], ecx
    push    topSpace
    pop    DWORD ptr [ebx + esi + 4]
    add    esi, 8
    add    ecx, 30
    add    edx, 30
    jmp    @B
 
@@:

    popad
    ret

InitControl1 endp

;********************************************************************
; 设置方块颜色
;********************************************************************
SetColor proc color : DWORD, pColor : DWORD

    pushad
 
    invoke    CreatePen, PS_SOLID, 1, pColor
    invoke    SelectObject, hGame, eax
    invoke    DeleteObject, eax
    invoke    CreateSolidBrush, color
    invoke    SelectObject, hGame, eax
    invoke    DeleteObject, eax
 
    popad
    ret

SetColor endp

;********************************************************************
; ■■■■图形向下走动
;********************************************************************
Control1Down proc

    pushad
 
    invoke    IsDownEnd
    .if     eax == 1    ;下面有障碍,改变状态为创建新的方块并保存当前方块在容器中的位置
     
        mov    curState, 1
        invoke    ChangeAreaState
        invoke    RtlZeroMemory, offset curControl, sizeof curControl
        popad
        ret

    .endif 
 
    ;如果下面不是障碍,则■■■■向下走动
    lea    edx, curControl
    xor    ecx, ecx
@@:
    cmp    ecx, 4
    jz    @F
    ;覆盖原有的方块
    push    ecx
    invoke    SetColor, 0h, 0h
    mov    eax, [edx + ecx * 8 + 4]
    mov    ebx, 30
    add    ebx, eax    ;ebx右下角y坐标
    mov    eax, [edx + ecx * 8]
    add    eax, 30        ;eax为右下角x坐标
    push    eax        ;保存右下角坐标
    push    ebx
    push    edx
    invoke    Rectangle, hGame, [edx + ecx * 8], [edx + ecx * 8 + 4], eax, ebx
    pop    edx
 
    ;生成新的方块
    invoke    SetColor, 0FF80FFh, 400040h
    pop    ebx
    pop    eax
    pop    ecx 
    add     DWORD ptr [edx + ecx * 8 + 4], 30
    add    ebx, 30
    push    ecx
    push    edx
    invoke    Rectangle, hGame, [edx + ecx * 8], [edx + ecx * 8 + 4], eax, ebx
    pop    edx
    pop    ecx
    inc    ecx
    jmp    @B
@@:
 
    popad
    ret

Control1Down endp

;********************************************************************
; 保存当前方块在容器中的状态
;********************************************************************
ChangeAreaState proc
 
    pushad
 
    ;计算区域单元坐标
    lea    ebx, curControl
    xor    ecx, ecx
@@:
    cmp    ecx, 4
    jz    @F
 
    ;计算二维x坐标
    invoke    CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 1
    mov    esi, eax
 
    ;计算二维y坐标
    invoke    CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 2
    mov    edi, eax
 
    ;设置区域更新,更新的坐标位置(eax + esi * 4 * 8 + edi * 4)
    lea    eax, area
    push    eax
    xchg    edi, eax
    mov    edi, 8
    mul    edi
    add    esi, eax
    pop    eax
    mov    DWORD ptr [eax + esi * 4], 1    ;设置当前位置已经被填充
    inc    ecx
    jmp    @B
@@: 

    popad
    ret
 
ChangeAreaState endp

;********************************************************************
; 根据顶角计算二维坐标
; left, top:顶角像素
; posType:1表示计算x坐标,2表示计算y坐标
; eax返回二维坐标
;********************************************************************
CalculatePos proc left : DWORD, top :DWORD, posType : DWORD
    local @ret : DWORD
    pushad
  
    mov    edx, left  
    add    edx, rectArea ;右下角x坐标
  
    mov    ecx, top
    add    ecx, rectArea ;右下角y坐标
  
    .if    posType == 1
      
        mov    eax, edx
        mov    ebx, 30
        xor    edx, edx
        div    ebx
      
    .elseif
      
        mov    eax, ecx
        sub    eax, topSpace
        mov    ecx, 30
        xor    edx, edx
        div    ecx
      
    .endif
    mov    @ret, eax
    popad
    mov    eax, @ret
    dec    eax
    ret

CalculatePos endp

;********************************************************************
; 判断下面是否有障碍
; 返回值::eax为1表示下落完毕,为0表示未完毕
;********************************************************************
IsDownEnd proc

    pushad
  
    lea    ebx, curControl
    xor    ecx, ecx
@@:
    cmp    ecx, 4
    jz    @F
  
    ;计算二维x坐标
    invoke    CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 1
    mov    esi, eax
  
    ;计算二维y坐标
    invoke    CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 2
    mov    edi, eax
    inc    edi
  
    ;设置区域更新,更新的坐标位置(eax + esi * 4 * 8 + edi * 4)
    lea    eax, area
    push    eax
    xchg    edi, eax
    mov    edi, 8
    mul    edi
    add    esi, eax
    pop    eax
    mov    edx, [eax + esi * 4]
    .if    edx == 1
      
        popad
        mov    eax, 1
        ret
      
    .endif
    inc    ecx
    jmp    @B
@@:  
  
    popad
    xor    eax, eax
    ret

IsDownEnd endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
    call    _WinMain
    invoke     ExitProcess, NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start

  • 标 题:答复
  • 作 者:tufuzi
  • 时 间:2009-08-06 13:09:56

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include    windows.inc
include    gdi32.inc
include    user32.inc
include    kernel32.inc

includelib  gdi32.lib
includelib  user32.lib
includelib  kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance  dd  ?
hWinMain  dd  ?
curType    dd   ?    ;当前图形
curControl  dd     8 dup (?)  ;当前控件左上顶点坐标集
netxType  dd   ?    ;下一个图形
hGame    dd   ?    ;游戏区DC
hTimer    dd  ?

.const
szClassName  db  'Ogame',0
szCaptionMain  db  '仿俄罗斯方块',0
rectArea  dd  30    ;每个方块的大小为30*30像素
topSpace  dd  5    ;顶端偏差值

.data
gameArea  RECT    <0, 0, 242, 426>
curState  dd  0    ;当前控件移动状态,1代表下落结束,0代表下落过程中
curKey    dd  0    ;当前方向按键
curDir    dd  0    ;图片当前方向,对于■■■■0表示横着,1表示竖着
area    dd  112 dup (?)
    dd  8 dup (1)
gamePoint  dd  0

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 函数定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
InitContainer proto
InitControl1 proto
ShowControl proto :DWORD
SetColor proto :DWORD, :DWORD
Control1Down proto
ChangeAreaState proto
CalculatePos proto :DWORD, :DWORD, :DWORD 
IsDownEnd proto
RLDown proto :DWORD
IsRLDownEnd proto :DWORD
ChangeC1 proto
ClearCur proto
GetPoint proto

刚把rgame.inc找出来

  • 标 题:答复
  • 作 者:tufuzi
  • 时 间:2009-08-06 14:27:28

刚才自己又看了一下,才发现这个好像不是最后的版本,虽然没写完,但是向下,向左,向右移动,还有填满后清除方块都写了。。。原来这个是很早的,这里才是一个图形完整的处理。其他的图形我没写,其实处理差不多,所以当时也就没兴趣了
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 俄罗斯方块 by Originality
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap : none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include rgame.inc
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 定时器测试
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DwonTest proc _hWnd, _uMsg, _idEvent, _dwTime

  pushad
  
  mov  eax, curState
  .if  eax    ;下落结束
    
    mov  curState, 0
    invoke  InitControl1
    
  .else
    
    .if  curKey == VK_RIGHT  ;向右移动
    
      invoke   RLDown, 1
      mov  curKey, 0
    
    .elseif curKey == VK_LEFT  ;向左移动
    
      invoke   RLDown, 0
      mov  curKey, 0
    
;    .elseif  curKey == VK_DOWN  ;加速
;      
;      mov  curKey, 0
      
    .elseif curKey == VK_UP    ;转向
      
      invoke  ChangeC1
      invoke  Control1Down
      mov  curKey, 0
      
    .else
      
      mov  curDir, 0
      invoke  Control1Down
    
    .endif
    
  .endif
  
  popad
  ret

DwonTest endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain proc uses ebx edi esi hWnd, uMsg, wParam, lParam
  local  @stPs : PAINTSTRUCT
  local  @stRect : RECT
  local  @hDc

  mov  eax, uMsg
;********************************************************************
  .if  eax == WM_PAINT  
  
    invoke  BeginPaint, hWnd, addr @stPs
    invoke  InitContainer
    invoke  ShowControl, 1
    invoke  Control1Down
    invoke   EndPaint, hWnd, addr @stPs    

  .elseif  eax == WM_KEYDOWN
    
    push  wParam
    pop  curKey

  .elseif  eax == WM_CREATE
      
    invoke  GetDC, hWnd
    mov  hGame, eax
    ;【此处定时器为测试所用】
    invoke  SetTimer, NULL, NULL, 1000, offset DwonTest

  .elseif  eax == WM_CLOSE
      
    invoke  ReleaseDC, hWnd, hGame
    invoke   DestroyWindow, hWinMain
    invoke   PostQuitMessage, NULL
      
  .elseif  eax == WM_SIZE
    
    invoke  ValidateRect, hWnd, offset gameArea

  .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  ;以0填充WNDCLASSEX结构体
;********************************************************************
; 注册窗口类
;********************************************************************
  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_WINDOW + 3  ;设置窗体背景色
  mov  @stWndClass.lpszClassName, offset szClassName  ;保存窗体类名
  invoke   RegisterClassEx, addr @stWndClass    ;注册窗口类
;********************************************************************
; 建立并显示窗口
;********************************************************************
  invoke   CreateWindowEx, WS_EX_TOOLWINDOW, offset szClassName, offset szCaptionMain,\
             WS_OVERLAPPEDWINDOW,\
             100, 100, 400, 456,\
             NULL, NULL, hInstance, NULL      ;建立窗口
  mov  hWinMain, eax          ;保存窗口句柄  
  invoke   ShowWindow, hWinMain, SW_SHOWNORMAL    ;显示窗口
  invoke   UpdateWindow, hWinMain        ;更新窗口
;********************************************************************
; 消息循环
;********************************************************************
  .while  TRUE            ;消息循环
      
    invoke   GetMessage, addr @stMsg, NULL, 0, 0    ;获取消息并填充MSG结构体
    
      .break .if  eax == 0        ;判断是否退出
      invoke   TranslateMessage, addr @stMsg    ;消息装换
      invoke   DispatchMessage, addr @stMsg    ;分发消息
      
    .endw
    ret

_WinMain endp

;********************************************************************
; 初始化游戏容器
;********************************************************************
InitContainer proc
  local @lpRect : RECT
  
  pushad
  
  ;建立游戏容器边框
  invoke  CreatePen, PS_SOLID, 5, 8000FFh
  push  eax
  invoke  SelectObject, hGame, eax
  invoke  DeleteObject, eax
  pop  eax
  invoke  FrameRect, hGame, offset gameArea,  eax
  
  popad
  ret

InitContainer endp

;********************************************************************
; 显示方块控件
; type:控件类型1为4格横条,2为田字形,3..4..
;********************************************************************
ShowControl proc cType : DWORD

  pushad
  
  .if  cType == 1  ;4格横条■■■■
    
    invoke  InitControl1
    
  .endif
  
  popad
  ret
  
ShowControl endp

;********************************************************************
; 初始化■■■■图形
;********************************************************************
InitControl1 proc

  pushad
  
  ;设置方块颜色
  invoke  SetColor, 0FF80FFh, 400040h
  ;创建方块并排列方块
  mov  ecx, 60    ;左上角起始位置
  mov  edx, 90    ;右下角起始位置
  xor  esi, esi
  lea  ebx, curControl
@@:
  cmp  ecx, 180
  jz  @F    ;4个方块都初始化完毕
  push  ebx
  push  ecx
  push  edx
  invoke  Rectangle, hGame, ecx, 5, edx, 30
  pop  edx
  pop  ecx
  pop  ebx
  mov  [ebx + esi], ecx
  push  topSpace
  pop  DWORD ptr [ebx + esi + 4]
  add  esi, 8
  add  ecx, 30
  add  edx, 30
  jmp  @B
  
@@:

  popad
  ret

InitControl1 endp

;********************************************************************
; 设置方块颜色
;********************************************************************
SetColor proc color : DWORD, pColor : DWORD

  pushad
  
  invoke  CreatePen, PS_SOLID, 1, pColor
  invoke  SelectObject, hGame, eax
  invoke  DeleteObject, eax
  invoke  CreateSolidBrush, color
  invoke  SelectObject, hGame, eax
  invoke  DeleteObject, eax
  
  popad
  ret

SetColor endp

;********************************************************************
; ■■■■图形向下走动
;********************************************************************
Control1Down proc

  pushad
  
  invoke  IsDownEnd
  .if   eax == 1  ;下面有障碍,改变状态为创建新的方块并保存当前方块在容器中的位置
    
    mov  curState, 1
    invoke  ChangeAreaState
    invoke  RtlZeroMemory, offset curControl, sizeof curControl
    popad
    ret

  .endif  
  
  
  ;如果下面不是障碍,则■■■■向下走动
  lea  edx, curControl
  xor  ecx, ecx
@@:
  cmp  ecx, 4
  jz  @F
  ;覆盖原有的方块
  push  ecx
  invoke  SetColor, 0h, 0h
  mov  eax, [edx + ecx * 8 + 4]
  mov  ebx, 30
  add  ebx, eax  ;ebx右下角y坐标
  mov  eax, [edx + ecx * 8]
  add  eax, 30    ;eax为右下角x坐标
  push  eax    ;保存右下角坐标
  push  ebx
  push  edx
  invoke  Rectangle, hGame, [edx + ecx * 8], [edx + ecx * 8 + 4], eax, ebx
  pop  edx
  
  ;生成新的方块
  invoke  SetColor, 0FF80FFh, 400040h
  pop  ebx
  pop  eax
  pop  ecx  
  add   DWORD ptr [edx + ecx * 8 + 4], 30
  add  ebx, 30
  push  ecx
  push  edx
  invoke  Rectangle, hGame, [edx + ecx * 8], [edx + ecx * 8 + 4], eax, ebx
  pop  edx
  pop  ecx
  inc  ecx
  jmp  @B
@@:
  
  popad
  ret

Control1Down endp

;********************************************************************
; 保存当前方块在容器中的状态
;********************************************************************
ChangeAreaState proc 
  
  pushad
  
  ;计算区域单元坐标
  lea  ebx, curControl
  xor  ecx, ecx
@@:
  cmp  ecx, 4
  jz  @F
  
  ;计算二维x坐标
  invoke  CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 1
  mov  esi, eax
  
  ;计算二维y坐标
  invoke  CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 2
  mov  edi, eax
  
  ;设置区域更新,更新的坐标位置(eax + esi * 4 * 8 + edi * 4)
  lea  eax, area
  push  eax
  xchg  edi, eax
  mov  edi, 8
  mul  edi
  add  esi, eax
  pop  eax
  mov  DWORD ptr [eax + esi * 4], 1  ;设置当前位置已经被填充
  inc  ecx
  jmp  @B
@@:  

  popad
  ret
  
ChangeAreaState endp

;********************************************************************
; 根据顶角计算二维坐标
; left, top:顶角像素
; posType:1表示计算x坐标,2表示计算y坐标
; eax返回二维坐标
;********************************************************************
CalculatePos proc left : DWORD, top :DWORD, posType : DWORD
  local @ret : DWORD
  pushad
  
  mov  edx, left  
  add  edx, rectArea ;右下角x坐标
  
  mov  ecx, top
  add  ecx, rectArea ;右下角y坐标
  
  .if  posType == 1
    
    mov  eax, edx
    mov  ebx, 30
    xor  edx, edx
    div  ebx
    
  .elseif
    
    mov  eax, ecx
    sub  eax, topSpace
    mov  ecx, 30
    xor  edx, edx
    div  ecx
    
  .endif
  mov  @ret, eax
  popad
  mov  eax, @ret
  dec  eax
  ret

CalculatePos endp

;********************************************************************
; 判断下面是否有障碍
; 返回值::eax为1表示下落完毕,为0表示未完毕
;********************************************************************
IsDownEnd proc

  pushad
  
  lea  ebx, curControl
  xor  ecx, ecx
@@:
  cmp  ecx, 4
  jz  @F
  
  ;计算二维x坐标
  invoke  CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 1
  mov  esi, eax
  
  ;计算二维y坐标
  invoke  CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 2
  mov  edi, eax
  inc  edi
  
  ;设置区域更新,更新的坐标位置(eax + esi * 4 * 8 + edi * 4)
  lea  eax, area
  push  eax
  xchg  edi, eax
  mov  edi, 8
  mul  edi
  add  esi, eax
  pop  eax
  mov  edx, [eax + esi * 4]
  .if  edx == 1
    
    popad
    mov  eax, 1
    ret
    
  .endif
  inc  ecx
  jmp  @B
@@:  
  
  popad
  xor  eax, eax
  ret

IsDownEnd endp

;********************************************************************
; 向右,左移动
; mType:1向右移动,2向左移动
; 返回值::eax为1表示移动成功,为0表示移动失败
;********************************************************************
RLDown proc mType : DWORD

  pushad
  
  invoke  IsRLDownEnd, mType
  .if   eax == 0  ;不能向右下移动,所以失败
    
    popad
    xor  eax, eax
    ret
    
  .else
    
    lea  edx, curControl
    xor  ecx, ecx
@@:
    cmp  ecx, 4
    jz  @F
    ;覆盖原有的方块
    push  ecx
    invoke  SetColor, 0h, 0h
    mov  eax, [edx + ecx * 8 + 4]
    mov  ebx, 30
    add  ebx, eax  ;ebx右下角y坐标
    mov  eax, [edx + ecx * 8]
    add  eax, 30    ;eax为右下角x坐标
    push  eax    ;保存右下角坐标
    push  ebx
    push  edx
    invoke  Rectangle, hGame, [edx + ecx * 8], [edx + ecx * 8 + 4], eax, ebx
    pop  edx
    
    ;生成新的方块向右下角移动
    invoke  SetColor, 0FF80FFh, 400040h
    pop  ebx
    pop  eax
    pop  ecx  
    .if  mType
      
      add  eax, 30
      add   DWORD ptr [edx + ecx * 8], 30    ;右边移动
    
    .else
      
      sub  eax, 30
      sub   DWORD ptr [edx + ecx * 8], 30    ;左边移动
      
    .endif
    add   DWORD ptr [edx + ecx * 8 + 4], 30
    add  ebx, 30
    push  ecx
    push  edx
    invoke  Rectangle, hGame, [edx + ecx * 8], [edx + ecx * 8 + 4], eax, ebx
    pop  edx
    pop  ecx
    inc  ecx
    jmp  @B
  
  .endif
@@:  

  popad
  mov  eax, 1
  ret

RLDown endp

;********************************************************************
; 判断是否可以进行左右
; mType:1判断是否可以向右边移动,0判断是否可以向左边移动
; 返回值::eax为1表示可以,为0表示不行
;********************************************************************
IsRLDownEnd proc mType : DWORD
  
  pushad
  
  lea  ebx, curControl
  xor  ecx, ecx
@@:
  cmp  ecx, 4
  jz  @F
  
  ;计算二维x坐标
  invoke  CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 1
  mov  esi, eax
  
  ;计算二维y坐标
  invoke  CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 2
  mov  edi, eax
  
  .if  (mType == 1 && esi >= 7) || edi >= 13 || (mType == 0 && esi == 0) ;如果已经在右边沿或在底部或者向左移动时在左边
    
    mov  curKey, 0
    .if  edi < 14      ;如果还没有到底部,则继续尝试向下滚动
      
      invoke  Control1Down
      
    .endif
    
    popad
    xor  eax, eax
    ret
  
  .endif
  
  ;右下
  .if  mType
    
    inc  esi
    
  .elseif    ;左下
    
    dec  esi
    
  .endif
  inc  edi
  ;判断当前块右下角是否有障碍
  lea  eax, area
  push  eax
  xchg  edi, eax
  mov  edi, 8
  mul  edi
  add  esi, eax
  pop  eax
  mov  edx, [eax + esi * 4]
  .if  edx == 1
    
    mov  curKey, 0
    popad
    xor  eax, eax
    ret
    
  .endif
  inc  ecx
  jmp  @B
@@:
  
  popad
  mov  eax, 1
  ret

IsRLDownEnd endp

;********************************************************************
; ■■■■反转
; 返回值:eax为1表示翻转成功,eax为0表示翻转失败
;********************************************************************
ChangeC1 proc

  pushad
  
  .if  curDir  ;当前为竖着
    
    
    
  .else    ;当前为横着
    
    ;判断是否可以竖立,以第二个点位基准树立判断是否有障碍
    ;1.判断当前y坐标是否大于2,如果大于2则表示可以竖立,否则返回0表示反转失败
    lea  ebx, curControl
    invoke  CalculatePos, [ebx + 8], [ebx + 12], 2
    .if  eax <= 2  ;当前y坐标小于2不能竖立
      
      popad
      xor  eax, eax
      ret
      
    .endif
    
    push  eax
    inc  eax
    ;判断在树立的线路上是否有障碍,判断eax为y轴的上三点是否有障碍
    lea  ebx, area
    mov  edx, 32
    mul  edx
    mov  ecx, 32
@@:
    cmp  ecx, 128
    jz  @F    
    push  eax
    sub  eax, ecx
    mov  edx, [ebx + eax]
    pop  eax
    .if  edx == 1  ;有障碍返回0
      
      pop  eax
      popad
      xor  eax, eax
      ret
      
    .endif
    add  ecx, 32
    jmp  @B
@@:
    invoke  IsDownEnd
    .if  eax == 0
      
      invoke  ClearCur  ;清除当前点
      ;说明没有障碍可以翻转
      ;开始翻转
      lea  ebx, curControl
      invoke  CalculatePos, [ebx + 8], [ebx + 12], 1
      mov  edx, 30
      mul  edx
      mov  edx, eax  ;edx存放x坐标的水平像素
      pop  esi    ;esi为最下点的y坐标
      
      
      ;使得curControl为竖立状态
      xor  ecx, ecx
  @@:
      cmp  ecx, 4
      je  @F
      mov  eax, 8
      push  edx
      mul  ecx
      pop  edx
      push  ecx
      mov  ecx, eax
      mov  [ebx + ecx], edx  ;设置水平坐标
      mov  edi, 30
      mov  eax, esi
      push  edx
      mul  edi
      pop  edx
      add  eax, 5
      mov  [ebx + ecx + 4], eax;设置垂直像素
      pop  ecx
      dec  esi
      inc  ecx
      jmp  @B
  @@:
      mov  curDir, 1
      
    .else
      
      pop  eax
    .endif
    
  .endif
  
  popad
  mov  eax, 1
  ret

ChangeC1 endp

;********************************************************************
; 清除当前方块
;********************************************************************
ClearCur proc

  pushad
  
  lea  edx, curControl
  xor  ecx, ecx
@@:
  cmp  ecx, 4
  jz  @F
  ;覆盖原有的方块
  push  ecx
  invoke  SetColor, 0h, 0h
  mov  eax, [edx + ecx * 8 + 4]
  mov  ebx, 30
  add  ebx, eax  ;ebx右下角y坐标
  mov  eax, [edx + ecx * 8]
  add  eax, 30    ;eax为右下角x坐标
  push  edx
  invoke  Rectangle, hGame, [edx + ecx * 8], [edx + ecx * 8 + 4], eax, ebx
  pop  edx
  pop  ecx
  inc  ecx
  jmp  @B
@@:

  popad
  ret

ClearCur endp

;********************************************************************
; 更新游戏分数
;********************************************************************
GetPoint proc

  pushad
  popad
  ret

GetPoint endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
  call  _WinMain
  invoke   ExitProcess, NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start