本系列文章由七十一雾央编写,转载请注明出处。
http://blog.csdn.net/u011371356/article/details/9313239
作者:七十一雾央 新浪微博:http://weibo.com/1689160943/profile?rightmod=1&wvr=5&mod=personinfo
对于一个游戏来说,画面的华丽程度在很大程度上决定了它的火热程度,记得以前初中时候我在网上找游戏玩时,首先看的就是画面是不是好看,技能是不是酷炫,呵呵。而精美游戏的实现就是通过贴图来实现啦,因此要想做出一个好游戏,光有Coder是不够的,必须要有给力的美工,当然还要有好的策划,好的数值设定什么的。不过大家自己学做游戏也不用担心素材的问题了,网上有很多,大家如果不是做商业游戏,用别人的是没什么问题的。
在这一节笔记里,我会讲解使用CBitmap和CImage两种贴图方式,并且会讲解一下透明贴图的实现。我先解释一下,所谓透明贴图,是指贴图只贴前景图,背景和大背景融合,比如大家贴了一张地图后,要在上面再贴一个小人,如果不采用透明贴图的话,那么小人图的背景也会被贴上。
一、一些基本的知识
创建一个窗口之后,显示的屏幕上便划分出三个区域,即屏幕区(Screen),窗口区(Window)与内部窗口区(Client)DeviceContext(设备内容)一般简称为DC,简单来说,DC就是程序可以进行绘图的地方。
若要取得窗口的DC,可以调用下面这个函数:
HDC GetDC(); //取得DC
若使用GetDC()函数取得窗口DC后,必须使用ReleaseDC()函数将DC释放。
Int ReleaseDC(HDC 要释放的DC名称);//释放DC,若运行成功,返回整数1,若失败返回0
我简单解释一下需要释放DC的原因:
每个进程的GDI句柄数是由上限的(在注册表中配置,一般值为10000)。如果不关闭,就会有句柄泄露(这些句柄会在进程结束时被关闭)。大家在编程要养成良好的习惯,就如同new的空间用完一定要delete一样,虽然可能表面上不会影响你的程序的运行,但是埋下了隐患。
在我们建立的MFC单文档程序中,大家在调整好窗口后,剩下的文件大家就只需要关注CChildView.h和CChildView.cpp这两个文件了,这个视图类会展示出程序的画面。
大家需要定义变量或者属性的时候可以在ChildView.h里面进行,就作为这个类的成员变量就好了。这些变量如果需要初始化,请放在ChildView.cpp中的BOOLCChildView::PreCreateWindow(CREATESTRUCT&cs) 函数里进行。在后面的教程中,如果未特别说明,就是按照这个规则来的。
在ChildView.h中有个函数void CChildView::OnPaint() ,这个就是绘图函数啦,我们需要绘制在屏幕上的所有东西就丢给它就好了。当产生WM_PAINT绘图消息时(比如别的窗口从我们的游戏窗口经过了等,就需要重新绘制一遍画面,windows就会产生一个WM_PAINT消息加入到程序的消息队列中去),这个OnPaint()函数就会被调用一遍。但是大家知道,游戏为了保持一个高的帧数(FPS),是需要不断的重绘画面的,因此我们就需要使得这个OnPaint()函数不断的被执行,这个可以采用定时器来做到,在后面我会进行讲解。
因此,在程序中绘图部分,我们首先要知道的是画图的地方,即获得DC,通过GetDC这个API可以实现,接着需要做的就是获得画图地方的大小,就是内部窗口区(Client),这个微软为我们提供了GetClientRect这个API,然后我们就可以画图啦,当然在最后需要释放DC哦。
讲了这么多,我们开始动手写代码吧。
大家在CChildView.h中加入变量定义
CRect m_client;
我解释一下,CRect 是一个矩形类,它由四个成员变量:top,bottom,left,right,可以用来记录一个矩形的左上角和右下角的坐标,一般我们都是用它来保存一个矩形物体的大小的。
接下来,在CChildView.cpp中的voidCChildView::OnPaint()函数中写入下面的代码就好了
CDC *cDC=this->GetDC(); //获得当前窗口的DC
GetClientRect(&m_client); //获得窗口的尺寸
//加入我们要绘制的代码。。。。。。
ReleaseDC(cDC); //释放DC
到现在绘图的准备工作都做完了,接下来我们就开始绘图了。
二、使用CBitmap类进行绘图
大家看名字就可以知道,这个类是用来绘制位图的,即以“.bmp”为后缀的图片。一般游戏之中,需要使用的图片比较多,都会将图片先存为文件,然后从文件中读取,而从文件中读取图片的步骤有以下几步:
1.建立一个与窗口DC兼容的内存DC
我们加载的图片是需要先放在一个内存中的DC里,然后把需要显示的图片从内存DC中绘到窗口DC中即可,我们可以认为内存DC就是一个个备胎,每个DC都是一个屌丝男士,窗口DC就是女神啦,女神需要谁去帮忙做事的时候,那个屌丝男士就和女神在一起了,当然是暂时的,呵呵。
我们首先定义一个内存DC对象;
CDC m_bgcDC;
然后就开始创建一个DC了;
m_bgcDC.CreateCompatibleDC(NULL);
看名字我们就可以知道它的意思了,创建一个兼容的DC。它的参数是CDC*类型的,即一个DC的指针,函数会创建和参数DC兼容的DC。如果我们将参数填为NULL,函数会自动创建和当前程序DC兼容的内存DC,所以我们可以直接设置为NULL。
2.加载资源中的位图
首先将位图添加进资源中,方法是右键工程名->添加->资源,选择Bitmap,点击导入,然后找到你的位图即可。位图添加进来后会有一个ID,大家在资源视图下的Bitmap那一栏下可以看到,位图的ID可以修改,默认是第一章是IDB_BITMAP1,事实上它是一个整型数字。大家可以将其编号为连续的数字,方便在循环中加载位图,和使用它们来显示动画效果。
接下来,就是代码部分了,我们先定义一个位图对象;
CBitmap m_bgBitmap;
然后就可以从资源中加载了
m_bgBitmap.LoadBitmap(IDB_BITMAP1);
3.选用位图对象
加载完毕后,我们需要做的就是将这张图和这个DC关联起来,可以说是将这个图放到内存DC中去,这个就是设置备胎的属性了。
m_bgcDC.SelectObject(&m_bgBitmap);
参数为要选择的位图对象指针。
4.将内存DC的内容粘贴到窗口DC中,绘制出来
由于我们的窗口DC使用的是指针,因此使用方式为
cDC->BitBlt(0,0,m_client.Width(),m_client.Height(),&m_bgcDC,0,0,SRCCOPY);
BitBlt这个函数的原型如下:
BOOL BitBlt(
int nXDest, //目的DC的起始x
int nYDest, //起始y
int nWidth, //宽度
int nHeight, //高度
HDC hdcSrc, //源DC
int nXSrc, //源DC起始x
int nYSrc, //起始y
DWORD dwRop //贴图方式,大家设置为SRCCOPY就可以了
);
经过这四步后,我们已经可以显示出图片了
赶紧运行一下程序,大家看到图片了吗?
三、使用CImage类进行贴图
CImage是MFC中一种图片处理的类,其头文件为atlimage.h,如果是VS2010或者VS2012,就不需要包含头文件了。它对PNG格式的图片支持很好,对于其他格式的图片需要借助CBitmap类实现,由于比较麻烦且使用价值感觉不大,所以就略去了,我主要讲解一下对于PNG格式的处理方法。
CImage的使用非常的简单,它的使用分为三步:
1.定义一个CImage对象
CImage m_hero;
2.加载图片
m_hero.Load("hero_No.png");
Load函数的参数是图片的路径,这里使用的是相对路径
3.绘制图片
m_hero.Draw(*cDC,100,400,60,60);
Draw函数有多个重载类型,这里给出的是最常用的,参数分别表示要绘制的DC,起始x,起始y,宽度,高度。 简单的几步过后,我们看下效果:
PS:大家在尝试的时候会发现窗口在不断的闪动,这个问题大家可以先忽略,在后面我会讲解解决方法,这个要采用图像缓冲来处理。 四、透明特效 上面的那张截图,大家可以看到,绘制的人物的背景白色也贴出来了,这显示是我们不想要的,要去掉白色,主要有两种方法。
1.如果采用的不是CImage类贴图,那么可以采用TransparentBlt函数来代替BitBlt函数进行贴图,TransparentBlt原型如下:
BOOL TransparentBlt(
int nXOriginDest, //前面的参数是和BitBlt是一样的含义,就不多说了,最后一个参数和用法见下面
int nYOriginDest,
int nWidthDest,
int hHeightDest,
HDC hdcSrc,
int nXOriginSrc,
int nYOriginSrc,
int nWidthSrc,
int nHeightSrc,
UINT crTransparent
);
它的参数最后一个表示要透明的颜色,比如对于上图的人物图片来说,我们不希望白色被显示出来,那么我们就可以设置最后一个参数为RGB(255,255,255),RGB是一个宏,其三个参数分别表示红色,绿色,蓝色三原色的分量,范围在0~255。 采用这种方式进行透明贴图有一点需要注意,就是人物中不能含有要去掉的背景色,否则也会被去掉,因此在制作图片的时候需要注意背景色必须为纯色,且前景中不含有该颜色。
2.采用CImage类贴图
这个要进行透明贴图就简单多了,只需要将要贴的图片中不需要的部分弄成透明就可以了,贴出来就是透明的了。 对于有些图片中含有一些特定颜色的像素,有时候仍然不是透明的,这个是CImage实现的问题。大家可以采用的方法是每张图片加载后,都自己对它处理以下,我为大家封装了一个函数:void TransparentPNG(CImage *png)
{
for(int i = 0; i <png->GetWidth(); i++)
{
for(int j = 0; j <png->GetHeight(); j++)
{
unsigned char* pucColor = reinterpret_cast<unsigned char*>(png->GetPixelAddress(i , j));
pucColor[0] = pucColor[0] *pucColor[3] / 255;
pucColor[1] = pucColor[1] *pucColor[3] / 255;
pucColor[2] = pucColor[2] *pucColor[3] / 255;
}
}
}
大家加载图片后,将CImage对象地址传递给它就好了,至于原理大家可以参考透明实现相关的知识。 就像下面这样TransparentPNG(&m_hero);
透明后就是这样的了:
五、两种贴图方式的对比 采用CBitmap类进行贴图时,操作比较麻烦,而且BMP图片占空间还比较大;使用CImage图片操作简单,而且PNG格式小巧,占用空间小。另外,还有一点很重要的区别,使用CBitmap类时,图片被打包进了可执行程序中去,导致可执行程序比较大,但是exe程序可以到处运行,而不需要那些资源图片在旁边。使用CImage类时,PNG图片是从文件中读取的,所以要运行程序,PNG图片必须在exe程序旁边,当然,exe程序也就很小了。 由于CImage比较简单,在以后的教程中,我将都采用CImage贴图。 如果您正在跟着本教程学习,建议自己打一遍代码,多尝试,遇到困难自己想办法去解决,这样会有很大的提高。有需要代码的同学
请点击这里下载本节源代码
《MFC游戏开发》笔记三到这里就结束了,更多精彩请关注下一篇。如果您觉得文章对您有帮助的话,请留下您的评论,点个赞,能看到你们的留言是我最高兴的事情,因为这让我知道我正在帮助曾和我一样迷茫的少年,你们的支持就是我继续写下去的动力,愿我们一起学习,共同努力,复兴国产游戏。
对于文章的疏漏或错误,欢迎大家的指出。
分享到:
相关推荐
在本文中,我们将深入探讨《MFC游戏开发》笔记三中的关键知识点——透明贴图技术。MFC(Microsoft Foundation Classes)是微软提供的一种C++库,用于构建Windows应用程序,包括游戏开发。透明贴图是游戏图形编程中...
在游戏开发领域,MFC(Microsoft Foundation Classes)虽然不是首选的框架,但作为一个学习和实践C++的基础平台,它仍然有其独特的价值。本篇主要探讨的是如何在MFC环境中实现场景滚动这一关键技术,这对于创建大型...
从给定的信息中,我们可以提炼出关于MFC(Microsoft Foundation Classes)的重要知识点,以及与之相关的C++编程、Visual Studio环境设置、Windows API使用、内存管理等关键概念。以下是对这些知识点的详细解释: ##...
本篇笔记主要围绕《MFC游戏开发》中的第十章内容,深入探讨了如何在C++环境下实现高级的碰撞检测技术。通过学习这部分知识,开发者可以为自己的游戏增加更真实的交互体验。 碰撞检测主要分为两个层面:几何碰撞检测...
在本文中,我们将深入探讨MFC(Microsoft Foundation Classes)框架下的游戏开发,特别是关于图像双缓冲技术的应用。图像双缓冲是一种提高图形显示质量和流畅性的技术,对于游戏开发来说至关重要,因为它能有效避免...
《MFC游戏开发》笔记八 游戏特效的实现(二):粒子系统 配套源代码 欢迎大家关注 配套博文地址http://blog.csdn.net/u011371356/article/details/9360993
在MFC中实现透明窗口是一项常见的需求,尤其在创建具有复杂界面设计的应用时。本篇文章将深入探讨如何使用MFC来实现窗口透明效果。 首先,我们需要了解透明窗口的基本原理。在Windows操作系统中,窗口可以通过使用`...
在MFC中实现贴图,特别是半透明贴图,是一项具有挑战性的任务,因为它涉及到颜色混合和深度缓冲等高级概念。本文将深入探讨如何使用MFC实现半透明贴图。 首先,理解半透明(Alpha Blending)的概念至关重要。半透明...
在本文中,我们将深入探讨MFC(Microsoft Foundation Classes)中的透明贴图技术,并通过一个实例代码来演示如何实现这一功能。MFC是微软提供的一种C++库,它为Windows应用程序开发提供了一种结构化的方式,使得...
【打字游戏 MFC开发】是一款基于Microsoft Foundation Classes (MFC)框架开发的娱乐与学习兼备的应用程序。MFC是微软提供的一套C++类库,用于简化Windows应用程序的开发,它封装了Windows API,使得程序员可以更高效...
《MFC开发的RPG游戏Demo》是一款基于微软的MFC(Microsoft Foundation Classes)框架开发的角色扮演游戏Demo,适用于学习和理解MFC编程技术。这款Demo是作者在毕业设计时完成的作品,尽管它采用的是较为老旧的开发...
总结,基于MFC的五子棋游戏开发不仅涉及MFC的基本原理和应用,还涵盖了游戏设计、图形界面编程、算法实现等多个方面,是一个综合性的编程实践项目。通过这个项目,开发者不仅可以提升MFC的使用技能,也能深入理解...
在本文中,我们将深入探讨如何使用C++编程语言和MFC(Microsoft Foundation Classes)库来实现一个五子棋游戏。MFC是微软提供的一套面向对象的类库,用于简化Windows应用程序开发,它封装了许多Win32 API,使得...
在这个“mfc界面开发”主题中,我们将探讨如何使用MFC来设计和实现用户界面,并通过三个具体的示例——360安全卫士、QQ和浩方游戏平台的Demo,深入理解其应用。 首先,MFC界面设计的一大亮点在于XML布局和定位。XML...
在本文中,我们将深入探讨如何在MFC(Microsoft Foundation Classes)框架中实现半透明效果的图片。MFC是微软提供的一套C++类库,用于简化Windows应用程序开发,特别是基于对话框的应用程序。半透明效果在现代用户...
在本文中,我们将深入探讨如何使用Microsoft Foundation Class (MFC)库来实现自定义界面的贴图美化。MFC是微软提供的一种C++类库,它简化了Windows应用程序的开发,特别是用户界面的设计。对于中高级MFC程序员来说,...
《MFC学习笔记:腾讯游戏连连看外挂制作(一)》 在本文中,我们将深入探讨如何使用Microsoft Foundation Classes (MFC) 来开发腾讯游戏连连看的外挂程序。MFC是微软提供的一套C++库,用于简化Windows应用程序的开发...
《MFC游戏编程——飞机大战》是一款基于Microsoft Foundation Classes (MFC)库开发的游戏项目,旨在为初学者提供一个学习MFC游戏开发的实践案例。MFC是微软为Windows平台提供的C++类库,它封装了Windows API,使得...
数独游戏是一款经典的逻辑解谜游戏,而使用MFC(Microsoft Foundation Classes)开发数独游戏界面,是Windows应用程序开发中的常见实践。MFC是微软提供的一套C++库,用于简化Windows API的使用,帮助开发者快速构建...
在Windows编程领域,MFC(Microsoft Foundation Classes)是C++库,它为开发Windows应用程序提供了一种方便的方式。本文将详细讲解如何在MFC中实现透明按钮,以及相关的技术要点。 透明按钮是一种视觉效果,使得...