Understanding the code
This is your code snippet:
for(int i = 1; i <= 1000 - Xpos; i += 1) {
// tempo do projétil, que é calculado em base do I
float t = i / (float) ((power + powerSalt[(int) power]) * Mathf.Cos(angle));
// altura do projétil, calculada com base no tempo
float Y = (float) (((power + powerSalt[(int) power]) * Mathf.Sin(angle)) * t - (0.5 * g * t * t));
// adiciona o ponto obtido, abaixo no "i + Xpos" se ocasiona o ponto horizontal, então o "player.y + y" seria a cordenada vertical
Vector3 point = new Vector3(Map.toWorldX((float) i + Xpos), Map.toWorldY(player.y + Y));
// enfim, adiciona o ponto (x, y) da linha
tracer.line.points3.Add(point);
}
The first line makes a loop that ranges from 1 to 1000, and you said yourself that this is the spatial limit of your playing field. So, the variable i
represents a discrete division of the horizontal space, i.e., the values of the X axis (perhaps if tievsse called the variable i
of x
that would be even clearer).
The second line, already inside the loop, calculates the time. As the movement on the horizontal axis (X) is uniform (i.e., the speed of the horizontal movement is constant, i.e., there is no acceleration/deceleration), this time is calculated based on the following formula:
Formula (2) is the trigonometric variation of the formula (1), and is the one you use in your code. After algebraic manipulation, and considering that the initial space is 0 (since everything begins at the origin), one has:
In your case, space is i
, and the speed is power + powerSalt[(int) power]
. Naturally, as you have the angle (in radians), the angle cosine is Mathf.Cos(angle)
.
Once having the time that the projectile will travel to space i
(note how the calculation is repeated for each crescent path), the third line calculates the position of the projectile on the Y axis (vertical) in time, using the formula of the uniformly varied motion (where the speed of vertical motion is not constant, as there is deceleration in the ascent and acceleration in the descent - the acceleration of gravity):
The formula (4) is the trigonometric variation of the formula (3), and is the one used in the code. Again, the initial space is 0 (origin) and its velocity is power + powerSalt[(int) power]
(yes, initially the same, although the actual speed is weighted by the acceleration at each time interval). In addition, the acceleration of gravity (commonly called g
instead of a
) is negative, since it pulls the projectile downwards (contrary to the launch direction). So there is a sign of -
in place of singla de +
in the code. The code line also does t * t
to calculate the square of time, and multiply the gravity by 0.5
to divide by 2.
Note: it should be obvious that multiplying by 0.5 is equivalent to
split by 2:
Finally, in the fourth line of code, the point in two-dimensional space is constructed from the values of X and Y calculated earlier. Remember that X is the value given in i
(its code adds such a Xpos
I don’t know what it is, but it must be some fixed difference value). This line also mapped the X and Y values from a local metric to global as an object position adjustment player
(that I suppose is the tank). This mapping is probably due to the use of these coordinates outside the scope of the tank (maybe the camera uses them, and therefore the mapping is necessary).
Adding wind
A rather simplified way of adding wind would be to consider it as an additional force which acts only horizontally, that it would be favorable (if it had blown in the same direction as the movement) or contrary (if it had blown against the direction of movement). As you said your wind only occurs on the X axis, simply add a positive (if favorable) or negative (if otherwise) value to your initial speed (that is, use power + powerSalt[(int) power] + <VELOCIDADE DO VENTO>
wherever the speed appears). Even though the wind speed is only horizontal, it is not a problem to use its value also in the calculation of Y (the component of the vertical movement), since the position will be weighted by the inclination of the pitch angle.
If, on the other hand, the wind can have any direction and direction, I would say it is more appropriate for you to use vector algebra (considering both the velocity of the projectile and the wind velocity as vectors and adding them together to have the resulting vector for point-to-point application in the calculation of the trajectory). In that case, use the non-trigonometric versions of the formulae (formulae (1) and (3)), because the inclination angle will be "embedded" in the vector direction.
For example, suppose you have your projectile and wind velocity defined as vectors, as follows:
Vector2 veloc = new Vector2(10, 20)
Vector2 vento = new Vector2(2, 0);
Vector2 res = veloc + vento;
When making a vector sum you get a new vector (res
) which is a "combined" speed. Note the graph below:
The velocity vector of the projectile (veloc
) is in purple, drawn from the origin (0, 0). The vector of the wind (vento
) is in green, also drawn from the origin (0, 0). This same wind vector was also drawn from another origin, the "final tip" of the velocity vector (i.e., point (10, 20)), in a light blue, only to demonstrate graphically the idea of vector sum. The result of this sum is a new vector (res
), drawn in red, resulting in point (12, 20). See how the resulting vector (in red) "points" to the same location as the "path" traveled by the two vectors that were added (purple + green).
In this example, the wind speed vector (vento
) had a value of 0 in the vertical component (the value of Y), so it is a merely horizontal wind (as you can see clearly in the graph). But he could have any direction and sense. For example, if instead of blowing right horizontally with force 2, the wind blew northwest:
Vector2 veloc = new Vector2(10, 20)
Vector2 vento = new Vector2(-5, 7);
Vector2 res = veloc + vento;
The following resulting graph would have been:
Note that the projectile’s original velocity (in purple) was affected by the wind (in green) to produce an appropriate resulting velocity (in red), as previously described.
If you use vectors instead of unique values for the speeds, you can use the above formulas to do something like this:
Vector2 veloc = new Vector2(10, 20)
Vector2 vento = new Vector2(-5, 7);
Vector2 s = 0 + (veloc + vento) * t - (g * t * t);
Note in the last line how the application of the physical formula (3) remains equal, with the difference that the resulting spatial value (s
) is now a vector (which contains both components X and Y).
Also note that the variable g
, that today in its code is a unique value, could also be a vector. "natural" gravity would be something like Vector2 g = new Vector2(0, -9.8)
(remember that you would need to get back the signal from +
in the formula calculation, since the negative sign is embedded in the vector direction), because it acts only on the Y axis and downwards. But you could even implement a different gravity in a space game, for example, doing something like Vector2 g = new Vector2(2, 7)
(this crazy "gravity" in a game would pull everything up, and slightly to the right). :)
Finally, note that, although several people have commented, until today you don’t describe question how the projectile moves in your game. You say you use Unity, but you don’t explain whether the motion of the projectile is controlled by you (that is, doing the calculations in the same way as described so far and the translation manually), or whether you simply apply an initial impulse force and Unity physics takes care of the rest. Since "wind" is not a feature that exists natively in Unity physics, we would also need to know if the wind you say already works on the projectile (so much so that the actual stroke does not match what you draw) is constantly applied to the rigid body of the projectile by some code of yours. In the real world the wind is a constantly active force, similar to gravity, and is therefore constantly applied to the moving projectile. If you want to reproduce this, you will have to consider the wind not as a speed, but as an acceleration. In that case, it would make more sense to have something like:
Vector2 veloc = new Vector2(10, 20)
Vector2 vento = new Vector2(2, 0);
Vector2 g = new Vector2(0, -9.8);
Vector2 s = 0 + veloc * t + ((g + vento) * t * t);
That is, adding the vectors of wind acceleration and gravity to have the correct acceleration being applied at each time instant.
For information on formulas, see this website. If
need, compare what has been explained here with the explanations in this
my other answer.
The aerodynamic drag is proportional to the square of the relative speed, so it would be an additional force, added to what you already have, you have to take the square of the difference between the object’s current speed and the wind speed. It is also necessary to consider the various cases (as favor wind, which can even accelerate the object instead of braking it)
– epx
Is some C# implementation of something similar to Robocode in Java? If so, it would be nice to share with the community. :)
– Luiz Vieira
The question is super interesting and very cool. But you can improve the clarity in some things. 1) Should I consider images as a top view (I’m looking at the tanks from above) or side view? 2) From the second image, it seems that the tank throws up (that is, side view and with the projectile making a parabola), but the angle of the shot considers a 3D axis or only 2D? 3) When you say that "the game gives the force and the angle", it means that it is already calculated and that the player has no control (it seems that the player only controls the wind...)?
– Luiz Vieira
In the reply of colleague @zwitterion you commented: "The variables Voxt and Voyt are also not stated in my context...". Of course not. The colleague just tried to explain the calculation to you - you need to try to implement it in your code. It’s still a little hard to understand exactly what you want. I’m not a physicist, but the formula you use only considers the vector of gravity, so it doesn’t even have a force component on any axis other than the vertical one. There is missing some important information on how your projectile today already travels some horizontal distance.
– Luiz Vieira
In fact, I just realized that you are not implementing this natively in C#, but using Unity3d (by using
Vector3
there and by the tag you added later). You should have made the question clearer from the beginning. By the way, since you use Unity, is the projectile using the native physics of the engine? If so, you should indicate this! Another thing, it would make it a lot easier for someone to help you if you provide a [mcve] to facilitate testing and implementation.– Luiz Vieira
What is the range of the force variable?
– pmargreff
Manually from 0 to 100.
– CypherPotato
The current answers may not even contain enough details, but your question also does not contain the necessary details. For example, you still haven’t answered whether the actual trajectory (that of the projectile, wind and all) is calculated by you or by Unity physics. The impression I get is that you have no idea how the code you have works (because it was a "guy" who did it). And then, my dear, it gets really hard for anyone to help you.
– Luiz Vieira
I insist: if the excerpt of code you posted is really enough to explain the co-production of your project today, try to prepare a [mcve] with it. If I can, I I pledge myself testing here and trying to help you.
– Luiz Vieira
Looking at all the comments and formulations, I miss an acceleration force. If you implement an acceleration force you can apply the force of gravity and wind speed to it.
– luisaddor
Hello again. Today I answered to that question, and I think what you have there can help you with your doubt here (if you still have it, of course). I don’t know the details of your implementation, but you might want to compare the codes.
– Luiz Vieira
For you to implement a "simple" wind in the code I posted there in the other answer, do the following: create a
Vector2
with the wind force you want to use, add it to the variablem_force
, just before it was used. The wind will count as a positive force (if in the same direction as the current force) or negative force (if against the current force), on both axes. Note that: an active wind works more or less like gravity: it is constantly influencing the projectile - gravity only influences the Y axis, while the wind influences the two axes.– Luiz Vieira
look at github, a library that has a chaos theory implementation. convert the library to c#. and try in some way to modulate the wind behavior as it seeks, and see which formula or set of formulas based on that same principle, which better of the answer to what it seeks
– Tiago Morais Morgado
I appreciate the feedback. was the best solution I could find, and it would be exactly this way that I would solve the problem if I were in the same situation. so I even suggested this solution as a possible answer to the problem. I understand that I don’t get the kind of response that maybe you’re waiting for, but once I can have a solution that goes through invoking either a function or an obggecto that someone else stuttered, I save a little bit of trouble. attentively, without any other subject
– Tiago Morais Morgado
take a look at this https://github.com/krlgrgn/OpenGL-Particles
– Tiago Morais Morgado
@Thiagomoraismorgado Read what permagreff said. The question here is not just getting the result, but knowing how to calculate. But even if using a third-party solution helped, your original answer just says "go and find another library that calculates it for you," which doesn’t answer either. It could be a comment at most. You can edit your reply explaining better what you meant by linking to the code you found and preferably some code or some indication of the snippet that solves the problem. This would work well as a complement.
– utluiz