HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Circular movement

04-15-2009, 11:11 AM#1
Flame_Phoenix
Hi guys, I am trying to make a spell that creates a summon with his own life (a flying bird).
this is not hard, however I want him to move in a "circular" fashion. This means, I want him to move in circles to places. Also he must be able to attack enemies in circular fashion. I saw some spells doing it, but they are poorly coded. So I wonder, is there a good solution any of you may know?
04-15-2009, 11:40 AM#2
Bobo_The_Kodo
Cos / Sin

use angle instead of position and do in expire:

Collapse JASS:
local Data d = GetTimerData( t )

local real x = GetUnitX( d.caster )
local real y = GetUnitY( d.caster )

local real tx
local real ty

set d.angle = d.angle + VELOCITY/ (2*bj_PI*d.dist)

set tx = x + d.dist * Cos( d.angle )
set ty = y + d.dist * Sin( d.angle )

Or you can use constant angle increase, instead of based off of radius...

If you want it done by velocity,acceleration, acceleration is always perpendicular to velocity towards center of circle
04-15-2009, 11:47 AM#3
akolyt0r
what you mean with "attack in circular fashion" ?
Quote:
basic circle equation:
(x-centerx)²+(y-centery)²=radius²
04-15-2009, 03:27 PM#4
Flame_Phoenix
By circular fashion I mean that a unit must "always" be moving in a circle. When it has no orders, instead of being in the same place without moving, it should perform a circle. When moving it should make half-circles, like a drunken plane moving =P
I made some code that works, see the example please.
I am open for ideas on how to improve:
Collapse JASS:
scope IntSummon initializer Init
    globals
        private constant integer SUMMON_ID = 'hphx'
        private constant real VELOCITY = 600.
        private constant real CICLE_TIMER = 0.02
        private constant real RANGE = 800
    endglobals
//===========================================================================
    private struct aSummon
        unit caster
        unit summon
        timer t

        real face
        real summonX
        real summonY
        real newX
        real newY
        real newface

        
        static method summonLoop takes nothing returns nothing
            local aSummon data = aSummon(GetTimerData(GetExpiredTimer())) 
            
            //if the unit has no order, than it is stoped and we force it to make 
            //circles
            //if GetCurrentOrder == DoNothing then
                //update the current position of the summon
                set data.face = GetUnitFacing(data.summon)
                set data.summonX = data.summonX + ( (VELOCITY * CICLE_TIMER) * Cos(data.face * bj_DEGTORAD) )
                set data.summonY = data.summonY + ( (VELOCITY * CICLE_TIMER) * Sin(data.face * bj_DEGTORAD) )
                
                //move the bird =P
                call SetUnitX(data.summon, data.summonX)
                call SetUnitY(data.summon, data.summonY)

                //Choose new position for summon to walk next time
                set data.newX = GetUnitX(data.caster) + ( ( GetRandomReal(0, RANGE) * CICLE_TIMER) * Cos(  360 * bj_DEGTORAD) )
                set data.newY = GetUnitY(data.caster) + ( ( GetRandomReal(0, RANGE) * CICLE_TIMER) * Sin(  360 * bj_DEGTORAD) )
                set data.newface = bj_RADTODEG * Atan2(data.newY - GetUnitY(data.summon), data.newX - GetUnitX(data.summon))
                call SetUnitFacing(data.summon, data.newface)
            //elseif GetCurrentOrder == MoveToSomePoint
                //here I make the unit move to that point, but making semi-circles
            //elseif GetCurrentOrder == Attack
                //here I make the unit move to that point, but making semi-circles
                //when the unit reaches the target we attack it
                //after the attack we repeat last steps
            //end
        endmethod
        
        static method create takes unit c, unit s returns aSummon
            local aSummon data = aSummon.allocate()
            
            //setting members
            set data.caster = c
            set data.summon = s
            set data.face = GetUnitFacing(c)
            set data.summonX = GetUnitX(s)
            set data.summonY = GetUnitY(s)
            
            //the movement timer
            set data.t = NewTimer()
            call SetTimerData(data.t, integer(data))
            call TimerStart(data.t, CICLE_TIMER, true, function aSummon.summonLoop)
            
            return data
        endmethod
        
        method onDestroy takes nothing returns nothing
            call ReleaseTimer(.t)
        endmethod
    endstruct
//===========================================================================
    private function Conditions takes nothing returns boolean
        local aSummon data
        
        if GetUnitTypeId(GetSummonedUnit()) == SUMMON_ID then
            set data = aSummon.create(GetSummoningUnit(), GetSummonedUnit())
        endif
        
        return false
    endfunction
//===========================================================================
    private function Init takes nothing returns nothing
        //when the Unit is summoned
        local trigger IntSummonTrg = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(IntSummonTrg, EVENT_PLAYER_UNIT_SUMMON)
        call TriggerAddCondition(IntSummonTrg, Condition(function Conditions))
    endfunction
endscope
04-15-2009, 06:35 PM#5
Anitarf
That kind of thing would take a lot of code and depends heavily on how exactly you want it to behave. Nobody can really write this for you.
04-15-2009, 08:56 PM#6
Flame_Phoenix
Quote:
That kind of thing would take a lot of code and depends heavily on how exactly you want it to behave. Nobody can really write this for you.
Crap ....

Is it at least possible to get some formula for the "drunken" summon movement?
04-15-2009, 09:12 PM#7
akolyt0r
you didnt specify how you image that drunken movement ..
half circles can be everything ...best thing would probably be when you just draw a picture of your thoughts...
04-15-2009, 10:33 PM#8
Flame_Phoenix
Quote:
you didnt specify how you image that drunken movement ..
half circles can be everything ...best thing would probably be when you just draw a picture of your thoughts...
I am usually afraid of making pictures ... (you will know why soon).

Anyway, here is what happens. In normal Wacraft, if I order a unit to move from point A to B, the unit will make the black line as a path. However I want the unit to make the red path (making semi-circles). Is this humanly possible?

Click image for larger version

Name:	Image2.jpg
Views:	6
Size:	72.4 KB
ID:	42185

PS: Behold, my super Da Vinci work ! All 3 year old children will envoy painting skills Muhaahhaa...
Attached Images
File type: jpgImage2.jpg (72.4 KB)
04-16-2009, 01:50 AM#9
Eznce
Didn't Vexorian make a curve like that (Sine curve or something? i dont know) for Stromy Dreams in xe? Don't know if that's the thing you're looking for, but.
04-16-2009, 01:59 AM#10
Anitarf
Quote:
Originally Posted by Flame_Phoenix
Anyway, here is what happens. In normal Wacraft, if I order a unit to move from point A to B, the unit will make the black line as a path. However I want the unit to make the red path (making semi-circles). Is this humanly possible?
Sure it's possible, but as I said, there are a whole bunch of different equations and algorithms that could define a movement like that, from direct circles to sin curves to parabolic shapes, then there's the whole issue of connecting those movements from circling the caster to moving and attacking. If you can't code all that on your own then I don't know if anyone can help you, it's just too big.
04-16-2009, 02:10 AM#11
Rising_Dusk
Quote:
Originally Posted by Eznce
Didn't Vexorian make a curve like that (Sine curve or something? i dont know) for Stromy Dreams in xe?
He used a four-point(If I recall) bezier curve for Stormy Dreams.
04-16-2009, 02:28 AM#12
Dil999
Zomg!
Instead of trying to find a single formula, you could always try this simple (but slow) method:
-Pick a radius for all of the semicircles you want the unit to form.
-Find the angle between your starting point and your ending point.
-Make a point, 200 away from your unit, at the angle you just found. We can call this P.
-Rotate your unit around P, for 180 degrees.
-Once you rotate it 180 degrees, start the process again, but this time rotate -180 degrees.

Behold: A shitty MS paint drawing!
04-16-2009, 02:38 AM#13
Bobo_The_Kodo
You could use a simple Sin curve :o

OT Edit: You be on skype tonight Dil?
04-16-2009, 03:21 AM#14
PipeDream
I'd add circular motion on top of linear motion, like a moon orbiting a (relatively) unbound planet.
04-16-2009, 03:25 AM#15
Rising_Dusk
Quote:
Originally Posted by PipeDream
I'd add circular motion on top of linear motion, like a moon orbiting a (relatively) unbound planet.
Yes, do this.