2014-10-06 83 views
0

我想繪製一條特定寬度的線。我在網上搜索了一些例子,但我只找到了使用直線的例子。我需要曲線。此外,我需要檢測用戶是否在線內觸摸。使用Objective C和Sprite Kit可以實現這一點嗎?如果有人能提供一個例子嗎?檢測曲線上的水龍頭?

This is an example of the line i need to draw

+0

你是什麼意思畫一條線?用戶繪製它?你有沒有想要繪製的特定貝塞爾路徑? – Milo 2014-10-06 23:17:10

+0

嗨,當遊戲開始時,用戶將看到該行,他將使用手指觸摸行。謝謝! – lyons 2014-10-07 12:15:33

回答

3

您可以使用UIBezierPath創建貝塞爾曲線(漂亮的平滑曲線)。您可以爲CAShapeLayer指定此路徑,並補充說,作爲一個子層到您的視圖:

UIBezierPath *path = [UIBezierPath bezierPath]; 
[path moveToPoint:CGPointMake(10, 150)]; 
[path addCurveToPoint:CGPointMake(110, 150) controlPoint1:CGPointMake(40, 100) controlPoint2:CGPointMake(80, 100)]; 
[path addCurveToPoint:CGPointMake(210, 150) controlPoint1:CGPointMake(140, 200) controlPoint2:CGPointMake(170, 200)]; 
[path addCurveToPoint:CGPointMake(310, 150) controlPoint1:CGPointMake(250, 100) controlPoint2:CGPointMake(280, 100)]; 

CAShapeLayer *layer = [CAShapeLayer layer]; 
layer.lineWidth = 10; 
layer.strokeColor = [UIColor redColor].CGColor; 
layer.fillColor = [UIColor clearColor].CGColor; 
layer.path = path.CGPath; 

[self.view.layer addSublayer:layer]; 

enter image description here


如果你想隨機了一點,你可以隨機一些曲線。如果你想要一些模糊性,請添加一些陰影。如果你想在兩端是圓的,指定一個圓形的線帽:

UIBezierPath *path = [UIBezierPath bezierPath]; 
CGPoint point = CGPointMake(10, 100); 
[path moveToPoint:point]; 

CGPoint controlPoint1; 
CGPoint controlPoint2 = CGPointMake(point.x - 5.0 - arc4random_uniform(50), 150.0); 
for (NSInteger i = 0; i < 5; i++) { 
    controlPoint1 = CGPointMake(point.x + (point.x - controlPoint2.x), 50.0); 
    point.x += 40.0 + arc4random_uniform(20); 
    controlPoint2 = CGPointMake(point.x - 5.0 - arc4random_uniform(50), 150.0); 
    [path addCurveToPoint:point controlPoint1:controlPoint1 controlPoint2:controlPoint2]; 
} 

CAShapeLayer *layer = [CAShapeLayer layer]; 
layer.lineWidth = 5; 
layer.strokeColor = [UIColor redColor].CGColor; 
layer.fillColor = [UIColor clearColor].CGColor; 
layer.path = path.CGPath; 
layer.shadowColor = [UIColor redColor].CGColor; 
layer.shadowRadius = 2.0; 
layer.shadowOpacity = 1.0; 
layer.shadowOffset = CGSizeZero; 
layer.lineCap = kCALineCapRound; 

[self.view.layer addSublayer:layer]; 

enter image description here

如果你希望它是更不規則,打破這些貝濟耶分成小段,但這個想法將是相同。連接貝塞爾曲線的唯一技巧就是要確保一條曲線的第二個控制點與下一個控制點的第一個控制點一致,否則最終會在曲線中出現尖銳的不連續點。


如果您想檢測用戶是否以及何時點擊它,那就更加複雜。但是,你必須做的是:

  1. 使圖像的快照:

    - (UIImage *)captureView:(UIView *)view 
    { 
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 1.0); // usually I'd use 0.0, but we'll use 1.0 here so that the tap point of the gesture matches the pixel of the snapshot 
    
        if ([view respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) { 
         BOOL success = [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES]; 
         NSAssert(success, @"drawViewHierarchyInRect failed"); 
        } else { 
         [view.layer renderInContext:UIGraphicsGetCurrentContext()]; 
        } 
    
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
        UIGraphicsEndImageContext(); 
    
        return image; 
    } 
    
  2. 獲取像素的顏色在座標用戶通過識別像素的顏色抽頭用戶點擊。

    - (void)handleTap:(UITapGestureRecognizer *)gesture 
    { 
        CGPoint point = [gesture locationInView:gesture.view]; 
    
        CGFloat red, green, blue, alpha; 
        UIColor *color = [self image:self.image colorAtPoint:point]; 
        [color getRed:&red green:&green blue:&blue alpha:&alpha]; 
    
        if (green < 0.9 && blue < 0.9 && red > 0.9) 
         NSLog(@"tapped on curve"); 
        else 
         NSLog(@"didn't tap on curve"); 
    } 
    

    我在哪裏,以便確定像素抽頭上的用戶是的顏色適於Apple's code for getting the pixel buffer

    // adapted from https://developer.apple.com/library/mac/qa/qa1509/_index.html 
    
    - (UIColor *)image:(UIImage *)image colorAtPoint:(CGPoint)point 
    { 
        UIColor *color; 
    
        CGImageRef imageRef = image.CGImage; 
    
        // Create the bitmap context 
        CGContextRef context = [self createARGBBitmapContextForImage:imageRef]; 
        NSAssert(context, @"error creating context"); 
    
        // Get image width, height. We'll use the entire image. 
        size_t width = CGImageGetWidth(imageRef); 
        size_t height = CGImageGetHeight(imageRef); 
        CGRect rect = {{0,0},{width,height}}; 
    
        // Draw the image to the bitmap context. Once we draw, the memory 
        // allocated for the context for rendering will then contain the 
        // raw image data in the specified color space. 
        CGContextDrawImage(context, rect, imageRef); 
    
        // Now we can get a pointer to the image data associated with the bitmap 
        // context. 
        uint8_t *data = CGBitmapContextGetData (context); 
        if (data != NULL) { 
         size_t offset = (NSInteger) point.y * 4 * width + (NSInteger) point.x * 4; 
         uint8_t alpha = data[offset]; 
         uint8_t red = data[offset+1]; 
         uint8_t green = data[offset+2]; 
         uint8_t blue = data[offset+3]; 
    
         color = [UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:alpha/255.0]; 
        } 
    
        // When finished, release the context 
    
        CGContextRelease(context); 
    
        // Free image data memory for the context 
    
        if (data) { 
         free(data); // we used malloc in createARGBBitmapContextForImage, so free it 
        } 
    
        return color; 
    } 
    
    - (CGContextRef) createARGBBitmapContextForImage:(CGImageRef) inImage 
    { 
        CGContextRef context = NULL; 
        CGColorSpaceRef colorSpace; 
        void *   bitmapData; 
        size_t   bitmapByteCount; 
        size_t   bitmapBytesPerRow; 
    
        // Get image width, height. We'll use the entire image. 
        size_t pixelsWide = CGImageGetWidth(inImage); 
        size_t pixelsHigh = CGImageGetHeight(inImage); 
    
        // Declare the number of bytes per row. Each pixel in the bitmap in this 
        // example is represented by 4 bytes; 8 bits each of red, green, blue, and 
        // alpha. 
        bitmapBytesPerRow = (pixelsWide * 4); 
        bitmapByteCount  = (bitmapBytesPerRow * pixelsHigh); 
    
        // Use the generic RGB color space. 
        colorSpace = CGColorSpaceCreateDeviceRGB(); // CGColorSpaceCreateDeviceWithName(kCGColorSpaceGenericRGB); 
        NSAssert(colorSpace, @"Error allocating color space"); 
    
        // Allocate memory for image data. This is the destination in memory 
        // where any drawing to the bitmap context will be rendered. 
        bitmapData = malloc(bitmapByteCount); 
        NSAssert(bitmapData, @"Unable to allocate bitmap buffer"); 
    
        // Create the bitmap context. We want pre-multiplied ARGB, 8-bits 
        // per component. Regardless of what the source image format is 
        // (CMYK, Grayscale, and so on) it will be converted over to the format 
        // specified here by CGBitmapContextCreate. 
        context = CGBitmapContextCreate (bitmapData, 
                pixelsWide, 
                pixelsHigh, 
                8,  // bits per component 
                bitmapBytesPerRow, 
                colorSpace, 
                (CGBitmapInfo)kCGImageAlphaPremultipliedFirst); 
        NSAssert(context, @"Context not created!"); 
    
        // Make sure and release colorspace before returning 
        CGColorSpaceRelease(colorSpace); 
    
        return context; 
    } 
    
+0

非常感謝你的解釋和你的時間。我在試着你告訴我的。只是一個問題,如果我想改變線條形狀的螺旋。在這種情況下,我將不得不修改方法addCurveToPoint正確嗎? – lyons 2014-10-07 12:30:51

+0

是的,你必須調整你添加的貝塞爾曲線的終點和控制點。請參閱[圖紙和打印指南]中關於貝齊爾的討論(https://developer.apple.com/LIBRARY/IOS/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/BezierPaths/BezierPaths.html#//apple_ref/doc/uid/ TP40010156-CH11-SW1)(儘管它正在討論用於beziers的較低級別的Core Graphics API,但在「向您的路徑添加曲線」部分中的控制點的圖示可能很明顯)。 – Rob 2014-10-07 13:18:40

+0

好的謝謝你的回答最好的問候@Rob – lyons 2014-10-07 13:21:14