0

I have a gamepad with a direction pad and 2 buttons. All of them are digital (not analog).

I have a procedure for handling their events:

-(void)gamepadTick:(float)delta
{
    ...
    if ([gamepad.B active]) {
        [ship shoot];
    }
    ...
}

And I call it via a command:

[self schedule:@selector(gamepadTick:) interval:1.0 / 60];

[ship shoot] calls shoot function from Weapon class:

-(void)shoot
{
    Bullet *bullet = [Bullet bulletWithTexture:bulletTexture];
    Ship *ship = [Ship sharedShip];
    bullet.position = [ship getWeaponPosition];
    [[[CCDirector sharedDirector] runningScene] addChild:bullet];

    CGSize winSize = [[CCDirector sharedDirector] winSize];
    int realX = ship.position.x;
    int realY = winSize.height + bullet.contentSize.height / 2;
    CGPoint realDest = ccp(realX, realY);

    int offRealX = realX - bullet.position.x;
    int offRealY = realY - bullet.position.y;
    float length = sqrtf((offRealX*offRealX) + (offRealY*offRealY));
    float velocity = 480/1; // 480pixels/1sec
    float realMoveDuration = length / velocity;

    [bullet runAction:[CCSequence actions:[CCMoveTo actionWithDuration:realMoveDuration position:realDest],
                       [CCCallFuncN actionWithTarget:self selector:@selector(bulletMoveFinished:)], nil]];
}

-(void)bulletMoveFinished:(id)sender
{
    CCSprite *sprite = (CCSprite *)sender;
    [[[CCDirector sharedDirector] runningScene] removeChild:sprite cleanup:YES];
}

The problem is the weapon shoots too much of bullets. Is it possible to reduce their amount without writing using of timers and functions which are separate for each button and direction pad?

Gargo
  • 704
  • 6
  • 16

2 Answers2

1

Use Delta to keep track of the time between shoots, and only shoot if delta has incremented by a certain amount. This is a common way of doing things that you don't want every frame.

You will need to keep an iVar counter of time elapsed, increment it by Delta on each shoot, then test the amount of time elapsed to see if it meets your desired interval threshold; if it does, then shoot and reset the time elapsed to 0.

johnbakers
  • 24,158
  • 24
  • 130
  • 258
  • +1, but I have found a concrete example of the same thing. If nobody wants to try then i'l post it – Gargo Apr 03 '12 at 22:00
0
-(void) update:(ccTime)delta {
totalTime += delta;
if (fireButton.active && totalTime > nextShotTime) {
    nextShotTime = totalTime + 0.5f;
    GameScene* game = [GameScene sharedGameScene];
    [game shootBulletFromShip:[game defaultShip]];
}
// Allow faster shooting by quickly tapping the fire button if (fireButton.active == NO)
{
    nextShotTime = 0;
}
}

it is an original code from "learn cocos2d game development" book by Steffen Itterheim. But I can improve this code a little.

Updated

It is harder to understand my code than the original one but it has a correct structure. It means the following: - global timer belongs to a scene; - ship can shoot via weapon; - weapon can shoot with bullets and delay between bullets belong to this weapon (not the scene as in the original example)

Scene class contains totalTime variable, a ship object and the following method to handle timer updating:

-(void)update:(ccTime)delta
{
    totalTime += delta;

    if (!fireButton.active) {
        ship.weapon.nextShotTime = 0;
    } else if (totalTime > ship.weapon.nextShotTime) {
        [ship.weapon updateNextShotTime:totalTime];
        [ship shoot];
    }
}

Ship class contains a weapon object and a shoot method (this method is not actual for this question).

Weapon class contains nextShotTime variable and the following method:

-(void)updateNextShotTime:(ccTime)currentTime
{
    nextShotTime = currentTime + 0.05f;
}
Gargo
  • 704
  • 6
  • 16