【问题标题】:animate point multiple times and more naturally多次动画点,更自然
【发布时间】:2011-11-06 22:27:51
【问题描述】:

所以我当前的版本是这样的:Animation Movie

我对核心动画还很陌生,所以我试图实现的是有多个点,就像当前的一样,从左边的盒子以不同的角度、高度和速度移动出来,就像网球一样球机。

第一个问题是,我的“球”看起来不像是被重力抓住的,而且一开始的速度也不够快。

另外,如何在起点之间的距离不同的情况下多次执行此动画。

如果有不清楚的地方,请发表评论。

我当前的代码:

- (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];

}

【问题讨论】:

  • 我建议你看看使用cocos2d/box2d 来运行你的“动画”作为物理模拟。如果您想要逼真的重力和粒子运动,这就是它听起来应该的样子。
  • 我认为我不需要这样的依赖。它仅适用于我的应用程序中的一个(并且不是很重要)视图。
  • 由于您尝试将基本物理特性融入球中,使用 CADisplayLink 并为球设置动画会反复改变其位置是否可以接受?有人反对这个解决方案吗?

标签: iphone objective-c ios animation core-animation


【解决方案1】:

模拟重力的最简单方法是使用您在基础物理学中学到的抛物线方程。简而言之,下面的函数采用初始位置、速度和角度(以弧度为单位,其中 0 位于右侧)。一个 CALayer 出现在该位置并以该速度和角度拍摄。

我正在使用 CADisplayLink(它实际上是一个与您的帧速率同步的计时器)来非常快速地调用一个函数。每次调用该函数时,都会移动该点。水平速度是恒定的,垂直速度每帧向底部增加以模拟重力(`vy -= 0.5f; )。如果您想要更多/更少的重力,只需使用这个 0.5f 值即可。

- (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];
  }
}

和界面:

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

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

@end

【讨论】:

    【解决方案2】:

    我认为您可以在这里做几件事。
    - 一种是使用 kCAMediaTimingFunctionLinear 而不是 kCAMediaTimingFunctionEaseOut。
    - 另一个是将控制点设置在球的下落中心,无论它在哪里。试试这个:

    CGPoint startPoint = CGPointMake(20, 300);
    CGPoint controlPoint = CGPointMake(160, 400);
    CGPoint endPoint = CGPointMake(300, 500);
    
    UIBezierPath *trackPath = [UIBezierPath bezierPath];
    [trackPath moveToPoint:startPoint];
    [trackPath addQuadCurveToPoint:endPoint controlPoint:controlPoint];
    
    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:kCAMediaTimingFunctionLinear];
    anim.repeatCount = HUGE_VALF;
    anim.duration = 2.0;
    [point addAnimation:anim forKey:@"movepoint"];
    

    然后您应该能够为不同的路径移动控制点。

    【讨论】:

    • 没错!所以你应该做的是使用控制点变量来获得曲线。例如,将曲线的 x 值移到 200 处。
    猜你喜欢
    • 2015-08-16
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多