C语言刮刮乐(掩码图的范例)
创始人
2024-05-10 04:42:22
0

程序简介

这个程序模拟了刮刮乐的刮卡操作,按下鼠标左键并移动可以刮开刮卡层。

刮卡操作是通过掩码图实现的,一张隐藏的待刮开背景图,一张掩码图。

刮卡的时候,是在黑色的掩码图上画线,显示的时候,通过掩码图将背景图显示出来。

现在具体说一下显示方式:

首先,背景图就是普通的 IMAGE 对象,不做任何处理。

其次,掩码图中,未刮开区域对应的是黑色,已刮开区域对应的是白色。

显示的步骤:

1. 将背景图中未刮开的区域置为黑色:

操作目标(D):背景图
操作源(S):掩码图
操作:背景图 AND 掩码图
⇒ 操作目标 AND 操作源 ⇒ D a S ⇒ DSa(后缀表达式),可以在三元光栅操作码中找到 DSa 对应的操作码是 008800C6(SRCAND)。

2. 将覆盖层中已刮开的区域置为黑色:

操作目标(D):覆盖层
操作源(S):掩码图
操作:覆盖层 AND (NOT 掩码图)
⇒ 操作目标 AND (NOT 操作源) ⇒ D a (n S) ⇒ DSna(后缀表达式),可以在三元光栅操作码中找到 DSna 对应的操作码是 00220326。

3. 将背景图合并到覆盖层中,就是将前两步的 IMAGE 图像进行 OR 操作合并:

操作目标(D):覆盖层
操作源(S):背景图
操作:覆盖层 OR 背景图
⇒ 操作目标 OR 操作源 ⇒ D o S ⇒ DSo(后缀表达式),可以在三元光栅操作码中找到 DSo 对应的操作码是 00EE0086(SRCPAINT)。

以上步骤,就是显示刮卡效果的函数的原理:

// 显示刮卡效果
void Show()
{IMAGE tmp = imgContent;SetWorkingImage(&tmp);putimage(0, 0, &imgMask, SRCAND);					// 将背景图中未刮开的区域置为黑色SetWorkingImage();putimage(offsetx, offsety, &imgMask, 0x00220326);	// 将覆盖层中已刮开的区域置为黑色putimage(offsetx, offsety, &tmp, SRCPAINT);			// 将背景图合并到覆盖层中
}

同时,该程序还使用了用图像填充区域的技术,以及输出字符符号的技术。

程序执行效果: 

友情提示:更换一下刮奖区的文字,可能是一件有趣的事情。

完整源代码:


//
// 程序名称:C语言刮刮乐(掩码图的范例)
// 编译环境:Visual C++ 6.0 ~ 2019,EasyX_20220116
//
#include const int offsetx = 170;		// 刮奖区的偏移 x 坐标
const int offsety = 260;		// 刮奖区的偏移 y 坐标IMAGE imgContent(300, 100);		// 刮开后的内容
IMAGE imgMask(300, 100);		// 已刮部分的掩码层// 绘制刮刮卡
void DrawCard()
{// 白色背景setbkcolor(0xf0f0f0);cleardevice();// 设置刮刮卡填充单元IMAGE unit(32, 32);SetWorkingImage(&unit);						// 设置绘图设备为 unit 对象setbkcolor(0x1a3bf0);						// 设置背景色cleardevice();settextstyle(20, 0, _T("Webdings"), 0, 0, 400, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH);	// 设置图标字体settextcolor(0x152fe5);outtextxy(0, 16, 0x59);						// 输出两个心outtextxy(16, 0, 0x59);settextcolor(0x284ff5);outtextxy(0, 0, 0x73);						// 输出两个问号outtextxy(16, 16, 0x73);SetWorkingImage();// 用 IMAGE 对象填充矩形区域setfillstyle(BS_DIBPATTERN, NULL, &unit);	// 设置填充模式solidrectangle(150, 30, 490, 450);			// 画填充矩形TCHAR s[] = _T("刮刮乐");settextstyle(80, 0, _T("黑体"), 0, 0, 400, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH);setbkmode(TRANSPARENT);settextcolor(0x034089);outtextxy(offsetx + (300 - textwidth(s)) / 2 + 5, 105, s);settextcolor(0x10c2fe);outtextxy(offsetx + (300 - textwidth(s)) / 2, 100, s);// 设置覆盖层填充单元IMAGE unit2(80, 50);SetWorkingImage(&unit2);					// 设置绘图设备为 unit 对象setbkcolor(LIGHTGRAY);cleardevice();settextstyle(20, 0, _T("黑体"), 150, 150, 400, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH);settextcolor(0x606060);outtextxy(10, 20, _T("刮奖区"));SetWorkingImage();// 用 IMAGE 对象填充矩形区域setfillstyle(BS_DIBPATTERN, NULL, &unit2);	// 设置填充模式solidrectangle(offsetx, offsety, offsetx + 300, offsety + 100);		// 画填充矩形
}// 初始化刮奖区内容
void InitContent()
{// 绘制刮奖区内容SetWorkingImage(&imgContent);setbkcolor(0x05d5ff);cleardevice();settextcolor(0x0024b8);TCHAR s1[] = _T("EasyX");TCHAR s2[] = _T("点亮你的创造力");settextstyle(40, 0, _T("黑体"), 0, 0, 900, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH);outtextxy((300 - textwidth(s1)) / 2, 10, s1);outtextxy((300 - textwidth(s2)) / 2, 50, s2);// 绘制刮卡的掩码图SetWorkingImage(&imgMask);setbkcolor(BLACK);cleardevice();setlinestyle(PS_SOLID, 10);		// 设置刮卡操作的粗细SetWorkingImage();
}// 实现刮卡操作
void Scrape(int x1, int y1, int x2, int y2)
{SetWorkingImage(&imgMask);line(x1, y1, x2, y2);
}// 显示刮卡效果
void Show()
{IMAGE tmp = imgContent;SetWorkingImage(&tmp);putimage(0, 0, &imgMask, SRCAND);					// 将背景图中未刮开的区域置为黑色SetWorkingImage();putimage(offsetx, offsety, &imgMask, 0x00220326);	// 将覆盖层中已刮开的区域置为黑色putimage(offsetx, offsety, &tmp, SRCPAINT);			// 将背景图合并到覆盖层中
}// 主函数
int main()
{initgraph(640, 480);	// 初始化图形窗口DrawCard();				// 绘制刮刮乐卡片InitContent();			// 初始化刮奖区内容// 获取鼠标消息,实现刮卡操作ExMessage msg;int x, y, oldx, oldy;bool scrape = false;while(true){msg = getmessage(EM_MOUSE);switch(msg.message){case WM_LBUTTONDOWN:scrape = true;x = oldx = msg.x - offsetx;y = oldy = msg.y - offsety;Scrape(oldx, oldy, x, y);break;case WM_LBUTTONUP:scrape = false;break;case WM_MOUSEMOVE:if (scrape){oldx = x;oldy = y;x = msg.x - offsetx;y = msg.y - offsety;Scrape(oldx, oldy, x, y);}break;}// 显示当前结果Show();}return 0;
}

小鱼快来啊的个人空间-小鱼快来啊个人主页-哔哩哔哩视频哔哩哔哩小鱼快来啊的个人空间,提供小鱼快来啊分享的视频、音频、文章、动态、收藏等内容,关注小鱼快来啊账号,第一时间了解UP注动态。编程学习群:725022484 每天分享一个编程小游戏~C/C++游戏源码素材及各种安装包, 私信不常看!https://space.bilibili.com/1827181878?spm_id_from=333.788.0.0

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...