I am a new learner in cococ2d-x game library, and I am learning how to create a simple game in iphone6. The SKD I am using is Xcode, but I have a problem in the screen resolution in the simulator, the situation is as follows:
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
CCLOG("visibleSize: visibleSize.width=%f, visibleSize.height=%f",visibleSize.width,visibleSize.height);
CCLOG("origin: origin.x=%f, origin.y=%f",origin.x, origin.y);
I use this code to print the visible size and the result is as follows:
visibleSize: visibleSize.width=180.281693,visibleSize.height=320.000000
origin: origin.x=149.859161, origin.y=0.000000
I go to google and found that the size of an iphone 6 is much bigger than the size I get from cocos2d-x code(320 x 480 points) and about the simulator, the tutorial is using iphone retina to show the demo, but I cannot found the iphone Retina simulator in my Xcode, I can only find Ipad Retina, and my simulator version is IOS9.3, this is really annoying because I cannot use the code like
node->setPosition(Point::ZERO);
to set the node to ZERO position, this object will be invisible due to the size problem.
Can someone help me please?
The resolution which you get by calling Director::getInstance()->getVisibleSize(); is not the real device's resolution. It's your Design Resolution.
Besides, if you want to understand more about cocos2d-x easy multi-resolution mechanism, check my other answer.
And notice the bottom-left point of the screen is determined by Origin Point not Point::ZERO.
Related
I have admob banner set up at the bottom of the screen.
I want to offset everything so that nothing is covered up by the banner.
I have no idea how to get the height of the admob banner DYNAMICALLY.
For iphone4, 120 is the height of admob, but for iphone 6, it's 100.
I guess it's something related to screen being scaled, but I couldn't figure it out.
My screen is set up like this in AppDelegate.cpp
cocos2d::Size designResolutionSize = cocos2d::Size(1136, 768);
and
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);
There is no real-metric like cm option in cocos2dx and in fact we don't need it.
But cocos2D-x 2.x and 3.x have very easy solution for multi-resolution problem ( either iDevices or Android devices) As you saw in Multi-resolution support document.
In fact you just need to set your DesignResolution and then just imagine your target device will has this resolution.
If target device really has this resolution ( or any other with same ratio) cocos2d will handle to fix screen and your game looks same in all devices.
And when ratio of target device is different, you have many option ( policy) to manage that.
For example if you use Exact fit policy, cocos2d will force your game ( and design) to fit target device screen (without that black boarder).
Exact fit
The entire application is visible in the specified area without trying
to preserve the original aspect ratio. Distortion can occur, and the
application may appear stretched or compressed.
For more detail just take a look at the official wiki.
Beside all above word, I found This Link (from V-Play engine) and Its Safe Zone definition really interesting and I highly recommend you to use recommended-resolution-value of this page for your work as I did.
Although this link is from another engine but the description helps you understand everything better. Here is a map between this page terms to cocos2d-x terms:
V-Play::letterbox => Cocos2dx::Show All
V-Play::ZoomToBiggerSide => Cocos2dx::NoBorder
In addition you did ask about required image size in cocos2dx development:
As you know the different size of image is not about game-look in different resolutions and you can publish your game with one size for each asset and your game/app looks good in all resolution with above description for resolution Policies.
But we need multiple image-size for each asset, to optimize memory usage. in this case ( as cocso2dx solution) we check device size and mark appropriate set of image ( each image set is in one folder with same-structure/different-size like HDR/HD/SD) as default folder of resource:
CCSize frameSize = pEGLView->getFrameSize();
if (frameSize.height > mediumResource.size.height)
{
searchPath.push_back(largeResource.directory); //mark HDR default
pDirector->setContentScaleFactor(largeResource.size.height/designResolutionSize.height); //handle scaling because of different between our programming-design-resolution and artist-design-canvase-resolution
}
else ...
I just started with Cocos2D-x after some years using Cocos2d-iPhone/swift/spritebuilder.
What I notice is that the coordinate system in X seems not to use the POINT system common since iOS development. Ie a box of 10x10 points used to be 10x10 pixels on 1x devices, 20x20 pixels on 2x devices and so on.
So my question is, does cocos2d-x only deal with pixels? How do we address this in code - because we used to be able to put a sprite at say 50x20 and it would end up in the right spot on any device regardless of resolution. Not possible in cocos2d-x? I have 3.5.
What would be related is this document, however it says that it is outdated. Is there a newer document anywhere? I really don't find anything else. http://www.cocos2d-x.org/wiki/Multi_resolution_support
You can look into using different asset folders for various resolution sizes. So you might have "/sd/" for < 480 height, "/hd/" for < 800 height, and "/ipadhd/" for others.
FileUtils::getInstance()->setSearchResolutionsOrder(...)
You can also change the content scale factor yourself in the AppController.mm using:
// should behave as if all art is #1x device
Director::getInstance()->setContentScaleFactor(1.0);
// should behave as if all art is #2x device
Director::getInstance()->setContentScaleFactor(2.0);
// should behave as if all art is #4x
Director::getInstance()->setContentScaleFactor(4.0);
This hasn't been updated yet, but still has some info:
http://www.cocos2d-x.org/wiki/Multi_resolution_support
In cocos2d-x, there is the the concept of "Design Resolution Size", which lets you pick the appropriate asset, depending on the size of the screen, and you can apply the appropriate content scaling factor.
Here is the problem:
I draw a 2d Sin Curve by passing in a set of vertices. These vertices are computed for a screen of 480x320.
What happens when I run it on a device which has a resolution of 1920x1200, even though the design resolution is set to 480x320 ? Do I have to recompute the vertices so that the same number of crests / troughs are seen on the higher resolution device, or is there some way to do this without extra computation ?
I don't have any more devices to test this, so I don't know how to figure this out.
EDIT: I now use cocos2d-x v3.
Anything drawn directly/solely with OpenGL will bypass/ignore any and all cocos2d internal settings and code paths, such as design resolution.
You can always use a simulator to test your resolution-specific code. For iOS the simulator comes with Xcode, for Android use the Emulator.
After purchasing and testing this on a number of devices with cocos2d-x v3, I find that scaling is handled automatically. Regardless of the resolution of the actual device, my openGl draw commands seem to result in the same output on all devices. It appears that cocos2d-x does something internally, so things looks the same on all devices.
I have strange problem in cocos2d v3, probably some misconfiguration which I was unable to find in google.
I'm adding background for iphone5 which is 640X1136
CCSprite *background = [CCSprite spriteWithImageNamed:#"background_iphone5.png"];
background.positionType = CCPositionTypeNormalized;
background.position = ccp(0.5f, 0.5f);
[self addChild:background];
but it is scaled up about 2x times so doesn't fits the screen. Same image worked perfectly in cocos2d v2
Please help
Cocos2d, like UIKits #2x uses suffixes to differentiate images intended for different screen sizes and resolutions.
These are the ones used by Cocos2d :
ipad
ipadhd
hd
iphone5hd
So you would have to add the appropriate image for your display with the suffix into your bundle like background_iphone5.png.
In your use case Cocos2d is resizing your non-retina image to a retina size (2x height, 2x width).
For consistency reasons this is a desired behaviour.
Consider the case of somebody not non-retina resources exclusively: all the sprites would be 2 times smaller on retina displays, which would probably get your game logics out of whack.
I highly suggest using SpriteBuiler because all this resizing and naming behaviour is integrated into the tool and works seamlessly. You only create retina ipad resolution images and it resizes them for you automatically.
The problem is, Cocos seems to think retina devices are the same resolution as standard devices. If you draw a sprite at 768,1024 on the ipad, it will put it at the upper right corner. If you draw a sprite at 768,1024 on the retina ipad, content scaling makes it so it also puts it in the upper right corner. Yet if you draw a sprite on the retina iphone 5 at 640,1136 it isn't in the upper right corner, its off the screen by 2x the distance. In order to put it in the corner you have to draw it at 320,568 because of the content scaling.
I do have a Default-568h#2x.png image, and I am on version 2.1.
My question is: Is there a way to get Cocos2d to make it so that drawing a sprite at 640,1136 on an iPhone5 will result in the sprite being in the upper right corner?
Is it possible to set up a cocos2d custom GL projection and set winSizeInPoints to equal winSizeInPixels and content scale 1.0 so that you can use the iPhone 4/5's full native resolution instead of using the half-size coordinates of older iPhones.
You can easily do this by changing the iPad suffix to use "-hd" via CCFileUtils. That way iPad devices will load the regular -hd assets for Retina iPhones.
Update regarding comments:
The positions on devices is measured in points, not pixels. So a non-retina iPad and a retina iPad both have a point resolution of 1024x768. This is great exactly because it makes adapting to screens with different pixel densities a no-brainer. This also works on the iPhone devices.
My suspicion is that you simply haven't added the Default-568h#2x.png launch image to your project yet, which may cause the widescreen devices to be treated differently.
And specifically on older cocos2d versions dated before iPhone 5 there's a bug that will treat the iPhone 5 as a non-Retina device, proper default image or not.
Yes You can share, easy way to do this is put all common sprite in sprite sheet and in runtime check if iPad, if yes then load iPhone HD sheet. We did this in many project and worked.
if(IS_IPAD)
{
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"GameSpriteSheet-hd.plist"];
}
else
{
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"GameSpriteSheet.plist"];
}
For background image, good to have separate iPad image, if scaling not look bad then you can scale image at runtime.
As far as I can understand what you are trying to do, the following approach should work:
call [director enableRetinaDisplay:NO] when setting up your CCDirector;
hack or override the following methods in CCDirector's so that winSizeInPixels is defines as the full screen resolution:
a. setContentScaleFactor:;
b. reshapeProjection:;
c. setView:;
Step 1 will make sure that no scaling factor is ever applied when rendering sprites or doing calculations; Step 2 will ensure that the full screen resolution is used whenever required (e.g., when defining the projection, but likely elsewhere as well).
About Step 2, you will notice that all listed methods show a statement like this:
winSizeInPixels_ = CGSizeMake( winSizeInPoints_.width * __ccContentScaleFactor, winSizeInPoints_.height * __ccContentScaleFactor );
__ccContentScaleFactor is made equal to 1 by step 1, and you should leave it like that; you could, e.g. customise winSizeInPixels calculation to your aim, like this:
if (<IPHONE_4INCHES>)
winSizeInPixels_ = CGSizeMake( winSizeInPoints_.width * 2, winSizeInPoints_.height * 2 );
else
winSizeInPixels_ = CGSizeMake( winSizeInPoints_.width * __ccContentScaleFactor, winSizeInPoints_.height * __ccContentScaleFactor );
Defining a custom projection would unfortunately not work because winSizeInPixels is always calculated based on __ccContentScaleFactor; but, __ccContentScaleFactor is also used everywhere in Cocos2D to position/size sprites and the likes.
A final note on implementation, you could hack this changes into the existing CCDirectorIOS class or you could derive from it your own MYCCDirectorIOS and override the methods there.
Hope it helps.