c++ 编写自己的小型游戏开发库
2010-10-05 22:49
519 查看
之前接触了SDL,的确是个很好的轻量级游戏引擎,其实自己一直也有个想法,自己来开发个游戏库,呵呵,有点大了,现在想想,在windows下也就是对图形操作和窗口消息的封装吧。试着写写看吧,花了两天的时间,搞出个雏形,发来给大家分享下:
定义了两个类,surface和wnd,surface就是对图形的操作,这里封装的是GDI+,wnd就是对窗口的封装,包括它的创建和消息处理等。实际编写中发现gdi+对图形的操作蛮方便的,但是效率其实不如gdi,所以我的代码里有大量的gdi操作代码的注释,这里我想模拟双缓冲技术,写的要是有问题还望大家指正。wnd的窗口创建我用的是多线程,所以每个窗口对应自己的消息线程,但是窗口处理函数是共用的,所以消息处理代码要判断当前消息是对于哪个窗口的。下面看下实例代码:
在peekmessage上有个轮询的过程,所以我们要用setrun要添加自定义处理函数,来对窗口不停的刷新。addevent是添加事件处理的。setdelay是轮询的延迟函数,create便创建窗体了,创建后pause下,让主线程暂停。
本文有不足之处,还望大家多多指正。
#pragma warning(disable:4786) #define ULONG_PTR ULONG #include <windows.h> #include <gdiplus.h> #include <map> #include <vector> #include <iostream> #include <string> #pragma comment(lib, "gdiplus.lib") using namespace Gdiplus; using namespace std; class surface{ public: surface(); ~surface(); static void init(); static void unit(); static surface *loadimg(wchar_t*,int,int); void create(int,int); int getwidth(); int getheight(); void bitblt(surface *,int,int,int,int); Graphics *getgdi(); Bitmap* getbitmap(); void string(wchar_t *,int,int,int,Color,wchar_t *); void line(int,int,int,int,int,Color); void rect(int,int ,int ,int ,int ,Color); void dot(int ,int ,int ,Color ); void fillrect(int,int,int,int,Color); void image(wchar_t *,int ,int ,int ,int ); private: Graphics *g; int width; int height; static ULONG_PTR m_gdiplusToken; Bitmap *b; }; ULONG_PTR surface::m_gdiplusToken=0; surface::surface(){ width=0; height=0; } surface::~surface(){ if(b) delete b; if(g) delete g; } void surface::init(){ GdiplusStartupInput gdiplusStartupInput; GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); } void surface::unit(){ GdiplusShutdown(m_gdiplusToken); } Bitmap* surface::getbitmap(){ return b; } void surface::create(int w,int h){ width=w; height=h; b=new Bitmap(w,h); g=Graphics::FromImage(b); } surface* surface::loadimg(wchar_t *path,int w,int h){ Image *i=Image::FromFile(path); surface *sur=new surface; sur->create(w,h); sur->getgdi()->DrawImage(i,0,0,w,h); return sur; } Graphics *surface::getgdi(){ return g; } int surface::getheight(){ return height; } int surface::getwidth(){ return width; } void surface::bitblt(surface *src,int x,int y,int w,int h){ g->DrawImage(src->getbitmap(),x,y,w,h); // BitBlt(g->GetHDC(),x,y,w,h,src->getgdi()->GetHDC(),0,0,SRCCOPY); } void surface::string(wchar_t *str,int x,int y,int big=1,Color c=Color(255,0,0,0),wchar_t *style=L"Latha"){ SolidBrush brush(c); FontFamily fontFamily(style); Font font(&fontFamily,big,FontStyleRegular,UnitInch); PointF pointF(x,y); g->DrawString(str,-1,&font,pointF,&brush); } void surface::line(int x1,int y1,int x2,int y2,int big=1,Color c=Color(255,0,0,0)){ Pen p(c); p.SetWidth(big); g->DrawLine(&p,x1,y1,x2,y2); /* HPEN b=CreatePen(PS_SOLID,3,RGB(255,255,255)); HPEN old=(HPEN)SelectObject(m_hdc,b); MoveToEx(m_hdc,x1,y1,0); LineTo(m_hdc,x2,y2); SelectObject(m_hdc,old); DeleteObject(b);*/ } void surface::dot(int x,int y,int big=1,Color c=Color(255,0,0,0)){ Pen p(c); p.SetWidth(big); g->DrawLine(&p,x,y,x,y); } void surface::rect(int x,int y,int w,int h,int big=1,Color c=Color(255,0,0,0)){ Pen p(c); p.SetWidth(big); g->DrawRectangle(&p,x,y,w,h); } void surface::fillrect(int x,int y,int w,int h,Color c=Color(255,0,0,0)){ SolidBrush brush(c); g->FillRectangle(&brush,x,y,w,h); /* HBRUSH b=CreateSolidBrush(RGB(111,111,111)); RECT r={0,0,640,480}; FillRect(m_hdc,&r,b); DeleteObject(b);*/ } void surface::image(wchar_t *str,int x,int y,int w,int h){ Image i(str); g->DrawImage(&i,x,y,w,h); } class wnd{ public: wnd(); ~wnd(); void create(int ,int ); HWND getwindow(); LRESULT sendmessage(UINT,WPARAM,LPARAM); LRESULT postmessage(UINT,WPARAM,LPARAM); void addevent(UINT,LRESULT (*)(HWND,WPARAM,LPARAM)); void removeevent(UINT,LRESULT (*)(HWND,WPARAM,LPARAM)); void setrun(void (*)(wnd *,LPVOID),LPVOID); surface *draw(); void setdelay(int); void exit(); private: int delay; void (*run)(wnd *,LPVOID); static map<UINT,LRESULT (*)(HWND,WPARAM,LPARAM)>e; int width; int height; HWND hwnd; static LRESULT CALLBACK wndproc(HWND,UINT,WPARAM,LPARAM); static DWORD WINAPI init(LPVOID); HANDLE thread; surface sur; LPVOID flag; static wnd *th; static vector<wnd*> wndmanage; int _exit; }; wnd* wnd::th=0; vector<wnd*> wnd::wndmanage; map<UINT,LRESULT (*)(HWND,WPARAM,LPARAM)> wnd::e; wnd::wnd(){ run=0; delay=0; _exit=0; } wnd::~wnd(){ } void wnd::setdelay(int i){ delay=i; } void wnd::create(int w,int h){ width=w; height=h; thread=CreateThread(0,0,init,(LPVOID)this,0,0); } surface *wnd::draw(){ return &sur; } void wnd::addevent(UINT m,LRESULT (*p)(HWND,WPARAM,LPARAM)){ e[m]=p; } void wnd::removeevent(UINT m,LRESULT (*p)(HWND,WPARAM,LPARAM)){ map<UINT,LRESULT (*)(HWND,WPARAM,LPARAM)>::iterator it; it=e.find(m); if(it!=e.end()){ e.erase(it); } } LRESULT CALLBACK wnd::wndproc(HWND h,UINT m ,WPARAM w,LPARAM l){ map<UINT,LRESULT (*)(HWND,WPARAM,LPARAM)>::iterator it; it=e.find(m); if(it!=e.end()){ return ((LRESULT (*)(HWND,WPARAM,LPARAM))it->second)(h,w,l); } if(m==WM_CREATE){ } if(m==WM_ERASEBKGND){ return 1; } if(m==WM_PAINT){ //MessageBox(0,0,0,0); PAINTSTRUCT ps; HDC dc=BeginPaint(h,&ps); RECT r; GetClientRect(h,&r); Graphics g(dc); //EnterCriticalSection(section); for(int i=0;i<wndmanage.size();i++){ // cout<<((wnd*)wndmanage[i])->getwindow()<<" "<<h<<endl; if(((wnd*)wndmanage[i])->getwindow()==h){ break; } } // if(i!=wndmanage.size()){ // cout<<i<<endl; if(((wnd*)wndmanage[i])->run!=0){ ((wnd*)wndmanage[i])->run((wnd*)wndmanage[i],((wnd*)wndmanage[i])->flag); g.DrawImage(((wnd*)wndmanage[i])->sur.getbitmap(),0,0,r.right-r.left,r.bottom-r.top); } // } // LeaveCriticalSection(section); /* g.FillRectangle(&SolidBrush(Color(255,100,100,100)),0,0,640,480); for(int i=40;i<480;i+=40){ g.DrawLine(&Pen(Color(255,200,200,200)),0,i,640,i); } for(i=40;i<640;i+=40){ g.DrawLine(&Pen(Color(255,200,200,200)),i,0,i,480); }*/ EndPaint(h,&ps); return 0; } if(m==WM_DESTROY){ for(int i=0;i<wndmanage.size();i++){ cout<<((wnd*)wndmanage[i])->getwindow()<<" "<<h<<endl; if(((wnd*)wndmanage[i])->getwindow()==h){ break; } } wndmanage.erase(&wndmanage[i]); PostQuitMessage(0); } return DefWindowProc(h,m,w,l); } DWORD WINAPI wnd::init(LPVOID l){ wnd * w=(wnd *)l; WNDCLASS wndclass; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hbrBackground=(HBRUSH) GetStockObject(BLACK_BRUSH); wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); wndclass.hIcon=LoadIcon(NULL,IDC_ARROW); wndclass.hInstance=GetModuleHandle(0); wndclass.lpfnWndProc=wndproc; wndclass.lpszClassName="sx"; wndclass.lpszMenuName="sx"; wndclass.style=CS_HREDRAW|CS_VREDRAW; RegisterClass(&wndclass); RECT rect = {0,0,w->width,w->height}; AdjustWindowRect(&rect,((WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX) & ~WS_SIZEBOX),false); th=w; w->hwnd=::CreateWindowEx(0,"sx","sx",((WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX) & ~WS_SIZEBOX) ,CW_USEDEFAULT, CW_USEDEFAULT,rect.right-rect.left, rect.bottom-rect.top,NULL,NULL,GetModuleHandle(0),NULL); wndmanage.push_back(w); w->sur.create(w->width,w->height); ShowWindow(w->hwnd,1); UpdateWindow(w->hwnd); HDC dc=GetDC(w->hwnd); RECT r; GetClientRect(w->hwnd,&r); Graphics g(dc); /* char a[10]; sprintf(a,"%d",r.right-r.left); MessageBox(0,a,0,0);*/ /* HDC hdc=CreateCompatibleDC(dc); HBITMAP bit=CreateCompatibleBitmap(dc,w->width,w->height); SelectObject(hdc,bit); HPEN b=CreatePen(PS_SOLID,3,RGB(255,255,255)); SelectObject(hdc,b); w->sur.attach(hdc);*/ MSG msg; while(1) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)){ if(msg.message==WM_QUIT){ break; } TranslateMessage(&msg); DispatchMessage(&msg); }else{ // EnterCriticalSection(section); if(w->run!=0){ w->run(w,w->flag); g.DrawImage(w->sur.getbitmap(),0,0,r.right-r.left,r.bottom-r.top); }else{ HBRUSH b=CreateSolidBrush(RGB(0,0,0)); RECT r={0,0,w->width,w->height}; FillRect(dc,&r,b); DeleteObject(b); } if(w->_exit==1){ break; } /* for(int i=40;i<480;i+=40){ MoveToEx(hdc,0,i,0); LineTo(hdc,640,i); }*/ //w->draw()->bitblt(img,0,0,200,200); /* for(int i=40;i<640;i+=40){ MoveToEx(hdc,i,0,0); LineTo(hdc,i,480); }*/ //::BitBlt(dc,0,0,w->width,w->height,hdc,0,0,SRCCOPY); Sleep(w->delay); // LeaveCriticalSection(section); } Sleep(1); } return 0; } LRESULT wnd::sendmessage(UINT m,WPARAM w,LPARAM l){ return ::SendMessage(hwnd,m,w,l); } LRESULT wnd::postmessage(UINT m,WPARAM w,LPARAM l){ return ::PostMessage(hwnd,m,w,l); } HWND wnd::getwindow(){ return hwnd; } void wnd::setrun(void (*p)(wnd *,LPVOID),LPVOID l){ flag=l; run=p; } void wnd::exit(){ _exit=1; }
定义了两个类,surface和wnd,surface就是对图形的操作,这里封装的是GDI+,wnd就是对窗口的封装,包括它的创建和消息处理等。实际编写中发现gdi+对图形的操作蛮方便的,但是效率其实不如gdi,所以我的代码里有大量的gdi操作代码的注释,这里我想模拟双缓冲技术,写的要是有问题还望大家指正。wnd的窗口创建我用的是多线程,所以每个窗口对应自己的消息线程,但是窗口处理函数是共用的,所以消息处理代码要判断当前消息是对于哪个窗口的。下面看下实例代码:
LRESULT onbuttondown(HWND h,WPARAM w,LPARAM l){ MessageBox(0,"sx","sx",0); return 0; } surface *img; void run(wnd *w,LPVOID l){ w->draw()->fillrect(0,0,640,480,Color(255,255,255,255)); for(int i=40;i<480;i+=40) w->draw()->line(0,i,640,i,1,Color(255,100,100,100)); //w->draw()->bitblt(img,0,0,200,200); for(i=40;i<640;i+=40) w->draw()->line(i,0,i,480,1,Color(255,100,100,100)); w->draw()->fillrect(0,0,80,80); } void run1(wnd *w,LPVOID l){ w->draw()->fillrect(0,0,640,480,Color(255,0,0,0)); for(int i=40;i<200;i+=40) w->draw()->line(0,i,200,i,1,Color(255,100,100,100)); // w->draw()->fillrect(0,0,80,80); } wnd w; wnd w1; LRESULT ondb(HWND h,WPARAM w,LPARAM l){ if(h==w1.getwindow()) MessageBox(0,"sx1","sx1",0); else MessageBox(0,"sx","sx",0); return 0; } main(){ surface::init(); atexit(surface::unit); img=surface::loadimg(L"c://1.jpg",1000,1000); w.setrun(run,0); //w.setdelay(100); w.create(640,480); //w.addevent(WM_LBUTTONUP,&onbuttondown); w1.setrun(run1,0); w1.setdelay(100); w1.addevent(WM_LBUTTONUP,ondb); w1.create(300,300); system("pause"); }
在peekmessage上有个轮询的过程,所以我们要用setrun要添加自定义处理函数,来对窗口不停的刷新。addevent是添加事件处理的。setdelay是轮询的延迟函数,create便创建窗体了,创建后pause下,让主线程暂停。
本文有不足之处,还望大家多多指正。
相关文章推荐
- c++ 编写自己的小型游戏开发库(续)
- 游戏开发之在UE4中编写C++代码控制角色
- 游戏开发之在UE4中编写C++代码控制角色
- 游戏开发之在UE4中编写C++代码控制角色
- 游戏开发之在UE4中编写C++代码控制角色
- 游戏开发之在UE4中编写C++代码控制角色
- 游戏开发之在UE4中编写C++代码控制角色
- 使用C++与SFML编写一个简单的撞球游戏Part1——新建工程以及设置
- 转载--c++游戏开发中使用json .
- 使用C++与SFML编写一个简单的撞球游戏Part8——添加AI弹板
- C++零基础教程,游戏开发入门
- 【 Visual C++】游戏开发笔记之二——最简单的DirectX,vc窗口的编写
- C++ 新手游戏开发之细节问题(1)
- 基于C++和JavaScript的全平台全栈式游戏开发解决方案的思考
- 用C++实现跨平台游戏开发之Irrlicht引擎
- 构建自己的C/C++插件开发框架
- 构建自己的C/C++插件开发框架(二)——总体功能
- Andriod C++游戏开发初探
- 【Android游戏开发-笨木头】抛弃自带输入框,自己实现~自由自在~!
- C++ 3D游戏开发