Why is my art displayed at 2x on screen? - image

I am creating a Universal App.
I have created my art in illustrator to fit properly on an iPhone screen, specifically at 640x1136 px. I exported PNGs and named myArt#2x.png and also a 50% version named myArt.png. The art is in an atlas folder.
I am creating sprite nodes a like this:
NSString * backgroundName=#"starField";
SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:backgroundName];
background.position = CGPointMake(screenWidth/2, screenHeight/2);
background.zPosition = LayerBackground;
[_worldNode addChild:background];
The problem is that when I run this in the simulator (iPhone 4 w/retina), the images are scaled up. I have to ousel xScale and yScale to bring it back to actual size.
Why? What am I doing wrong?
Thanks,
rich!

You need to set the size property of the SKNode I think. For example:
background.size = CGSizeMake(screenWidth, screenHeight);

Okay I think I solved it -
I don't start creating my content until viewWillLayoutSubviews had been called. The default SpritKit Template uses viewDidLoad, but I changed that to viewWillLayoutSubviews and everything looks fine now.
I think I was trying to create stuff before the view "sorted" itself out...
Not sure what the difference is but it worked.
-r

Related

SpriteKit unarchiveFromFile does not load textures from asset catalogues and atlases

I'm still new with SpriteKit, and wanted to see if I can construct a level using Xcode's SKS editor. When i added a couple of sprites with the "Spaceship.png" texture and built the template app, the textures don't load.
Here's a screenshot of the vanilla OSX Game template using Swift as the language, and adding a supplied "Spaceship.png" sprite. The texture shows fine:
And here's the result of building and running the app with only that modification to the template:
The debug console displays this warning message:
I tried to add an .atlas folder, and got the same result. the scene just displays the red X icon in place of the sprite. If the added sprites where just color sprites, they display fine. I had an app some time ago that I scrapped, where I used to load the SKScene and would manually add the sprite assets within to my SKScene sub-class, and it worked fine.
If, however, i moved the textures - "Spaceship.png" as an example - to the root of the project, i.e. not inside an asset catalogue or .atlas folder, the scene loads with the textures displaying fine.
Here's the texture added to the root of the project:
And this is the desired result:
I tried to manually add the loaded assets from the SKS file to the scene via enumerateChildNodesWithName(_,usingBlock) and I get the same result if the textures were not in the root of the project folder.
This is me trying to add the assets manually:
func applicationDidFinishLaunching(aNotification: NSNotification) {
/* Pick a size for the scene */
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
let sceneToBePresented = GameScene()
/* Set the scale mode to scale to fit the window */
sceneToBePresented.scaleMode = .AspectFill
sceneToBePresented.size = scene.size
/* Sprite Kit applies additional optimizations to improve rendering performance */
self.skView!.ignoresSiblingOrder = true
self.skView!.showsFPS = true
self.skView!.showsNodeCount = true
scene.enumerateChildNodesWithName("*") { node, stop in
sceneToBePresented.addChild(node.copy() as SKSpriteNode)
}
self.skView!.presentScene(sceneToBePresented)
}
}
I looked around SpriteKit classes - SKNode, SKScene, SKTexture, SKSPriteNode - for any clue about paths, caching, preloading, or anything but was unable to find a thing that could make this work.
I am running Xcode 6.1.1 and my target is 10.9, and the language I'm using is Swift, although the same behavior holds true using ObjC. Is this a feature or a bug? Anybody else running/ran into a similar situation ?
Thanks in advance for any help
[UPDATE]
Looks like this is not implemented yet - loading textures from asset catalogs - as this post in the dev forums discusses the same issue, and his solution is to rename the asset catalogues to be the same name as the texture. In essence, what I found out about having the image files in the root folder: How do you load sprite textures from Images.xcassets when using SKS scene file, although my earlier app which i managed to roll-back to a working state does load textures from .atlas'es, but i can't seem to do it with a clean template!!!
[Answering my own question here]
As far as I can tell, at this moment, loading texture from asset catalogues - Images.xcassets - while unarchiving or deserializing an SKScene file does not work on OSX based on my attempts and the devforumns post referenced above.
Loading of the textures from image atlases, however, works by forcing SKTexture to load the image. Forcing or 'touch'ing SKTexture can be done via the preloadWithCompletionHandler(_:) or preloadTextures(_:, withCompletionHandler:) methods, or simply by printing the description of the sprite's SKTexture as i have discovered.
For the benefit of anybody who might need further assistance, here is a code snippet that preloads the textures after unarchiving an SKS file:
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
for child in scene.children as [SKNode] {
if child is SKSpriteNode {
let sprite = child as SKSpriteNode
sprite.texture?.preloadWithCompletionHandler({ })
/* or even a simple debug log of the texture */
/* println(sprite.texture) */
}
}
/* Do your other stuff ... */
...
}
If I'm wrong please correct me. Until somebody does, or Apple fixes the discrepancy between SpriteKit's behavior between iOS and OSX, I will not be looking for another solution, and will follow Murphey's law:
If it works, don't fix it
Follow Salam Horani solution's, for Swift 2.x you dont have yet "unarchiveFromFile" so you can create scene like this:
if let gameScene = GameScene(fileNamed: "GameScene") {
// ...
}

Removing Glossy Effect on UITabBar

I know this is a common question but it's quite different in my case.
I want an image to be placed when the bar is active and I've done that successfully using these code under didFinishLoadingWithOptions method [[UITabBar appearance] setSelectionIndicatorImage:[UIImage imageNamed:#"tabbar-active.png"]];
And that's what my app looks like
Now I just want to remove that glossy effect, not the blue image on the bar
Thanks in advance!
After digging a little bit, I found the solution for the same. You simply need to create an UIImage object with empty image.
[yourTabbar setSelectionIndicatorImage:[[UIImage alloc] init]];
Thats it :)

Displaying landscape images from camera roll xcode

I'm pulling images from the camera roll to display in my app, and portrait taken pictures work just fine, but landscape images get all funky smushed together.
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
displayPhoto.image = image;
I've figured out how to check the length and width of the pictures themselves, and therefore can do an if else statement to only rotate landscape pictures... but trying to find working code to actually rotate the images is difficult. I found an answer here, but he's calling functions that don't exist, and clearly the code did not work for me :p. Any assistance would be greatly appreciated. Thanks.
u have to use
[displayPhoto setContentMode:UIViewContentModeScaleAspectFit];

Adding Custom Retina Image To TabBar In iOS5

I am trying unsuccessfully to get my custom retina images to display in my custom iOS5 TabBar.
I have 4 items in my TabBar, I have set the selected/unselected image to contact#2x.png which has a resolution of 160px x 75px. I figured 4 of these 160px width images would accommodate the 640px retina width nicely.
You can view my contact#2x.png here
https://lh4.googleusercontent.com/-afHulbEcxNE/TuPe-YIj91I/AAAAAAAAAII/lCojphAxF9w/s160/contact%2525402x.png
I have set all the items programtically as seen below.
UIImage *selectedContact = [UIImage imageNamed:#"contact#2x.png"];
UIImage *unselectedContact = [UIImage imageNamed:#"contact#2x.png"];
UITabBar *tabBar = self.tabBarController.tabBar;
UITabBarItem *item0 = [tabBar.items objectAtIndex:0];
UITabBarItem *item1 = [tabBar.items objectAtIndex:1];
UITabBarItem *item2 = [tabBar.items objectAtIndex:2];
UITabBarItem *item3 = [tabBar.items objectAtIndex:3];
[item0 setFinishedSelectedImage:selectedContact withFinishedUnselectedImage:unselectedContact];
[item1 setFinishedSelectedImage:selectedContact withFinishedUnselectedImage:unselectedContact];
[item2 setFinishedSelectedImage:selectedContact withFinishedUnselectedImage:unselectedContact];
[item3 setFinishedSelectedImage:selectedContact withFinishedUnselectedImage:unselectedContact];
At runtime I can see that the scale is set to 1
Why isn’t the 2 being picked up off the image suffix? The tab bar is huge, and isnt scaled.
Please see the simulator screenshot below…
https://lh5.googleusercontent.com/-A5oxZprlDhU/TuPfAlG_HQI/AAAAAAAAAIc/mIwHXOPZSrE/s735/simulator.png
My other retina images for my app icon and default icon are working.
Thoughts? I am driving myself nuts ☺ Thanks in advance.
JoePasq is wrong, he obviously is not up to date with the latest iOS5 appearance customisation API. Your problem could be that you specified the #2x in the filename, just pass "contact.png" to imagedNamed...
[UIImage imageNamed:# "contact.png"]
Have you looked at the documentation for customizing the appearance of UITabBar?
You should consult this tutorial by Ray Wenderlich about using the UIAppearance APIs.
His code is this:
UIImage *tabBackground = [[UIImage imageNamed:#"tab_bg"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UITabBar appearance] setBackgroundImage:tabBackground];
[[UITabBar appearance] setSelectionIndicatorImage: [UIImage imageNamed:#"tab_select_indicator"]];`
Note that the customization happens on the Tab bar, not the tab bar items—assuming it’s the same customization for each one.
As nbransby said you do not use #2x in the filename.
Prior unedited answer:
From the documentation:
The images displayed on the tab bar are derived from this image. If this image is too large to fit on the tab bar, it is scaled to fit. The size of an tab bar image is typically 30 x 30 points. The alpha values in the source image are used to create the unselected and selected images—opaque values are ignored.
Your icons should be 30x30 px for normal resolution and 60x60 px for retina resolution. They should also be a solid color, the tab bar adds the coloring.

colorWithPatternImage creates black grids in iphone 4

I have
UIView *topPart = [[UIView alloc] initWithFrame:CGRectMake(9, 0, 302, 318)];
topPart.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"pattern.png"]];
[someScroller addSubview:topPart];
[topPart release];
and I can see the pattern fine when I use a 3gs or the iphone simulator, but when I tested on an actual iPhone 4, I see the pattern images but there are black lines separating each pattern so it looks like a grid. I checked the pattern image and there is no black border or anything .
There was someone with a different problem but it may be the same solution
colorWithPatternImage with iPhone 4 Retina Display (image#2x.png)
but they suggested using the -(void)drawRect: method, only problem is i have no idea how to do that.
Thanks
I was experiencing the same issue and found it was due to my png being greyscale (not RGB)
To check if this is the case, just select the image in Xcode, show the Utilities sidebar (the one that appears from the right) and look at the Color Space.
To fix this you can use your favourite image editor, but for photoshop do this:
Open the greyscale image
Select all and copy
Create a new document (but this time make sure the colour space is RGB)
Paste
Hope it helps :)
I figured it out by combining the answers from these 2 posts
https://devforums.apple.com/message/259150#259150
How can I use CGContextDrawTiledImage to tile an image?
UIImage *thePattern= [self GetFineTiles:[UIImage imageNamed:#"Feedbackpattern.png"]];
theView.backgroundColor = [UIColor colorWithPatternImage:thePattern];
-(UIImage*)GetFineTiles:(UIImage*)badImage{
UIGraphicsBeginImageContext(badImage.size);
CGContextRef imageContext = UIGraphicsGetCurrentContext();
CGContextDrawTiledImage(imageContext, (CGRect){CGPointZero,badImage.size}, badImage.CGImage);
UIImage *goodPattern = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return goodPattern;
}
Hope this helps others

Resources