2011年6月28日 星期二

cocos2D 使CCSprite可以觸發touch事件

參考來源

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

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




------------------------------------------------------------------------------------------------------
//  TouchSprite.h

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

@interface TouchSprite : CCSprite <CCTargetedTouchDelegate> {

    id targetCallback_;
    SEL selector_;
}
- (id)initWithFile:(NSString *)filename target:(id)target selector:(SEL)selector;
@end
------------------------------------------------------------------------------------------------------
//  TouchSprite.m
#import "TouchSprite.h"

@implementation TouchSprite

- (id)initWithFile:(NSString *)filename target:(id)target selector:(SEL)selector{

    self = [super initWithFile:filename];
    if (self) {
        targetCallback_ = target;
        selector_ = selector;
    }
    
    return self;
}

- (void)dealloc{
    targetCallback_ = nil;
    selector_ = nil;
    [super dealloc];
}


- (void)onEnter{
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:1 swallowsTouches:NO];
    [super onEnter];
}

- (void)onExit{
    [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
    [super onExit];

- (CGRect)rect{
    CGSize s = [self boundingBox].size;
    return CGRectMake(-s.width / 2, -s.height / 2, s.width, s.height);
}
- (BOOL)containsTouchLocation:(UITouch *)touch{
    return CGRectContainsPoint(self.rect, [self convertTouchToNodeSpaceAR:touch]);
}


- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
    if([self containsTouchLocation : touch]){
        NSLog(@"Touch Began");

        [targetCallback_ performSelector:selector_];

    }
    return YES;
}

- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{
    if([self containsTouchLocation : touch]){
        NSLog(@"Touch Ended");
    }
}
@end
------------------------------------------------------------------------------------------------------

後來發現這個沒辦法達到我要的效果....


然後找了一下,發現只要用





CCSprite *p1Spr = [[CCSprite alloc] initWithFile:@"scene.png"];
CCSprite * p1Sprselected = [[CCSprite alloc] initWithFile:@"scene.png"];

CCMenuItemSprite *p1Ment = [CCMenuItemSprite itemFromNormalSprite:p1Spr selectedSprite:p1Sprselected target:self selector:@selector(toLevelSelect:)]; 
CCMenu *mn1 = [CCMenu menuWithItems:p1Ment, nil];
[pageOne addChild:mn1];
這樣就可以做到我想要的
用sprite顯示一張圖, 然後點擊到圖的範圍就可以執行我要的動作....


同樣內容的東西 產生兩個CCSprite , 是因為
CCMenuItemSprite itemFromNormalSprite:xxx selectedSprite:yyy target:...
這邊的xxx跟yyy不能是同一個來源,不然會出錯..

6 則留言:

  1. 我做法不一樣

    是直接使用這三種
    - (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
    - (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
    - (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

    這個去開關touch
    self.isTouchEnabled = YES;

    touch事件裡面加入
    UITouch *myTouch = [touches anyObject];
    CGPoint TouchPoint = [myTouch locationInView:[myTouch view]];
    TouchPoint = [[CCDirector sharedDirector]convertToGL:TouchPoint];
    CGRect rect = TouchRect;
    //範圍內
    if (CGRectContainsPoint(rect, TouchPoint))
    {
    }

    回覆刪除
  2. 我的好像比較囉唆XD

    回覆刪除
  3. http://www.hksilicon.com/kb/articles/17030/UIButton?mobi=true

    不規則形狀的UIButton

    剛好看到,晚點再來研究.

    回覆刪除
  4. 在 TouchSprite中加上
    id targetCallback_;
    SEL selector_;

    再用
    [targetCallback_ performSelector:selector_];
    不知道可不可以

    回覆刪除
  5. to Eveian:
    我最近才剛準備動到和 touch event 有關的操作 ... 所以才剛玩 XD

    妳用到的 touch event method 好像是iOS 本身提供的手段 ^^
    如果是 cocos2d 的 lib 提供的是下面這三類,剛好傳遞進入的參數有些許的差異:

    - ( BOOL ) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
    - ( void ) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
    - ( void ) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
    - ( void ) ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event

    然後 touch event 內的檢查和妳提到的方式有點類似,不過因為是 cocos2d 本身提供的座標系統,所以不用再透過 convertToGL 的手段進行座標值轉換的作業。

    內容大致是這樣:
    CGPoint localPoint;
    CGRect rect;
    CCSprite * pSprite;

    for loop ...
    {
    pSprite = [ ... 略];
    localPoint = [pSprite convertTouchToNodeSpaceAR: touch];
    rect = [self AtlasRect: pSprite];
    if ( CGRectContainsPoint( rect, localPoint) == YES ) // 這裡是判斷的地方 ...
    {
    }
    } // end of for loop.

    回覆刪除
  6. 不用再透過 convertToGL 的手段, 這個寫法好像有點怪怪的,改成 透過其他手段轉換 好像比較恰當 XD

    ----
    回文不能改的啊 >"<

    回覆刪除