Search code examples
androidopengl-escocos2d-xresolutiontiled

How to make TMXTiledMap responsive?


My game is a 2D car-based one, with a straight infinite map where I've finally been able to add some random obstacles. There are only 3 positions the car can be at, and everything is working fine.

The point is that I've recently noticed that it is not responsive, and tried to make it responsive by adding a line like these one to the AppDelegate.cpp:

glview->setDesignResolutionSize(1024.0, 600.0, kResolutionFixedWidth);

I've tried to use kResolutionFixedWidth, kResolutionFixedHeight and all others 5 variables you can put there, but I only got black lines along the screen and every single screen breakdown you can imagine -.-'

I can figure out I need to resize my TMXTiledMap manually because of the nature of tiles (I did it with Tiled), but I don't know how to face this problem.

Note that I'm currently developing for a 1024x600 Android device but I would want to support at least the most common resolutions for both tablets and smartphones.


Solution

  • There are probably 2 resolution policies you want to use.

    If you use No Border then you shouldn't see any black bars, but the engine will crop your design resolution so you won't want to put UI in the corners, or you'll want to use Visible Origin and Visible Size to calculate positions.

    If you use Exact Fit you should set the design resolution to the devices exact size, and then you're responsible for positioning and scaling everything correctly to avoid distortion.

    You will need to scale your art depending on your policy and design resolution choices if you are seeing black bars.

    Have you read through this wiki page? http://www.cocos2d-x.org/wiki/Multi_resolution_support

    Here's what we do for one of our games:

    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    
    float contentScaleFactor = 1.f;
    
    // Set the design resolution
    Size frameSize = glview->getFrameSize();
    Size designSize = glview->getDesignResolutionSize();
    CCLOG("defaults:");
    CCLOG("framesize = {%f,%f}", frameSize.width, frameSize.height);
    CCLOG("visibleSize = {%f,%f}", glview->getVisibleSize().width, glview->getVisibleSize().height);
    CCLOG("designSize = {%f,%f}", designSize.width, designSize.height);
    CCLOG("contentscalefactor = %f", director->getContentScaleFactor());
    
    Vec2 origin = director->getVisibleOrigin();
    CCLOG("visibleSize = %s", CStrFromSize(director->getVisibleSize()));
    CCLOG("origin = {%f,%f}", origin.x, origin.y);
    
    // Retina? 
    contentScaleFactor = director->getContentScaleFactor();
    float designWidth = frameSize.width / contentScaleFactor;
    float designHeight = frameSize.height / contentScaleFactor;
    CCLOG("contentScale = %f, designWidth/Height = {%f,%f}", contentScaleFactor, designWidth, designHeight);
    
    glview->setDesignResolutionSize(designWidth, designHeight, ResolutionPolicy::EXACT_FIT);
    
    // we designed the game for 480x320 (hence the divisors)
    // used to scale full screen backgrounds
    float fullWidthScaleFactor = designWidth/480.f;
    // used to scale up most UI
    float largeScaleFactor = floorf(designHeight/320.f);
    // round to closest HALF step (1.0,1.5,2.0,2.5,3.0,etc)
    // used for scaling UI where pixel art is affected by .1 scales
    float largeScaleFactorExact = floorf(designHeight * 2.f / 320.f) * 0.5f;
    // used to scale up UI that must be touchable (larger on high desnsity)
    float largeScaleFactorUI = STROUND(designHeight / 320.f);
    
    // this forces minimum of 1x scale (we should just not support these devices)
    float scaleFitAll = designWidth > designHeight ? designHeight/320.f : designWidth/480.f;
    if(largeScaleFactor < 1.f)
        largeScaleFactor = scaleFitAll;
    if(largeScaleFactorExact < 1.f)
        largeScaleFactorExact = scaleFitAll;
    if(largeScaleFactorUI < 1.f)
        largeScaleFactorUI = scaleFitAll;