Math Questions

Discussion in 'JASS Zone' started by tommerbob, Aug 15, 2011.

  1. tommerbob

    tommerbob Minecraft. :D

    Ratings:
    +110 / 0 / -0
    I think I'm just gonna create a thread for all of my math questions I ever have in the future. I should pay more attention in math class. :p

    So here's my problem:

    I'm trying to launch a projectile in a random direction from the point of origin:

    JASS:
    local projectile p  = 0
    local real       ux = GetUnitX(d.orb)
    local real       uy = GetUnitY(d.orb)
    local real       tx = GetRandomReal(0, 360)
    local real       ty = GetRandomReal(0, 360)
                 
    set p = projectile.create(ux,uy,50.00,Atan2((ty - uy),(tx - ux)))


    (I'm using Kenny's Projectile system)

    I thought the angle here:

    JASS:
    Atan2((ty - uy),(tx - ux))


    should be random, but its not. The projectile is always going in the same direction. :confused:

    Thanks for help.
     
  2. Solmyr

    Solmyr Active Member

    Ratings:
    +30 / 0 / -0
    projectile.create(ux, uy, 50.00, GetRandomReal(0, 2 * bj_PI)) // You may want to pre-calculate 2 * bj_PI though.
     
    • Like Like x 1
  3. Dirac

    Dirac 22710180

    Ratings:
    +147 / 0 / -0
    Atan2(a,b) takes radians, not angles.
    bj_PI/2=90 degrees
    bj_PI=180 degrees
     
  4. tommerbob

    tommerbob Minecraft. :D

    Ratings:
    +110 / 0 / -0
    Okay, sorry I should have specified more. I need a random X/Y coordinate, to get the angle for

    JASS:
     projectile.create(ux,uy,50.00,Atan2((ty - uy),(tx - ux)))


    and I need the same random X/Y coordinate for this:

    JASS:
    call p.projectArcing(tx, ty, p.posZ + 25.00, SHARD_SPEED, 0.08)
     
  5. Dirac

    Dirac 22710180

    Ratings:
    +147 / 0 / -0
    JASS:
    local real randomAngle=GetRandomReal(0,bj_PI*2)
    set x=ux+1000*Cos(randomAngle)
    set y=uy+1000*Sin(randomAngle)

    Is that what you want?
     
  6. tommerbob

    tommerbob Minecraft. :D

    Ratings:
    +110 / 0 / -0
    perfecto. thanks :)
     
  7. emjlr3

    emjlr3 Change can be a good thing Staff Member

    Ratings:
    +396 / 0 / -0
    *6.28318=Pi*2
     
  8. NoobImbaPro

    NoobImbaPro You can change this now in User CP.

    Ratings:
    +60 / 0 / -0
    And Pi is equal to:

    3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959...

    :p Wikipedia FTW
     
  9. Sevion

    Sevion The DIY Ninja

    Ratings:
    +423 / 0 / -0
    Let's not post useless things, NoobImbaPro.

    Realistically, in vJASS, Pi only needs to be accurate to the 4th decimal place. And actually, going up to the 2nd decimal place would be more than enough precision for anything vJASS related.
     
  10. NoobImbaPro

    NoobImbaPro You can change this now in User CP.

    Ratings:
    +60 / 0 / -0
    Why useless mate, I gave you the first 1100+ decimals of pi exactly
    vJass can read a number with 6 decimals, but 3.1415 is accurate enough, even 3.14.

    @tommerbob
    give us another questions guy, we hope we help you understand many things that don't make sense to you
     
  11. Nestharus

    Nestharus o-o

    Ratings:
    +83 / 0 / -0
    vjass can read a number with 20 decimals too.. they are stored in floats after all. However, to add/subtract things that are like 20 decimals, you have to do a trick because vjass value reading is weird (for numbers, not variables).
     
  12. tommerbob

    tommerbob Minecraft. :D

    Ratings:
    +110 / 0 / -0
    I don't have any questions at the moment, but don't worry, I will in the future.
     
  13. tommerbob

    tommerbob Minecraft. :D

    Ratings:
    +110 / 0 / -0
    Okay it didn't take me long to get lost in math again. :p Sorry for the double post.

    I'm working on a "leap" spell. The unit jumps 600 distance toward his facing angle. I based it off a spell written by Dinowc, so I don't completely understand all of the math functions.

    Problem: instead of jumping 600, he jumps like 3000.

    Code:

    JASS:
    scope Leap initializer init
    
    // Requirements:
    //      NewGen
    //      Timer Utils (TU)
    //      Math Functions
    
    // configurables:
    
    globals
        //========================================
        private constant integer SPELL_ID = 'A01C' // raw code of Leap spell
        private constant integer CROW_FORM = 'Amrf' // raw code of Crow Form
        
        //========================================
        private constant boolean INVULNERABLE = false // make unit invulnerable while in the air?
        //========================================
        private constant real INTERVAL = 0.03125
        //========================================
        private constant real MOVESPEED  = 800.
        private constant real MAX_HEIGHT = 250.
        private constant real JUMP_SPEED = 800. // wont affect much, but keep it at 800.
        
        //========================================
        private constant real DAMAGE_BASE = 20.
        private constant real DAMAGE_LVL  = 10.
        private constant real STR_BASE    = 2.
        private constant real STR_LVL     = 0.25
        private constant real INITIAL_AOE = 200.
        private constant real AOE_PER_LVL = 0.
        
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_HERO
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
        
        //========================================
        // don't touch anything bellow:
        
        private constant real MS = MOVESPEED * INTERVAL
    endglobals
    
    // Math functions:
    
    globals
        private constant real RADIANS = 0.0174
        
        private real MaxX
        private real MaxY
        private real MinX
        private real MinY
    endglobals
    
    private function PolarX takes real x, real dist, real angle returns real
        return x + (dist * Cos(angle * RADIANS))
    endfunction
    
    private function PolarY takes real y, real dist, real angle returns real
        return y + (dist * Sin(angle * RADIANS))
    endfunction
    
    private function GetParabolaZ takes real x, real d, real h returns real
        return 4 * h * x * (d - x) / (d * d)
    endfunction
    
    private function distance takes real x1, real y1, real x2, real y2 returns real
        local real dx = x2 - x1
        local real dy = y2 - y1
        return SquareRoot(dx * dx + dy * dy)
    endfunction
    
    private function AngleBetween takes real x1, real y1, real x2, real y2 returns real
        return Rad2Deg(Atan2(y2 - y1, x2 - x1))
    endfunction
    
    private function SafeX takes real x returns real
        if x < MaxX then
            return x
        else
            return MaxX
        endif
        
        if x > MinX then
            return x
        else
            return MinX
        endif
    endfunction
    
    private function SafeY takes real y returns real
        if y < MaxY then
            return y
        else
            return MaxY
        endif
        
        if y > MinY then
            return y
        else
            return MinY
        endif
    endfunction
    
    //=========================================================
    
    private function AOE takes integer level returns real
        return INITIAL_AOE + ((level - 1) * AOE_PER_LVL)
    endfunction
    
    private function DAMAGE takes unit u, integer level returns real
        return (DAMAGE_BASE + DAMAGE_LVL * (level - 1)) + ((STR_BASE + STR_LVL * (level - 1)) * GetHeroStr(u, true))
    endfunction
    
    private struct data
        unit caster
        real damage
        real x
        real d
        real cos
        real sin
        integer level
        timer t
        
        static method create takes unit whichUnit, real tx, real ty returns data
            local data d = data.allocate()
            
            local real ux = GetUnitX(whichUnit)
            local real uy = GetUnitY(whichUnit)
            local real angle = GetUnitFacing(whichUnit)
            
            set d.caster = whichUnit
            
            set d.x = MS
            set d.d = distance(ux, uy, tx, ty)
            
            set d.cos = PolarX(0., MS, angle)
            set d.sin = PolarY(0., MS, angle)
        
            set d.level = GetUnitAbilityLevel(d.caster, SPELL_ID)
            set d.damage = DAMAGE(d.caster, GetUnitAbilityLevel(d.caster, SPELL_ID))
            
            set d.t = NewTimer()
            
            call UnitAddAbility(d.caster, CROW_FORM)
            call UnitRemoveAbility(d.caster, CROW_FORM)
            
            call SetUnitInvulnerable(d.caster, INVULNERABLE)
            
            if d.d < 100. then
                set d.d = 100.
            endif
    
            call SetUnitAnimation(d.caster, "attack slam")
            call SetUnitTimeScale(d.caster, 0.4)
            
            return d
        endmethod
        
        method destroy takes nothing returns nothing
            call ReleaseTimer(.t)
        endmethod
    endstruct
    
    globals
        private group G = CreateGroup()
        private player P
        private data D
    endglobals
    
    //=======================================================
    
    private function filterFunc takes nothing returns boolean
        local unit picked = GetFilterUnit()
        
        if IsUnitEnemy(picked, P) and UnitAlive(picked) then
            call UnitDamageTargetEx(D.caster, picked, D.damage, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE_WHOKNOWS)
        endif
        
        set picked = null
        
        return false
    endfunction
    
    //=======================================================
    
    private function callback takes nothing returns nothing
        local data d = GetTimerData(GetExpiredTimer())
        
        local real xc = GetUnitX(d.caster)
        local real yc = GetUnitY(d.caster)
        local real angle = GetUnitFacing(d.caster)
        
        if d.x <= d.d then
            
            if d.x == MS then
                call PauseUnit(d.caster, true)
            endif
            
            call SetUnitX(d.caster, SafeX(xc + d.cos))
            call SetUnitY(d.caster, SafeY(yc + d.sin))
            
            call SetUnitFlyHeight(d.caster, GetParabolaZ(d.x, d.d, MAX_HEIGHT), JUMP_SPEED)
            
            set d.x = d.x + MS
        else
            if GetUnitAbilityLevel(d.caster, 'BSTN') == 0 and GetUnitAbilityLevel(d.caster, 'BPSE') == 0 then
                
                set D = d
                set P = GetOwningPlayer(d.caster)
    
                call GroupEnumUnitsInRange(G, xc, yc, AOE(d.level), Filter(function filterFunc))
                
                call PauseTimer(d.t)
            else
                call d.destroy()
            endif
    
            call PauseUnit(d.caster, false)
            call SetUnitTimeScale(d.caster, 1.)
            call QueueUnitAnimation(d.caster, "stand")
            call SetUnitInvulnerable(d.caster, false)
            
            call SetUnitFlyHeight(d.caster, 0., JUMP_SPEED)
        endif
    endfunction
    
    private function actions takes nothing returns nothing
        local unit caster = GetTriggerUnit()
        local real angle = GetUnitFacing(caster)
        local real ux = GetUnitX(caster)
        local real uy = GetUnitX(caster)
        local real tx    = ux + 600 * Cos(angle)
        local real ty    = uy + 600 * Sin(angle)
        local data d = data.create(caster, tx, ty)
            
        call SetTimerData(d.t, d)
        
        call TimerStart(d.t, INTERVAL, true, function callback)
        
        set caster = null
    endfunction
    
    //=======================================================
    
    private function conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELL_ID
    endfunction
    
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i = 0
        
        loop
            call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            set i = i + 1
            exitwhen i == MAX_PLAYERS - 1 
        endloop
        call TriggerAddCondition(t, Condition(function conditions))
        call TriggerAddAction(t, function actions)
        
        
        set MaxX = GetRectMaxX(bj_mapInitialPlayableArea)-50.
        set MaxY = GetRectMaxY(bj_mapInitialPlayableArea)-50.
        
        set MinX = GetRectMinX(bj_mapInitialPlayableArea)+50.
        set MinY = GetRectMinY(bj_mapInitialPlayableArea)+50.
        
        set t = null
    endfunction
    
    endscope
     
  14. Sevion

    Sevion The DIY Ninja

    Ratings:
    +423 / 0 / -0
    Are you sure GetUnitFacing returns the angle in radians? I'm 99.99% sure that it returns it in degrees.

    If that's the case, in your actions, do local real angle = GetUnitFacing(caster) * bj_DEGTORAD.

    I haven't done vJASS in a while, but IIRC that is what you have to do with Cos/Sin. They take radians and GetUnitFacing returns degrees.
     
  15. tommerbob

    tommerbob Minecraft. :D

    Ratings:
    +110 / 0 / -0
    Well the caster always moved in the correct direction, but always too far.

    I changed the angle to:

    JASS:
    local real angle = GetUnitFacing(caster) * bj_DEGTORAD


    and the caster now never moves in the correct direction, always to the right, the distance is still way too far.

    I simplified the above code to cut down on space to make it easier to read through. Below should be just the necessary math functions/data that would screw this up:

    JASS:
    scope Leap initializer init
    
    // Requirements:
    //      NewGen
    //      Timer Utils (TU)
    //      Math Functions
    
    // configurables:
    
    globals
     
        private constant real INTERVAL = 0.03125
        //========================================
        private constant real MOVESPEED  = 800.
        private constant real MAX_HEIGHT = 250.
        private constant real JUMP_SPEED = 800. // wont affect much, but keep it at 800.
    
        // don't touch anything bellow:
        
        private constant real MS = MOVESPEED * INTERVAL
    endglobals
    
    // Math functions:
    
    globals
        private constant real RADIANS = 0.0174
        
        private real MaxX
        private real MaxY
        private real MinX
        private real MinY
    endglobals
    
    private function PolarX takes real x, real dist, real angle returns real
        return x + (dist * Cos(angle * RADIANS))
    endfunction
    
    private function PolarY takes real y, real dist, real angle returns real
        return y + (dist * Sin(angle * RADIANS))
    endfunction
    
    private function GetParabolaZ takes real x, real d, real h returns real
        return 4 * h * x * (d - x) / (d * d)
    endfunction
    
    private function distance takes real x1, real y1, real x2, real y2 returns real
        local real dx = x2 - x1
        local real dy = y2 - y1
        return SquareRoot(dx * dx + dy * dy)
    endfunction
    
    private function AngleBetween takes real x1, real y1, real x2, real y2 returns real
        return Rad2Deg(Atan2(y2 - y1, x2 - x1))
    endfunction
    
    private function SafeX takes real x returns real
        if x < MaxX then
            return x
        else
            return MaxX
        endif
        
        if x > MinX then
            return x
        else
            return MinX
        endif
    endfunction
    
    private function SafeY takes real y returns real
        if y < MaxY then
            return y
        else
            return MaxY
        endif
        
        if y > MinY then
            return y
        else
            return MinY
        endif
    endfunction
    
    private struct data
        unit caster
        real damage
        real x
        real d
        real cos
        real sin
        integer level
        timer t
        
        static method create takes unit whichUnit, real tx, real ty returns data
            local data d = data.allocate()
            
            local real ux = GetUnitX(whichUnit)
            local real uy = GetUnitY(whichUnit)
            local real angle = GetUnitFacing(whichUnit)
            
            set d.caster = whichUnit
            
            set d.x = MS
            set d.d = distance(ux, uy, tx, ty)
            
            set d.cos = PolarX(0., MS, angle)
            set d.sin = PolarY(0., MS, angle)
            
            set d.t = NewTimer()
            
            call UnitAddAbility(d.caster, CROW_FORM)
            call UnitRemoveAbility(d.caster, CROW_FORM)
            
            if d.d < 100. then
                set d.d = 100.
            endif
            
            return d
        endmethod
        
        method destroy takes nothing returns nothing
            call ReleaseTimer(.t)
        endmethod
    endstruct
    
    globals
        private group G = CreateGroup()
        private player P
        private data D
    endglobals
    
    private function callback takes nothing returns nothing
        local data d = GetTimerData(GetExpiredTimer())
        
        local real xc = GetUnitX(d.caster)
        local real yc = GetUnitY(d.caster)
        local real angle = GetUnitFacing(d.caster)
        
        if d.x <= d.d then
            
            if d.x == MS then
                call PauseUnit(d.caster, true)
            endif
            
            call SetUnitX(d.caster, SafeX(xc + d.cos))
            call SetUnitY(d.caster, SafeY(yc + d.sin))
            
            call SetUnitFlyHeight(d.caster, GetParabolaZ(d.x, d.d, MAX_HEIGHT), JUMP_SPEED)
            
            set d.x = d.x + MS
        else
            if GetUnitAbilityLevel(d.caster, 'BSTN') == 0 and GetUnitAbilityLevel(d.caster, 'BPSE') == 0 then
                
                set D = d
                
                call PauseTimer(d.t)
            else
                call d.destroy()
            endif
            
            call SetUnitFlyHeight(d.caster, 0., JUMP_SPEED)
        endif
    endfunction
    
    private function actions takes nothing returns nothing
        local unit caster = GetTriggerUnit()
        local real angle = GetUnitFacing(caster)
        local real ux = GetUnitX(caster)
        local real uy = GetUnitX(caster)
        local real tx    = ux + 600. * Cos(angle)
        local real ty    = uy + 600. * Sin(angle)
        local data d = data.create(caster, tx, ty)
            
        call SetTimerData(d.t, d)
        call TimerStart(d.t, INTERVAL, true, function callback)
        
        set caster = null
    endfunction
    
    function init takes nothing returns nothing
        set MaxX = GetRectMaxX(bj_mapInitialPlayableArea)-50.
        set MaxY = GetRectMaxY(bj_mapInitialPlayableArea)-50.
        
        set MinX = GetRectMinX(bj_mapInitialPlayableArea)+50.
        set MinY = GetRectMinY(bj_mapInitialPlayableArea)+50.
        
    endfunction
    
    endscope
     
  16. NoobImbaPro

    NoobImbaPro You can change this now in User CP.

    Ratings:
    +60 / 0 / -0
    why don't you use my system?? AUMS

    and see how I am doing all the stuff??

    PS: You confuse radians with degrees, witch one will you use?? I prefer radians as emjlr3 does
     
  17. tommerbob

    tommerbob Minecraft. :D

    Ratings:
    +110 / 0 / -0
    Well, no offense, but I won't use a system that 1) isn't approved or 2) isn't generally accepted by the community.

    I'll look through it.

    That just went through one ear and out the other.
     
  18. Dirac

    Dirac 22710180

    Ratings:
    +147 / 0 / -0
    IMO leaps are quite easy, you can write one yourself if you have basic sliding knowledge and AceHart's jump parabola or even this crazy equation i have here

    y = [(2a-4c)/(b^2)]*x^2 + [(4c-3a)/b]*x + a

    a = Initial height of the proyectile
    c = Max height of the proyectile
    /////////////////////////////////////////////////////////
    x = distance traveled
    y = returns the height of the proyectile
    b = input the distance between the start point and the end point here
     
  19. NoobImbaPro

    NoobImbaPro You can change this now in User CP.

    Ratings:
    +60 / 0 / -0
    I haven't meant to use it, just see how it does the whole thing.
    Because it isn't approved does not mean that it is a crappy one.
    It is the half system, that's why it isn't approved. When I mean the half I mean like Timer32 without T32x module
     
  20. NoobImbaPro

    NoobImbaPro You can change this now in User CP.

    Ratings:
    +60 / 0 / -0
    @Dirac

    yeah it may seem as a crazy equation, but a simpler one may be better, like my equation:
    y=ax-bx[SUP]2[/SUP]+c

    with b = 4*height/distance[SUP]2[/SUP]
    a = b*distance

    and it's a normal physics parabola.

    Where height is the max height of the projectile, where distance the distance the projectile/unit will do, x is the current distance from start point and y the requested height at that point. Oh and c the initial height. Is same with aceheart's but with less arithmetics
     

Share This Page