HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Circular Motion

12-19-2006, 12:59 PM#1
zen87
I'm trying to make some circular motion effect that looks something like this
Collapse JASS:
function CreateCircularEffect takes string model, unit target, real radius, real angle, real speed returns unit
...
...
endfunction

what it does is make an effect (lets's say, farseer missle) at certain angle (9o'clock for example) and it moves circular around the target unit with the speed v, returns the dummy unit so that i can destroy it by using KillUnit(e) later.

well my problem now is that i have totally no idea how to write this i figured some of the spell makers here might have made something like this so i wish you could share how you done it .

p/s : my map have caster systems installed so if you need to put any native such as NewTimer() or ReleaseTimer(t) will not be a problem

million thanks !!
12-19-2006, 01:09 PM#2
moyack
special effects only can be moved if they are attached to a unit. So you should create a dummy unit, preferably changing its model by the effect you want to use, and trigger the unit movement.
12-19-2006, 01:17 PM#3
zen87
oh yeah i forgot that special effect cant be moved... fixed post#1
12-19-2006, 01:56 PM#4
PurplePoot
start a timer, and inside the loop, just say

Collapse JASS:
local real x = GetUnitX( around ) + radius * Cos( angle * bj_DEGTORAD )
local real y = GetUnitY( around ) + radius * Cos( angle * bj_DEGTORAD )
//safety check goes here, if you want one
call SetUnitX( rotator, x )
call SetUnitY( rotator, y )

Assuming that around is unit Target, radius is real Radius, angle is real Angle, and rotator is unit SFX (the unit that spins) from your call at the top of the function

Is this what you needed, or do you need to be shown how to pass stuff through timers, etc, etc as well?
12-19-2006, 08:43 PM#5
PipeDream
Basic questions can often be answered by taking a peek at the tutorials section. These should get you started:
http://www.wc3campaigns.net/showthread.php?t=89072
http://www.wc3campaigns.net/showthread.php?t=82489
http://www.wc3campaigns.net/showthread.php?t=82663
http://www.wc3campaigns.net/showthread.php?t=88052
http://www.wc3jass.com/viewtopic.php?t=1999
12-20-2006, 02:54 AM#6
zen87
ah thanks pipe !! I think i got it, i've tried to search for timer tutorials but it came out some other stuff, what ya gave there really help alot :D
12-20-2006, 08:46 AM#7
zen87
uhh... i have some question here, whats the different between these two ? I'm not sure which should i use for the angle of rotation per cycle...

Collapse JASS:
native Atan     takes real x returns real
native Atan2    takes real y, real x returns real
12-20-2006, 08:54 AM#8
PipeDream
Atan2(y,x) roughly means Atan(y/x). You want to use Atan2 because it extracts quadrant information (-y,x != y,-x; -y,-x != y,x) and because x=0 will give you a divide by zero if you use Atan.
12-20-2006, 09:13 AM#9
zen87
oh ic ! totally understand ! thanks !!

ah... i finally get the trigger working ><, it looks like this
Collapse JASS:
function CircularEffect_child takes nothing returns nothing
 local timer t = GetExpiredTimer()
 local unit u = GetAttachedUnit(t,"CricDummy")
 local unit c = GetAttachedUnit(t,"CricTarget")
 local real x = GetUnitX(c)
 local real y = GetUnitY(c)
 local real a = GetAttachedReal(t,"CricAngle") + AngleBetweenPointsEx(x,y,GetUnitX(u),GetUnitY(u))
 local real r = GetAttachedReal(t,"CricRadius")
    if GetAttachedBoolean(u,"CricDestroy") or GetWidgetLife(c)<=0.405 then
        call DestroyEffect(GetAttachedEffect(u,"CricEffect"))
        call CleanAttachedVars(u)
        call CleanAttachedVars(t)
        call RecycleCaster(u)
        call ReleaseTimer(t)
    else
        call CS_MoveUnit(u,PolarProjectionX(x,r,a),PolarProjectionY(y,r,a))
        call SetUnitFacingTimed(u,a,0.04)
    endif
 set c=null
 set u=null
 set t=null
endfunction

function CreateCircularEffect takes string e, unit c, real a, real r, real v returns unit
 local unit u = GetACaster()
 local timer t = NewTimer()
 local real x = GetUnitX(c)
 local real y = GetUnitY(c)
 local effect sfx
    call CS_MoveUnit(u,PolarProjectionX(x,r,a),PolarProjectionY(y,r,a))
    if e!=null and e!="" then
        set sfx = AddSpecialEffectTarget(e,u,"origin")
        call AttachObject(u,"CricEffect",sfx)
        set sfx = null
    endif
    call AttachObject(t,"CricDummy",u)
    call AttachObject(t,"CricTarget",c)
    call AttachReal(t,"CricAngle",Atan2(v*0.04,r)*57.2958)
    call AttachReal(t,"CricRadius",r)
    call TimerStart(t,0.04,true,function CircularEffect_child)
    set t=null
    return u
endfunction

function DestroyCircularEffect takes unit u returns nothing
    call AttachBoolean(u,"CricDestroy",true)
endfunction

p/s oh yeah... i forget that i've used some of my own native there, here is it
Collapse JASS:
function PolarProjectionX takes real x, real dist, real angle returns real
    return x + dist*Cos(angle*0.017453)
endfunction

function PolarProjectionY takes real y, real dist, real angle returns real
    return y + dist*Sin(angle*0.017453)
endfunction

function AngleBetweenPointsEx takes real x1, real y1, real x2, real y2 returns real
    return 57.2958*Atan2(y2-y1,x2-x1)
endfunction

function DistanceBetweenPointsEx takes real x1, real y1, real x2, real y2 returns real
    return SquareRoot(Pow(x1-x2,2)+Pow(y1-y2,2))
endfunction
12-20-2006, 10:02 AM#10
PipeDream
Since this is one of those rare places where you need speed, I would:
- Use radians. No need for the extra bj_DEGTORAD and bj_RADTODEG constants you've written in-they're just reciprocal.
- Instead of using Pow(x1-x2,2), use (x1-x2)*(x1-x2).
- If NewTimer()/ReleaseTimer() is what I think it is set t = null is unnecessary
- set u = null will do nothing since you capture it in the function where you return the dummy. You don't need it anyway since, like the timers, it goes in a pool and isn't deallocated (again, if it is what I think it is.)
- You could inline the math functions, but that's really something that we should figure out how to do automatically.