zoukankan      html  css  js  c++  java
  • cocos2d-x屏幕分辨率,窗口大小总结

    这个东西很烦人,相信很多人都不理解

    今天来总结一下,首先有很多概念都要事先弄得清楚明白

    1.屏幕分辨率

    所谓屏幕分辨率相信很多人都知道他的概念,不就是1280pxX720PX吗?不就是这种形式吗?有什么难的,这几个词在各种手机评测上面不是已经用烂了吗?

    可是很多人都没有真正理解这个概念!!!

    1280pxX720px

    它的意思是纵向1280个像素,横向720个像素。

    记住!只是像素而已,和尺寸,和大小,和比例没有半毛钱的直接关系

    我一直都以为为什么这个东西要叫做屏幕分辨率,为什么要叫做分辨率?之前一直觉得名不符实,一直以为像素不过是另一种度量单位,深受我们摄影老师的影响,误人子弟,现在想起来,真是naive!

    记住,像素不是一种新的,类似cm,mm的单位,像素并不是一种计量长度的单位,至于他究竟是什么,对不起,无可奉告,自己看百度百科

    可以知道的是:像素越密,清晰度越高

    2.屏幕分辨率和屏幕尺寸

      先说说屏幕尺寸,这东西,才是我们直观感受到的东西,什么屏幕的大小啊,屏幕的尺寸啊,屏幕的比例啊,一切的一切都落在这个屏幕尺寸上,

      接下来就是干货了

      1.相同比例和大小的尺寸,屏幕上的像素分辨率越高,屏幕,越清晰!!!(这个足可以证明尺寸,大小和分辨率无关吧)

      2.同样的屏幕分辨率(比如1280pxX720px),用在不同的屏幕上,我们看到的效果天差地别!!!

      接下来进入正题!在游戏中是怎么做的!!

      接触过各种引擎或者直接做游戏的人应该都知道,在游戏中我们做游戏都是以像素作为单位的,比如,一张精灵的图片,100pxX30px,怎样处理呢?

      在windows平台是这样的,因为windows平台是窗口式程序,一个游戏程序可以设置它的窗口大小,也就是说,他的屏幕尺寸并不是固定的!!

      这个时候是分为两部分处理的:

          1.设置窗口的大小:长宽;这一步相当于人为地规定了屏幕的尺寸(以像素的形式)

          2.设置设计尺寸:根据各种手段,使精灵图片适配窗口的大小

      而在移动端,包括安卓端和苹果端:因为并不是窗口式的OS,事实上就那么点屏幕,也做不了窗口式的OS,所以屏幕并不可更改所以只有一个步骤:

          设置设计尺寸:根据各种手段,使屏幕适配窗口的大小

    好,解决方案就是以上两种思想,我来仔细解释一下,我们知道,因为各种电脑,各种手机,尺寸都不一样,分辨率也他妈不一样,这对于开发者来说是一个很复杂的问题,你想想,不同的尺寸,市面上真是数不胜数,我们怎么办呢?

    好,开发者决定以像素为单位,进行开发,这个方法不错,毕竟各种图片,纹理,都是以像素为单位的

    ,可是相同的像素大小,也就是相同的分辨率,在不同平台上的尺寸都不一样,比如说,同样是960pxX720px,在这个手机上也许尺寸更大一些,那个手机上,也许尺寸更小一些?我们怎么紧紧跟随尺寸呢?毕竟,尺寸和分辨率是两回事啊!!

    这个任务实际上是交给手机厂商的!!怎么样?是不是有一种很爽的感觉!!,这就是产业链啊!!!以前总在知乎上看他们辩论产业链优势,现在终于体会到了,对于厂商来说,分辨率就是写上去的事儿,很简单,可是解决了我们一个大麻烦,这样,对于我们来说,从手机设备厂商上获得的分辨率,就是尺寸啊!!!!  他在逻辑上并不是尺寸,但是这并不妨碍我们把他当作尺寸来看待!!!!

    好了,有了以上的解释,

      对于PC端:第一步设置窗口大小的时候,实际上可以认为我们是在认为设置安卓手机的大小尺寸,怎么样,是不是有一种很吊的感觉!!!模仿手机端,我们是以像素来代替尺寸

      第二步的处理接下来在手机端一起讲

      对于安卓端:

          第一步对于安卓端来说不用考虑。

          第二步:获得固定的尺寸分辨率(自己发明的:即可以代表尺寸的分辨率):这一步对于开发者来说是透明的,也就是说,开发者这一步并不知道 具体的分辨率是多少,系统会自动给与

          记作ScreenX和ScreenY

          开发者自定义一个尺寸,我们称之为设计尺寸,仍然以像素为单位,记作designX和designY

          scaleX=ScreenX/designX

          scaleY=ScreenY/designY

          然后就选择适配方式:

            有铺满屏幕:那就用scaleXxdesignX,scaleYXdesignY来获得实际的尺寸,注意在这个过程中,场景中的精灵等等都这样变换,也就是说,游戏场景可能会变形得比较厉害

            有保持比例而且不超出屏幕:也就是保持比例不变形且不对素材进行裁剪:实现的时候是对选择scaleX和scaleY中较小的一个作为缩放因子,对designX和designY进行缩放

            有保持比例而且不留空白:也就是保持比例不变形,且充分利用屏幕的每个空间:实现的时候是对选择scaleX和scaleY中较大的一个作为缩放因子,对designX和designY进行缩放

            有保持比例且按照宽度铺满屏幕:也就是保持比例不变形,且让宽度刚好铺满屏幕,实现的时候用scaleX作为缩放因子,对designX和designY进行缩放

            有保持比例且按照高度度铺满屏幕:也就是保持比例不变形,且让宽度刚好铺满屏幕,实现的时候用scaleY作为缩放因子,对designX和designY进行缩放

    总结一下,后四种其实是一种类似的思想,

    终于把理论部分说完了,感觉上面讲完了,cocos2d-x里面的也没有什么讲的了,cocos里面的思想和这个就是一样的,

    直接上函数

    glview->setDesignResolutionSize(720,1280,ResolutionPolicy::SHOW_ALL);
    

      这个函数其实就是第二步骤的完整函数,这个前一部分指定我们设计游戏的时候用的尺寸分辨率,然后后面的就是适配风格了

    怎么实现这种适配风格可以看看源码

    void GLView::setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy)
    {
        CCASSERT(resolutionPolicy != ResolutionPolicy::UNKNOWN, "should set resolutionPolicy");
        
        if (width == 0.0f || height == 0.0f)
        {
            return;
        }
    
        _designResolutionSize.setSize(width, height);
        _resolutionPolicy = resolutionPolicy;
        
        updateDesignResolutionSize();
     }
    

      这个是setDesignResolutionsize函数,可以看到,通过参数指定了私有成员_designResolutionSize的值,这个就是设计分辨率!!但是注意一下,opengl创建窗口的时候(请原谅我用窗口这个词),并不是以设计尺寸分辨率创建的,

      可以看到,这个函数里只是指定了设计尺寸和适配风格,并没有实现适配风格,可以猜一下,实现应该封装在updateDesignResoltionSize里了,进去看看

    void GLView::updateDesignResolutionSize()
    {
        if (_screenSize.width > 0 && _screenSize.height > 0
            && _designResolutionSize.width > 0 && _designResolutionSize.height > 0)
        {
            _scaleX = (float)_screenSize.width / _designResolutionSize.width;
            _scaleY = (float)_screenSize.height / _designResolutionSize.height;
            
            if (_resolutionPolicy == ResolutionPolicy::NO_BORDER)
            {
                _scaleX = _scaleY = MAX(_scaleX, _scaleY);
            }
            
            else if (_resolutionPolicy == ResolutionPolicy::SHOW_ALL)
            {
                _scaleX = _scaleY = MIN(_scaleX, _scaleY);
            }
            
            else if ( _resolutionPolicy == ResolutionPolicy::FIXED_HEIGHT) {
                _scaleX = _scaleY;
                _designResolutionSize.width = ceilf(_screenSize.width/_scaleX);
            }
            
            else if ( _resolutionPolicy == ResolutionPolicy::FIXED_WIDTH) {
                _scaleY = _scaleX;
                _designResolutionSize.height = ceilf(_screenSize.height/_scaleY);
            }
            
            // calculate the rect of viewport
            float viewPortW = _designResolutionSize.width * _scaleX;
            float viewPortH = _designResolutionSize.height * _scaleY;
            
            _viewPortRect.setRect((_screenSize.width - viewPortW) / 2, (_screenSize.height - viewPortH) / 2, viewPortW, viewPortH);
            
            // reset director's member variables to fit visible rect
            auto director = Director::getInstance();
            director->_winSizeInPoints = getDesignResolutionSize();
            director->_isStatusLabelUpdated = true;
            director->setGLDefaultValues();
        }
    }
    

      

     可以看到,这个里面实现了上面讲的那些适配风格的适配方法

    看到这里,我们应该大体能猜到,最终创建的窗口应该是那个叫做_viewPortRect的东西,好了,屏幕适配就写到这里了,今天状态不好,从今天起,决定戒掉小说,OK!

    今天更新一下,主要是最近自己的项目中间出现一个非常麻烦的问题,今天终于解决了,关于触摸响应位置不准确的问题,其实主要是windows平台上设置产生的窗口大小超过了PC的物理尺寸大小!!!

    详细的解释见下面的链接

    触摸位置不准确

  • 相关阅读:
    js实现继承
    简单原型语法和原型动态性
    js中关于原型的几个方法
    js创建对象的几种方式
    收藏的js学习小例子
    结合 WebService 实现消息 主动推送到客户端
    Exceptionless 本地搭建记录
    EF6 SqlServer 简单例子 和 支持的原生sql例子
    Ubuntu下deb文件及tgz文件安装
    Windows 10家庭版远程桌面连接错误
  • 原文地址:https://www.cnblogs.com/YTYMblog/p/6138427.html
Copyright © 2011-2022 走看看