2012-05-28 3 views
0

간단한 퍼즐 게임을 만들고 다음 용도로 사용합니다.간단한 퍼즐 게임 iOS : 알파 픽셀 문제 분석

나는 Piece라는 클래스가 있습니다. 조각 클래스는 UIImageView에서 상속 및 다음 필드 포함 : 각 조각 (녹색, 파란색과 다른 레드) 색상이 내 게임에서

@property(nonatomic, strong) NSString *pieceName; 
@property(nonatomic) CGFloat pos_x; 
@property(nonatomic) CGFloat pos_y; 
@property(nonatomic) BOOL snapped; 

합니다. 각 조각은 모양이 불규칙합니다. 이것은 알파 색상이있는 이미지입니다. 알파 색상을 탭하면이 작품을 선택할 필요가 없습니다.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 

    UITouch *touch = [[event allTouches] anyObject]; 
    CGPoint touchLocation = [touch locationInView:self.view]; 

    NSArray *views = [self.view subviews]; 

    for (UIView *v in views) { 
     if([v isKindOfClass:[Piece class]]){ 
      if (CGRectContainsPoint(v.frame, touchLocation) && ((Piece *)v).snapped == FALSE) { 

       UITouch* touchInPiece = [touches anyObject]; 
       CGPoint point = [touchInPiece locationInView:(Piece *)v]; 
       BOOL solidColor = [self verifyAlphaPixelImage:(Piece *)v atX:point.x * resolution atY:point.y * resolution]; 

       if (solidColor) {     

        NSArray *tempViews = [self.view subviews]; 
        [tempViews reverseObjectEnumerator]; 

        for (UIView *tv in tempViews) { 
         if (tv == v) { 
          [tv setExclusiveTouch:YES]; 
          dragging = YES; 
          oldX = touchLocation.x; 
          oldY = touchLocation.y; 
          piece = (Piece *)v; 
          [self.view bringSubviewToFront:piece]; 
          break; 
         } 
        } 

       } 

      } 
     } 
    } 
} 


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UITouch *touch = [[event allTouches] anyObject]; 
    CGPoint touchLocation = [touch locationInView:self.view]; 

    if (dragging) {   
     CGRect frame = piece.frame; 
     frame.origin.x = piece.frame.origin.x + touchLocation.x - oldX; 
     frame.origin.y = piece.frame.origin.y + touchLocation.y - oldY; 
     if ([self verifyOutOfScopeCoordX:touchLocation.x CoordY:touchLocation.y]) { 
      piece.frame = frame; 
     }    
     [self snapPiece]; 
    } 

    oldX = touchLocation.x; 
    oldY = touchLocation.y; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{  
    dragging = NO; 
} 

- (BOOL)verifyAlphaPixelImage:(Piece *)image atX:(int)x atY:(int)y{ 

    CGImageRef imageRef = [image.image CGImage]; 
    NSUInteger width = CGImageGetWidth(imageRef); 
    NSUInteger height = CGImageGetHeight(imageRef); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char)); 
    NSUInteger bytesPerPixel = 4; 
    NSUInteger bytesPerRow = bytesPerPixel * width; 
    NSUInteger bitsPerComponent = 8; 
    CGContextRef context = CGBitmapContextCreate(rawData, width, height, 
               bitsPerComponent, bytesPerRow, colorSpace, 
               kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 
    CGColorSpaceRelease(colorSpace); 

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); 
    CGContextRelease(context); 

    int byteIndex = (bytesPerRow * y) + x * bytesPerPixel; 

    CGFloat red = (rawData[byteIndex]  * 1.0)/255.0; 
    CGFloat green = (rawData[byteIndex + 1] * 1.0)/255.0; 
    CGFloat blue = (rawData[byteIndex + 2] * 1.0)/255.0; 
    CGFloat alpha = (rawData[byteIndex + 3] * 1.0)/255.0; 
    /* 
    NSLog(@"red: %f", red); 
    NSLog(@"green: %f", green); 
    NSLog(@"blue: %f", blue); 
    NSLog(@"alpha: %f", alpha); 
    */  
    free(rawData);  
    if(alpha==0 && red == 0 && green == 0 && blue == 0) return NO; 
    else return YES; 

} 

내가 아무 문제없이 내 조각을 이동이 들어

나는 다음 방법을 사용합니다. 그러나 때로는이 줄의 verifyAlphaPixelImage 메서드로 이상한 오류가 발생합니다. CGFloat red = (rawData[byteIndex] * 1.0)/255.0; EXC_BAD_ACCESS이 나옵니다.

verifyAlphaPixelImage - 알파 픽셀을 분석 할 때이 메서드가 필요합니다. 알파 픽셀을 탭하면이 조각을 선택할 필요가 없습니다.

이제 rawData를 사용하는 주된 문제는 EXC_BAD_ACCESS입니다.

지금 나는 이것을 사용

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 

    UITouch *touch = [[event allTouches] anyObject]; 
    CGPoint touchLocation = [touch locationInView:self.view]; 

    NSArray *views = [self.view subviews]; 

    for (UIView *v in views) { 
     if([v isKindOfClass:[Piece class]]){ 

      CGFloat pos_x = touchLocation.x - v.frame.origin.x; 
      CGFloat pos_y = touchLocation.y - v.frame.origin.y;   

      if (CGRectContainsPoint(v.frame, touchLocation) && ((Piece *)v).snapped == FALSE) { 


       BOOL solidColor = [self verifyAlphaPixelImage:(Piece *)v atX:pos_x * resolution atY:pos_y * resolution]; 

       if (solidColor) {     

        NSArray *tempViews = [self.view subviews]; 
        [tempViews reverseObjectEnumerator]; 

        for (UIView *tv in tempViews) { 
         if (tv == v) { 
          [tv setExclusiveTouch:YES]; 
          dragging = YES; 
          oldX = touchLocation.x; 
          oldY = touchLocation.y; 
          piece = (Piece *)v; 
          [self.view bringSubviewToFront:piece]; 
          break; 
         } 
        } 

       } 

      } 
     } 
    } 
} 

이 일 ... 당신의 첫 번째 방법에서 같은 목적을 위해 두 다른 터치를 사용하고 있는지

+0

해상도는 무엇입니까? (매개 변수 x * resolution 및 y * resolution을 사용하여 verifyAlphaPixelImage를 호출합니다). x와 y가 이미지 공간으로 변환되었는지 확인하십시오. 그렇지 않으면 rawData 배열의 색인이 올바르게 지정되지 않습니다. – giorashc

+0

해상도 - 이는 망막 디스플레이 용입니다. 망막 디스플레이 내가이 변수 (CGFloat) 2.0을 설정하지 않으면 망막 (CGFloat) 1.0을 설정합니다. –

+0

코드는 괜찮은 것 같습니다. 거기에 좌표를 전달해야합니다. 그것이 정확히 일어 났을 때 시나리오가 있습니까? 아니면 무작위로 발생합니까? – giorashc

답변

1

알 수 있습니다.

먼저 당신이 할 :

UITouch *touch = [[event allTouches] anyObject]; 
CGPoint touchLocation = [touch locationInView:self.view]; 

터치가 조각보기 내에 있는지 확인하십시오.

그러나 당신은 또 다른 터치를 가지고 :

Incase의
UITouch* touchInPiece = [touches anyObject]; 
CGPoint point = [touchInPiece locationInView:(Piece *)v]; 

당신이 두 번째 터치가 첫 번째 터치하지 않을 수도 있습니다, 심지어 첫 번째 터치가 감지 뷰 내부되지 않을 수도 있습니다 하나 이상의 터치 이벤트 인치 첫 번째 터치로 감지 된 부분보기의 두 번째 터치가 범위를 벗어날 수 있습니다.