从这期开始,文章参考了毛星云老师的Windows游戏编程之从零开始。并结合前面孙鑫老师讲述的MFC编程做了一些小的程序示例。
Lesson11:GDI 2D编程基础
GDI 2D编程是游戏编程中的重要部分,在二维游戏编程中应用广泛。游戏编程中一个重要环节是背景图像、人物图像的处理,绚丽的视觉冲击可以提高玩家的体验感。本文主要讲解一些DGI 2D编程的基础知识,包括创建程序启动画面、启动音乐、播放背景音乐、窗口背景贴图等。
1. 创建程序启动画面
这部分内容在前面讲过,可以参考MFC——7.定制应用程序外观:
http://blog.csdn.net/u010757264/article/details/50932180#t7
这里需要说的一点是,如果我们想像酷我音乐一样,每次启动都有一个提示音,可以在void CWzdSplash::OnPaint()函数开始处添加下面一句代码:
PlaySound(L"startmusic",NULL, SND_FILENAME | SND_ASYNC);
2. 背景音乐
在菜单资源中添加音乐菜单,并添加play和stop子菜单,通过切换两个菜单按钮实现音乐的播放和停止,子菜单ID号分别为ID_MUSIC_PLAY和ID_MUSIC_STOP,然后通过类向导在view类里添加命令响应函数。
为了实现停止功能时检测是否当前有音乐播放,我们添加一个bool型变量MusicRuning,初始化为false,表示没有音乐播放。
void CYuTaoView::OnMusicPlay()
{
//TODO: 在此添加命令处理程序代码
//PlaySound(L"AIR- 夏影",NULL,SND_FILENAME|SND_ASYNC|SND_LOOP);
MusicRuning= PlaySound(L"AIR - 夏影", NULL, SND_ASYNC);
}
void CYuTaoView::OnMusicStop()
{
//TODO: 在此添加命令处理程序代码
if(MusicRuning&&IDYES == MessageBoxA(NULL, "是否结束播放","YuTao", MB_YESNO))
{
MusicRuning= !(PlaySound(NULL, NULL, SND_PURGE));
}
if(!MusicRuning)
MessageBox(L"当前无音乐播放");
}
3. 两种方法贴图
在菜单资源中添加背景菜单,并添加Background_1和Background_2子菜单,通过两个子菜单按钮实现背景贴图,子菜单ID号分别为ID_BACKGROUND1和ID_ BACKGROUND2,然后通过类向导在view类里添加命令响应函数。
//方法一:按钮点击贴背景图1
void CYuTaoView::OnBackground1()
{
//TODO: 在此添加命令处理程序代码
CBitmapbitmap; //1创建位图
bitmap.LoadBitmap(IDB_BACKGROUND1);
BITMAPbmp; //这里为了根据窗口大小显示位图,后面得到位图的像素
bitmap.GetBitmap(&bmp);
CDCdcCompatible; //2创建兼容DC
dcCompatible.CreateCompatibleDC(GetDC());
dcCompatible.SelectObject(&bitmap); //3将位图选到兼容DC中
CRectrect; //4将兼容DC中的位图贴到当前DC中
GetClientRect(&rect);
//GetDC()->BitBlt(0,0, rect.Width(), rect.Height(), &dcCompatible, 0, 0, SRCCOPY); //bitblt()是一比一显示位图
GetDC()->StretchBlt(0,0, rect.Width(), rect.Height(), &dcCompatible, 0, 0, bmp.bmWidth,bmp.bmHeight, SRCCOPY); //根据窗口大小显示位图
DeleteObject(bitmap); //清理工作
DeleteDC(dcCompatible);
}
//方法二:按钮点击贴背景图2
void CYuTaoView::OnBackground2()
{
//TODO: 在此添加命令处理程序代码
CClientDCg_hdc(this); //1创建位图
CRectrect; //这里是为了得到屏幕矩形尺寸
GetClientRect(&rect);
HBITMAPbitmap = (HBITMAP)LoadImage(NULL, L"background2.bmp", IMAGE_BITMAP,rect.Width(), rect.Height(), LR_LOADFROMFILE);
HDCdcCompatible = CreateCompatibleDC(g_hdc); //2创建兼容DC
SelectObject(dcCompatible,bitmap); //3将位图选到兼容DC中
BitBlt(g_hdc,0,0, rect.Width(), rect.Height(), dcCompatible, 0, 0, SRCCOPY); //4将兼容DC中的位图贴到当前DC中
//StretchBlt(g_hdc,0, 0, rect.Width(), rect.Height(), dcCompatible, 0, 0, rect.Width(),rect.Height(), SRCCOPY);
//前面的代码已经实现了贴图工作,后面的代码为在一幅图上再贴上一个人物图像,可以将代码注释掉看看两次的效果
HBITMAPhCharacter = (HBITMAP)LoadImage(NULL, L"character.bmp", IMAGE_BITMAP,640, 579, LR_LOADFROMFILE); //载入图片,其中图像大小为640*579像素
SelectObject(dcCompatible,hCharacter); //选择设备到兼容DC
BitBlt(g_hdc,50, 700 - 579, 320, 640, dcCompatible, 320, 0, SRCAND);//透明遮罩法第一步,即将遮罩图与背景图做"AND"运算
BitBlt(g_hdc,50, 700 - 579, 320, 640, dcCompatible, 0, 0, SRCPAINT);//透明遮罩法第二步,即将素材图(前景图)与背景图做"OR"运算
}
这是程序中用到的素材图片
background1.bmp
background2.bmp
character.bmp