HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Effects Within a Circle

02-25-2010, 12:24 AM#1
Panto
Greets.

I thought this was going to be easy, but I must be tired tonight because it's not coming to me. I want a simple function to create a certain number of effects inside a circle defined by its X, Y, and radius. I created the shell of the function easily enough, but I need to figure out how to find a random point inside the circle to create the effect there.

Here's the shell:
Collapse JASS:
function EffectInAoE takes string sPath, real rX, real rY, real rRad, integer iQty, real rDur returns nothing
    local integer iL = 1
    local effect array fxYay

    loop
        exitwhen iL > iQty
        
        // create effect inside rRad from point rX,rY
        set fxYay[iL] = AddSpecialEffect(sPath, 0, 0)

        set iL = iL + 1
    endloop


    call TriggerSleepAction(rDur)
    set iL = 1
    loop
        exitwhen iL > iQty
        
        call DestroyEffect(fxYay[iL])
        set iL = iL + 1
    endloop
endfunction
I imagine this is quite easy for anyone who's done it before. Help is appreciated.

Thanks.
02-25-2010, 04:41 AM#2
saw792
Collapse JASS:
function EffectInAoE takes string sPath, real rX, real rY, real rRad, integer iQty, real rDur returns nothing
    local integer iL = 1
    local real sqrrad = rRad*rRad
    local real ta = 0
    local real td = 0
    local real x = 0
    local real y = 0
    local effect array fxYay

    loop
        exitwhen iL > iQty
        
        // create effect inside rRad from point rX,rY
        //Option 1: Even probability of any point within circle
        loop
          set x = GetRandomReal(-rRad, rRad)
          set y = GetRandomReal(-rRad, rRad)
          exitwhen (x*x + y*y) <= sqrrad
        endloop
        
        //Option 2: No loop, skewed towards centre of circle
        set ta = GetRandomReal(0, 2 * bj_PI)
        set td = GetRandomReal(0, rRad)
        set x = td * Cos(ta)
        set y = td * Sin(ta)

        set fxYay[iL] = AddSpecialEffect(sPath, x + rX, y + rY)

        set iL = iL + 1
    endloop


    call TriggerSleepAction(rDur)
    set iL = 1
    loop
        exitwhen iL > iQty
        
        call DestroyEffect(fxYay[iL])
        set iL = iL + 1
    endloop
endfunction
02-25-2010, 05:00 AM#3
Earth-Fury
While the random sampling method may seem insane and suboptimal, it is the best method of the two. You get even distribution with only a few cycles wasted on incorrect "attempts".

Also, for god sakes, use timers, not TriggerSleepAction.... (If you couple timerutils with either vJass dynamic arrays or one of the collections (LinkedList, Stack, etc) classes available on this site, it's not a whole lot more complex.)
02-25-2010, 12:17 PM#4
Panto
Thanks guys! I'll give these a shot!
02-25-2010, 02:34 PM#5
Ammorth
Collapse JASS:
        //Option 3: No loop, even distribution
        set ta = GetRandomReal(0, 2 * bj_PI)
        set td = SquareRoot(GetRandomReal(0, 1))*rRad
        set x = td * Cos(ta)
        set y = td * Sin(ta)
02-25-2010, 04:50 PM#6
Anitarf
Getting a random point in a square is likely the fastest even when taking the wasted cycles into account (which make it slower by a mere 27%). Regardless, I prefer the method Ammorth posted, it just feels more "correct" than doing it through trial&error.
02-26-2010, 04:12 AM#7
Panto
Super! I went with Ammorth's suggestion first and found it completely to my liking. Thanks for the help, guys!