How to have a view travel the path of an inverted parabola? - iphone

I have an inverted parabola and i need to have a view traverse through the path of the parabola.The view should slightly rotate and translate along the path of the parabola.
I did some research and found that BezierPath (quadcurve with control points) could be used to lay the path of the parabola out and then we could use CAKeyFramAnimation to move the object along the path.Animating the view object along the path of the parabola is whats confusing me.
How do i keep changing the starting points of the object within the parabola and retain the latest state of the view
Here's a brief description of what i want to achieve with the view in the parabola
The view starts from a particular point in the parabola and then traverses the parabola till the specified end point.
How do i find out the end point within the parabola?
Once the view reaches its end point.For the next traversal it can start from that point and then move on to any other point within the parabola.This happens continuously based on the next end point.
This is a rough sketch oh how the path and the view would look like
And also i would like both the rotation and translation of the view traversing the path to happen simultaneously
How can this be done?
Thank you!

Draw parabola with UIBezierPath and convert it to CGPath or Create a CGPath.
Use CAKeyFrameAnimation to move UIView's position.
Look at the below source code,
Drawing Parabola
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path,NULL,50.0,120.0);
CGPathAddCurveToPoint(path,NULL,50.0,275.0,
150.0,275.0,
150.0,120.0);
CGPathAddCurveToPoint(path,NULL,150.0,275.0,
250.0,275.0,
250.0,120.0);
CGPathAddCurveToPoint(path,NULL,250.0,275.0,
350.0,275.0,
350.0,120.0);
CGPathAddCurveToPoint(path,NULL,350.0,275.0,
450.0,275.0,
450.0,120.0);
CAKeyFrameAnimation along a path.
CAKeyframeAnimation* AniLoc = [CAKeyframeAnimation animationWithKeyPath:#"position"]; // notice key change
// rest is the same
AniLoc.path = thePath;
AniLoc.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
AniLoc.keyTimes= [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:0.3f],
[NSNumber numberWithFloat:1.0f],nil];
AniLoc.duration = 2.0;
CFRelease(thePath);
[self.logo.layer addAnimation:AniLoc forKey:nil];

Related

Cocos2D CCNode position in absolute screen coordinates

I've been looking around for a while, and I have not been able to find an answer to this for some reason. It seems simple enough, but maybe I just can't find the right function in the library.
I have a scene with a layer that contains a bunch of CCNodes with each one CCSprite in them.
During the application, I move around the position of the main layer, so that I "pan" around a camera in a way. (i.e. I translate the entire layer so that the viewport changes).
Now I want to determine the absolute position of a CCNode in screen coordinates. The position property return the position relative to the parent node, but I really would like this transformed to its actual position on screen.
Also, as an added bonus, it would be awesome if I could express this position as coordinate system where 0,0 maps to the upper left of the screen, and 1,1 maps to the lower right of the screen. (So I stay compatible with all devices)
Edit: Note that the solution should work for any hierarchy of CCNodes preferably.
Every CCNode, and descendants thereof, has a method named convertToWorldSpace:(CGPoint)p
This returns the coordinates relative to your scene.
When you have this coordinate, flip your Y-axis, as you want 0,0 to be in the top left.
CCNode * myNode = [[CCNode alloc] init];
myNode.position = CGPointMake(150.0f, 100.0f);
CCSprite * mySprite = [[CCSprite alloc] init]; // CCSprite is a descendant of CCNode
[myNode addChild: mySprite];
mySprite.position = CGPointMake(-50.0f, 50.0f);
// we now have a node with a sprite in in. On this sprite (well, maybe
// it you should attack the node to a scene) you can call convertToWorldSpace:
CGPoint worldCoord = [mySprite convertToWorldSpace: mySprite.position];
// to convert it to Y0 = top we should take the Y of the screen, and subtract the worldCoord Y
worldCoord = CGPointMake(worldCoord.x, ((CGSize)[[CCDirector sharedDirector] displaySizeInPixels]).height - worldCoord.y);
// This is dry coded so may contain an error here or there.
// Let me know if this doesn't work.
[mySprite release];
[myNode release];

Moving a UIImageView on an arc using CGAffine

I understand that CGAffineTransformMakeRotation can rotate an image, and CGAffineTransformMakeTranslation translates an image. I also understand CGAffineTransformConcat can merge two transformations. However, I cannot seem to figure out a way to move an image on an arc using both of these. I understand this is more a mathematical question but does anyone have a reference they can point me to?
Edit:
[bezierPathWithArcCenter:radius:startAngle:endAngle:clockwise:]
did the trick.
Reference: http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIBezierPath_class/Reference/Reference.html#//apple_ref/occ/clm/UIBezierPath/bezierPathWithArcCenter:radius:startAngle:endAngle:clockwise:
Use a CAKeyframeAnimation with the path set instead of discreet values.
CAKeyframeAnimation *a = [CAKeyframeAnimation animationWithKeyPath:#"position"];
CGRect circleRect = CGRectMake(0,0,50,50);
a.duration = 2.0;
a.rotationMode = kCAAnimationRotateAuto;
a.path = [UIBezierPath bezierPathWithOvalInRect:circleRect].CGPath;
[imageView.layer addAnimation:a forKey:#"moveCircle"];
Rotate it about the center of the circle corresponding to the arc.
This will involve three steps:
1) Translate so that the center of your arc moves to the origin.
2) Rotate through the appropriate angle.
3) Reverse the translation from step 1.

How to set the initial orientation of an animated UIImageView?

I am programming a gauge display for an iphone application: a centered needle UIImageView against a fixed background UIImageView. I am new to iPhone programming, and don't know much about CoreAnimation, but with looking through examples and fiddling with my anchorPoint setting and the position of the needle image against the background in InterfaceBuilder, my needle is coming up with my desired rotation point properly centered against the background:
self.needleIV.layer.anchorPoint = CGPointMake( 0.5, 0.68 );
My test animations work perfectly (the needle remains properly centered in the gauge, and rotates around my desired rotation point, the anchor point), using this code:
CABasicAnimation *rotateAnimation = [CABasicAnimation animation];
rotateAnimation.keyPath = #"transform.rotation.z";
rotateAnimation.fromValue = [NSNumber numberWithFloat:DegreesToRadians( (rand() % 270 - 135) )];
rotateAnimation.toValue = [NSNumber numberWithFloat:DegreesToRadians( (rand() % 270 - 135) )];
rotateAnimation.duration = 4.0;
rotateAnimation.removedOnCompletion = NO;
// leaves presentation layer in final state; preventing snap-back to original state
rotateAnimation.fillMode = kCAFillModeBoth;
rotateAnimation.repeatCount = 0;
rotateAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
// Add the animation to the selection layer. This causes it to begin animating.
[self.needleIV.layer addAnimation:rotateAnimation forKey:#"rotateAnimation"];
The problem is that at application launch the needle comes up initially pointing straight up (which is how the needle looks in the image file), and I can't figure out how to give it an initial rotation value which doesn't mess up the animation code. (By "mess up" I mean the needle doesn't rotate on the correct axis, and becomes uncentered in the gauge).
I've tried setting layer.transform to a 3d rotation matrix rotated around the z axis, but this moves the needle off center. I've tried this code as well:
[self.needleIV.layer setValue:[NSNumber numberWithFloat:DegreesToRadians(-135.0)] forKeyPath:#"transform.rotation.z"];
which didn't work either (needle moved off anchorPoint center), and I had high hopes since it's apparently using the same transform to the working animation code.
I also tried just putting the working animation snippet in my view controller's viewDidLoad function to "animate" the needle to it's start location, but it doesn't do anything at all -- apparently the animation doesn't run until the image is actually up and on the screen, and I've confirmed in the debugger that the screen is still black in viewDidLoad.
At this point I'm about to try just hacking in a timer to run an initial animation "long enough" after the app starts to set an animation that rotates the needle properly, but I'd really like to understand what's going wrong here, and why the animation is apparently rotating around a different axis than is my other attempts at pre-rotation/pre-animation.
The anchorPoint is relative to the bounds of the parent. Is it possible the bounds of the parent layer/view change after viewDidLoad?
You should be able to do all this using the UIView center and transform properties, which are 2D so implicitly rotate about the z axis.

CAKeyframeAnimation - Examples

I have a a menu that is a CALayer that will slide across the screen to a given point. I want the effect where the menu will go a little past the point, then a little before the point, and then land on the point. I can move the menu by applying a transform, but I was hoping to get this bouncing effect to work. I was looking into CAKeyframeAnimation, but I'm having trouble locating an example/tutorial. I've looked at the CA Programming Guide but haven't really found anything. Any links or help would be great. Thanks.
I released some code a while ago that does just what you're looking for. Basically, you need to generate your own CGPathRef containing all of the points you want the layer to hit, and use that path for the path attribute of the CAKeyframeAnimation. The code will look something like this:
CGPoint path[3] = {
FTAnimationOutOfViewCenterPoint(enclosingView.bounds, view.frame, view.center, direction),
[self overshootPointFor:view.center withDirection:direction threshold:(overshootThreshold_ * 1.15)],
view.center
};
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
CGMutablePathRef thePath = CGPathCreateMutable();
CGPathAddLines(thePath, NULL, path, 3);
animation.path = thePath;
CGPathRelease(thePath);
The whole method is here.

Quartz 2D Path rotation

I'm fairly new to Quartz 2D.
Imagine the following scenario:
You have a circle-shaped mini map view.
I'm drawing triangle (the arc isn't important right now) on top of the map. This shape represents the visible area.
I need to have the triangle shape rotate along the mini map as the user changes orientation.
Currently this how the path is being drawn:
CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians);
CGPath visibleAreaPath = CGPathCreateMutable();
CGPathMoveToPoint(visibleAreaPath, &transform, miniMapCenter.x, miniMapCenter.y);
CGPathAddLineToPoint(visibleAreaPath, &transform, 18.0, 8.0);
CGPathAddLineToPoint(visibleAreaPath, &transform, 66.0, 8.0);
CGPathCloseSubpath(visibleAreaPath);
I then draw the path using a CAShapeLayer like so:
CALayer *rootLayer = [visibleAreaView layer];
visibleAreaShape = [CAShapeLayer layer];
[visibleAreaShape setFillColor:[UIColor colorWithHue:0.584 saturation:0.8 brightness:0.9 alpha:0.6].CGColor];
[visibleAreaShape setFillRule:kCAFillRuleNonZero];
[visibleAreaShape setAnchorPoint:CGPointMake(0.5, 0.5)];
[rootLayer addSublayer:visibleAreaShape];
[visibleAreaShape setPath:visibleAreaPath];
The path is being rotated, but not based on a given origin.
Keep in mind that setting the layer's anchor point doesn't help me since what I want is to rotate the path (ultimately I wouldn't even need to display it, since I will be using it to determine which points are visible on the mini map).
Any ideas on how to accomplish this?
Thank you.
I would suggest you store the points in polar form and convert to a path when needed. It's very easy to rotate in polar coordinates (simply change the theta value).