Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

director.setContentScaleFactor broken, multiple resolutions not actually supported #1011

Open
MarkEHenderson opened this issue Jul 17, 2013 · 6 comments

Comments

@MarkEHenderson
Copy link

The first problem

In the existing codeBase, CCMacro.js is loaded before CCConfig.js, which means cc.IS_RETINA_DISPLAY_SUPPORTED is undefined when CCMacro is parsed.

because of this the definition for cc.CONTENT_SCALE_FACTOR will always return 1:

cc.CONTENT_SCALE_FACTOR = cc.IS_RETINA_DISPLAY_SUPPORTED ? function () {
    return cc.Director.getInstance().getContentScaleFactor();
} : function () {
    return 1;
};

the fix

Change the load order in jsloader.js to:

    var engine = [
        'cocoa/CCGeometry.js',
        'platform/Sys.js',
        'platform/CCConfig.js',

and add a line to ccGeometry to define cc

var cc = cc || {};

The second problem(s)

After making the above fixes, I tried to run using the xhdpi assets from our cocos2d-x game. In cocos2d-x we just used a designResolutionSize of 320x480 and a contentScaleFactor of 2, and everything lays out nicely and scales properly.

In html5, there are a bunch of bugs:

  • Sprites are twice as large as they should be
  • Scale9Sprites render incorrectly
    Expected: (from cocos2dx)
    screen shot 2013-07-17 at 12 00 31 pm

What actually shows
screen shot 2013-07-17 at 12 00 14 pm
(I suspect the bottom right bit is caused by the capInsets rect not being scaled up. Not sure why the top part is missing)

  • LabelTTF nodes appear to be twice as large as they should be

There are probably other bugs as well - most of our game is created using those three types of nodes. I don't have time to be digging into all of these, so for now we're just going to be sticking with our mdpi assets.

I've also noticed that none of the sample games / projects use the built in multi resolution support. CocosDragonJS does support multi resolution, but it does that in game code.

@dingpinglv
Copy link
Contributor

Hi Mark,

We will fix the first problem soon. Thank you very much.

And the second problem, could you please send a demo or sample codes to me that reproduce the problem?
I don't know How did you make your game support multi resolution.

We have a sample app to demonstrate that how to load resources by resolution.
The sample codes in template/main.js:

var screenSize = cc.EGLView.getInstance().getFrameSize();
        var resourceSize = cc.size(800, 450);
        var designSize = cc.size(800, 450);

        var searchPaths = [];
        var resDirOrders = [];

        searchPaths.push("res");
        cc.FileUtils.getInstance().setSearchPaths(searchPaths);

        var platform = cc.Application.getInstance().getTargetPlatform();
        if (platform == cc.TARGET_PLATFORM.MOBILE_BROWSER) {
            if (screenSize.height > 450) {
                resDirOrders.push("HD");
            }
            else {
                resourceSize = cc.size(400, 225);
                designSize = cc.size(400, 225);
                resDirOrders.push("Normal");
            }
        }
        else if (platform == cc.TARGET_PLATFORM.PC_BROWSER) {
            resDirOrders.push("HD");
        }

        cc.FileUtils.getInstance().setSearchResolutionsOrder(resDirOrders);

        director.setContentScaleFactor(resourceSize.width / designSize.width);

        cc.EGLView.getInstance().setDesignResolutionSize(designSize.width, designSize.height, cc.RESOLUTION_POLICY.SHOW_ALL);

        // turn on display FPS
        director.setDisplayStats(this.config['showFPS']);

        // set FPS. the default value is 1.0/60 if you don't call this
        director.setAnimationInterval(1.0 / this.config['frameRate']);

        //load resources
        cc.LoaderScene.preload(g_resources, function () {
            director.replaceScene(new this.startScene());
        }, this);

        return true;
    }

@MarkEHenderson
Copy link
Author

Here's the relevant portion of our main.js:

        var mdpiResource  =  { size:cc.size(320, 480), path:"res/mdpi" };
        var xhdpiResource =  { size:cc.size(640, 960), path:"res/xhdpi" };
        var designResolutionSize = cc.size(320, 480);

        var frameSize = cc.EGLView.getInstance().getFrameSize();

        var resource = mdpiResource;

        if( frameSize.width > mdpiResource.size.width ||
            cc.Application.getInstance().getTargetPlatform() == cc.TARGET_PLATFORM.PC_BROWSER) {
            //use xhdpi resources
            resource = xhdpiResource;
            designResolutionSize = cc.size(640, 960);
        }


        cc.FileUtils.getInstance().setSearchPaths([resource.path]);
        cc.FileUtils.getInstance().addSearchPath("fonts");
        cc.FileUtils.getInstance().addSearchPath("locales");

        // in the code above, resource.size.width will always = designResolutionSize.width....
        var scaleSize=resource.size.width / designResolutionSize.width;
        cc.log("Resource scale size: "+scaleSize);
        director.setContentScaleFactor(scaleSize);

        cc.EGLView.getInstance().setDesignResolutionSize(
            designResolutionSize.width,
            designResolutionSize.height,
            cc.RESOLUTION_POLICY.SHOW_ALL);

        // turn on display FPS
        director.setDisplayStats(this.config['showFPS']);

        // set FPS. the default value is 1.0/60 if you don't call this
        director.setAnimationInterval(1.0 / this.config['frameRate']);

of note - both in our code and in yours, the contentScaleFactor always comes out to 1.

In the c++ code, the designResolutionSize is always set to 320 x height, and the contentScaleFactor is set to 1 or 2. In the template JS code, the contentScaleFactor is always set to 1, and the designResolutionSize is set to 320x480 or 640x960. Trying to set up the html5 game in the same way as we set up our native game causes the rendering errors I reference above. using a contentScaleFactor of 1 and a larger designResolution causes a lot of layout bugs from our game code, and displays a lot of Nodes at half they size they should show.

I've also noticed a couple of missing calls to cc.POINT_POINTS_TO_PIXELS in CCSprite.js and CCSpriteFrame.js when compared to the c++ versions, though adding them doesn't seem to have fixed the problems.

NOTE: I'm rendering in Canvas.

@MarkEHenderson
Copy link
Author

I tried running with webGL enabled and a contentScaleFactor of 2. Sprites and Scale9Sprites render correctly, but LabelTTFFonts are rendering at half the size they should be and have a strange rendering artifact:
screen shot 2013-07-19 at 1 41 26 pm
screen shot 2013-07-19 at 1 44 27 pm
I'm guessing the text is getting rendered at the wrong contentScale, and the last pixel is getting stretched?

@MarkEHenderson
Copy link
Author

I've discovered the root cause of most of my canvas scale problems. Still testing and cleaning up the fixes, but I've identified the root cause and am preparing a pull request.

cc.Texture2D automatically accounts for ContentScaleFactor when getContentSize() is called, but in canvas mode the HTMLCanvasElement replaces cc.Texture2D but does not account for ContentScaleFactor.

I went through sprite and scale9Sprite and found every instance where the code was referencing texture.width and texture.height. forcing those and the spriteCanvas.draw function to all account for ContentScaleFactor fixed most of the non-text layout and size bugs we have.

I actually had to remove the reference to cc.CONTENT_SCALE_FACTOR from cc.LabelTTFCanvas to make that work properly, though I notice that the HEAD labelTTF code has extra calls to that in other parts of the code.

@dingpinglv
Copy link
Contributor

Yes, cc.Texture2D has a problem that canvas Mode and WebGL Mode appears differently in cocos2d-html5.

I will fix the problem in next version, I need more time to solve this problem, because this is a core class.

@MarkEHenderson
Copy link
Author

I have fixed all of the bugs I'm aware of and submitted it as a new pull request:
#1018

You can probably figure out a cleaner fix than this - the primary problem that I had to deal with was that HTMLCanvasElement.width and .height doesn't account for contentScale the way that Texture2D does.

I've tested the code from the pull request in Canvas and WebGL for my game, which mostly uses Sprites, Scale9Sprites, LabelTTF, and ParticleSystems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants