?? mybox.asm
字號:
;************************************************************************
.386
.model flat, stdcall
option casemap : none
;************************************************************************
include windows.inc
include user32.inc
include kernel32.inc
include gdi32.inc
include Comctl32.inc
includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib
includelib Comctl32.lib
include StoreHouse.inc ; 導入關卡地圖數據
;************************************************************************
; 宏定義數據
;------------------------------------------------------------------------
ICO_MAIN equ 1000h ; 窗口圖標ID
ICO_MSG equ 1001h
IDM_CUR equ 1000h ; 窗口光標ID
IDM_MAIN equ 1000h ; 菜單ID
IDM_REFLUSH equ 1001h
IDM_PREV equ 1002h
IDM_NEXT equ 1003h
IDM_ABOUT equ 1004h
IDM_EXIT equ 1005h
ID_TOOLBAR equ 1 ; 工具欄ID
IDM_TOOLBAR equ 2000h ; 工具欄圖標位圖ID
ID_STATUSBAR equ 2 ; 狀態欄ID
DLG_MAIN equ 3 ; 消息對話框ID
BM_MAIN equ 3000h ; 背景位圖資源ID
ID_GAMETIMER equ 100 ; 關卡計時器
ID_SHOWBOMB equ 101 ; 刷新炸彈計時器
xBmBack equ 0d
xBmWall equ 30d
xBmRoad equ 60d
xBmBox1 equ 90d
xBmBox2 equ 120d
xBmObject equ 150d
xBmMan equ 180d
xBmBomb equ 210d
VK_B equ 42h ; 字母"B"的掃描碼
BackStep equ 20d ; 后退的次數
;************************************************************************
; 數據段
;------------------------------------------------------------------------
.const
szClassName db 'Game', 0
szCaption db '推箱子', 0
dwStatusWidth dd 80, 160, 255, -1
NUM_BUTTONS equ 6 ;工具欄圖標位圖中包含的小圖標個數
stToolbar equ this byte
TBBUTTON <0, IDM_REFLUSH, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, -1>
TBBUTTON <1, IDM_PREV, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, -1>
TBBUTTON <2, IDM_NEXT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, -1>
TBBUTTON <3, IDM_ABOUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, -1>
TBBUTTON <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, -1>
TBBUTTON <4, IDM_EXIT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, -1>
;------------------------------------------------------------------------
.data
szOutOfRange db '已超出游戲關卡范圍!', 0
szSuccessMsg db '您成功通過了關卡!是否繼續?', 0
szGameOver db '已到達最后一關', 0
FmtGate db '—第%d關', 0
szBomb db '炸彈數量 : 1', 0
szNoBomb db '炸彈數量 : 0', 0
szStep db '移動次數 : %d', 0
szGameTime db ' %02d:%02d:%02d', 0
;------------------------------------------------------------------------
.data?
hInstance dd ? ; 實例句柄
hWinMain dd ? ; 主窗口句柄
hMenu dd ? ; 菜單句柄
hWinToolbar dd ? ; 工具欄句柄
hWinStatus dd ? ; 狀態欄句柄
hBackDC dd ? ; 背景位圖設備環境句柄
hBitmap dd ? ; 背景位圖句柄
LocalTime dd ? ; 當前系統時間的秒數
TimeCircle dd ? ; 時間循環周期的秒數: 24 * 3600 * n
TimeFlag dd ? ; 計時標志位,1表示進行及時;0表示停止計時
GameHour dd ?
GameMinute dd ?
GameSecond dd ?
Map db 14d * 12d dup (?) ; 存放當前關卡的地圖數據
ObjectLeft dd ? ; 剩余的目標地點數量
ManXPos dd ? ; 角色的列坐標
ManYPos dd ? ; 角色的行坐標
BombXPos dd ? ; 炸彈的列坐標
BombYPos dd ? ; 炸彈的行坐標
CurrentGate dd ? ; 當前的關卡號
BombCount dd ? ; 炸彈的剩余數量,初始化時為1
BombFlag dd ? ; 炸彈的存在標志,1表示存在,0表示隱藏
StepNumber dd ? ; 玩家移動次數
dwCount dd ? ; 隨機數
BackBuffer dd 8 * BackStep dup (?) ; 回退坐標緩沖區
BackLength dd ? ; 當前可回退的次數
;************************************************************************
;************************************************************************
; 代碼段
;------------------------------------------------------------------------
.code
;************************************************************************
_Quit proc
invoke DestroyWindow, hWinMain
invoke PostQuitMessage, NULL
ret
_Quit endp
;************************************************************************
;************************************************************************
; 加載位圖資源
;------------------------------------------------------------------------
_LoadRes proc
local @hDC ; 參考句柄
invoke GetDC, hWinMain
mov @hDC, eax
invoke CreateCompatibleDC, @hDC
mov hBackDC, eax
invoke LoadBitmap, hInstance, BM_MAIN
mov hBitmap, eax
invoke ReleaseDC, hWinMain, @hDC
invoke SelectObject, hBackDC, hBitmap
ret
_LoadRes endp
;************************************************************************
;************************************************************************
; 釋放資源
;------------------------------------------------------------------------
_FreeRes proc
invoke DeleteDC, hBackDC
invoke DeleteObject, hBitmap
invoke KillTimer, hWinMain, ID_GAMETIMER
; invoke KillTimer, hWinMain, ID_SHOWBOMB
ret
_FreeRes endp
;************************************************************************
;************************************************************************
; 設置當前系統時間
;------------------------------------------------------------------------
_SetLocalTime proc uses ebx
local @Hour, @Minute, @Second
local @stST:SYSTEMTIME
invoke GetLocalTime, addr @stST
movzx eax, @stST.wHour
mov @Hour, eax
movzx eax, @stST.wMinute
mov @Minute, eax
movzx eax, @stST.wSecond
mov @Second, eax
mov eax, @Hour
mov ebx, 60d
mul ebx
add eax, @Minute
mul ebx
add eax, @Second
mov LocalTime, eax
mov eax, 1
mov TimeFlag, eax ; 允許及時
ret
_SetLocalTime endp
;************************************************************************
;************************************************************************
; 在狀態欄中顯示游戲中當前關卡的運行時間
;------------------------------------------------------------------------
_SetGameTime proc
local @Hour, @Minute, @Second
local @stST:SYSTEMTIME
pushad
.if TimeFlag == 1
invoke GetLocalTime, addr @stST
movzx eax, @stST.wHour
mov @Hour, eax
movzx eax, @stST.wMinute
mov @Minute, eax
movzx eax, @stST.wSecond
mov @Second, eax
mov eax, @Hour
mov ebx, 60d
mul ebx
add eax, @Minute
mul ebx
add eax, @Second
mov ecx, eax
.if ( ecx == LocalTime && !TimeCircle )
inc eax
.elseif ( ecx < LocalTime || ( ecx == LocalTime && TimeCircle > 0 ) )
mov ecx, 86400d
sub ecx, LocalTime
add TimeCircle, ecx
push eax
invoke _SetLocalTime
pop eax
.endif
add eax, TimeCircle
sub eax, LocalTime
mov edx, 0
mov ebx, 3600d
div ebx
mov GameHour, eax
mov eax, edx
mov edx, 0
mov ebx, 60d
div ebx
mov GameMinute, eax
mov GameSecond, edx
.endif
popad
ret
_SetGameTime endp
;************************************************************************
;************************************************************************
; 使窗口客戶區無效,使Windows向窗口過程發送WM_PAINT消息
;------------------------------------------------------------------------
_Repaint proc
local @rect:RECT
invoke GetClientRect, hWinMain, addr @rect
invoke InvalidateRect, hWinMain, addr @rect, 0
ret
_Repaint endp
;************************************************************************
;************************************************************************
; Pos = y * 14 + x, 其中( x, y )以0為起始坐標
; eax中存儲著( x, y )在Map中的線性邏輯地址
; edx中存儲著( x, y )在Map中線性邏輯地址對應的位圖索引值相應的位圖起始X坐標
;------------------------------------------------------------------------
_SearchMapLinePos proc uses ebx esi, x, y
mov esi, offset Map
mov eax, y
mov ebx, 14d
mul ebx
add eax, x
mov bl, [esi][eax]
.if bl == MAP_BACK
mov edx, xBmBack
.elseif bl == MAP_WALL
mov edx, xBmWall
.elseif bl == MAP_ROAD
mov edx, xBmRoad
.elseif bl == MAP_BOX1
mov edx, xBmBox1
.elseif bl == MAP_BOX2
mov edx, xBmBox2
.elseif bl == MAP_OBJECT
mov edx, xBmObject
.elseif bl == MAP_MAN
mov edx, xBmMan
.else
mov edx, xBmBomb
.endif
ret
_SearchMapLinePos endp
;************************************************************************
;************************************************************************
; 將"BitMapXPosition"打印到起始點為( xPosition, yPosition )的客戶區中
;------------------------------------------------------------------------
_PaintOneBitmap proc xPosition, yPosition, BitmapXPosition, @hDC
local x, y
pushad
mov eax, xPosition ; xPosition為在Map中的列號
mov ebx, 30d
mul ebx
mov x, eax
mov eax, yPosition ; yPosition為在Map中的行號
mov ebx, 30d
mul ebx
add eax, 30d ; 因為工具欄亦畫到客戶區中,因此要畫到客戶區以下
mov y, eax
.if @hDC == 0
invoke GetDC, hWinMain
mov @hDC, eax
invoke BitBlt, @hDC, x, y, 30, 30, hBackDC, BitmapXPosition, 0, SRCCOPY
invoke ReleaseDC, hWinMain, @hDC
.else
invoke BitBlt, @hDC, x, y, 30, 30, hBackDC, BitmapXPosition, 0, SRCCOPY
.endif
popad
ret
_PaintOneBitmap endp
;************************************************************************
;************************************************************************
; 重新繪制客戶區
;------------------------------------------------------------------------
_WMPaint proc @hDC
local i, j, x, y
mov x, 0
mov y, 30d
mov i, 1
mov j, 1
mov esi, offset Map
;--------------------------------------------------------------------------
;按照StoreHouse中相應的位圖索引將BackBitMap中的位圖像素復制到窗口的設備環境中
;--------------------------------------------------------------------------
@@NextRol:
mov x, 0
mov j, 1
@@NextCol:
;---Calc nPos, nPos = (i-1) * 14 + (j-1)
mov eax, i
dec eax
mov ebx, 14d
mul ebx
add eax, j
dec eax
mov al, [esi][eax]
.if al == MAP_BACK
invoke BitBlt, @hDC, x, y, 30, 30, hBackDC, xBmBack, 0, SRCCOPY
.elseif al == MAP_WALL
invoke BitBlt, @hDC, x, y, 30, 30, hBackDC, xBmWall, 0, SRCCOPY
.elseif al == MAP_ROAD
invoke BitBlt, @hDC, x, y, 30, 30, hBackDC, xBmRoad, 0, SRCCOPY
.elseif al == MAP_BOX1
invoke BitBlt, @hDC, x, y, 30, 30, hBackDC, xBmBox1, 0, SRCCOPY
.elseif al == MAP_BOX2
invoke BitBlt, @hDC, x, y, 30, 30, hBackDC, xBmBox2, 0, SRCCOPY
.elseif al == MAP_OBJECT
invoke BitBlt, @hDC, x, y, 30, 30, hBackDC, xBmObject, 0, SRCCOPY
.else
invoke BitBlt, @hDC, x, y, 30, 30, hBackDC, xBmMan, 0, SRCCOPY
.endif
add x, 30d
inc j
cmp j, 15d
jb @@NextCol
inc i
add y, 30d
cmp i, 13
jb @@NextRol
;------------------------------------------------------------------------
; 按照man在Map中的坐標,將他對應的像素復制到相應位置
;------------------------------------------------------------------------
invoke _PaintOneBitmap, ManXPos, ManYPos, xBmMan, @hDC
ret
_WMPaint endp
;************************************************************************
;************************************************************************
; 選擇參數@Gate指定的關卡
;------------------------------------------------------------------------
_SelectGate proc @Gate
local szTmp1[10] : byte
local szTmp2[20] : byte
mov eax, @Gate
.if ( eax > MAX_GATES || eax < 1 )
xor eax, eax
mov TimeFlag, eax
invoke MessageBox, hWinMain, addr szOutOfRange, \
addr szCaption, MB_ICONINFORMATION or MB_OKCANCEL
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -