WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Graphics Help (https://www.wowinterface.com/forums/forumdisplay.php?f=14)
-   -   "Pulsating" effect...what's the proper method? (https://www.wowinterface.com/forums/showthread.php?t=30271)

nightcracker 02-06-10 06:43 AM

Quote:

Originally Posted by Hati-EK (Post 177537)
Code:

last_update = last_update -0.25
is more precise and does not skip seconds (even if this would just be some miliseconds) than reseting the whole value to 0 - (ie last_update could be 0.25182965 - so you would missing 0.00182965 - if you have this ~1000 times there's something missing

Nope, because THIS time if you run at 120 fps then the function would run a lot more then when at 10 fps.

Hati-EK 02-06-10 08:08 AM

Quote:

Originally Posted by nightcracker (Post 177542)
Nope, because THIS time if you run at 120 fps then the function would run a lot more then when at 10 fps.

this is right - at 120fps the function is more fluently ... as the frequency is another - 1/120 vs. 1/10 - but the sampling frequency is 0.25 - so at 120fps it would take 30frames to match the sampling frequency - with 10fps it would take 2.5frames (3frames as there are NO floating frames)


120 fps:
approx. elapsed = 1/120 = 0.0083333333333333s per OnUpdate ( called frequence g in rest of text )
sampling frequency f = 0.25 Hz (or 4fps = 1/4Hz)
f = 30*g
so every 30-frame((n*30)%120, n<-N{0,1,2,..) the SinusFunction() is called - at this point it works fine

now think of ppl having an average fps of not 120fps - like you said 10fps
drawing frequency h = 1/10 Hz
sampling frequency f = 0.25 Hz
resulting that point of collide = frame2.5, as there is no frame 2.5, it will take frame 3 (>=)
time between frame2.5 and frame3 is t=((frame3-frame2)/2);
frame2 is drawn after 0.2s, frame3 after second 0.3 (on time graph) - would result in a 0.05s delay

so with last_update=0, it will result in:
frame1 drawn - frame2 drawn - frame3 drawn - function fires, last_update is now 0 again - frame4 drawn - frame5 drawn (NOW it should fire again - but it doesn't as this is again 0.2 not 0.25) - frame6 drawn - function fires and again 3 frames required


with last_update=last_update-sampling_frequency:
frame1 drawn - frame2 drawn - frame3 drawn - function fires, last_update now is 0.05 - frame4 drawn (last_update 0.15) - frame5 drawn(last_update 0.25) - function fires correctly at (50% of fps as it should with sampling frequency 0.25 - and not at 60%) - frame 6 drawn - etc...


and ppl have not an average fps of continuously 120fps (atleast not the most have)

Torhal 02-06-10 08:30 AM

Quote:

Originally Posted by Hati-EK (Post 177537)
Code:

last_update = last_update -0.25
is more precise and does not skip seconds (even if this would just be some miliseconds) than reseting the whole value to 0 - (ie last_update could be 0.25182965 - so you would missing 0.00182965 - if you have this ~1000 times there's something missing

This is true, if you're looking to be precise.

nightcracker 02-06-10 08:31 AM

Quote:

Originally Posted by Hati-EK (Post 177548)
this is right - at 120fps the function is more fluently ... as the frequency is another - 1/120 vs. 1/10 - but the sampling frequency is 0.25 - so at 120fps it would take 30frames to match the sampling frequency - with 10fps it would take 2.5frames (3frames as there are NO floating frames)


120 fps:
approx. elapsed = 1/120 = 0.0083333333333333s per OnUpdate ( called frequence g in rest of text )
sampling frequency f = 0.25 Hz (or 4fps = 1/4Hz)
f = 30*g
so every 30-frame((n*30)%120, n<-N{0,1,2,..) the SinusFunction() is called - at this point it works fine

now think of ppl having an average fps of not 120fps - like you said 10fps
drawing frequency h = 1/10 Hz
sampling frequency f = 0.25 Hz
resulting that point of collide = frame2.5, as there is no frame 2.5, it will take frame 3 (>=)
time between frame2.5 and frame3 is t=((frame3-frame2)/2);
frame2 is drawn after 0.2s, frame3 after second 0.3 (on time graph) - would result in a 0.05s delay

so with last_update=0, it will result in:
frame1 drawn - frame2 drawn - frame3 drawn - function fires, last_update is now 0 again - frame4 drawn - frame5 drawn (NOW it should fire again - but it doesn't as this is again 0.2 not 0.25) - frame6 drawn - function fires and again 3 frames required


with last_update=last_update-sampling_frequency:
frame1 drawn - frame2 drawn - frame3 drawn - function fires, last_update now is 0.05 - frame4 drawn (last_update 0.15) - frame5 drawn(last_update 0.25) - function fires correctly at (50% of fps as it should with sampling frequency 0.25 - and not at 60%) - frame 6 drawn - etc...


and ppl have not an average fps of continuously 120fps (atleast not the most have)

What I say now I assuming you meant this:

Code:

do
        local last_update = 0
        local updater = CreateFrame("Frame", nil, UIParent)

        updater:Hide()
        updater:SetScript("OnUpdate",
                          function(self, elapsed)
                                  last_update = last_update + .25

                                  if last_update <= -.25 then
                                          RunSinFunction()
                                          last_update = 0
                                  end
                          end)
end

Then that is equal to this:
Code:

do
        local start = 0
        local updater = CreateFrame("Frame", nil, UIParent)

        updater:Hide()
        updater:SetScript("OnUpdate", function(self, elapsed)
                start = start + .25
                SomeFrame:SetAlpha(math.sin(start))
        end)
end

Which means that the speed of the pulsing is determined by your FPS, not the amount of fluentness(is that a word?).

Hati-EK 02-06-10 08:41 AM

Quote:

Originally Posted by nightcracker (Post 177555)
What I say now I assuming you meant this:

Code:

do
        local last_update = 0
        local updater = CreateFrame("Frame", nil, UIParent)

        updater:Hide()
        updater:SetScript("OnUpdate",
                          function(self, elapsed)
                                  last_update = last_update + .25

                                  if last_update <= -.25 then
                                          RunSinFunction()
                                          last_update = 0
                                  end
                          end)
end

Then that is equal to this:
Code:

do
        local start = 0
        local updater = CreateFrame("Frame", nil, UIParent)

        updater:Hide()
        updater:SetScript("OnUpdate", function(self, elapsed)
                start = start + .25
                SomeFrame:SetAlpha(math.sin(start))
        end)
end

Which means that the speed of the pulsing is determined by your FPS, not the amount of fluentness(is that a word?).


nah
i meant this :
Code:

do
        local last_update = 0
        local updater = CreateFrame("Frame", nil, UIParent)

        updater:Hide()
        updater:SetScript("OnUpdate",
                          function(self, elapsed)
                                  last_update = last_update + elapsed

                                  if last_update >= 0.25 then
                                          RunSinFunction()
                                          last_update = last_update-0.25
                                  end
                          end)
end


Quote:

Originally Posted by Torhal (Post 177554)
This is true, if you're looking to be precise.

well it's a sinus function - where little differences may cause weird results or atleast not nice looking ones ;)

nightcracker 02-06-10 08:42 AM

Oh I see... That's pretty amazing :P

I still think though that using sin every quarter of a second isn't NEARLY as efficient then multiplying by -1. And I see the disadvantage of my function, it uses SetAlpha WAAAAAAAAAY too often. This should be much much more efficient.

Code:

frame.mult = 1
frame.alpha = 1
frame.tslu = 0 -- time since last update
frame:SetScript("OnUpdate", function(self, elapsed)
        self.tslu = self.tslu + elapsed
        if self.tslu > .25 then
                self.tslu = 0
                self:SetAlpha(self.alpha)
        end
        self.alpha = self.alpha - elapsed*self.mult
        if self.alpha < 0 and self.mult > 0 then
                self.mult = self.mult*-1
                self.alpha = 0
        elseif self.alpha > 1 and self.mult < 0 then
                self.mult = self.mult*-1
        end
end)

Final question, is it efficienter to use solution #1 or #2? I can hardly imagine that mod is faster then setting a variable to a table, but I may be wrong since frames have metatables etc etc etc...

#1
Code:

self.tslu = self.tslu + elapsed
if self.tslu > .25 then
        self.tslu = 0
        self:SetAlpha(self.alpha)
end

#2
Code:

self.tslu = self.tslu + elapsed
if self.tslu%.25 < .125 then
        self:SetAlpha(self.alpha)
end


Hati-EK 02-06-10 08:53 AM

Quote:

Originally Posted by nightcracker (Post 177560)
Final question, is it efficienter to use solution #1 or #2? I can hardly imagine that mod is faster then setting a variable to a table, but I may be wrong since frames have metatables etc etc etc...

#1
Code:

self.tslu = self.tslu + elapsed
if self.tslu > .25 then
        self.tslu = 0
        self:SetAlpha(self.alpha)
end

#2
Code:

self.tslu = self.tslu + elapsed
if self.tslu%.25 < .125 then
        self:SetAlpha(self.alpha)
end


well to #2:
i would say permanently incrementing of a variable may cause an overflow (dunno about max value in lua) - as you aren't calc the modulo and store it

Code:

self.tslu = (self.tslu + elapsed)%.25
if self.tslu <= elapsed then
        self:SetAlpha(self.alpha)
end

might be better

zork 02-12-10 06:57 AM

If I hadn't stopped playing atm I would post you an example with the animation system.

Using onUpdates to do this is out of date.

Slakah 02-12-10 10:52 AM

Quote:

Originally Posted by zork (Post 178293)
If I hadn't stopped playing atm I would post you an example with the animation system.

Using onUpdates to do this is out of date.

Is the animation system more efficient?

Haleth 02-12-10 12:24 PM

Sorry for thread hijack, but how can this code be applied to a single animation instead of a looping 'pulse'? I'm trying to add opening/closing animations to some addon frames, for example in the following code:

Code:

local function Stuffing_Open()
        Stuffing.frame:Show()
end


local function Stuffing_Close()
        Stuffing.frame:Hide()
end

I've tried a couple of things, but no luck.

Hati-EK 02-12-10 12:55 PM

Quote:

Originally Posted by Haleth (Post 178316)
Sorry for thread hijack, but how can this code be applied to a single animation instead of a looping 'pulse'? I'm trying to add opening/closing animations to some addon frames, for example in the following code:

Code:

local function Stuffing_Open()
        Stuffing.frame:Show()
end


local function Stuffing_Close()
        Stuffing.frame:Hide()
end

I've tried a couple of things, but no luck.

maybe you are looking for

frame:SetScript('OnShow', doSomethingOnShow)

or frame:SetScript('OnHide', doSomethingOnHide)

?

nightcracker 02-12-10 01:17 PM

Quote:

Originally Posted by Slakah (Post 178307)
Is the animation system more efficient?

It's not more efficient, the mem/cpu usage does get dumped at the blizzard addons(so it seems more efficient).

Smacker 06-25-10 08:39 AM

Use the built-in animation code:

Code:

        local alpha = animationGroup:CreateAnimation("Alpha");
        alpha:SetOrder(order);
        alpha:SetDuration(duration);
        alpha:SetMaxFramerate(fps);
        alpha:SetChange(alphaTo);


Dawn 06-26-10 02:07 PM

Arrrr, sometimes thread necrotism is good stuff, indeed. I somehow missed this one. *bookmarks thread* :D

tsadok 06-28-10 01:28 AM

Quote:

Originally Posted by nightcracker (Post 177560)
Oh I see... That's pretty amazing :P

I still think though that using sin every quarter of a second isn't NEARLY as efficient then multiplying by -1. And I see the disadvantage of my function, it uses SetAlpha WAAAAAAAAAY too often. This should be much much more efficient.

I may be wrong, but setting the alpha of a frame is not CPU intensive. The graphics engine works hard, whatever the alpha is, whether it has changed or not. Using sine I think would give a more pleasing looking pulse.

lieandswell 07-30-10 01:21 PM

If you wanted to use the Blizzard animation API in XML, you could do something like:

Code:

<Frame>
    ...
    <Animations>
        <AnimationGroup name="$parentPulse" parentKey="pulse" looping="BOUNCE">
            <Alpha change="-1" duration="1.5"/>
        </AnimationGroup>
    </Animations>
    <Scripts>
        <OnLoad>
            self.pulse:Play();
        </OnLoad>
    </Scripts>
</Frame>



All times are GMT -6. The time now is 11:51 PM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI