0

フライト コントロールのコントロールと同様に、ユーザーが定義しているパスに沿って飛行機を動かそうとしています。非効率的ではありますが、パスを描くことはできますが、パスに沿って平面をスムーズにアニメーション化することはできません。

最初は、位置を変更することによって提供される暗黙的なアニメーションを使用して、平面をパスに沿って動かそうとしましたが、アニメーションの速度を変更できないため、平面の動作が悪くなります。

現在、アニメーション ブロックを再帰的に使用しようとしていますが、完了ブロックが呼び出されるのが早すぎて、パスが描画された直後の平面になってしまいます。

これはセットアップコードです:

- (CALayer *)plane{
    if(!_plane){
        _plane = [CALayer layer];
        UIImage *planeImage = [UIImage imageNamed:@"airplane.png"];
        _plane.bounds = CGRectMake(20.0, 20.0, planeImage.size.width, planeImage.size.height);
        _plane.contents = (id)(planeImage.CGImage);
        [self.layer addSublayer:_plane];
    }
    return _plane;
}
- (void)touchesEnded:(NSSet *)touches
           withEvent:(UIEvent *)event{
    if(isDrawingPath){
        [self.trackPath addLineToPoint:[[touches anyObject] locationInView:self]];
        NSLog(@"%@", self.trackPath);

        UITouch *touch = [touches anyObject];
        CGPoint toPoint = [touch locationInView:self];
        //now, save each point in order to make the path
        [self.points addObject:[NSValue valueWithCGPoint:toPoint]];
        [self setNeedsDisplay];
        [self goToPointWithIndex:0];
    }
    isDrawingPath = NO;
}

この実装は機能しますが、うまくいきません。飛行機はパスをたどりますが、途切れ途切れです。

- (void)goToPointWithIndex:(NSNumber *)indexer{
    int toIndex = [indexer intValue];

    if(toIndex < self.points.count){
        //extract the value from array
        CGPoint toPoint = [(NSValue *)[self.points objectAtIndex:toIndex] CGPointValue];
        CGPoint pos = self.plane.position;
        float delay = PLANE_SPEED * (sqrt( pow(toPoint.x - pos.x, 2) + pow(toPoint.y - pos.y, 2)));
        self.plane.position = toPoint;

        // Allows animation to continue running
        if(toIndex < self.points.count - 1){
            toIndex++;
        }

        //float delay = 0.2;
        NSLog(@"%f", delay);
        //repeat the method with a new index
        //this method will stop repeating as soon as this "if" gets FALSE
        NSLog(@"index: %d, x: %f, y: %f", toIndex, toPoint.x, toPoint.y);
        [self performSelector:@selector(goToPointWithIndex:) withObject:[NSNumber numberWithInt:toIndex] afterDelay:delay];
    }
}

これが私がブロックでやろうとしていることです。全体をたどるのではなく、描画されたパスの最後までスキップするだけです。

- (void)goToPointWithIndex:(int)toIndex{
    if(self.resetPath) return;
    //extract the value from array
    if(toIndex < self.points.count) {
        CGPoint toPoint = [(NSValue *)[self.points objectAtIndex:toIndex] CGPointValue];
        NSLog(@"index: %d, x: %f, y: %f", toIndex, toPoint.x, toPoint.y);
        CGPoint pos = self.plane.position;
        //float delay = PLANE_SPEED * (sqrt( pow(toPoint.x - pos.x, 2) + pow(toPoint.y - pos.y, 2)));

        // Allows animation to continue running
        if(toIndex < self.points.count - 1){
            toIndex++;
        }

        [UIView animateWithDuration:0.2
                     animations:^{
                         self.plane.position = toPoint;
                     }
                completion:^(BOOL finished) {
                    if(finished == YES) {NSLog(@"Complete");[self goToPointWithIndex:toIndex];}
        }];
    }
}

どこが間違っているのかわかりません。私はobjective-cとブロックが初めてです。アニメーションが始まった直後に完了ブロックが実行されることになっていますか? 私には意味がありませんが、私が見つけることができる唯一の説明です。


編集: ブロック アニメーションを引き続き使用できるように、最終的に平面を UIView にしました。CALayer トランザクションは、私の再帰をあまり好きではありませんでした。

4

2 に答える 2