《WINDOWS游戏编程之从零开始》第五章学习笔记

原本粗略浏览了这一章节,就又去自己找图片素材了…

找到一半发现贴图不太好找原图,但是不想抠图,也不想用糊图,结果我下回了《美少女万华镜 4》(甚至忍不住玩了一会,剧情还是大赞的),并看了一圈 galgame 解包的教程,最后还是最方便的 GARbro 随随便便就解了 OMG. 忙活了不知道多久,并获得了很多高质量 CG、音效以及立绘。嘿嘿……回归主题。

本章讲的是透明贴图。

5.2 透明遮罩

透明遮罩用一个黑白图和一个素材图。另外还有一个背景图。

黑白遮罩图与背景图做与运算,就在背景上得到一个黑色人物轮廓。

接着,素材图与背景图做或运算,就将黑色轮廓填充了。

至于实现上,这一次更加熟悉了 BitBlt 函数.

要知道,其第一对坐标,表示的是在 DC 中开始绘制的坐标;第二对表示的是绘制的大小;第三对则是素材要用的 x、y 坐标. 就是说来源是来自你的内存 DC 的。然后最后一个参数的贴图方式里面的宏, SRC 就表示当前 DC 里面已经画上去的东西。那么 SRCCOPY 自然就是直接粘贴。

下面我们看进行透明遮罩时的示例:

先看素材:

在这里插入图片描述

首先,这是一个 2560x720 的贴图(当然我传上来的是缩略图,不完整),两边各占1280x720.

然后看函数调用(这张图的位图句柄为 g_hSprite1):

SelectObject(g_mdc, g_hSprite1);
	BitBlt(g_hdc, -320, 0, 1280, 720, g_mdc, 1280, 0, SRCAND);
	BitBlt(g_hdc, -320, 0, 1280, 720, g_mdc, 0, 0, SRCPAINT);

那么这张图在绘制的窗口中奖从(-320,0)这个坐标开始绘制,并且大小是 1280x720. 然后看第一个 BitBlt,他是从素材的(1280,0)这个坐标开始,包含一个 1280x720 的区域,并与 SRC 进行位图与运算。白色是全1,黑色是全0,那么与运算的结果就会变成:素材中白的部分没有任何改变,仍然是原来的背景,而纯黑的部分都填为纯黑了。

所以如果我们不进行第二步,就会得到这样的结果:

在这里插入图片描述

所以,我们还需要一步,再让上图和素材中(0,0)开始的 1280x720 个像素进行或运算(SRCPAINT),就得到的最终的图。

两个位图进行透明遮罩的显示结果:

在这里插入图片描述

然而,其实解包之后,游戏文件里面的图本身就是透明的,遮罩图都是我自己用ps抠出来的,难免会有一些像素点没抠到位,这里不是重点,主要是要实现透明贴图。也说明《美少女万华镜4》本身就没有使用这一技术。当然, .bmp 本身就没有透明像素,现在谁还用 BITMAP 文件啊…

我的 Game_Init() 函数:

BOOL Game_Init(HWND hwnd)
{
	g_hdc = GetDC(hwnd);

	// STEP1
	g_hBackGround = (HBITMAP)LoadImage(NULL, L"11.bmp", IMAGE_BITMAP, WINDOW_WIDTH, WINDOW_HEIGHT, LR_LOADFROMFILE);
	g_hSprite1 = (HBITMAP)LoadImage(NULL, L"夕莉1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
	g_hSprite2 = (HBITMAP)LoadImage(NULL, L"夕莉2.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);


	// STEP2
	g_mdc = CreateCompatibleDC(g_hdc);

	Game_Paint(hwnd);
	ReleaseDC(hwnd, g_hdc);
	return TRUE;
}

我的 Game_Paint() 函数:

VOID Game_Paint(HWND hwnd)
{
	SelectObject(g_mdc, g_hBackGround);
	BitBlt(g_hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_mdc, 0, 0, SRCCOPY);


	SelectObject(g_mdc, g_hSprite1);
	BitBlt(g_hdc, -320, 0, 1280, 720, g_mdc, 1280, 0, SRCAND);
	BitBlt(g_hdc, -320, 0, 1280, 720, g_mdc, 0, 0, SRCPAINT);

	SelectObject(g_mdc, g_hSprite2);
	BitBlt(g_hdc, 320, 0, 1280, 720, g_mdc, 1280, 0, SRCAND);
	BitBlt(g_hdc, 320, 0, 1280, 720, g_mdc, 0, 0, SRCPAINT);
}

如果需要素材可以留言 😃

5.3 透明色彩

透明色彩比透明遮罩更加直观简单:指定某种特定的颜色为透明的。这其实就是影片中广泛应用的“绿幕素材”。

指定的颜色通常称为 ColorKey, 色键。

要做到透明色彩,只需要熟悉一下另一个贴图函数:TransparentBlt(). 注意使用要链接 Msimg32.lib.

话不多说,直接用起来。

在这里插入图片描述

然而暂时不知道是什么原因…上网查了很多,都没有发现代码中的错误。有可能是图片的?

在保存的时候我将 .png 另存为 .bmp文件时选择的是 24位色彩,但一般应该用 32位?我觉得影响不在这里。暂时先放着不管。更不用说,虽然 TransparentBlt() 方便,但总会有黑边出现(这就是一般的素材会使用绿幕的原因,一般绿色很少出现在图像上,但黑色就不一定了)

所以,如果要绘制一个带透明效果的位图,老老实实使用遮罩法。

其实我在其他游戏的文件里也见过这样的遮罩来着。

诶,从上图可以看到刚刚重新抠出来的图更细腻了,没有杂色像素,尝试重新制作遮罩图并使用遮罩看看效果:

在这里插入图片描述

嗨呀,还是没有更好,只是黑边更加有规则了……

图源的,都是图源的……

万一遮罩真会常用的话,那我还得好好学学怎么制作遮罩图。这种级别的黑边可完全上不了台面。

总结

OK!

如果要熟悉,以后自然大有机会;如果不需要熟悉,那则啥事没有。总之,在一些细小的地方无需太过纠结,不管这些东西重不重要,你需不需要,现在纠结都是没用的。

明天开始学习第六章 2D 动画的制作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值