1

子供向けの非常にシンプルな Cocos2d 教育ゲームの作成が完了しました。このゲームでは、ユーザーが文字または数字でバブルし、特定の文字またはアルファベットをポップするようにユーザーに指示する音声が表示されます。ほとんどの場合、ゲームは問題なく動作しますが、「Pop the Letter R」と表示されることがあります。そして、タッチしてポップしようとしても、ポップしません。これは 10% の確率で発生し、アプリをアプリ ストアに送信できません。どこが欠けているのかよくわかりません。

ランダムなアルファベットまたは数字を選択する方法:

以下のコードのオプションは、A から Z までのアルファベットで構成される NSMutableArray にすることができます。

-(void) populateRandomBubbles:(NSMutableArray *) options 
{
    int randomNumber;
    int randomBubbleColor; 
    NSString *option = @"";

    for(int i=0;i<self.gamePlaySettings.noOfBubblesToDisplay;i++) 
    {
        randomNumber = arc4random() % options.count; 
        randomBubbleColor = arc4random() % self.bubbleColors.count; 
        option = [options objectAtIndex:randomNumber];

        CGPoint point = [self getRandomPointOnScreen]; 

        // add first bubble 
        Bubble *bubble = [[Bubble alloc] initWithColor:[self getRandomBubbleColor]];
        bubble.delegate = self; 
        bubble.text = option; 
        bubble.soundFile = [[option stringByAppendingPathExtension:@"caf"] lowercaseString];
        bubble.sprite.position = point; 

        bubble.tag = [option characterAtIndex:0];

        [bubble setStringForLabel:bubble.text];

        if([self getChildByTag:bubble.tag] == nil)
        {
            if(  (int) (self.bubbles.count) < self.gamePlaySettings.noOfBubblesToDisplay)
            {
                [self.bubbles addObject:bubble];
            }
        }
        else 
        {
            i--;
        }
    }

    // set the randomly selected alphabet 

    randomNumber = arc4random() % self.bubbles.count; 

    Bubble *bubble = [self.bubbles objectAtIndex:randomNumber];
    bubble.isSelected = YES;

    // play sound 
    [self.environment playSoundByFileName:bubble.soundFile];

}

Bubble クラスは以下のように定義されています。

@implementation Bubble

@synthesize soundFile,text,isSelected,color,label,delegate = _delegate;

-(id) initWithColor:(NSString *)bubbleFile
{
    self = [super init];
    self.sprite = [CCSprite spriteWithFile:bubbleFile];
    [self addChild:self.sprite];
    return self; 
}

-(void) pop
{

    CCParticleExplosion *explosion = [[CCParticleExplosion alloc] init];
    explosion.position = self.sprite.position;
    [explosion setAutoRemoveOnFinish:YES];
    [self.parent addChild:explosion];
    [self.parent removeChild:self cleanup:YES];

    Environment *environment = [[Environment alloc] init]; 
    [environment playPopSound];
}

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {

    if([self containsTouchLocation:touch]) 
    {   
        // if this is the correct bubble then pop the bubble 

        if(self.isSelected) 
        {

            [self pop];
            [_delegate onBubblePop:self];

        }
        return YES;
    }

    return NO; 
}

BaseNode は以下で定義されます。

@implementation BaseNode

@synthesize sprite;

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

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

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

- (BOOL)containsTouchLocation:(UITouch *)touch
{
    BOOL isCollided = CGRectContainsPoint([self.sprite boundingBox], [self convertTouchToNodeSpace:touch]);

    return isCollided; 

}

バグがどこにあるのでしょうか?

更新 1:

オリジナルにも貼り付けられている次のコードは、重複がないことを確認します。重複に遭遇したことがないので、うまく機能しているようです。

 if([self getChildByTag:bubble.tag] == nil)
        {
            if(  (int) (self.bubbles.count) < self.gamePlaySettings.noOfBubblesToDisplay)
            {
                [self.bubbles addObject:bubble];
            }
        }
4

4 に答える 4

1

私は問題を解決したかもしれません。問題は、バブル コレクション内のオブジェクトが一意であることを確認するためのチェックを行っていなかったことだと思います。更新されたコードは次のとおりです。

NSArray *bubbleAlreadyInArray = [self.bubbles filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"tag == %d",bubble.tag]];


        if([self getChildByTag:bubble.tag] == nil)
        {
            if(  (int) (self.bubbles.count) < self.gamePlaySettings.noOfBubblesToDisplay)
            {
                // only add to the bubbles array if not already added!
                if(bubbleAlreadyInArray.count == 0)
                {
                [self.bubbles addObject:bubble];
                }
            }
        }
        else 
        {
            i--;
        }

NSPredicate を使用するよりも良い方法があるのだろうかと思いますが、今のところ問題なく動作し、重複は発生しません。

于 2012-04-17T15:52:26.770 に答える
1

これを使用して、重複がないことを確認してください

int length = [YOURBUBBLEARRAY count];
NSMutableArray *indexes = [[NSMutableArray alloc] initWithCapacity:length];
for (int i=0; i<length; i++) [indexes addObject:[NSNumber numberWithInt:i]];
NSMutableArray *shuffle = [[NSMutableArray alloc] initWithCapacity:length];
while ([indexes count])
{
    int index = rand()%[indexes count];
    [shuffle addObject:[YOURBUBBLEARRAY objectAtIndex:index]];
    [indexes removeObjectAtIndex:index];
}
[indexes release];

Bubble *bubble = [shuffle objectAtIndex:randomNumber];

それが役立つことを願っています

于 2012-04-17T14:29:32.743 に答える
0

実はここにある…

[self.parent removeChild:self cleanup:YES];

する必要があります

[self.parent removeChild:self.sprite cleanup:YES];
于 2012-04-17T14:40:13.317 に答える
0
The game works fine most of the time but sometimes the game says "Pop the Letter R".

問題は... 正しい文字 r をポップしていますか? 重複の使用を回避するコードは何もありません。画面に 2 つの r が同時に表示されている可能性があり、そのうちの 1 つを押しても、もう 1 つのアクションがトリガーされません。

Bubble *bubble = [self.bubbles objectAtIndex:randomNumber];

重複がある場合、両方のバブルを設定していません。

于 2012-04-17T14:14:06.430 に答える