这里说的“大小”,包括了以下一些内容:
(1).窗口的大小
(2).分辨率的大小
(3).影幕的大小
(4).视口的大小
(5).裁剪区域的大小
我们先来看(1),窗口的大小
窗口的大小,即是Windows窗体大小。我们以HelloCpp为例,打开main.cpp,。找到这两句代码:
- <SPAN style="FONT-FAMILY: SimSun; FONT-SIZE: 14px">CCEGLView* eglView = CCEGLView::sharedOpenGLView();
- eglView->setFrameSize(960, 640 );</SPAN>
这里取得了Opengl视窗类CCEGLView单件实例指针返回给指针变量eglView,并调用其setFrameSize函数设置一个所谓的Frame大小。这个大小是神马东西?进去看看!
进入到CCEGLView.cpp的相应函数:
- <SPAN style="FONT-SIZE: 14px">void CCEGLView::setFrameSize(float width, float height)
- {
- Create((LPCTSTR)m_szViewName, (int)width, (int)height);
- CCEGLViewProtocol::setFrameSize(width, height);
- }</SPAN>
看一下Create函数:
- <SPAN style="FONT-SIZE: 14px">bool CCEGLView::Create(LPCTSTR pTitle, int w, int h)
- {
- bool bRet = false;
- do
- {
- CC_BREAK_IF(m_hWnd);
- HINSTANCE hInstance = GetModuleHandle( NULL );
- WNDCLASS wc;
-
- 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());
-
- RECT rcDesktop;
- GetWindowRect(GetDesktopWindow(), &rcDesktop);
- WCHAR wszBuf[50] = {0};
- MultiByteToWideChar(CP_UTF8, 0, 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,
- 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);
- return bRet;
- }</SPAN>
创建窗口时并没有用到w和h,所以只有继续看重点函数才能知道窗口大小是怎么设置的。
- <SPAN style="FONT-SIZE: 14px">void CCEGLView::resize(int width, int height)
- {
- if (! m_hWnd)
- {
- return;
- }
-
- RECT rcClient;
- 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, 0, 0, 0, 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中相应函数定义:
- <SPAN style="FONT-SIZE: 14px">void CCEGLViewProtocol::setFrameSize(float width, float height)
- {
- m_obDesignResolutionSize = m_obScreenSize = CCSizeMake(width, height);
- }
- </SPAN>
双击“m_obDesignResolutionSize”,按下Ctrl+F,在弹出查找对话框里对当前文档CCEGLViewProtocol.cpp中查找全部使用。
点击第一个查找结果,看一下所在函数setDesignResolutionSize,这个函数是用来设置分辨率大小的。前两个参数无疑就是设置分辨率横向纵向的像素数量的。最后一个参数resolutionPolicy我们必须了解一下,进入ResolutionPolicy的定义:
- enum ResolutionPolicy
- {
- kResolutionExactFit,
- 画布上所对应的相应方向上与最低值一致。
- kResolutionNoBorder
- 矩形在画布上所对应的相应方向上与最高值一致。同时这个矩形的另一个方向按最低值进行裁剪,区域外部分填充黑色。
- kResolutionShowAll,
- kResolutionUnKnown,
- };
这个枚举归结为“分辨率模式”。是不是有点迷糊,得,我们在继续下面的函数之前,先以例子来说明一下:
打开HelloLua工程的AppDelegate.cpp,看一下这个函数:
- <SPAN style="FONT-SIZE: 14px">bool AppDelegate::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::string path = CCFileUtils::sharedFileUtils()->fullPathFromRelativePath("hello.lua");
- pEngine->addSearchPath(path.substr(0, path.find_last_of("/")).c_str());
- pEngine->executeScriptFile(path.c_str());
- #endif
-
- return true;
- }
- </SPAN>
我们要干点坏事,好吧。我们尝试着将其分别改为
- CCEGLView::sharedOpenGLView()->setDesignResolutionSize(80, 320, kResolutionExactFit);
- CCEGLView::sharedOpenGLView()->setDesignResolutionSize(80, 320, kResolutionNoBorder);
- CCEGLView::sharedOpenGLView()->setDesignResolutionSize(80, 320, kResolutionShowAll);
并进行测试。下面是测试图。 好好理解一下。
再回来看setDesignResolutionSize函数:
- void CCEGLViewProtocol::setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy)
- {
- CCAssert(m_bIsRetinaEnabled == false, "can not enable retina while set design resolution size!");
- CCAssert(resolutionPolicy != kResolutionUnKnown, "should set resolutionPolicy");
- 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);
- }
-
- float viewPortW = m_obDesignResolutionSize.width * m_fScaleX;
- float viewPortH = 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, 320, kResolutionShowAll);
后面增加代码:
- tpCCEGLView->setScissorInPoints(100,100,100,100);
- glEnable(GL_SCISSOR_TEST);
运行测试:
可以看到,我们对画面进行了裁剪。从屏幕100,100位置起的大小为宽100,高100的区域被设为了裁剪显示区域,其它部分均被裁切掉了。
本文转蓬莱仙羽51CTO博客,原文链接:http://blog.51cto.com/dingxiaowei/1366387,如需转载请自行联系原作者