IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> x86汇编游戏——2048 -> 正文阅读

[开发工具]x86汇编游戏——2048

2.1游戏界面绘制

游戏界面绘制窗口程序主要有_WinMain和_ProcWinMain两个函数来构成。

_WinMain是生成窗口的主函数,主要流程为:

(1)得到应用程序句柄

(2)注册窗口类

(3)建立窗口

(4)显示窗口

(5)刷新窗口客户区

(6)维护消息获取和处理的循环

通过GetMessage获取消息

TranslateMessage翻译消息

DispatchMessage分派消息给回调函数处理

通过User32来调用回调函数

_ProcWinMain是用来处理消息的,是窗口的回调函数,也叫窗口过程。消息如WM_PAINT,WM_CHAR等。

2.1.1 界面构成

界面主要由4个部分3个模块构成.

4个部分分别是

?(1)游戏主体部分的方块

?(2)游戏说明部分

?(3)显示得分部分

?(4)游戏名称部分

3个模块分别是

?(1)静态控件'Static'绘制游戏模块

?(2)文本框'edit'绘制得分和游戏说明

?(3)位图装饰界面

2.1.2 绘制静态控件

需要绘制4X4的方块,采用一个2重循环,通过i,j控制绘制的位置和绘制的控件ID

L6:
	;eax=i*100+140,绘制的x坐标,140为起始坐标
	imul eax,i,100
	add eax,140
	;ecx=j*100+100,绘制的y坐标,100为起始坐标
	imul ecx,j,100
	add ecx,100

	;edx=i*4+j,表示第[i][j]个方块
	imul edx,i,4
	add edx,j
	;gameMat[i][j]的值转为字符数组存到Data中,dword:*4
	invoke num2byte,dword ptr gameMat[edx*4]
	;如果为0
	;eax=i*100+140,绘制的x坐标,140为起始坐标
	imul eax,i,100
	add eax,140
	;ecx=j*100+100,绘制的y坐标,100为起始坐标
	imul ecx,j,100
	add ecx,100
	.IF Data[0] =='0'
		;创建静态控件,居中有边框
		invoke CreateWindowEx,NULL,offset static,offset EmptyText,\
		WS_CHILD or WS_VISIBLE or SS_CENTER or WS_BORDER or SS_CENTERIMAGE,ecx,eax,100,100,\  
		hWnd,edx,hInstance,NULL  ;句柄为edx
	.else
		invoke CreateWindowEx,NULL,offset static,offset Data,\
		WS_CHILD or WS_VISIBLE or SS_CENTER or WS_BORDER or SS_CENTERIMAGE,ecx,eax,100,100,\ 
		hWnd,edx,hInstance,NULL  ;句柄为edx
	.endif
	;edx=i*4+j,表示第[i][j]个方块
	imul edx,i,4
	add edx,j
	;存储窗口句柄,句柄返回值在eax中
	mov hGame[edx*4],eax

2.1.2 绘制文本框

绘制文本框同绘制方块一样,通过调用CreateWindowEx函数,指定对应的值即可,由于文本框可以在界面上进行编辑,所以绘制时指定为禁用状态。

L7:
	;绘制游戏说明部分
	;创建文本框,但设为Disabeled防止玩家更改
	invoke CreateWindowEx,NULL,offset edit,offset szText1,\
	WS_CHILD or WS_VISIBLE OR WS_DISABLED,100,60,120,15,\
	hWnd,16,hInstance,NULL
	MOV hGame[64],eax
	invoke CreateWindowEx,NULL,offset edit,offset szText2,\
	WS_CHILD or WS_VISIBLE OR WS_DISABLED,100,75,400,15,\
	hWnd,17,hInstance,NULL
	mov hGame[68],eax
	invoke CreateWindowEx,NULL,offset edit,offset szText5,\
	WS_CHILD or WS_VISIBLE OR WS_DISABLED,100,90,400,15,\
	hWnd,18,hInstance,NULL
	mov hGame[72],eax
	invoke CreateWindowEx,NULL,offset edit,offset szText3,\
	WS_CHILD or WS_VISIBLE OR WS_DISABLED,100,105,400,15,\
	hWnd,19,hInstance,NULL
	mov hGame[76],eax
	invoke CreateWindowEx,NULL,offset edit,offset szText4,\
	WS_CHILD or WS_VISIBLE OR WS_DISABLED,100,120,400,15,\
	hWnd,20,hInstance,NULL
	mov hGame[80],eax

2.1.3 绘制位图

加载位图主要通过调用gdi32库所支持的API,其主要流程为:

具体实现代码如下:

		;加载位图
		;首先获取窗口DC
		invoke GetDC, hWnd
		mov @hDc,eax
		
		;创建兼容窗口DC的缓存dc
		invoke CreateCompatibleDC,@hDc
		mov hdcIDB_BITMAP1,eax
		
		invoke CreateCompatibleDC,@hDc
		mov hdcIDB_BITMAP2,eax
		
		;创建位图缓存
		invoke CreateCompatibleBitmap, @hDc,150,80
		mov hbmIDB_BITMAP1,eax

		invoke CreateCompatibleBitmap, @hDc,90,60
		mov hbmIDB_BITMAP2,eax

		;将hbm与hdc绑定
		invoke SelectObject,hdcIDB_BITMAP1,hbmIDB_BITMAP1
		
		;载入位图到位图句柄中
		invoke LoadBitmap,hInstance,BITMAP1
		mov @hBm,eax
		;创建以位图为图案的画刷
		invoke CreatePatternBrush,@hBm
		push eax
		;以画刷填充缓存DC
		invoke SelectObject,hdcIDB_BITMAP1,eax
		;按照PATCOPY的方式
		invoke PatBlt,hdcIDB_BITMAP1,0,0,150,80,PATCOPY
		pop eax
		;删除画刷
		invoke DeleteObject,eax
		;在主窗口DC上绘制位图dc
		invoke BitBlt,@hDc,90,0,150,80,hdcIDB_BITMAP1,0,0,SRCCOPY

2.1.4 显示数字和分数

我们通过使用一个数组gameMat来保存游戏的局面,由于存储的是数字,所以需要通过不断除以10,按位转换为数字字符串来显示,之后调用SetWindowText函数显示文字。

L7:
	;绘制游戏说明部分
	;创建文本框,但设为Disabeled防止玩家更改
	invoke CreateWindowEx,NULL,offset edit,offset szText1,\
	WS_CHILD or WS_VISIBLE OR WS_DISABLED,100,60,120,15,\
	hWnd,16,hInstance,NULL
	MOV hGame[64],eax
	invoke CreateWindowEx,NULL,offset edit,offset szText2,\
	WS_CHILD or WS_VISIBLE OR WS_DISABLED,100,75,400,15,\
	hWnd,17,hInstance,NULL
	mov hGame[68],eax
	invoke CreateWindowEx,NULL,offset edit,offset szText5,\
	WS_CHILD or WS_VISIBLE OR WS_DISABLED,100,90,400,15,\
	hWnd,18,hInstance,NULL
	mov hGame[72],eax
	invoke CreateWindowEx,NULL,offset edit,offset szText3,\
	WS_CHILD or WS_VISIBLE OR WS_DISABLED,100,105,400,15,\
	hWnd,19,hInstance,NULL
	mov hGame[76],eax
	invoke CreateWindowEx,NULL,offset edit,offset szText4,\
	WS_CHILD or WS_VISIBLE OR WS_DISABLED,100,120,400,15,\
	hWnd,20,hInstance,NULL
	mov hGame[80],eax

	;绘制分数框
	invoke num2byte,score
	invoke CreateWindowEx,NULL,offset edit,offset Data,\
	WS_CHILD or WS_VISIBLE OR WS_DISABLED,420,38,80,15,\ 
	hWnd,21,hInstance,NULL
	mov hGame[84],eax

	xor eax,eax
	ret

2.1.5 显示游戏胜利和失败消息

通过维护gameIsEnd,gameIsWin和gameContinue三个变量。

游戏失败时,gameIsEnd置1,弹出游戏失败提示消息,点击OK重新开始游戏。

游戏胜利时,gameIsWin置1,弹出游戏胜利提示消息,玩家可选择继续游戏或结束游戏。

若游戏继续,gameContinue置1,则之后不再对游戏是否胜利进行判断。

2.2生成新模块

2.3方块移动及合并

方块的移动分为四个方向,所以首先设想为该模块编写四个函数,分别实现上下左右的移动的实现。通过沟通,我们将输入字符WASD分别代表向上、向左、向下、向右移动。

?

2.3.1移动方向以及起点

上图的四个函数的实现过程,直观上讲有如下效果:

?

通过对16个方块按行或按列进行划分,然后我们对每个方向的行或列进行遍历,之后通过遍历过程中某方块和他周围方块的关系进行比较,如此实现整个遍历过程。例如我们对向右的移动进行分析,我们就会把所有方块按行分组,对每一行的每一个方块进行遍历。

完成分治后,我们还要对遍历起点进行分析。在实现过程中,我采用了Loop的方式进行循环,所以我们的循环起点始终为4,之后不断递减形成循环。此时我们对不同方向的移动起点进行分析,可知我们的起点如图所示:

2.3.2合并实现

确定了循环起点后,我们还要对具体的方块移动方向进行确定。此处我们仍对D方向(向右移动)进行分析。在游戏过程中,我们发现,每个方块都会和其左边的方块进行比较,若某方块的左边出现相同数字或者该相同数字和数字0一同出现,则会进行合并。如此,我们就确定了每个循环中行或列的遍历方向是与移动方向相反的,如此才能更快更好的实现该功能。在确定了循环内遍历方向后,我们自然会向确定移动方向一样,对每个行或列的所有方块抽象为一个状态,并对每个状态进行遍历判断。事实上,在开发过程中我发现整个过程可以抽象为一个递归的判断过程,这样实现就更加简单。其具体实现思想如下:

我们不再对每个方向上的四个方块分别抽象,而是对其状态进行抽象:

1)是否为0

如果我们遍历到该数字为0的话,我们直接跳过,因为我们不需要对0进行任何操作;

2)左右是否为0

如果是在移动过程,在其移动方向上若存在0(存在0就说明有空方块,有位置支持移动),我们就对该方块进行移动,即0和非零数字的交换,然后继续进行判断,若到达边界或没有空方块则无法进行移动,我们对其进行合并功能的判断。

??????????

3)忽略0后是否有相同数字

我们知道在合并过程中,我们会对移动过程的反方向进行判断,当然判断过程中,我们仍需要对是否有0(即是否有空方方块)进行判断,若有则直接跳过,继续遍历;若遇到相同数字,直接合并,并将遍历到的数字置为0,若没有或者遍历越界,则对循环中的下一个方块进行如上方式的判断,如此就能完成每一行或列的移动和合并。

?????????

3.完整代码X86-2048: x86汇编语言编写的2048游戏 (gitee.com)https://gitee.com/chris-william/x86-2048

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 22:25:26  更:2022-03-11 22:26:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:25:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码