程序简介
这个程序模拟了刮刮乐的刮卡操作,按下鼠标左键并移动可以刮开刮卡层。
刮卡操作是通过掩码图实现的,一张隐藏的待刮开背景图,一张掩码图。
刮卡的时候,是在黑色的掩码图上画线,显示的时候,通过掩码图将背景图显示出来。
现在具体说一下显示方式:
首先,背景图就是普通的 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;
-
}
转载:https://blog.csdn.net/yx5666/article/details/128631621