使用 cocos2d 处理对 CCSprite 的触摸的最佳实践

Best practices for handling touches to a CCSprite with cocos2d(使用 cocos2d 处理对 CCSprite 的触摸的最佳实践)

本文介绍了使用 cocos2d 处理对 CCSprite 的触摸的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好.我刚开始研究 cocos2d 库.我听说如果您习惯于使用 ActionScript 进行编程,它是一个很容易进入的库,而且我发现很多概念确实相似.

Hey all. I just started looking into the cocos2d library. I've heard that it's an easy library to get into if you're used to programming in ActionScript and I've found that a lot of the concepts are indeed similar.

我开始浏览示例项目(链接的示例游戏 这里 特别有用),我看到通常不会在 CCSprite 中完成触摸处理.相反,实例化 CCSprites 的 CCLayer 对触摸事件做出反应并遍历它创建的 sprite 以检测哪个 CCSprite 被触摸(如果有).

I started looking through sample projects (the sample games linked here were especially helpful) and I saw that handling of touches usually isn't done in a CCSprite. Rather, the CCLayer that instantiates CCSprites reacts to a touch event and iterates through the sprites it created to detect which CCSprite was touched (if any).

我希望 CCSprites 自己处理它们是否已被触摸,并调用 up 以通知它已被触摸(如果需要)./tests/TouchesTest 下的 Paddle 类就是这样做的——它自己处理触摸.

I want CCSprites to handle whether they've been touched themselves, and call up to notify that it's been touched (if needed). The Paddle class found under /tests/TouchesTest does just this - it handles touches by itself.

所以,我的问题是:什么是最佳实践?在中心位置处理触摸并遍历子项以查看触摸了什么会更好吗?还是每个孩子都应该处理自己的触摸事件?还是没关系?

So, the question I have is: What's considered best practice for this? Is it better to have touches handled in a central location and iterate through children to see what's been touched? Or should each child handle its own touch events? Or does it not matter?

我希望每个孩子都处理自己的触摸事件,但我想遵循这方面的最佳做法(如果存在).谢谢!

I'd prefer each child handling its own touch events but I'd like to follow best practices on this (if they exist). Thanks!

推荐答案

我认为这是一个偏好问题,但我喜欢让 sprite 检测它是否被子类化 CCSprite 所触及.我在我的 CCSprite 子类中创建了一个 getter 方法,该方法从子类中检索状态变量,然后主程序可以相应地采取行动.

I think it is a matter of preference but I like to have the sprite detect if it was touched by subclassing CCSprite. I make a getter method in my CCSprite subclass that retrieves the state variable from the subclass and then the main program can act accordingly.

这是我的 CCSprite 子类spuButton"的示例头文件:

Here is an example header file for my CCSprite subclass "spuButton":

    #import "cocos2d.h"

    typedef enum tagButtonState {
        kButtonStatePressed,
        kButtonStateNotPressed
    } ButtonState;

    typedef enum tagButtonStatus {
        kButtonStatusEnabled,
        kButtonStatusDisabled
    } ButtonStatus;

    @interface spuButton : CCSprite <CCTargetedTouchDelegate> {
    @private
        ButtonState state;
        CCTexture2D *buttonNormal;
        CCTexture2D *buttonLit;
        ButtonStatus buttonStatus;

    }

    @property(nonatomic, readonly) CGRect rect;

    + (id)spuButtonWithTexture:(CCTexture2D *)normalTexture;

    - (void)setNormalTexture:(CCTexture2D *)normalTexture;
    - (void)setLitTexture:(CCTexture2D *)litTexture;
    - (BOOL)isPressed;
    - (BOOL)isNotPressed;

    @end

以下是 .m 文件的示例:

and here is an example of the .m file:

    #import "spuButton.h"
    #import "cocos2d.h"

    @implementation spuButton

    - (CGRect)rect
    {
        CGSize s = [self.texture contentSize];
        return CGRectMake(-s.width / 2, -s.height / 2, s.width, s.height);
    }

    + (id)spuButtonWithTexture:(CCTexture2D *)normalTexture
    {
        return [[[self alloc] initWithTexture:normalTexture] autorelease];
    }

    - (void)setNormalTexture:(CCTexture2D *)normalTexture {
        buttonNormal = normalTexture;
    }
    - (void)setLitTexture:(CCTexture2D *)litTexture {
        buttonLit = litTexture;
    }

    - (BOOL)isPressed {
        if (state == kButtonStateNotPressed) return NO;
        if (state == kButtonStatePressed) return YES;
        return NO;
    }

    - (BOOL)isNotPressed {
        if (state == kButtonStateNotPressed) return YES;
        if (state == kButtonStatePressed) return NO;
        return YES;
    }

    - (id)initWithTexture:(CCTexture2D *)aTexture
    {
        if ((self = [super initWithTexture:aTexture]) ) {

            state = kButtonStateNotPressed;
        }

        return self;
    }

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

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

    - (BOOL)containsTouchLocation:(UITouch *)touch
    {
        return CGRectContainsPoint(self.rect, [self convertTouchToNodeSpaceAR:touch]);
    }

    - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
    {
        if (state == kButtonStatePressed) return NO;
        if ( ![self containsTouchLocation:touch] ) return NO;
        if (buttonStatus == kButtonStatusDisabled) return NO;

        state = kButtonStatePressed;
        [self setTexture:buttonLit];

        return YES;
    }

    - (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
    {
        // If it weren't for the TouchDispatcher, you would need to keep a reference
        // to the touch from touchBegan and check that the current touch is the same
        // as that one.
        // Actually, it would be even more complicated since in the Cocos dispatcher
        // you get NSSets instead of 1 UITouch, so you'd need to loop through the set
        // in each touchXXX method.

        if ([self containsTouchLocation:touch]) return;
        //if (buttonStatus == kButtonStatusDisabled) return NO;

        state = kButtonStateNotPressed;
        [self setTexture:buttonNormal];

    }

    - (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
    {

        state = kButtonStateNotPressed;
        [self setTexture:buttonNormal];


    }

@end

希望这对您有所帮助,祝您编码愉快!

Hope this helps and Happy coding!

添加打勾方法和解释(针对Stephan的问题如下):

ADDITION of tick method and explanation (for Stephan's question below):

要检查按钮的状态,我有一个勾号:基本上触发每一帧并检查我所有按钮的状态的方法.

To check the status of the buttons I have a tick: method that basically fires every frame and checks the status of all my buttons.

    -(void)tick:(ccTime)dt {

do my button checks here....

}

我通过调用我的 spuButton 类中的 isPressed 或 isNotPressed 函数来检查按钮的状态.

I check the status of my buttons by calling a isPressed or isNotPressed function that is part of my spuButton class.

for (spuButton *aButton in _fourButtonsArray) {
     if ([aButton isNotPressed]) continue; //this button is not pressed
     .....otherwise record that it is pressed.....
}

然后我做同样的检查,看看它是否已经被释放并做出相应的回应.我这样做是因为我希望能够对多个按钮按下组合做出反应,而且我想在它被按下时做一些事情,然后在它被释放时做其他事情.我使用 ccTouchBegan 和 ccTouchEnded 来更改纹理(精灵图像)并相应地更改状态变量.

Then I do the same kind of check to see if it has been released and respond accordingly. I do it this way because I want to be able to react to multiple button press combos plus I want to do something when it gets pressed down and then something else when it gets released. I use the ccTouchBegan and ccTouchEnded to change the textures(the sprite image) and to change the state variable accordingly.

这篇关于使用 cocos2d 处理对 CCSprite 的触摸的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:使用 cocos2d 处理对 CCSprite 的触摸的最佳实践