📄 1.asm
字号:
pop g_pTail
push 0
pop g_NodeCount
mov ecx,8
L5:
push ecx
L4:
invoke Random,50
mov x2,eax
invoke Random,50
mov y2,eax
mov edx,50
mul edx
add eax,x2
mov ebx,OFFSET g_Map
add ebx,eax
mov al,BYTE PTR [ebx]
cmp al, MAP_NONE
jne L4
mov BYTE PTR[ebx],MAP_WALL
pop ecx
loop L5
invoke DrawMap
invoke Flip
push DR_RIGHT
pop g_Direct
push GS_PLAY
pop g_GameState
invoke SetTimer,g_hWnd,TIMER1_ID,TIMER1_INTERVAL,addr TimeProc ;创建定时器1 :120ms
invoke SetTimer,g_hWnd,TIMER2_ID,TIMER2_INTERVAL,addr TimeProc2 ;创建定时器2 :3s
ret
NewGame endp
DrawMap proc ;画地图的子程序
LOCAL x,y :DWORD ;注意地图的底,其实已经画好了
LOCAL i,j :DWORD ;这个子程序就是在底上画上“豆子”和“蛇”
LOCAL Pos:DWORD
LOCAL pNode :DWORD
invoke Rectangle,g_hBackDc,0,0,400,400
mov j, 0 ;j是行,先=0
mov Pos, 0 ;相对的坐标
@@1:
mov i, 0 ;i是列,=0
@@2:
mov ebx ,offset g_Map
add ebx,Pos
mov al,byte ptr [ebx]
.if al == MAP_WOOD ;画豆'
mov eax, i
shl eax,3 ; i*8
mov x , eax
mov eax ,j
shl eax ,3 ; j*8
mov y,eax
invoke BitBlt,g_hBackDc,x,y,8,8,g_hImgDc,8,0,SRCCOPY
.elseif al==MAP_WALL
mov eax, i
shl eax,3 ; i*8
mov x , eax
mov eax ,j
shl eax ,3 ; j*8
mov y,eax
invoke BitBlt,g_hBackDc,x,y,8,8,g_hImgwallDc,0,0,SRCCOPY
.endif
inc i
inc Pos
cmp i,50 ;不足一列,继续循环
jnz @@2
inc j ;一列完,行加1
cmp j,50 ;行没到50,继续循环
jnz @@1
;-- Draw Snake 画蛇
mov ebx , g_pHead
@@3:
cmp ebx , NULL
jz @@Break
mov pNode ,ebx ;保存蛇头的值 ???问题蛇头是怎么处理的,是不是4个字节4个字节的数据结构
mov eax ,[ebx+4] ;x
shl eax , 3 ;x*8
mov x,eax
mov eax, [ebx+8] ;y*8
shl eax,3
mov y,eax
mov eax ,[ebx+12] ;next
mov pNode ,eax ;
invoke BitBlt,g_hBackDc,x,y,8,8,g_hImgDc,0,0,SRCCOPY
mov ebx,pNode
jmp @@3
@@Break:
ret
DrawMap endp
KeyDownProc proc dwKey :DWORD
.if g_GameState != GS_PLAY
ret
.endif
mov eax,dwKey
.if eax == VK_UP ;如果按下的是上
.if g_Direct != DR_DOWN ;蛇头不是向后的,才行
push DR_UP
pop g_Direct ;蛇头改为朝上
.endif
.elseif eax == VK_DOWN ;如果按下的是下
.if g_Direct != DR_UP ;蛇头不是向上的,才行
push DR_DOWN
pop g_Direct ;蛇头改为朝下
.endif
.elseif eax == VK_LEFT ;如果按下的是左
.if g_Direct != DR_RIGHT ;蛇头不是向右的,才行
push DR_LEFT
pop g_Direct ;蛇头改为朝左
.endif
.elseif eax == VK_RIGHT ;如果按下的是右
.if g_Direct != DR_LEFT ;蛇头不是向左的,才行
push DR_RIGHT
pop g_Direct ;蛇头改为朝右
.endif
.endif
ret
KeyDownProc endp
FreeGame proc ;释放程序中创建的一些资源
LOCAL pNode :DWORD
.if g_pHead == NULL
ret
.endif
;Kill Timer
invoke KillTimer,g_hWnd,TIMER1_ID ;释放定时器1
invoke KillTimer,g_hWnd,TIMER2_ID ;释放定时器2
; Clear Map
invoke RtlZeroMemory,addr g_Map,50*50
; Free The Snake
mov ebx , g_pHead
mov eax ,[ebx+12] ;pNext
mov pNode ,eax
@@1:
invoke LocalFree, ebx ; free mem
mov ebx,pNode
cmp ebx,NULL
jz @@Break
mov eax,[ebx+12]; pNext
mov pNode ,eax
jmp @@1
@@Break:
mov eax, NULL
mov g_pHead ,eax
mov g_pTail ,eax
push 0
pop g_NodeCount
push GS_STOP
pop g_GameState
ret
FreeGame endp
MsgBox proc
invoke MessageBox,g_hWnd,addr AppName,addr AppName,MB_OK
ret
MsgBox endp
Random proc Range:DWORD ;生成随数的子程序
mov eax, g_RandomSeed
mov ecx, 23
mul ecx
add eax, 7
and eax, 0FFFFFFFFh
ror eax, 1
xor eax, g_RandomSeed
mov g_RandomSeed, eax
mov ecx, Range
xor edx, edx
div ecx
mov eax, edx
ret
Random endp
TimeProc proc hWnd:HWND,uMsg:UINT,idEvent :UINT,dwTime:DWORD
LOCAL pNode:DWORD ; ;功能是叫蛇向前移动
LOCAL Pos:DWORD
LOCAL x1,y1:DWORD
pushad ;保存所有寄存器
invoke KillTimer,g_hWnd,TIMER1_ID ;关定时器
mov ebx , g_pHead
mov eax,[ebx+4]
mov x1,eax
mov eax,[ebx+8]
mov y1,eax
mov eax, g_Direct
.if eax == DR_LEFT ;方向是左,就把头的列-1
dec x1
cmp x1,0
jge @@1
invoke GameOver ;看看到了地图边上没有,到边上就死了
popad
ret
.elseif (eax==DR_RIGHT)
inc x1
cmp x1,50
jle @@1
invoke GameOver
popad
ret
.elseif(eax==DR_UP)
dec y1
cmp y1,0
jge @@1
invoke GameOver
popad
ret
.elseif(eax==DR_DOWN)
inc y1
cmp y1,50
jle @@1
invoke GameOver
popad
ret
.endif
@@1:
mov eax,y1
mov ecx,50
mul ecx
add eax,x1
mov ebx,OFFSET g_Map
add ebx,eax
mov Pos,ebx
mov al, BYTE PTR[ebx]
.if(al==MAP_WOOD) ;加一个身长
inc g_NodeCount
invoke wsprintf,addr g_szBuffer, addr FmtStrNodeCount,g_NodeCount ;输出为g_szBuffer,输入为FmtStrNodeCount,g_NodeCount
invoke SendDlgItemMessage,g_hWnd,IDC_SBR1,SB_SETTEXT,2,addr g_szBuffer ;工具栏的显示
mov esi,g_pHead
invoke LocalAlloc ,LPTR,sizeof(SNode)
mov g_pHead,eax
mov edi,eax
mov pNode,eax
mov [esi],eax
mov eax,esi
mov [edi+12],eax ;后一个和前一个链接好
mov eax,NULL
mov [edi],eax
mov al,MAP_NODE ;更改地图里的值
mov eax,Pos
mov BYTE PTR[eax],al
invoke SetTimer,g_hWnd,TIMER2_ID,TIMER2_INTERVAL,addr TimeProc2
jmp L
.elseif(al==MAP_NONE)
jmp L3
.elseif(al==MAP_NODE)
invoke GameOver
popad
.elseif(al==MAP_WALL)
invoke GameOver
popad
.endif
L3:
mov eax,g_pTail
mov pNode,eax
mov ebx,[eax+4]
mov eax,[eax+8]
mov ecx ,50
mul ecx
add eax,ebx
mov ebx,OFFSET g_Map
add eax,ebx
mov BYTE PTR[eax],MAP_NONE
.while(1)
mov eax,pNode
mov esi,[eax]
.if(esi==NULL)
jmp L
.endif
mov ebx,[esi+4]
mov [eax+4],ebx
mov ebx,[esi+8]
mov [eax+8],ebx
mov edx,[eax+8]
mov pNode,esi
.endw
L:
mov ebx,x1
mov eax,pNode
mov [eax+4],ebx
mov ebx,y1
mov [eax+8],ebx
mov eax,y1
mov ecx,50
mul ecx
add eax,x1
mov ebx,OFFSET g_Map
add ebx,eax
mov al,MAP_NODE
mov byte PTR[ebx],al
invoke DrawMap
invoke Flip
invoke SetTimer,g_hWnd,TIMER1_ID,TIMER1_INTERVAL,addr TimeProc ;又再创建定时器1
mov eax,food
.if(eax==g_NodeCount)
push GS_STOP
pop g_GameState
invoke KillTimer,g_hWnd,TIMER2_ID ;关定时器2
invoke KillTimer,g_hWnd,TIMER1_ID ;关定时器1
invoke MessageBox,g_hWnd,addr success,addr AppName,MB_ICONINFORMATION
.endif
popad ;恢复所有寄存器
ret
TimeProc endp
TimeProc2 proc hWnd:HWND,uMsg:UINT,idEvent:UINT,dwTime:DWORD ;每三秒在地图上放一个豆
LOCAL x,y:DWORD
LOCAL Pos:DWORD
pushad
L1:
invoke Random, 50
mov x,eax
invoke Random,50
mov y,eax
mov ecx,50
mul ecx
add eax,x
mov Pos,eax
mov ebx,OFFSET g_Map
add eax,ebx
mov al,byte ptr [eax]
.if(al!=0)
jmp L1
.else
jmp L2
.endif
L2:
mov ebx,offset g_Map ;如果不是0的话,就可以放豆
add ebx,Pos ;下面的代码就是放豆
mov al ,MAP_WOOD ;wood就是豆,呵呵,是不是应该取名为food更好些呢?
mov byte ptr [ebx],al
invoke KillTimer,g_hWnd,TIMER2_ID
invoke DrawMap
invoke Flip
popad
ret
TimeProc2 endp
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -