游戏开发工具之纹理打包器-3.使用GDI+绘图
上一次我们实现了把我们要的图片添加到CTreeCtrl控件里去,并显示图片的缩略图,现在开始我们要讲比较重要的部分--绘图区。为了实现能编辑图片的功能,绘图区应该具有如下功能。
1. 添加删除图片。
2. 放大缩小绘图区。
3. 选中一张图片,移动一张图片。
4. 绘制图片
5. 给图片添加点击事件
为了更好的实现这些功能,我模仿了cocos2d的内存管理机制以及节点结构,写了一个静态库VALib,它使用GID+渲染图片,以及实现观察者模式来监听鼠标事件。源码可一从这里下载。当然,你也可以使用cocos2d 来实现绘图区的功能。这里我使用我自己写的VALib 库来实现。
下面开始上码。
首先我们需要先继承VALib库里的VASprite类,来写一个符合我们自己需求的Image类
.h文件
#pragma once
#pragma comment(lib, "../debug/valib.lib")
#include "valib.h"
#include "SelectHandler.h"
#include "RectPlacement.h"US_VA_NS
class VaImage :public VASprite , public SelectHandler ,public CRectPlacement::TRect
{
private:bool m_TouchFlag;bool m_selectFlag;VAPoint* m_lastPoing;void init();
public:VaImage(const char* m_name);~VaImage(void);/************************************************************************//* 使用一个图片创建一个VASprite/* fileName: 图片路径/************************************************************************/static VaImage* FromFile(const WCHAR* filename);bool intersectPoint(VAPoint* pt);/************************************************************************//* 重写registerTouchDispatcher函数,使图片吞并touch事件,图片下方的图片不响应touch事件 *//************************************************************************/virtual void registerTouchDispatcher();virtual bool vaTouchBegan(VATouch* m_pTouch, VAEvent* m_pEvent);virtual void vaTouchMoved(VATouch* m_pTouch, VAEvent* m_pEvent);virtual void vaTouchEnded(VATouch* m_pTouch, VAEvent* m_pEvent);virtual void vaTouchCancelled(VATouch* m_pTouch, VAEvent* m_pEvent);virtual bool select(CPoint* pt);virtual void unselect();virtual void draw();
};
.cpp文件
#include "StdAfx.h"
#include "VaImage.h"
#include <regex>US_VA_NSVaImage::VaImage(const char* m_name):VASprite(m_name)
, m_TouchFlag(false)
, m_selectFlag(false)
, m_lastPoing(NULL)
{init();
}VaImage::~VaImage(void)
{
}VaImage* VaImage::FromFile( const WCHAR* filename )
{Bitmap* bitmap = Bitmap::FromFile( filename );//截取文件名CString tempName = filename;int m_index = tempName.Find(L"\\");while ( m_index!=-1 ){tempName = tempName.Right(tempName.GetLength()-(m_index+1));m_index = tempName.Find(L"\\");}USES_CONVERSION;const char *name = W2A(tempName.GetBuffer(tempName.GetLength()));//LPSTR)(LPCTSTR)tempName;//新建VAImage并贴上图片VaImage* vaImage = new VaImage(name);vaImage->setBitmap(bitmap);return vaImage;
}void VaImage::init()
{registryDispatch();
}bool VaImage::intersectPoint( VAPoint* pt )
{VARect rect = getRect();VAPoint m_pt = VAPoint(pt->x, pt->y);return rect.containsPoint(m_pt);
}void VaImage::registerTouchDispatcher()
{registerWithTouchDispatcher(NULL, true);
}bool VaImage::vaTouchBegan( VATouch* m_pTouch, VAEvent* m_pEvent )
{VAPoint* pt = new VAPoint(*(m_pTouch->getLocation()));if(intersectPoint(pt)){m_TouchFlag = true;if(m_lastPoing != NULL){//setPosition(new VAPoint( getPosition()->x + (pt->x - m_lastPoing->x), getPosition()->y + (pt->y - m_lastPoing->y) ));}m_lastPoing = pt;pt->release();return true;}pt->release();return false;
}void VaImage::vaTouchMoved( VATouch* m_pTouch, VAEvent* m_pEvent )
{if(m_TouchFlag){VAPoint* pt = new VAPoint(*(m_pTouch->getLocation()));VAPoint tempPT = VAPoint( getPosition().x + (pt->x - m_lastPoing->x), getPosition().y + (pt->y - m_lastPoing->y) );setPosition(tempPT);m_lastPoing = pt;tempPT.release();pt->release();}
}void VaImage::vaTouchEnded( VATouch* m_pTouch, VAEvent* m_pEvent )
{m_TouchFlag = false;
}void VaImage::vaTouchCancelled( VATouch* m_pTouch, VAEvent* m_pEvent )
{}bool VaImage::select( CPoint* pt )
{VAPoint m_pt = VAPoint(pt->x, pt->y);if(intersectPoint(&m_pt)){m_selectFlag = true;m_pt.release();return true;}m_pt.release();unselect();return false;
}void VaImage::unselect()
{m_selectFlag = false;
}void VaImage::draw()
{VASprite::draw();//绘制边框if(m_selectFlag){VADirector* director = VADirector::sharedDirector();vertex vertex = cloneVertex();int minX = min(min(min(vertex.leftTop.X, vertex.rightTop.X), vertex.rightBottom.X), vertex.leftBottmo.X);int minY = min(min(min(vertex.leftTop.Y, vertex.rightTop.Y), vertex.rightBottom.Y), vertex.leftBottmo.Y);int maxX = max(max(max(vertex.leftTop.X, vertex.rightTop.X), vertex.rightBottom.X), vertex.leftBottmo.X);int maxY = max(max(max(vertex.leftTop.Y, vertex.rightTop.Y), vertex.rightBottom.Y), vertex.leftBottmo.Y);VARect rect = getRect();Gdiplus::Rect r(rect.getMinX(), rect.getMinY(), rect.getMaxX()-rect.getMinX(), rect.getMaxY()-rect.getMinY());director->DrawBorder(&r);}
}
完后我们需要继承CWnd来创建一个自定义组件ImageView
.h文件
#pragma once
#include "valib.h"
#pragma comment(lib, "../debug/valib.lib")
#include "stdafx.h"
#include "ImgsTool.h"
#include "VaImage.h"// ImageView
US_VA_NS//使用valib命名空间typedef std::vector<VaImage*> VaImageArray;
class ImageView : public CWnd
{DECLARE_DYNAMIC(ImageView)
private:VADirector* m_vaDirector;VATouchDispatcher* m_vaTouchDispatcher;SelectDispatcher* m_pSelectDispatcher;Bitmap* m_canva;Bitmap* m_bgImg;float m_scale;VaImageArray imgList;float m_tagArrange;bool m_drawTage;
public:VAScene* m_scene;ImageView();virtual ~ImageView();void saveImg(CString filePath, CString type, Bitmap* bitmap = NULL);void savePlis(CString filePath, CString ImageType);void addImage(const WCHAR* filename);void setAutoArrange(float isArrange);void autoArrange();
protected:DECLARE_MESSAGE_MAP()virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);void init();void drawBackground();void update();void draw(CDC* pDC);int GetEncoderClsid(const WCHAR* format, CLSID *pClsid);
};
.cpp 文件
// ImageView.cpp : implementation file
//
#include "stdafx.h"
#include "ImgsTool.h"
#include "ImageView.h"
#include <algorithm>
#include "PublishPlist.h"// ImageView
US_VA_NS//使用valib命名空间
IMPLEMENT_DYNAMIC(ImageView, CWnd)
enum{viewInterval,
};
ImageView::ImageView()
{}ImageView::~ImageView()
{
}BEGIN_MESSAGE_MAP(ImageView, CWnd)
END_MESSAGE_MAP()
// ImageView message handlersLRESULT ImageView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{// TODO: Add your specialized code here and/or call the base classVATouch* pTouch = new VATouch();CPoint pt = (CPoint)lParam;pTouch->setTouchInfo((float)pt.x, (float)pt.y);switch (message){case WM_CREATE:init();break;case WM_PAINT:if(m_drawTage){update();}break;case WM_TIMER:Invalidate(FALSE);break;case WM_LBUTTONDOWN:m_pSelectDispatcher->callAllHandler(&pt);m_vaTouchDispatcher->touchesBegan(pTouch, NULL);break;case WM_MOUSEMOVE:m_vaTouchDispatcher->touchesMoved(pTouch, NULL);break;case WM_LBUTTONUP:m_vaTouchDispatcher->touchesEnded(pTouch, NULL);break;
// case WM_COMMAND://接收控件发送来的消息的
// break;}return CWnd::WindowProc(message, wParam, lParam);
}void ImageView::init()
{m_tagArrange = true;CRect rect;this->GetClientRect(rect);m_bgImg = new Bitmap(rect.Width(), rect.Height());drawBackground();//绘制背景m_canva = new Bitmap(rect.Width(), rect. Height());//创建画布m_pSelectDispatcher = ToolsCenter::getInstance()->getSelectDispatcher();m_vaDirector = VADirector::sharedDirector();m_vaDirector->init(this->m_hWnd);m_vaTouchDispatcher = m_vaDirector->getTouchDispatcher();m_scene = new VAScene();SetTimer(viewInterval, 5, NULL);Invalidate(FALSE);
}void ImageView::drawBackground()
{CRect rect;this->GetClientRect(rect);int size = 20;Graphics* bgG = Graphics::FromImage(m_bgImg);Bitmap* m_bgtexture = new Bitmap(size,size);Graphics* txG = Graphics::FromImage(m_bgtexture);txG->FillRectangle(&SolidBrush(Color(255,255,255)), 0, 0, size, size);txG->FillRectangle(&SolidBrush(Color(192,192,192)), size/2, 0, size/2 , size/2);txG->FillRectangle(&SolidBrush(Color(192,192,192)), 0, size/2, size/2 , size/2);bgG->FillRectangle(&TextureBrush(m_bgtexture), rect.left, rect.top, rect.right, rect.bottom);//saveImg(m_bgImg);
}
//更新窗口
void ImageView::update()
{CDC* dc = this->GetDC();draw(dc);
}
//绘制窗口
void ImageView::draw(CDC* pDC)
{CDC MemDC; //首先定义一个显示设备对象CBitmap MemBitmap; //定义一个位图对象CRect rect;this->GetClientRect(rect);MemDC.CreateCompatibleDC(NULL);//随后建立与屏幕显示兼容的内存显示设备MemBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()); //建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小//将位图选入到内存显示设备中//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);Graphics* memG = Graphics::FromHDC(MemDC);Rect destinationRect(0, 0, rect.Width(), rect.Height());memG->DrawImage(m_bgImg, destinationRect, 0, 0, rect.Width(), rect.Height(), Gdiplus::UnitPixel);m_canva = new Bitmap(rect.Width(), rect.Height());Graphics* canvaG = Graphics::FromImage(m_canva);//m_scene->update();VADirector::sharedDirector()->initDraw(memG);m_scene->draw();//绘制valib的场景里的各个图片memG->DrawImage(m_canva, destinationRect, 0, 0, rect.Width(), rect.Height(), Gdiplus::UnitPixel);delete canvaG;delete m_canva;//绘图后将内存中的图拷贝到屏幕上进行显示pDC->BitBlt(0,0, rect.Width(), rect.Height(), &MemDC,0, 0,SRCCOPY);//绘图完成后清理临时对象MemBitmap.DeleteObject();delete memG;MemDC.DeleteDC();ReleaseDC(pDC);
}void ImageView::saveImg(CString filePath, CString type, Bitmap* bitmap /*= NULL*/)
{//m_drawTage = false;CRect rect;this->GetClientRect(rect);Gdiplus::Bitmap* _canva = new Bitmap(rect.Width(), rect.Height());Gdiplus::Graphics* canvaG = Gdiplus::Graphics::FromImage(_canva);Rect destinationRect(10, 0, rect.Width(), rect.Height()); VADirector::sharedDirector()->initDraw(canvaG);m_scene->draw();Bitmap* _bitmap;if(!bitmap)_bitmap = _canva;else_bitmap = bitmap;CLSID encoderClsid;this->GetParent();CString t = type.Right(type.GetLength()-1);if(t == "jpg") t = "jpeg";GetEncoderClsid(L"image/" + t, &encoderClsid);_bitmap->Save(filePath+type, &encoderClsid, NULL);
}void ImageView::addImage(const WCHAR* filename){VaImage* img = VaImage::FromFile(filename);m_scene->addChild(img);imgList.push_back(img);if(m_tagArrange){autoArrange();}
}void ImageView::savePlis( CString filePath, CString ImageType)
{filePath += ".plist";const wchar_t* ffd = filePath.GetBuffer(filePath.GetLength());USES_CONVERSION;const char* file = W2A(ffd);const char* _type = W2A(ImageType.GetBuffer(ImageType.GetLength()));PublishPlist* plist = new PublishPlist(file,_type, "100, 100");for(int i = 0; i< (int)imgList.size(); i++){VaImage* img = imgList.at(i);plist->addItem( img->getName(), int(img->getPosition().x), int(img->getPosition().y), int(img->getSize().width), int(img->getSize().height) );}plist->publish();
}void ImageView::setAutoArrange( float isArrange )
{m_tagArrange = isArrange;
}void ImageView::autoArrange(){//排序,由大小std::sort(imgList.begin(), imgList.end(), CRectPlacement::TRect::Greaters);CRectPlacement crp = CRectPlacement(imgList.front()->getSize().width, imgList.front()->getSize().height);for(int i = 0; i< (int)imgList.size(); i++){CRectPlacement::TRect r(0, 0, imgList.at(i)->getSize().width, imgList.at(i)->getSize().height);bool bPlaced = false;bPlaced = crp.AddAtEmptySpotAutoGrow(&r, 100000, 100000);imgList.at(i)->setPosition(VAPoint(r.x, r.y));}
}/*获取Image编码
* format: image/png, image/jpeg, image/gif
* pClsid: CLSID
*/
int ImageView::GetEncoderClsid( const WCHAR* format, CLSID *pClsid )
{UINT num = 0; //number of image encoder;UINT size = 0; //size of the image encoder array in bytes;ImageCodecInfo *pImageCodecInfo = NULL;GetImageEncodersSize(&num, &size);if(size ==0)return -1; //FailurepImageCodecInfo = (ImageCodecInfo *)(malloc(size));if(pImageCodecInfo==NULL)return -1;GetImageEncoders(num, size, pImageCodecInfo);for(UINT j=0; j< num; ++j){if(wcscmp(pImageCodecInfo[j].MimeType, format)==0){*pClsid = pImageCodecInfo[j].Clsid;free(pImageCodecInfo);return j;}}free(pImageCodecInfo);return -1;
}
这样我们就可以正常显示我们的图片了!
工具的完整代码可以从这里下载
转载于:https://www.cnblogs.com/dyllove98/p/3249251.html
游戏开发工具之纹理打包器-3.使用GDI+绘图相关推荐
- 纹理打包器 TexturePacker
纹理打包器 TexturePacker 序 TexturePacker介绍 TexturePacker简单使用 准备工作 添加精灵和生成 纹理贴图集json 序 在前端调用图片时,可能会使用到雪碧图( ...
- Android 游戏开发工具大升级
不同的硬件厂商为 Android 用户带来了不同尺寸和体验的设备,因此,我们也一直努力地帮助开发者们将游戏呈现到尽多的 Android 设备并使得开发过程更加高效轻松.本文将向您介绍众多新的 Andr ...
- 高端游戏开发工具:Unity Pro 2019 Mac版
Unity Pro 2019 for Mac是专业的游戏开发工具,unity pro 2019 mac版具备最先进的游戏引擎之一,新版本提供了模块化组件系统.着色器可视化编程工具.可视乎开发环境.渲染 ...
- 【转】部分游戏开发工具
2019独角兽企业重金招聘Python工程师标准>>> GPL许可证 GPL通用性公开许可证(General Public License,简称GPL).在字典中的含义 ...
- 部分游戏开发工具(转载)
GPL许可证 GPL通用性公开许可证(General Public License,简称GPL).在字典中的含义是非洲大羚羊,我们可以常常看到非常个性化的羊头,想必很多人已经非常熟悉.象征 GNU ...
- Unity3D ——强大的跨平台3D游戏开发工具教程
http://unity3d.9ria.com/?p=22 众所周知,Unity3D是一个能够实现轻松创作的多平台的游戏开发工具,是一个全面整合的专业游戏引擎.在现有的版本中,其强大的游戏制作功能已经 ...
- Action Game Maker 游戏开发工具介绍
游戏开发者的论坛(66rpg):http://bbs.66rpg.com/forum-agm-1.html 在上面的论坛看一款游戏开发工具,使开发比较便利,主要能开发2d游戏(RPG,ARPG,RTG ...
- 2022 年顶级游戏开发工具
2,000 亿美元. 这样一个可以追溯到 20 世纪 50 年代的产业现今产值已逾 2,000 亿美元,据估计,间接收入可达 1,000 亿美元.新冠疫情对于蓬勃发展中的游戏业确有益处,因为新老玩家都 ...
- Linux游戏开发工具收集
转载自 xoxoxo 最终编辑 xyk34 FMOD FMOD 是一个非常容易使用的跨平台声音引擎,能够在 WINDOWS,WINDOWS CE,LINUX,MACINTOSH,GAMECUBE,PL ...
最新文章
- 强强联合!Papers with Code携手arXiv,上传论文、提交代码一步到位
- 《精通Unix下C语言与项目实践》读书笔记(16)
- 入门4:PHP 语法基础1
- 计算机网络第三章-数据链路层
- BZOJ 4734 UOJ #269 如何优雅地求和 (多项式)
- boost::iostreams::back_inserter用法的测试程序
- HDU - 4784 Dinner Coming Soon(bfs+动态规划+优先队列)
- 浏览器实验中的故障排除
- 为什么交叉熵(cross-entropy)可以用于计算代价?
- 已创建仓库后 github提交流程
- 一个可变布局列表,有9种布局item大小,每个item可拖拽切换位置
- 面向意图的SDN北向接口
- BatchPreparedStatementSetter,用法
- foremost 原理和使用
- 中国互联网络发展状况统计报告计算机,中国互联网络发展状况统计报告-计算机网络信息中心.DOC...
- mpa和pis_有关压力单位pis
- 云虚拟主机☀️利用FileZilla,使用FTP协议给阿里云虚拟主机上传、下载文件
- MDK 5.25 J-link V9 烧写程序失败
- 压缩pdf大小的方法?怎样压缩pdf大小?pdf文档怎么压缩?pdf文件太大怎么压缩?pdf文件太大怎么压缩成小内存?如何降低pdf文件大小?怎么把pdf文件压缩到指定大小?压缩pdf的简单方法
- 快手、抖音、微视类短视频SDK接入教程,7步就能搞定