Not sure how helpful this will be but I was looking through the Wurst showcase repos and Gold Rush has some missile code.
WurstScript • Showcase
HannesHaglund/Gold-Rush
If I remember correctly the game had fire-in-a-line missiles to swap places with target unit or knockback in an aoe.
It was pretty neat that they separated the concept of the collision detection (they called it Sensors) with the actual projectile.
I am using this. Might be useful for you. Its an abstract base class for custom projectile. Currently it only offers warcraft 3 style projectiles aka. unit homing and ground-target, with arc (gravity) if desired.
island-troll-tribes/island-troll-tribes
Bonus demo from the original pull request: 2019-01-27 15-11-04 - Create, Discover and Share Awesome GIFs on Gfycat
I also noticed that originalDistance is an old leftover unused variable on the class. The gravity numbers must be quite high to get a significant arc. I believe in the demo I used over 3000
Yeah. I didnt know how the arc formula worked with original projectile so the gravity causes the same effect. The higher the gravity the higher the arc the projectile has to make to reach target before hitting ground, basically. And 0 means no arc.
In a sense that would not be realistic for the flight path though. If you you mean the launch angle would be the same regardless of distance.
But if you anyways need say, the projectile to reach a certain height, you will need to adjust the gravity based on the distance and horizontal speed. There is a simple formula in wikipedia for maximum height reached by a projectile Projectile motion - Wikipedia
//Update vertical speed for appropriate flight arc
let flightTime = distance2D / this.groundSpeed
real heightDifference = (this.targetPos - missileFx.getPos3()).z
this.verticalSpeed = (heightDifference / flightTime) - (0.5 * this.gravity * flightTime)
Oh, right. If you want to keep the angle same you got to adjust the force at which the missile is fired instead. I just dont see how that would make sense with the homing component, which mystically gives the missile force to reach its target even if it moves away. Basically how my class works, is it calculates the required vertical speed on every update so if the target position changes it adapts the flight path like wc3 projectiles do.
Code://Update vertical speed for appropriate flight arc let flightTime = distance2D / this.groundSpeed real heightDifference = (this.targetPos - missileFx.getPos3()).z this.verticalSpeed = (heightDifference / flightTime) - (0.5 * this.gravity * flightTime)
I believe
Vertical launch speed = tan(angle) * horizontal launch speed
However, if distance and horizontal speed and angle are a given, the flight path is basically set for a given gravity, therefore you must adjust the gravity to reach the target.
The gravity or the vertical velocity
Haven't stumpled on that formular though - that would make my life so much easier.
Thats simply not correct. The vertical velocity is only adjustable through firing angle, which you said was a given parameter. If you instead increase the initial total velocity ("cannon propulsion force") it will also increase the horizontal velocity unless you also change the angle.
However, if distance and horizontal speed and angle are a given, the flight path is basically set for a given gravity, therefore you must adjust the gravity to reach the target.
Right, I might have said something wrong here. I agree with this:
The flight path should indeed be set when given those parameters - that's the ideaThe difference from your system to this, is that this takes the firing angle as a parameter instead of gravity.
Why I need the vertical velocity is for calculations purposes. And knowing the firing angle, the horizontal distance and velocity, I should be able to calculate it.
Vertical launch speed = tan(angle) * horizontal launch speed
If you know the angle and either the horizontal velocity or the total firing velocity, you get the vertical speed by:
Vertical launch speed = tan(angle) * horizontal launch speed
or
Vertical launch speed = sin(angle) * total launch speed
However, if you have a given firing velocity, your projectile might not even be able to reach a point that you want to reach. Also you cannot give firing angle, total distance to target and horizontal speed as parameters, since two of those being given means the third one is a given as well.
That's exactly what I wantI have tried this:
... But I can't seem to get it to work - probably something wrong with my other calculations. Have to try and find a fix for that.
I might be able to help if you if you share your code. Basically if you want your missiles to work so that they always launch at a constant total velocity, but at a different launch angle, you have to calculate the required launch angle like this:
![]()
Source: Projectile motion - Wikipedia
This also makes me realize propably how they calculate the firing angle for with original wc3 projectiles. The "arc" setting probably sets the relation between the x-velocity and the y-velocity, such the the VelY = VelX * arc * someArcConstant (someArcConstant seems like its 2). Thus it will never be able to exceed a firing angle that is directly upwards nor negative or backwards. It also explains why the missiles go so fast when you set the arc to something high, like 5.
If you increase arc, does it take a longer time to hit the target even when distance stays the same?
If it stays the same, it probably works similarly to my system where the horizontal speed stays the same, and only vertical speed is increased (and the gravity, since otherwise increasing the vertical speed would increase distance).
If the time to hit target changes, the arc value is probably the value of tan(angle) and the vertical and horizontal speeds are just calculated with that ange, and then the gravity is reduced to a point where the projectile flies long enough to reach the desired distance.
gravity = (2 / time) * (heightDifference / time - verticalSpeed)
Allright, in that case, if you want to modify my class to use an arc constant like WC3, you just replace the gravity parameter with an arc parameter that accepts values between 0-0.9999, calculate tan(arc * pi/2) * horizontal speed to get vertical speed, and then solve for gravity required to have the appropriate height after time = distance / horizontal speed
Code:gravity = (2 / time) * (heightDifference / time - verticalSpeed)
Im pretty confident my formula should work. Push your code and we can take a look.
Im not sure if it will affect the accuracy or anything, but just a few comments:
- originPos.angleTo2d(targetPos) returns an angle for which you can already call trigonometric functions such as .cos()
- I believe ANIMATION_PERIOD is the shortest interval you can have on timers, not 0.01. Not sure what happens if you enter 0.01 anyway.
- You can use closures ( doPeriodically() ) to run the updateloop. No need for timers and adding data to them etc.
I believe ANIMATION_PERIOD is the shortest interval you can have on timers, not 0.01. Not sure what happens if you enter 0.01 anyway.
You can use closures ( doPeriodically() ) to run the updateloop. No need for timers and adding data to them etc.
Weird that Watsuby only linked gold rush, actually all my maps contain missiles of some sort, based on Frentity. e.g. Frotty/Snowball-Fight
It's not lowest for timers, it's a threshold of when SetUnitPosition will cause a unit to be unable to move, e.g. used for ice sliding.
With 1/32 it will not, with 1/33 or 0.03 in this case it will.
Also in general it seems to be a good value for smooth movement, hence animation.
Collision checks are usually fine with higher values, I'm using 0.06, so roughly 16 checks per second, which is totally fine if you don't have high speed, small, bullet-like missiles or very thin walls.
Since you are iterating over all objects of a class, the TimedLoop module should be even nicer to use as it's made for that purpose.
Awesome, even more stuff to get draw inspiration from! Thanks for your feedback!
I'm toying with the idea of making a simple version of the missile where the on-hit-action would be saved as a lambda function, instead of having to implement an abstract missile class. Not sure if it makes any sense to do in this way, but nonetheless I'll give it a shot.
You're very welcome! Spread the love
Yes, it is very reasonable. The generated code is basically the same - the dispatch just changes location.
Mostly depends on taste - in my case I started using wurst from the start - before it had closures etc. so especially my old maps have a wide mix of different practices.
@Cokemonkey11 's maps heavily use closures in many places.
Cheers
Weird that Watsuby only linked gold rush, actually all my maps contain missiles of some sort, based on Frentity. e.g. Frotty/Snowball-Fight
Didn't know about that. That was the only map I had played recently so I was most familiar with how the game mechanics were directly translating to the code.
Not sure if it was mentioned anywhere but is there a good way to generate projectiles and throw them at certain attachment points?
With the projectile system, the projectile impacts the target unit's origin.
With a dummy projectile based off of shadowstrike/acid bomb, the projectile spawns from the caster's origin (cause dummy is spawned at caster origin).
What I'm doing, is to make it possible to hit the unit at a certain z-offset.
Is there any way to get this programmatically?
It would be nice to know the z-offset of chest/head/overhead/etc.
For all the vertical attachment points (not hands i.e.) you could build a system which keeps data of the attachment point's z-offset from the unit's origin, such that you could use that in a missile system. I've considered to do this several times, but just the thought of it is super tidious.
Other than that, I don't know of any solutions to get what you want :/
Darn, alright. I think I'll go the compromise route and just use some number.
If you just want projectile motion, see the `Knockback3` library in the standard lib.