Cocos2d-x3.x tower defense game (defending radish) from scratch (2), cocos2d tower defense game
I. Prerequisites:
Complete the content of the previous article.
Reference: Cocos2d-x3.x tower defense game (defending radish) from scratch ()
Ii. Objectives of this article:
L about cocos2dx mobile phone resolution adaptation
L complete screen adaptation for the previous anti-tower game prototype
Iii. content:
L about cocos2dx mobile phone resolution adaptation
At the end of the previous article, we left a problem. When running on a real machine, the heroine and the color wolf are on the opposite path, in addition, it seems that the background map does not display the top and bottom of the full background, but it runs normally in windows. Why? How can I adjust it? My mobile phone resolution is 960x540, and our map material image resolution is 960x640. The difference between the two sizes leads to this problem, this is about screen resolution adaptation of different mobile phones. There are a wide variety of Android mobile phones, and there are also a wide variety of screen sizes and resolutions. In order to adapt the game to different Android mobile phones, we need to do a lot of work, this IOS game is much happier. After all, there are just a few dimensional resolutions.
Two factors that affect the game: screen size (resolution) and aspect ratio. The screen size ranges from 480x320 of a small screen to 2048x1536 of a large screen or even a tablet, if you use a low-resolution clip image on a high-resolution device, the image will be blurred. If you use a high-resolution clip on a low-resolution device, the system will be burdened, we usually use multiple sets of different resolution materials for matching. This problem is easy to solve. However, the aspect ratio is much more troublesome. The mobile phones include the and standard wide screens. In this article, the Huawei mobile phone I tested is a wide screen, aspect ratio may cause the game to be not proportionally compressed or stretched, resulting in variations in the display and position of the game elements, and even make the game unusable, the Aspect Ratio causes more serious problems than the screen size. For example, our tower guard game causes the location offset of game characters. Can the aspect ratio be solved by using multiple sets of Aspect Ratio materials like the resolution? Yes! But if different aspect ratios are combined with different resolutions, how many sets of materials are provided? In addition, new cell phones with aspect ratio are constantly emerging, making a set of materials for every cell phone is too costly.
There is a sample project named cpp-empty-test under the cocos2d-x-3.3/tests directory that opens proj with Microsoft Visual Studio 2012. the project under win32 shows its solution to this problem. For details, refer to AppMacros. h. AppDelegate. clips in the cpp and Resources directories.
This example project can be summarized as follows:
1. screen size (resolution) Solution
Provide multiple sets of materials according to the above ideas. Generally, the game provides four sets of materials with different resolutions: low, medium, high, and ultra-high, low to deal with general small screen mobile phones, medium to cope with high-resolution mobile phones, high to cope with tablets, ultra high to deal with high-definition flat or TV devices. Four sets of materials are placed in four folders under the project Resources file, such as iphone, iphone HD, ipad, and ipadhd. When the device is loaded into the game, determine the resolution of the current device, and then select materials in different folders for loading to adapt to devices with different resolutions.
2. Aspect Ratio Solution
To adapt to various screen aspect ratios of devices, Cocos2dx provides corresponding solutions to help us better adapt to different screens when designing games. Cocos2dx provides a ResolutionPolicy to solve this problem by setting different resolutionpolicies for GLView.
Five ResolutionPolicy types:
1. EXACT_FIT
2. NO_BORDER
3. SHOW_ALL
4. FIXED_HEIGHT
5. FIXED_WIDTH
L complete screen adaptation for the previous anti-tower game prototype
1, Screen size (resolution) Adaptation
Step 1:
According to the above solution, we first made two sets of materials for iphone and iphone HD, and then copied them to the Resources file of the project. Our game is designed for mobile devices, therefore, we only provide two sets of resolution materials. If you need to support devices with higher resolution, you need to provide more sets of materials. Personally, if your game needs to support tablets, we recommend that you create an HD version separately. Although code and material adaptation can support both mobile phones and tablets, however, such implementation still has certain limitations, which will reduce the playability of a certain type of equipment to a certain extent.
Step 2:
Create an AppMacros. h file and copy the file code with the same name under the cpp-empty-test sample project to modify it. You only need to keep two different resolution codes:
#define DESIGN_RESOLUTION_480X320 0#define DESIGN_RESOLUTION_960X640 1/* If you want to switch design resolution, change next line */#define TARGET_DESIGN_RESOLUTION_SIZE DESIGN_RESOLUTION_960X640typedef struct tagResource{ cocos2d::Size size; char directory[100];}Resource;static Resource smallResource = { cocos2d::Size(480, 320), "iphone" };static Resource mediumResource = { cocos2d::Size(960, 640), "iphonehd" };#if (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_480X320)static cocos2d::Size designResolutionSize = cocos2d::Size(480, 320);#elif (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_960X640)static cocos2d::Size designResolutionSize = cocos2d::Size(960, 640);#else#error unknown target design resolution!#endif// The font size 24 is designed for small resolution, so we should change it to fit for current design resolution#define TITLE_FONT_SIZE (cocos2d::Director::getInstance()->getOpenGLView()->getDesignResolutionSize().width / smallResource.size.width * 24)
Step 3:
Open the AppDelegate. cpp file, add a reference to AppMacros. h, and then add the applicationDidFinishLaunching Method to Determine the screen resolution of the current device and set different image clips:
# Include <vector> # include <string> # include "AppMacros. h "...... // Obtain the screen Size of the current device. Size: frameSize = glview-> getFrameSize (); vector <string> searchPath; // if the screen Size is wide, smallResource material Size is wide. if (frameSize. width> smallResource. size. width) {// use the material searchPath in the mediumResource directory. push_back (mediumResource. directory); float scale = mediumResource. size. width/designResolutionSize. width; director-> setContentScaleFactor (scale);} else {// use the material searchPath in the smallResource directory. push_back (smallRes Ource. directory); float scale = smallResource. size. width/designResolutionSize. width; director-> setContentScaleFactor (scale);} // you can specify the directory FileUtils: getInstance ()-> setSearchPaths (searchPath );......
Through this code, we solve the problem of low-resolution and high-resolution mobile phone image material adaptation. How can we test the results? Find a low-resolution mobile phone and a high-resolution mobile phone respectively? This is too troublesome. In fact, you only need a line of code to directly simulate the effects of different resolutions on the phone during debugging. Add a line in the applicationDidFinishLaunching method.Glview-> setFrameSize (960,440 );The code can be implemented. When the game development is complete, the code of this line is deleted.
If (! Glview) {glview = GLViewImpl: create ("DefendTheGirl"); // set the resolution size of the simulator glview-> setFrameSize (960,440); director-> setOpenGLView (glview );}
2, Aspect Ratio adaptation
Step 1:
According to the above solution, add the following code to the applicationDidFinishLaunching method of AppDelegate. cpp:
/Set the game design size and Resolution Policy glview-> setDesignResolutionSize (designResolutionSize. width, designResolutionSize. height, ResolutionPolicy: FIXED_HEIGHT );
ResolutionPolicy has five types. Let's test these five types to see what the difference is and determine which type of game we should adopt for the best effect, in order to see the difference clearly, we can test the effect by setting different resolutions of the simulator.
EXACT_FIT:It will stretch the material to display the whole screen, which is the simplest and most crude, but may cause image deformation.
Glview-> setFrameSize (960,440 );
Conclusion:Looking at the game effect, there is indeed an image deformation as described. No matter what kind of aspect ratio is on the mobile phone screen, the materials are all stretched and deformed according to the aspect ratio of the filled mobile phone screen, I think this method is definitely not available.
NO_BORDER:The short side is full of the screen, and the other side is out of the screen. Some of the screen is out of the screen and cannot be displayed.
Glview-> setFrameSize (960,440 );
Corresponding analysis graph:
Glview-> setFrameSize (460,640 );
CorrespondingAnalysis diagram:
Conclusion:We used two cell phone sizes: 960,440 and 460,640. The analysis graph shows that the first size is that the material width (960px) is full of the entire cell phone screen, while the material height (640px) only shows the middle pixel, the upper part of the clip is covered by the mobile phone screen, and the lower part is covered by 100px; the second size is that the height of the clip (640px) is full of the entire mobile phone screen, the width of the clip (960px) only shows the 460px in the middle. the left part of the clip is covered by the mobile phone screen and the right part of the clip is covered by 250px. Explanation of NO_BORDER:Short SideThe screen is full and the other side is out of the screen. Some of the screen is out of the screen and cannot be displayed. The short side here does not mean that the material itself is wide and the high school is short, but the material width and the mobile phone width are compared, the material height and the mobile phone height are compared, the difference is small, even if it is short side, for example, in the first dimension, the width difference is = | the width of the clip is 960px-the screen width of the mobile phone is 960px | = 0, height Difference = | the height of the clip is 640px-the screen width of the mobile phone is pixel PX | = 200, so the short side is the width of the clip. I think the width and height of this method are related to the aspect ratio of the device, that is, the device may not decide which side is short.
SHOW_ALL:Keep the original proportion so that one side is full of the screen and the other side is black.
Glview-> setFrameSize (960,540 );
Conclusion:This method seems to be relatively reasonable, and the image must maintain the proportion of the original material, such as not stretching and deformation, however, it is a pity that the left and right sides of the mobile phone or the upper and lower sides will have a black blank area, unless the aspect ratio of the materials is exactly the same as that of the mobile phone. I think this method is also optional for our game, but black borders are not the best user experience, but this method is the easiest way to keep the real picture of the game on any device.
FIXED_HEIGHT:Similar to NO_BORDER, but the specified height occupies the full screen, and the width part is beyond the screen and cannot be displayed.
Glview-> setFrameSize (960,440 );
CorrespondingAnalysis diagram:
Glview-> setFrameSize (460,640 );
CorrespondingAnalysis diagram:
Conclusion:This method seems to be a bit like NO_BORDER. The above two screen sizes show that the screen size of the mobile phone screen is high, and the screen width is not greater than or less than the screen, materials still maintain their aspect ratio, and there is a certain offset between the character positions in the game background. This method is not suitable for our game.
FIXED_WIDTH: NO_BORDER is similar, but the specified width occupies the full screen. The height is beyond the screen and cannot be displayed.
Glview-> setFrameSize (960,440 );
CorrespondingAnalysis diagram:
Glview-> setFrameSize (460,640 );
CorrespondingAnalysis diagram:
Conclusion:This method seems to be a bit like NO_BORDER. The above two screen sizes show that the screen width of the mobile phone is full, and the height must not exceed the screen or be smaller than the screen, materials still maintain their own aspect ratio, and there is a certain offset between the character positions on the game background.
Our game options:
The test results and analysis results of the five types have been completed. Now we need to find the most suitable type for our anti-tower games. EXACT_FIT cannot be directly negated, SHOW_ALL is the simplest solution. Although it is a little flawed, it is acceptable for its simplest effect, and some early versions of many well-known Games use this model, however, I personally think that our game is a little high pursuit, so we have to choose one of the three preparations NO_BORDER, FIXED_HEIGHT, and FIXED_WIDTH, although it will increase the difficulty of coding and material design, however, with reasonable material design and code combination, the full screen effect can be fully realized and the proportion of the game is not distorted. These three actually belong to almost one type, NO_BORDER actually includes two types: FIXED_HEIGHT and FIXED_WIDTH, but the specific manifestation is determined by the aspect ratio of the actual device, that is, there is a certain degree of uncertainty, the FIXED_HEIGHT and FIXED_WIDTH indicate either high adaptation or wide adaptation directly by the developer, so that at least the same uncertainties can be determined. To reduce the difficulty of coding and material design to a certain extent. But FIXED_HEIGHT and FIXED_WIDTH should be selected for the two games, which should be related to the actual development. For example, horizontal screen games are more suitable for FIXED_WIDTH while vertical screen games are more suitable for FIXED_HEIGHT, at the same time, it may also be related to the game material design. For example, if we use this game map background, we must at least ensure that the road part of the map should be completely displayed in the visible area of the mobile phone screen, other parts can be covered. It can be seen that our game should choose FIXED_WIDTH.
Complete screen adaptation for the previous anti-tower game prototype
The above tests and analysis determine that our game uses the FIXED_WIDTH type to solve the problem. Now we will start the specific coding work.
Step 1:
In the applicationDidFinishLaunching method of AppDelegate. cpp, add the following code:
// Set the game design size and Resolution Policy glview-> setDesignResolutionSize (designResolutionSize. width, designResolutionSize. height, ResolutionPolicy: FIXED_WIDTH );
Step 2:Set the simulator screen size glview-> setFrameSize (960,540); then run the game
We will find that the game road is completely displayed, and some areas on the top and bottom of the background image are covered and not displayed. In this way, we can deliberately increase the upper and lower areas of the background image when designing materials, try to center the valid parts such as the road with a high material height as much as possible. For example, to adapt to the square screen of 960x960, we only need to increase the upper and lower parts of the map to 960 or higher at the same time, in addition, you only need to tile the green background to add a higher part, so that the game can be displayed on a harmonious full screen.
Step 3:The above game has another problem. It can be seen that some of the background materials are blocked at the bottom, resulting in an offset between the coordinates at the design time and the coordinates at the actual game.
However, in the previous article, the path coordinate of the road was calculated based on the relative design origin. Now, the offset of the origin coordinate leads to inaccurate path coordinate, in this way, the offset height needs to be corrected in the code.
Dw: Material Width dh: Material height sw: screen width sh: screen height offset height value: x
X =(Sh* 0.5-(Sw/Dw )*Dh* 0.5 )/(Sw/Dw)
The offset height is calculated using this formula. When applicationDidFinishLaunching, we use this formula to calculate the offset height and save it to a static variable for later use.
GameMediator. h. GameMediator. cpp class, used to save variables that are frequently used in games. For example, our offset height and material scaling ratio are saved in this class. This class implements a single instance mode, the function is simple to store variables in the form of static variables for a single instance.
GameMediator. h:
Class GameMediator: public cocos2d: CCObject {public: GameMediator (void );~ GameMediator (void); bool init (); // obtain the static GameMediator * sharedMediator () of a single instance; // The offset height CC_SYNTHESIZE (float, _ offsetHeight, OffsetHeight ); // scale ratio CC_SYNTHESIZE (float, _ scaleHeight, ScaleHeight)}; GameMediator. cpp: // static instance static GameMediator _ sharedContext; GameMediator * GameMediator: sharedMediator () {static bool s_bFirstUse = true; if (s_bFirstUse) {_ sharedContext. init (); s_bFirstUse = false;} return & _ shar EdContext;} GameMediator: GameMediator (void) {} GameMediator ::~ GameMediator (void) {} bool GameMediator: init () {bool bRet = false; do {_ offsetHeight = 0; _ scaleHeight = 1; bRet = true ;} while (0); return bRet ;}
Step 4:Introduce the GameMediator header file in the AppDelegate class, and then add the following code to the applicationDidFinishLaunching method:
// Calculate the scaled ratio float scaleHeight = frameSize Based on the width. width/designResolutionSize. width; // calculated based on the height offset. // x = (sh * 0.5-(sw/dw) * dh * 0.5)/(sw/dw) float offsetHeight = (frameSize. height * 0.5f-scaleHeight * designResolutionSize. height * 0.5f)/scaleHeight; // Save the zoom ratio GameMediator: sharedMediator ()-> setOffsetHeight (offsetHeight); // Save the height offset value GameMediator: sharedMediator () -> setScaleHeight (scaleHeight );
Step 5:In MainScene. cpp, modify the init method to declare the coordinates of 12 path points as follows:
...... // Get the saved offset height float offsetHeight = GameMediator: sharedMediator ()-> getOffsetHeight (); // get the saved zoom ratio float scaleHeight = GameMediator: sharedMediator () -> getScaleHeight ();...... // Add the path number 1 of the map to Waypoint * waypoint1 = Waypoint: nodeWithTheLocation (Point (920,435 + offsetHeight) in the collection ));...... // Add the path number 12 of the map to the Point in the set. Waypoint * waypoint12 = Waypoint: nodeWithTheLocation (Point (50,350 + offsetHeight ));......
Step 6:In this way, the coordinates of the road points have been corrected. Now we also need to improve the half position of the color Wolf and the heroine so that the bottom of their feet is just in the center of the road. In MainScene. cpp, find the code for initializing the color Wolf and the heroine in the init method and modify it as follows:
...... // Obtain uncle colorwolf's high float dsh = dsSprite-> getTextureRect (). size. height ;...... // Female Master height float nzh = nhSprite-> getTextureRect (). size. height ;...... // Obtain the last vertex in the Set, point 12 Waypoint * waypoint0 = wayPositions. back (); // set the start point of the motion beginningWaypoint = waypoint0; // set the target point of the motion to the next point of point 12, destinationWaypoint = waypoint0-> getNextWaypoint (); // set the current position value of the color Wolf, myPosition = waypoint0-> getMyPosition (); // increase the position of the half color wolf. add (Vec2 (0, dsh/2.0f); // set the initial position of the color wolf in the map dsSprite-> setPosition (myPosition); // set the initial position of the heroine in the map, point 1 pos = wayPositions in the set. front ()-> getMyPosition (); // increase by half Heroine position pos. add (Vec2 (0, nzh/2.0f); nhSprite-> setPosition (pos );......
Find the color wolf moving along the road in the update method in MainScene. cpp and modify the Code as follows:
// Obtain uncle colorwolf's high float dsh = dsSprite-> getTextureRect (). size. height; Point destinationPos = destinationWaypoint-> getMyPosition (); // improve the color Wolf's half position destinationPos. add (Vec2 (0, dsh/2.0f); // determines whether uncle colorwolf meets the target if (this-> collisionWithCircle (myPosition, 1, destinationPos, 1 )) {// whether there is another target point if (destinationWaypoint-> getNextWaypoint () {// reset the start point and target point beginningWaypoint = destinationWaypoint; destinationWaypoint = destinationWaypoint-> getNextWaypoint ();}} // obtain the coordinates of the target Point: Point targetPoint = destinationWaypoint-> getMyPosition (); // raise the half position of the color wolf targetPoint. add (Vec2 (0, dsh/2.0f ));
Step 7:Start to test the modified effects. Use glview-> setFrameSize (960,540); constantly modify the screens of various sizes to see the game effects under these screens. Compile and package the so file on the android real machine to see if the problem has been solved. before packaging, remember to add all the newly added cpp files to the Android. mk compilation list.
After modification, the effects on the real machine are as follows:
Conclusion:
This article takes a long time to solve a problem left over from the previous article, but I think this is very worthwhile because the screen adaptation problem is a very important issue, early and reasonable selection of solutions can reduce the amount of rework in the future. Now we have solved this problem and will adapt the code to this solution when developing and writing code. This article ends with coming soon: Cocos2d-x3.x tower defense game (defending radish) from scratch (3)
The author communicated QQ: 2303452599
Email: mymoney1001@126.com