So I created a spreadsheet containing all of the screen resolution s I’m likely to encounter in the wild
(there is a link to it from my blog if you’re interested)
http://www.pooperp1g.com/blog/
Against each resolution I have put 4 different resource resolutions (2048 x 1536, 1920 x 1080, 960 x 640 and 570 x 320) which I decided upon after experimentation and looking at the various resolution ratios etc.
For each screen resolution I calculate the scale factor and visible offset for each of my resource resolutions.
Then, for each device resolution I decide which resource resolution is most appropriate (essentially, one that doesn’t scale too big or too small, and doesn’t cut off too much width (I’m assuming a fixed height policy all of these)
So I end up with a relatively simple formula to decide which resource resolution to use …
// Information about resources
typedef struct tagResource
{
cocos2d::Size size; // The size that this resource is designed for
char directory[100]; // The name of teh directory containing resources of this type
} Resource;
// Define all our resource types and locations
static Resource ultraResource = { Size(2048, 1536), "UD"};
static Resource hiResource = { Size(1920, 1080), "HD" };
static Resource stdResource = { Size(960, 640), "SD" };
static Resource lowResource = { Size(570, 320), "LD" };
// Declare the resolution we designed the game at
static Size designResolutionSize = Size(1920, 1080);
// Declare an array containing the resource descriptions, from largest to smallest
static std::array<Resource,4> resources{{ultraResource, hiResource, stdResource,lowResource }};
bool AppDelegate::applicationDidFinishLaunching() {
// initialize director
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
if(!glview) {
glview = GLViewImpl::createWithRect("PooperPig", Rect(0,0,1920,1280));
director->setOpenGLView(glview);
}
// Tell cocos our design resolution and our resolution policy
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::FIXED_HEIGHT);
// The vector we will use to build a list of paths to search for resources
std::vector<std::string> searchPaths;
// Get the actual screen size
Size frameSize = glview->getFrameSize();
// Define a silly scale factor so we know when we have calculated it
float scaleFactor = -1;
int widthDiff = 999;
Resource found;
// Look through our resource definitions
for (auto resource : resources)
{
// Calculate the Horizontal ratio for the resouces (i.e. Resource Height / Device Height
float ratio = resource.size.height / frameSize.height;
// Calculate the scaled widths based on the horizontal ratio
float scaleWidth = resource.size.width / ratio;
// Calculate the Width Differences (i.e. how much bigger is the resource than the screen, width wise- so how many pixels are we going to lose?
int diff = scaleWidth - frameSize.width;
// If the width difference is < -1 we'd have black bars, so ignore it (single pixel is fine!)
// If the scale factor is > 2 we're scaling a bit too much, ignore it
// If the scale factor is < 0.5 we're scaling a bit to much, ignore it
if (diff >= -1 && ratio <= 2 && ratio >= 0.5)
{
// Use this one if it is the lowest width difference
if (diff < widthDiff)
{
widthDiff = diff;
found = resource;
scaleFactor = ratio;
}
}
}
// so now we should have found which resource to use
searchPaths.push_back(found.directory);
CCLOG("Using %s widthDiff %d ScaleFactor %.2f", found.directory, widthDiff, scaleFactor);
Do you think this is over complex? Is anything wrong with it in principal? Is it sensible to provide resources at these three resolutions?
I’d appreciate any advice you may care to offer