Conceptual Physics with an Environment like XNA

Gotta love my total improper capitalization but thats just how I type.

Page 1 of 1

14 Replies - 2123 Views - Last Post: 13 January 2011 - 02:01 PM

#1 SMASH  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 34
  • Joined: 01-May 09

Conceptual Physics with an Environment like XNA

Posted 08 January 2011 - 07:37 PM

Hey so I am working on a top down car game and I realized that as much as I understand physics algebraically, programming it is a totally different story...

So where I am right now is that I have the car able to move around using the whole x += v + .5(Accel)time^2. Yeah it works but I have to feed a time into it and it's a huge pain in the ass to manipulate and is probably horribly inaccurate (though accuracy isn't what I'm REALLY looking for). Anyways, I saw a way to do it with forces where:

A = F / M
V += A * T
P += V * T

and adjusting the force on the car affects everything else... but I still have to feed in a time... I am SO confused on how to actually do this in a programming environment...

Is This A Good Question/Topic? 0
  • +

Replies To: Conceptual Physics with an Environment like XNA

#2 Kilorn  Icon User is offline

  • XNArchitect
  • member icon



Reputation: 1356
  • View blog
  • Posts: 3,528
  • Joined: 03-May 10

Re: Conceptual Physics with an Environment like XNA

Posted 08 January 2011 - 08:09 PM

Well, we can start out simple on this. The first line in your example, assuming I'm reading them properly, is Acceleration = Force / Mass. So that tells us already that we need 3 values to represent each of these.
float acceleration;
float force;
float mass;



I've decided to use floats here just to make the math a little simpler since we will be dealing with decimal points inevitably. We will obviously need a method for determining the force that is applied to the object that we will be moving. In this case, it's a car. The mass of a car isn't really going to change, unless you're planning on having realistic damage where parts of the car will actually fly off, but to keep things simple, we're going to go with a constant mass for the car. In this instance, I'm just going to create an arbitrary number to use. I'm going to say the mass of the car is 10.
float acceleration;
float force;
float mass = 10f;



Using the formulas that you've already laid out, we can start to plug in some values to those formulas. Let's just say for now that the force is 20. This give us the values we need in order to calculate the acceleration.
float acceleration;
float force = 20f;
float mass = 10f;
...
// Inside your code where you will actually calculate these values...
acceleration = force / mass;



Now that we have the value for the acceleration, we can move to the next formula that you posted. Velocity += acceleration * time. XNA already has a great way of keeping track of time down to the milliseconds. The GameTime class is used to keep track of time that has passed. So we have our acceleration, and a way of keeping track of the time, so let's take a look at it in code:
// We'll obviously need another value to keep track of the velocity of the object.
float velocity;

// And a variable for keeping track of the time. There are better ways of keep track of the time    // that has passed, but I'm just going to go ahead and do it this way for simplicity.
float time;

// For now, I'm going to place this line in the Update method just to keep track of the time
time += gameTime.ElapsedGameTime.Milliseconds;

// In your code where you calculate all of these values...
velocity += acceleration * time;



Now that we've determined our velocity, we can calculate the change in the object position based on the velocity applied to the object over a period of time, or as your formula dictates, Position += velocity * time. Since you're doing a top down racing game, I'm assuming your world is 2d, we just need to apply some vector math to your object to change the position in the right way according to the velocity. This post has gotten a little long, so I'm going to end it here for now. Let's keep this going, though. Try some things out and let me know how it goes and we'll work through it.

This post has been edited by Kilorn: 08 January 2011 - 08:17 PM

Was This Post Helpful? 1
  • +
  • -

#3 SMASH  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 34
  • Joined: 01-May 09

Re: Conceptual Physics with an Environment like XNA

Posted 08 January 2011 - 08:53 PM

Don't the velocity, acceleration, and force all need to be vector2? I'm sorry if I didn't clarify but it's a top down remote control car type game. The whole concept of the game is to hit the other players on the side to do damage as hitting them head on won't do damage.
Was This Post Helpful? 0
  • +
  • -

#4 Kilorn  Icon User is offline

  • XNArchitect
  • member icon



Reputation: 1356
  • View blog
  • Posts: 3,528
  • Joined: 03-May 10

Re: Conceptual Physics with an Environment like XNA

Posted 08 January 2011 - 09:18 PM

Yea, I could see using Vector2's for all of those variables in order to make things a little simpler.
Was This Post Helpful? 0
  • +
  • -

#5 SMASH  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 34
  • Joined: 01-May 09

Re: Conceptual Physics with an Environment like XNA

Posted 08 January 2011 - 09:18 PM

As well I assume you have to make an object (gameTime) of GameTime. I don't know what to initialize it to though... I'm getting a null reference error from the "time += gameTime.ElapsedGameTime.Milliseconds;" code...
Was This Post Helpful? 0
  • +
  • -

#6 Kilorn  Icon User is offline

  • XNArchitect
  • member icon



Reputation: 1356
  • View blog
  • Posts: 3,528
  • Joined: 03-May 10

Re: Conceptual Physics with an Environment like XNA

Posted 08 January 2011 - 10:27 PM

In the method that you're using that line of code, is there already a GameTime object instance? If not, then you might need to declare one. I just tested all of the code that I posted in my earlier post and I can run it without errors. In my code, I put time += gameTime.ElapsedGameTime.Milliseconds; in the Update method of the Game1 class.
Was This Post Helpful? 0
  • +
  • -

#7 SMASH  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 34
  • Joined: 01-May 09

Re: Conceptual Physics with an Environment like XNA

Posted 09 January 2011 - 02:05 PM

Ok so I've been hard at work taking the ideas you've given me, Kilorn, and putting them into use and I'm fairly happy with the way that it's turning out, even if it has less features than I had before, but I think this is more realistic and will allow for better automation, plus I've condensed the amount of code in the main game class (that will be transfered to a level class when I create it) down to just one call to update the car and just passing in a KeyboardState and time. Here's my car class:


using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;


namespace BattleBumperCars
{
    class Car
    {
        protected Vector2 position;         //Overall position of the car

        protected float dragForce;          //Drag force on the car (effects how long it takes the car to stop after accelerating)
        protected float engineForce;        //Force generated by the engine
        protected float normalForce;        //Force that will cause car to drift
        protected Vector2 netForce;         //NetForce Vector (takes the rest of the forces + rotation into it)

        protected Vector2 acceleration;
        protected Vector2 velocity;
        protected float time;
        
        protected float rotation;           //Ovarall rotation of the car
        protected float wheelRotation;      //Rotation of the front wheels in comparison to the body of the car     
        protected float direction;          //Rotation of the front wheels in the world

        protected KeyboardState prevKeyState;

        protected int mass;                 //Mass of the car, will factor into collisions
        protected Texture2D carTexture;
        protected CarRectangle carRect;


        private Random random = new Random();

        public Car(int m, Texture2D carTex, Texture2D wheelTex)
        {
            time = 0;
            position = new Vector2(0);
            velocity = new Vector2(0);
            acceleration = new Vector2(0);

            netForce = new Vector2(0);
            dragForce = 0.5f;
            engineForce = 3.0f;

            rotation = 0.0f;
            wheelRotation = 0.0f;
            
            mass = m;
            carTexture = carTex;
            carRect = new CarRectangle(position, carTexture.Width, carTexture.Height, rotation);
        }

        public Vector2 Position
        {
            get
            {
                return position;
            }
        }
        public double WheelRotation
        {
            get
            {
                return wheelRotation;
            }
            set
            {
                wheelRotation = MathHelper.ToRadians((float)value);
                MathHelper.Clamp((float)wheelRotation, MathHelper.ToRadians(-15.0f), MathHelper.ToRadians(15.0f)); //Clamps the wheel rotation
                direction = rotation + wheelRotation;
            }
        }
        public Vector2 Velocity
        {
            get
            {
                return velocity;
            }
        }
        
        public void setNew()
        {
            position = new Vector2(random.Next(50, 974), random.Next(50, 462));
            rotation = MathHelper.ToRadians(random.Next(0,360));
            velocity = new Vector2(0, 0);
            acceleration = new Vector2(0, 0);
            netForce = new Vector2(0, 0);
            

            wheelRotation = 0;
            direction = rotation + wheelRotation;
            carRect = new CarRectangle(new Vector2(position.X - carTexture.Width / 2, position.Y + carTexture.Height / 2), carTexture.Height, carTexture.Width, rotation);
        }

        public void update(KeyboardState ks, float time_step)
        {
            if(ks.IsKeyDown(Keys.Up))
            {
                time += time_step;

                netForce = new Vector2((engineForce - dragForce) * (float)Math.Cos(direction), (engineForce - dragForce) * (float)Math.Sin(direction));
                acceleration = netForce / mass;
                velocity += acceleration * time;
                position += velocity;
            }

            if (ks.IsKeyUp(Keys.Up) && ks.IsKeyUp(Keys.Down))
            {

                if (Math.Sqrt(Math.Pow(velocity.X,2) + Math.Pow(velocity.Y,2)) > 0)
                {
                    time += time_step;

                    netForce = new Vector2(-dragForce * (float)Math.Cos(direction), -dragForce * (float)Math.Sin(direction));
                    acceleration = netForce / mass;
                    velocity += acceleration * time;
                    position += velocity;
                }
                else
                {
                    time = 0;
                }
            }

        }
         
        public bool checkCollision(Car car)
        {
            return carRect.Intersects(car.carRect);
        }
        public void draw(SpriteBatch sb)
        {
            sb.Draw(carTexture, position, null, Color.White, (float)rotation, new Vector2(carTexture.Width / 2, carTexture.Height / 2), 1.0f, SpriteEffects.None, 0.0f);
        }

    }
}




What it does right now is it's able to move forward but when the button is released and the secondary function kicks in to let it roll with only the dragForce working on it, it does slow down, but it also shoots backwards. I need it to just stop rolling, hence the if the magnitude of velocity is > 0, yet somethings wrong...
Was This Post Helpful? 0
  • +
  • -

#8 SMASH  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 34
  • Joined: 01-May 09

Re: Conceptual Physics with an Environment like XNA

Posted 09 January 2011 - 03:47 PM

oh wow, I just realized that I'm taking a SQRT so it'll always be positive >.<. Oh crap, well I guess the question still stands... how do I fix this to tell if it's begun to move backwards so I can reset my time variable so it won't shoot backwards but will rather decelerate to a stop.
Was This Post Helpful? 0
  • +
  • -

#9 Kilorn  Icon User is offline

  • XNArchitect
  • member icon



Reputation: 1356
  • View blog
  • Posts: 3,528
  • Joined: 03-May 10

Re: Conceptual Physics with an Environment like XNA

Posted 09 January 2011 - 03:52 PM

Off the top of my head, without digging into the code too much, I'd think it might have something to do with the math you're doing on netForce using the sine and cosine of direction. You'll need to convert direction to radians in order to use Math.Sin() and Math.Cos(). To convert to radians, just multiply the variable by Math.Pi/180. Give that a shot and we'll go from there.
Was This Post Helpful? 0
  • +
  • -

#10 SMASH  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 34
  • Joined: 01-May 09

Re: Conceptual Physics with an Environment like XNA

Posted 09 January 2011 - 04:21 PM

View PostKilorn, on 09 January 2011 - 02:52 PM, said:

Off the top of my head, without digging into the code too much, I'd think it might have something to do with the math you're doing on netForce using the sine and cosine of direction. You'll need to convert direction to radians in order to use Math.Sin() and Math.Cos(). To convert to radians, just multiply the variable by Math.Pi/180. Give that a shot and we'll go from there.


Direction is a radian. If you look at the direction function that gets and sets it, it's all converted to radians instantly. The problem is figuring out when the car has come to a stop so that the drag force doesn't force it into reverse. I think I'm gonna just have to create a temp variable of the velocity Vector2 and if X is negative, then when it goes positive is when I stop it and vice versa and do the same for the Y component. Though that just isn't very sexy coding... I wish there was an equation but the SQRT decides to kick me in the balls lol.
Was This Post Helpful? 0
  • +
  • -

#11 Kilorn  Icon User is offline

  • XNArchitect
  • member icon



Reputation: 1356
  • View blog
  • Posts: 3,528
  • Joined: 03-May 10

Re: Conceptual Physics with an Environment like XNA

Posted 11 January 2011 - 12:06 PM

So how's it going with this, SMASH, did you ever figure out what was causing the car to move backwards?
Was This Post Helpful? 0
  • +
  • -

#12 lesPaul456  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 173
  • View blog
  • Posts: 729
  • Joined: 16-April 09

Re: Conceptual Physics with an Environment like XNA

Posted 11 January 2011 - 02:57 PM

Here's how I like to handle velocity and acceleration with drag. Maybe it will help give you some ideas...

// NOTE: Position, Velocity and Acceleration are all Vector2 instances. Drag is a float.

float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
float deltaTimeSquaredDividedByTwo = (deltaTime * deltaTime) / 2;

Position.X += (Velocity.X * deltaTime) + (Acceleration.X * deltaTimeSquaredDividedByTwo);
Position.Y += (Velocity.Y * deltaTime) + (Acceleration.Y * deltaTimeSquaredDividedByTwo);

Velocity.X += Acceleration.X * deltaTime;
Velocity.Y += Acceleration.Y * deltaTime;

Velocity.X -= (Velocity.X * Drag) * deltaTime;
Velocity.Y -= (Velocity.Y * Drag) * deltaTime;


Was This Post Helpful? 0
  • +
  • -

#13 SMASH  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 34
  • Joined: 01-May 09

Re: Conceptual Physics with an Environment like XNA

Posted 11 January 2011 - 09:50 PM

Sorry guys I was out snowboarding all day... I enjoy the thought that you guys give me though, it pushes me to fight the tiredness and keep working, though right now I'm not thinking of any solutions...

And lesPaul I'd really have to see implementation to really understand how each part would work because when i pass my equations (float)gameTime.ElapsedGameTime.TotalSeconds, it is always constant, thus the car doesn't move at all. The GameTime classtype is pretty new to me so utilizing is a little beyond me right now.

I guess the problem is that I can't test to see if the car is moving backwards since backwards is relative to whichever way is forward... huhhhhh, sorry this is just me thinking outloud but would you think if I created a Vector2 the direction scalar and a temp velocity that is guaranteed to be "forward" and then normalized that Vector2 and the current velocity Vector2 and they should be equal unless the car's velocity has switched to be backwards right? Idk if the theory is even worth trying to implement... Anyways I'm off to bed, check back tomorrow before and after work lol.
Was This Post Helpful? 0
  • +
  • -

#14 lesPaul456  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 173
  • View blog
  • Posts: 729
  • Joined: 16-April 09

Re: Conceptual Physics with an Environment like XNA

Posted 12 January 2011 - 10:42 AM

The elapsed game time is the amount of time that has passed since the last frame, and should should remain pretty constant.

Here's an example to show how the code works:

Texture2D texture;

float drag = 0;

Vector2 pos = Vector2.Zero;
Vector2 vel = Vector2.Zero;
Vector2 accel = Vector2.Zero;

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    texture = Content.Load<Texture2D>("SomeImage");

    accel = new Vector2(0, 10);
    drag = 2;
}

protected override void Update(GameTime gameTime)
{
    float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
    float dtSD2 = (dt * dt) / 2;

    pos.X += (vel.X * dt) + (accel.X * dtSD2);
    pos.Y += (vel.Y * dt) + (accel.Y * dtSD2);

    vel.X += accel.X * dt;
    vel.Y += accel.Y * dt;

    vel.X -= (vel.X * drag) * dt;
    vel.Y -= (vel.Y * drag) * dt;

    base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();
    spriteBatch.Draw(texture, pos, Color.White);
    spriteBatch.End();

    base.Draw(gameTime);
}



The image will begin to accelerate, and then begin to slow down. Try switching the acceleration and drag values to get different effects.

This post has been edited by lesPaul456: 12 January 2011 - 10:43 AM

Was This Post Helpful? 2
  • +
  • -

#15 SMASH  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 34
  • Joined: 01-May 09

Re: Conceptual Physics with an Environment like XNA

Posted 13 January 2011 - 02:01 PM

Aight well I think I'm going to scrap this project... I got it working if it goes in a straight line but when it turns, all bets are off. Maybe I'll try something less physics intensive and actually finish it.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1