# Implementing Attack-Speed( Delay )- help please :-)

This topic is 4862 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello all! I am trying to implement an attackspeed(attack delay) formula from an other game(ro)! I have no idea how I can implement the delay to my game. (okay, i have.. but it isn't right! ^^ ) I am using SDL. Here is my code that calculates the delay:
// variables the calculations are based on
// ASpd is improved by your Job, the Weapon Speed of the
// Weapon/s  you are wielding, your Agility
const int WeaponDelay = 70;
const int Agi = 10;
const int Dex = 10;
const float ImprovementPercentages = 0;

// calculat extra_speed from items
const float SPEED_MODS = (100-ImprovementPercentages)/100;

// get delay reduces from agi and dex
// agi helps more than dex!
const float delay_agi = floor( WeaponDelay* (Agi/25) );
const float delay_dex = floor( WeaponDelay* (Dex/100) );
const float delay_agi_dex =(delay_agi + delay_dex)/10;

// get final delay
const int delay = static_cast<int>( ceil(SPEED_MODS *(WeaponDelay - delay_agi_dex)) );

But how can I use the delay now? I am using SDL
if((SDL_GetTicks() - Ticks) >= 1000) // what here? :O
{
// strike..
}

Formula:
Delay = SpeedMods * (WeaponDelay - ([WeaponDelay*Agi/25] + [WeaponDelay*Dex/100])/10)

Extra-infos:
You can calculate your Swings/Minute as 60/(Delay/50).
This is because each point of Weapon Delay is equal
to 1 frame on the screen. There are 50 frames per second
and of course 60 seconds per minute.
This can be further simplified to 3000/Delay.

Thank you very much for your help guys! :-) [Edited by - rakoon2 on August 21, 2004 6:42:55 PM]

##### Share on other sites
Pseudo code :

if (SDL_GetTick() - PreviousTick > delay)
{
{
strike
player asked for strike = false
PreviousTick = SDL_GetTicks()
}
]

HTH,

##### Share on other sites
yes! :-) but the delay number is so low.. (40-75) but 1 sec is 1000 in SDL. must i mulitplicate the number with 10? Or so?

##### Share on other sites
What I do is this

delaycounter = 0;
delay = 50;

proc player_fire()
if player fired then
if (delaycounter <= 0) then
fireweapon()
delaycounter = delay
end if
end if
end proc

proc player_update(frameTick)
// Do movement stuff here, etc

if (delaycounter > 0) then
delaycounter -= frameTick;
end if
end proc

Each frame ticks in miliseconds and decreases the fire limiting timer, so to get your delay to be in seconds, instead of miliseconds simply multiply (desired seconds * 1000). So to wait around half a second, use delaycounter = 0.5 * 1000

##### Share on other sites
Oh! :) And frametick is: SDL_GetTick() - PreviousTick ? hm...
Thank you!

##### Share on other sites
Yup, that's the one. Unless you're using a fixed timestep, that is. I generally have the game do the tick caluculation and have each update routine take a tick as a paramter, that way you know they're all updating the same - plus you could put in fixed time stepping without breaking it too, if you need it.

##### Share on other sites

frameTick = SDL_GetTicks() - Ticks; // this one is wrong too?!
if( attack_with_bow > 0 )
{
if( delaycounter < 0 )
{
// FIRE !!
const int delay = player->getDelay_bow();

delaycounter = delay*10; // this one is wrong!

attack_with_bow--;
}
}
delaycounter -= frameTick;
Ticks = SDL_GetTicks();

Can you tell me what I do wrong? Please :-) Thank you!

##### Share on other sites
Delay counter, Ticks and frameTick is in your class or is global, or passed as a parameter, right?

eg:

class player
{
public:
player() : delayCounter(0), fireDelay(0.5f)
{
// firedelay is set at 0.5 seconds
}

float delayCounter;
float fireDelay;

void updatePlayer(float frameTick)
{
if (delayCounter > 0 )
delayCounter -= frameTick;
}

void fireBow()
{
if (delayCounter <= 0)
{
// Fire!
delayCounter = fireDelay;
}

}
};

// Then in your game somewhere

Game::Update()
{
float frameTick = SDL_GetTick() - lastTicks;

if (fire_bow_key_pressed)
{
player->fireBow( frameTick );
}

// Reset keyboard, etc.
lastTick = frameTick;

}

##### Share on other sites
Well, that was just a test.. That code was in the game::gameLoop
code!

Delay is a number btwn 0 and WeaponDelay. WeaponDelay is 70 for bows.

float frameTick = SDL_GetTick() - lastTicks;

must be
UINT32 frameTick = SDL_GetTick() - lastTicks;

Delay = SpeedMods * (WeaponDelay - ([WeaponDelay*Agi/25] + [WeaponDelay*Dex/100])/10)

I don't care about design yet.. I want to get it to work first.

gameloop:

int delaycounter = 0;
int frameTick = 0;
Uint32 Ticks = 0;

//...
//...

const int delay = player->getDelay_bow();
frameTick = SDL_GetTicks() - Ticks;
if( delaycounter <= 0 )
{

// fire
delaycounter = delay*10; // what here? delay is a nr btw 0 and ~75( or more )
// you shoot faster if the delay is lower!
}
if( delaycounter > 0 )
delaycounter -= frameTick;

Ticks = frameTick;

gives me crazy results!
delaycounter gets lower and lower
and frameTick higher and higher..!

Thank you!! :-/

##### Share on other sites
I forgot to say, I always scale the value I get back from GetTicks(), so Tick = GetTicks() / 1000; This way you get a fraction of a second and it can be used as a scalar.

If you use all ints however, you should still get the right results (I just prefer seeing it in 'real' seconds).

The effect you should be getting is that frameTick stays about the same and is linked to the speed of your game, and that delay counter should decrease if higher than 0. When delaycounter is 0 or less, the player can fire. If it's higher, it can't.

The problem is that frametick gets higher each time, I think. Are you sure it's getting calculated properly? I mean, is Ticks keeping it's value from the last frame?

##### Share on other sites
This seems to work! :-)

const int delay = player->getDelay_bow();
frameTick = (SDL_GetTicks()/1000) - Ticks;
if( delaycounter <= 0 )
{
//fire
delaycounter = delay;
}
if( delaycounter > 0 )
delaycounter -= frameTick;

Ticks = frameTick;

but it doesn't work in the first ~5secs!

##### Share on other sites
Make sure delay counter is set to zero, also that when the game starts, Tick is the same as frameTick.

Glad you got it working! [grin]

##### Share on other sites
Hmm! ok it isn't working! I shoot faster and faster..! I don't change the delay! BUt it still gets faster and faster over time. :/
Here is my code:

1.: Variable declaration:

int delaycounter = 0;
int frameTick = 0;
Uint32 Ticks = 0;

int fire_arrows = 0;

2.: update delay

frameTick = (SDL_GetTicks()/1000) - Ticks;
if( delaycounter > 0 )
delaycounter -= frameTick;

Ticks = frameTick;

3.: check if key is pressed

// if attack key is pressed:
if( delaycounter <= 0 )
{
fire_arrows++;
const int delay = player->getDelay_bow();
delaycounter = delay;
}

4.: spawn arrow

and in the end:
if( fire_arrows > 0 )
{
//spawn error object
fire_arrows--;
}

5.: go to 1.

Thank you! :/

##### Share on other sites
Right, first off - don't scale frameTicks by 1000 if you're not scaling delay by 1000. If you scale it by 1000, you want to use floats as the delayCounter and frameTick.

In level_init() or whatever, you need to set up your variables.

float delaycounter = 0;
float frameTick = 0;
float Ticks = frameTick;

int fire_arrows = 0;

In game_tick() you need to calculate the tick and update the delay

// calc tick count
frameTick = (float)(SDL_GetTicks() / 1000) - Ticks;
if( delaycounter > 0 )
{
delaycounter -= frameTick;
}

Ticks = frameTick;

// check keypresses
// if attack key is pressed:
if( delaycounter <= 0 )
{
// delay counter is at 0, can fire
delaycounter = player->getDelay_bow();
}

Do not set tick, frametick, etc to zero after the frame is updated. They need to persist through the game.

Why are you incrementing fire_arrows? What does that variable signify? As far as i can tell, you're either a) Setting the trametick, tick, etc to zero on each frame or the problem has something to do with how you're using fire_arrows.

I really can't tell any more from here. [shrug]

##### Share on other sites
here is a screenshot, what I get if I wait a little.
I shoot them faster and faster!
http://members.chello.at/ennemoser/time_bug.jpg

Here is the code related to it:

float delaycounter = 0;
float frameTick = 0;
float Ticks = frameTick;

while( done == false )
{
//....
frameTick = static_cast<float>( (SDL_GetTicks() / 1000) ) - Ticks;

if( delaycounter > 0 )
delaycounter -= frameTick;

Ticks = frameTick;

if( attack_key_Is_Pressed == true )
{
if( delaycounter <= 0 )
{
const int delay = player->getDelay_bow();
delaycounter = delay;
// now spawn the arrow
}
}
//....
}

Help please!:/ Thank you very very much!

##### Share on other sites
This is how I would do it:

float delaycounter = 0;
float frameTick = 0;
float Ticks = frameTick;

while( done == false )
{
//....
frameTick = static_cast<float>( SDL_GetTicks() ) / 1000.0f - Ticks;

delaycounter += frameTick;

Ticks += frameTick;

if( attack_key_Is_Pressed == true )
{
if( delaycounter >= static_cast<float>(player->getDelay_bow()) ) // be consistant on casts
{
delaycounter = 0;
// now spawn the arrow
}
}
//....
}

[EDIT] I spotted a pair of important bugs in the timer code!

##### Share on other sites
Oh, thank you. But that deosn't work too! I shoot more and more arrows over time! Why?

http://members.chello.at/ennemoser/time_bug.jpg

This one doesn't even let me spawn an arrow! ( nothing happens if I press the key )

frameTick = ( static_cast<float>( SDL_GetTicks() ) / 1000.0f ) - Ticks;
delaycounter += frameTick;
Ticks += frameTick;
//..
if( key_is_pressed == true )
{
if( delaycounter >= static_cast<float>(player->getDelay_bow()) )
{
// spawn arrow
delaycounter = 0;
}
}
//..

Thank you..! :3

:edit:
I just logged the delaycounter to a logfile.log every frame:

LOG FILE
contains errors/infos from the last game-start
0.159
0.233
0.276
0.313
0.349
0.384
0.422
0.457
0.493
0.528
0.562
0.598
0.638
0.681
0.719
0.757
0.794
0.829
0.865
0.904
0.94
0.976
1.01
1.047
1.097
1.131
1.169
1.207
1.241
1.277
1.313
1.347
1.384
1.42
1.454
1.489
1.527
1.565
1.601
1.637
1.675
1.711
1.749
1.784
1.82
1.855
1.89
1.927
1.966
2.002
2.037
2.075
2.108
2.144
2.181
2.22
2.255
2.291
2.328
2.364
2.421
2.466
2.491
2.517
2.543
2.568
2.593
2.619
2.645
2.67
2.695
2.726
2.753
2.781
2.808
2.841
2.871
2.898
2.928
2.955
2.985
3.013
3.041
3.068
3.097
3.125
3.153
3.181
3.211
3.244
3.281
3.308
3.336
3.364
3.388
3.414
3.441
3.469
3.496
3.524
3.551
3.575
3.601
3.627
3.652
3.696
3.729
3.755
3.783
3.814
3.954
4.111
4.196
4.234
4.259
4.292
4.326
4.354
4.388
4.417
4.508
4.533
4.56
4.587
4.615
4.645
4.67
4.697
4.729
4.759
4.791
4.819
4.848
4.876
4.905
4.934
4.962
4.991
5.018
5.049
5.085
5.116
5.146
5.174
5.207
5.239
5.268
5.297
5.322
5.348
5.373
5.398
5.427
5.455
5.483
5.516
5.545
5.574
5.602
5.63
5.656
5.684
5.71
5.738
5.764
5.792
5.819
5.848
5.876
5.901
5.938
5.977
6.013
6.047
6.078
6.107
6.136
6.163
6.193
6.223
6.254
6.28
6.305
6.333
6.358
6.389
6.417
6.443
6.476
6.506
6.533
6.568
6.595
6.623
6.648
6.674
6.701
6.729
6.754
6.779
6.805
6.83
6.857
6.882
6.907
6.933
6.958
6.985
7.011
7.038
7.065
7.093
7.119
7.153
7.184
7.217
7.245
7.27
7.298
7.325
7.353
7.381
7.412
7.443
7.469
7.498
7.526
7.552
7.579
7.618
7.647
7.675
7.702
7.731
7.765
7.795
7.822
7.851
7.882
7.911
7.938
7.963
7.992
8.018
8.048
8.075
8.102
8.129
8.16
8.192
8.261
8.301
8.333
8.359
//..

this seems to low.. I will never reach the delay_bow in this way!

##### Share on other sites
ohhk.. I found the bug in the Thunder_Hawk/my/our last attempt

Ticks += frameTick;
should be
Ticks = frameTick;

But I still have the bug that let the arrows spawn faster and faster: http://members.chello.at/ennemoser/time_bug.jpg
Why? :/

##### Share on other sites
You said that the delay was somewhere between 40 and 75, right? Those units are obviously in milliseconds, but here they are being compared to seconds. In other words, you will have to wait between 40 and 75 seconds between bow firings. A quick fix would be to change this line:

if( delaycounter >= static_cast<float>(player->getDelay_bow()) ) // be consistant on casts

to:

if( delaycounter >= static_cast<float>(player->getDelay_bow())/1000.0f ) // be consistant on casts

Also, I neglected this is my first post, but if you're using my way , you have to initialize delayCounter to the bow's delay.

float delaycounter = static_cast<float>(player->getDelay_bow())/1000.0f;
float frameTick = 0;
float Ticks = frameTick;

##### Share on other sites
Quote:
 Original post by rakoon2ohhk.. I found the bug in the Thunder_Hawk/my/our last attempt*** Source Snippet Removed ***But I still have the bug that let the arrows spawn faster and faster: http://members.chello.at/ennemoser/time_bug.jpgWhy? :/

Don't do that!! That introduces the arrows spawning faster and faster bug. Just read my previous post.

##### Share on other sites
Oh nice! It works great now! :-)

Thank you very much:

Thunder_Hawk,
evolutional
and Emmanuel Deloget !!

##### Share on other sites

This topic is 4862 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628702
• Total Posts
2984298

• 23
• 10
• 9
• 13
• 13