I'm using Cocos2D 2.1 and this app is planned to be iPad only retina and non-retina. When I use spriteWithFile, and specify the filename without the -hd suffix, Cocos2D finds the image with the -hd suffix and uses it, but it displays in standard definition, meaning it doesn't scale down so it's displaying as a retina image.
In my delegate's - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method, I have the following:
CCGLView *glView = [CCGLView viewWithFrame:[window_ bounds]
pixelFormat:kEAGLColorFormatRGBA8
depthFormat:GL_DEPTH24_STENCIL8_OES
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
[glView setMultipleTouchEnabled:YES];
director_ = (CCDirectorIOS*) [CCDirector sharedDirector];
[director_ setDisplayStats:YES];
[director_ setAnimationInterval:1.0/60];
// attach the openglView to the director
[director_ setView:glView];
// 2D projection
[director_ setProjection:kCCDirectorProjection2D];
[director_ enableRetinaDisplay:YES];
// // Enables High Res mode (Retina Display) on iPhone 4 and maintains low res on all other devices
if( ! [director_ enableRetinaDisplay:NO] )
CCLOG(#"Retina Display Not supported");
// If the 1st suffix is not found and if fallback is enabled then fallback suffixes are going to searched. If none is found, it will try with the name without suffix.
CCFileUtils *sharedFileUtils = [CCFileUtils sharedFileUtils];
[sharedFileUtils setEnableFallbackSuffixes:NO]; // Default: NO. No fallback suffixes are going to be used
[sharedFileUtils setiPadRetinaDisplaySuffix:#"-hd"];
glView.opaque = NO;
glClearColor(0.0f,0.0f,0.0f,0.0f);
//glClear(GL_COLOR_BUFFER_BIT);
// Assume that PVR images have premultiplied alpha
[CCTexture2D PVRImagesHavePremultipliedAlpha:YES];
When I add the sprite using spriteWithFile (instead of using a sprite sheet because it's only one image) I have the following code:
movingTileGroup.handleSprite1 = [CCSprite spriteWithFile:#"draggableTileGroupHandle.png"];
movingTileGroup.handleSprite1.position = ccp(x,y);
[self.theMap addChild:movingTileGroup.handleSprite1 z:13];
Update: I see when -(BOOL) enableRetinaDisplay:(BOOL)enabled is called, none of the if statements return true. Could it have to do with a scale factor setting?
-(BOOL) enableRetinaDisplay:(BOOL)enabled
{
NSLog(#"enableRetinaDisplay called");
// Already enabled ?
if( enabled && __ccContentScaleFactor == 2 ){
NSLog(#"enabled && __ccContentScaleFactor == 2 ");
return YES;
}
// Already disabled
if( ! enabled && __ccContentScaleFactor == 1 ){
NSLog(#"! enabled && __ccContentScaleFactor == 1 ");
return YES;
}
// setContentScaleFactor is not supported
if (! [__view respondsToSelector:#selector(setContentScaleFactor:)]){
NSLog(#"setContentScaleFactor is not supported");
return NO;
}
// SD device
if ([[UIScreen mainScreen] scale] == 1.0){
NSLog(#"SD device");
return NO;
}
float newScale = enabled ? 2 : 1;
[self setContentScaleFactor:newScale];
// Load Hi-Res FPS label
[[CCFileUtils sharedFileUtils] buildSearchResolutionsOrder];
[self createStatsLabel];
return YES;
}
I am assuming you are using Spritebuilder to generate sprites , if that is so you need to specify the default size of the image in the spritebuilder software, this can be done by clicking on the image which is showing the problem and then on the left sidebar or panel select the image size as "default" and it will automatically scale to the required size...
If this doesn't solves your problem, Do let me know... regards...
Related
I'm working on a game which should have a constant height(480.0)
and because so I wrote that code below..
what's wrong with it is that I have sprite sheets power of 2s
for sd here're normal images, for hd - double size and for iPad retina - 4 times bigger;
so in this case when I draw my sprites from scene images are not correctly drawn..
And I guess that's because CCSpriteFrame is using CC_ContentScaleFactor() to calculate frame of a image and it cut's wrong frame..
does anybody has any idea how to solve it? :?
CCSize designResolutionSize = CCSize(320,480);
CCDirector* pDirector = CCDirector::sharedDirector();
CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
pDirector->setOpenGLView(pEGLView);
pEGLView->setDesignResolutionSize(designResolutionSize.width,
designResolutionSize.height,
kResolutionFixedHeight);
CCSize size = CCEGLView::sharedOpenGLView()->getFrameSize();
std::vector<std::string> res;
if(size.width >= 2048 || size.height >= 2048){
res.push_back("ipadhd");
}
else if(size.width >= 960 || size.height >= 960){
res.push_back("hd");
}
else {
res.push_back("sd");
}
CCFileUtils::sharedFileUtils()->setSearchPaths(res);
CCDirector::sharedDirector()->setContentScaleFactor(size.height / designResolutionSize.height);
Thanks, George..
Hello! I am running the most basic Hello World app using Cocos2d, literally unmodified from the most basic cocos2d template in Xcode.
When I start the simulator the launch image for iPhone 5 automatically loads - however after a few seconds the launch image switches to the default#2x for iPhone 4, so there are two small back stripes of unused space on either side of the launch image.
Why is this so? And how can I make it so that the launch image doesn't automatically switch to smaller version for iPhone 4 after a few seconds?
Thanks
In IntroLayer.mm add this code:
CCSprite *background;
if( IS_IPAD)
{
if(IS_RETINA)
background = [CCSprite spriteWithFile:#"Default-Portrait#2x~ipad.png"];
else
background = [CCSprite spriteWithFile:#"Default-Portrait~ipad.png"];
}
else
{
if(IS_IPHONE5)
background = [CCSprite spriteWithFile:#"Default-568h#2x.png"];
else
{
if(IS_RETINA)
background = [CCSprite spriteWithFile:#"Default#2x.png"];
else
background = [CCSprite spriteWithFile:#"Default.png"];
}
}
Used Macro:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0f)
#define IS_RETINA ([[UIScreen mainScreen] respondsToSelector:#selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))
Globally my game supports two orientations: landscape right and landscape left
In one subscreen (inheriting CCLayer) I need to lock the current orientation so that ... the current orientation is locked...
When the user pops back to another screen (CCLayer), orientation should work freely again.
I did it like this:
Edit AppDelegate.h, add a mask for locking orientation:
#interface MyNavigationController : UINavigationController <CCDirectorDelegate>
#property UIInterfaceOrientationMask lockedToOrientation;
#end
In AppDelegate.m, synthesize the mask, and replace two functions:
#synthesize lockedToOrientation; // assign
-(NSUInteger)supportedInterfaceOrientations {
if (!self.lockedToOrientation) {
// iPhone only
if( [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone )
return UIInterfaceOrientationMaskLandscape;
// iPad only
return UIInterfaceOrientationMaskLandscape;
}
else {
return self.lockedToOrientation;
}
}
// Supported orientations. Customize it for your own needs
// Only valid on iOS 4 / 5. NOT VALID for iOS 6.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (!self.lockedToOrientation) {
// iPhone only
if( [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone )
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
// iPad only
// iPhone only
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
else {
// I don't need to change this at this point
return NO;
}
}
Then whenever I need to lock interface to a certain orientation, I access navController in the appdelegate. Check its interfaceOrientation property and set locked mask accordingly
AppController* appdelegate = (AppController*)[UIApplication sharedApplication].delegate;
const UIDeviceOrientation ORIENTATION = appdelegate.navController.interfaceOrientation;
appdelegate.navController.lockedToOrientation = ORIENTATION == UIInterfaceOrientationLandscapeLeft ? UIInterfaceOrientationMaskLandscapeLeft : UIInterfaceOrientationMaskLandscapeRight;
In dealloc or whenever I wanna remove the lock, I do this:
AppController* appdelegate = (AppController*)[UIApplication sharedApplication].delegate;
appdelegate.navController.lockedToOrientation = 0;
I'm implementing Game Kit in a cocos2d game project.
The game is landscape orientation only. And so should gamekit also be.
When I present the gamekit modal viewcontroller for matchmaking, it displays in landscape. But the underlying cocos2d CCLayer becomes portrait.
The rootViewContollers orientation code looks like this:
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
//
// There are 2 ways to support auto-rotation:
// - The OpenGL / cocos2d way
// - Faster, but doesn't rotate the UIKit objects
// - The ViewController way
// - A bit slower, but the UiKit objects are placed in the right place
//
#if GAME_AUTOROTATION==kGameAutorotationNone
//
// EAGLView won't be autorotated.
// Since this method should return YES in at least 1 orientation,
// we return YES only in the Portrait orientation
//
return ( interfaceOrientation == UIInterfaceOrientationPortrait );
#elif GAME_AUTOROTATION==kGameAutorotationCCDirector
//
// EAGLView will be rotated by cocos2d
//
// Sample: Autorotate only in landscape mode
//
if( interfaceOrientation == UIInterfaceOrientationLandscapeLeft ) {
[[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeRight];
} else if( interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
[[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeLeft];
}
// Since this method should return YES in at least 1 orientation,
// we return YES only in the Portrait orientation
return ( UIInterfaceOrientationIsLandscape(interfaceOrientation) );
#elif GAME_AUTOROTATION == kGameAutorotationUIViewController
//
// EAGLView will be rotated by the UIViewController
//
// Sample: Autorotate only in landscpe mode
//
// return YES for the supported orientations
return ( UIInterfaceOrientationIsLandscape( interfaceOrientation ) );
#else
#error Unknown value in GAME_AUTOROTATION
#endif // GAME_AUTOROTATION
// Shold not happen
return NO;
}
It makes no difference if I define GAME_AUTOROTATION to kGameAutorotationUIViewController or kGameAutorotationCCDirector or kGameAutorotationNone
So I believe I have found a fix.
In my AppDelegate I made these changes:
//[window addSubview: viewController.view];
[window setRootViewController:viewController];
Then orientation worked perfectly on iOS6, but on iOS versions prior to iOS6 the width and height of the window size was reversed, and caused issues for the game. I solved that by adding a blank scene before running my normal scene, because the reverse size was fixed by itself when pushing a new scene. From the blank scene I ran [[CCDirector sharedDirector] replaceWithScene:[Game scene]]; after a delay, and it works now.
I'm using the default cocos2d template with slight modification to the base code.
My game is played on left or right only- no portrait.
When the game launches, it starts right, then flips upside-down, then flips right again.
I looked through several posts on the issue and cannot seem to put my finger on what's making the interface flip back and forth without the device being moved. Appreciate any help!
I have the following related code:
RootViewController.m:
#if GAME_AUTOROTATION == kGameAutorotationUIViewController
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGRect rect = CGRectZero;
if(toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
rect = screenRect;
else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
rect.size = CGSizeMake( screenRect.size.height, screenRect.size.width );
CCDirector *director = [CCDirector sharedDirector];
EAGLView *glView = [director openGLView];
float contentScaleFactor = [director contentScaleFactor];
if( contentScaleFactor != 1 ) {
rect.size.width *= contentScaleFactor;
rect.size.height *= contentScaleFactor;
}
glView.frame = rect;
}
#endif
AppDelegate:
#if GAME_AUTOROTATION == kGameAutorotationUIViewController
[director setDeviceOrientation:kCCDeviceOrientationPortrait];
#else
[director setDeviceOrientation:kCCDeviceOrientationLandscapeRight];
#endif
GameConfig.h:
#define kGameAutorotationNone 0
#define kGameAutorotationCCDirector 1
#define kGameAutorotationUIViewController 2
#if defined(__ARM_NEON__) || TARGET_IPHONE_SIMULATOR
#define GAME_AUTOROTATION kGameAutorotationUIViewController
#elif __arm__
#define GAME_AUTOROTATION kGameAutorotationNone
I had the same problem today, it appeared to be down to the order of supported orientations in my application plist. The app would launch in Landscape Left, flip to right, then flip to left again really quickly.
I went into my project properties in the "Summary" tab (where you configure supported orientations, the app icons, launch images, etc) and deselected all the supported orientations.
I then ticked them again in order (Landscape Right, Landscape Left) - and verified in the "Info" tab that they were in this order in the array, under the "Supported Interface Orientations" section.
Item 0 - Landscape (right home button)
Item 1 - Landscape (left home button)
Not had the problem since, hope this helps.