Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

animate point multiple times and more naturally

so my current version looks like this: Animation Movie

i'm fairly new to core-animations, so what i try to achieve is that there are multiple points like the current one, moving from the left box in various angles, heights and speeds out of it, just like a tennis ball machine.

enter image description here

the first problem is, that my "ball" doesn't look like it gets grabbed from gravity and also the speed at first is not fast enough.

also, how to do this animation multiple times with variating distances between the beginning.

if something is unclear, PLEASE leave a comment.

my current code:

- (void)loadView {
    [super loadView];

    self.view.backgroundColor = [UIColor lightGrayColor];   

    CGPoint startPoint = CGPointMake(20, 300);
    CGPoint endPoint = CGPointMake(300, 500);

    UIBezierPath *trackPath = [UIBezierPath bezierPath];
    [trackPath moveToPoint:startPoint];
    [trackPath addQuadCurveToPoint:endPoint controlPoint:CGPointMake(endPoint.x, startPoint.y)];

    CALayer *point = [CALayer layer];
    point.bounds = CGRectMake(0, 0, 20.0, 20.0);
    point.position = startPoint;
    point.contents = (id)([UIImage imageNamed:@"point.png"].CGImage);
    [self.view.layer addSublayer:point];

    CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    anim.path = trackPath.CGPath;
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    anim.repeatCount = HUGE_VALF;
    anim.duration = 2.0;
    [point addAnimation:anim forKey:@"movepoint"];

    CALayer *caseLayer = [CALayer layer];
    caseLayer.bounds = CGRectMake(0, 0, 140.0, 150.0);
    caseLayer.position = startPoint;
    caseLayer.contents = (id)([UIImage imageNamed:@"case.png"].CGImage);
    [self.view.layer addSublayer:caseLayer];

}
like image 318
choise Avatar asked Nov 04 '22 11:11

choise


1 Answers

Easiest way to model gravity is with those parabolic equations that you learn in basic physics. In short, the function below takes an initial position, a speed, and an angle (IN RADIANS, where 0 is to the right). a CALayer appears at position and gets shot at that speed and angle.

I'm using a CADisplayLink (which is effectively a timer that synchronizes with your frame rate) to call a function very quickly. Every time the function is called, the point is moved. The horizontal speed is constant and the vertical speed increases towards the bottom every frame to emulate gravity (`vy -= 0.5f; ). If you want more/less gravity, just mess around with this 0.5f value.

- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
      point = [[CALayer alloc] init];
      point.bounds = CGRectMake(0.0f, 0.0f, 10.0f, 10.0f);
      point.backgroundColor = [UIColor redColor].CGColor;
      point.position = CGPointMake(-10.0f, -10.0f);
      [self.layer addSublayer:point];
      [point release];
    }
    return self;
}

-(void)animateBallFrom:(CGPoint)start withSpeed:(CGFloat)speed andAngle:(CGFloat)angle       
  vx = speed*cos(angle);
  vy = speed*sin(angle);


  [CATransaction begin];
  [CATransaction setDisableActions:YES];
  point.position = start;
  [CATransaction commit];

  displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(animate)];
  [displayLink setFrameInterval:2];
  [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}

-(void)animate {
  if (point.position.x + point.bounds.size.width/2.0f < 0.0f || point.position.x > self.bounds.size.width + point.bounds.size.width/2.0f ||
    point.position.y + point.bounds.size.height/2.0f < 0.0f || point.position.y > self.bounds.size.height + point.bounds.size.height/2.0f) {
    [displayLink invalidate];
  } else {
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    point.position = CGPointMake(point.position.x+vx, point.position.y-vy);
    vy -= 0.5f;
    [CATransaction commit];
  }
}

and the interface:

@interface Bounce : UIView {
  CALayer *point;
  CADisplayLink *displayLink;
  CGFloat vx, vy;
}

-(void)animateBallFrom:(CGPoint)start withSpeed:(CGFloat)speed andAngle:(CGFloat)angle;

@end
like image 65
aleph_null Avatar answered Nov 11 '22 13:11

aleph_null