
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 俄羅斯方塊 by Originality
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap : none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定義
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include rgame.inc
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代碼段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 定時(shí)器測(cè)試
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DwonTest proc _hWnd, _uMsg, _idEvent, _dwTime
pushad
mov eax, curState
.if eax ;下落結(jié)束
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
;【此處定時(shí)器為測(cè)試所用】
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 ;獲得應(yīng)用程序?qū)嵗?br> mov hInstance, eax ;實(shí)例保存在全局變量中
invoke RtlZeroMemory, addr @stWndClass, sizeof @stWndClass ;以0填充WNDCLASSEX結(jié)構(gòu)體
********************************************************************
; 注冊(cè)窗口類
;********************************************************************
invoke LoadCursor, 0, IDC_ARROW ;獲取光標(biāo)句柄
mov @stWndClass.hCursor, eax ;設(shè)置光標(biāo)
push hInstance
pop @stWndClass.hInstance ;保存應(yīng)用程序?qū)嵗?br> mov @stWndClass.cbSize, sizeof WNDCLASSEX ;保存結(jié)構(gòu)體大小
mov @stWndClass.style, CS_HREDRAW or CS_VREDRAW ;設(shè)置窗體樣式
mov @stWndClass.lpfnWndProc, offset _ProcWinMain ;保存回調(diào)函數(shù)
mov @stWndClass.hbrBackground, COLOR_WINDOW + 3 ;設(shè)置窗體背景色
mov @stWndClass.lpszClassName, offset szClassName ;保存窗體類名
invoke RegisterClassEx, addr @stWndClass ;注冊(cè)窗口類
;********************************************************************
; 建立并顯示窗口
;********************************************************************
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 ;更新窗口
;********************************************************************
; 消息循環(huán)
;********************************************************************
.while TRUE ;消息循環(huán)
invoke GetMessage, addr @stMsg, NULL, 0, 0 ;獲取消息并填充MSG結(jié)構(gòu)體
.break .if eax == 0 ;判斷是否退出
invoke TranslateMessage, addr @stMsg ;消息裝換
invoke DispatchMessage, addr @stMsg ;分發(fā)消息
.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
;設(shè)置方塊顏色
invoke SetColor, 0FF80FFh, 400040h
;創(chuàng)建方塊并排列方塊
mov ecx, 60 ;左上角起始位置
mov edx, 90 ;右下角起始位置
xor esi, esi
lea ebx, curControl
@@:
cmp ecx, 180
jz @F ;4個(gè)方塊都初始化完畢
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
;********************************************************************
; 設(shè)置方塊顏色
;********************************************************************
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
;********************************************************************
; ■■■■圖形向下走動(dòng)
;********************************************************************
Control1Down proc
pushad
invoke IsDownEnd
.if eax == 1 ;下面有障礙,改變狀態(tài)為創(chuàng)建新的方塊并保存當(dāng)前方塊在容器中的位置
mov curState, 1
invoke ChangeAreaState
invoke RtlZeroMemory, offset curControl, sizeof curControl
popad
ret
.endif
;如果下面不是障礙,則■■■■向下走動(dòng)
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坐標(biāo)
mov eax, [edx + ecx * 8]
add eax, 30 ;eax為右下角x坐標(biāo)
push eax ;保存右下角坐標(biāo)
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
;********************************************************************
; 保存當(dāng)前方塊在容器中的狀態(tài)
;********************************************************************
ChangeAreaState proc
pushad
;計(jì)算區(qū)域單元坐標(biāo)
lea ebx, curControl
xor ecx, ecx
@@:
cmp ecx, 4
jz @F
;計(jì)算二維x坐標(biāo)
invoke CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 1
mov esi, eax
;計(jì)算二維y坐標(biāo)
invoke CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 2
mov edi, eax
;設(shè)置區(qū)域更新,更新的坐標(biāo)位置(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 ;設(shè)置當(dāng)前位置已經(jīng)被填充
inc ecx
jmp @B
@@:
popad
ret
ChangeAreaState endp
;********************************************************************
; 根據(jù)頂角計(jì)算二維坐標(biāo)
; left, top:頂角像素
; posType:1表示計(jì)算x坐標(biāo),2表示計(jì)算y坐標(biāo)
; eax返回二維坐標(biāo)
;********************************************************************
CalculatePos proc left : DWORD, top :DWORD, posType : DWORD
local @ret : DWORD
pushad
mov edx, left
add edx, rectArea ;右下角x坐標(biāo)
mov ecx, top
add ecx, rectArea ;右下角y坐標(biāo)
.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
;計(jì)算二維x坐標(biāo)
invoke CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 1
mov esi, eax
;計(jì)算二維y坐標(biāo)
invoke CalculatePos, [ebx + ecx * 8 ], [ebx + ecx * 8 + 4], 2
mov edi, eax
inc edi
;設(shè)置區(qū)域更新,更新的坐標(biāo)位置(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