cocos2d-x 和 cocoscreator屏幕适配

【cocos2d-x  v3.x】

c++核心代码:

void GLView::updateDesignResolutionSize()
{
// _screenSize  就是屏幕分辨率 _designResolutionSize  传入的设计分辨率
    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) {
            // 固定高度 取 height的比值 重新计算 设计分辨率的宽度 
            _scaleX = _scaleY;
            _designResolutionSize.width = ceilf(_screenSize.width/_scaleX);
        }
        
        else if ( _resolutionPolicy == ResolutionPolicy::FIXED_WIDTH) {
             // 固定宽度 取 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->setProjection(director->getProjection());

        glViewport(0, 0, _screenSize.width, _screenSize.height);
    }
}

总结:

frameSize ======> 设备实际分辨率(1280*720 ,2340*1080),实际的屏幕大小。( 可以根据这个尺寸选择适配方式 )

 

CCSize winSize = CCDirector::sharedDirector()->getWinSize(); 
const Size& Director::getWinSize(void) const
{
    return _winSizeInPoints;
}
_winSizeInPoints = _openGLView->getDesignResolutionSize();

 

winSize =======>  显示窗口分辨率, 是通过计算后的设计分辨率,(UI元素的显示逻辑 根据这个分辨率适配)

visibleSize 任何情况下 visibleSize == WinSize

_viewPortRect:视图viewPort,这个分辨率与最终的_designResolutionSize成比例       

float viewPortW = _designResolutionSize.width * _scaleX;  
float viewPortH = _designResolutionSize.height * _scaleY;

【cocoscreator 2.x】(跟2dx的逻辑基本一致)

1、CCCanvas.js

//修改canvas size个pos

    alignWithScreen: function () {
        var designSize, nodeSize;
        if (CC_EDITOR) {
            nodeSize = designSize = cc.engine.getDesignResolutionSize();
            this.node.setPosition(designSize.width * 0.5, designSize.height * 0.5);
        }
        else {
            //这里取得最终的visibleRect
            var canvasSize = nodeSize = cc.visibleRect;
            designSize = cc.view.getDesignResolutionSize();
            var clipTopRight = !this.fitHeight && !this.fitWidth;
            var offsetX = 0;
            var offsetY = 0;
            if (clipTopRight) {
                // offset the canvas to make it in the center of screen
                offsetX = (designSize.width - canvasSize.width) * 0.5;
                offsetY = (designSize.height - canvasSize.height) * 0.5;
            }
            this.node.setPosition(canvasSize.width * 0.5 + offsetX, canvasSize.height * 0.5 + offsetY);
        }
        this.node.width = nodeSize.width;
        this.node.height = nodeSize.height;
    },


//设置canvas的fixed方式
   applySettings: function () {
        var ResolutionPolicy = cc.ResolutionPolicy;
        var policy;

        if (this.fitHeight && this.fitWidth) {
            policy = ResolutionPolicy.SHOW_ALL;
        }
        else if (!this.fitHeight && !this.fitWidth) {
            policy = ResolutionPolicy.NO_BORDER;
        }
        else if (this.fitWidth) {
            policy = ResolutionPolicy.FIXED_WIDTH;
        }
        else {      // fitHeight
            policy = ResolutionPolicy.FIXED_HEIGHT;
        }

        var designRes = this._designResolution;
        if (CC_EDITOR) {
            cc.engine.setDesignResolutionSize(designRes.width, designRes.height);
        }
        else {
            cc.view.setDesignResolutionSize(designRes.width, designRes.height, policy);
        }
    }

2.CCView.js

setDesignResolutionSize: function (width, height, resolutionPolicy) {

        this.setResolutionPolicy(resolutionPolicy);
        var policy = this._resolutionPolicy;


        this._originalDesignResolutionSize.width = this._designResolutionSize.width = width;
        this._originalDesignResolutionSize.height = this._designResolutionSize.height = height;

        //关键代码
        var result = policy.apply(this, this._designResolutionSize);

        if(result.scale && result.scale.length === 2){
            this._scaleX = result.scale[0];
            this._scaleY = result.scale[1];
        }


        // 关键数据 result 在fixedWidth或者fixedHeight其一时
        //viewPort = 原framesize(用于计算设计后的分辨率)其他情况下viewport是经过计算的 
        if(result.viewport){
            var vp = this._viewportRect,
                vb = this._visibleRect,
                rv = result.viewport;  

            vp.x = rv.x;
            vp.y = rv.y;
            vp.width = rv.width;
            vp.height = rv.height;

            vb.x = 0;
            vb.y = 0;
            vb.width = rv.width / this._scaleX;
            vb.height = rv.height / this._scaleY;
        }

        policy.postApply(this);
        cc.winSize.width = this._visibleRect.width;
        cc.winSize.height = this._visibleRect.height;

        //visibleRect = 最终被canvas使用的尺寸 
        cc.visibleRect && cc.visibleRect.init(this._visibleRect);

        renderer.updateCameraViewport();
        _cc.inputManager._updateCanvasBoundingRect();
        this.emit('design-resolution-changed');
    },

计算 result的代码

    _buildResult: function (containerW, containerH, contentW, contentH, scaleX, scaleY) {
        // Makes content fit better the canvas
        Math.abs(containerW - contentW) < 2 && (contentW = containerW);
        Math.abs(containerH - contentH) < 2 && (contentH = containerH);

        //主要是后两个值。可以理解为经过适配后的设计分辨率
        var viewport = cc.rect((containerW - contentW) / 2, (containerH - contentH) / 2, contentW, contentH);

        // Translate the content
        if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS){
            //TODO: modify something for setTransform
            //cc.game._renderContext.translate(viewport.x, viewport.y + contentH);
        }

        this._result.scale = [scaleX, scaleY];
        this._result.viewport = viewport;
        return this._result;
    },


_buildResult实际传入的数据由各种适配方式决定

比如 fixedWidth

    var FixedWidth = cc.Class({
        name: "FixedWidth",
        extends: cc.ContentStrategy,
        apply: function (view, designedResolution) {
            var containerW = cc.game.canvas.width, containerH = cc.game.canvas.height,
                designW = designedResolution.width, scale = containerW / designW,
                contentW = containerW, contentH = containerH;

//contentW 和 contentH都是原值传入的

            return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
        }
    });

再如
    var ShowAll = cc.Class({
        name: "ShowAll",
        extends: cc.ContentStrategy,
        apply: function (view, designedResolution) {
            var containerW = cc.game.canvas.width, containerH = cc.game.canvas.height,
                designW = designedResolution.width, designH = designedResolution.height,
                scaleX = containerW / designW, scaleY = containerH / designH, scale = 0,
                contentW, contentH;

            scaleX < scaleY ? (scale = scaleX, contentW = containerW, contentH = designH * scale)
                : (scale = scaleY, contentW = designW * scale, contentH = containerH);

//contentW 和 contentH是经过缩放的

            return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
        }
    });

总结:关键概念,1. viewportRect(最终可视裁剪区域:它决定最终的显示区域,最终的设计分辨率通过缩放显示在此分辨率下),接口cc.view.getViewportRect()获得;

viewportRect:在fixedHeight或者fixedWidth都等于frameSize;在其他情况由frameSize与designedResolution的比例决定. viewPortRect.height  = designH*scale

 

2.  _visibleRect 适配策略后到设计分辨率 

除了FixedWidth或FixedHeight 会有变化,其他情况都得到的是canvas设计分辨率,

cc.winSize和cc.view.getVisibleSize()的返回值是一样的 都是visibleRect;

cc.view.getDesignResolutionSize()和cc.view.getFrameSize()决定适配方式。设计分辨率到屏幕的显示 可以用cc.view.getViewportRect()()来理解

 

3. cc.view._scaleX  scaleY    缩放比例,除了ExactFit俩值不一样,其他都一样。可视裁剪viewportRect与设计分辨率designedResolution的缩放比例;从这里可以预制显示区域的大小。

过程:_scaleX,Y 决定viewport的大小。viewport / _scalex,y决定final designedResolution即_visibleRect。

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值