0
votes

I'd really like to get to the bottom of why this code causes intermittent response to touch input... Even with NSLog as the first instruction...

I've just made a new project in cocos2d with Box2d for a game that at this stage needs to just a few simple things...

A basket that appears in the centre of the screen. It must be a b2Fixture and fall onto a surface. Then if the user touched the screen, I want the basket to zoom to the touch point, and from there the user can drag it around the screen.

When the user lets go, the basket drops... I have this working right now...

However the BUG is that touching the screen doesn't always work... It intermittently responds to touches, and therefore intermittently calls the methods.

As you will see below, I have used NSLog to check when each methods are being called. The result is that sometimes you have to lift your finger off the screen and then back on several times, and then "seemingly at random", it will decide to run the code....

Heres what I got...

My touch methods....

-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"Multi Touch Moved...");
    if (_mouseJoint == NULL) return;

    UITouch *myTouch = [touches anyObject];
    CGPoint location = [myTouch locationInView:[myTouch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];
    b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);

    _mouseJoint->SetTarget(locationWorld);
}

-(void)ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event
{
    NSLog(@"\nThe touch was CANCELED...");
}

-(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
    NSLog(@"Single Touch Moved...");
}

- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *myTouch = [touches anyObject];
    CGPoint location = [myTouch locationInView:[myTouch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];
    b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);

    NSLog(@"\n\nTouch did begin...");

    if (_mouseJoint != NULL)
    {
        _mouseJoint->SetTarget(locationWorld);
        NSLog(@"The IF statment was met...");
        return;
    }

    NSLog(@"The IF statment was NOT met...Running _mouseJoint setup...");

    b2MouseJointDef md;
    md.bodyA = _groundBody;
    md.bodyB = _body;
    md.target = _body->GetPosition();
    md.collideConnected = true;
    md.maxForce = 100000000.0f * _body->GetMass();
    _mouseJoint = (b2MouseJoint *)_world->CreateJoint(&md);
    _body->SetAwake(true);

    _mouseJoint->SetTarget(locationWorld);
}

-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (_mouseJoint != nil) {
        _world->DestroyJoint(_mouseJoint);
        _mouseJoint = nil;
    }
}

And this is the interface that some of the code refers to...

@interface HelloWorldLayer : CCLayerColor
{
b2World *_world;
    b2Body *_body;
    b2Fixture *_bodyFix;
    b2MouseJoint *_mouseJoint;
    b2Body *_groundBody;
}

The only idea another member helped me determine is, that because I'm working within a single scene, and I have/had a CCMenu and a CCLabelTTF on the screen, is it possible that the CCMenu is still intercepting touches, and if so, how can I destroy the CCMenu after my animation has finished?

Pressing the only button item simply CCmoves the title and label(CCMenuItem) off the screen vertically... But the object still exists...

1
have you tried both simulator and device? And device works fine with other apps? Are you perhaps tapping in the control center / notification area (bottom/top row of screen)? Do you have another finger (or other object interpreted as touch) on the screen but multi touch is not enabled?LearnCocos2D
Nope, it's none of that... I've tried simulator and real devices. Am defiantly in the near center of the screen.phpN00b
try to reproduce it in a blank cocos2d project with just the touches methods and logs. I wager it 's got something to do with how the scene is setup, ie other nodes receiving and swallowing touches.LearnCocos2D
It's a brand new project with only a single main. Got the std intro layer, and helloworldlayer. There's nothing amazing on there, if u like, I'd send u the project file.phpN00b
OOOOOO..... Idea, you might be close! I am working within a single scene, and I have/had a CCMenu and a CCLabelTTF on the screen... Pressing the only button item simply CCmoves the title and label(CCMenuItem) off the screen vertically... Is it possible that the CCMenu is still intercepting touches, and if so, how can I destroy the CCMenu after my animation has finished?phpN00b

1 Answers

1
votes

The problem here was that my CCMenu was still receiving touches (I assume in parts of the screen where the CCMenuItems where formed).

The solution was to declare my CCMenu in my @implementation rather than in my init scene setup.

@implementation HelloWorldLayer
{
    CCLabelTTF *label;
    CCLabelTTF *startTheGameLabel;
    CCSprite *theCattery;
    CCMenu *_menu;
}

Then in my init, rather than declaring it there, i simply assign to the one in the @implementation.

-(id) init { if( (self=[super initWithColor:ccc4(50, 180, 220, 255)]) )
{
    //.. Other "irrelevant to question" scene setup stuff here...//

    // Start the game button
    startTheGameLabel = [CCLabelTTF labelWithString:@"Save Some Kitties!" fontName:@"Zapfino" fontSize:20];
    CCMenuItemLabel *startTheGameLabelItem = [CCMenuItemLabel itemWithLabel:startTheGameLabel target:self selector:@selector(startGameStub:)];

    // Push the menu
    _menu = [CCMenu menuWithItems: startTheGameLabelItem, nil];
    [self addChild:_menu];

    //.. Other "irrelevant to question" scene setup stuff here...//
}

This gives me access to the CCMenu throughout my class, so I can later disable touch input once the user has made a selection.

-(void) startGameStub:(id)sender
{
    CGSize size = [[CCDirector sharedDirector] winSize];

     // Clear the labels off the screen
    CMoveTo *moveTheTitleLabelAction = [CCMoveTo actionWithDuration:1.0 position:ccp(label.position.x, size.height + label.boundingBox.size.height)];
    CCMoveTo *moveTheStartLabelAction = [CCMoveTo actionWithDuration:1.0 position:ccp(startTheGameLabel.position.x, size.height + startTheGameLabel.boundingBox.size.height)];

    // Commit actions
    [label runAction:moveTheTitleLabelAction];
    [startTheGameLabel runAction:moveTheStartLabelAction];

    // LIFE SAVING MESSAGE!!!
    [_menu setTouchEnabled:NO]; // This is what fixes the problem
}