This site requires JavaScript, please enable it in your browser!
Greenfoot back
Michael1000
Michael1000 wrote ...

2016/5/25

How to apply gravity and air resistance?

Michael1000 Michael1000

2016/5/25

#
Thank you for helping me with the previous issue, but I have another problem with my project. I am trying to make it so, that the projectile is given an initial angle and velocity, after which it travels accros the screen, and then disappears. I am also however planning on including gravity and air resitance into the program, but my previous attempts have failed. Can somebody explain please with examples, that how can I make my program work? I have been trying to use trigonometry and setLocation functions, but they haven't helped me.
SPower SPower

2016/5/25

#
If you want to specify a velocity and an angle, what you're doing is using polar coordinates to express velocity. It's easier to first convert them into x and y coordinates before continuing:
int angleInDegrees = something; // I expect you have an angle in degrees
double angleInRadians = Math.toRadians(angleInDegrees); // Java however needs it expressed in radians
double sine = Math.sin(angleInRadians);
double cosine = Math.cos(angleInRadians);
// with some basic trig:
double velocityX = velocityMagnitude *cosine;
double velocityY = -velocityMagnitude *sin;
The velocityY is negative because y points down (+y is downward) in Greenfoot. Depending on the way you express your angle (i.e., the way it 'rotates' as the angle increases, e.g. clockwise or anti-clockwise), you'd need to change some negative signs here. I advice you to make velocityX and velocityY instance variables, so you won't have to compute them each act cycle (sines and cosines are expensive in terms of CPU power). Then, on to gravity. Gravity only works in the down (i.e. y) direction, and in Greenfoot +y goes down, so gravity is a positive acceleration in the y-direction in this case. Because one may assume each act cycle is of constant time, you can represent gravity with a constant addition to the velocity in the y-direction, which you would have to experimentally fine-tune to get the result you want. Each act cycle, you would do:
velocityY += gravityAcceleration; // you'd have to find a number for gravityAcceleration
setLocation(getX() +(int)Math.round(velocityX), getY() +(int)Math.round(velocityY));
And as for air resistance, that is a force the other direction, so it would be a negative acceleration in the y direction. According to basic physics, air resistance is a product of some constants depending on, among other things, the size of the object, and the velocity squared, it would be computed like this:
double airResistanceAccel = constants *velocityY*velocityY; // you'd have to pick a value for constants
You may wish to include a factor for the size of the object that you can specify, depending on your needs. Then, in the act cycle, simply add this line before changing the location:
velocityY -= airResistanceAccel;
If I made any mistakes (which is possible - I have a tendency to overlook stuff), please point them out.
SPower SPower

2016/5/25

#
Some extra info: when I mentioned the possibility of adding a 'size' measurement for the air resistance factor, to do it properly, I should have said 'frontal area', which would translate in this case to the square of the width of the object (assuming the object is square in its frontal area), or some factor multiplied by the width of the object. Though depending on what kind of result you're looking for, this addition would not even be necessary, and I actually doubt if air resistance should be visible at all in this, but again, I don't know your implementation goals :)
Michael1000 Michael1000

2016/5/25

#
Thank you very much for the help, but when I implimented the code the trajectory of the projectile was an inverse parabola, and not the parabola it would hopefully be.
SPower SPower

2016/5/25

#
As I stated in my post, depending on the way you implement it, you would have to change some negative signs. Try calculating the x and y components of the velocity like so:
 double velocityX = velocityMagnitude *cosine;
double velocityY = velocityMagnitude *sin;
Michael1000 Michael1000

2016/5/25

#
*not an inverse parabola, but a parabola with a positive cofactor of x^2.
Michael1000 Michael1000

2016/5/25

#
sorry for the inconvenience
Michael1000 Michael1000

2016/5/25

#
I think that I solved my problem. Thank you very much for this help.
SPower SPower

2016/5/25

#
When I implement my code, I get a parabola with a negative coefficient, so there is something wrong with your implementation. And to correct my previous post, you do need to make the velocityY negative (making it positive makes no sense since +y is downward in Greenfoot, unless you want the angle to increase clockwise starting with 0 degrees pointing at +x).
SPower SPower

2016/5/25

#
To summarise the code I implemented in my own test:
velocityY = - velocityMagnitude *sine;

// in act:
velocityY += gravityAccel; // added, not subtracted
velocityY -= airResistanceAccel; // subtracted
setLocation(getX() +(int)Math.round(velocityX), getY() +(int)Math.round(velocityY));
danpost danpost

2016/5/25

#
I have written a support class for smooth movement and rotation that has a subclass to apply gravity and drag (air-resistance). They are both included in my GQActor Superclass Demo scenario.
You need to login to post a reply.