Alright, I recently started work on a pac-man style game using Tiled to quickly create my levels which is SUPER awesome. However I ran across a universal resolution issue… My Levels contain 3 layers. 2 tile layers: 1. for the walls and general tiles. 2. for the meta tile layers for collision detection. the last layer is an object layer consisting of a spawner for the character in the middle of the tmx map. I created 2 different .tmx maps for each resolution (HD “2048x1536” and SD “1024x768”) and added them to my resources. In my AppDelegate I set up the contentScaleFactor, the resource paths, and choose the FixedWidth policy and everything is going just swell. I write my code to add the map and “Whoosh” there it is working perfectly across the different devices. Here is where my story turns bad… I try to add my character to the scene by extracting the spawn point from the object layer into a CCDictionary. I then get the x and y values and set my CCSprite to this position. However when I run the program my sprite is nowhere to be found. This is due to the fact that my sprite is way off screen to the right… (200 px or so and who knows how high or whatever) My only explanation for this is that the graphical layers, and the maps themselves get scaled accordingly but the object layer’s positions do no get repositioned based upon this newly scaled map thus making the object layer do some really funny things like spawn your sprites on Mars or something. I found that if I take the values of x and y from the CCDictionary and divide them by the contentScaleFactor I get positioning very close to where it is supposed to be, however this is not a solution because it is not practical to constantly do that across every device every time an object is created or moves or replaced or set or whatever you want to do. Anyone have a solution for this???
Sprites are positioned based on points and not pixels.
My guess is that despite having multiple resolutions, you set the designResolutionSize (points) to the same thing (or close to it) and set the contentScaleFactor different for each resolution.
Points * contentScaleFactor = Pixels (at least usually)
However, when you created higher resolution Tiled maps, if you doubled the x and y coordinates, then those values are in pixels and NOT in points. This is why when you divide by the contentScaleFactor, you get roughly the correct position.
So just for clarification what you are saying is cocos2d uses points for positioning and Tiled uses pixels? So when I create an object on the object layer in Tiled it is being positioned based on pixels, so when I scale my resources the points and pixels don’t match up?
Also my DesignResolution is 480x360 so I get the visible size of the screen say an iPad (1024x768) and set the resource path to the SD folder and set the ContentScaleFactor to:
While using the FixedWidth Policy this gives me the desired fit on the screen. Don’t know if knowing that information helps just thought I would add it, but getting to the point… I need to figure out a way to have my objects at points not pixels or find a way to convert them?
Well I looked more into this and learned nothing new… On retina devices points are at a ratio of 1pt:2px and on a standard device it is a one to one ratio. I am supporting devices from the iPhone 4 and up so all retina based. So I guess my question now is should I position my sprites based on if the device is retina or not because in my head as long as the device is non-retina I don’t need to mess with the sprite positioning, the one to one ratio should allow for the sprite to be exactly where the object is. However my plan is to make some function that can convert the position based on the retina device:
I also found that adding the sprites as children of the map its self makes their position exact:
GameMap->addChild(Sprite, 1);
This puts it right where I need them. However I still think the fact that I have to create an entire function to convert something so simple as points and pixels is a bit ridiculous… If it were me creating the software I would make multiple formats to export to… such as the ability to create maps based on points vs pixels or whatever other measurement system your little heart desires! But what do I know I’m just a guy programming little app games in his free time while finishing school hahaha
For anyone looking for this solution. Since I had such a hard time finding anything on this subject matter that wasn’t complete garbage or useless information I will share my findings.
If you want to support a universal app using tmx maps you need to:
have multiple tmx maps in your respective resource folder, my case:
level1.tmx (tileSize 50x50) //SD
TileSet.png //SD
level1.tmx (tileSize 100x100) //HD
TileSet.png //HD
You MUST convert pixels to points!!! Use functions similar to these:
CCPoint pixelToPoint(CCPoint pixel){
//converts pixels to points for spawning your sprites
return ccpMult(pixel, CC_CONTENT_SCALE_FACTOR());
}
CCSize pixelToPointSize(CCSize pixelSize){
//converts tileSizes to points
return CCSizeMake(pixelSize.width/CC_CONTENT_SCALE_FACTOR(), pixelSize.height/CC_CONTENT_SCALE_FACTOR());
Well I thought I had the problem fixed… However when the SD (iPhone 4, 5 and iPad) tmx maps are used my sprite positions are right on but when the HD (iPad Mini or iPad Retina based) tmx maps are used my sprite is still off slightly… guess this topic is still open for discussion…