간단한 퍼즐 게임을 만들고 다음 용도로 사용합니다.간단한 퍼즐 게임 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;
}
}
}
}
}
}
}
이 일 ... 당신의 첫 번째 방법에서 같은 목적을 위해 두 다른 터치를 사용하고 있는지
해상도는 무엇입니까? (매개 변수 x * resolution 및 y * resolution을 사용하여 verifyAlphaPixelImage를 호출합니다). x와 y가 이미지 공간으로 변환되었는지 확인하십시오. 그렇지 않으면 rawData 배열의 색인이 올바르게 지정되지 않습니다. – giorashc
해상도 - 이는 망막 디스플레이 용입니다. 망막 디스플레이 내가이 변수 (CGFloat) 2.0을 설정하지 않으면 망막 (CGFloat) 1.0을 설정합니다. –
코드는 괜찮은 것 같습니다. 거기에 좌표를 전달해야합니다. 그것이 정확히 일어 났을 때 시나리오가 있습니까? 아니면 무작위로 발생합니까? – giorashc