第5章 透明贴图

《逐梦旅程 WINDOWS游戏编程之从零开始》笔记2——透明贴图,动画技术

像这样直接贴图会产生这种情况,所以我们需要透明贴图。

透明遮罩法:主要利用BitBlt函数中Raser(光栅)值的运算,需要准备素材图和遮罩图:

《逐梦旅程 WINDOWS游戏编程之从零开始》笔记2——透明贴图,动画技术

《逐梦旅程 WINDOWS游戏编程之从零开始》笔记2——透明贴图,动画技术

《逐梦旅程 WINDOWS游戏编程之从零开始》笔记2——透明贴图,动画技术

这个方法的原理解释见书131页。

示例程序:

  1 #include <windows.h>
  2 
  3 #define WINDOW_WIDTH    800                            //为窗口宽度定义的宏,以方便在此处修改窗口宽度
  4 #define WINDOW_HEIGHT    600                            //为窗口高度定义的宏,以方便在此处修改窗口高度
  5 #define WINDOW_TITLE    L"【致我们永不熄灭的游戏开发梦想】程序核心框架"        //为窗口标题定义的宏
  6 
  7 HDC    g_hdc=NULL,g_mdc=NULL;       //全局设备环境句柄
  8 HBITMAP g_hBackGround,g_hCharacter1,g_hCharacter2;  //定义3个位图句柄,用于3张图片的存放
  9 
 10 LRESULT CALLBACK    WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );  //窗口过程函数
 11 BOOL Game_Init(HWND hwnd); //在此函数中进行资源的初始化
 12 VOID Game_Paint(HWND hwnd); //进行绘图代码的书写
 13 BOOL Game_CleanUp(HWND hwnd); //资源的清理
 14 
 15 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nShowCmd)
 16 {
 17     //【1】窗口创建四步曲之一:开始设计一个完整的窗口类
 18     WNDCLASSEX wndClass = { 0 };                            //用WINDCLASSEX定义了一个窗口类,{0}用来初始化结构体
 19     wndClass.cbSize = sizeof( WNDCLASSEX ) ;            //设置结构体的字节数大小
 20     wndClass.style = CS_HREDRAW | CS_VREDRAW;    //设置窗口的样式
 21     wndClass.lpfnWndProc = WndProc;                    //设置指向窗口过程函数的指针
 22     wndClass.cbClsExtra  = 0;                                //窗口类的附加内存,取0就可以了
 23     wndClass.cbWndExtra  = 0;                            //窗口的附加内存,依然取0就行了
 24     wndClass.hInstance = hInstance;                        //指定包含窗口过程的程序的实例句柄。
 25     wndClass.hIcon=(HICON)::LoadImage(NULL,L"icon.ico",IMAGE_ICON,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);  //本地加载自定义ico图标
 26     wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );    //指定窗口类的光标句柄。
 27     wndClass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);  //为hbrBackground成员指定一个灰色画刷句柄    
 28     wndClass.lpszMenuName = NULL;                        //用一个以空终止的字符串,指定菜单资源的名字。
 29     wndClass.lpszClassName = L"ForTheDreamOfGameDevelop";        //用一个以空终止的字符串,指定窗口类的名字。
 30 
 31     //【2】窗口创建四步曲之二:注册窗口类
 32     if( !RegisterClassEx( &wndClass ) )                //设计完窗口后,需要对窗口类进行注册,这样才能创建该类型的窗口
 33         return -1;        
 34 
 35     //【3】窗口创建四步曲之三:正式创建窗口
 36     HWND hwnd = CreateWindow( L"ForTheDreamOfGameDevelop",WINDOW_TITLE,        //喜闻乐见的创建窗口函数CreateWindow
 37         WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH,
 38         WINDOW_HEIGHT, NULL, NULL, hInstance, NULL );
 39 
 40     //【4】窗口创建四步曲之四:窗口的移动、显示与更新
 41     MoveWindow(hwnd,250,80,WINDOW_WIDTH,WINDOW_HEIGHT,true);        //调整窗口显示时的位置,使窗口左上角位于(250,80)处
 42     ShowWindow( hwnd, nShowCmd );    //调用ShowWindow函数来显示窗口,第二个参数用于指定窗口的显示状态
 43     UpdateWindow(hwnd);                        //对窗口进行更新,就像我们买了新房子要装修一样
 44 
 45     //游戏资源的初始化,若初始化失败,弹出一个消息框,并返回FALSE
 46     if(!(Game_Init(hwnd)))
 47     {
 48         MessageBox(hwnd,L"资源初始化失败",L"消息窗口",0);
 49         return FALSE;
 50     }
 51 
 52     //【5】消息循环过程
 53     MSG msg = { 0 };        //定义并初始化msg
 54     while( msg.message != WM_QUIT )            //使用while循环,如果消息不是WM_QUIT消息,就继续循环
 55     {
 56         if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )   //查看应用程序消息队列,有消息时将队列中的消息派发出去。
 57         {
 58             TranslateMessage( &msg );        //将虚拟键消息转换为字符消息
 59             DispatchMessage( &msg );            //分发一个消息给窗口程序。
 60         }
 61     }
 62 
 63     //【6】窗口类的注销
 64     UnregisterClass(L"ForTheDreamOfGameDevelop", wndClass.hInstance);  //程序准备结束,注销窗口类
 65     return 0;  
 66 }
 67 
 68 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )      
 69 {
 70     PAINTSTRUCT paintStruct;    //定义一个PAINTSTRUCT结构体来记录一些绘制信息
 71 
 72     switch( message )                        //switch语句开始
 73     {
 74     case WM_PAINT:                        // 若是客户区重绘消息
 75         g_hdc=BeginPaint(hwnd,&paintStruct);    //指定窗口进行绘图工作的准备,并将和绘图有关的信息填充到paintstruct结构体中
 76         Game_Paint(hwnd);
 77         EndPaint(hwnd,&paintStruct);    //EndPaint函数标记指定窗口的绘画过程结束
 78         ValidateRect(hwnd, NULL);        // 更新客户区的显示
 79         break;                                    //跳出该switch语句
 80 
 81     case WM_KEYDOWN:                // 若是键盘按下消息
 82         if (wParam == VK_ESCAPE)    // 如果被按下的键是ESC
 83             DestroyWindow(hwnd);        // 销毁窗口, 并发送一条WM_DESTROY消息
 84         break;                                    //跳出该switch语句
 85 
 86     case WM_DESTROY:                //若是窗口销毁消息
 87         PostQuitMessage( 0 );        //向系统表明有个线程有终止请求。用来响应WM_DESTROY消息
 88         break;                                //跳出该switch语句
 89 
 90     default:                                    //若上述case条件都不符合,则执行该default语句
 91         return DefWindowProc( hwnd, message, wParam, lParam );        //调用缺省的窗口过程
 92     }
 93     return 0;            //正常退出
 94 }
 95 
 96 //初始化函数,进行一些简单的初始化
 97 BOOL Game_Init(HWND hwnd)
 98 {
 99     g_hdc = GetDC(hwnd);  //获取设备环境句柄
100 
101     //-----【位图绘制四步曲之一:加载位图】-----
102     //从文件加载3张位图
103     g_hBackGround = (HBITMAP)LoadImage(NULL,L"bg.bmp",IMAGE_BITMAP,WINDOW_WIDTH,WINDOW_HEIGHT,LR_LOADFROMFILE);   
104     g_hCharacter1 = (HBITMAP)LoadImage(NULL,L"character1.bmp",IMAGE_BITMAP,640,579,LR_LOADFROMFILE);  
105     g_hCharacter2 =  (HBITMAP)LoadImage(NULL,L"character2.bmp",IMAGE_BITMAP,800,584,LR_LOADFROMFILE);
106 
107     //-----【位图绘制四步曲之二:建立兼容DC】-----
108     g_mdc = CreateCompatibleDC(g_hdc);    //建立兼容设备环境的内存DC
109 
110     Game_Paint(hwnd);
111     ReleaseDC(hwnd,g_hdc);  //释放设备环境
112     return TRUE;
113 }
114 
115 //绘制函数
116 VOID Game_Paint(HWND hwnd)
117 {
118     //先贴上背景图
119     SelectObject(g_mdc,g_hBackGround);
120     BitBlt(g_hdc,0,0,WINDOW_WIDTH,WINDOW_HEIGHT,g_mdc,0,0,SRCCOPY);    //采用BitBlt函数在g_hdc中先贴上背景图
121 
122     //用透明遮罩法绘制出第一个人物
123     SelectObject(g_mdc,g_hCharacter1);
124     BitBlt(g_hdc,50,WINDOW_HEIGHT-579,320,640,g_mdc,320,0,SRCAND);//透明遮罩法第一步,即将屏蔽图与背景图做"AND"运算 
125     BitBlt(g_hdc,50,WINDOW_HEIGHT-579,320,640,g_mdc,0,0,SRCPAINT);//透明遮罩法第二步,即将前景图与背景图做"OR"运算
126 
127     //用透明遮罩法绘制出第二个人物
128     SelectObject(g_mdc,g_hCharacter2);
129     BitBlt(g_hdc,450,WINDOW_HEIGHT-584,400,584,g_mdc,400,0,SRCAND);//透明遮罩法第一步,即将屏蔽图与背景图做"AND"运算
130     BitBlt(g_hdc,450,WINDOW_HEIGHT-584,400,584,g_mdc,0,0,SRCPAINT);//透明遮罩法第二步,即将前景图与背景图做"OR"运算
131 }
132 
133 //清理资源
134 BOOL Game_CleanUp(HWND hwnd)
135 {
136     //释放资源对象
137     DeleteObject(g_hBackGround);
138     DeleteObject(g_hCharacter2);
139     DeleteObject(g_hCharacter1);
140     DeleteDC(g_mdc);
141     return TRUE;
142 }
View Code

相关文章:

  • 2022-01-31
  • 2021-11-02
  • 2021-12-07
  • 2021-04-02
  • 2022-12-23
  • 2022-12-23
  • 2021-11-25
猜你喜欢
  • 2022-12-23
  • 2021-12-28
  • 2022-12-23
  • 2022-12-23
  • 2022-03-03
  • 2022-03-08
  • 2022-12-23
相关资源
相似解决方案