2015年12月5日 星期六

iOS筆記:UIBezierPath Practice

結果如下圖所示:
enter image description here

規則是當一偵測的手指tap時, 分數就會開始扣. 當超出線的時候就會被扣大量的分數, 當沒有到終點就放棄時遊戲就會停止並跳出警告.

MountainPath

    // First Path

    CGPoint firstPoint = CGPointMake(rect.size.width * (1/6.0), CGRectGetMaxY(rect));
    CGPoint secondPoint = CGPointMake(rect.size.width * (1/3.0), rect.size.height * (5/6.0));
    CGPoint thirdPoint = CGPointMake(CGRectGetMaxX(rect), rect.size.height * (5/6.0));
    CGPoint fourthPoint = CGPointMake(CGRectGetMaxX(rect), rect.size.height * (2/3.0));
    CGPoint fifthPoint = CGPointMake(rect.size.width * (1/6.0), rect.size.height * (6/12.0));
    CGPoint sixthPoint = CGPointMake(rect.size.width * (1/6.0), rect.size.height * (6/12.0));
    CGPoint seventhPoint = CGPointMake(rect.size.width * (1/3.0), rect.size.height * (2/6.0));
    CGPoint eigthPoint = CGPointMake(rect.size.width * (2/3.0), rect.size.height * (6/12.0));
    CGPoint ninthPoint = CGPointMake(rect.size.width * (11/20.0), rect.size.height * (5/24.0));
    CGPoint controlPoint = CGPointMake(rect.size.width * (6 / 8.0), rect.size.height * (1/ 3.0));

UIBezierPath *rightMountainPath = [UIBezierPath bezierPath]; 

[rightMountainPath moveToPoint:firstPoint];
    [rightMountainPath addLineToPoint:secondPoint];
    [rightMountainPath addLineToPoint:thirdPoint];
    [rightMountainPath addLineToPoint:fourthPoint];
    [rightMountainPath addLineToPoint:fifthPoint];
    [rightMountainPath addLineToPoint:sixthPoint];
    [rightMountainPath addLineToPoint:seventhPoint];
    [rightMountainPath addLineToPoint:eigthPoint];
    [rightMountainPath addQuadCurveToPoint:ninthPoint controlPoint:controlPoint];

    [variousPaths addObject:rightMountainPath];

    return [variousPaths copy];

Second Path 則是透過 First Path再去減寬度PATH_WIDTH

畫曲線

  • (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint

endPoint: 曲線的終點
controlPoint: 畫曲線的基準點
enter image description here

Add Tap

+(UIBezierPath *)tapTargetForPath:(UIBezierPath *)path
{
    //To detect that our path is being tapped.
    CGPathRef tapTargetPath = CGPathCreateCopyByStrokingPath(path.CGPath, NULL, fmaxf(10.0f, path.lineWidth), path.lineCapStyle, path.lineJoinStyle, path.miterLimit);

    UIBezierPath *tapTarget = [UIBezierPath bezierPathWithCGPath:tapTargetPath];

    CGPathRelease(tapTargetPath);

    return tapTarget;
}

Main View

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapDetected:)];
    [self.pathView addGestureRecognizer:tapRecognizer];
    //tapRecognizer.numberOfTapsRequired = 2;

    UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panDeteced:)];
    [self.pathView addGestureRecognizer:panRecognizer];

    self.scoreLabel.text = [NSString stringWithFormat:@"Score: %i", RTMAP_STARTING_SCORE];
}
- (void)panDeteced:(UIPanGestureRecognizer *)panRecognizer
{
    CGPoint fingerLocation = [panRecognizer locationInView:self.pathView];
    //NSLog(@"I'm at (%f, %f", fingerLocation.x, fingerLocation.y);

    if (panRecognizer.state == UIGestureRecognizerStateBegan && fingerLocation.y < 750) {
        self.timer = [NSTimer scheduledTimerWithTimeInterval:RTTIMER_INTERVAL target:self selector:@selector(timerFired) userInfo:nil repeats:YES];

        self.scoreLabel.text = [NSString stringWithFormat:@"Score: %i", RTMAP_STARTING_SCORE];
    }
    else if (panRecognizer.state == UIGestureRecognizerStateChanged)
    {
        for (UIBezierPath *path in [RTMountainPath mountainPathsForRect:self.pathView.bounds]) {
            UIBezierPath *tapTarget = [RTMountainPath tapTargetForPath:path];

            if ([tapTarget containsPoint:fingerLocation]) {
                //NSLog(@"You hit the wall");
                [self decrementScoreByAmount:RTWALL_PENALTY];
            }
        }
    }
    else if (panRecognizer.state == UIGestureRecognizerStateEnded && fingerLocation.y<= 165)
    {
        [self.timer invalidate];
        self.timer = nil;
    }
    else {
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Error" message:@"Make sure to start the bottom of the path, hold your finger down and finish at the top of the path" preferredStyle:UIAlertControllerStyleAlert];

        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
        UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:nil];

        [alertController addAction:cancelAction];
        [alertController addAction:okAction];
        [self presentViewController:alertController animated:YES completion:nil];

        [self.timer invalidate];
        self.timer = nil;
    }
}

- (void)tapDetected:(UITapGestureRecognizer *)tapRecognizer
{
    CGPoint tapLocation = [tapRecognizer locationInView:self.pathView];
    NSLog(@"tap location is at (%f, %f)", tapLocation.x, tapLocation.y);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)timerFired
{
    [self decrementScoreByAmount:RTMAP_SCORE_DECREMENT_AMOUNT];
}

- (void)decrementScoreByAmount:(int)amount
{
    NSString *scoreText = [[self.scoreLabel.text componentsSeparatedByString:@" "] lastObject];
    int score = [scoreText intValue];
    score = score - amount;

    self.scoreLabel.text = [NSString stringWithFormat:@"Score: %i", score];
}

參考:
https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIBezierPath_class/index.html#//apple_ref/occ/instm/UIBezierPath/addQuadCurveToPoint:controlPoint:

沒有留言:

張貼留言