您的位置:首页 > 移动开发 > Cocos引擎

cocos2d中对CCMenu 实现扩展使触摸正常图片的透明区域不触发事件

2012-11-15 10:50 435 查看
原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和本声明。否则将追究法律责任。
/article/8218522.html

下面的代码是一位朋友提供的,扩展了CCMenu
(1)MenuExtras.h
//
//  MenuExtras.h
//  CCSpriteTouchedNonAlpha
//
//

#import <Foundation/Foundation.h>
#import "cocos2d.h"

/**
* 对 CCMenu 实现扩展使触摸正常图片的透明区域不触发事件
*
*/
@interface MenuExtras : CCMenu {
CGImageRef inImage_;
}

- (CGContextRef)createARGBBitmapContextFromImage:(CGImageRef)inImage;

- (int)getPixelColorAtLocation:(CGPoint)point imageRef:(CGImageRef)inImage;

@end


(2)MenuExtras.m
//
//  MenuExtras.m
//  CCSpriteTouchedNonAlpha
//

#import "MenuExtras.h"
#import "UIImage-ToSprite.h"

@implementation MenuExtras

/**
* 触摸元素的图片是否在图片的非透明范围内
*
*/
-(BOOL)containsNonAlpha:(UITouch *)touch item:(CCMenuItem *) item{
CCMenuItemSprite *spriteItem = (CCMenuItemSprite *)item;
UIImage *image = [UIImage convertSpriteToUIImage:(CCSprite *)spriteItem.normalImage];
inImage_ = CGImageRetain(image.CGImage);

//得到图片触摸的位置
CGPoint pos = [spriteItem.normalImage convertTouchToNodeSpace:touch];

//得到像素值
int pixel = [self getPixelColorAtLocation:pos imageRef:inImage_];
CGImageRelease(inImage_);
return pixel == 0 ? false : true;
}

/**
* copy CCmenu
*/
-(CCMenuItem *) itemForTouch: (UITouch *) touch{
CGPoint touchLocation = [touch locationInView: [touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];

CCMenuItem* item;
CCARRAY_FOREACH(children_, item){
// ignore invisible and disabled items: issue #779, #866
if ( [item visible] && [item isEnabled] ) {

CGPoint local = [item convertToNodeSpace:touchLocation];
CGRect r = [item rect];
r.origin = CGPointZero;
if( CGRectContainsPoint( r, local ) && [self containsNonAlpha:touch item:item]){
return item;
}
}
}
return nil;
}

-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
if( state_ != kCCMenuStateWaiting || !visible_ )
return NO;

selectedItem_ = [self itemForTouch:touch];

if(selectedItem_ != nil ){
[selectedItem_ selected];
state_ = kCCMenuStateTrackingTouch;
return YES;
}

return NO;
}

/**
* 传入图片上的一个点,返回图片上点的像素值,(如果返回值为0则表示是透明区域).
*
* @param point    图片上的点
* @param inImage  一个图片的CGImageRef实例
*/
- (int)getPixelColorAtLocation:(CGPoint)point imageRef:(CGImageRef)inImage {

CGContextRef cgctx = [self createARGBBitmapContextFromImage:inImage];
if (cgctx == NULL) {
return -1; /* error */
}

size_t w = CGImageGetWidth(inImage);
size_t h = CGImageGetHeight(inImage);
CGRect rect = {{0,0},{w,h}};

//不知道哪里把图片旋转180度???这里必须要旋转180度才能对称过来.旋转之后模拟器可以通过,真机不能通过???解决不了。。
//    CGContextRotateCTM(cgctx, 180);
CGContextDrawImage(cgctx, rect, inImage);
CGContextSaveGState(cgctx);

unsigned char* data = CGBitmapContextGetData (cgctx);

int alpha;
if (data != NULL) {
@try {
int offset = 4 * ((w * round(h - point.y)) + round(point.x));

alpha =  data[offset];
} @catch (NSException * e) {

} @finally {

}
}
CGContextRelease(cgctx);

if (data) { free(data); }

return alpha;
}

/**
* 得到图片的上下文
*
* @param inImage  一个图片的CGImageRef实例
*/
- (CGContextRef)createARGBBitmapContextFromImage:(CGImageRef)inImage{
CGContextRef    context = NULL;
CGColorSpaceRef colorSpace;
void *          bitmapData;
int             bitmapByteCount;
int             bitmapBytesPerRow;

size_t pixelsWide = CGImageGetWidth(inImage);
size_t pixelsHigh = CGImageGetHeight(inImage);

bitmapBytesPerRow   = (pixelsWide * 4);
bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);

colorSpace = CGColorSpaceCreateDeviceRGB();
if (colorSpace == NULL)
return nil;

bitmapData = malloc( bitmapByteCount );
if (bitmapData == NULL){
CGColorSpaceRelease( colorSpace );
return nil;
}

context = CGBitmapContextCreate (bitmapData,
pixelsWide,
pixelsHigh,
8,
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedFirst|kCGBitmapByteOrder32Big);

if (context == NULL) {
free (bitmapData);
fprintf (stderr, "Context not created!");
}

CGColorSpaceRelease( colorSpace );
CGContextSetBlendMode(context, kCGBlendModeCopy);

return context;
}

@end


这里提供的是扩展的MenuExtras,使用的时候就是 _menu = [MenuExtras menuWithItems:nil];
这是OC的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: