[Cocos2d-x相关教程来源于红孩儿的游戏编程之路 CSDN博客地址:http://blog.csdn.net/honghaier]
红孩儿Cocos2d-X学习园地QQ群:249941957加群写:Cocos2d-x
谈一谈Cocos2d-x中的某些“大小”
首先感谢各位的大力支持,让本博主的博客排名坐上火箭,一路向前。吾与所有Cocos2d-x的学习者同在~
又是一个孤独的周末,应各位同学的要求,把Cocos2d-x的cocos2d-2.0-x-2.0.2版本下载下来。继续用自已的VS2005方案打开,大概看了一下目录。嗯,改动还是挺多的。首先,最明显的是HelloWorld改名为了HelloCpp,其次加入了Javascript脚本支持,以及增加了Shader支持。感觉Cocos2d-x的更新速度算挺快了,而且比较紧跟现在游戏研发的方向。对于使用过Unity3d或长期进行图形引擎开发的程序来说,新增的两个节目应该还是比较对胃口的。最近Cocos2D-HTML5也发布了Alpha版,不错,学Cocos2d-x真是大有前途啊。
好了,话归正转,本章的标题起的怪一点,其实我只是在重新学习2.0版本时看到一些东西,感觉对于初学者来说非常容易迷糊,正好写篇博文Mark一下,留得日后备查。
这里说的“大小”,包括了以下一些内容:
(1).窗口的大小
(2).分辨率的大小
(3).影幕的大小
(4).视口的大小
(5).裁剪区域的大小
我们先来看(1),窗口的大小
窗口的大小,即是Windows窗体大小。我们以HelloCpp为例,打开main.cpp,。找到这两句代码:
- <spanstyle="font-family:SimSun;font-size:14px;">CCEGLView*eglView=CCEGLView::sharedOpenGLView();
- eglView->setFrameSize(960,640);</span>
这里取得了Opengl视窗类CCEGLView单件实例指针返回给指针变量eglView,并调用其setFrameSize函数设置一个所谓的Frame大小。这个大小是神马东西?进去看看!
进入到CCEGLView.cpp的相应函数:
- <spanstyle="font-size:14px;">voidCCEGLView::setFrameSize(floatwidth,floatheight)
- {
- Create((LPCTSTR)m_szViewName,(int)width,(int)height);
- CCEGLViewProtocol::setFrameSize(width,height);
- }</span>
看一下Create函数:
- <spanstyle="font-size:14px;">boolCCEGLView::Create(LPCTSTRpTitle,intw,inth)
- {
- boolbRet=false;
- do
- {
- CC_BREAK_IF(m_hWnd);
- HINSTANCEhInstance=GetModuleHandle(NULL);
- WNDCLASSwc;
- wc.style=CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
- wc.lpfnWndProc=_WindowProc;
- wc.cbClsExtra=0;
- wc.cbWndExtra=0;
- wc.hInstance=hInstance;
- wc.hIcon=LoadIcon(NULL,IDI_WINLOGO);
- wc.hCursor=LoadCursor(NULL,IDC_ARROW);
- wc.hbrBackground=NULL;
- wc.lpszMenuName=NULL;
- wc.lpszClassName=kWindowClassName;
- CC_BREAK_IF(!RegisterClass(&wc)&&1410!=GetLastError());
- RECTrcDesktop;
- GetWindowRect(GetDesktopWindow(),&rcDesktop);
- WCHARwszBuf[50]={0};
- MultiByteToWideChar(CP_UTF8,m_szViewName,-1,wszBuf,sizeof(wszBuf));
- m_hWnd=CreateWindowEx(
- WS_EX_APPWINDOW|WS_EX_WINDOWEDGE,
- kWindowClassName,
- wszBuf,
- WS_CAPTION|WS_POPUPWINDOW|WS_MINIMIZEBOX,
- 0,
- 0,
- 0,
- NULL,
- NULL,
- hInstance,
- NULL);
- CC_BREAK_IF(!m_hWnd);
- resize(w,h);
- bRet=initGL();
- CC_BREAK_IF(!bRet);
- s_pMainWindow=this;
- bRet=true;
- }while(0);
- returnbRet;
- }</span>
创建窗口时并没有用到w和h,所以只有继续看重点函数才能知道窗口大小是怎么设置的。
- <spanstyle="font-size:14px;">voidCCEGLView::resize(intwidth,intheight)
- {
- if(!m_hWnd)
- {
- return;
- }
- RECTrcClient;
- GetClientRect(m_hWnd,&rcClient);
- if(rcClient.right-rcClient.left==width&&
- rcClient.bottom-rcClient.top==height)
- {
- return;
- }
- rcClient.right=rcClient.left+width;
- rcClient.bottom=rcClient.top+height;
- 指定的客户区大小rcClient和窗口样式来自动调整,确保了客户区就是rcClient指定大小。其中GetWindowLong用来获取当前窗口的
- 样式,GWL_STYLE为基本样式信息,GWL_EXSTYLE为扩展栏式信息。返回窗口的整体大小再传给rcClient。
- AdjustWindowRectEx(&rcClient,GetWindowLong(m_hWnd,GWL_STYLE),false,
- GetWindowLong(m_hWnd,GWL_EXSTYLE));
- SetWindowPos(m_hWnd,rcClient.right-rcClient.left,
- rcClient.bottom-rcClient.top,SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOOWNERZORDER
- |SWP_NOZORDER);
- }
- </span>
好了,我们看,窗口的大小就是这么设置的。作者考虑到了不同的样式窗口对于客户区大小的影响,故做了相应的处理。所以我们创建指定大小的窗口时其实真正的意思是创建一个指定客户区大小的窗口。
我们再来看 (2),分辨率的大小和 (3),影幕的大小 (4),视口的大小
分辨率:即是屏幕上图像的精细度,在Cocos2d-x中其大小为屏幕在横向和纵向可以容纳的逻辑点数量,为了好理解,我们把它想像成投影机的分辨率。
影幕:想想小时候看电影时用到的那块白布吧,当然也许公司会议室里也能看到它。也就是投影机用来投射画面的画布。
视口:其实就是上面说的投影机投影出来的影片画面所占的矩形。它如果大于影幕的大小,那么你就不能看到完整的影片画面。如果小于影幕的大小。你就可以在它显示的区域里看到影片画面。
我们现在看一下刚才略过的代码:CCEGLViewProtocol::setFrameSize(width,height);
进入CCEGLViewProtocol.cpp中相应函数定义:
- <spanstyle="font-size:14px;">voidCCEGLViewProtocol::setFrameSize(floatwidth,floatheight)
- {
- m_obDesignResolutionSize=m_obScreenSize=CCSizeMake(width,height);
- }
- </span>
双击“m_obDesignResolutionSize”,按下Ctrl+F,在弹出查找对话框里对当前文档CCEGLViewProtocol.cpp中查找全部使用。
点击第一个查找结果,看一下所在函数setDesignResolutionSize,这个函数是用来设置分辨率大小的。前两个参数无疑就是设置分辨率横向纵向的像素数量的。最后一个参数resolutionPolicy我们必须了解一下,进入ResolutionPolicy的定义:
- enumResolutionPolicy
- {
- kResolutionExactFit,
- 画布上所对应的相应方向上与最低值一致。
- kResolutionNoBorder
- 矩形在画布上所对应的相应方向上与最高值一致。同时这个矩形的另一个方向按最低值进行裁剪,区域外部分填充黑色。
- kResolutionShowAll,
- kResolutionUnKnown,
- };
这个枚举归结为“分辨率模式”。是不是有点迷糊,得,我们在继续下面的函数之前,先以例子来说明一下:
打开HelloLua工程的AppDelegate.cpp,看一下这个函数:
- <spanstyle="font-size:14px;">boolAppDelegate::applicationDidFinishLaunching()
- {
- CCDirector*pDirector=CCDirector::sharedDirector();
- pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());
- CCEGLView::sharedOpenGLView()->setDesignResolutionSize(480,320,kResolutionShowAll);
- pDirector->setDisplayStats(true);
- pDirector->setAnimationInterval(1.0/60);
- CCScriptEngineProtocol*pEngine=CCLuaEngine::engine();
- CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine);
- #if(CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)
- CCString*pstrFileContent=CCString::createWithContentsOfFile("hello.lua");
- if(pstrFileContent)
- {
- pEngine->executeString(pstrFileContent->getCString());
- }
- #else
- std::stringpath=CCFileUtils::sharedFileUtils()->fullPathFromRelativePath("hello.lua");
- pEngine->addSearchPath(path.substr(0,path.find_last_of("/")).c_str());
- pEngine->executeScriptFile(path.c_str());
- #endif
- returntrue;
- }
- </span>
我们要干点坏事,好吧。我们尝试着将其分别改为
- CCEGLView::sharedOpenGLView()->setDesignResolutionSize(80,kResolutionExactFit);
- CCEGLView::sharedOpenGLView()->setDesignResolutionSize(80,kResolutionNoBorder);
- CCEGLView::sharedOpenGLView()->setDesignResolutionSize(80,kResolutionShowAll);
并进行测试。下面是测试图。
好好理解一下。
再回来看setDesignResolutionSize函数:
- voidCCEGLViewProtocol::setDesignResolutionSize(floatwidth,floatheight,ResolutionPolicyresolutionPolicy)
- {
- CCAssert(m_bIsRetinaEnabled==false,"cannotenableretinawhilesetdesignresolutionsize!");
- CCAssert(resolutionPolicy!=kResolutionUnKnown,"shouldsetresolutionPolicy");
- if(width==0.0f||height==0.0f)
- {
- return;
- }
- m_obDesignResolutionSize.setSize(width,height);
- m_fScaleX=(float)m_obScreenSize.width/m_obDesignResolutionSize.width;
- m_fScaleY=(float)m_obScreenSize.height/m_obDesignResolutionSize.height;
- if(resolutionPolicy==kResolutionNoBorder)
- {
- m_fScaleX=m_fScaleY=MAX(m_fScaleX,m_fScaleY);
- }
- if(resolutionPolicy==kResolutionShowAll)
- {
- m_fScaleX=m_fScaleY=MIN(m_fScaleX,m_fScaleY);
- }
- floatviewPortW=m_obDesignResolutionSize.width*m_fScaleX;
- floatviewPortH=m_obDesignResolutionSize.height*m_fScaleY;
- m_obViewPortRect.setRect((m_obScreenSize.width-viewPortW)/2,(m_obScreenSize.height-viewPortH)/2,viewPortW,viewPortH);
- m_eResolutionPolicy=resolutionPolicy;
- CCDirector::sharedDirector()->createStatsLabel();
- CCDirector::sharedDirector()->m_obWinSizeInPoints=CCDirector::sharedDirector()->m_obWinSizeInPixels=getSize();
- CCDirector::sharedDirector()->setGLDefaultValues();
- }
现在大家明白我为什么将(2),(3),(4)并在一起说了。它们其实是有机结合的。相辅相成,缺一不可。
我们最后来看一下:(5),裁剪区域的大小:
裁剪区域:如果对Opengl显示窗口设定裁剪区域,则裁剪区域外的像素将不会显示。
我们仍然在HelloLua工程中进行说明:
在函数AppDelegate::applicationDidFinishLaunching()中我们在
- CCEGLViewProtocol*tpCCEGLView=(CCEGLViewProtocol*)CCEGLView::sharedOpenGLView();
- CCEGLView::sharedOpenGLView()->setDesignResolutionSize(80,kResolutionShowAll);
后面增加代码:
- tpCCEGLView->setScissorInPoints(100,100,100);
- glEnable(GL_SCISSOR_TEST);
运行测试:
可以看到,我们对画面进行了裁剪。从屏幕100,100位置起的大小为宽100,高100的区域被设为了裁剪显示区域,其它部分均被裁切掉了。
好了,以上这些个“大小”的基础知识,也颇让我费了些脑子去想该怎么讲出来。希望本节课目不会令大家失望。 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|