MFC飞机大战开发之绘制图像
来源:互联网 发布:java的设计模式有哪些 编辑:程序博客网 时间:2024/05/22 03:17
这一节来演示一种绘图的方法,让我们的程序真正的看得见~ 哈哈哈,而不再是命令行的黑框框。 采用的是二重缓冲的方式
先说一下当前工程的启动过程,省略一部分,直接看到我们的ChildView.cpp这个文件,里边有两个函数BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)
和 void CChildView::OnPaint()
,可以简单的理解为,前者是窗口出现之间,程序所做的事情,所以你可以把游戏的一些初始化的操作放在这个函数里边,后者就是绘制这个窗口,每执行一次这个函数,就会重新绘制一下当前的窗口,你所看到的动画啊,游戏啊 都是通过一直执行这个函数实现的动画的效果的~,好啦~ 说了这么一堆话了,来开始贴上我们的飞机们把~
第一步:
找到ChildView.h 这个头文件,在里边添加一些我们所需要的属性,
// 特性public: //绘图相关 CRect m_client;//记录客户区大小 CDC m_cacheDC; //缓冲DC CBitmap m_cacheCBitmap;//缓冲位图
然后转到ChildView.cpp这个文件,修改OnPaint函数
void CChildView::OnPaint() { CPaintDC dc(this); // 用于绘制的设备上下文 // TODO: 在此处添加消息处理程序代码 // 不要为绘制消息而调用 CWnd::OnPaint() //获取窗口DC指针 CDC *cDC = this->GetDC(); //获取窗口大小 GetClientRect(&m_client); //创建缓冲DC m_cacheDC.CreateCompatibleDC(NULL); m_cacheCBitmap.CreateCompatibleBitmap(cDC, m_client.Width(), m_client.Height()); m_cacheDC.SelectObject(&m_cacheCBitmap); //————————————————————开始绘制—————————————————————— //把要绘制的内容都贴到m_cacheDC当中就可以了 Manager.Draw(&m_cacheDC); //最后将缓冲DC内容输出到窗口DC中 cDC->BitBlt(0, 0, m_client.Width(), m_client.Height(), &m_cacheDC, 0, 0, SRCCOPY); //————————————————————绘制结束————————————————————— //在绘制完图后,使窗口区有效 ValidateRect(&m_client); //释放缓冲DC m_cacheDC.DeleteDC(); //释放对象 m_cacheCBitmap.DeleteObject(); //释放窗口DC ReleaseDC(cDC); ReleaseDC(cDC);}
我这段代码当中的Manager.Draw(&m_cacheDC);
就是把所有的内容都贴到缓冲DC当中(m_cachaeDC),Manager是一个类的实例对象,该类可以存储多个物体(比如:飞机,敌机,导弹等等),可以通过该类的Draw方法一次绘制所有的内容。 看到这里你可能说 哎呀 我不知道怎么写Manager这个类呀,我还是不知道怎么贴图啊,别着急~ 接下来我就给你们演示如何贴图~
我们试着新建一个类,就叫他Plane 类吧, 一个飞机有什么属性呢,嗯~ 有他的外观(贴图),长,宽,在游戏世界中还有一个属性是坐标,好,我们的类就长这个样子:
#pragma once#include <atltypes.h>#include <atlimage.h>class Plane{private: CImage Image_; //物体的贴图 int Height_; //物体的高度 int Width_; //物体的宽度 CPoint Postion_; //物体的位置坐标public: Plane(){}; ~Plane(){};};
CImage Image_ ; 就是储存物体的模样(外观)的,我们把一张图片放进去就好了~ 来看看怎么放一张图片呢
一般来讲是通过 CImage的load方法加载图片的,比如Image_.Load("Plane.png");
,然而我们想要最后生成的exe文件可以独立的运行就需要把图片加载到我们的资源当中,那么如何从我们的资源文件中加载图片呢,是通过这样的一个函数做到的
//从资源加载图片 第一个是资源的名称,第二个是资源的类型 BOOL LoadImageFromResource(UINT nResID, LPCTSTR lpTyp) { /*Image_.Destroy();*/ // 查找资源 HRSRC hRsrc = ::FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(nResID), lpTyp); if (hRsrc == NULL) return false; // 加载资源 HGLOBAL hImgData = ::LoadResource(AfxGetResourceHandle(), hRsrc); if (hImgData == NULL) { ::FreeResource(hImgData); return false; } // 锁定内存中的指定资源 LPVOID lpVoid = ::LockResource(hImgData); LPSTREAM pStream = NULL; DWORD dwSize = ::SizeofResource(AfxGetResourceHandle(), hRsrc); HGLOBAL hNew = ::GlobalAlloc(GHND, dwSize); LPBYTE lpByte = (LPBYTE)::GlobalLock(hNew); ::memcpy(lpByte, lpVoid, dwSize); // 解除内存中的指定资源 ::GlobalUnlock(hNew); // 从指定内存创建流对象 HRESULT ht = ::CreateStreamOnHGlobal(hNew, TRUE, &pStream); if (ht != S_OK) { GlobalFree(hNew); } else { // 加载图片 Image_.Load(pStream); GlobalFree(hNew); } // 释放资源 ::FreeResource(hImgData); return true; }
如果是PNG图片的话,在通过这个函数把图片转为透明的(原本透明的部分)
//转换PNG图片为透明 static void TransparentPNG(CImage *png) { if (png->GetBPP() == 32) { 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; } } } }
最后 我们封装一个接口方便使用
//从资源中加载图片 void LoadImage(UINT nResID, LPCTSTR lpTyp = _T("PNG")) { LoadImageFromResource(nResID, lpTyp); if (lpTyp == _T("PNG")) TransparentPNG(&Image_); } //对象的绘制方法 void Draw(CDC *cDC) { Image_.Draw(*cDC, Postion_.x, Postion_.y, Width_, Height_); }
好啦,现在生成一个实例对象去试试吧~
//————————————————————开始绘制—————————————————————— //把要绘制的内容都贴到m_cacheDC当中就可以了 plane.Draw(&m_cacheDC); //plane是Plane类的实例对象,记得先给他加载一张图片哦~ //最后将缓冲DC内容输出到窗口DC中 cDC->BitBlt(0, 0, m_client.Width(), m_client.Height(), &m_cacheDC, 0, 0, SRCCOPY);
完成后运行一下看看吧,是不是小飞机出现在屏幕当中了呢
最后附上一个完整的飞机类
#pragma once#include <atlimage.h>#include <afxwin.h>class Plane{private: CImage Image_; //物体的贴图 int Height_; //物体的高度 int Width_; //物体的宽度 CPoint Postion_; //物体的位置坐标public: Plane() { LoadImage(IMG_Plane); // 让对象初始化的时候自动加载图片 Height_ = 30; Width_ = 30; Postion_ = CPoint(Game_Width / 2, Game_Height); }; ~Plane(){}; //转换PNG图片为透明 static void TransparentPNG(CImage *png) { if (png->GetBPP() == 32) { 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; } } } } //从资源加载图片 第一个是资源的名称,第二个是资源的类型 BOOL LoadImageFromResource(UINT nResID, LPCTSTR lpTyp) { /*Image_.Destroy();*/ // 查找资源 HRSRC hRsrc = ::FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(nResID), lpTyp); if (hRsrc == NULL) return false; // 加载资源 HGLOBAL hImgData = ::LoadResource(AfxGetResourceHandle(), hRsrc); if (hImgData == NULL) { ::FreeResource(hImgData); return false; } // 锁定内存中的指定资源 LPVOID lpVoid = ::LockResource(hImgData); LPSTREAM pStream = NULL; DWORD dwSize = ::SizeofResource(AfxGetResourceHandle(), hRsrc); HGLOBAL hNew = ::GlobalAlloc(GHND, dwSize); LPBYTE lpByte = (LPBYTE)::GlobalLock(hNew); ::memcpy(lpByte, lpVoid, dwSize); // 解除内存中的指定资源 ::GlobalUnlock(hNew); // 从指定内存创建流对象 HRESULT ht = ::CreateStreamOnHGlobal(hNew, TRUE, &pStream); if (ht != S_OK) { GlobalFree(hNew); } else { // 加载图片 Image_.Load(pStream); GlobalFree(hNew); } // 释放资源 ::FreeResource(hImgData); return true; } //从资源中加载图片 void LoadImage(UINT nResID, LPCTSTR lpTyp = _T("PNG")) { LoadImageFromResource(nResID, lpTyp); if (lpTyp == _T("PNG")) TransparentPNG(&Image_); } //对象的绘制方法 void Draw(CDC *cDC) { Image_.Draw(*cDC, Postion_.x, Postion_.y, Width_, Height_); }};
- MFC飞机大战开发之绘制图像
- MFC飞机大战开发之建立工程、设置窗口
- 飞机大战开发02之添加玩家飞机
- 飞机大战(上篇绘制)
- "飞机大战"开发笔记
- Android 开发飞机大战
- unity之飞机大战
- [Unity3D]Unity3D游戏开发之飞机大战项目讲解
- Cocos2d-X研究之豪华版飞机大战游戏开发系列
- Unity3D游戏开发之飞机大战项目讲解,食用攻略
- C#游戏《飞机大战》开发之重点总结
- C#《飞机大战》游戏开发之细节总结
- 飞机大战之二:主角飞机登场
- unity开发-飞机大战
- 使用UGUI开发飞机大战
- unity之飞机大战后续
- unity之飞机大战总结
- 飞机大战之GUI设置
- Java 7之多线程并发容器
- CF 779B Weird Rounding 贪心
- 习题4-2 正方形
- Eclipse Android Studio 配置自己的调试证书
- (转)Rust :文件分层
- MFC飞机大战开发之绘制图像
- vs转eclipse之工具快速上手篇
- 树状数组
- Commbox 控件
- sessionStorage 刷新 传值消失
- 达梦数据库导入.dmp文件
- C++第二次实验报告
- C语言指针的内存分配和Java中的引用
- 对于事务的理解