Analysis of cocos2d-x screen adaptation principle

Source: Internet
Author: User

Cocos2d-x, as a famous C ++ player in cocos2d game development framework, has developed rapidly in the past year. More and more apps use it for fast multi-platform deployment, from the initial ios, android, win32 to the latest html5 to achieve mobile, full coverage from the client to the browser ~~

 


Screen Adaptation and love for mobile app development are an eternal proposition that exists in the Age of flood, with the fundamental goal of unifying user experience on different devices.
Cocos2d-x did not provide a solution before the cocos2d-2.0-x-2.0.4 version, developers can only solve it by themselves, some of the methods see here

From 2.0-x-2.0.4, the hardworking cocos2d-x team finally started to solve this problem ~ Like! The following uses an example to analyze its implementation principles. For official instructions, see here.

============================== Hello everyone, before the beginning of the text, I am a gorgeous separation line ====================================

Create a project with the helloworld example and run it like this:

 

The size of the window is 480x320, and the original size of the background fireblue genie is 480x320, which is filled with the screen.

 


Here we start to change...
First, simulate a screen with a resolution of 960x640 to see what the program looks like.
Will windows size be changed under win32? If you are jumping directly from a version earlier than 2.0-x-2.0.4, such as me (originating from 1.0.1-x-0.11.0... "From xxxx" indicates that the wine is very good. Do you have any programming skills .. We still need to keep pace with the times and improve our work style to keep close contact with the masses ~), The first response is to go to AppDelegate. cpp to find the code for setting the win32 window size.
Unfortunately, you cannot find the familiar "CC_TARGET_PLATFORM = CC_PLATFORM_WIN32". The new version moves the size of the win32 window to main. cpp,
 
In terms of the code structure, this is more reasonable, because AppDelegate. cpp is a platform-independent program logic entry, which should not contain a large number of adaptation code from different platforms.
Give it to win32's main. app and let God's belong to God, and Caesar's belong to Caesar!


Then, change eglView-> setFrameSize (480,320) to eglView-> setFrameSize (960,640), and simulate a screen with a resolution of 960x640,
OK. The size of the background image is 480x320. If the size of the background image is 960x640, it is not enough ~

Well, the requirement is: no matter what resolution we want, the user should see that the background image fills up the screen!

So, solution:
1. Use different resources to adapt to different screens. You can determine the screen resolution to set the resources for loading different directories.
2. Use a set of resources to scale the screen at different resolutions.

Let's talk about solution 1 one by one. Since we want to use different resources for different resolutions, we can create a fireblue genie background image with the same pattern. The size is 960x640,
It is used for screens with a resolution of 960x640. Create two directories under the project Resources directory:


The "iphone" directory stores the 480x320 background and button icons, and "iphone-retina" stores the 960x640 background and button icons.
The two directories are named randomly. Then we can see AppDelegate. cpp,

Run the program again

The frame finds the background image of 960x640 according to the settings, and the screen is no longer empty or lonely.
Note: To obtain the actual screen resolution of a device, use CCSize szFrame = pEGLView-> getFrameSize ();
Instead of the previous version of ccctor ctor: sharedDirector ()-> getWinSizeInPixels (); this function has another meaning, which will be introduced later.


But can you hold on to so many mobile devices around the world with so many resolutions? Even if you hold it, do your art sisters hold it?
A resolution provides a set of matching art resources .. "I hope you can accompany me to the dungeon to the sky, and hope you can accompany me to the sea to the sky ".
Even if a team is proud to be a game of the old days, the installation package will be downloaded to the old days ~
So, this is not a good way.

Let's look at the second solution, scale the Resources and restore the structure of the Resources directory:


Now there is only one x320 background image. How can this problem be solved? Modify in AppDelegate. cpp:

 

Run again, amazing! The screen is no longer empty and not lonely again ~


Analysis:
DesignResolutionSize is a new concept that completely frees all data related to coordinates and dimensions from the limitations of screen resolution, or
The framework layer helps developers complete the conversion. All developers need is to set the designResolutionSize. Tell the framework in what scenarios are you looking?
For example, if the original size of the background image is 480x320 and the requirement is to just fill the screen, you should tell the Framework "Hi, I designed it
The 480x320 screen is standard. You can turn it around for me. "Then the framework will answer you," don't worry !" How is the framework implemented? Tracking
PEGLView-> setDesignResolutionSize (480,320, kResolutionNoBorder );


It can be found that the framework obtains the ratio of the actual resolution to the developer's designResolutionSize. During rendering, the image is scaled according to the ratio.
In this example, if the screen size is 960x640, The designResolutionSize is 480x320, and the scaling ratio is 2, the background image of the original size is x.
It will be drawn with x2, that is, the actual size of 960x640 is drawn, so that the window is filled up!
Note the processing of different resolutionpolicies here. The principles will be analyzed later.

OK. Now you can write the automatically adapted code for the 480x320 and 960x640 screens (in fact, there is only one sentence, the benefits of the Framework ~~)
There is a new demand. "Who are you? Change the code and the program must be able to adapt to ipad2", WTF! Okay, greetings are returned, and the problem is always resolved.
So you started to think, "ipad2 resolution 1024x768, just modify it in main. cpp as Shuai taught me just now.", okay, change it to 1024x768,
Ms is full. You are very satisfied, but not right. Is the button in the lower right corner swollen so close to the outside of the screen ?! Take a closer look. If it is not filled, the background image is too full and exceeds the screen.
Is it swollen? The root cause is pEGLView-> setDesignResolutionSize (480,320, kResolutionNoBorder). For the third parameter, locate the definition:

I made it very clear:
KResolutionExactFit: fills the screen by stretching. In this example, the background image is deformed to fill the screen, because 1024: 768 = 1.3, 480: 320 = 1.5, the aspect ratio is different, the image cannot be scaled proportionally to fill the screen and can only be deformed.
KResolutionNoBorder: you cannot see the Black edge. It is actually the zoom in ratio of width to height, but the zoom in ratio is greater than the width to height.
KResolutionShowAll: Display All, which can be understood as ensuring that the content is displayed on the screen. It is also the scaled ratio of width to height, but the scaled ratio is smaller than the scaled ratio.

In general, we hope that the content on the design screen can be seen on the actual device. In this example, when the resolution is 1024x768, the button in the lower-right corner of the page goes out of the screen. After reading the above analysis, you should know how to solve the problem: Right, change pEGLView-> setDesignResolutionSize (480,320, kResolutionNoBorder); the third parameter is kResolutionShowAll. OK to see the effect:


Bingo! The background image fills the screen (horizontal), and the buttons are placed close to the bottom right corner to meet the unified requirements of the basic style.
However, black edges appear vertically, which is caused by different actual resolution aspect ratio and design resolution aspect ratio, which cannot be solved through the framework layer.
You can only give it to the developer. For example, when a black edge appears in the code based on resolution calculation, the corresponding image is filled with the Black edge. For some solutions, see here

 

SetPosition () Changes
Previous versions may be used to CCNode: setPosition (const CCPoint & position); and CCNode: setPositionInPixel (const CCPoint & position );
However, in the new version, only setPosition (const CCPoint & position );
The input parameter is not a pixel, but also different from the traditional point. It refers to the coordinates under the designResolutionSize reference.
Verify it to yourself: for example, if the design resolution is 480x320, set the sprite position to 240,160. At the 480x320 resolution, you will find it in the middle of the screen,
Simulate other resolutions, such as 960x768, 240,160 x, and you will find that it is still in the center of the screen. This means that the value has nothing to do with the actual screen resolution,
It is only related to the designResolutionSize. Understanding this is crucial and is the basis for the correct space sense in subsequent development!


Changes in CC_CONTENT_SCALE_FACTOR ()
First, enableRetinaDisplay () is canceled in the new version. There will be no statement that scalefactor is 2 on the retina device,
Because designResolutionSize solves the problem of scaling by different screens, CC_CONTENT_SCALE_FACTOR (); always returns 1.
 
 
Therefore, the definition in the new version is out of date.

Of course, developers can set contentScaleFactor through CCDirector: sharedDirector ()-> setContentScaleFactor (). This coefficient can be understood
The ratio of the original image size to the designResolutionSize, which is used to draw the image.
If only one set of resources scales according to different screen resolutions, you can ignore it.


GetWinSize () Changes

CCDirector: sharedDirector ()-> getWinSize (); The returned value is designResolutionSize.
CCDirector: sharedDirector ()-> getWinSizeInPixels (); get the value after getWinSize * contentScaleFactor, which is the same as the old version.
If contentScaleFactor is 1, the two functions return the same value.

 

Note the following when using the kResolutionNoBorder policy:
CCSize szVisible = CCDirector: sharedDirector ()-> getVisibleSize ();
CCPoint posVisible = CCDirector: sharedDirector ()-> getVisibleOrigin ();
When using this policy, because the standard background image may be out of the screen, you must have a visible rectangle as the reference when setting the position.
As you can understand, szVisible is the width and height of the valid area that you can see on the actual device. posVisible is the starting coordinate of the valid area, and szVisible forms a visible rectangle, generally, this visible rectangle is a subset of the visible rectangle at the design resolution.

 

To sum up, the new version of cocos2d-x (for people from 1.0.1-x-0.11.0) does add a lot of new features, the code structure is more reasonable, these are the blessing of developers, we hope 2dxteam will continue to work!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.