顯示具有 cocos2D 標籤的文章。 顯示所有文章
顯示具有 cocos2D 標籤的文章。 顯示所有文章

2013年2月19日 星期二

CCSprite的touch 與 透明部份的檢查

因為要做一個CCSprite的圖 並播動畫, 之後還要可以點擊 做一些事.
還要能判斷是不是點到圖的透明部份..


首先是 CCSprite的 touch event 部份
自訂一個MySprite的類別.



MySprite.h

@interface MySprite : CCSprite < CCTargetedTouchDelegate > {

}
@end
加上 < CCTargetedTouchDelegate > 就好..

然後
MySprite.h
@implementation MySprite

- (void)onEnter{
    [[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:1 swallowsTouches:NO];
    [super onEnter];
}

- (void)onExit{
    [[[CCDirector sharedDirector] touchDispatcher] removeDelegate:self];
    [super onExit];
}

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
    CCLog(@"touch ");
    return YES;
}

@end

加上onEnter跟 onExit中的設定, 就可以取得touch event.
之後就可以在對應的函式中接收到點擊事件 做想做的事.

OnEnter中的設定 . :
priority 設定這個物件的優先度 .
swallowsTouches 設定是否要吃掉touch events 不往下傳.
(這跟- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event 的回傳值也有關)

---------

再來就是檢查是不是在sprite範圍內,並檢查點擊位置的alpha值.

//判段是否在sprite範圍, 並檢查alpha值,是否透明.

- (BOOL)containsTouchLocation:(UITouch *)touch
{

    CGPoint touchLocation = [touch locationInView: [touch view]];

    touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
   
    CGPoint local = [self convertToNodeSpace:touchLocation];
   
    CGRect r = [self rect];
   
    r.origin = CGPointZero;
   
    BOOL isTouched = CGRectContainsPoint( r, local );
   
    if (isTouched) {
       
        //在sprite上的座標 , 由GL系統轉成UI系統.
        CGPoint uilocal = CGPointMake(local.x, self.boundingBox.size.height-local.y);
       
        int alpha = [self getPixelColorAtLocation:uilocal];

        if (alpha < 85) { //小於85 表示透明,不攔截事件.
            return NO;
        }
       
        return isTouched;
    }
   
    return isTouched;
}

-(CGRect) rect
{
    return CGRectMake( position_.x - contentSize_.width*anchorPoint_.x,
                      position_.y - contentSize_.height*anchorPoint_.y,
                      contentSize_.width, contentSize_.height);
}

以上是判斷是否在sprite範圍內 的code.

接下來用getPixelColorAtLocation: 取得sprite上的某點的color中的alpha

//取得某pixel的color 的alpha值.
- (int)getPixelColorAtLocation:(CGPoint)point
{
   
    CGContextRef cgctx = [self createARGBBitmapContextFromImage];
    if (cgctx == NULL) { return -1; /* error */ }

   
    size_t w = [self boundingBox].size.width;
    size_t h = [self boundingBox].size.height;
   
    CGRect rect = {{0,0},{w,h}};


    //取得的offset不是原始texture上對應的資料,所以自己算.
    int oriOffsetX = self.offsetPosition.x - (w-self.textureRect.size.width )/2 ;
    int oriOffsetY = self.offsetPosition.y - (h-self.textureRect.size.height)/2 ;
    if (self.flipX) {
        oriOffsetX *= -1;
    }
    if (self.flipY) {
        oriOffsetY *= -1;
    }

    CGPoint oriOffset = CGPointMake(oriOffsetX , oriOffsetY);



    //使用CCSpriteFrame 從目前的CCSprite中建立新的CCSprite .
    //解決CCSprite從spritesheet產生會造成texture是整張大圖的問題.
    CCSpriteFrame *sprFrame = [CCSpriteFrame frameWithTexture:[self texture] rectInPixels:self.textureRect rotated:self.textureRectRotated offset:self.offsetPosition originalSize:CGSizeMake(w, h)];
   
    CCSprite *spr = [CCSprite spriteWithSpriteFrame:sprFrame];
     
  //做跟目前圖形對應的翻轉,這樣取值才正確.
    [spr setFlipX:self.flipX];
    [spr setFlipY:self.flipY];

    CGContextDrawImage(cgctx, rect, [[UIImage convertSpriteToImage:spr] CGImage]);
   
    unsigned char* data = CGBitmapContextGetData (cgctx);
   
    int alpha;
   
    if (data != NULL) {
       
        @try {
            int offset = 4*((w*round(point.y))+round(point.x));
           
            alpha =  data[offset];
        }
        @catch (NSException * e) {
        }
        @finally {
           
        }  
    }
   
    CGContextRelease(cgctx);
   
    if (data) { free(data); }
   
    return alpha;
}

- (CGContextRef)createARGBBitmapContextFromImage
{
   
    CGContextRef    context = NULL;
    CGColorSpaceRef colorSpace;
    void *          bitmapData;
    int             bitmapByteCount;
    int             bitmapBytesPerRow;
   
    size_t pixelsWide = [self boundingBox].size.width;
    size_t pixelsHigh = [self boundingBox].size.height;
   
    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);
   
    if (context == NULL)
    {
        free (bitmapData);
        fprintf (stderr, "Context not created!");
    }
   
    CGColorSpaceRelease( colorSpace );
   
    CGContextSetBlendMode(context, kCGBlendModeCopy);
   
    return context;
}

其中會用到
+(UIImage *) convertSpriteToImage:(CCSprite *)sprite
{
    CGPoint p = sprite.anchorPoint;
    [sprite setAnchorPoint:ccp(0,0)];
    CCRenderTexture *renderer = [CCRenderTexture renderTextureWithWidth:sprite.contentSize.width height:sprite.contentSize.height];
    [renderer begin];
    [sprite visit];
    [renderer end];
    [sprite setAnchorPoint:p];
   
    return [renderer getUIImage];
}
這個 convertSpriteToImage 去將sprite轉成UIImage, 然後再從UIImage 取CGImage 再去處理.
取得對應某一個點的ARGB 的 color[4] , 將alpha 值回傳就是判斷透明度會需要的.

2012年1月18日 星期三

Cocos2d 官方網站查到的 Release Note 中,和舊的 class or method 無法使用有關的修正事項 for 1.0.1.


cocos2d-iphone release-1.0.1 CHANGELOG


利用 deprecat 這樣的關鍵詞彙 可以在 Release Note 裡頭找到一些到 ver 1.0.1 版之後,不再被支援的 method.
//  ------------------------------------------------------------------------------------------------

version 1.0-rc - 29-Mar-2011
. [NEW] All: Removed many deprecated methods and classes that were scheduled for removal on v1.0

version 1.0-beta - 01-Mar-2011
. [NEW] Layer: CCMultiplexLayer deprecated. New name is CCLayerMultiplex

version 0.99.5-rc0 - 25-Oct-2010
. [NEW] AnimationCache: New class. It deprecates the CCSprite#animation methods (issue #848)
. [NEW] Animation: simplified API. Name is no longer needed. Deprecated API that uses name.

version 0.99.5-beta2 31-Ago-2010
. [NEW] Label: CCLabelAtlas#labelAtlasWithString: -> labelWithString. Old method deprecated
. [NEW] Label: CCBitmapFontAtlas deprecated. Use CCLabelBMFont instead.
. [NEW] Label: CCBitmapFontAtlas#bitmapFontAtlasWithString -> labelWithString. Old method deprecated.

version 0.99.5-beta 30-Jul-2010 - AKA 'CJ the artifact killer'
. [NEW] SpriteSheet is deprecatd. Use SpriteBatchNode instead.

//  ------------------------------------------------------------------------------------------------


利用 rename 這樣的關鍵詞彙 可以在 Release Note 裡頭找到一些到 ver 1.0.1 版之後,不再被支援的 method.
//  ------------------------------------------------------------------------------------------------

version 1.0-beta - 01-Mar-2011
. [FIX] Templates: ItunesArtwork renamed to iTunesArtwork (issue #1092)

version 0.99.5-rc1 - 15-Nov-2010
. [FIX] Particles: centerOfGravity renamed to sourcePosition (issue #1026)


version 0.99.5-beta2 31-Ago-2010
. [NEW] Actions: files renamed: CCXXXAction.[hm] -> CCActionXXX.[hm]
. [NEW] Actions: Using new naming convetion:
               CCInstantAction -> CCActionInstant
               CCIntervalAction -> CCActionInterval
               CCEaseAction -> CCActionEase
               CCCameraAction -> CCActionCamera
. [NEW] Action: CCPropertyAction renamed to CCActionTween
. [NEW] Director: New naming convention: CCnameDirector -> CCDirectorName
. [NEW] Label: CCLabel renamed to CCLabelTTF

version 0.99.5-beta 30-Jul-2010 - AKA 'CJ the artifact killer'
. [FIX] Tests: AtlasTest renamed to LabelTest

version 0.99.4-rc3 - 01-Jul-2010
. [FIX] Director: renamed mainLoop -> drawScene

//  ------------------------------------------------------------------------------------------------


疑似與 CCSlideInRTransition to CCTransitionSlideInR 這一類的 method 有關的修正.
CCXxxTransition -> CCTransitionXxx
//  ------------------------------------------------------------------------------------------------

version 0.99.5-beta2 31-Ago-2010
. [NEW] Transitions: new transition naming convention (issue #946)


//  ------------------------------------------------------------------------------------------------
//  ------------------------------------------------------------------------------------------------

----

還在看範例的初學者の小試身手


2011年7月31日 星期日

cocos2d Scene切換特效.

簡單記一下.方便查找..
原本用的是 [[CCDirector sharedDirectorpushScene:[SelectLayer scene]];
把後面的 的 scene替換掉. 改成.
    [[CCDirector sharedDirector] pushScene:
     [CCTransitionSlideInT transitionWithDuration:1.0f scene:[SelectLayer scene]]];
就可以有換景的特效..
除了 CCTransitionSlideInT
還有其他類似的可以用 都是 CCTransition... 開頭.

另外,如果是用 [[CCDirector sharedDirectorpopScene];
無法加上換景的特效.

要加特效的話要在 在 這裡 有人提出一個方法.
1. 修改 CCDirector.h,在 -(void)popScene 下加上
- (void) popSceneWithTransition: (Class)c duration:(ccTime)t;

2.修改 CCDirectior.m , 在 -(void)popScene下加上

-(void) popSceneWithTransition: (Class)transitionClass duration:(ccTime)t;
{
 NSAssert( runningScene_ != nil, @"A running Scene is needed");

 [scenesStack_ removeLastObject];
 NSUInteger c = [scenesStack_ count];
 if( c == 0 ) {
  [self end];
 } else {
  CCScene* scene = [transitionClass transitionWithDuration:t scene:[scenesStack_ objectAtIndex:c-1]];
  [scenesStack_ replaceObjectAtIndex:c-1 withObject:scene];
  nextScene_ = scene;
 }
}

3.用
[[CCDirector sharedDirector] popSceneWithTransition:[CCTransitionSlideInB class] duration:0.5f];

取代原本的 [[CCDirector sharedDirectorpopScene]; 指令即可.
其中的 [CCTransitionSlideInB class] 看需要什麼效果就替換上去.

2011年7月1日 星期五

cocos2d-particle粒子特效

最近在玩cocos2d內建的particle,
cocos2d的專案裡面有particle test範例可以參考,
但是那個參數看的眼花撩亂....
我都是憑感覺去亂調><
後來找到兩個很方便的工具,
可以視覺調整之後輸出參數,
先保留起來....有機會再玩玩它


2011年6月30日 星期四

cocos2d-用ccmenuitem建立button

CCMenuItem *_Btn = [[CCMenuItemImage itemFromNormalImage:@Img_Back //按鈕圖

selectedImage:@Img_BackSelect //click之後的圖

target:self

selector:@selector(Click_Reset:)] retain]; //觸發函數

CCMenu *menu2 = [CCMenu menuWithItems: _Btn, nil]; //建立選單

[self addChild: _Btn z:0];


以上是簡單的按鈕產生方式,

不知有沒有那種按著不放就觸發的方法?

我用愚人法做出來不知道有沒有更簡單的方式,
建立一個schedule跟BOOL開關還有一個rect,
ccTouchesBegan的時候就開啟BOOL,
ccTouchesEnded的時候關閉BOOL,
schedule裡面去判斷BOOL有沒有開啟再去做,

2011年6月29日 星期三

cocos2d-使用plist處理動畫

之前看的知易教學所使用的CCSpriteSheet好像已經不能使用了 (我用1.0.0-rc),
在網路上有找到一篇教學寫得很詳細,

iPhone 程式要間隔一段時間執行某個函式的方法

最基本的就是用NSTimer ..
只是這個要建一個 NSTimer 再做一些設定..
感覺有點麻煩..

有看到另一種方法.
[self performSelector:@selector(test:) withObject:nnil afterDelay:1.0];


2011年6月28日 星期二

cocos2D 使CCSprite可以觸發touch事件

參考來源

把TouchSprite 再改一下..讓它可以設定要執行的動作,這樣就跟用CCMenu差不多了

簡單的說就是,新增一個繼承CCSprite的類別,
且加入並實作 <CCTargetedTouchDelegate> 的協定 .
實作類別如下.


2011年6月27日 星期一

cocos2d-利用NSUserDefaults保存數值

有時候需要在不同的Scene運用某個變數時,
可以利用NSUserDefaults或是NSData保存起來在另外一個Scene運用,
這裡先只講NSUserDefaults的作法(因為我現在只用過這種XD)
//宣告
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];

cocos2D 取得目前執行中的secne或layer

今天因為有需要從某些地方取得目前執行中的layer來做一些事,
所以找了一下作法,並記錄一下免得之後忘了.

[CCDirector sharedDirector]
的功能..
發現其中有一個是.
CCScene *runningSC = [[CCDirector sharedDirector] runningScene];

2011年6月23日 星期四

cocos2D中加入UIView

參考資料

這感覺跟之前的取得RootViewControll很接近..
不過 細部要做的事情.好像還是有一點點不同..

所以就順便記錄一下.之後再依情況使用了.

簡單說
就先建好 UIView 或子類別的元件後.
使用
[[[CCDirector sharedDirector] openGLView] addSubview:obj];
就可以把元件加到rootView上.

2011年6月22日 星期三

cocos2D 上的 ScrollView

資料來源

這位作者 givp ,有整理了一個簡單好用的類別.
CCScrollLayer 是一個CCLayer的子類別.
可以將一群CCLayer加入到CCScrollLayer內,

CCLayer 的內容可以附加Image , Label , Menu 等..

然後再將CCScrollLayer加到scene上.
如此便可方便的呈現出ScrollView效果

使用的方法很簡單.
1.將CCScrollLayer類別的所有檔案加到專案中
2.在scene中import CCScrollLayer.h
3.在scene的init時,設定每一個layer , 再將這群layers加到CCScrollLayer中

範例如下:

2011年6月21日 星期二

cocos2D 存取rootViewController

使用cocos2D 0.99.5 版

要存取RootViewController的方法:

1.
AppDelegate.h 設定 
@property (nonatomic, retain) RootViewController *viewController;
AppDelegate.m 設定
@synthesize viewController;