【问题标题】:Timed Events with Cocos2dCocos2d 的定时事件
【发布时间】:2011-12-22 16:51:33
【问题描述】:

我正在寻找建议,也许还有一些例子。我试图弄清楚如何创建CCSprite 并让玩家在创建后尽可能靠近int aCertainAmountOfTime 触摸它。我希望玩家的分数取决于他们击中物品的 1 秒标记的接近程度,过早或过晚得分较低。

最好通过创建某种日程更新或打勾来解决这个问题?我从来没有这样做过,我对它的逻辑有点困惑。我了解需求,但不了解如何实施。

我知道这个问题含糊不清,但我有点迷茫,任何建议都将不胜感激。有人可以分享一个基本示例,说明计划的更新滴答何时相关,以及代码的外观?

感谢您处理我的歧义=D

【问题讨论】:

    标签: objective-c cocos2d-iphone touch scheduled-tasks


    【解决方案1】:

    我的解决方案很简单,你只需要将这个添加到你的 CCSprite 类的 init 方法中:

    [self scheduleUpdate];
    

    然后 update 只计算自创建以来的时间(lifeTime 是在类'@interface 中声明的浮点 ivar):

    -(void) udpate:(ccTime)delta
    {
       lifeTime += delta;
    }
    

    当用户触摸精灵时,只需将 lifeTime 减去 1 即可得到相对于 1 秒的时间差:

    -(void) playerTouchedMe
    {
       int diff = lifeTime - 1.0f;
    }
    

    如果 diff 为负数,则玩家过早接触了这么多秒。如果 diff 是正数,那么玩家触碰的时间太晚了这么多秒。为了获得绝对差异,您可以使用 fabsf,即基本上它只是删除了符号(如果有的话):

    int absoluteDiff = fabsf(diff);
    

    完成。

    【讨论】:

    • 这似乎是一个不错的方法。增量部分很重要。
    • 我认为我最喜欢这个答案。你能解释一下在 CCSprite 类中添加scheduleUpdate 的实际作用吗?我试图推断你在这里给我的信息,所以我可以在其他地方使用这些概念。感谢您的宝贵时间!
    • scheduleUpdate 只是指示 Cocos2D 每帧调用一次 -(void) update:(ccTime)delta 方法。这通常用于每帧推进游戏,例如更改精灵的位置等。
    【解决方案2】:

    根据您的解释,我认为安排更新来处理这个问题会有点矫枉过正而且毫无意义。

    您可以通过组合 CCSprite 和 NSDate 来创建对象,以保存它在场景中的放置时间(可能在 -(void)onEnter 上),添加触摸检测(CCTouchDispatcher 的 addTargetedDelegate)并比较触摸日期和触摸日期之间的差异创建日期和您的时间。

    如果您需要代码示例,请告诉我,我稍后会添加。这是用手机写的。

    编辑:添加缺失的代码

    @interface TimedObject : CCNode <CCTargetedTouchDelegate> {
        CCSprite    *sprite_;
        NSDate      *spawnDate_;
        NSUInteger  amountOfTime_;
    }
    
    -(id)initWithSprite:(CCSprite *)sprite andTime:(NSUInteger)amountOfTime;
    
    @end
    
    @implementation TimedObject
    
    -(id)initWithSprite:(CCSprite *)sprite {
        if (self = [super init]) {
            sprite_ = sprite;
            [sprite_ setPosition:ccp(sprite_.contentSize.width * 0.5, sprite_.contentSize.height * 0.5)];
            [self addChild:sprite_];
    
            [self setContentSize:sprite_.contentSize];
    
            amountOfTime_ = amountOfTime;
        }
    }
    
    -(void)onEnter {
        [super onEnter];
    
        [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
    
        spawnDate_ = [[NSDate date] retain];
    }
    
    -(void)onExit {
        [super onExit];
    
        [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
        [spawnDate_ release];
        spawnDate_ = nil;
    }
    
    - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
    
        CGPoint touchLocation = [touch locationInView:touch.view];
        touchLocation = [self convertToNodeSpace:touchLocation];
    
        CGRect touchArea;
        touchArea.origin = CGPointZero;
        touchArea.size = self.contentSize;
    
        if(CGRectContainsPoint(touchArea, touchLocation)) {
            // Tapped inside
    
            NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:spawnDate_];
    
            // Check here and handle
            if (interval > amountOfTime) {
                // over
            }
            else {
    
            }
    
            return YES;
        }
    
        return NO;
    }
    
    @end
    

    【讨论】:

    • 计划更新是多余的,但这不是吗?我认为情况正好相反。
    • 这只会在点击时访问对象。通过安排更新,您每秒更改对象的状态 60 次。就它可能更简单的编码而言,我觉得它不需要访问和更改浮动。
    • 也许是这样,但这是一个非常非常便宜的操作。
    【解决方案3】:

    我会通过创建一个 sprite 的子类来做到这一点,比如 MySprite,里面有一个浮点计数器作为私有成员实例。

    然后在你的主循环中说

    -(void) nextFrame:(ccTime) dt {
    
    [mysprite tick:dt]
    
    if( mysprite.isExpired ) {
      //stuff here
    }
    

    在您的触摸方法中,当您触摸精灵时,您可以获得

    float score = mysprite.score;
    

    实现 tick 和属性 isExpired 和 score 非常简单

    -(void) tick:(ccTime) dt {
      counter += dt; //increment the private counter
    }
    

    @property (readonly, nonatomic) BOOL isExpired;

    -(BOOL) isExpired {
    return counter > TIME_LIMIT ? YES : NO;
    }
    

    和@property (readonly, nonatomic) 浮点分数只是根据经过的时间返回您的计算机分数

    【讨论】:

      【解决方案4】:

      创建一个CCNode 子类。我们称之为Custom。在Custom 中,将有一个CCSprite 实例(称为mySprite)和一个float 属性(称为myTimer)。到目前为止,我们得到了这样的结果:

      #import <Foundation/Foundation.h>
      #import "cocos2d.h"
      
      @interface Custom : CCNode {
          CCSprite *mySprite;
          float myTimer;
      }
      @property(readwrite)float myTimer;
      @end
      

      很好。记得在Custominit函数中初始化myTimer。该值为0.0

      现在转到您的游戏场景。在这里,我们将设置一个时间表。转到你的游戏场景的init函数并输入:

      [self schedule:@selector(updateCustomTimers:)interval:0.1];
      

      当然,您必须在游戏场景类中创建一个updateCustomTimers 方法。很好,现在您要做的就是遍历您拥有的每个 Custom 实例并增加它们的计时器:

      -(void)updateCustomTimers {
          for (Custom *myCustomInstance in arrayOfCustomInstances) {
              myCustomInstance.myTimer += 0.1;
          }
      }
      

      请注意,arrayOfCustomInstances 是一个 NSMutableArray,它应该包含游戏场景中的所有 Custom 实例。因此,每当您创建一个新的 Custom 实例时,也将其添加到数组中。

      现在您可以为游戏中的每个精灵(包装在自定义类中)更新单独的计时器。从这里开始得分计算应该很容易(您可以使用myTimer float 属性访问您获得的任何Custom 实例的计时器)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多