游戏开发工具之纹理打包器-3.使用GDI+绘图
生活随笔
收集整理的這篇文章主要介紹了
游戏开发工具之纹理打包器-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+绘图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Epic大特卖开启!7.5折套娃优惠券来
- 下一篇: 判断凸多边形