1.在cocos2dx目录下创建基于对话框的MFC工程,对话框中间放一个Picture控件
2.添加cocos2dx的相关头文件包含路径、库包含路径和依赖项,可以参考其他cocos工程设置
3.选中Picture控件后右键单击,在弹出菜单中找到“添加变量”。为Picture控件生成一个控件变量。这里命名为m_cocosWin,并点击完成
4.右击工程添加MFC类,类名里输入“CCocos2dXWin”,并选择基类CWnd。把上面的m_cocosWin变量类型改为CCocoWin 然后点击“完成”并做如下修改。
4.1头文件添加变量和函数
//是否已经初始化 BOOL m_bInitCocos2dX; //创建Cocos2dX窗口 BOOL CreateCocos2dXWindow();
4.2 cpp添加COCOS的头文件,并加入一个全局变量
#include "AppDelegate.h" #include "cocos2d.h" USING_NS_CC; AppDelegate CocoApp;
4.3函数实现
//创建Cocos2dX窗口 BOOL CCocoWin::CreateCocos2dXWindow() { //新建一个CRect变量获取窗口的客户区大小 CRect tClientRect; GetClientRect(&tClientRect); //取得使用的OpenGL视窗 CCEGLView* eglView = CCEGLView::sharedOpenGLView(false,GetSafeHwnd()); //指定客户区大小。 eglView->setFrameSize(tClientRect.Width(),tClientRect.Height()); //调用程序的运行函数,增加参数bool型变量控制是否进行消息循环。因为MFC控件本身有自已的消息响应处理。如果不改动的话,这里就会进入死循环。 cocos2d::CCApplication::sharedApplication()->run(); //这里将变量设置为TRUE m_bInitCocos2dX = TRUE; SetTimer(1,15,NULL); return TRUE; }
4.4在CCocoToolDlg的OnInitDialog()方法中调用 CreateCocos2dXWindow()
m_cocosWin.CreateCocos2dXWindow();
5.利用类视图为CCocoWin添加如下方法
代码实现如下:
void CCocoWin::OnTimer(UINT_PTR nIDEvent) { //我们写一个renderWorld函数代表Cocos2d-x的世界渲染 cocos2d::CCApplication::sharedApplication()->renderWorld(); CWnd::OnTimer(nIDEvent); } void CCocoWin::OnDestroy() { //在Cocos2d-x的引擎文件CCEGLView_win32.cpp中CCEGLView::release()会再次发送调用DestroyWindow,所以这里用变量m_bInitCocos2dX做下判断,避免二次销毁 if(TRUE == m_bInitCocos2dX) { //退出将m_bInitCocos2dX设为FALSE m_bInitCocos2dX = FALSE; //释放定时器资源 KillTimer(1); //调用显示设备单件实例对象的end函数 CCDirector::sharedDirector()->end(); //处理一次下一帧,必须调用. CCDirector::sharedDirector()->mainLoop(); CWnd::OnDestroy(); } } void CCocoWin::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); // TODO: 在此处添加消息处理程序代码 if(TRUE == m_bInitCocos2dX) { CRect tClientRect; GetClientRect(&tClientRect); //重新设置窗口大小及投影矩阵 CCEGLView::sharedOpenGLView()->resize(tClientRect.Width(),tClientRect.Height()); CCDirector::sharedDirector()->reshapeProjection(CCSizeMake(tClientRect.Width(),tClientRect.Height())); } }
6.CCEGLView做如下修改
头文件
virtual bool Create(bool bCreateWin=true,HWND hWnd=NULL); public: bool m_bIsSelfCreWin;//是否cocos自己创建了窗口 static CCEGLView* sharedOpenGLView(bool bCreateWin=true,HWND hWnd=NULL);//bCreateWin是否自己创建窗口,hWnd已有的MFC窗口句柄
cpp
void CCEGLView::centerWindow() { if (! m_hWnd||!m_bIsSelfCreWin) { return; } .... } bool CCEGLView::Create(bool bCreateWin,HWND hWnd) { bool bRet = false; do { CC_BREAK_IF(m_hWnd); m_bIsSelfCreWin=bCreateWin; if (bCreateWin) { 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 ); }else { m_hWnd=hWnd; } 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; } CCEGLView* CCEGLView::sharedOpenGLView(bool bCreateWin,HWND hWnd) { if (s_pEglView == NULL) { s_pEglView = new CCEGLView(); if(!s_pEglView->Create(bCreateWin,hWnd)) { delete s_pEglView; s_pEglView = NULL; } } return s_pEglView; }
7.CCEGLView做如下修改
头文件添加方法
//帧循环调用渲染 virtual bool renderWorld();
cpp
bool CCApplication::renderWorld() { static LARGE_INTEGER nFreq; static LARGE_INTEGER nLast; static LARGE_INTEGER nNow; static bool sbinit=true; //只执行一次 if (sbinit) { QueryPerformanceFrequency(&nFreq); QueryPerformanceCounter(&nLast); sbinit=false; } // Get current time tick. QueryPerformanceCounter(&nNow); // If it's the time to draw next frame, draw it, else sleep a while. if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart) { nLast.QuadPart = nNow.QuadPart; CCDirector::sharedDirector()->mainLoop(); return true; } return false; } int CCApplication::run() { PVRFrameEnableControlWindow(false); // Main message loop: MSG msg; LARGE_INTEGER nFreq; LARGE_INTEGER nLast; LARGE_INTEGER nNow; QueryPerformanceFrequency(&nFreq); QueryPerformanceCounter(&nLast); // Initialize instance and cocos2d. if (!applicationDidFinishLaunching()) { return 0; } CCEGLView* pMainWnd = CCEGLView::sharedOpenGLView(); //pMainWnd->centerWindow(); ShowWindow(pMainWnd->getHWnd(), SW_SHOW); //cocos自己创建的窗口才要循环处理消息 bool bloop=CCEGLView::sharedOpenGLView()->m_bIsSelfCreWin; if (bloop) { while (1) { if (! PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // Get current time tick. QueryPerformanceCounter(&nNow); // If it's the time to draw next frame, draw it, else sleep a while. if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart) { nLast.QuadPart = nNow.QuadPart; CCDirector::sharedDirector()->mainLoop(); } else { Sleep(0); } continue; } if (WM_QUIT == msg.message) { // Quit message loop. break; } // Deal with windows message. if (! m_hAccelTable || ! TranslateAccelerator(msg.hwnd, m_hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } return 0; }
8.新建个Classes文件夹,并把AppDelegate两个文件复制过去,在VS中右击包含到工程里
9.把工程的工作目录指向Resources文件夹,可以是以前的COCOS工程的Resources目录
如果出现类似 error LNK2005: "void * __cdecl operator new(unsigned int)的错误,参考
http://m.blog.csdn.net/blog/dotphoenix/13511863
运行效果:
具体修改的思路不做详细说明,具体请参考