- Joined
- Jun 12, 2010
- Messages
- 413
This tutorial is a work in progress. I'll finish it up as I manage to put aside some time to do so.
Timers in JASS can be pretty imprecise. The reason for this is the fact thay floating point numbers are used, which are inherently imprecise. One important thing to know in order to understand this tutorial is that floating point numbers can only represent integers and fractions whose divisor is a power of 2 (1/2, 1/4, 7/4, etc.) with 100% precision. Every other number is represented through approximation.
Ilustrating Imprecision
However, normal floating point imprecision does NOT account for timer imprecision. Let's see an example:
As soon as my ticks reach 128 (2 to the power of 8), timer precision greatly decreases. The values are now being incremented by 1008, instead of 1000. However, my timer which was executing in a period that is a power of two is still fine when it comes to precision.
When we reach 256 ticks, precision dips again. This is the maximal imprecision that we will reach for 0.001. Now each timer will execute 24 more times than normal, in other words, it will execute 1024 times per second. This is the closest power of 2 to 1000, so our precision should not go lower for any practical amount of game time.
Handling Imprecision
If you don't want the precision of your timers to vary with time, then you must use a period that is perfectly represented in floating point. The best way to go about this is using fractions.
Good vs bad periods:
1/1024. ~ 0.001
1/128. ~ 0.01
1/64. ~ 1/60. (60 FPS)
Timers in JASS can be pretty imprecise. The reason for this is the fact thay floating point numbers are used, which are inherently imprecise. One important thing to know in order to understand this tutorial is that floating point numbers can only represent integers and fractions whose divisor is a power of 2 (1/2, 1/4, 7/4, etc.) with 100% precision. Every other number is represented through approximation.
Ilustrating Imprecision
However, normal floating point imprecision does NOT account for timer imprecision. Let's see an example:
As soon as my ticks reach 128 (2 to the power of 8), timer precision greatly decreases. The values are now being incremented by 1008, instead of 1000. However, my timer which was executing in a period that is a power of two is still fine when it comes to precision.
When we reach 256 ticks, precision dips again. This is the maximal imprecision that we will reach for 0.001. Now each timer will execute 24 more times than normal, in other words, it will execute 1024 times per second. This is the closest power of 2 to 1000, so our precision should not go lower for any practical amount of game time.
Handling Imprecision
If you don't want the precision of your timers to vary with time, then you must use a period that is perfectly represented in floating point. The best way to go about this is using fractions.
Good vs bad periods:
1/1024. ~ 0.001
1/128. ~ 0.01
1/64. ~ 1/60. (60 FPS)
JASS:
scope aaaaa
globals
private integer seconds = 0
private integer milis = 0
private integer centis = 0
private integer milis2 = 0
private integer tracker = 0
private integer tracker2 = 0
private integer lastMilis = 0
private integer lastCentis = 0
private integer lastMilis2 = 0
private timer clock
private timer clock2
endglobals
private function onMiliPow2 takes nothing returns nothing
set milis2 = milis2 + 1
endfunction
private function onMili takes nothing returns nothing
set milis = milis + 1
endfunction
private function onCenti takes nothing returns nothing
set centis = centis + 1
endfunction
private function onSecond takes nothing returns nothing
local integer miliImprecision = milis - lastMilis - 1000
local integer centiImprecision = centis - lastCentis - 1000
local integer mili2Imprecision = milis2 - lastMilis2 - 1024
set lastMilis = milis
set lastCentis = centis
set lastMilis2 = milis2
set seconds = seconds + 1
call TimerStart(clock, 0.001, true, function onMili)
call BJDebugMsg(I2S(seconds) + "Imprecision: ")
call BJDebugMsg(I2S(centis) + "Imprecision: " + I2S(miliImprecision))
call BJDebugMsg(I2S(milis) + "Imprecision: " + I2S(centiImprecision))
call BJDebugMsg(I2S(milis2) + "Imprecision: " + I2S(mili2Imprecision))
endfunction
//===========================================================================
function InitTrig_Imprecie_Timers takes nothing returns nothing
set clock = CreateTimer()
set clock2 = CreateTimer()
call TimerStart(clock, 0.001, true, function onMili)
call TimerStart(clock2, 0.001, true, function onCenti)
call TimerStart(CreateTimer(), 1/1024., true, function onMiliPow2)
call TimerStart(CreateTimer(), 1., true, function onSecond)
endfunction
endscope