What's the best way to convert iPad app to handle both view modes? - objective-c

I have an existing iPad app (XCode 4.6, iOS 6.2, ARC and Storyboards). It is currently in the App Store in Portrait mode only; I have had several requests for landscape mode. Unfortunately, all of the lines, etc are drawn using CG methods, controlled mathematically. This is what it looks like in portrait mode:
and this is what it looks like in landscape mode:
My question is: where can I find some good docs that will give me the basic steps I need to convert this app for both modes, knowing that the drawing is controlled mathematically?

If it is controlled mathematically, the best way is to refer all coordinates to the dimensions of the parent view, specifically to the property self.view.bounds that changes with the rotation of the device.
Then you have to redraw the interface when the orientation has been changed. A good way to do it is inside the method:
-(void)viewWillLayoutSubviews
If did some custom views in the past with CG methods and the best way is to refer everything to the bounds. In that way when you change the screen size, either by rotating or by using it on the iPhone it works without modifications.
update
Imagine that you have a point at (76.8, 512.0) this is precisely in an iPad and portrait orientation, a 10% of the width and a 50% of the height.
So for every pair of coordinates instead of using them with absolute numbers you have to replace them by fractions of the dimensions of the parent view:
// old drawing method
CGPoint oldPoint = CGPointMake(76.8, 512.0);
// new drawing method
CGFloat W = self.view.bounds.size.width;
CGFloat H = self.view.bounds.size.height;
CGPoint newPoint = CGPointMake(0.1 * W, 0.5 * H) // 76.8 = 0.1 * 768; 512 = 0.5 * 1024
In this second case; when you change the orientation so will the bounds change and the coordinate will get new values, but the proprotion will be the same as in the other orientation, 10% in horizontal and 50% in vertical.
You get the idea.

Related

How do you scale images/sprites properly in Godot?

I'm trying to create a 2D cross-platform game (primarily for android & ios in portrait mode, however compatibility with a tablet/desktop would be a bonus) and I'm trying to wrap my head around scaling of my sprites.
I've looked online, and I've ended up setting the following in my Project Settings > Stretch
'Mode' : 2D
'Aspect' : keep-height.
According to https://www.mydevice.io the viewport of my android phone is 360 x 640px (the standard 16:9 ratio for mobiles). But obviously phones/tablet screens come in all sorts of dimensions.
If I wanted to create a sprite with a width exactly 1/3rd of that of my screen/viewport, how should I go about doing this? Should I be creating multiple sprites of various dimensions (in say, GraphicsGale) to account for different screen sizes, or should I be purely doing this scaling in Godot?
I know there's a 'scale' property in Godot, but I can't see a way of setting my image width and height via pixels or by a percentage of the viewport.
Have you tried setting the sprite size depending on the viewport height and width ?
$sprite.size.x = get_viewport().size.x * 0.33
$sprite.size.y = get_viewport().size.y * 0.33
You can check out this reddit post if this is not working.

Scaling for Different iPhone Screens in Sprite Kit

I am creating an iPhone game in sprite kit. After weeks of research, I am still having trouble understanding how to properly size and implement sprites for each screen size.
I understand that these suffixes determine which image to use (depending on the aspect ratio of the screen)
#2x - 4s,5,6
#3x - 6+
I have read and tooled with different scaling modes in my view controller but had no luck and difficulty understanding them.
If I provide a background of 750x1136 (pixels) as the #2x, it will perfectly fit the iphone 6 but will be too big for the iphone 5. If scaling is the answer, how would "sprite kit" know I provided an image for the iphone 5 that I want scaled up for the 6, or vice versa? Is this a build setting? Same for characters, I need iphone 6 sprites to be proportionally bigger than the iphone 5 sprites.
How would I most appropriately size and scale sprites for the different devices? (easier to discuss in terms of the backgrounds that should be the exact size of the screen)
I am expecting to create one set of sprites for each aspect ratio using the resolution of the biggest screen size. Ex. #2x designed for iPhone 6 and scaled down for the 5 and 4s.
The 3x, 2x and normal images are not really intended to be manipulated that way. The three images should be essentially the same image with the 3x having exactly 3 times the pixel dimensions of the normal, the 2x having double dimensions etc.
If you need to scale the scene to better fit the format of a particular device, you may need to scale that when you create the scene, the way Apple sample code does:
var viewSize = self.view.bounds.size
// On iPhone/iPod touch we want to see a similar amount of the scene as on iPad.
// So, we set the size of the scene to be double the size of the view, which is
// the whole screen, 3.5- or 4- inch. This effectively scales the scene to 50%.
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
viewSize.height *= 2
viewSize.width *= 2
}

Optimize QuartzCore Animation with Shadows and Rasterization

Within my iOS app, I have a uiview that needs to be animated, transformed with gestures, shaded (using quartzcore shadows), and edited. When I perform animations and gestures on this UIView it is extremely "laggy". The animations aren't very "laggy" on the iPhone, however when using the iPad the animations become almost unresponsive (to the point where it seems like my app is crashing). I've tested my app using Instruments, and the app isn't taking up much memory / CPU / power until the animations begin. I have tested both on the device and on my Intel i7 8GB iMac and the animations are "laggy" on both.
The animation I am performing is nothing complex, it is simply a translation across the X Axis. After looking through every line of code related to the animation, I found that these lines are the issue(s):
viewer.layer.masksToBounds = NO;
viewer.layer.shadowOffset = CGSizeMake(-1, 1);
viewer.layer.shadowRadius = 3;
viewer.layer.shadowOpacity = 0.3;
The above code adds a shadow to the view that lags whenever I animate it (viewer). If I use the above code, but I add the following line animations work nicely:
viewer.layer.shouldRasterize = YES;
The problem with this code is that is seriously decreases the quality of the content displayed inside of the UIView (viewer). Here's an image with shouldRasterize set to YES:
Then the UIView without shouldRasterize:
Those screenshots are both from the same Retina iPad.
The ultimate question: How can I smoothly perform animations on a UIView with shadows (preferably using QuartzCore)? Is there a way to rasterize the content without degrading its quality?
The shadow properties on CALayer can be very inefficient while animating because it requires recalculating the shadow on every frame based on the contents of the layer. Luckily, the expensive part is the shadow path calculation, so if you just create a CGPath representing the shape of your content and assign it to layer.shadowPath then performance will skyrocket.
Since your layer seems to be completely filled with opaque data, the shadowPath is pretty simple:
layer.shadowPath = [UIBezierPath bezierPathWithRect:(CGRect){CGPointZero, layer.bounds.size}].CGPath;
The only downside is you'll need to edit this whenever the size of the layer changes.

View behaviour differences between IOS 5.x and IOS 4.x

I've been trying to animate an image view to slide upwards on the screen. The views height is also increased whilst the position is moved upwards.
On my iPhone 4S (5.x) the image view behaves as expected, the view only moves upwards as its height is increased, however on my iPhone 3G (4.1), the view moves down a little bit during this animation.
Such a level of accuracy is needed as the image view is used to create a non expensive shadow effect. Its alignment is important for the effect. The image is a resizable graphic.
This is how I change the position and size of the view
CGRect oldShadow = self.shaddowView.frame;
oldShadow.size.height = oldShadow.size.height+200;
oldShadow.origin.y = oldShadow.origin.y - 200;
self.shaddowView.frame =oldShadow;
This is how the image for the view is set up as resizable:
UIImage* shadow = [[UIImage imageNamed:#"shadow.png"] stretchableImageWithLeftCapWidth:20 topCapHeight:20];
self.shaddowView.image = shadow;
Thanks.
I used the following animation, with a border around not only the starting position but also the intended final position, so that I could confirm whether any undesired shifting of the view (other than the obvious upward expansion) took place, but it worked fine on iOS 4.2.1:
[UIView animateWithDuration:2.0
animations:^{
CGRect newImageFrame = imageView.frame;
newImageFrame.origin.y -= stretchBy;
newImageFrame.size.height += stretchBy;
imageView.frame = newImageFrame;
}];
I don't have iOS 4.1 device sitting around (my old 3G test phone is running iOS 4.2.1, the latest supported iOS version for that device), so I can't speak to that, but it's fine with iOS 4.2.1.
I have to confess, though, that I find it very unlikely that when you animate the changing of a frame, that the final frame would not be precisely what you specified it to be. If you NSLog the frame when you're done, it is not the correct value? Or are you saying that it momentarily moves during the animation but then ends up in the correct location? Or that it shifts down during animation and ends up in the wrong position even when the animation is done?
I wonder if there's something else going on (e.g. is your animated view a subview of a scroll view, which itself might be shifting? or is there some code not shown here that is accidentally further adjusting the frame after the animation? etc.). Seems like a little debugging should confirm whether the frame is actually not what you intended, or whether there is some other issue going on.
I originally answered suggesting shouldRasterize option, but if you're trying to support old iPhone 3G devices, then maybe that's not good enough. Definitely stutters a little on these old phones. Anyway, this was my original answer:
I assume you're doing this because the layer shadow feature is a little CPU intensive. But I've heard (but can't speak to it) that if you use the shouldRasterize option, it's a little better:
viewThatNeedsShadow.layer.shadowColor = [UIColor blackColor].CGColor;
viewThatNeedsShadow.layer.shadowOffset = CGSizeMake(3.0, 3.0);
viewThatNeedsShadow.layer.shadowOpacity = 0.5;
viewThatNeedsShadow.layer.shouldRasterize = YES;
viewThatNeedsShadow.clipsToBounds = NO;

AssetsLibrary with UIImagePicker - ELCImagePickerController

I was wondering if anyone else has used the following in their iOS applications.
https://github.com/elc/ELCImagePickerController
Basically it is a clone of the UIImagePicker using the using the AssetsLibrary that is available with iOS 4.0.
For the most part I like it, but I ran into two issues.
1) When on a device, it take quite a while when there are more that 200 images in a Library. While it works when once it loads, it takes quite a bit longer than I would ideally like.
2) When selecting some images, it brings it over with a different orientation that is shown on the screen. (looks like that happens most with pictures I took from the iPhone) I even seen it turn an image upside down.
I am just curious if anyone else has used this, and if so, were they able to overcome these issues.
Regarding orientation you can use the "ALAssetPropertyOrientation" and get the image orientation and than get any orientation that you may need.
Below are the orientation that iOS support
typedef enum {
UIImageOrientationUp, // default orientation
UIImageOrientationDown, // 180 deg rotation
UIImageOrientationLeft, // 90 deg CCW
UIImageOrientationRight, // 90 deg CW
UIImageOrientationUpMirrored, // as above but image mirrored along other axis. horizontal flip
UIImageOrientationDownMirrored, // horizontal flip
UIImageOrientationLeftMirrored, // vertical flip
UIImageOrientationRightMirrored, // vertical flip
} UIImageOrientation;
1) Load first 100 images, update GUI and load other in background.
2) UIImage have property imageOrientation