Simple iPad Support (here's how)

Forums Programming cocos2d support (graphics engine) Simple iPad Support (here's how)

This topic contains 28 replies, has 7 voices, and was last updated by  ayt 2 years, 10 months ago.

Viewing 25 posts - 1 through 25 (of 29 total)
Author Posts
Author Posts
March 7, 2011 at 5:59 am #228420

akasurreal
Participant
@akasurreal

Ok.. who do I have to pay or bribe to get the following possible for a super easy iPad port? I know many of you would also love to have this.

These are the things that need to be done or hacked into Cocos but I am not sure how to hack it myself.

1) Use my existing Retina (-hd) graphics with iPad

2) Use Retina Points on iPad

3) Offset everything including points by 32×64 (landscape) so game appears and works centered on screen

4) Draw a border around image

Done! You now have a fully functional iPad game! This is exactly what we did for our last game release “Mummys Treasure”. It was a huge pain in the a** though because we did it manually. Users have not complained at having this border, in fact iPad is our best selling version right now!

Even better would be to offer some scaling options to either fill screen or letterbox and translate points accordingly, but for now I would take some simple hacks. Thanks for any help!

P.S. I did try a couple hacks I found on here and they either didn’t work and/or didn’t address the point translation.

March 7, 2011 at 4:07 pm #315001

cocos
Participant
@cocos

Hi @akasurreal! Your post confuses me.

Simple iPad Support (here’s how)

Are you planing to post some tips and solutions for community?

March 8, 2011 at 12:12 am #315002

akasurreal
Participant
@akasurreal

I am trying to help the community by getting people to talk about this and I proposed a solution but need help on implementing it. Was hoping for some more action though!

March 8, 2011 at 1:16 am #315003

FogleBird
Participant
@foglebird

I had this exact idea just the other day. It’d be cool if the border could be some graphic and not just black, as an option.

What was your approach in implementing it manually?

March 8, 2011 at 11:10 pm #315004

akasurreal
Participant
@akasurreal

@FogleBird, Basically I just had to offset all my coordinates by 32×64 manually in a bunch of places, and then in my touch handling, also offset as well. Then I created a border graphic I drew. I wasn’t using Cocos2D though so there was no built in point translation for Retina; I was already doing that manually as well. I would like to find a solution that doesn’t require me to do a ton of manual work.

@Riq / Cocos2D Devs? I feel like this solution I proposed wouldn’t be too hard to implement by the people that work on this project, but I guess I am not getting the attention of any of them? Anyone?? =)

March 8, 2011 at 11:36 pm #315005

TBBle
@tbble

Couldn’t you just give your CCScene a position offset by 32×64, to get all your layers and children centered?

In fact, thinking about it, all you’d need is a CCScene subclass which detects iPad mode and applies the offset and sets up a background border, and then your CCLayer needs to be adjusted to have its content size the size of an iPhone full screen rather than winSize as it is currently… The node-space translation should take care of everything else.

March 9, 2011 at 1:38 am #315006

akasurreal
Participant
@akasurreal

@TBBIe hmm that sounds worth exploring for the offset and border, but how do you get the iPad to use retina assets and do retina point translation? I did not have any luck trying to force that on with the hacks I found.

March 9, 2011 at 2:56 am #315007

TBBle
@tbble

Wouldn’t simply forcing contentScale to 2 and then resetting the glView bounds and scale back to scale 1 work? Then your cocos2d points are 4 pixels each, but your UIKit scale is still 1 point to 1 pixel so it won’t try and double your 1024×768 glView out to 2048×1536.

Something like that, anyway. I’m just speculating. I’d rather either code specifically for the iPad, loading -hd spritesheets for those assets I want to be twice as large physically as on the iPhone, or investigate the ipad2x branch from a while ago which lets you use retina-scale assets on a iPhone app in 2x mode on an iPad.

March 9, 2011 at 3:17 am #315008

akasurreal
Participant
@akasurreal

I dont want to do the 2x mode thing because then its not an actual iPad app and not listed as such on the App Store. WIll try what you said when I get a chance, but I suspect it may be more than that.

March 9, 2011 at 5:05 am #315009

TBBle
@tbble

Then I’d do what my first suggestion was. In iPad mode, load the -hd version of certain assets. Remember the iPad’s dot-pitch is the same as a non-retina iPhone, and you may want some of your UI elements to be the same _physical_ size on screen, so loading the -hd versions of those may not be what you want.

At least that’s my approach to the issue:

The iPad is not duplo to the iPhone’s lego. The iPad doesn’t make your fingers bigger. So don’t double the size of your buttons. ^_^ I don’t even double the size of my text. The only things I grow are things that’re full-screen relative rather than user-relative. A little bit of shell scripting around TexturePacker means I only have to care about the difference in a couple of places.

March 9, 2011 at 5:12 am #315010

akasurreal
Participant
@akasurreal

Well as I stated in my original post, for our last game Mummys Treasure, we took the exact Retina assets and used them on the iPad with a border and it is our best selling version of the game. Didn’t bother resizing assets or anything and I think its just fine. Maybe for some projects it would be a bigger issue.

March 9, 2011 at 8:27 am #315011

Abica
Participant
@abica

Ok, maybe this isn’t the cleanest way, but I really needed the -ipad suffixes for an app I’m doing and needed separate assets for ipad since although the layout of my game may remain the same visually there is a lot more room for detail.

I searched everywhere for this and found that it’s not supported yet, but also found that it’s super easy to add. I simply changed ccRemoveHDSuffixFromFile and getDoubleResolutionImage: in CCFileUtils.m to look like the following:

NSString *ccRemoveHDSuffixFromFile( NSString *path )
{
#if CC_IS_RETINA_DISPLAY_SUPPORTED

if( CC_CONTENT_SCALE_FACTOR() == 2 ) {

NSString *name = [path lastPathComponent];

// check if path already has the suffix.
if( [name rangeOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {

CCLOG(@"cocos2d: Filename(%@) contains %@ suffix. Removing it. See cocos2d issue #1040", path, CC_RETINA_DISPLAY_FILENAME_SUFFIX);

NSString *newLastname = [name stringByReplacingOccurrencesOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX withString:@""];

NSString *pathWithoutLastname = [path stringByDeletingLastPathComponent];
return [pathWithoutLastname stringByAppendingPathComponent:newLastname];
}
} else if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
NSString *name = [path lastPathComponent];

// check if path already has the suffix.
if( [name rangeOfString:CC_IPAD_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {

CCLOG(@"cocos2d: Filename(%@) contains %@ suffix. Removing it. See cocos2d issue #1040", path, CC_IPAD_DISPLAY_FILENAME_SUFFIX);

NSString *newLastname = [name stringByReplacingOccurrencesOfString:CC_IPAD_DISPLAY_FILENAME_SUFFIX withString:@""];

NSString *pathWithoutLastname = [path stringByDeletingLastPathComponent];
return [pathWithoutLastname stringByAppendingPathComponent:newLastname];
}

}

#endif // CC_IS_RETINA_DISPLAY_SUPPORTED

return path;

}

and

+(NSString*) getDoubleResolutionImage:(NSString*)path
{
#if CC_IS_RETINA_DISPLAY_SUPPORTED

if( CC_CONTENT_SCALE_FACTOR() == 2 ) {

NSString *pathWithoutExtension = [path stringByDeletingPathExtension];
NSString *name = [pathWithoutExtension lastPathComponent];

// check if path already has the suffix.
if( [name rangeOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {

CCLOG(@"cocos2d: WARNING Filename(%@) already has the suffix %@. Using it.", name, CC_RETINA_DISPLAY_FILENAME_SUFFIX);
return path;
}

NSString *extension = [path pathExtension];

if( [extension isEqualToString:@"ccz"] || [extension isEqualToString:@"gz"] )
{
// All ccz / gz files should be in the format filename.xxx.ccz
// so we need to pull off the .xxx part of the extension as well
extension = [NSString stringWithFormat:@"%@.%@", [pathWithoutExtension pathExtension], extension];
pathWithoutExtension = [pathWithoutExtension stringByDeletingPathExtension];
}

NSString *retinaName = [pathWithoutExtension stringByAppendingString:CC_RETINA_DISPLAY_FILENAME_SUFFIX];
retinaName = [retinaName stringByAppendingPathExtension:extension];

if( [__localFileManager fileExistsAtPath:retinaName] )
return retinaName;

CCLOG(@"cocos2d: CCFileUtils: Warning HD file not found: %@", [retinaName lastPathComponent] );
} else if( (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)) {

NSString *pathWithoutExtension = [path stringByDeletingPathExtension];
NSString *name = [pathWithoutExtension lastPathComponent];

// check if path already has the suffix.
if( [name rangeOfString:CC_IPAD_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {

CCLOG(@"cocos2d: WARNING Filename(%@) already has the suffix %@. Using it.", name, CC_IPAD_DISPLAY_FILENAME_SUFFIX);
return path;
}

NSString *extension = [path pathExtension];

if( [extension isEqualToString:@"ccz"] || [extension isEqualToString:@"gz"] )
{
// All ccz / gz files should be in the format filename.xxx.ccz
// so we need to pull off the .xxx part of the extension as well
extension = [NSString stringWithFormat:@"%@.%@", [pathWithoutExtension pathExtension], extension];
pathWithoutExtension = [pathWithoutExtension stringByDeletingPathExtension];
}

NSString *retinaName = [pathWithoutExtension stringByAppendingString:CC_IPAD_DISPLAY_FILENAME_SUFFIX];
retinaName = [retinaName stringByAppendingPathExtension:extension];

if( [__localFileManager fileExistsAtPath:retinaName] )
return retinaName;

CCLOG(@"cocos2d: CCFileUtils: Warning HD file not found: %@", [retinaName lastPathComponent] );
}

#endif // CC_IS_RETINA_DISPLAY_SUPPORTED

return path;
}

and added the following constant under CC_RETINA_DISPLAY_FILENAME_SUFFIX in ccConfig.h:

#define CC_IPAD_DISPLAY_FILENAME_SUFFIX @"-ipad"

Because I hacked into the retina support, you need to enable retina display by calling [director enableRetinaDisplay:YES] in your delegate. Mine looks like this:

// globals.h
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_HD ([[CCDirector sharedDirector] contentScaleFactor] == 2.0f || [[UIScreen mainScreen] scale] == 2.0f)

// in app delegate
if( ! [director enableRetinaDisplay:(IS_IPAD || IS_HD)] ) {
CCLOG(@"Retina Display Not supported");
}

March 9, 2011 at 9:38 am #315012

akasurreal
Participant
@akasurreal

@abica, thanks for sharing. Can you show me what you did to your enableRetinaDisplay method to make it work? By default mine does not turn on Retina for an iPad, when I try to enable it. Does your method handle point translation?

March 10, 2011 at 3:54 am #315013

Abica
Participant
@abica

I haven’t found the point translation to be a problem since all of my positions look like sprite.position = ccp(WIDTH * 0.025, HEIGHT * 0.75) so everything tends to fit. There are a few places where I’m a few pixels off and I have macros to handle that. I made a little matrix to help me remember what the different devices look like when retina is enabled:

+

+
+
+
+
| device | scale | dim | suffix |
+
+
+
+
+
| 3G | 1 | 320x480 | n/a |
| 4G | 2 | 320x480 | -hd |
| iPad | 1 | 768x1024 | -ipad |
+
+
+
+
+

cocos scales the position for retina and leaves it alone for other devices.

I actually didn’t change enableRetinaDisplay: at all. I simply turn it on if this is a retina device or an ipad. If it’s retina then the -hd suffix is used and if it’s an ipad the -ipad suffix is used to load the graphics. Since I disable retina on non 4g/ipad devices none of the changes have any effect, but you could leave it enabled all of the time if you wanted. I wouldn’t for performance reasons. It’s worth noting that you must also have the non suffixed version of the graphics as well as the -hd or -ipad version if you choose to enable the retina support in cocos for ipad and 4g so you support all devices. It’s an all or nothing solution.

I made the ipad version of my app first and then turned it into a universal app late in the game. Initially my iphone version was a separate build forked from the ipad one. When I found out I had to support universal I upgraded from 0.99.2 to 0.99.5 and made the above changes.

You must have your project setup to target iPhone/iPad, you can do this by clicking on your project name under Targets in the groups and files pane of xcode and clicking Info, then go to build settings and search for targeted device family. Make sure this is set to iPhone/iPad.

You will need to create a new sprite atlas for each device if you are using those. Otherwise you may want to properly scale your graphics to the new aspect ratio so they don’t appear squashed. But using a % based layout handles most of the translation issues.

I’ve tested this on an ipad, 4g, 3gs and 2nd gen touch and it seems to work pretty well for my app.

As I said there were a sections where my game had a bunch of json levels using absolute positions for the ipad. In those cases I just scaled the coords down using my macros, which look like this:

#define IPHONE_X_SCALE 0.46875f
#define IPHONE_Y_SCALE 0.41666f

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_HD ([[CCDirector sharedDirector] contentScaleFactor] == 2.0f || [[UIScreen mainScreen] scale] == 2.0f)
#define SMALL_DEVICE !IS_IPAD
#define IF_SMALL_DEVICE(true_val,false_val) (SMALL_DEVICE ? true_val : false_val)
#define IF_HD_DEVICE(true_val,false_val) (IS_HD ? true_val : false_val)

#define DEVICE_X_SCALE IF_SD_DEVICE(IPHONE_X_SCALE, 1.0f)
#define DEVICE_Y_SCALE IF_SD_DEVICE(IPHONE_Y_SCALE, 1.0f)

#define SCALE_POSITION(x,y) ccp(x * DEVICE_X_SCALE, y * DEVICE_Y_SCALE)

March 10, 2011 at 7:02 am #315014

akasurreal
Participant
@akasurreal

I see, so you are doing your point translation inline in every CCP basically. That works but seems silly to me this is not built into the framework since the existing Retina support just needs to be extended a bit. I don’t have a need/desire to actually do “-ipad” specific graphics. I intend to use the -hd graphics for the iPad as well if you see the original post above. I just can’t seem to get that to work yet on the iPad though, but I haven’t spent a ton of time digging through the cocos code to see why it doesn’t.

The reason I ask about enable retina, is because from what I can tell, unless it detects that you are an iPhone4, it does nothing and just returns.

March 11, 2011 at 5:35 am #315015

Abica
Participant
@abica

Yeah, it does seem silly that it’s not supported but I had a very fast need for a solution and that one fit my need exactly since simply scaling up retina graphics or manually offsetting or dealing with some bar seems strange to me.

I only do that inline point translation for the json levels that were using absolute ipad positioning, so I need to perform a translation on them. Every other element in my game just uses relative positioning.

When you enable retina by default it will only use your -hd graphics for the 4g since it’s the only device that supports the retina display. If you want to simply use your -hd graphics for the ipad as well you can go into CCFileUtils.m and change every line that looks like:

if( CC_CONTENT_SCALE_FACTOR() == 2 ) {

to:

if (( CC_CONTENT_SCALE_FACTOR() == 2 ) || (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)) {

and then pass YES to enableRetinaDisplay: if you’re on an ipad or a 4g.

March 12, 2011 at 2:53 am #315016

akasurreal
Participant
@akasurreal

@abica what I really want it to do is do full cocos2d Retina mode that includes point translation, but on the iPad, but I have not been able to get that to work. I tried a hack to enable “-hd” graphics but that did not work correctly either, and did not enable point translation.

March 14, 2011 at 9:36 am #315017

PaulCentaur
@paulcentaur

I see, so you are doing your point translation inline in every CCP basically. That works but seems silly to me this is not built into the framework since the existing Retina support just needs to be extended a bit.

Basically the cocos2d framework does what iOS does, which is: handle pixel density (retina) but let the programmer decide how to handle point ratio and screen size differences.

If the framework did offer automatic translation it would be much like those translation macros above. But automatic translation of every element would be dumb. As TBBle said above, buttons don’t need to double in size on iPad. Even Abica isn’t using the same method for everything.

The top post contains an error which I think is affecting the debate: “2) Use Retina Points on iPad”. The whole point of points is that they are the same on retina and non-retina. There isn’t any point translation between retina and non-retina iPhone. What I think is meant instead is “double up points on iPad so that the points match the -hd pixels”.

You really need to know when to double up and when not to. For example, I have a simple shadow effect on a page title which is achieved by plonking some white text on top of some black text with 1 point offsets in X and Y. On iPad, the positioning and text size need to be “translated” but I don’t want a 2 point offset for my shadow. So I must keep control of point translation.

With iOS programming, we are lucky to only have 2 different point ratios that we *have* to worry about. It’s not like Android where one has to adjust for many different screen sizes, and as a result iPad and iPhone users have come to expect well laid out screens. I don’t see that it’s that great a hardship to take some care in laying out the iPad version – and in any event chasing some “automatic” solution may take just as long.

I’m working on a universal app where the iPad uses a mixture of -hd graphics and standard resolution images. This is achieved by a mixture of:

* use of a routine (where appropriate) that returns -hd graphics on iPad

* inline point doubling with offset specific to the current orientation

* inline point doubling with position relative to screen height & width

* straight inline point doubling (eg some text)

* variables with device & orientation specific positions / point sizes for certain elements

* some iPad specific graphics

* running a different scene when layout is very different (the Rules section)

This may not be “simple”, but it is straight-forward. I believe that this approach is more future proof. We may one day get an actual retina iPad, and I wouldn’t have to adjust very much. If I had instead pretended that the iPad was a retina device, I’d be in a right old mess.

March 14, 2011 at 10:55 pm #315018

akasurreal
Participant
@akasurreal

I appreciate your thoughts, but as usual on forums like this, instead of anyone helping me to do what I want, they tell me what I want to do is wrong =)

It may not be perfect for everyone, or work for everyone but on our last game, double the size of buttons as you put it, was not an issue whatsoever. In fact, many iPad users seem to like the oversized elements and felt it made the game easier to navigate for them. Again, I understand its not perfect for everyone, but I still believe there should be an easier way to use the Retina mode on an iPad and just allow the developer to place a border to fill in the gaps on the edges. In most cases, the iPad market is not worth the money to us to develop assets specifically for it, at least not yet.

March 17, 2011 at 12:27 am #315019

TBBle
@tbble

I appreciate your thoughts, but as usual on forums like this, instead of anyone helping me to do what I want, they tell me what I want to do is wrong =)

Well, we still haven’t heard back from how you went attempting to implement my suggestion for how to do what you want, so the discussion kinda naturally went into the discussion of what you want to do and why.

I’d be fine with a “treat the iPad as a retina display with larger CCLayers” #define option, by the way. I don’t think I’d use it myself, but it’s a pretty good idea. (Like the iPadHD idea, which’d be neat if we could get it working)

March 17, 2011 at 9:04 pm #315020

akasurreal
Participant
@akasurreal

Thanks, once I get closer to launch of current project and put some more time into the iPad solution and suggestions here, I will post more here.

March 18, 2011 at 11:48 pm #315021

akasurreal
Participant
@akasurreal

This person at this link did exactly what I am trying to do, but my attempts to duplicate are going nowhere. Would appreciate anyone’s help.

Read the user’s own solution in the reply to the answer:

http://stackoverflow.com/questions/5002970/create-a-framed-ipad-version-using-cocos2d

Here is what I have done to attempt to copy:

Added to CCDirectorIOS:setProjection

case kCCDirectorProjection2D:
..
..
glScalef(2, 2, 2);

Added to end of CCDirectorIOS:convertToGL

ret = ccpMult(ret, 0.5f);

And then in my Delegate applicationDidFinishLaunching

if( ! [director enableRetinaDisplay:YES] )
CCLOG(@"Retina Display Not supported");

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
[director setContentScaleFactor:2];
}

All I get is a black screen on the iPad though. This happens as soon as I set the contentscalefactor to 2, the other mods don’t make any difference. I am guessing the original poster did not fully explain other changes they made?

Any help appreciated on figuring this out and I am sure many others would like to try this approach, thanks!

March 21, 2011 at 6:20 pm #315022

akasurreal
Participant
@akasurreal

Bump

March 22, 2011 at 1:07 am #315023

TBBle
@tbble

Quick check, _are_ you using the 2D projection? Cocos2d defaults to the 3D projection…

March 22, 2011 at 2:31 am #315024

akasurreal
Participant
@akasurreal

Doh, that was definitely part of the problem, I forgot I switched back to 3D Projection. So now I don’t just have a black screen, but nothing is in the right place on the screen now. So I am still missing something. I know one thing based on reading his post that he somehow resized the EAGLVIEW too?

I want to create the iPad version by redefining the EAGLView so its boundary is (64, 32, 640, 960)

Viewing 25 posts - 1 through 25 (of 29 total)

You must be logged in to reply to this topic.