3
\$\begingroup\$

I'm really curious about why a lot of people and game engines use Vector2 as its coordinate system instead of the traditional x and y value.

Is there any benefit to this?

I feel like it's just slow me down and barely has any benefit other than organizing your code.

\$\endgroup\$
  • 11
    \$\begingroup\$ In what way has it slowed you down? Out of curiosity. \$\endgroup\$ – Aethenosity May 25 '18 at 15:07
  • 30
    \$\begingroup\$ Honestly, anything that has "barely any benefit other than organizing your code" already seems immensely useful to me. \$\endgroup\$ – Nax May 25 '18 at 15:38
  • 21
    \$\begingroup\$ On the other hand, writing Object.pos += Object.mov; is significantly faster and easier than Object.x += Object.movX; Object.y += Object.movY; \$\endgroup\$ – Nolonar May 25 '18 at 17:16
  • 6
    \$\begingroup\$ Nothing prevents you from writing an inline function that takes separate parameters for convenience constructing the two Vector2 for you. But from experience in practice you actually save time using Vector2 once your system gets complex like managing relative objects: render_pos = object->pos; object = object->parent; while(object) { render_pos += object->pos; object=object->parent; } Saves you a lot of writing on the long run. \$\endgroup\$ – Stephane Hockenhull May 25 '18 at 18:04
  • 10
    \$\begingroup\$ If typing has any significant contribution to "things that slow you down," then either you're not spending enough time reasoning about your code or your problems are beyond trivial. The things that slow you down in real world problems are working out the logic and tracking down the causes of errors/bugs that don't have a useful message. In those things, good organization is golden. \$\endgroup\$ – jpmc26 May 26 '18 at 0:47
40
\$\begingroup\$

First of all, it's way less clutter. If you have a position, a velocity and an acceleration, that's already 6 variables you have to deal with, 9 in 3d.

Secondly, and this is the most important part, it grants you access to many ways to use or change them. For instance, getting the length of the vector, normalizing it, adding them together, dot product, cross product in 3d, etc. It's possible to do this using separate variables too, but it's much easier using vectors and follows the DRY principle much better.

As for slowing you down, I'm not sure why this would do that. Apart from having to create a new Vector instead of just 2 variables, you only have to pay attention to using vector.x and vector.y, which shouldn't be that hard and isn't much worse, than vectorX and vectorY

\$\endgroup\$
  • 1
    \$\begingroup\$ In languages which support transparent structure types, a structure declaration can generally be processed at the machine level in a way that's at least as efficient as two separate int or float declarations. In languages that don't support such types, however, encapsulating pairs of numbers in class objects will impose a cost that might have been avoided by handling the numbers separately. \$\endgroup\$ – supercat May 25 '18 at 15:17
  • 11
    \$\begingroup\$ @supercat on the other hand many computers can do vector arithmetics, which speed up the calculations 2, 3 or even 4 fold depending on the amount of coordinates \$\endgroup\$ – Bálint May 25 '18 at 17:07
  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. \$\endgroup\$ – Alexandre Vaillancourt Jun 6 '18 at 17:41
15
\$\begingroup\$

Compare the function signatures of both RotatePoints versions.

Lone variables:

void RotatePoints(
   float *out_x, 
   int x_interleave_out,
   const float *in_x, 
   int x_interleave_in,
   float *out_y, 
   int y_interleave_out, 
   const float *in_y, 
   int y_interleave_in,
   float angle, 
   int count
) 
{
  float s = sinf(angle);
  float c = cosf(angle);

  while(count--){
    *out_x = *in_x * c + *in_y * -s;
    *out_y = *in_x * s + *in_y * c;
    out_x += x_interleave_out;
    out_y += y_interleave_out;
    in_x += x_interleave_in;
    in_x += y_interleave_in;
  }
}

Compared to using structures/classes:

void RotatePoints(
  Vector2 *out, 
  const Vector2 *in, 
  float angle, 
  int count)
{
   Matrix2x2 rotation;
   rotation.SetRotation(angle);

   while(count--){
     *out++ = *in++ * rotation;
   }
}

You need to tell the first version if your x and y arrays are interleaved or separate:

float all_together[200]; // x0,y0,x1,y1,x2,y2...

Or:

float x[100];
float y[100];

It's a lot less messy to just have a Vector2 array and pass that and the inner code is more readable too.

And the more complex the math the messier and hairier it gets if you're not using Vector and Matrix classes;

\$\endgroup\$
  • 3
    \$\begingroup\$ This code seems a little more advanced than the skill level of the question. You're even bringing pointers into this and are using... 8(?) params for something which is supposed to be the same as 2 Vector2s? \$\endgroup\$ – Raphael Schmitz May 25 '18 at 18:01
  • 13
    \$\begingroup\$ Because it hits you only once you hit advanced problems. Using separate variable is short-term simpler. But when you hit advanced topics that's where it becomes unmaintainable. \$\endgroup\$ – Stephane Hockenhull May 25 '18 at 18:07
  • 1
    \$\begingroup\$ Oh yeah that's exactly the gist of my answer, but I feel like you don't have to go that advanced to demonstrate that. I mean, I have 7 years of programming experience, but only very little with C/C++ and I don't understand what's going on here. OP was talking about ints x and y vs Vector2, but I have no idea which is the real x and y in your first example. \$\endgroup\$ – Raphael Schmitz May 25 '18 at 18:16
  • 1
    \$\begingroup\$ @R.Schmitz Plus, he may not know c at all. E.g. in Unity, you're not programming with c/c++, you just work with references (Hope that was the point of them in this code :D). The loop structure maybe not that understandable for a programer, that doesn't know c, too. (As an example) \$\endgroup\$ – SomeWindowsUser May 27 '18 at 15:22
11
\$\begingroup\$

Readability > Writeability

I feel like it's just slow me down and barely has any benefit other than organizing your code.

You are correct in that it (slightly) slows you down writing that code. However, you write it once in the beginning and from then on everytime you come back you are going to read it. So optimizing the reading speed will do much more good that optimizing the writing speed.

Naming things

Now, you might have difficulties seeing how draw_rect(Vector2(x, y), Vector2(width, height)) is supposed to be more readable than draw_rect(x, y, width, height), but to be honest, they both aren't as readable as they could be.

Look at this pseudocode:

position = Vector2(x, y)
size = Vector2(width, height)
draw_rect(position, size)

Yes, this takes 2 lines more and in the beginning I also thought that was bad. It isn't though. Giving things names makes this take less brain power to read, which you will be very thankful for as soon as the program gets more complex. Especially when you're debugging it. Naming things well will also improve other things and make you faster in the long run.

The still very short, but slightly longer run

You mentioned Object.x += 1 vs Object.pos += Vector2(1, 0) Again you're right, your way is faster for this (a single line). But let's just look at a minimally more complex class, you can have:

position;
velocity;

void UpdatePosition(){
    position += velocity;
}

Compare with:

xPosition;
yPosition;
xVelocity;
yVelocity;


void UpdatePosition(){
    xPosition += xVelocity;
    yPosition += xVelocity;
}

That is faster to read and to write. By the way, with such a small example it's not suuuper hidden, but did you notice the typo in the second version? That's easy to overlook, especially if the class is more complex than this unrealistically small example (There's a theme here...). It's one bug that can't happen when using Vector2.

IDEs

you cant shorten it by using something like Vec2 = Vector2

You might be working on a school assignment where you aren't allowed to use an IDE. If you don't, use one and look up the autocomplete shortcut (most of the time it's Ctrl+Space).

Then you can write "Vec" and use that shortcut and the IDE will show you a list of all classes that start with "Vec". I don't think any professional coder works without this, because this is so much faster. The alternative is to learn every class by heart, with correct typing down to the single character. Ain't nobody got time for that, especially in the business world where time is money.

\$\endgroup\$
  • \$\begingroup\$ I believe there is a typo in your "update position" method. It should be yPosition += yVelocity right? Rather than yPosition += xVelocity? \$\endgroup\$ – Aethenosity May 25 '18 at 23:26
  • 2
    \$\begingroup\$ "You are correct in that it (slightly) slows you down writing that code." This is patently untrue in any application where things move in more than one direction. Writing code that transforms a coordinate or vector in multiple dimensions would be vastly harder to write. \$\endgroup\$ – jpmc26 May 26 '18 at 0:44
  • \$\begingroup\$ And if you can't use autocomplete then don't call your vector type Vector2 to start with, call it vec2, or just vec if you have a primarily 2D game. \$\endgroup\$ – immibis May 28 '18 at 0:07
  • 1
    \$\begingroup\$ @Aethenosity Exactly, something like that can happen easily while typing or copy-pasting, especially if you're keeping other things in mind while doing that. \$\endgroup\$ – Raphael Schmitz May 28 '18 at 8:41
  • 2
    \$\begingroup\$ @NicHartley Because you lose the context a Vector2 gives you. Even if only one value changes I'd still prefer Vector2 oneStepRight = Vector2(1,0). A Vector2 just... feels right, that is a movement (or size, velocity etc) in 2-dimensional space. As a result, when I want to concentrate on game mechanics, I don't have to care about floats or doubles or ints or the amount of dimensions, I just have to do position += oneStepRight. \$\endgroup\$ – Raphael Schmitz May 28 '18 at 11:14
8
\$\begingroup\$

Operator overloading.

Vector v3 = v2 + v1;

There is now only one place in your code where you have to write, test and debug vector addition, as opposed to tens, hundreds or thousands.

Obviously vector addition is an overly simplistic example, but there are more complex vector operations and the same applies to those too.

\$\endgroup\$
2
\$\begingroup\$

Using structures & classes in place of a pile of primitive variables allows us to focus more of our attention on the higher levels of problem solving.

As taken from Code Complete:

Reduce Complexity - A primary goal of software design and construction is conquering complexity. The motivation behind many programming practices is to reduce a program’s complexity, and reducing complexity is arguably the most important key to being an effective programmer.

Program in Terms of the Problem Domain - Another specific method of dealing with complexity is to work at the highest possible level of abstraction. One way of working at a high level of abstraction is to work in terms of the programming problem rather than the computer science solution.

Using a vector class / struct plays to both these points.

\$\endgroup\$
1
\$\begingroup\$

The same reasons that primitive obsession is a code smell apply to using a vector instead of separate variables. Vector2D/3D is just a special case of avoiding primitives.

\$\endgroup\$
1
\$\begingroup\$

Mathematically a vector is a point in a vector space. That's something with real physical relevance – the space we live in is basically a vector space.

The individual components x and y are not. They depend on a choice of coordinate frame, and generally there is no clear reason why some particular coordinate frame should be used. It's an implementation detail, so it's best encapsulated in an opaque type. Indeed, you'll mostly access individual components in very simple applications like 2D platformers, but in anything with somewhat serious physics handling you'll much more typically have offsets pointing in some direction that's unrelated to the coordinate axes. Doing that with coordinates would always require basically duplicating each calculation.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.