Implementing 2D Physics

  • (4 Pages)
  • +
  • 1
  • 2
  • 3
  • Last »

51 Replies - 8854 Views - Last Post: 25 June 2012 - 09:56 PM

#1 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Implementing 2D Physics

Posted 09 May 2012 - 01:55 AM

Hello,

I'm currently working on a 'Generic Engine' that I can use for multiple games, and am up to creating a physics system.

I was thinking of creating a Physics class, with a few methods like CreateForce() and what not, but I am seeking some help with general gravity.

I know there are countless tutorials on the web, but I find that it helps me to write things down, and I thought why not do it on the forum and see what other people suggest.

Basically I want a few features, but not that complicated for the time being as it is my first engine.



Vector2 position, velocity, gravity;
float elapsed = (float)gameTime.ElapsedGameTime.Milliseconds; // or something to that effect.
int mass;



There are probably a few more I would need but I wanted to know what other people did.

I have a basic idea of what to do. Something like this:

velocity += gravity * elapsed;
position += velocity * gravity;



But I wanted to know how to implement the mass in as well.

With the bouncing I thought of doing something like this: (but it didn't work ;()
if (Collision)
{
   velocity = new Vector2(-velocity.X * mass, -velocity.Y * mass);
}



Is there also something I should be doing to tone done the values, because when I mix a few of them together it goes kinda crazy

Thanks in advance,
Daniel,

Is This A Good Question/Topic? 0
  • +

Replies To: Implementing 2D Physics

#2 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 579
  • View blog
  • Posts: 1,285
  • Joined: 24-April 12

Re: Implementing 2D Physics

Posted 09 May 2012 - 06:36 AM

Let me start by saying that I've never written any physics into any of the programs I can think of that I've ever written. I was real close in my current project and now I've decided to delve off into another project, for the moment. (Also as a disclaimer: I just woke up and haven't had my coffee yet.) So, hopefully, you'll forgive me if my comment isn't helpful or along the lines of what you were asking. But I thought I would add my 2 cents.

If I were going to implement something similar, with mass and gravity, I would probably start thinking about it like this:

First of all, you probably want to think of speed as "momentum". Say I have a ball in space. It's not moving. It's momentum is zero. Say it has a mass of 10 kilograms. It's momentum is 10*zero= zero.

Momentum = Mass * Velocity

Now we want to move it, so we hit it with a vector (an amount of force in a specific direction - we'll call the direction "forward"). Notice that we have no gravity so far. We apply the force to it as an "acceleration". Accelerations happen "in time". Basically you are adding a velocity over a period of time.

A velocity is a distance of change over a period of time. Let's use seconds for our time period. And let's use meters for our distance. So, the ball's velocity is zero meters of movement per second.

An acceleration is an increase in velocity over a period of time. So, we add a velocity every second, for example. Notice that velocity already has a time component. So if we add a forward acceleration of 1 meter every second (with our imaginary rocket engine or something) then you have 1 meter of movement per second added every second. Notice time is in their twice now.

So we apply the acceleration for 2 seconds and stop the acceleration. Now the ball has a velocity of 2 meters every second from adding a 1 meter per second acceleration for two seconds.

The ball's momentum is it's velocity times it's mass. So the momentum is 10 kilograms * 2 meters per second = 20kilogram-meters per second.

Word problem time! How much force does it take to stop the ball?

Well first thing is that we need to apply an amount of force in a specific direction (the exact opposite of "forward") which is a vector. (A vector is an amount tied to a direction).

Force = Mass * Acceleration
Force = Momentum over a time period

So, we could apply our force by striking our original ball with a second ball from the exact opposite direction (pool table physics). Let's say this ball is 2 kilograms (quite a bit lighter). We would have to accelerate it to 10 times the amount of the other ball or 10 meters per second velocity.

I would point out that momentum is almost the same thing as a force. The difference is that a force has a speed in seconds and is applied over a period of time.

So, to stop it, we have to apply a momentum per second for a certain number of seconds, which is a force. A 2 kilogram ball with a velocity of 10 meters per second, acting on the first ball for one second. Since both objects are acting on each other for the same period of time I think you basically just cancel out the time period.

Anyway, gravity is just an acceleration towards the planet.

I don't know if that helps or if I'm just rambling. :-)
Was This Post Helpful? 3
  • +
  • -

#3 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 579
  • View blog
  • Posts: 1,285
  • Joined: 24-April 12

Re: Implementing 2D Physics

Posted 09 May 2012 - 07:38 AM

Ok. Now that I've had half a cup of coffee, maybe I can talk about the actual problem. :-)

Wikipedia has some good info:
http://en.wikipedia....iki/Gravitation

Earth's gravity is 9.81 meters per second every second. It's an acceleration that always accelerates you towards the center of the planet.

So, I would start by positioning my ball and "dropping" it. That means you need to apply a gravity vector of 9.81 meters per second every second. At 60 Updates per second, you need to apply 1/60th of that amount. So gravity per frame (at 60 frames per second is 9.81m per sec per sec /60 frames per sec = 0.1635 meters per second.

So you need to apply a downward vector of length 0.1635 meters every frame.

The acceleration will continue until it reaches terminal velocity. That's where mass comes in, because it's part of the drag equation.

Terminal Velocity = SquareRoot((2*mass*gravitational acceleration)/(projected area of the object*fluid density of air*drag coefficient))

Anyway, velocity can never be allowed to exceed terminal velocity when falling.

I would have to do some research to calculate terminal velocity. We've already covered mass and gravity. The projected area of a ball should be the area of a circle the diameter of the ball. It's roundness or flatness would probably be part of the "drag coefficient" and I think most coefficients like this, in physics, don't have a formula for calculating them unless the object is as simple as a ball... maybe. You can probably get the fluid density of air from somewhere on the internet.

You may be best off by just "winging it" and just assigning a terminal velocity without calculating it. The drag coefficient is probably going to have to be a guess anyway. I think that sort of thing is generally determined by engineers who go out and experiement until they find the coefficient by observation. Then they publish it in some journal or something for other engineers to lookup. But there may not be a way to "calculate it".

98 meters per second seems to be good for a bullet's terminal velocity and about 50 meters per second for a skydiver with arms out and what not. I would be tempted to just plug in a number for terminal velocity.

http://en.wikipedia....iki/Gravitation

http://en.wikipedia..../Drag_(physics)

What happens when the ball collides with the Earth? Good question. Glad you asked. ;-)

Its a question of how "elastic" the collision is. I "believe" what should happen "theoretically" is that the ball would reverse course (sp?) and head upwards with the exact same velocity it had when it hit. Gravity acting against that velocity vector would slow it until it started falling again.

In the real world, collisions are almost never completly elastic. Part of the energy is lost in the form of sound and heat even if the sound and heat aren't noticed. So, you should probably have a factor in the equation for collision elasticity.

Instead of mearly reversing the ball's velocity vector from down to up (by multiplying the vector by -1) you should probably also reduce the velocity vector by an "elasticity coefficient". In other words you could probably multiply the vector times (-1+elasticity). You probalby want to keep the elasticity coefficient very small and always less than one. So the elasticity coefficient would be 1 for perfect elasticity and 0 from perfectly inelastic (and you should play a "thud" sound effect for the ball that doesn't bounce ;-) )

Anyway, that probably helps more than my last post. I hope so anyway.

Also, just as a reminder - in case I wasn't clear or you didn't already realize this - but gravity is an acceleration, not a velocity. In otherwords it's added to the downward velocity every second (or every frame or whatever). So, don't get confused and just move the ball the distance of the gravity. The ball needs to be moved the distance of velocity which is increased by the amount of gravity every second until velocity reaches terminal velocity or it hits something.

You probably already knew that though.
Was This Post Helpful? 3
  • +
  • -

#4 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 579
  • View blog
  • Posts: 1,285
  • Joined: 24-April 12

Re: Implementing 2D Physics

Posted 09 May 2012 - 07:50 AM

Oops. I wrote that elasticity coefficient equation wrong. It's -1 plus the e-coefficient. Multiplying a vector time -1 reverses it's direction without changing it. Our vector is the velocity.

So it's Vector * (-1 + e). Where e is the elasticity coefficient affecting -1. So 1 will change it to zero and make the ball stop dead on collision and 0 will not affect -1 at all and make the collision perfectly elastic. A number in between will give you something in between.

You might want to store an elasticity coefficient with every object involved in collisions.

I'm also assuming the earth is perfectly elastic. Really the elasticity coefficient calculation should probably be

Vector * (-1 + (e1 + e2)/2)

In otherwords it should probably be an average of the two objects or something like that. I mean what happens if 2 bouncy objects hit each other and what happens if two hard objects hit each other and what happens if a bouncy object hits a hard object? I'm thinking

Earth's e-coefficient = 1
Ball's e-coefficient = 0

then the e-coefficient is 0.5

but in reality earth is probably more like 0.9 and the ball is probably more like 0.1 but that still gives 0.5 for their average.
Was This Post Helpful? 1
  • +
  • -

#5 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 579
  • View blog
  • Posts: 1,285
  • Joined: 24-April 12

Re: Implementing 2D Physics

Posted 09 May 2012 - 10:30 AM

View PostBBeck, on 09 May 2012 - 07:38 AM, said:

Terminal Velocity = SquareRoot((2*mass*gravitational acceleration)/(projected area of the object*fluid density of air*drag coefficient))

Anyway, velocity can never be allowed to exceed terminal velocity when falling.

I would have to do some research to calculate terminal velocity. We've already covered mass and gravity. The projected area of a ball should be the area of a circle the diameter of the ball. It's roundness or flatness would probably be part of the "drag coefficient" and I think most coefficients like this, in physics, don't have a formula for calculating them unless the object is as simple as a ball... maybe. You can probably get the fluid density of air from somewhere on the internet.



I got to thinking about this and realized a few things.

The "projected area of the object" is "projected". I said "The projected area of a ball should be the area of a circle the diameter of the ball." That's a good start, but you need to multiply that times the distance that the object moves through the air during that time. Turns out this is kind of "key" to understanding what's happening. I remember reading about this in a paper about automobile physics for a "game" that I've been working on.

Basically the "projected area of the object" is the air column that the object has to push out of the way in order to move. That's why it's a key part of drag. The air column for the ball would be the surface area of a circle the same diameter as the ball times the distance the ball will travel per frame (or whatever unit of time). It's basically the velocity vector (distance traveled) times Pi times the radius of the ball squared (Pi*r^2). Basically, it's the velocity vector times the area of the object's shadow. Imagine a light shining directly down over that object.

This should work perfectly with a perfectly flat "ball", or other object, but our object has a more "aerodynamic" shape which is probably where the "drag coefficient" comes in.

The "fluid density of the air" * the "projected area" is probably "basically" the weight of the air column that has to be moved out of the way for the ball to travel. So when the ball is suspended in the air, and not moving, it's the "shadow area" of the object times zero = zero drag. As the object moves through the air it moves an air column basically equal to its shadow size times the distance it moves during that period of time (one frame in XNA or 1/60th of a second). The faster it moves the longer the air column gets. So drag goes from zero and goes up very fast as the object moves faster and faster. Eventually the column of air weighs so much that the object reaches terminal velocity and can't travel any faster without something pushing it faster (like a rocket engine) or changing its "shadow area" by something like a skydiver bringing his arms in and going head down.

The interesting thing is that this is not only for terminal velocity. It's also for regular movement. Horizontal movement works the same way. The article I was reading the other day says a car pushes aside a column of air in front of the car. You could imagine a light shining behind the car to project it's shadow in front of the car to get its "shadow size". At a stand still it's not pushing anything. 1 foot per second and the column is now the shadow size times 1 foot for one second of movement. Speed the car up to 1000 feet per second and the air column it has to push out of the way is the "shadow area" times 1000 feet for one second of movement.

The end result is that you can speed up to 60 mph real fast, but it's much slower to get up to 150 mph because the air column you are pushing out of the way is larger. Eventually, the car doesn't have enough power to push a bigger air column and the car reaches it's max speed. So the max speed of the car is directly related to the size of the air column that it can push out of the way for a given horse power.

So maybe its worth while to explore the terminal velocity formula a little closer, since if you replace gravitational acceleration with a car's acceleration you basically have a formula to determine a car's max velocity.

Also, if you want to make this more complicated realize that air density changes with temperature and elevation. As if this were not complicated enough. ;-)

View PostBBeck, on 09 May 2012 - 07:38 AM, said:

Terminal Velocity = SquareRoot((2*mass*gravitational acceleration)/(projected area of the object*fluid density of air*drag coefficient))

Anyway, velocity can never be allowed to exceed terminal velocity when falling.

I would have to do some research to calculate terminal velocity. We've already covered mass and gravity. The projected area of a ball should be the area of a circle the diameter of the ball. It's roundness or flatness would probably be part of the "drag coefficient" and I think most coefficients like this, in physics, don't have a formula for calculating them unless the object is as simple as a ball... maybe. You can probably get the fluid density of air from somewhere on the internet.



I got to thinking about this and realized a few things.

The "projected area of the object" is "projected". I said "The projected area of a ball should be the area of a circle the diameter of the ball." That's a good start, but you need to multiply that times the distance that the object moves through the air during that time. Turns out this is kind of "key" to understanding what's happening. I remember reading about this in a paper about automobile physics for a "game" that I've been working on.

Basically the "projected area of the object" is the air column that the object has to push out of the way in order to move. That's why it's a key part of drag. The air column for the ball would be the surface area of a circle the same diameter as the ball times the distance the ball will travel per frame (or whatever unit of time). It's basically the velocity vector (distance traveled) times Pi times the radius of the ball squared (Pi*r^2). Basically, it's the velocity vector times the area of the object's shadow. Imagine a light shining directly down over that object.

This should work perfectly with a perfectly flat "ball", or other object, but our object has a more "aerodynamic" shape which is probably where the "drag coefficient" comes in.

The "fluid density of the air" * the "projected area" is probably "basically" the weight of the air column that has to be moved out of the way for the ball to travel. So when the ball is suspended in the air, and not moving, it's the "shadow area" of the object times zero = zero drag. As the object moves through the air it moves an air column basically equal to its shadow size times the distance it moves during that period of time (one frame in XNA or 1/60th of a second). The faster it moves the longer the air column gets. So drag goes from zero and goes up very fast as the object moves faster and faster. Eventually the column of air weighs so much that the object reaches terminal velocity and can't travel any faster without something pushing it faster (like a rocket engine) or changing its "shadow area" by something like a skydiver bringing his arms in and going head down.

The interesting thing is that this is not only for terminal velocity. It's also for regular movement. Horizontal movement works the same way. The article I was reading the other day says a car pushes aside a column of air in front of the car. You could imagine a light shining behind the car to project it's shadow in front of the car to get its "shadow size". At a stand still it's not pushing anything. 1 foot per second and the column is now the shadow size times 1 foot for one second of movement. Speed the car up to 1000 feet per second and the air column it has to push out of the way is the "shadow area" times 1000 feet for one second of movement.

The end result is that you can speed up to 60 mph real fast, but it's much slower to get up to 150 mph because the air column you are pushing out of the way is larger. Eventually, the car doesn't have enough power to push a bigger air column and the car reaches it's max speed. So the max speed of the car is directly related to the size of the air column that it can push out of the way for a given horse power.

So maybe its worth while to explore the terminal velocity formula a little closer, since if you replace gravitational acceleration with a car's acceleration you basically have a formula to determine a car's max velocity.

Also, if you want to make this more complicated realize that air density changes with temperature and elevation. As if this were not complicated enough. ;-)
Was This Post Helpful? 3
  • +
  • -

#6 bonyjoe  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 175
  • View blog
  • Posts: 548
  • Joined: 08-September 10

Re: Implementing 2D Physics

Posted 09 May 2012 - 10:35 AM

I suggest you just use a physics library like XNABox2D or Farseer. The reason I say this is because a few days ago you were asking about how to use properties, so I'm assuming you are relatively new to the language and XNA. If there is anything that will lead to you becoming burnt out quickly it's definitely physics as it's mathematically heavy and is a major blackhole, once you start implementing things you will think of more and more things that need to be in there to complete it.

I completed a basic 2d physics engine for a university module last year and I thought it was awesome at the start, but sincerely hated it by the end. Though if you are interested in knowing how I handled forces you're welcome to ask.
Was This Post Helpful? 2
  • +
  • -

#7 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 579
  • View blog
  • Posts: 1,285
  • Joined: 24-April 12

Re: Implementing 2D Physics

Posted 09 May 2012 - 11:16 AM

For anyone whos managed to wade through the "novel" I've written in this thread, I thought maybe I should explain the vectors in this problem a little better. For people reading this thread that don't understand vectors, I at least wanted to explain the vector math for this problem.

The main thing I wanted to clarify was the idea of applying a "coefficient of elasticity" to your velocity vector during collision.

Remember, all a vector is is an amount that's permenantly tied to a direction (except unit vectors which have an amount of one because you only care about their direction).

Think of vectors as arrows where the length of the arrow is the amount. The tail is always at 0,0 - or 0,0,0 for 3D. The head position is what you are storing in your vector object. The amount is the distance between tail and the head of the arrow and the direction is whatever direction the head is pointing in.

So, basically you have a position vector that really isn't a vector at all because you're just using it to store positional coordinates. That's fine, just don't get confused with it.

Every frame (60th of a second) you add a vector that points in whatever direction the ball is traveling to the position coordinates (causing it to move). Starting out this velocity vector has a length of zero. You always apply this velocity unless some collision blocks the object from moving.


Every frame you add any accelerations to the object's velocity/movement vector. Gravity is a constant downward vector(0f,-0.1635f) that gets applied every frame. To apply it you just change the velocity vector by this amount. So,

New Velocity = Velocity from the previous frame + Gravity Velocity.

You add the two vectors together and then change the position of the object's position. I'm thinking you want a Translation matrix to translate the position "vector" by the new velocity vector. I think you could also add the velocity vector to the position vector every frame.

You'll need to check for a collision, which would prevent the object from moving, and make sure the velocity vector never gets longer than terminal velocity (which you could start by saying is 1.6 units per frame and then just play with the number from there if you don't want to get into the complexities of calculating a terminal velocity.)

If a collision occurs, in any direction, you have to apply the elasticity coefficient to determine whether the objects bounce off of one another.

When the object collides with another object multiply the velocity vector * (-1 + the elasticity coefficient) like I talk about above.

I wanted to talk about this for those that don't necessarily understand vector math. Velocity is a vector and the elasticity is not. It's a normal number. That's called a "scaler".

So you're multiplying a vector times a scalar. I believe the way to do this is multiply the scaler number times every coordinate in the head position of the vector. So for 2D you're just multiplying the X and Y coordinates times the scalar. Just realize you're multiplying both x and y.

But really, it doesn't matter if you know this. XNA is really good with vector math. I'm pretty sure you can just multiply a vector object times a scalar number and XNA just know how to do it.

When you multiply a scalar times a vector, you are changing the length of the vector without changing it's direction. The exception of that is that if you multiply a vector times a negative number it reverses the direction of the vector.

So the easy way to reverse the direction of a vector is to multiply by -1. Otherwise, multiplying a vector times a scalar only changes the vector's length (which represents some "amount" such as velocity).

So, in our collision multiplying the velocity bector times -1 results in the vector just turning around the opposite direction. We don't want it to accelerate for no reason in a collision, because - if anything - the collision is going to slow it down but never speed it up. So, we multiply by a number between 1 and 0 (actually -1 and zero if you include the change in direction). This is going to shorten our velocity vector representing the loss of speed during the collision.

Now our object is moving in the opposite direction (up if it was moving straight down). We still apply the gravity acceleration vector to the velocity vector. But now the velocity vector and the gravity vector are pointing in exact opposite directions. When moving downward, both vectors were negative. Now that the velocity has reversed directions and is positive, adding the negative acceleration vector causes the velocity vector to grow shorter every frame until it reaches zero and the object stops moving.

Then adding the gravity acceleration vector causes the velocity vector of the object to again grow and be negative, causing downward movement.

Any other acceleration to the object will basically cause it to do the same thing, it's just that a different acceleration vector will probably not be pointed straight down.

If the object hits a wall, the collision will work basically the same way, but the velocity vector will be pointing horizontal and reversing it's direction will point it in the opposite direction.
Was This Post Helpful? 3
  • +
  • -

#8 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 579
  • View blog
  • Posts: 1,285
  • Joined: 24-April 12

Re: Implementing 2D Physics

Posted 09 May 2012 - 11:45 AM

View Postbonyjoe, on 09 May 2012 - 10:35 AM, said:

I suggest you just use a physics library like XNABox2D or Farseer. The reason I say this is because a few days ago you were asking about how to use properties, so I'm assuming you are relatively new to the language and XNA. If there is anything that will lead to you becoming burnt out quickly it's definitely physics as it's mathematically heavy and is a major blackhole, once you start implementing things you will think of more and more things that need to be in there to complete it.

I completed a basic 2d physics engine for a university module last year and I thought it was awesome at the start, but sincerely hated it by the end. Though if you are interested in knowing how I handled forces you're welcome to ask.



I agree and I disagree. If you've read this far into this thread, you're probably getting an idea of how complicated it can get just applying gravity and a simple collision with the ground to an object. If this is just way more than you are ready to think about then a physics library may help you.

If you're seriously trying to put together a working game to sell, or even maybe to share with your friends, then maybe considering a physics engine is a good idea.

But, if you're just learning and playing around, I say "Why not play around with physics too." You might find that you like physics. And even if you're not crazy about it, you need to know what your physics engine is doing at some point.

If you're just learning and "messing around", then your "physics model" doesn't have to be super realistic. For example, I suggested just assigning a terminal velocity. I mean why not? If it gets you close enough to make you happy, it's good enough. On the other hand, if you dive in and understand what causes terminal velocity maybe you can make your model a little more realistic.

I'm guessing that a physics engine of any real ability is going to cost money. And implementing gravity in your 2D program is not much harder than what I've discussed in this thread. I think it could be a great learning experience to dig in and figure out the physics. And you can always go buy a physics engine if you get frustrated.

As for the math, there's vectors involved. The bad news is that almost every problem is going to have a lot of vectors in it. The good news is XNA knows how to do vector math even if you don't. And vectors aren't nearly as hard to understand as a lot of people make them out to be. They are nothing other than an amount that is permenantly tied to a direction. That's it. Period. They're just that simple. I intend to write a tutorial explaining vectors in the not too distant future. But just realize they are that simple.

I've bought two books on game physics now, and both of them were full of calculus formulas. Let me tell you that my college physics text book basically doesn't have one single calculus equation in it. Most physics can be solved with just addition/subtraction, multiplication/division, and vectors. Maybe throw in some trig when working with rotations and angles.

Complex physics models are complex. But the math generally doesn't get much worse than what I've thrown out in this thread unless your physics model is being used for scientific research. Games physics is about 80% to 90% accurate to the real world (at best and often throws reality completly out the door). Scientific models may get to 99.9% realism and require a PHD to put together. But your players may never notice the difference between 90% accurate and 99.9% accurate.

I'm sure BoneyJoe's recommendation of using a physics engine is words of wisdom from experience. But I think it's worth your while to attempt to do your own physics if you enjoy it and maybe also just to get a better understanding of what the physics engine is doing.

For anyone ready to go off the "deep end" and play around with Game Physics, I suggest this book

http://www.amazon.co...36588644&sr=8-1

It costs an arm and a leg, but that's just the way it is with college text books. If you live with your parents, they might buy it for you just because you're expressing an interest in physics. Also, I think the two "game physics" books I own probably cost almost $100 for the two books and I found both of them basically useless.

It's actually a lot easier to read than the "game physics" books that I've seen and probably explains a lot of things better. You probably need to know algebra pretty well, and probably need to know trig to get much out of it though. But no calculus required. There's no computer code in it, but it teaches you what happens in the real world, and then you can figure out how you want to code it.

Really, I think it comes down to this: if you bothered to read this thread this far and you thought this discussion was "interesting" you should probably keep playing around with physics. If you're not reading this right now, or you just thought this sounds boring or way too complicated, then a physics engine may be right for you. Or, if you don't want to learn and play around, but instead want to get directly to making a working game, then maybe a physics engine is right for you.

Incidently, you can get a lot of the physics formulas just by "Googl-ing".
Was This Post Helpful? 3
  • +
  • -

#9 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 579
  • View blog
  • Posts: 1,285
  • Joined: 24-April 12

Re: Implementing 2D Physics

Posted 09 May 2012 - 12:55 PM

View PostDanielLeone, on 09 May 2012 - 01:55 AM, said:

Hello,

I'm currently working on a 'Generic Engine' that I can use for multiple games, and am up to creating a physics system.

I was thinking of creating a Physics class, with a few methods like CreateForce() and what not, but I am seeking some help with general gravity.

I know there are countless tutorials on the web, but I find that it helps me to write things down, and I thought why not do it on the forum and see what other people suggest.

Basically I want a few features, but not that complicated for the time being as it is my first engine.



Vector2 position, velocity, gravity;
float elapsed = (float)gameTime.ElapsedGameTime.Milliseconds; // or something to that effect.
int mass;



There are probably a few more I would need but I wanted to know what other people did.

I have a basic idea of what to do. Something like this:

velocity += gravity * elapsed;
position += velocity * gravity;



But I wanted to know how to implement the mass in as well.

With the bouncing I thought of doing something like this: (but it didn't work ;()
if (Collision)
{
   velocity = new Vector2(-velocity.X * mass, -velocity.Y * mass);
}



Is there also something I should be doing to tone done the values, because when I mix a few of them together it goes kinda crazy

Thanks in advance,
Daniel,



Boy, I can't leave this topic alone. ;-)

But, I went back and reread your post. I realized after discussing this whole thing what the issues are in your equations.


velocity += gravity * elapsed;
position += velocity * gravity;



The velocity equation is basically true. You need to add the gravity vector to the velocity vector every frame or tick. Your formula is correct if elapsed is the percentage of a second that has passed since the last frame and gravity is per second. The gravity acceleration of 0.1635 could be added every from (every 1/60th of a second and you probably wouldn't need elapsed unless you have your game time set to not be 60 frames per second - which is a real posibility). Just realize that gravity is velocity change per second and you need to convert it to what ever unit of time each frame is.

Position, however will already have gravity in it due to having velocity in it. So, you don't need to add gravity in again.

if (Collision)
{
   velocity = new Vector2(-velocity.X * mass, -velocity.Y * mass);
}



This is going to result in explosive collisions (pun intended). Basically, you are accelerating during a collision by the mass of the object. So, a 10 mass object causes the object to speed up 10 times on collision.

If you read my previous posts you've probably realized that this formula needs to be

if (Collision)
{
   velocity = new Vector2(-velocity.X * elasticity, -velocity.Y * elasticity);
}




And I would do it like this:

elasticity = -1 + (ObjectA.elasticity + ObjectB.elasticity)/2;

if (Collision)
{
   velocity *= elasticity;
}



When the elasticity of the collision is 0, the object stops dead on collision. If the elacticity is 1 then the object wil reverse directions but the velocity will remain unchanged. Elasticity < 1 will be energy lost in the collision and a slow down. (And incidently, probably some indication of how much the objects were damaged in the collision. Zero elasticity means the objects absorbed 100% of the collisions energy.) Elasticity > 1 means the collision resulted in an acceleration. The only way I can envision this happening is if there was an explosion in the collision.

So back to my pun, if your collision multiplies the velocity * >1 then you are accelerating as if the objects are being blown apart due to the collision. And even a small number here will have BIG results since 1 is 100%. 4 will result in a 400% increase in velocity. Still, you may find this useful if you want to simulate an explosive collision.
Was This Post Helpful? 2
  • +
  • -

#10 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: Implementing 2D Physics

Posted 09 May 2012 - 05:10 PM

Okay, Just got home from school and read through all of the post, I really did.

And I have to say, they were actually really, really, helpful.

With what you said BBeck in reply to bonyjoe, I totally agree. I will try to implement my own physics because with only just having started learning programming a few months ago, the last thing that I really want is to 'copy' or import a massively complex system, even if it is close to realism.

I would much rather understand how all this stuff, physics, works even if it doesn't really turn out realistic, because to me it's all about a massive learning curve, not a massive success, not that you were wrong bonyjoe, because I would guarantee many people would just get a physics engine for the first time, it's just that I prefer to know what I'm doing and why.

As for all the other 'stuff' (what I way to sum that up ;)) you said BBeck, it all started to make a lot of sense to me. :D. I read through it about 3 times (including the duplicate post ;)), and comprehended it all, well most of it anyway.

That was truly a great 'tutorial' I would say, and honestly, I would consider making a physics tutorial out of it. It was in-depth, but not overly complicated. Great Job.

I changed my code dramatically, and I actually worked :D :D :D :D. I was totally surprised.
This is what I have, and will expand on it very soon :

            if (velocity.X < terminalVelocity.X && velocity.Y < terminalVelocity.Y)
            {
                velocity += gravity;
            }
            position += velocity;

            if (IntersectEdge())
            {
                velocity = new Vector2(-velocity.X * elasticity, -velocity.Y * elasticity);
            }



This works awesome for up and down directly but as soon as you add an X value, it goes a bit crazy (well because it stays in the same direction).

Also I need to change it so that it stops when the reaches a minimum velocity, so it doesn't start sinking into the ground :(.

That was truly and exceptional post (posts) BBeck, thanks immensely,

Daniel,

I'll post back when I complete some more on this,
(probably when I get a stupid error ;)),

This post has been edited by DanielLeone: 10 May 2012 - 01:45 AM

Was This Post Helpful? 0
  • +
  • -

#11 bonyjoe  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 175
  • View blog
  • Posts: 548
  • Joined: 08-September 10

Re: Implementing 2D Physics

Posted 10 May 2012 - 12:18 PM

if (velocity.X < terminalVelocity.X && velocity.Y < terminalVelocity.Y)
{
    velocity += gravity;
}



Doing it this way means that you can exceed the terminal velocity, for two reasons

a) You are doing an AND conditional which checks whether you are breaking terminal velocity on both axis, so you will keep adding on gravity because you are no faster than the termincal velocity on the x axis.

b ) you are testing before you add on gravity, so you may be at terminal velocity - 0.0000001 and because of that you add gravity and are now past your terminal velocity.

I would suggest testing your velocities separately and after all forces have been added. If terminal velocity is breached then set you velocity to terminal.

Good luck with your physics implementation though.

edit: silly smilies invading my writing

This post has been edited by bonyjoe: 10 May 2012 - 12:28 PM

Was This Post Helpful? 1
  • +
  • -

#12 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: Implementing 2D Physics

Posted 10 May 2012 - 04:11 PM

Thanks for the input bonyjoe, that makes sense and I'll implement it right now.

I've come across two problems though :(.

The terminalVelocity only works for incrementing, so I can go backwards or high as fast as I want.

And I want it keep momentum when bouncing, for example when travelling diagonally across and down the window, when I hit the ground, it negates both X and Y velocity. If hitting the ground, I basically want it to keep the X, and negate the Y only.

I can probably fix both of these myself, but have only just come across them, and as I said, I helps me to write things down.

Thanks once again for all the information and suggestions guys,
Daniel,

Have a smiley bonyjoe :) :) :) :) :) :) :) :) :) ;)

This post has been edited by DanielLeone: 10 May 2012 - 04:25 PM

Was This Post Helpful? 0
  • +
  • -

#13 racidon  Icon User is offline

  • D.I.C Head

Reputation: 59
  • View blog
  • Posts: 172
  • Joined: 27-August 11

Re: Implementing 2D Physics

Posted 10 May 2012 - 08:34 PM

I'd agree with bonyjoe, as making something bounce is one thing, but doing it accurately is another thing all together. You'll start off with gravity, then move on to inertia then energy transfer, it's going to slowly but surely evolve into some pretty complex stuff to make it "generic".
Was This Post Helpful? 0
  • +
  • -

#14 DanielLeone  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 177
  • Joined: 04-February 12

Re: Implementing 2D Physics

Posted 11 May 2012 - 01:20 AM

Hey racidon,

Maybe Generic was the wrong word, or we simply have a different definition from each other.

I probably meant something like 'Basic', or Simple but effective. All I want from this is a way to 'mimic', gravity and 1 or 2 modifiable variables.

Mimic was what I was intending there, I still want something similar to the effect of gravity, and thanks to BBeck, I now have that, but I only want it to be simple, effective, and does the job.

I understand where your're coming from racidon, I could easily take this much further and spend the next 8 months working on it. This however wouldn't be easy at all ;), and be a complete waste of my time. I would much rather, grasp the general concept of Programming Physics, and leave the complicated stuff for later.

Please don't reply saying I haven't grasp the concept, and that programming physics is nothing but complicated, because that won't be helping. Not that I'm assuming your are going to say that. Just want to avoid that particular conversation.

Anywho, thanks for the input, and I'll go with what you said (well the opposite), and make an effort to leave my physics at where it is now.

Apart from the problem of it not changing direction.

I have come up with what I think is a solution. That is to put in my IntersectEdge method, at the moment it returns a bool (weather it has intersected and edge) (Derr..). I have changed it to also return weather it was along an X or Y.

Then I use this other boolean, and basically do it like this (couldn't be stuffed trying to explain it ;)) :

        protected bool IntersectEdge(Rectangle rect, out bool X)
        {
            if (position.X - SourceRectangle.Width / 2 <= rect.Left)
            {
                X = true;
                return true;
            }
            else if (position.X + SourceRectangle.Width / 2 >= rect.Width)
            {
                X = true;
                return true;
            }
         
            if (position.Y - SourceRectangle.Height / 2 <= rect.Top)
            {
                X = false;
                return true;
            }
            else if (position.Y + SourceRectangle.Height / 2 >= rect.Height)
            {
                X = false;
                return true;
            }
            X = false;
            return false;
        }
            bool x = false;
            if (IntersectEdge(ScreenManager.Room, out x))
            {
                if (x)
                {
                    velocity = new Vector2(-velocity.X * elasticity, velocity.Y * elasticity);
                }
                if (!x)
                {
                    velocity = new Vector2(velocity.X * elasticity, -velocity.Y * elasticity);
                }
            }




That works, quite well actually, but was wondering if it was a good way of doing it?
If so, I'm happy with that, and have only one more question of this topic.

I so far have elasticity working great.
I also said that having something like an int for mass would be great.

Anyone have any ideas?

I just changed all the parts where velocity is increased by gravity to this:
     velocity.X += gravity.X * mass;



Works alright, but looks like everything just speeds up a bit.


If that is the most effective way of doing it without getting too complicated, then I'm happy with that, otherwise, any suggestions?

Thanks once again for showing the interest,
Daniel,

Wow, my post are getting nearly as long as one of BBecks ;).

This post has been edited by DanielLeone: 11 May 2012 - 01:27 AM

Was This Post Helpful? 0
  • +
  • -

#15 racidon  Icon User is offline

  • D.I.C Head

Reputation: 59
  • View blog
  • Posts: 172
  • Joined: 27-August 11

Re: Implementing 2D Physics

Posted 11 May 2012 - 03:26 AM

I'm not sure, as your method seems a little off to me, so apologies if I'm wrong. But wouldn't that method fail if your ball bounced in a corner?

Other than that I see no problem with the method itself.

Don't get me wrong I wasn't trying to discourage you, I've just experience the time spent on what I thought could be great engines I could use, when I still clearly don't have the expertise to write one properly. I read an article some time actually that explained don't start trying to write an engine just write helpful libraries you know will help you along the way.

Side note you seem to have picked it up quite quick, wish you the best :)
Was This Post Helpful? 0
  • +
  • -

  • (4 Pages)
  • +
  • 1
  • 2
  • 3
  • Last »