# Cocos 2D - Hold down CCMenuItem

I am using the following code to move a CCSprite left and right.

-(id)init{
CCMenuItemImage * moveLeftButton = [CCMenuItemImage itemFromNormalImage:@"Move Left Button.png" selectedImage:@"Move Left Button.png" target:self selector:@selector(moveLeftVoid:)];
}
-(void)moveLeftVoid{
id moveLeft = [CCMoveBy actionWithDuration:.3 position:ccp(-10, 0)];
[_mainSprite runAction:moveLeft];
}


This does work, but only as a single tap. What I want for the CCSprite to move continously in that direction when the CCMenuItem is held down. Then when it's released the character stops moving. If you need to see more code, please just ask. :) Thanks

Another approach is to subclass the CCMenuItemImage object. You can override the two functions -(void)selected and -(void)unselected to determine when the user has pressed and is holding.

I think the CCMenu (and the CCMenuItem) is not appropriated in your case. Indeed, the CCMenu is designed to fire an event only when a touch up inside an item occured, nothing else.

I should you to use the CCControlButton (from the CCControlExtension). This component works like a UIButton and thereby you can know when a user touches down your button and when he touches up. So while the button is pushed you can schelude your "moveLeftVoid" method each among of time and unschedule it when the button is released.

If you are traying to implement some kind of touch controller I suggest you to use SneakyInput

Extremely easy to create analog sticks, dpad, buttons and It's totally customizable(skinnable).

It's been a while since the last update but works fine with the latest stable cocos2d

I wanted this sort of thing too. I looked at both of the CCControlButton and SneakyInput options, but decided against them. CCControlButton didn't really do what I wanted, plus it seems to assume/require you to use a CCScale9Sprite, which for a simple button in a game, is too much work.

SneakyInput, upon analysis seems to schedule it's own update events which seems overkill and inefficient to me.

So, I wrote a simple subclass of CCMenuItemSprite which allows a second block to be provided. When the user taps, the first block is called, when the user releases, the second block is called. It might be worthwhile to add a check to ensure that the hold isn't fired unless the button is held for at least a second, but for a game, I'm not sure it's a good idea. I'll leave that to those that follow.

The code can be found at: CCExtensions

Instead of overriding the selected method, I simply used the isSelected variable.

Change this:

   -(id)init{
CCMenuItemImage * moveLeftButton = [CCMenuItemImage itemFromNormalImage:@"Move Left Button.png" selectedImage:@"Move Left Button.png" target:self selector:@selector(moveLeftVoid:)];
}
-(void)moveLeftVoid{
id moveLeft = [CCMoveBy actionWithDuration:.3 position:ccp(-10, 0)];
[_mainSprite runAction:moveLeft];
}


To this:

-(id)init{
CCMenuItemImage * moveLeftButton = [CCMenuItemImage itemFromNormalImage:@"Move Left Button.png" selectedImage:@"Move Left Button.png" ];
}
}


And in your scheduler method do something like:

 if(moveLeftButton.isSelected){

//change your position according to (ccTime) dt

//maybe something like:
_mainSprite.position = CGPointMake(_mainSprite.position.x - 10/.3*dt,_mainSprite.position.y);

}

• In my case, I am working with Box2D, so all I did in the if statement is set the velocity of my player. – tiffanyButterfly23 May 30 '13 at 19:07