HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Ground bouncing formula

04-29-2009, 03:58 PM#1
Vestras
Hey guys, I'm having some trouble with a grenade that should be bouncing on the ground. This doesn't work (surprise) so I need some help.

This is what I have:
Expand JASS:

This is where I call it:
Expand JASS:

And this is the full code:
Expand JASS:

The grenade should be having a realistic bounce, like when it has just hit the ground it is at its fastest point, where it basically is increasing in height medium fast, and then the higher up is goes the slower it becomes.

When it then has hit the maximum, it should be doing the same thing except the other way around.
04-29-2009, 04:20 PM#2
0zyx0
So, what does the code do now? Isn't it doing anything at all? Doesn't the projectile height change? Or is it simply that the movement isn't realistic?

If the answer to the last question is yes:
To make the height change look realistic, the acceleration in the z direction has to be constant
Collapse JASS:
        if xp.groundBounce then
            if xp.state == 1 then
                set p = GetUnitFlyHeight(e) + xp.addZ
                set xp.addZ = xp.addZ - VAR
            elseif xp.state == 0 then
                set p = GetUnitFlyHeight(e) - xp.addZ 
                set xp.addZ = xp.addZ + VAR
            endif
            call SetUnitFlyHeight(e, p, 0)
            if p >= xp.maxBounceZ then
                set xp.state = 0
            elseif p <= xp.minBounceZ then
                set xp.state = 1
                set xp.bounces = xp.bounces + 1
            endif
        endif
Wher VAR should have a value that makes xp.addZ around 0 when the projectile reaches its maximum height.

And you deserve a comment about your post count, so here it is.
04-29-2009, 04:25 PM#3
Vestras
The code makes the height change so much that you sometimes can't even see the proj.

I just need a new way to do it.
04-29-2009, 09:28 PM#4
Anitarf
I'd say you should use vectors for stuff like this.
04-30-2009, 03:58 PM#5
Vestras
> I'd say you should use vectors for stuff like this.

Hnnng. I'd prefer it not to.
Bumpy.
04-30-2009, 04:18 PM#6
Ammorth
Use 2 variables, a current height and a current velocity. You will constantly be adding to the velocity by some constant acceleration. You will subtract the velocity from the height, causing it to go downward. On a bounce, you multiply your velocity by some negative factor, to shrink and flip the direction of the ball. Since you are adding the velocity, it will cause the ball to slow down going up, and then speed up going down.

Collapse JASS:
if (xp.groundBounce==true) then
    set xp.vel = xp.vel + xp.acc
    set xp.height = xp.height - xp.vel
    if xp.height <= 0 then
        set xp.vel = xp.vel * -0.75 // flips and reduces the velocity (75% bounce)
        set xp.height = 0 // to make sure it doesn't stay under on the next iteration.
    endif
    call SetUnitFlyHeight(e, xp.height, 0)
endif

hopefully you get the idea.
04-30-2009, 05:42 PM#7
Vestras
Thanks for helping Ammorth, but I am experiencing problems. I'm sure I'm just failing.

My code:
Collapse JASS:
library VPM initializer Init requires DummyUtils

    globals
        //* Conf
        public constant real PERIOD = 0.04
    endglobals

    struct projsetup
        unit proj
        real sx
        real sy
        real sz
        real tx
        real ty
        real tz
        real f
        real speed
        real zspeed
        real scale
        real minBounceZ
        real maxBounceZ
        real accZ
        real vel
        string model
        string attach
        player owner
        boolean useZ
        boolean groundBounce
        integer maxBounces
    endstruct

    public struct mainproj extends projsetup
        real cos
        real sin
        real max
        real t
        real count
        effect e
        projsetup x
        boolean finish
        boolean stopWhenExceeded
        integer bounces
        trigger trg1
        trigger trg2
        real height
    endstruct
    
    globals
        private timer xt=CreateTimer()
        private group xgrp=CreateGroup()
        private unit temp
        public real Game_maxX
        public real Game_maxY
        public real Game_minX
        public real Game_minY
        private location ZLoc=Location(0,0)
    endglobals

    public function GetUnitZ takes unit which returns real
     local real x=GetUnitX(which)
     local real y=GetUnitY(which)
         
        call MoveLocation(ZLoc,x,y)
         
     return (GetUnitFlyHeight(which)+GetLocationZ(ZLoc))
    endfunction

    public function SetUnitZ takes unit which, real z returns nothing
     local real x=GetUnitX(which)
     local real y=GetUnitY(which)
     local real h
            
        call MoveLocation(ZLoc,x,y)
        set h=GetLocationZ(ZLoc)
            
        if (z>h) then
            call SetUnitFlyHeight(which,(z-h),0)
        endif
        call SetUnitFlyHeight(which,h,0)
    endfunction
    
    private function HandleProjs_Callback takes nothing returns nothing
     local unit e=GetEnumUnit()
     local mainproj xp=GetUnitUserData(e)
     local real x=GetUnitX(e)
     local real y=GetUnitY(e)
     local real z
     local real px=(x+xp.speed*xp.cos)
     local real py=(y+xp.speed*xp.sin)
     local real pz
     local real p
     local boolean b=false
        
        set temp=xp.proj
        call TriggerEvaluate(xp.trg1)
        set xp.t=(xp.t+xp.speed)
        
        if (x<Game_minX) then
            set px=Game_minX
        elseif (x>Game_maxX) then
            set px=Game_maxX
        endif
        
        if (py<Game_minY) then
            set py=Game_minY
        elseif (y>Game_maxY) then
            set py=Game_maxY
        endif
        
        call SetUnitX(e,px)
        call SetUnitY(e,py)
        
        if (xp.useZ==true) then
            set z=GetUnitZ(e)
            set pz=(z+xp.zspeed)
            call SetUnitZ(e,pz)
        endif
        
        if (xp.groundBounce==true) then
            set xp.vel=(xp.vel+xp.accZ)
            set xp.height=(xp.height-xp.vel)
            if (xp.height<=0) then
                set xp.vel=(xp.vel*-0.75)
                set xp.height=0
                set xp.bounces=(xp.bounces+1)
            endif
            call BJDebugMsg(R2S(xp.height))
            call SetUnitFlyHeight(e,xp.height,0)
        endif
        
        if (xp.maxBounces!=0) then
            set b=(xp.bounces>=xp.maxBounces)
        endif
        
        if ((xp.t>=xp.max) and (xp.stopWhenExceeded==true)) or (xp.finish==true) or (b==true) then
            call GroupRemoveUnit(xgrp,e)
            call DestroyEffect(xp.e)
            call TriggerEvaluate(xp.trg2)
            call DestroyTrigger(xp.trg1)
            call DestroyTrigger(xp.trg2)
            call ReleaseDummy(xp.proj)
            call xp.x.destroy()
            call xp.destroy()
        endif
        
        set e=null
    endfunction
    
    private function HandleProjs takes nothing returns nothing
        call ForGroup(xgrp,function HandleProjs_Callback)
    endfunction
    
    public function KillProjectile takes unit proj returns nothing
        set mainproj(GetUnitUserData(proj)).finish=true
    endfunction
    
    public function CreateProjectile takes projsetup x, code moveCode, code finishCode returns unit
     local mainproj xp=mainproj.create()
     local real angle
     local real dx
     local real dy
        
        set xp.proj=NewDummy(x.owner,x.sx,x.sy,x.f)
        set xp.e=AddSpecialEffectTarget(x.model,xp.proj,x.attach)
        set xp.speed=(x.speed*PERIOD)
        set xp.zspeed=(x.zspeed*PERIOD)
        set xp.tx=x.tx
        set xp.ty=x.ty
        set xp.useZ=x.useZ
        set xp.count=0
        set xp.stopWhenExceeded=true
        set xp.bounces=0
        set xp.height=GetUnitFlyHeight(xp.proj)
        
        set xp.minBounceZ=x.minBounceZ
        set xp.maxBounceZ=x.maxBounceZ
        
        if (x.groundBounce==true) then
            set xp.useZ=false
            set xp.stopWhenExceeded=false
        endif
        
        set xp.groundBounce=x.groundBounce
        set xp.x=x
        set xp.finish=false
        set xp.t=0
        
        set dx=(x.tx-x.sx)
        set dy=(x.ty-x.sy)
        set xp.max=SquareRoot(dx*dx+dy*dy)
        
        set angle=Atan2(x.ty-x.sy,x.tx-x.sx)
        set xp.cos=Cos(angle)
        set xp.sin=Sin(angle)
        
        set xp.trg1=CreateTrigger()
        set xp.trg2=CreateTrigger()
        call TriggerAddCondition(xp.trg1,Condition(moveCode))
        call TriggerAddCondition(xp.trg2,Condition(finishCode))
        
        call SetUnitScale(xp.proj,(x.scale*0.01),(x.scale*0.01),(x.scale*0.01))
        call UnitAddAbility(xp.proj,'Amrf')
        call UnitRemoveAbility(xp.proj,'Amrf')
        call SetUnitUserData(xp.proj,xp)
        call GroupAddUnit(xgrp,xp.proj)
        
     return xp.proj
    endfunction
    
    public function GetProj takes nothing returns unit
        return temp
    endfunction
    
    private function Init takes nothing returns nothing
        set Game_maxX=(GetRectMaxX(bj_mapInitialPlayableArea)-64.00)
        set Game_maxY=(GetRectMaxY(bj_mapInitialPlayableArea)-64.00)
        set Game_minX=(GetRectMinX(bj_mapInitialPlayableArea)+64.00)
        set Game_minY=(GetRectMinY(bj_mapInitialPlayableArea)+64.00)
        call TimerStart(xt,PERIOD,true,function HandleProjs)
    endfunction
    
endlibrary

Collapse JASS:
library Grenade initializer Init requires VPM

    globals
        private constant integer RAW_CODE = 'A002' //* Raw code of the spell
        private constant real RADIUS      = 200    //* Radius of the check/damage
        private constant real DAMAGE      = 75     //* Damage done to units
        
        //* Don't touch
        private trigger Trg=CreateTrigger()
        private group Grp=CreateGroup()
        private unit Temp
    endglobals

    private function EnumAct takes nothing returns boolean
     local unit f=GetFilterUnit()
        
        if ((IsUnitEnemy(f,GetOwningPlayer(Temp))) and (IsUnitType(f,UNIT_TYPE_STRUCTURE)==false) and (GetWidgetLife(f)>.405)) then
            set VPM_mainproj(GetUnitUserData(Temp)).finish=true
            call UnitDamageTarget(Temp,f,DAMAGE,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
        endif
        
        set f=null
     return false
    endfunction
    
    private function MoveAct takes nothing returns boolean
     local unit u=VPM_GetProj()
     local real x=GetUnitX(u)
     local real y=GetUnitY(u)
        
        set Temp=u
        call GroupEnumUnitsInRange(Grp,x,y,RADIUS,Filter(function EnumAct))
        
        set u=null
     return false
    endfunction
    
    private function FinishAct takes nothing returns boolean
     local unit u=VPM_GetProj()
     
        call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Other\\AcidBomb\\BottleMissile.mdl",GetUnitX(u),GetUnitY(u)))
        set u=null
     
     return false
    endfunction
    
    private function Actions takes nothing returns boolean
     local projsetup x
     local unit u
     local location l
        
        if (GetSpellAbilityId()==RAW_CODE) then
            set u=GetTriggerUnit()
            set l=GetSpellTargetLoc()
            set x=projsetup.create()
            
            set x.tx=GetLocationX(l)
            set x.ty=GetLocationY(l)
            set x.sx=GetUnitX(u)
            set x.sy=GetUnitY(u)
            set x.sz=0
            set x.tz=0
            set x.speed=400
            set x.zspeed=0
            set x.scale=100
            set x.model="Abilities\\Spells\\Other\\AcidBomb\\BottleMissile.mdl"
            set x.attach="origin"
            set x.owner=GetOwningPlayer(u)
            set x.useZ=false
            set x.groundBounce=true
            set x.minBounceZ=1
            set x.maxBounceZ=100
            set x.maxBounces=GetRandomInt(10,15)
            set x.accZ=5
            set x.vel=50
            set x.f=0
            set x.proj=VPM_CreateProjectile(x,function MoveAct,function FinishAct)
            call RemoveLocation(l)
            set u=null
            set l=null
        endif
        
     return false
    endfunction
    
    private function Init takes nothing returns nothing
        call TriggerRegisterAnyUnitEventBJ(Trg,EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(Trg,Condition(function Actions))
    endfunction

endlibrary

The debug msg displays 50 all the way and the height doesn't change.
04-30-2009, 06:58 PM#8
MaD[Lion]
use vector will do the trick fast easy and fast
05-01-2009, 12:57 AM#9
kingkingyyk3
Add Crow Form to the unit u wan to bounce