📄 msc.asm
字号:
.386
.model flat,stdcall ; 指定内存模式
option casemap:none ; 告诉 MASM 要区分标号的大小写
include msc.Inc
include gdi32.inc
include kernel32.inc ; 函数原型声明的头文件
include user32.inc
include windows.inc ; 包含了 WIN32 编程所需要的常量和结构体的定义
includelib gdi32.lib
includelib kernel32.lib
includelib user32.lib
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
MoveProc proto :HWND,:BROOD,:DWORD,:DWORD
.const
IDI_ICON equ 100
IDB_BG equ 200
IDB_T1 equ 201
IDB_T2 equ 202
IDB_T3 equ 203
IDB_T4 equ 204
IDB_T5 equ 205
IDB_T6 equ 206
IDB_T7 equ 207
IDB_T8 equ 208
IDB_P1 equ 211
IDB_P2 equ 212
IDB_P3 equ 213
IDB_P4 equ 214
IDB_P5 equ 215
IDB_P6 equ 216
IDB_P7 equ 217
IDB_P8 equ 218
ID_TIMER1 equ 1
ID_TIMER2 equ 2
ID_TIMER3 equ 3
VULTURE equ 101
ZEALOT equ 102
ZEALOT2 equ 103
.data ; initialized data
ClassName db "MSC",0 ; the name of window class
AppName db "Mcrio StarCraft",0 ; the name of window
T_state db "Vulture Life: ",0
P_state db "Zealot Life: ",0
sgameNext db "WAIT FOR NEXT GATE!!!",0 ; 进入下一关显示的信息
sgameWin db "YOU WIN,GAME OVER!!!",0 ; 获胜,游戏结束显示的信息
sgameLost db "YOU LOST,GAME OVER!!!",0 ; 失败,游戏结束显示的信息
; 名字,x坐标,y坐标,生命,状态方向,射程,移动速度,攻击间隔
T_Vulture BROOD <VULTURE,360,400,5,0,150,20,1500>
P_Zealot BROOD <ZEALOT,360,20,8,0,40,12,1000>
P_Zealot2 BROOD <ZEALOT2,420,20,8,0,40,12,1000>
T_isArrive dd TRUE
P_inRange dd 0 ; 在Vulture的攻击范围
P2_inRange dd 0
P_isArrive dd 0 ; 到达目的地
P2_isArrive dd 0
P_isHit dd 0 ; 被击中
P2_isHit dd 0
P_isDead dd 0 ; 死亡
P2_isDead dd 0
T_isDead dd 0
T_isSelected dd 0 ; 被选中
P_isSelected dd 0
P2_isSelected dd 0
stateRect RECT <0,0,740,20> ; 状态生命显示区
deadRect RECT <300,200,500,220> ; 死亡信息显示区
nextGate dd 0 ; 判断是否为第二关
gameOver dd 0 ; 判断游戏结束
.data? ; Uninitialized data
hInstance HINSTANCE ? ; 应用程序的句柄
CommandLine LPSTR ? ; 保存从命令行传入的参数
hIcon dd ? ; 图片句柄
hBitmapBG dd ?
hBitmapT1 dd ?
hBitmapT2 dd ?
hBitmapT3 dd ?
hBitmapT4 dd ?
hBitmapT5 dd ?
hBitmapT6 dd ?
hBitmapT7 dd ?
hBitmapT8 dd ?
hBitmapP1 dd ?
hBitmapP2 dd ?
hBitmapP3 dd ?
hBitmapP4 dd ?
hBitmapP5 dd ?
hBitmapP6 dd ?
hBitmapP7 dd ?
hBitmapP8 dd ?
T_disX dd ? ; T_Vulture据目的点的横纵距离
T_disY dd ?
destpoint POINT <> ; T_Vulture目的地
ptLBD POINT <> ; 左键按下的坐标
ptLBU POINT <> ; 左键释放的坐标
T_updateRect RECT <> ; 要更新的区域
selectRect RECT <> ; 选择的区域
.code
start:
invoke GetModuleHandle, NULL ; get the instance handle of program
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc ; 窗口处理函数的指针
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance ; 本模块的事例句柄
mov wc.hbrBackground,COLOR_WINDOW+1 ; 背景画刷的句柄
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,hInst,IDI_ICON ; 加载图标
mov hIcon,eax
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW ; 光标句柄
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc ; register window class
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax ; 获得窗口句柄
invoke ShowWindow, hwnd,SW_SHOWNORMAL ; display window on desktop
invoke UpdateWindow, hwnd ; refresh the client area
.while TRUE ; Enter message loop
invoke GetMessage, ADDR msg,NULL,0,0
.break .if (!eax)
invoke TranslateMessage, ADDR msg ; 传送键盘消息
invoke DispatchMessage, ADDR msg ; 把消息发送给负责该窗口过程的函数
.endw
mov eax,msg.wParam
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL ps:PAINTSTRUCT, hdc:HDC, hMemDC:HDC, rect:RECT
cmp uMsg,WM_DESTROY ; 对不同消息进行不同处理
jz destroy
cmp uMsg,WM_CREATE
jz create
cmp uMsg,WM_PAINT
jz paint
cmp uMsg,WM_LBUTTONDOWN
jz lbuttondown
cmp uMsg,WM_LBUTTONUP
jz lbuttonup
cmp uMsg,WM_RBUTTONDOWN
jz rbuttondown
cmp uMsg,WM_TIMER
jz timer
retern:
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
endcheck:
xor eax,eax
jmp retern
ret
destroy: ; 删除句柄,对象
invoke DeleteObject,hBitmapBG
invoke DeleteObject,hBitmapT1
invoke DeleteObject,hBitmapT2
invoke DeleteObject,hBitmapT3
invoke DeleteObject,hBitmapT4
invoke DeleteObject,hBitmapT5
invoke DeleteObject,hBitmapT6
invoke DeleteObject,hBitmapT7
invoke DeleteObject,hBitmapT8
invoke DeleteObject,hBitmapP1
invoke DeleteObject,hBitmapP2
invoke DeleteObject,hBitmapP3
invoke DeleteObject,hBitmapP4
invoke DeleteObject,hBitmapP5
invoke DeleteObject,hBitmapP6
invoke DeleteObject,hBitmapP7
invoke DeleteObject,hBitmapP8
invoke KillTimer,hWnd,ID_TIMER1
invoke KillTimer,hWnd,ID_TIMER2
invoke PostQuitMessage,0
jmp endcheck
create: ; 载入各种资源
invoke LoadBitmap,hInstance,IDB_BG
mov hBitmapBG,eax
invoke LoadBitmap,hInstance,IDB_T1
mov hBitmapT1,eax
invoke LoadBitmap,hInstance,IDB_T2
mov hBitmapT2,eax
invoke LoadBitmap,hInstance,IDB_T3
mov hBitmapT3,eax
invoke LoadBitmap,hInstance,IDB_T4
mov hBitmapT4,eax
invoke LoadBitmap,hInstance,IDB_T5
mov hBitmapT5,eax
invoke LoadBitmap,hInstance,IDB_T6
mov hBitmapT6,eax
invoke LoadBitmap,hInstance,IDB_T7
mov hBitmapT7,eax
invoke LoadBitmap,hInstance,IDB_T8
mov hBitmapT8,eax
invoke LoadBitmap,hInstance,IDB_P1
mov hBitmapP1,eax
invoke LoadBitmap,hInstance,IDB_P2
mov hBitmapP2,eax
invoke LoadBitmap,hInstance,IDB_P3
mov hBitmapP3,eax
invoke LoadBitmap,hInstance,IDB_P4
mov hBitmapP4,eax
invoke LoadBitmap,hInstance,IDB_P5
mov hBitmapP5,eax
invoke LoadBitmap,hInstance,IDB_P6
mov hBitmapP6,eax
invoke LoadBitmap,hInstance,IDB_P7
mov hBitmapP7,eax
invoke LoadBitmap,hInstance,IDB_P8
mov hBitmapP8,eax
mov eax,hBitmapT1 ; 初始化各对象状态
mov T_Vulture.state,eax
mov eax,hBitmapP2
mov P_Zealot.state,eax
mov P_Zealot2.state,eax
invoke SetTimer,hWnd,ID_TIMER1,165,NULL ; 创建移动延时定时器
jmp endcheck
paint:
invoke BeginPaint,hWnd,addr ps ; 获得窗口客户区的DC句柄
mov hdc,eax
invoke CreateCompatibleDC,hdc ; 创建该DC 的内存映像
mov hMemDC,eax
invoke SelectObject,hMemDC,hBitmapBG ; 显示地图
invoke GetClientRect,hWnd,addr rect
invoke BitBlt,hdc,0,0,rect.right,rect.bottom,hMemDC,0,0,SRCCOPY
.if !T_isDead ; 显示秃鹰战车
invoke SelectObject,hMemDC,T_Vulture.state
invoke GetClientRect,hWnd,addr rect
invoke BitBlt,hdc,T_Vulture.xPos,T_Vulture.yPos,rect.right,rect.bottom,hMemDC,0,0,SRCCOPY
.endif
.if !P_isDead ; 显示狂热者
invoke SelectObject,hMemDC,P_Zealot.state
invoke GetClientRect,hWnd,addr rect
invoke BitBlt,hdc,P_Zealot.xPos,P_Zealot.yPos,rect.right,rect.bottom,hMemDC,0,0,SRCCOPY
.endif
.if !P2_isDead && nextGate ; 显示狂热者2
invoke SelectObject,hMemDC,P_Zealot2.state
invoke GetClientRect,hWnd,addr rect
invoke BitBlt,hdc,P_Zealot2.xPos,P_Zealot2.yPos,rect.right,rect.bottom,hMemDC,0,0,SRCCOPY
.endif
.if T_isSelected && !T_isDead ; 画矩形选择框
mov eax,T_Vulture.xPos
mov selectRect.left,eax
add eax,56
mov selectRect.right,eax
mov eax,T_Vulture.yPos
mov selectRect.top,eax
add eax,56
mov selectRect.bottom,eax
invoke DrawEdge,hdc,addr selectRect,EDGE_BUMP,BF_RECT
RGB 0,255,0 ; 显示Vulture状态,生命
invoke SetTextColor,hdc,eax
RGB 0,255,0
invoke CreatePen,PS_SOLID,2,eax
invoke SelectObject,hdc,eax
invoke lstrlen,ADDR T_state
invoke TextOut,hdc,0,0,ADDR T_state,eax
mov eax,20
mul T_Vulture.life
add eax,100
invoke Rectangle,hdc,100,5,eax,12
RGB 255,0,0 ; 显示Zealot状态,生命
invoke SetTextColor,hdc,eax
RGB 255,0,0
invoke CreatePen,PS_SOLID,2,eax
invoke SelectObject,hdc,eax
invoke lstrlen,ADDR T_state
invoke lstrlen,ADDR P_state
invoke TextOut,hdc,300,0,ADDR P_state,eax
mov eax,20
mul P_Zealot.life
add eax,400
invoke Rectangle,hdc,400,5,eax,12
.if nextGate ; 显示Zealot2状态,生命
mov eax,20
mul P_Zealot2.life
add eax,580
invoke Rectangle,hdc,580,5,eax,12
.endif
.endif
.if P_isDead && P2_isDead && nextGate ; Zealot死亡,游戏结束
RGB 0,0,255 ; 显示结束信息
invoke SetTextColor,hdc,eax
invoke lstrlen,ADDR sgameWin
invoke TextOut,hdc,300,200,ADDR sgameWin,eax
invoke SetTimer,hWnd,ID_TIMER2,5000,NULL ; 启动自动关闭定时器
.endif
.if T_isDead ; Vulture死亡,游戏结束
RGB 0,0,0 ; 显示结束信息
invoke SetTextColor,hdc,eax
invoke lstrlen,ADDR sgameLost
invoke TextOut,hdc,300,200,ADDR sgameLost,eax
invoke SetTimer,hWnd,ID_TIMER2,5000,NULL ; 启动自动关闭定时器
.endif
.if P_isDead && !nextGate ; Zealot死亡,游戏进入下一关
RGB 0,0,255 ; 显示过关信息
invoke SetTextColor,hdc,eax
invoke lstrlen,ADDR sgameNext
invoke TextOut,hdc,300,200,ADDR sgameNext,eax
invoke SetTimer,hWnd,ID_TIMER3,3000,NULL ; 启动进入下一关定时器
.endif
invoke DeleteDC,hMemDC
invoke EndPaint,hWnd,addr ps
jmp endcheck
lbuttondown:
mov eax,lParam
and eax,0FFFFh
mov ptLBD.x,eax
mov eax,lParam
shr eax,16
mov ptLBD.y,eax
invoke LoadCursor,NULL,IDC_HAND
invoke SetCursor,eax
mov eax,T_Vulture.xPos ; 判断选取
mov edx,T_Vulture.yPos
.if (ptLBD.x>=eax)&&(ptLBD.y>=edx)
add eax,56
add edx,56
.if (ptLBD.x<=eax)&&(ptLBD.y<=edx)
mov T_isSelected,TRUE
mov P_isSelected,0
mov P2_isSelected,0
invoke MessageBeep,0FFFFFFFFh ; 选中对象调用系统声音
mov eax,T_Vulture.xPos
mov selectRect.left,eax
add eax,56
mov selectRect.right,eax
mov eax,T_Vulture.yPos
mov selectRect.top,eax
add eax,56
mov selectRect.bottom,eax
invoke InvalidateRect,hWnd,addr selectRect,TRUE
invoke InvalidateRect,hWnd,addr stateRect,TRUE
jmp endcheck
.endif
.endif
jmp endcheck
lbuttonup: ; 扩展用
mov eax,lParam
and eax,0FFFFh
mov ptLBU.x,eax
mov eax,lParam
shr eax,16
mov ptLBU.y,eax
jmp endcheck
rbuttondown:
.if !T_isSelected || gameOver || (P_isDead && !nextGate)
jmp endcheck
.endif
mov T_isArrive,0
mov P_isArrive,0
mov P2_isArrive,0
mov eax,lParam ; lParam包含了鼠标的位置
and eax,0FFFFh ; 低位为x坐标,高位为y坐标
mov destpoint.x,eax
mov eax,lParam
shr eax,16
mov destpoint.y,eax
mov eax,P_Zealot.xPos
mov edx,P_Zealot.yPos
.if (destpoint.x>=eax)&&(destpoint.y>=edx)
add eax,24
add edx,30
.if (destpoint.x<=eax)&&(destpoint.y<=edx)&&P_inRange
mov P_isHit,TRUE ; Zealot被击中
invoke MessageBeep,MB_ICONASTERISK
sub P_Zealot.life,1
mov P_isHit,0
.if P_Zealot.life==0 ; 判断Zealot死亡
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -