感觉cocos2d/x的各种编辑器还是挺丰富的,但由于都是免费的软件,其中有各种隐患,cocos2d/x在不断的更新,但如果相应的编辑器没更新的话,这软件就不能用了,或者有些软件的bug层出不穷,所以自己能动手开发相应的编辑器还是有必要的。一开始想用windows的GDI开发,后来再想了一下为啥不直接用cocos2d-x来开发呢,将cocos2d-x嵌入到MFC里,就可以将windows各种强大的控件跟cocos2d-x各种动画结合起来了。
原理很简单,cocos2d-x在windows上运行的时候其实也是依赖于窗口的,但那是一个顶层窗口,要稍微修改一下,将cocos2d-x运行在一个子窗口里,这样就能嵌入到编辑器里。
打开cocos2d-x的libcoco2d库里的platform/win32/CCEGLView.cpp,替换bool CCEGLView::Create()的代码:
bool bRet = false;
do
{
CC_BREAK_IF(m_hWnd);
HINSTANCE hInstance = GetModuleHandle( NULL );
WNDCLASS wc; // Windows Class Structure
// Redraw On Size, And Own DC For Window.
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = _WindowProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon( NULL, IDI_WINLOGO ); // Load The Default Icon
wc.hCursor = LoadCursor( NULL, IDC_ARROW ); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = m_menu; //
wc.lpszClassName = kWindowClassName; // Set The Class Name
CC_BREAK_IF(! RegisterClass(&wc) && 1410 != GetLastError());
// center window position
RECT rcDesktop;
GetWindowRect(GetDesktopWindow(), &rcDesktop);
WCHAR wszBuf[50] = {0};
MultiByteToWideChar(CP_UTF8, 0, m_szViewName, -1, wszBuf, sizeof(wszBuf));
// create window
m_hWnd = CreateWindowEx(
WS_EX_APPWINDOW | WS_EX_WINDOWEDGE, // Extended Style For The Window
kWindowClassName, // Class Name
wszBuf, // Window Title
WS_CAPTION | WS_POPUPWINDOW | WS_MINIMIZEBOX, // Defined Window Style
0, 0, // Window Position
//TODO: Initializing width with a large value to avoid getting a wrong client area by 'GetClientRect' function.
1000, // Window Width
1000, // Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL );
CC_BREAK_IF(! m_hWnd);
bRet = initGL();
if(!bRet) destroyGL();
CC_BREAK_IF(!bRet);
s_pMainWindow = this;
bRet = true;
} while (0);
#if(_MSC_VER >= 1600)
m_bSupportTouch = CheckTouchSupport();
if(m_bSupportTouch)
{
m_bSupportTouch = (s_pfRegisterTouchWindowFunction(m_hWnd, 0) != 0);
}
#endif /* #if(_MSC_VER >= 1600) */
return bRet;
替换为
bool bRet = false;
do
{
CC_BREAK_IF(m_hWnd);
HINSTANCE hInstance = GetModuleHandle( NULL );
WNDCLASS wc; // Windows Class Structure
// Redraw On Size, And Own DC For Window.
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = _WindowProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon( NULL, IDI_WINLOGO ); // Load The Default Icon
wc.hCursor = LoadCursor( NULL, IDC_ARROW ); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = NULL; //
wc.lpszClassName = kWindowClassName; // Set The Class Name
CC_BREAK_IF(! RegisterClass(&wc) && 1410 != GetLastError());
// center window position
RECT rcDesktop;
//GetWindowRect(GetDesktopWindow(), &rcDesktop);
GetClientRect(mParentHwnd,&rcDesktop);
WCHAR wszBuf[50] = {0};
MultiByteToWideChar(CP_UTF8, 0, m_szViewName, -1, wszBuf, sizeof(wszBuf));
// create window
m_hWnd = CreateWindowEx(
WS_EX_APPWINDOW | WS_EX_WINDOWEDGE, // Extended Style For The Window
kWindowClassName, // Class Name
wszBuf, // Window Title
WS_CHILDWINDOW|WS_VISIBLE, // Defined Window Style
0, 0, // Window Position
//TODO: Initializing width with a large value to avoid getting a wrong client area by 'GetClientRect' function.
1000, // Window Width
1000, // Window Height
mParentHwnd, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL );
CC_BREAK_IF(! m_hWnd);
bRet = initGL();
if(!bRet) destroyGL();
CC_BREAK_IF(!bRet);
s_pMainWindow = this;
bRet = true;
} while (0);
#if(_MSC_VER >= 1600)
m_bSupportTouch = CheckTouchSupport();
if(m_bSupportTouch)
{
m_bSupportTouch = (s_pfRegisterTouchWindowFunction(m_hWnd, 0) != 0);
}
#endif /* #if(_MSC_VER >= 1600) */
return bRet;
在libcocos2d项目下增加一个文件,里面存放MFC跟cocos2d-x交互的C函数。
extern "C"
{
CC_DLL bool M2InitializeApplication( HWND hwnd )
{
cocos2d::CCEGLView::SetParentHwnd(hwnd);
// create the application instance
AppDelegate app;
cocos2d::CCEGLView* eglView = cocos2d::CCEGLView::sharedOpenGLView();
eglView->setFrameSize(480, 320);
// The resolution of ipad3 is very large. In general, PC's resolution is smaller than it.
// So we need to invoke 'setFrameZoomFactor'(only valid on desktop(win32, mac, linux)) to make the window smaller.
//eglView->setFrameZoomFactor(0.4f);
cocos2d::CCApplication::sharedApplication()->run();
return true;
}
CC_DLL bool M2GameCleanUp()
{
cocos2d::CCDirector::sharedDirector()->end();
cocos2d::CCEGLView* eglView = cocos2d::CCEGLView::sharedOpenGLView();
eglView->Destroy();
return true;
}
CC_DLL bool M2GameLoop( float interval )
{
cocos2d::CCDirector::sharedDirector()->mainLoop();
return true;
}
}
后在MFC的对话框或View的初始化函数里增加如下代码,以绑定cocos2d的句柄并设置cocos2d视口的大小:
HWND hCocos = ::GetDlgItem(this->m_hWnd, IDC_PANEL);
CRect rect;
::GetWindowRect(hCocos, &rect);
ScreenToClient(&rect);
::MoveWindow(hCocos, rect.left, rect.top, 480, 320, TRUE);
::M2InitializeApplication(hCocos);
增加一个定时器辅助cocos2d进行重绘:
SetTimer(1,16,NULL);
在OnTimer函数里刷新cocos2d-x:
::M2GameLoop(16);
DEMO可以在这里下载:http://download.csdn.net/detail/visualcatsharp/4947482