这几天一直在想,cocos2d-x跨平台这么牛X,为什么没有人用cocos2d-x来作PC的端游呢,如果用cocos2d-x作2D的端游,那岂不是windows,linux,Mac,ios,android全平台通吃了。当然了,这只是cocos2d-x,但是如果我们使用的是cocos3d那岂不是,一个游戏引擎,可以在任何平台上运行,所有平台通吃。并且是2D游戏,3D游戏都通吃的游戏引擎,而且还使用的是GPU渲染的游戏,而且游戏运行的性能大家就可想而知了。
2.然后,我要说一下游戏使用的图形渲染引擎,cocos2d-x使用的是OpenGL ES,之所以使用从OpenGL裁剪的OpenGL ES是因为手机端使用完全的OpenGL性能有问题,但让我们高兴的是OpenGL ES的代码可以完全运行与OpenGL显卡。而且性能不比手机的GPU差。还有一个更好的消息就是OpenGL和OpenGL ES的协议正在被OpenGL组织设法合并为一个协议。
3.支持windows系统的显卡硬件提供商因为受到微软的软件协议管控,不能自行开发性能更高的显示硬件,所以一般显卡的生产商都会全力支持OpenGL协议,以显示他们新硬件的性能。所以,几乎所有可以跑windows系统的显卡都可以找到OpenGL驱动。换句话说,就是windwos,linux,mac都支持OpenGL硬件协议。
下边是对cocos2d-x引擎全屏显示的一些修改。linux和Mac应该也会很方便。因为你可以看到cocos2dx的cocos2dx\platform目录下有很多操作系统相关的文件夹。如下图:
1.cocos2dx\platform\win32目录下的CCEGLView.cpp文件中的"bool CCEGLView::initGL()"前边加入以下代码:
HWND hDesk; RECT rc; hDesk = GetDesktopWindow(); GetWindowRect( hDesk, &rc ); SetWindowLong( m_hWnd, GWL_STYLE, WS_BORDER ); SetWindowPos( m_hWnd, HWND_TOPMOST,0,0, rc.right, rc.bottom,SWP_SHOWWINDOW);
ShowWindow(hDesk,SW_SHOWMAXIMIZED);
加入后的样子如下图:(记得改完了,要再把cocos2dlib项目再编译一下)
2.再修改你自已的cocos2d-x项目中的main.cpp:
把原来代码中的
eglView->setFrameSize(480, 320);
改成下边代码
RECT rcWindow; HWND xxtmp = eglView->getHWnd(); GetWindowRect(xxtmp,&rcWindow); int w = (int)rcWindow.right; int h = (int)rcWindow.bottom; eglView->setFrameSize(w, h);
改过之后的效果如下图:
3.第三个要改地方是为了让我们的项目能动自适应显示器的分辨率而没有黑边。要改的地方是在我们的AppDelegate.cpp中修改方法AppDelegate::applicationDidFinishLaunching()加入设置EGLView显示方式的代码。如下图
pEGLView->setDesignResolutionSize(480,320, kResolutionExactFit);
kResolutionExactFit:这个参数表示自动拉申以适合屏幕大小。
还有几个别的参数,这里就不写了,有要了解的,大家去网上搜,一搜一大把。
好了,这样设置完之后,我们的cocos2d-x游戏项目就在windows系统下变成像端游一样的全屏显示了。接下来的事情就要看大家的主观能动性和想象力了。
有兴趣的,可以进我建的QQ群:213571088
//================================
Cocos2d-x win32 版本,其中的HelloWorld演示项目的CPU占用率一直很高,有时候高达100%,所以在一番排查后,发现是由于在主循环里使用了 Sleep(0),它位于 cocos2dx\platform\win32\CCApplication.cpp,大致长像如下:
1
2
3
4
5
6
7
|
while
( 1 ) {
if
( 有消息 ) {
if
( 时间到 ) 更新计时, call 主循环函数;
else
Sleep(0);
}
}
|
也就是说,该循环除了执行 mainLoop 以外,花了大量时间在检查消息和 Sleep(0) 上面。
并且,我还发现一个奇怪的现象(暂时还不清楚是为什么),即:
HelloCPP 项目的 AppDelegate.cpp 文件中有一行代码:
1
2
|
pDirector->setAnimationInterval(1.0 / 60);
|
上面的 60 ,如果改大,不起任何作用,帧速始终是 60 不会变。但如果改到小于60,是可以起作用的。
于是,解决 CPU 占用的思路,始于 “是否可以降低循环精度” 的念头。
已知正常情况下,执行 Sleep(1) ,会睡大概 1/50 秒,这个时间并不精确也不准确,看上去无法满足 60 fps 这个流畅度需求。不过,如果游戏运行帧速不需要这么高,比如 30 fps,则该方案大为可行。
经实际测试,将 Sleep(0) 改成 Sleep(1), 再将上面代码中的 60 改成 25, 效果非常显著。但另一个问题来了:如果每游戏循环做的事有点多,时间有点长,那么游戏将被拖慢。
原engine中,同步时间的代码如下:
1
2
3
|
QueryPerformanceCounter(&nNow);
if
(nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart) {
nLast.QuadPart = nNow.QuadPart;
|
因为每次在 nLast 中记录 nNow 时间,并用时间差与设定间隔作比较,时间差往往会比设定间隔要大,如果是在不精确的 Sleep(1) 以及每循环负担比较大的情况下,将导致每帧实际所花的时间,会超出设定间隔不少,从而拖慢游戏速度(如果游戏按帧步进计时的话)。
为解决这个问题,我用的是时间对齐的方式。其实就是改了一下更新nLast 的表达式:
1
|
nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % m_nAnimationInterval.QuadPart);
|
这样每帧的总消耗时间就相当的恒定了。
至于在保持 60 fps的情况下,也能让 cpu占用率在0%,可以修改 Sleep(1) 的精度。
通过查找资料,发现 Winmm.lib 库中有timeBeginPeriod(1); timeEndPeriod(1); 函数可以用于该目的,令 Sleep(1) 的精度提升到1毫秒级别,遂动手改之:
1. 添加 Winmm.lib 库的引用。我在这里采取了在 CCApplication.cpp 头部添加 #pragma comment(lib, "Winmm.lib") 语句的方式。
2. 在 while(1) 代码段的前后,分别放上 timeBeginPeriod(1); timeEndPeriod(1); 语句
这样基本就搞定了。
//================================
网上搜到下面的参考资料,但可能因为Cocos2d-x版本不同,已经不好按这种方式修改了。于是自己想到了解决办法。
参考资料:
http://download.csdn.net/detail/chenzhizs/4813602
其实Win32想弄成全屏不难,两个步骤搞定:1.去掉标题栏;2. 设置为想要的分辨率。
1. 在CCEGLView.cpp的CreateWindowEx中,把WS_CAPTION 这个属性注释掉或删掉,即可没有标题栏。
2. 在main.cpp中设置eglView->setFrameSize(1920, 1080);
这样基本就可以了,应该在各版本中都可以用。
//================================
Cocos2d-x在windows下实现全屏(cocos2d-x+win32+fullScreen)
2013-10-08 23:21
2522人阅读
收藏
举报
本人使用的cocos2dx版本为cocos2d-x_v2.1.5b,之前查到一些解决全屏的办法,但是这些方法对新版本已经不再适用,经过辛苦查询,总算是皇天不负有心人,找到了新版本的解决办法。参考原文:http://www.cocos2d-x.org/forums/6/topics/24432
方法如下:(亲测可行)
1、在目录cocos2dx\platform\win32下找到CCEGLView.h和CCEGLView.cpp,用记事本打开,在CCEGLView.h中添加如下代码
- bool enterFullscreen(int fullscreenWidth=0, int fullscreenHeight=0);
- bool exitFullscreen(int windowX, int windowY, int windowedWidth, int windowedHeight, int windowedPaddingX, int windowedPaddingY);
- int getFullscreenWidth();
- int getFullscreenHeight();
2、在CCEGLView.cpp中添加如下代码
- int CCEGLView::getFullscreenWidth()
- {
- return GetDeviceCaps(m_hDC, HORZRES);
- }
-
- int CCEGLView::getFullscreenHeight()
- {
- return GetDeviceCaps(m_hDC, VERTRES);
- }
-
- bool CCEGLView::enterFullscreen(int fullscreenWidth, int fullscreenHeight)
- {
- DEVMODE fullscreenSettings;
- bool isChangeSuccessful;
-
- if(fullscreenWidth == 0 || fullscreenHeight == 0)
- {
- fullscreenWidth = GetDeviceCaps(m_hDC, HORZRES);
- fullscreenHeight = GetDeviceCaps(m_hDC, VERTRES);
- }
-
- int colourBits = GetDeviceCaps(m_hDC, BITSPIXEL);
- int refreshRate = GetDeviceCaps(m_hDC, VREFRESH);
-
- EnumDisplaySettings(NULL, 0, &fullscreenSettings);
- fullscreenSettings.dmPelsWidth = fullscreenWidth;
- fullscreenSettings.dmPelsHeight = fullscreenHeight;
- fullscreenSettings.dmBitsPerPel = colourBits;
- fullscreenSettings.dmDisplayFrequency = refreshRate;
- fullscreenSettings.dmFields = DM_PELSWIDTH |
- DM_PELSHEIGHT |
- DM_BITSPERPEL |
- DM_DISPLAYFREQUENCY;
-
- SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_TOPMOST);
- SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
- SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, fullscreenWidth, fullscreenHeight, SWP_SHOWWINDOW);
- isChangeSuccessful = ChangeDisplaySettings(&fullscreenSettings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL;
- ShowWindow(m_hWnd, SW_MAXIMIZE);
-
- resize(fullscreenWidth, fullscreenHeight);
-
- return isChangeSuccessful;
- }
-
- bool CCEGLView::exitFullscreen(int windowX, int windowY, int windowedWidth, int windowedHeight, int windowedPaddingX, int windowedPaddingY)
- {
- bool isChangeSuccessful;
-
- SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, WS_EX_LEFT);
- SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
- isChangeSuccessful = ChangeDisplaySettings(NULL, CDS_RESET) == DISP_CHANGE_SUCCESSFUL;
- SetWindowPos(m_hWnd, HWND_NOTOPMOST, windowX, windowY, windowedWidth + windowedPaddingX, windowedHeight + windowedPaddingY, SWP_SHOWWINDOW);
- ShowWindow(m_hWnd, SW_RESTORE);
-
- return isChangeSuccessful;
- }
3、如何使用
在main.cpp中添加
-
- AppDelegate app;
- CCEGLView* eglView = CCEGLView::sharedOpenGLView();
-
-
- //eglView->setFrameSize(eglView->getFullscreenWidth(), eglView->getFullscreenHeight());
-
- eglView->enterFullscreen(0, 0);
-
- int ret = CCApplication::sharedApplication()->run();
这样就能够实现全屏了!
//================================
这个问题我解决了 确实很简单 showCursor(False) 就可以隐藏当前的鼠标,如果要自定义鼠标格式就自己做个精灵,然后再鼠标移动事件里面移动即可。 但是要主要鼠标事件 里面获取的坐标不是 游戏里面的坐标。而是以windows 标准 的坐标。 所以需要转化一下。
//============================
某些时候,我们可能需要把pc上面的Flash动画拿到Cocos2d-x上面使用。
解决方案:
第一:
若你的.fla源文件中不带有骨骼动画,则你可以使用TexturePacker结合AnimatePacker来解决这个问题。
a.把.fla文件导出为.swf
b.把.swf文件直接丢到TexturePacker中,它会自动帮你解析出所有的帧,并导出为.plist文件,它附带一张.png图
c.把.plist文件丢到AnimatePacker中,它也会自动帮你解析出所有的帧,然后根据需要,制作你动画,AnimatePacker不知道怎么使用的,可以看我前面的文章。
这样你的Falsh动画就能转移到Cocos2d-x使用了。
这种方案在b这个步骤的时候经常会遇到一个问题,就是你丢进去的.swf文件只能帮你解析出来一帧,接下来我们来分析这种情况。
出现这种情况的原因:大部分的Flash动画都是比较复杂的,它包含了多套的动画方案,而且它们一般都不是设计在主场景中的,而是绑定在各个元件中的,主场景中只是丢了一张图片。这样就带来了问题了,因为TexturePacker只会解析你主场景中的帧动画,所以,你就只解析到了一张图片。
那这个问题我们要怎么解决呢?跟TexturePacker的作者商量一下吧。能不能把元件中的帧动画也解析了呢。或许以后可以,但是至少目前是不行的。所以,我们能做的就是如下:
a.在Flash cs6中文件->新建->ActionScript 3.0,新建一个.fla文件,假设我们命名为new.fla
b.选中原.fla文件中元件里面绑定的帧动画,右键复制帧,黏贴到new.fla的主场景中,你可以把所有元件中的动画都黏贴到new.fla中,这不会影响我们之后的读取。都完成之后,右键另存为new.swf。
c.然后把new.swf文件丢到TexturePacker中,怎么样,是不是所有帧都出来了?而且一样的帧TexturePacker还会自动帮你合并到一起,可以减少生成的.png图片大小。导出为.plist文件,附带一张.png图。
d.把.plist文件丢到AnimatePacker中,它也会自动帮你解析出所有的帧,然后根据需要,制作你动画。
这种方案或许比较繁琐,但是是目前我能实现的不带骨骼动画的.fla文件的移植到Cocos2d-x中使用的方法。接下来介绍一下带骨骼动画的.fla文件又是如何导出为Cocos2d-x可以使用的文件
第二:
第二个方案我们是要使用到的一个工具叫Flash2Cocos2d-x,至于安装方面问题,也可以看看我前面的文章。
当我们的.fla文件中不带骨骼数据的时候,我们使用的上面的方案。我也尝试使用Flash2Cocos2d-x来导出,但是在Import选项上面时,第一个和第二个都没有反映,第三个提示不包含骨骼数据,或许这个工具只能用来导出骨骼动画吧!
所以,你也可以把这个方案当作Flash2Cocos2d-x的一点资料吧。
大体步骤如下:
打开.fla文件,窗口->其他面板->SkeletonSWFPanel,打开面板,点击import(默认为All library items),若你有封装了骨骼信息的.swf文件,也可以选择第三项。waiting......然后所有的骨骼信息就都出来了。
至于具体的这个工具怎么做骨骼动画,可以参考作者的文章。
然后Export导出文件,
这边有4个选项,第一个会直接导出一张封装了骨骼信息的PNG图片,第二个导出带有骨骼信息的swf动画,第三个暂时不明白,第四个导出许多单张的PNG图片和XML文件。据论坛上面使用过这个工具的朋友说(这个方案本人没在Cocos2d-x中引用过),一般都是使用第四个选项,然后再使用TexturePacker工具,把所有的单张图片生成图片集.plist文件,这样需要放入到Cocos2d-x 资源文件夹中的文件就有.png .plist .xml 3个文件,跟第一种方案最后是一样的。但是它们在Cocos2d-x中引用需要使用不同的类库(关于类库在cocos2d-x2.0.4中报错的问题,应该改一下类的路径就可以了)。这边需要用到的类库就是在下载的工具里面的Flash2Cocos2d-X子文件夹中的类(大概有40+,是不是全部需要用到,我没实践过)。
最后在代码方面的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
// step 1: add your skeleton xml file //CCConnectionData::sharedConnectionData()->addData("knight.xml"); CCConnectionData::sharedConnectionData()->addData("zombie.xml");
// step2: add plist and png to cache CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("zombie.plist", "zombie.png");
// step 3: create a CCSpriteBatchNode //CCSpriteBatchNode *batchNode = CCSpriteBatchNode::create("knight.png"); CCSpriteBatchNode *batchNode = CCSpriteBatchNode::create( "zombie.png" );
// step 4: create a armature just need armature name, plist, picture, and a CCSpriteBatchNode // armature = CCArmature::create("Knight_f/Knight", "Knight_f/Knight", "knight.plist", "knight.png", batchNode); armature = CCArmature::create("Zombie_f/Zombie", "Zombie_f/Zombie", batchNode);
armature->getDisplay()->setPosition(ccp(size.width/2, size.height/2)); armature->getDisplay()->setScale( 1 );
// step 5: play the animation armature->getAnimation()->playTo("stand");
|
这个工具对于骨骼动画的支持还是挺好的,很期待作者继续更新。
当然我们也可以使用CocosBuilder来做骨骼动画,在CocosBuilder做骨骼动画的时候,遇到了一个骨骼动画和Cocos2d-x里面的action结合出现action只运行固定时间的异常,比如我action设置的是2s,但是它只运行0.5s就停止了,至于这个问题是什么导致的,暂时还没解决,以后解决了会在我的博客上面补上。如果有哪位朋友懂的,麻烦指导一下!
总结一下:
第一:PC上面的不带骨骼动画的.fla文件我们导出为.swf文件后,结合TexturePacker和AnimatePacker来开发
第二:带骨骼动画的.fla文件或者是分装了骨骼信息的.png和.swf文件,我们可以使用Flash2Cocos2d-x结合TexturePacker来开发。
第三:制作骨骼动画可以使用Flash2Cocos2d-x,也可以使用Cocosbuilder来制作,关于使用Cocosbuilder如何制作骨骼动画,可以看我前面的博客。
原文链接:
http://momowing.diandian.com/post/2012-11-22/40042074075