C语言实现刮刮乐效果是示例代码
编程小鱼六六六 人气: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 <graphics.h> 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; }
加载全部内容