Mathematical vectors

Hi everyone!

So here I am again requesting a bit of information and if possible some pseudo code to make me understand some vector theory. Before fixing up collision detection (just a few corrections to do to make it function properly), I was wondering if I could use vectors for the current 2d top down car game I’m working on.

The vectors would be used for my car class, but the problem is I don’t see how I would go along doing it. I do know basic vector math and reading up on it for a memory refresh wouldn’t be a problem. The problem is when I try to think about it conceptually. Basically I have my car - Friction would be a vector - and the motion itself would be a vector, but how would I go about calculating its new motion vector since I don’t have the destination coordinates? All I have is the acceleration which is being increased each update. To my knowledge the to add vectors I would need current car coordinates + destination coordinates?

If someone could just nudge me in the right direction I’m sure I will be able to figure it out, since when I think about it all I think I would need is vector addition. I think using vectors would give more depth to the application instead of using a simple scalar value such as currentSpeed.

Thanks!

You’re already using vectors, but you’re using two 1-D vectors rather than one 2-D vector.

Position: (x, y)
Speed: (vx, vy)
Acceleration: (ax, ay)

For a very simple quadrature mechanism:
(x, y) += (vx, vy) * dt
(vx, vy) += (ax, ay) * dt

There are, of course, better quadrature schemes. Which you use depends on the accuracy you want and the amount of computing power you have available. (I’ve used RK4 in one game, but that had a fairly complex physics model and I wanted the accuracy).

Hmm… I wrote this last night but never pressed Post.

Just use 2D vectors for anything that happens in two dimensional space. Friction is not a vector, it’s a single coefficient value (so one float), because it just applies against your current force, it has no direction.

Common 2D vectors I use for every entity:

  • position
  • velocity
  • size

Acceleration is a 2D vector but it is usually applied by something else, not by the entity itself (for example gravity is applied by World on every entity).

Things that are not vectors:

  • friction

Things that are 1D vectors (they have a length, but not a direction):

  • rotational velocity
  • rotation
  • speed (speed is one dimensional, so is not a vector. You will never have both velocity and speed in one object, though. I will typically have speed in things that always move at a rate towards whichever direction they’re facing)

I know what you mean, but…

Friction is a force, hence a vector. The Coefficient of Friction on the other hand is a scalar. Of course in most games friction just means “slowy-downy effect” so you can define it however you like. :wink:
Simon

And if the aim is to be realistic then you need two coefficients of friction - one linear and one quadratic. Then you need to overdamp the frictional system to avoid getting harmonic motion just due to friction.

I’ll start off by saying in all honesty I don’t know much of what you are talking about when you say 1D vector instead of 2D vector. (I’ll venture a guess and say its 1D because it doesn’t contain the full coordinate? I am probably totally off here) When I look at the equations I’m thinking they are 2d right? So that makes me think that x,y is a 2D vector because it has the full location? - If it is then I probably can go to 2D vectors pretty easily! :slight_smile:

I actually re-read what Eli said, and the difference between 1D and 2D vectors is just that 1D doesn’t have direction?

I’m trying to implement something as simple as velocity for example. But if I’m correct about what pjt33 said about them 2D vectors then implementing it shouldn’t be a problem!:). As far friction not being a vector, I was thinking the exact way dishmoth described it :slight_smile:

And for rotation not being a vector I’m not totally sure about that, since the way I think about it, is having the rotationAngle can give me the updated direction? and I would use rotational velocity for its magnitude? Or am I just confusing myself ???

WRT: 1D vectors. These are scalars. A 1D vector (if such a thing exists) would only exist in a one dimensional space. From a linear algebra standpoint a n-d vector is a (1xn) or (nx1) matrix. From a subspace standpoint they are 1-dimension subspace. Form a geometric standpoint they are a direction and a magnitude. So don’t anyone run off and try to understand 1D vectors.

As a complete aside vector analysis can be quite confusing. This is because the cross product of two vectors produces a bivector and not a vector.

Not exactly, although notation is often abused to identify the two.

Opps. What I intended to say is that the examples are scalars and not 1D vectors. Not that scalars are 1D vectors. Me bad.

hehe, math pedantry.

You can go into alot of detail about what-is-what. Vectors, scalars, pseudo-scalars, bivectors etc. are analogous to types in the math world. So a scalar and a pseudo-scalar can be written as a real number, but mean subtly different things. So some functions accept certain types, even though the number of reals are the same. For our purposes, the difference is how the value is interpreted in a geometric context.

Vectors are sometimes used just like arrays to collect math variables up (general use). In a geometric context a Euclidean vector denotes simultaneously a direction and a magnitude in a Euclidean vector space (what we are dealing with, ‘normal’ geometry).

[quote]And for rotation not being a vector I’m not totally sure about that, since the way I think about it, is having the rotationAngle can give me the updated direction? and I would use rotational velocity for its magnitude? Or am I just confusing myself
[/quote]
Rotation is the classic example of where the subtleties creep in (in a Euclidean vector space). So the angle between two vectors is a firm concept for a Euclidean vector space (in all dims), it always considered positive. The problem starts when you want a polarity attached. E.g. in 2D, what is the angle clockwise between vector A and B? The clockwise bit is an additional property of the vector space, which needs to be defined. So when you have angles against a global handedness of the space, your new signed angular quantity is something (subtly) different to the old one (even though both can be represented as reals). So the signed version is a pseudo scalar whereas the first is a plain scalar.

So rotation is not really a vector quantity, in 2D is a pseudo scalar. In 3D it has three components, but they are related in a weird way and have their own type SO(3). You can’t really call them vectors or psuedo vectors because they won’t go into any function that normally accepts vectors and compute anything that makes sense.

All of this is not that important to know. We all have our own internal heuristics when we want to practically apply coding in geometric space. Mine is “rotation is a pain in the butt”, and its the reason why we have to have the tan2 function in 2D (the quadrant aware version of tan), and quaternions in 3D. Whenever I find my rotation code is buggy or bloaty (like lots of ifs to determine an angle polarity), I start checking where I can use the tan2 function.

e.g. http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm

Humm. To me pedantry is more correctness for correctness sake. Are you suggesting that it isn’t both misleading and confusing to call values vectors when they are in fact scalars?

I am saying we can get bogged down in abstract math details which is not that important when implementing a car driving game. The difference between the types is nice to know, but doesn’t really help point you in the right practical direction (tan2 <- not a mathematicians invention or naming convention).

Yes, I meant the coefficient of friction.

Also I just said 1D vector because pjt33 had already used that terminology and I wanted to avoid being confusing by calling it a scalar or float. Just keeping things consistent. I think we’re getting way over deadly72’s head. :slight_smile:

Actually I quite understand that ;D, but what IS getting over my head is what t_larkworthy mentioned - I’m guessing its mostly abstract stuff, nothing in there that is too concrete. In addition I’m a bit confused as to what Roquen means when talking about pedantry - but I do understand the difference between vectors and scalars.

I am on the other hand trying to incorporate using a mathematical vector class in my top down car project, but all I would need is abit of clarification to see if I’m headed in the right way? For example this would just be my basic class.


public class Vector2D {
	private double x;
	private double y;
	
	public Vector2D(double x, double y) {
		this.x = x;
		this.y = y;
	}
	
	public static Vector2D add(Vector2D v1, Vector2D v2) {
		return new Vector2D(v1.x + v2.x, v1.y + v2.y);
	}
}

and from that we declare a Vector2D position inside the car class which would be (x,y). Then we apply the formulas


(x, y) += (vx, vy) * dt
(vx, vy) += (ax, ay) * dt

giving something like Vector2D newPosition = Vector2D.add(position, direction + ???) that is where I get lost actually. I’m using currentSpeed and it’s not a vector (scalar value). How do I split up currentSpeed to make it vx and vy? so i can multiply it with dt then add it to vector position.

that pjt33 was so kind enough to share :smiley:

The magnitude of a 2D vector is sqrt(x^2 + y^2), and you “encode” speed in the vector by setting the vector’s magnitude to the speed. When you scale a vector’s components by its length, you create a vector that is parallel to the original, but will have a length of 1. Then if you multiply both x and y with a scalar, s, this newest vector has a length equal to s.

Example:


public void setLength(double length) {
   double currentLength = Math.sqrt(x * x + y * y);
   x *= length / currentLength;
   y *= length / currentLength;
}

This updates a Vector2D to have the given length, which in the case of velocity is its speed. Besides looking at vector math, you’re beginning to get into Newtonian physics and how to approximate it on a computer. That’s why you have dt * velocity to get the change in position, and dt * acceleration to get the change in velocity.

You’ll be making enough additions scaled by the timestep that it’s worth having


	public static Vector2D add(Vector2D v1, Vector2D v2, double scale) {
		return new Vector2D(v1.x + v2.x * scale, v1.y + v2.y * scale);
	}

        public double magnitude() { return Math.sqrt(x*x + y*y); }

        public Vector2D scaleTo(double len) {
            double s = len / magnitude();
            return new Vector2D(x * s, y * s);
        }

Then the logic is something like


    Vector2D x = new Vector2D(startx, starty);
    Vector2D v = new Vector2D(0, 0);
    Vector2D a = new Vector2D(0, 0);

    while (!endOfLevel) {
        x = Vector2D.add(x, v, dt);
        v = Vector2D.add(v, a, dt);

        // Acceleration: if key down then we accelerate in the direction we're facing.
        // Keep it simple: facing in the direction of our speed
        if (keyDown(KEY_ACCELERATE)) a = v.scaleTo(ACCELERATION);
        else a = new Vector2D(0, 0);

        // Need to apply friction to limit speed. Keep it simple: linear scaling only.
        double speed = v.magnitude();
        Vector2D friction = v.scaleTo(-speed * COEFF_FRICTION); // negative because opposes motion
        a = Vector2D.add(a, friction);

        // Render: since we said we're facing in the direction of our speed, need to rotate sprite by atan2(v.y, v.x)
    }

That will get you something which works. It can be improved in many ways, but better to start simple and then complicate it than to start complicated and never get anything working.

Will crash (divide-by-zero) first time through because v is zero?

Not crash but NaN. Good point.

If it helps, I usually overload all my methods in my Vector2D classes to take either a Vector2D or a float.


public void scale(Vector2D otherVec)
{
    x *= otherVec.x;
    y *= otherVec.y;
}

public void scale(float scale)
{
    x *= scale;
    y *= scale;
}

My vector class actually has kind of a ridiculous number of functions. But once you write all of them you can then reuse them in every project from now on.

Another helpful thing can be to return the Vector that was modified. This allows you to chain functions like this: “v.add(1.0,0.0).normalize();”.