Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Current position of animating CALayer

KroupyKroupy Posts: 269Registered Users @ @
edited June 2010 in iPhone SDK Development
Hi

a layers position is animating from one CGPoint to an other.

Works great.

But I need to know the current position of the CALayer during the animation.

If I say layer.position.x

it shows the position of the point where it is heading to....

how to get the current position...

Thanks a lot!
Post edited by Kroupy on

Replies

  • Jason RogersJason Rogers Posts: 97Registered Users
    edited June 2009
    hi
    I tried for a while (I was trying to track the position to detect collisions between objects).
    long story short: you can't (or uptil now nobody has been able to tell me how

    I tried accessing the values during animations, putting observers etc etc

    the problem is that you delegate the animation to Core Animation (I'm guessing) like in the move me example of apple.

    then its CA that handels everything. it doesn;t seem to physically move your layer. (in you code at the end you have to do something like whatIsAnimated.center = layerAnimated.center; (if you moving an object)

    if your trying something simple like changing the animation while its executing then just end it and restart a new one

    if your creating something much more precise like a game with moving object, collisions etc then you have to major choices:
    - take out the big guns and use OpenGl ES
    - create your own moveable object

    both methods are similar (since the logic is the same) it really depends on what type of app you want and what are your overall goals


    I don't think without some code and/or some general goal of your animation, anybody will be able to help you more

    hope this helps

    jason rogers
    We all have to go down this same road.<br />
    You liked it when the ones in front of you helped.<br />
    So think about the ones behind you.<br />
    ---<br />
    try, try again, try some more, then ask.<br />
    once you asked, continue trying until you find a
  • KroupyKroupy Posts: 269Registered Users @ @
    edited June 2009
    HI

    sure,

    well I'm having a layer moving from A to B. Let's say this way: When the user taps the screen, a dot has to appear exactly there, where the layer is at this precise moment.

    Yes it is a game.

    But it's not worth OpenGL

    Thanks!

    Me
  • Jason RogersJason Rogers Posts: 97Registered Users
    edited June 2009
    I'm guessing you mean a dot appears where the layer is at the moment the screen is tapped

    well then if you want the cheap fix try something like this
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event{
    	animated.frame = [[animated.layer presentationLayer] frame];
    	[playerShip.layer removeAnimationForKey:@"animate"];
    	//display your point
    
           //restartyour animation
    }
    

    cheap fix because you stop your animation to make your system update the position of the layer before restarting the animation

    if you don't have a lot more animation then that should do the trick
    We all have to go down this same road.<br />
    You liked it when the ones in front of you helped.<br />
    So think about the ones behind you.<br />
    ---<br />
    try, try again, try some more, then ask.<br />
    once you asked, continue trying until you find a
  • KroupyKroupy Posts: 269Registered Users @ @
    edited June 2009
    Er, what exactly is "animated"? and animated.layer?

    The layer itself is animated. I have layer.frame but no animated.layer?
  • wdnwdn Posts: 28Registered Users
    edited June 2009
    Have you looked at the -presentationLayer method of CALayer in the reference docs?
  • KroupyKroupy Posts: 269Registered Users @ @
    edited June 2009
    sure I have.

    I'm seeing no other way, than looking into the future.

    That means, I'm going to calculate the path and cut it into little bits and put the bits into an array indexed with a global timestamp that I made on my own, coupled with the number of loops my main timer does....pretty crappy...
  • Jason RogersJason Rogers Posts: 97Registered Users
    edited June 2009
    if your heading down that path (calculating the futur etc etc) wouldn't it be easier to do your own animation?

    by animated I was talking about the UIView your animating
    We all have to go down this same road.<br />
    You liked it when the ones in front of you helped.<br />
    So think about the ones behind you.<br />
    ---<br />
    try, try again, try some more, then ask.<br />
    once you asked, continue trying until you find a
  • KroupyKroupy Posts: 269Registered Users @ @
    edited June 2009
    Hi

    thanks

    Yes I thought you talked about the UIView but I don't have an UIView that I'm animating. It's just layer.position = CGPointMake....during an [UIView beginAnimation...

    How can I do "my own animation?"

    Thanks!
  • KroupyKroupy Posts: 269Registered Users @ @
    edited June 2009
    Well I tried with the array and calculating the positions of the layer into the future, but it just isn't exact. I really need the current position of the layer. It is the same, when animating (via UIView beginAnimation) an UIView. Its also not possible to get its current position.

    So how can I implement my own animation? Any help?
  • wdnwdn Posts: 28Registered Users
    edited June 2009
    Does this work for you or is there something I'm missing? For simplicity, the code is located in a view controller in a skeleton Xcode project--you can move it around according to your needs and do hit testing once you get the current position.
    - (void)viewDidLoad
    {
          [super viewDidLoad];
    	
          layer = [CALayer layer]; // Declare layer as an ivar in your .h file
          UIImage *image = [UIImage imageNamed:@"YourSpriteImage.png"];
          layer.contents = (id)image.CGImage;
          layer.bounds = CGRectMake(0, 0, image.size.width, image.size.height);
          [self.view.layer addSublayer:layer];
    	
          CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
          anim.fromValue	= [NSValue valueWithCGPoint:CGPointMake(0, 0)];
          anim.toValue	= [NSValue valueWithCGPoint:CGPointMake(320, 480)];
          anim.duration	= 30.0;
          anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
          [layer addAnimation:anim forKey:@"positionTest"];
    }
    
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
          CGPoint currentPosition = [[layer presentationLayer] position];
          NSLog(@"%@", NSStringFromCGPoint(currentPosition));
    }
    
  • Jason RogersJason Rogers Posts: 97Registered Users
    edited June 2009
    I'm pretty sure that somewhere down the line you are using a derivative of a UIView surely a UIImageVIew to display what your moving, and that the layer your refering to is the view layer that you get when doing something like this
    - (void)animatePlacardViewToCenter{
    		CALayer *welcomeLayer = placardView.layer;
    ...
    

    (code from the move me example of the apple website).

    to build your own animation its pretty straight forwards (and a classic algorithm for game programing ^^)

    create a loop that iterates at a high enough speed (human eye distinguishes around 23 FPS so you need at that, 3D engines to make clean animations work on anideal goal of 60FPS)

    the basic physics : speed = distance / time

    to create your animation you need to add a unit of movement usually referred as delta. at each iteration you add this delta to the position of the object you want to animate. the delta represents the distance your object has moved since the last iteration.

    to go down this road (especially on a mobile platform) you have to optimize you code and limit the number of test you do.

    thats the basics

    jason
    We all have to go down this same road.<br />
    You liked it when the ones in front of you helped.<br />
    So think about the ones behind you.<br />
    ---<br />
    try, try again, try some more, then ask.<br />
    once you asked, continue trying until you find a
  • KroupyKroupy Posts: 269Registered Users @ @
    edited June 2009
    this is weird....seems like this code (from wdn) works awesomely perfectly.

    the only thing is...when the animation is done, it jumps back to the start....
  • KroupyKroupy Posts: 269Registered Users @ @
    edited June 2009
    I'm pretty sure that somewhere down the line you are using a derivative of a UIView surely a UIImageVIew to display what your moving, and that the layer your refering to is the view layer that you get when doing something like this
    - (void)animatePlacardViewToCenter{
    		CALayer *welcomeLayer = placardView.layer;
    ...
    

    (code from the move me example of the apple website).

    to build your own animation its pretty straight forwards (and a classic algorithm for game programing ^^)

    create a loop that iterates at a high enough speed (human eye distinguishes around 23 FPS so you need at that, 3D engines to make clean animations work on anideal goal of 60FPS)

    the basic physics : speed = distance / time

    to create your animation you need to add a unit of movement usually referred as delta. at each iteration you add this delta to the position of the object you want to animate. the delta represents the distance your object has moved since the last iteration.

    to go down this road (especially on a mobile platform) you have to optimize you code and limit the number of test you do.

    thats the basics

    jason

    I can't beliEVE it, it's just soo oldschool. Of course I could code something like this, but especially when I'm trying to have this EaseInOut Curve it is going to be just stupid work to do on your own...I don't blame you, but Apple...but...well wdn's code somehow works...and I'm pretty sure that my problem with the layer jumping back to the start is some idiotic mistake I made...lets see...
  • KroupyKroupy Posts: 269Registered Users @ @
    edited June 2009
    wdn - you're a GOD.

    Thanks, it works perfectly!

    To all who read this toppic: Use the code writen by wdn.
  • wdnwdn Posts: 28Registered Users
    edited June 2009
    I'm pretty sure that somewhere down the line you are using a derivative of a UIView...

    Unless CAAnimation is doing something behind the scenes I'm not aware of (which would be odd since it works only with layers), the only UIView is the container view of the view controller.
    Kroupy wrote:
    the only thing is...when the animation is done, it jumps back to the start....

    This is because only the presentation layer changes from the animation. The model layer hasn't changed when the animation is done. Simply update your layer.position property when the animation is finished.
  • KroupyKroupy Posts: 269Registered Users @ @
    edited June 2009
  • teekteek Posts: 49Registered Users
    edited April 2010
    This helped me a lot, had the exact same problem.
    ./t<br />
    <br />
    Mac Mini 2,26GHz - 4 GB<br />
    iPhone 3GS - 32 GB :: iPod Touch - 16 GB :: iPod Shuffle - 4 GB
  • FunbitFunbit Posts: 1New Users
    edited April 2010
    wdn wrote: »
    Does this work for you or is there something I'm missing? For simplicity, the code is located in a view controller in a skeleton Xcode project--you can move it around according to your needs and do hit testing once you get the current position.
    - (void)viewDidLoad
    {
          [super viewDidLoad];
    	
          layer = [CALayer layer]; // Declare layer as an ivar in your .h file
          UIImage *image = [UIImage imageNamed:@"YourSpriteImage.png"];
          layer.contents = (id)image.CGImage;
          layer.bounds = CGRectMake(0, 0, image.size.width, image.size.height);
          [self.view.layer addSublayer:layer];
    	
          CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
          anim.fromValue	= [NSValue valueWithCGPoint:CGPointMake(0, 0)];
          anim.toValue	= [NSValue valueWithCGPoint:CGPointMake(320, 480)];
          anim.duration	= 30.0;
          anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
          [layer addAnimation:anim forKey:@"positionTest"];
    }
    
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
          CGPoint currentPosition = [[layer presentationLayer] position];
          NSLog(@"%@", NSStringFromCGPoint(currentPosition));
    }
    

    This code worked fine for me prior to 3.2 and 4.0 versions of the SDK (i.e. up to 3.1.3)...
    But it seems that Apple has changed something in the internal implementation and now (in 3.2 or 4.0) [[layer presentationLayer] frame] function doesn't return the CURRENT location/size of the layer anymore... The value just doesn't get updated properly and always equals the initial position of the object (or final, don't remember exactly) being animated. Does anybody experience this problem? I've just tried iPhone SDK 4 Beta 2, which was released yesterday - and it still doesn't work...

    I wanted to confirm the problem before reporting a bug to Apple.

    Thanks to everyone,
    Funbit
  • AthensteanAthenstean Posts: 2New Users
    edited June 2010
    Same problem here. Rotation values taken from the presentationLayer seem to be okay, but using [(CALayer*)(aView.layer.presentationLayer) position] returns some weird values starting with 3.2 ... anyone any idea how to fix this?
Sign In or Register to comment.