Professional Documents
Culture Documents
This part is an understanding of these concepts after reading the article reproduced below:
FrameSize is the actual resolution of the screen, which is unchanged. For example, the resolution of the mobile phone I used for the Geshisan is
1280x720, which is the FrameSize of the Geshisan.
Note that this FrameSize is easy to understand as the length and width of the screen, in fact, not, the resolution and the actual length
and width are not necessarily related.
such as:
The Geshi 3 has a size (length and width) of 4.8 inches and a resolution of 1280x720.
The size (length and width) of the Geshi 4 is 4.99 inches with a resolution of 1920x1080.
So when designing a game, just consider the resolution of the screen, regardless of the actual length and width of the screen.
WinSize is the design resolution, which is equivalent to the logical size of the game design. It can be understood that the above FrameSize is the
frame, where WinSize is the canvas.
VisibleSize is the part of the canvas that is displayed in the frame. Note that its size is represented by WinSize.
VisibleOrigin is the coordinate point of the VisibleSize in the lower left corner of the frame. Note that it is also represented by WinSize.
such as:
FrameSize: assumed to be width = 720, height = 420
WinSize: assumed to be width = 360, height = 240
In kResolutionNoBorder mode, the example image is as follows:
The VisibleSize at this time is HIKJ, and the VisibleSize at this time is Width = 360, height = 210.
Because FrameSize has an aspect ratio of 720 : 420 = 360 : 210 and our design resolution is 360 : 240, the design resolution cut off by the frame
in kResolutionNoBorder mode
Just 360:210
VisibleOrigin at this time is the K in VisibleSize, the coordinates are (0,15), and the right picture shows 15 = (240210)/2
Selfsummary:
In fact, the design resolution (WinSize) is the logical canvas size in the program. It is something we need to pay attention to. All our drawing
elements are placed on a logically sized canvas.
As for the design resolution display to the screen resolution (FrameSize), it is through the program to give us several modes (kResolutionExactFit,
kResolutionNoBorder, kResolutionShowAll, kResolutionFixedHeight, kResolutionFixedWidth) let us adapt, to determine which parts of the canvas
need to be displayed in the painting On the box (phone screen).
The following article is reproduced:
Http://www.himigame.com/iphone-cocos2dx/1404.html
In order to adapt to various resolutions of mobile terminals, various screen aspect ratios, in cocos2dx (current stable version: 2.0.4 ), provide
corresponding solutions to facilitate us when designing games. Good to adapt to different environments.
At the beginning of the design game, we decided which factors are suitable for our screen adaptation. In short, there are only two points: the
screen size and the aspect ratio . How these two factors affect the game:
Screen size: from small resolution 480 × 320 to 1280 × 800 resolution, then to full HD 1080p , from mobile phone to tablet, and Apple
device Retina screen, so many different resolutions, and the size difference is very large, impossible to do Going to a set of resources to go to
the world, the resources are designed to be small, the display will be blurred on the big screen, the picture will be big, the device on the small
screen will be too wasteful, and the hardware resources of the small screen will be relatively scarce, so according to the screen It is
necessary to use different resources in size , and cocos2dx also solves this for us.
Aspect ratio: What is the aspect ratio, whether your screen is square or long, the resolution near the square is 480×320, the ratio is 3:2 , and
there is a 960×540 16:9 standard widescreen. It can be regarded as two kinds of general extremes. If you can adapt to the two ratios, you can do
it. If it is more "3" than "3:2", it is longer than 16:9. Regardless of the layout, the display effect is very different, it is best to optimize the fixed ratio.
When the aspect ratio is within a certain range, it can be adapted by flexible programming. In terms of display effect, cocos2dx provides us with
three modes, which are more to help us solve the problem of different ratios. Exist , if it's just the screen size (the same ratio), it can be
done by simply zooming in and out.
Three modes
He said that the three models, in fact, there is a free mode , which is the default cocos2dx adaptation scheme, now we come to know about
these patterns, and these patterns to understand some of the concepts FrameSize , WinSize , VisibleSize , VisibleOrigin , And the meaning
of their existence, and finally the flexibility to run these concepts creates a new adaptation solution that does not belong to these
patterns beyond these patterns , which is the ultimate goal.
kResolutionUnKnown knows FrameSize
This is the default mode written by cocos2dx. There is no processing. In this case, the size and proportion of the game screen are uncontrollable.
At the beginning of the program, the screen size is defined by each platform entry function:
1. // proj.linux/main.cpp linux platform manually specify the screen size
2. CCEGLView* eglView = CCEGLView::sharedOpenGLView();
3. eglView>setFrameSize(720, 480);
4.
5. // proj.android/jni/hellocpp/main.cpp android platform calls the device resolution parameter by jni
6. Void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject thiz, jint w, jint h)
7. {
8. If (!CCDirector::sharedDirector()>getOpenGLView())
9. {
10. CCEGLView *view = CCEGLView::sharedOpenGLView();
11. View>setFrameSize(w, h);
12.
13. AppDelegate *pAppDelegate = new AppDelegate();
14. CCApplication::sharedApplication()>run();
15. }
16. Else
17. {
18. //other
19. ...
20. }
21. }
1.
game is running . If you run it on your phone, different resolutions will get different values. Since this value is uncontrollable, there is no reference
value in writing the game. For example, we write the position of a sprite from the bottom 320 height, at 480× 320 resolution, you can see it at the
top of the screen. If you change the resolution of a mobile phone to 960×540, you can only display it in the middle position. If you set the sprite
position to be above the screen (height) 320, the opposite is still displayed. The effect is different.
The feasible solution at this point is to use the percentage, such as the sprite position in the horizontal width of the screen 1/3 width to the left, in
the middle of 1/2, and settings like this do not depend on the specific value of FrameSize. In this way, the internal elements are like springs, and
the size of the FrameSize changes, scaling or squeezing. The size of the image resource is completely uncontrollable. If you zoom in and out
according to the screen size, we can consider the following. Mode, the modeless scheme of cocos2dx is not recommended here.
kResolutionExactFit and kResolutionShowAll Meet WinSize
At AppDelegate.cpp you can set it by:
1. CCEGLView::sharedOpenGLView()>setDesignResolutionSize(720, 480, kResolutionShowAll);
2. // or
3. CCEGLView::sharedOpenGLView()>setDesignResolutionSize(720, 480, kResolutionExactFit);
1.
DesignResolutionSize! As the name implies, it is the logical game screen size. Here we set the resolution to 720×480 as an example. In the game,
we can set the position of the sprite to refer to this value, such as ccp (0 in the lower left corner). 0), ccp (720, 480) in the upper right corner,
regardless of the size of FrameSize, is 720 × 480 is also, is 480 × 320, it can always display its position correctly, the lower left corner and the
upper right corner. The reason for this is that the design resolution is fixed to determine its fixed aspect ratio. The advantage is that you can use
the specific value to place the sprite position, not because of the actual screen size aspect ratio. The relative positional relationship
of internal elements is confusing .
In order to maintain the aspect ratio of the picture, cocos2dx made some sacrifices, what sacrificed? kResolutionExactFit sacrifices image quality
while maintaining fullscreen display and stretching the picture. What does this mean? This means that in the extreme case, the original sprite is
square, and the display becomes a rectangle. The original round shape becomes an ellipse. This mode is not recommended. kResolutionShowAll
In order to maintain the design screen ratio, black border processing is performed on all sides, so that the screen cannot be full screen at different
scales. Fish and bear's paw can't have both.
We can get the value set by setDesignResolutionSize by the following method :
1. CCSize winSize = CCDirector::sharedDirector()>getWinSize();
We can use the Cocos2dx program to start and end the article, track the WinSize initialization, the acquisition process, here is a brief mention,
the following steps:
1. // get winSize
2. CCSize winSize = CCDirector::sharedDirector()>getWinSize();
3.
4. / / View its getWinSize (); method implementation
5. [cocos2dxpath]/cocos2dx/CCDirector.cpp
6.
7. CCSize CCDirector::getWinSize(void)
8. {
9. Return m_obWinSizeInPoints;
10. }
11.
12. // and when m_obWinSizeInPoints is assigned
13. [cocos2dxpath]/cocos2dx/platform/CCEGLViewProtocol.cpp
14.
15. Void CCEGLViewProtocol::setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy)
16. {
17. ...
18. ...
19. m_obDesignResolutionSize.setSize(width, height);
20.
21. ...
22. ...
23. CCDirector::sharedDirector()>m_obWinSizeInPoints = getDesignResolutionSize();
24. }
25.
26. Const CCSize& CCEGLViewProtocol::getDesignResolutionSize() const
27. {
28. Return m_obDesignResolutionSize;
29. }
1.
Specific advantages: By setting the logical resolution size, compared to no mode, it can help us solve the problem of automatic zooming and
shrinking of the screen, and keep the aspect ratio of the screen, so that the game is better designed, and the design image size can be used as the
default background image size. Wait, the only regret is the little sacrifice mentioned earlier.
The kResolutionShowAll solution can be used as our default solution to make the design of the game more simplified, but in order to fill the stretch
or leave the black edge, enter the next mode!
kResolutionNoBorder Learn about VisibleSize and VisibleOrigin
This mode can solve two problems, one: the game screen full screen; the second: keep the aspect ratio when setting the game, compared to
kResolutionShowAll, in order to fill the remaining black edges, the screen is slightly enlarged to As for the right side of the black
side , the consequences of this can be imagined, while filling the black side, there will be a part of the screen in the other direction out of the
screen, as shown below:
The black border indicates the actual screen resolution, the purple area indicates the size of the game design, and by zooming in and out, keeping
the aspect ratio fixed, you can see that the black shaded part of Show All is the left edge, while the purple shaded part of No Border is
Cannot be displayed, and the size of this purple area is uncontrollable at the time of game design. Then the original design's picture size loses a
certain reference value, because this may make your picture display defective. At this time, we can't satisfy our design requirements only through
WinSize, so we introduced the VisibleSize and VisibleOrigin concepts.
As shown above, the purple area is the part that is truncated by the screen and cannot be displayed. According to the actual situation, horizontal
interception and vertical interception may occur depending on the aspect ratio of the actual resolution. The design resolutions and fixed sizes are
indicated by A, B, C, and D. If we want a sprite element to be displayed at the top of the screen, then if you set the position using the height of
WinSize, it may happen that it is displayed outside the screen. FrameSize and WinSize We already know the concept, and what VisibleSize and
VisibleOrigin represent, and how to solve the problem for us! Notice the definition below the image above, VisibleSize = HIJK is marked in
purple. In the above picture is a black label indicating the actual resolution of the screen. Although both FrameSize and VisibleSize are HIJK,
the meaning is different. Purple indicates that it is related to the design resolution.
FrameSize is the actual screen resolution, and VisibleSize is the largest area within WinSize that maintains the aspect ratio of
FrameSize . The actual screen resolution HIJK (black) can be larger than WinSize, but VisibleSize must be less than or equal to WinSize. The
two are the same as the aspect ratio. VisibleSize has a WinSize size (which changes as WinSize changes), and a FrameSize aspect ratio, which
is the size of the visible area on the screen at the design resolution (WinSize). VisibleOrigin marks the size of the area intercepted at
the design resolution, marked with a point K. With this data, we want the game elements to always be within the area of the screen display. The
following is a few values to bring in, to deepen the impression of these concepts.
1. // group [1] :
2. FrameSize: width = 720, height = 420
3. WinSize: width = 720, height = 480
4. VisibleSize: width = 720, height = 420
5. VisibleOrigin: x = 0, y = 30
6.
7. // group [2]: compared to group [1] FrameSize is unchanged VisibleSize and VisibleOrigin become smaller as WinSize becomes smaller
8. FrameSize: width = 720, height = 420
9. WinSize: width = 480, height = 320
10. VisibleSize: width = 480, height = 280
11. VisibleOrigin: x = 0, y = 20
12.
13. // group [3] : compared to group [1] WinSize is unchanged, VisibleSize changes as the proportion of FrameSize changes
14. FrameSize: width = 720, height = 540
15. WinSize: width = 720, height = 480
16. VisibleSize: width = 640, height = 480
17. VisibleOrigin: x = 40, y = 0
18.
19. // WinSize VisibleSize VisibleOrigin is related to the resolution of the design, which satisfies the following relationship
20. WinSize.width = (VisibleOrigin.x * 2) + VisibleSize.width
21. WinSize.height = (VisibleOrigin.y * 2) + VisibleSize.height
1.
The specific usage of NoBorder can refer to cocos2dx's own routine TestCpp , which has detailed usage methods, and encapsulates the
VisibleRect class, which can obtain the design resolution, the main reference point when the screen is different in proportion, the four corners of
the screen, and The midpoint of the edge, etc., let us set the position of the element so that it can always be displayed in the screen, which will not
be described in detail here.
Based on the program usage of these modes, cocos2dx comes with routines or there are many tutorials on the Internet. Only the various concepts
are explained in detail here, and knowing these concepts, of course, there is not much problem.
kResolutionLeafsoar
! ! ! What is this mode! Well, Leafsoar is a leaf ID, or the firstlevel domain name of this blog: P does not have this mode in cocos2dx. Apart
UnKnown and ExactFit not say, ShowAll advantage is that the design requires only a resolution, and then set the relative alignment by
WinSize can, and the maximum length and width positions are determined to facilitate the development, but can not fill the screen, NoBorder The
advantage of the mode is that the screen is not deformed, the full screen is displayed, and the display effect is better. However, WinSize is invalid
to a certain extent. It is necessary to calculate the position by calculating VisibleSize and VisibleOrigin at runtime. Since it is a runtime calculation, it
will also appear. Various screens display different effects.
ShowAll and NoBorder each have their own strengths, and each has its own shortcomings. The new adaptation solution proposed here is based
on the combination of the two . Simply put, use NoBorder to implement the idea of ShowAll. NoBorder can guarantee full screen utilization,
ShowAll can better use the actual design coordinates fixed position, and the relative position does not change with the aspect ratio change, which
is convenient when writing games. First on the schematic, at a glance (two maps, two directions):
Added a new concept to the original NoBorder mode diagram, LsSize = XYMN (leafsoar abbreviated, in order not to be confused with some
concepts of cocos2dx, what name is not important, just understand its meaning), LsSize in NoBorder mode Relative to FrameSize, just like
WinSize in ShowAll mode is relative to FrameSize, so this is the combination concept of ShowAll NoBorder, and the aspect ratio of LsSize
and WinSize is the same here.
Looking at it suddenly, it seems to complicate the problem. If you look closely, it’s better to look at it~~
In ShowAll, WinSize is the highest width and height, so as to refer to the set position, because it can be displayed on the screen within this range.
NoBorder is used to make an area around the area, and the size of this area is uncontrollable, so it cannot Then use WinSize as a reference point
to set the position, and here LsSize is the same, because LsSzie can always be displayed in the screen under any circumstances, we can easily
use LsSize as a coordinate system reference, and can be displayed in full screen, in coordination VisibleSize is much better than the pure
NoBorder. How can it be used?
You can use LsSize as the WinSize in ShowAll, and the black border can be filled with a slightly larger image, or use other images to decorate
the border . The decorated border pattern can be large or small, can be long or short, fill the screen, and maintain full screen.
Start the game design implementation based on LsSize
In order to accurately implement the LsSizebased design, it is initially planned to set the LsSize to a resolution of 480×320. To make some
preparations for this, firstly, without using any mode, the following is called in the scene:
1. CCSize size = CCDirector::sharedDirector()>getWinSize();
2.
3. CCPoint center = ccp(size.width/2, size.height/2);
4.
5. // Size 600×500 For NoBorder to see the effect, use a slightly larger background image
6. CCSprite* pb = CCSprite::create("Back.jpg");
7. Pb>setPosition(center);
8. This>addChild(pb, 0);
9.
10. // 480×320 This image is for the design resolution LsSize
11. CCSprite* pSprite = CCSprite::create("HelloWorld.png");
12. pSprite>setPosition(center);
13. This>addChild(pSprite, 0);
14.
15. // 37×37 Add reference to the four corners of the 480×320 screen
16. CCSprite* p1 = CCSprite::create("Peas.png");
17. P1>setPosition(ccpAdd(center, ccp(240, 160)));
18. This>addChild(p1);
19.
20. CCSprite* p2 = CCSprite::create("Peas.png");
21. P2>setPosition(ccpAdd(center, ccp(240, 160)));
22. This>addChild(p2);
23.
24. CCSprite* p3 = CCSprite::create("Peas.png");
25. P3>setPosition(ccpAdd(center, ccp(240, 160)));
26. This>addChild(p3);
27.
28. CCSprite* p4 = CCSprite::create("Peas.png");
29. P4>setPosition(ccpAdd(center, ccp(240, 160)));
30. This>addChild(p4);
1.
Display effect: (FrameSize = 640×540)
Display effect: (ShowAll; FrameSize = 520×320; WinSize = 480×320)
Display effect: (NoBorder; FrameSize = 520×320; WinSize = 480×320)
Through the effect, we can see that when NoBorder under the same FrameSize, the picture is enlarged by the black border, so that the upper and
lower parts are not fully displayed, which can be seen by the four sprites at the corner.
it is good! Since we know that it is due to amplification, then we will shrink the picture? Cocos2dx provides a method, we call the following code:
1. CCDirector *pDirector = CCDirector::sharedDirector();
2. pDirector>setContentScaleFactor(
3. CCEGLView::sharedOpenGLView()>getScaleY() );
In order to compensate for the need for the screen to appear without filling in the blanks, we will reduce the image, and the magnification factor can
be obtained by CCEGLView::sharedOpenGLView()>getScaleY() . In fact, the setContentScaleFactor method is designed to adapt to
different resources. You can use this method to adapt, scale, and so on different resources. The effect is as follows:
We see that the 480×320 image is completely correct, and it is exactly what we want, but the only drawback is that ~~ The position of the four
elves at the corner is still not what we want. The location we designed is 480. ×320 Set the position, and WinSize is also 480×320. At this time, the
design based on 480×320 will inevitably be displayed outside the screen, and if you want to display the correct position without modifying the sprite
position, then to ensure LsSize Fixed, we need a method, which is to dynamically set WinSize .
What do you mean? We know that when designing games in these modes, WinSize is set by setDesignResolutionSize . This value is fixed
during game running, and VisibleSize is dynamically changed. The concept of LsSize is proposed here. As you can imagine, if WinSize is fixed,
then LsSize will change as the aspect ratio of the screen changes. Then we reverse the line and fix the LsSize value. At runtime, the actual
aspect ratio can be used to calculate the WinSize value, so that the dynamically calculated WinSize value can Make sure our LsSize is a fixed
value.
Relativity , the value of WinSize and LsSize is relative, instead of dynamically obtaining LsSize at runtime by fixing WinSize (this is also the
default way of NoBorder, and the result is that WinSize has no reference value), it is better to fix LsSize and WinSize at runtime. The settings are
more wonderful.
Now instead of using the setContentScaleFactor method, and modifying the value of setDesignResolutionSize , we know that when
WinSize is 480×320, LsSize will inevitably be smaller than this value, and the amplification factor of NoBorder can be calculated as follows (refer to
the internal implementation of setDesignResolutionSize method), and Execute in AppDelegate:
1. CCSize frameSize = CCEGLView::sharedOpenGLView()>getFrameSize();
2. / / Set the LsSize fixed value
3. CCSize lsSize = CCSizeMake(480, 320);
4.
5. Float scaleX = (float) frameSize.width / lsSize.width;
6. Float scaleY = (float) frameSize.height / lsSize.height;
7.
8. / / Define the scale variable
9. Float scale = 0.0f; // MAX(scaleX, scaleY);
10. If (scaleX > scaleY) {
11. // If the X direction is too large, scaleX needs to be divided by an amplification factor, and the magnification factor can be obtained from the 枞
direction.
12. // Because the top and bottom of FrameSize and LsSize overlap at this time
13. Scale = scaleX / (frameSize.height / (float) lsSize.height);
14. } else {
15. Scale = scaleY / (frameSize.width / (float) lsSize.width);
16. }
17.
18. CCLog("x: %f; y: %f; scale: %f", scaleX, scaleY, scale);
19.
20. // Dynamically set WinSize based on LsSize and screen aspect ratio
21. CCEGLView::sharedOpenGLView()>setDesignResolutionSize(lsSize.width * scale,
22. lsSize.height * scale, kResolutionNoBorder);
1.
Display effect: (NoBorder mode; FrameSize = 520×320; LsSize = 480×320; WinSize = dynamic acquisition)
We saw that the source code was not modified, and the 480×320 reference system was used in the design. It is also based on the LsSize design.
As we expected, let's change the FrameSize to see if it can adapt automatically. as follows:
Display effect: (NoBorder mode; FrameSize = 600×480; LsSize = 480×320; WinSize = dynamic acquisition)
At this point, the game design based on the LsSize reference system has been completed. The advantage of this is obvious. The advantages of
ShowAll and NoBorder are in one place. The picture elements here are written for the purpose of positioning and implementation. The scene can
be displayed using a background map, or a large image, without any effect, you can continue to use VisibleSize to get the size of the area outside
the LsSize, you can use the background image as a decoration outside of LsSize, which guarantees the full screen of the game. It also guarantees
the convenience of the game design. If you use the design based entirely on LsSize, in addition to displaying the background decoration, we don't
want to let the internal elements of LsSize show up outside of LsSize. We only need to set the display area of the LsSize layer, we can modify the
implementation of the scene:
1. // Here is the first simple way to achieve ideas
2.
3. CCScene* HelloWorld::scene() {
4.
5. CCScene *scene = CCScene::create();
6. // Create a background layer
7. CCLayer* b = CCLayer::create();
8. Scene>addChild(b);
9.
10. // Add a background image and set the location, you can use other decorations, or a small image screen will do
11. CCSize size = CCDirector::sharedDirector()>getWinSize();
12. CCPoint center = ccp(size.width/2, size.height/2);
13. CCSprite* pb = CCSprite::create("Back.jpg");
14. Pb>setPosition(center);
15. B>addChild(pb, 0);
16.
17. // Create an LsLayer layer
18. HelloWorld *lsLayer = HelloWorld::create();
19. Scene>addChild(lsLayer);
20.
21. Return scene;
22. }
23.
24. // Rewrite the visit() function in HelloWorld to set the display area.
25. Void HelloWorld::visit() {
26. glEnable(GL_SCISSOR_TEST); // Turn on display of the specified area
27. // Only write fixed values here, in the characteristic environment, in order to quickly see the effect, the actual value needs to be calculated
according to the actual situation.
28. glScissor(20, 0, 480, 320); // only show the area of the current window
29. CCLayer::visit(); // Call the following method
30. glDisable(GL_SCISSOR_TEST); // disable
31. }
1.
Display effect: (NoBorder mode; FrameSize = 520×320; LsSize = 480×320; WinSize = dynamic acquisition)
Screen adaptation new solution
After reading this article, I must have a good understanding of the cocos2dx screen adaptation scheme and its principles, from the three modes
provided internally, to our custom LsSizebased Leafsoar mode (good, because it is called ShowAllNoBorder) ). Here we have given the
complete implementation principle and implementation method, and with the effect diagram, of course, there are some details to pay attention to,
such as our size design based on LsSize, then the actual picture must be larger than LsSize, how much Too small to adapt, too big and waste, how
to choose and other issues, what depends on this factor, leaving the reader to think ~~
A leaf will create a ScreenSolutions project at GitHub , from which readers can refer to the implementation. (Perhaps the implementation seen on
GitHub at this time is not complete, but there is a simple implementation and it can run, if necessary, a new blog will be written to implement
ScreenSolutions and explain)