Stuck trying to implement touch and hold (bullet firing)?

Hi, I’ve been having a lot of trouble implementing a smooth and reliable touch-and-hold solution for firing bullet (sprites) - even after looking through this forum and Stack Overflow for help.

The solution has to switch between touch-began, touch moved and touch ended seamlessly: always firing bullets at the touch location until the finger is released. At the moment I have many problems with reliability and stability with every case but touchmoved, which works fine.

The exact issue is around half the time a finger is held down (touchBegan + scheduler) the bullets appear but disappear a second later but other times they move towards the touch perfectly - something is deleting them and i don’t have much experience with schedulers or actions to know what.

Heres the code, of special importance is the scheduling at the bottom of init(), the touch methods, and the 2 bullet firing methods. Or if you’ve got your own implementation, equally useful. Thanks in advance!

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !CCLayer::init() )
    {
        return false;
    }
    
    visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    visibleOrigin = CCDirector::sharedDirector()->getVisibleOrigin();
	
	player = CCSprite::create("player.png");//, CCRectMake(0, 0, 64, 128));    2 argument constructor optional
	CCPoint playerOrigin = ccp(160, 320); //160,140
	player->setPosition(playerOrigin);
	this->addChild(player, 1);
	
	screenHeld = false;
	
	gun = CCSprite::create("gun.png");
	this->addChild(gun, 2);
	firePoint = ccp(gun->getPosition().x + 13, gun->getPosition().y);
	
	cursor = CCSprite::create("cursor.png");
	this->addChild(cursor);
	
	pLabel = CCLabelTTF::create("", "Arial", 24);
    pLabel->setPosition(ccp(visibleSize.width/2,visibleSize.height-100));
    // add the label as a child to this layer
    this->addChild(pLabel, 1);

	this->setTouchEnabled(true);
	
	this->scheduleUpdate(); //game logic every frame
	
	this->schedule(schedule_selector(HelloWorld::fireBullets), 0.05);	

    return true;
}

void HelloWorld::update(float dt)
{
	gun->setPosition(ccp(player->getPosition().x+27, player->getPosition().y + 8));
}	

void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
		CCTouch* touch = (CCTouch*)( pTouches->anyObject() );               // get single-touch as opposed to multitouch

		touchLocation = CCDirector::sharedDirector()->convertToGL(touch->getLocationInView());
		
		
		if (touchLocation.x <= 400 && !jumping && onGround)
		{
			jumping = true;
			jumpStartTime = getTimeTick();
		}
		
		if (touchLocation.x > 400)
		{
			float dX = touchLocation.x - gun->getPosition().x;
			float dY = touchLocation.y - gun->getPosition().y;
			
			touchAngle = atan2(dY, dX);  
			gun->setRotation(-CC_RADIANS_TO_DEGREES(touchAngle));
			
			cursor->setPosition(touchLocation);
			
			screenHeld = true;
			
			//fireBullet(touchAngle);
		}
}

void HelloWorld::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)
{
		CCTouch* touch = (CCTouch*)( pTouches->anyObject() );               // for single-touch as opposed to multitouch
		
		touchLocation = CCDirector::sharedDirector()->convertToGL(touch->getLocationInView());
		
		//CCRect lever1Box = lever1->boundingBox();
		//if(lever1Box.containsPoint(location)) ...
		
		if (touchLocation.x > 400)
		{	
			float dX = touchLocation.x - gun->getPosition().x;
			float dY = touchLocation.y - gun->getPosition().y;
			
			float angle = atan2(dY, dX);  
			gun->setRotation(-CC_RADIANS_TO_DEGREES(angle));
			
			cursor->setPosition(touchLocation);
			
			screenHeld = false; //not technically true but touchMoved bullet firing works differently (not scheduled, every movement instead)
			
			if (getTimeTick() - lastBulletFire > 50)
			{
				fireBullet(angle);
			}
		}
}

void HelloWorld::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
{	
	screenHeld = false;
        //note: this is not the problem because I removed it and problem remained
        //as in, I removed screenHeld requirement and bullet firing was still erratic
}

//this is for touchMoved and works fine, everytime finger is moved bullet fired
void HelloWorld::fireBullet(float angle) 
{
	CCSprite* bullet = CCSprite::create("bullet.png");
	bullet->setPosition(ccp(gun->getPosition().x, gun->getPosition().y)); //add a random spread to the y value (or maybe the y-value of the destination)
	this->addChild(bullet, 5);
	
	bullet->setRotation(-CC_RADIANS_TO_DEGREES(angle));
	
	bullet->runAction(CCSequence::create(CCMoveBy::create(1.5f, ccp(800 * cos(angle), 800 * sin(angle))), NULL));
	
	lastBulletFire = getTimeTick();
}

//this is for touchBegan and has issues, scheduled to run every 50ms touch-held
void HelloWorld::fireBullets(CCTime dt) 
{
	if (screenHeld)
	{
	CCSprite* bullet = CCSprite::create("bullet.png");
	bullet->setPosition(ccp(gun->getPosition().x, gun->getPosition().y));
	bullet->setRotation(-CC_RADIANS_TO_DEGREES(touchAngle));
	
	bullet->runAction(CCSequence::create(CCMoveBy::create(1.5f, ccp(800 * cos(touchAngle), 800 * sin(touchAngle))), NULL));
	
	this->addChild(bullet, 5);
	}
}

float HelloWorld::getTimeTick() {
    timeval time;
    gettimeofday(&time, NULL);
    unsigned long millisecs = (time.tv_sec * 1000) + (time.tv_usec/1000);
    return (float) millisecs;
}