|
|
#1 |
|
MSc
Cinematics Moderator
|
This system is made for moving units as if they were particles. It is perfect for projectiles from weapons, or anything other needing to move physically.
It uses: Anitarf's Vector System My Linked Lists both of which are, ofcourse, already included in the map. Be sure to download and read the documentation of the vector system, since you will need to activily use it too. The beauty of the system is that you can add an unlimited amount of forces which can be different for each particle. You can also link a function to a condition which makes each particle have its own "triggers". All of this is done by functions which you can very easily write yourself. In the post below this one I will send some of these functions which you can use yourself (some of which are already included in the map). Be sure to read the documentation so you know exactly when I am talking about :) Find any bugs? please tell me. (P.S. It is gamecache free) Last edited by iNfraNe : 10-07-2006 at 04:56 PM. |
|
|
|
| Sponsored Links - Login to hide this ad! |
|
|
|
|
#2 |
|
MSc
Cinematics Moderator
|
Forces:
__________________ JASS:// Needs variable: forceGravity (integer) function G takes nothing returns integer if udg_forceGravity == 0 then set udg_forceGravity = VectorCreate(0,0,-2500) endif return udg_forceGravity endfunction Conditions: JASS:// Needs variable conditionGroundHit (trigger) function ParticleGroundHitCond takes nothing returns boolean local unit u = GetEnumUnit() local location loc = GetUnitLoc(u) local integer i = udg_clsParticlePlace[GetUnitUserData(u)] if GetLocationZ(loc) > udg_vectorZ[i] then call RemoveLocation(loc) set loc = null return true endif call RemoveLocation(loc) set loc = null return false endfunction function ParticleGroundHit takes nothing returns trigger if udg_conditionGroundHit == null then set udg_conditionGroundHit = CreateEvalTrig(function ParticleGroundHitCond) endif return udg_conditionGroundHit endfunction // Needs variable conditionDeath (trigger) function ParticleDeathCond takes nothing returns boolean return GetWidgetLife(GetEnumUnit()) < 0.405 endfunction function ParticleDeath takes nothing returns trigger if udg_conditionDeath == null then set udg_conditionDeath = CreateEvalTrig(function ParticleDeathCond) endif return udg_conditionDeath endfunction // needs an extra variable: udg_TUnit (unit), can hit allies to, add a condition to the group otherwise function ParticleCollisionCond takes nothing returns boolean local group g = CreateGroup() local unit u = GetEnumUnit() local unit f local integer p = udg_clsParticlePlace[GetUnitUserData(u)] local integer tv local location l call GroupEnumUnitsInRange(g, udg_vectorX[p], udg_vectorY[p], 60, null) loop set f = FirstOfGroup(g) exitwhen f == null set l = GetUnitLoc(f) set tv = VectorCreate(GetLocationX(l), GetLocationY(l), GetLocationZ(l)+GetUnitFlyHeight(f)) call RemoveLocation(l) if IsPointInSphere(tv, p, 60) then call VectorDestroy(tv) set udg_TUnit = f //This is a temp global to be used in the conditionfuncs set u = null set l = null set f = null return true endif call VectorDestroy(tv) call GroupRemoveUnit(g,f) endloop set u = null set l = null set f = null return false endfunction function ParticleCollision takes nothing returns trigger if udg_conditionCollision == null then set udg_conditionCollision = CreateEvalTrig(function ParticleCollisionCond) endif return udg_conditionCollision endfunction Actions (ConditionFuncs): JASS:// Bounces a particle back up. This function works on both flat and angled terrain. function GroundHit_Bounce takes nothing returns nothing local unit u = GetEnumUnit() local integer i = GetUnitUserData(u) local integer p = udg_clsParticlePlace[i] local integer v = udg_clsParticleSpeed[i] local integer vector1 = VectorGetTerrainNormal(udg_vectorX[p], udg_vectorY[p], 25.0) local integer vector2 = VectorProjectVector(v,vector1) set udg_vectorX[p] = udg_vectorX[p] - udg_vectorX[v]*ParticlePeriod() set udg_vectorY[p] = udg_vectorY[p] - udg_vectorY[v]*ParticlePeriod() set udg_vectorZ[p] = udg_vectorZ[p] - udg_vectorZ[v]*ParticlePeriod() call VectorScale(vector2, -2) call VectorAdd(v, vector2) call VectorScale(v, 0.65) call VectorDestroy(vector1) call VectorDestroy(vector2) set u = null endfunction // damages the target (used in CollisionDamage condition) for 10 hp. function Collision_Damage10 takes nothing returns nothing local unit u = GetEnumUnit() call UnitDamageTarget(u, udg_TUnit, 10, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS) call DestroyEffect(AddSpecialEffectTarget("bloodeffect?", udg_TUnit, "chest")) //replace "bloodeffect?" with the path of a blood effect, you can also leave out this part. call KillUnit(u) call RemoveParticle(u,true) set u = null endfunction More of these functions will be added later... Last edited by iNfraNe : 10-23-2006 at 03:07 PM. |
|
|
|
|
|
#3 |
|
User
Join Date: Jan 2004
Posts: 388
![]() ![]() ![]()
|
OOOO I am so looking forward to rip... lend.. uh use some of these functions in my map. ;)
__________________Don't have time to look at it right now, but I can certainly testify to the usefulness of such a system. Assuming it is working well, and I bet it does, great and useful work! |
|
|
|
|
|
#4 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
Since all forces and the differential equation are constant it is practical to solve the diff eq exactly. Since you don't need any genericity you can do this by precomputing (when forces change):
__________________W = acceleration*period U = w*period/2 and at each time step: pos_f = U + vel_i*period + pos_i vel_f = W + vel_i |
|
|
|
|
|
#5 |
|
MSc
Cinematics Moderator
|
Yes, however the forces could change at any time. The system was ment to handle both constant forces and forces that are constantly changing.
__________________ |
|
|
|
|
|
#6 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
Your forces are constant over a time step, the interval in which this is relevant. Of course you would do even better (in terms of number of operations / size of time step) if you did take in to account the changing forces.
__________________ |
|
|
|
|
|
#7 |
|
Nonchalant
Respected User
|
I'm not sure exactly what you are meaning by time step there Pipe, but he may be accounting for an external thing changing the forces at some other time? (Like a spell causing missiles to slow down or something)
__________________ |
|
|
|
|
|
#8 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
In general using a better integration method lets you increase the time step. Two things limit you to a small step: visually smooth and numerical stability/precision. If you are currently limited by stability/precision, you switch to a more accurate method and larger time steps which reduces your total computational costs practically for free.
__________________I say in free in contrast to the hard way that one would do this under non JASS circumstances: use separate loops for integration and display. |
|
|
|
|
|
#9 |
|
MSc
Cinematics Moderator
|
I dont see anyway reason to... It runs smoothly with 50 particles at a 0.025 timer, the changes with changing forces that happen when you higher the period would be non-noticable. And I dont see a reason to make it higher anyway, since you usually dont need more than 50 particles.
__________________(tell me if im completely missing the point here...) |
|
|
|
|
|
#10 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
It's just room for optimization. The demonstration with the current integrator is geared towards constant forces where things are not very curved. If you want to have things oscillating, moving in small circles or in general experiencing large periodic accelerations you'll have to start ratcheting the time step down to get under the stability threshold. Using the midpoint integrator is relatively cheap and reduces the error by a factor of four (instead of two) for every time you cut the time step in half. And it has the nice side bonus that the curves from constant acceleration are computed exactly.
__________________ |
|
|
|
|
|
#11 |
|
MSc
Cinematics Moderator
|
But what you are saying is... s = s+v*dt+0.5a*dt² right? Isn't that exactly what im doing, only in 2 steps? I'm not quite sure how I should else do it...
__________________ |
|
|
|
|
|
#12 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
Almost. What you are doing is stepping to the end of the interval and computing acceleration there:
__________________v1 = v0 + a dt x1 = x0 + v1*dt = x0 + v0*dt + a*dt^2 <-- no factor of 1/2 Which has the same amount of error as doing it from the beginning, but depending on the direction of things it'll grow instead of decay. |
|
|
|
|
|
#13 |
|
MSc
Cinematics Moderator
|
Indeed!
__________________I never realised that. How odd. I'll fix this and update asap. Thanks once again. |
|
|
|
|
|
#14 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
Still going to update it?
__________________ |
|
|
|
|
|
#15 |
|
MSc
Cinematics Moderator
|
Yep, asap.
__________________ |
|
|
|
![]() |
| Thread Tools | Search this Thread |
|
|
|
Donate |