本节主要讲一下如何在MFC窗口中使用cocos2dx

  在做比较复杂的游戏,有时需要通过一些工具来编辑生成关卡或者特效,技能等的配置文件。为了方便配置,需要可以通过修改参数直观得到显示的效果。这就需要将引擎加载到工具中进行效果显示,这里我们将cocos2dx应用到MFC,得到最终效果如下:

一、通过HWND创建cocos2dx窗口View

  通过参考 GLViewImpl 及 GLView 创建MFC中可以使用的 CMyEGLView 。在GLView中我们可以看到如下所示,Win32中实际使用的窗口指针就是HWND。

    

同时,继承GLView时有4个必须重载实现的函数如下:

  

因此,我们自己实现的 CMyEGLView 需要 接口如下:

class /*CC_DLL*/ CMyEGLView : public cocos2d::GLView
{
public:
static CMyEGLView* createWithRect(const std::string& viewName, Rect size, HWND handle, float frameZoomFactor = 1.0f); bool initWithRect(const std::string& viewName, Rect rect, HWND handle, float frameZoomFactor);/* override functions */
virtual bool isOpenGLReady() override;
virtual void end() override;
virtual void swapBuffers() override;
virtual void setIMEKeyboardState(bool bOpen) override; virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
HWND getWin32Window() { return m_hWnd; }
#endif /* (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) */ protected: CMyEGLView();
virtual ~CMyEGLView(); bool initGlew(); float _frameZoomFactor;
HDC m_hDC;
HGLRC m_hRC;
HWND m_hWnd; bool _captured;
};

由上述代码可以看到,这里多出了一个WindowProc接口,这是用来将MFC窗口的指令传入cocos2dx中并对应转成相应的消息。主要通过参考GLViewImpl 中的回调实现,详细可以参考文章结尾的源码。

  同时在initWithRect中通过窗口指针 m_hWnd 取得窗口 m_hDC 并通过SetupPixelFormat中设置如下代码实现窗口对Opengl的支持。

static void SetupPixelFormat(HDC hDC)
{
int pixelFormat; PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // size
1, // version
PFD_SUPPORT_OPENGL | // OpenGL window
PFD_DRAW_TO_WINDOW | // render to window
PFD_DOUBLEBUFFER, // support double-buffering
PFD_TYPE_RGBA, // color type
, // preferred color depth
0, 0, 0, 0, 0, 0, // color bits (ignored)
, // no alpha buffer
0, // alpha bits (ignored)
0, // no accumulation buffer
0, 0, 0, 0, // accum bits (ignored)
24, // depth buffer
8, // no stencil buffer
0, // no auxiliary buffers
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0, // no layer, visible, damage masks
}; pixelFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, pixelFormat, &pfd);
}

其余初始化opengl es等同样直接参考GLViewImpl 中实现。

二、在AppDelegate中创建CMyEGLView 

  参考Application::run() 实现并将其拆成3部分在AppDelegate中实现,添加如下接口:

   // 传入窗口指针并创建
virtual void CreateWnd(HWND hwnd); // 刷新显示
virtual void Run2(); // 窗口大小变化
void Resize(int width, int height); // MFC 消息
LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);

1、CreateWnd用于传入MFC窗口指针,同时调用applicationDidFinishLaunching来实现View的创建等;

2、Run2用于原来run中的while循环部分,即执行 director->mainLoop();

3、在析构函数中添加对view释放等操作。

详细可以参考文章结尾的源码。

三、在MFCAPPView中使用AppDelegate

1、首先在cocos2dx项目中添加一个MFC项目,如下图所示:  

  

2、添加MFC项目对cocos2dx的项目引用

  右键属性->通用属性->引用->添加新引用->libcocos2d

3、在视图->属性管理器中添加现有的cocos2dx属性表,如下:

  右键添加现有属性表,在~/cocos2d/cocos/2d 目录找到对应的属性表进行添加,注意先后顺序。

  

  然后在项目的属性页->C/C++->常规->附加包含目录中添加如下头文件引用目录:

$(EngineRoot)cocos\editor-support;$(EngineRoot)cocos;$(EngineRoot)cocos\platform;$(EngineRoot)cocos\platform\desktop;$(EngineRoot)external\glfw3\include\win32;$(EngineRoot)external\win32-specific\gles\include\OGLES;$(EngineRoot)external\freetype2\include\win32\freetype2;$(EngineRoot)external\freetype2\include\win32\;$(EngineRoot)external

4、然后对应的在MFCApplicationView.h中添加如下:

// 操作
public:
afx_msg void OnTimer(UINT_PTR nIDEvent);
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
afx_msg void OnSize(UINT nType, int cx, int cy);
protected:
AppDelegate m_app;
bool m_bCreated;

  在MFCApplicationView.cpp中添加对应的消息映射

BEGIN_MESSAGE_MAP(CMFCApplicationView, CView)
// 标准打印命令
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CMFCApplicationView::OnFilePrintPreview)
ON_WM_CONTEXTMENU()
ON_WM_RBUTTONUP() ON_WM_TIMER()
ON_WM_SIZE()
END_MESSAGE_MAP()

  同时实现.h中的三个函数,如下:

void CMFCApplicationView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (m_bCreated)
{
m_app.Run2();
}
}
void CMFCApplicationView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码 if (cx != && cy != )
{ if (!m_bCreated)
{
m_app.CreateWnd(m_hWnd);
SetTimer(, , NULL);
m_bCreated = true;
} m_app.Resize(cx, cy);
}
}
LRESULT CMFCApplicationView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: 在此添加专用代码和/或调用基类
if ( == m_app.WindowProc(message, wParam, lParam))
return ;
return CView::WindowProc(message, wParam, lParam);
}

到这里,即可以在MFC中正常使用cocos2dx了,同时还可以正常响应点击等消息。

5、编译后发现MFC中定义OS_WINDOWS冲突,在stdafx.h添加如下:

//去除MFC中与cocos2dx冲突的默认定义
#ifdef OS_WINDOWS
#undef OS_WINDOWS
#endif

四、其他

  然而同这里 http://www.cnblogs.com/GuyaWeiren/p/4600937.html 通过glfw创建一个新的窗口一样,我这里测试最新cocos2dx-3.9版本同样存在内存泄漏。经测试,直接用cocos2dx源码也一样,只要在MFC中用了AppDelegate就存在泄漏。暂无解决办法,希望有同学知道的可以知会一下~~

完整代码地址:https://github.com/mydishes/cocos2dx-Ex/tree/master/MFCView

cocos2dx - 在MFC中使用cocos2dx的更多相关文章

  1. 强行在MFC窗体中渲染Cocos2d-x 3.6

    [前言] 把Cocos2dx渲染到另一个应用程序框架中的方法,在2.x时代有很多大神已经实现了,而3.x的做法网上几乎找不着.这两天抽空强行折腾了一下,不敢独享,贴出来供大家参考. [已知存在的问题] ...

  2. 使用“Cocos引擎”创建的cpp工程如何在VS中调试Cocos2d-x源码

    前段时间Cocos2d-x更新了一个Cocos引擎,这是一个集合源码,IDE,Studio这一家老小的整合包,我们可以使用这个Cocos引擎来创建我们的项目. 在Cocos2d-x被整合到Cocos引 ...

  3. cocos2dx 3.7中 AppDelegate.h的class TestController;这种写法的具体意思不太明白,只能猜是类似于外部定义的东西。

    cocos2dx 3.7中 AppDelegate.h的class TestController;这种写法的具体意思不太明白,只能猜是类似于外部定义的东西.

  4. 解决cocos2dx在Xcode中运行时报:convert: iCCP: known incorrect sRGB profile 的问题

    解决cocos2dx在Xcode中运行时报:convert: iCCP: known incorrect sRGB profile 的问题 本文的实践来源是参照了两个帖子完成的: http://dis ...

  5. cocos2d-x 3.0rc2中读取sqlite文件

    cocos2d-x 3.0rc2中读取sqlite文件的方式,在Android中直接读取软件内的会失败.须要复制到可写的路径下 sqlite3* dbFile = NULL; std::string ...

  6. ios怎样实现快速将显卡中数据读出压缩成视频在cocos2dx扩展开发中

    如果解决ios怎样实现快速将显卡中数据读出压缩成视频在cocos2dx扩展开发中 手机平台性能是个关键问题. 压缩视频分成3个步骤: 读取显卡数据, 使用编码器压缩,保存文件. 使用libav 压缩的 ...

  7. Cocos2d-x游戏开发中的消息机制:CCNotificationCenter的使用

    在HTML5游戏开发中,js可以使用Event对象的addEventListener(添加事件监听).dispatchEvent(触发事件)实现监听机制,如果在coocos2d-x中,去实现这种机制该 ...

  8. 深入分析Cocos2d-x 2.0中的“纹理”

    对CCImage的绘制是通过CCTexture2D来实现的(OPENGL es)通过纹理绘制到某个面. (本文中所提到的方法在cocos2d2.0中部分有调整,请应用时候具体察看源码)1. 首先来了解 ...

  9. lua 中处理cocos2dx 的button 事件

    lua 中处理cocos2dx 的button 事件 2014-05-08 09:44:32|  分类: lua |举报 |字号 订阅   1.引入这个类:require "GuiConst ...

随机推荐

  1. tkinter第一章

    tk1 ------------------------------------------------------------------------------------------ impor ...

  2. ★电车难题的n个坑爹变种

    哲学家都不会做的电车难题变异 此题会答清华北大 "电车难题(Trolley Problem)"是伦理学领域最为知名的思想实验之一,其内容大致是: 一个疯子把五个无辜的人绑在电车轨道 ...

  3. 201521123055 《Java程序设计》第7周学习总结

    1. 本章学习总结 2. 书面作业 1.ArrayList代码分析 1.1 解释ArrayList的contains源代码 1.2 解释E remove(int index)源代码 1.3 结合1.1 ...

  4. 201521123034《Java程序设计》第十四周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...

  5. openfire:openfire单独编译指定插件的方法

    方法一: openfire默认编译时,是同时编译主程序和所有在plugins目录中的插件.但进行插件开发时,这样编译就太费时费力.使用ant plugins可以只编译插件,能够节省部分时间.最节省时间 ...

  6. 笔记3 linux 多线程 条件变量+互斥锁

    //cond lock #include<stdio.h> #include<unistd.h> #include<pthread.h> struct test { ...

  7. request.getParameter()获取URL中文参数乱码的解决办法

    这个问题耽误好长时间,URL传中文参数出现乱码,就算首次使用request接收就添加 request.setCharacterEncoding("UTf-8"); 依然报错不误. ...

  8. Spring第三篇【Core模块之对象依赖】

    前言 在Spring的第二篇中主要讲解了Spring Core模块的使用IOC容器创建对象的问题,Spring Core模块主要是解决对象的创建和对象之间的依赖关系,因此本博文主要讲解如何使用IOC容 ...

  9. Python-老男孩-03_socket

    Socket简介: 所谓Socket也称"套接字",用于描述IP和端口,是一个通信链的句柄,应用程序通过"套接字"向网络发出请求或应答网络请求. Socket起 ...

  10. Saltstack批量编译部署nginx(多模块)

    最近一直在研究saltstack的同步文件和批量执行命令,随着架构的变大,批量部署的需求也变得明显起来了,我需要用一条命令就部署好nginx和tomcat,并且符合我所有的环境需求,可以直接投入生产环 ...