Testing if vectors are pointing in same direction

hey guys,

so you guessed it I'm still studying vectors and game physics, My goal now is to test if both vectors are pointing in the same direction, why? because I want to tell if both objects( red and black rectangles ) are moving in the same direction, but I think I'm doing something wrong,

To find if both vectors are pointing in the same direction I could use the dot product, but I think I know the problem just don't know how to solve it. The problem I suspect is that when the black rectangle hits the wall or bounds it should change direction, the rectangle does technically change direction but I'm pretty sure I'm not changing the vectors direction rather just decrementing the black rectangles x value.

I create two direction vectors one for the red rectangle and one for the black rectangle I then apply the cross product but no matter what they will be pointing in the same direction, so really it comes down to how do I change the black rectangles direction when it collides with the wall ( instead of just decrementing it's x value)

thanks!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <cmath>

using namespace std;

SDL_Renderer* renderer;
SDL_Window* window;
SDL_Texture* texture;
SDL_Surface* surface;
SDL_Event event;


class Vector2{

   public:
       double x;
       double y;

       Vector2(double x,double y): x(x),y(y){}
       Vector2(){x = 0;y = 0;}

       void add(Vector2& other){

          x += other.x;
          y += other.y;
       }

       void scale(double scalar){

          x*=scalar;
          y*=scalar;
       }

       double magnitude(){

         return sqrt( (x * x) +  (y * y) );
       }

       Vector2 normalize(){

           double mag = magnitude();
           return Vector2(x/mag,y/mag);
       }

       int dotProduct(Vector2& other){

          cout << " x * other.x == " << x << " * " << other.x << " == " << x * other.x << endl;
          cout << " y * other.y == " << y << " * " << other.y << " == " << y * other.y << endl;
          cout << "(x * other.x) + (y * other.y) == " << (x * other.x) + (y * other.y) << endl;
          return (x * other.x) + (y * other.y);
       }

};

Vector2 subtractVectors(const Vector2& one,const Vector2& two){

   Vector2 difference;
   double x = -(two.x);
   double y = -(two.y);
   difference.x = one.x + x;
   difference.y = one.y + y;
   return difference;
}


class BlackRect{

  public:
      bool objectLeft = false;
      bool objectRight = true;
      Vector2 vec;
      SDL_Rect spriteOneRect;
      SDL_Surface* spriteOneSurface;
      SDL_Texture* spriteOneTexture;


      BlackRect(int x,int y,string fileName){

         vec.x = x;
         vec.y = y;
         spriteOneSurface = IMG_Load(fileName.c_str());
         spriteOneTexture = SDL_CreateTextureFromSurface(renderer,spriteOneSurface);
         spriteOneRect.x = x;
         spriteOneRect.y = y;
         SDL_QueryTexture(spriteOneTexture,NULL,NULL,&spriteOneRect.w,&spriteOneRect.h);
      }
      BlackRect(){

        vec.x = 250;
        vec.y = 250;
      }

      void update(){

        spriteOneRect.x = vec.x;
        spriteOneRect.y = vec.y;
      }

};


void render(BlackRect& br,BlackRect& rr){

    SDL_RenderClear(renderer);
    SDL_SetRenderDrawColor(renderer,255,255,255,255);
    SDL_RenderCopy(renderer,br.spriteOneTexture,NULL,&br.spriteOneRect);
    SDL_RenderCopy(renderer,rr.spriteOneTexture,NULL,&rr.spriteOneRect);
    SDL_RenderPresent(renderer);
}

bool collisionBounds(SDL_Rect &rect){

  if(rect.y <= 0)
    return true;
  if(rect.y + rect.h >= 600)
    return true;
  if(rect.x <= 0)
    return true;
  if(rect.x + rect.w >= 800)
    return true;

  return false;
}

void moveObject(BlackRect& rect,Vector2& velocity){

   if(collisionBounds(rect.spriteOneRect)){

       if(rect.objectRight){

          rect.objectRight = false;
          rect.objectLeft = true;
       }else{
         rect.objectLeft = false;
         rect.objectRight = true;
       }
   }

   if(rect.objectRight)
    rect.vec.x += velocity.x;

   if(rect.objectLeft)
    rect.vec.x -= velocity.x;

    rect.update();
}


int SDL_main(int argc,char* argv[]){

   init();
   bool quit = false;
   BlackRect br(20,400,"blockone.png");
   BlackRect rr(400,200,"blockoneRed.png");
   Vector2 brVelocity(4,0);


    while(true)
    {
        while(SDL_PollEvent(&event))
        {
            if(event.type == SDL_QUIT)
            {
                cleanUp();
                return 0;
            }

            if(event.type == SDL_KEYDOWN)
            {

                int key = event.key.keysym.sym;
                if(key == SDLK_b)
                    moveObject(br,brVelocity);
                
            }

        }

        Vector2 direc = br.vec.normalize();
        Vector2 direc2 = rr.vec.normalize();
        direc.scale(10);
        direc2.scale(10);
        int directions = direc.dotProduct(direc2);
        cout << "directions == " << directions << endl;
        if(directions > 0)
            cout << "same direction" << endl;
        else if(directions < 0)
            cout << "opposite directions" << endl;
        else
            cout << "perpendicular " << endl;

        render(br,rr);
        SDL_Delay(20); 
}

Last edited on
If they are going in the same direction, then they have the same (within floating point roundoff) direction. Just compute direction 1 and 2 and compare (abs(1-2) > 0.0000001).
there are a bunch of ways you can get there, so whatever math you understand. Depending on what you want to know this for it may be helpful to know if they are in the same general direction, not just exact...

a perfect bounce off something is going to rebound current direction +- pi (either works).
note that this will change the signs and cause you to go in the opposite direction as before when adding your delta positions.
Last edited on
To test for direction with the same sense only (as opposed to direction and magnitude) compute a unit vector (length 1.0) with your normalize function and compare within floating point round off as jonnin explained. You could create an operator== to help with this.

I would not have named the class BlackRect the colour is just an attribute or property of a rectangle and shouldn't be in the name of the class unless black rectangles have different behaviour to other rectangles.

This code does not at all do what the first 2 cout statements say:

188
189
190
191
192
193
if(directions > 0)
            cout << "same direction" << endl;
        else if(directions < 0)
            cout << "opposite directions" << endl;
        else
            cout << "perpendicular " << endl;


Recall that a dot product of a, b = |a| * |b| * cos(angle between the 2 vectors). Unless you want an angle of +/- 89.999... degrees say to mean the same direction.

The other problem with that code is it would be fairly unlikely the else statement is encountered because of the way floating point works. If directions was 2e-16, the else statement would not happen: that is rather impractical in my mind.
2 vectors V1<x1,y1> and V2<x2,y2> are pointing in the same direction when
y1/x1 = y2/x2 ( = -y2/x2 when V1 and V2 are pointing in opposite directions.

(EDIT: In the interests of correct physics the 2nd part of this has been ‘colston-statued’ and obliterated from history)
Last edited on
Three ways of finding whether the two vectors are in the same direction:
(i) use dot product to determine an angle of 0 (or cosine of 1); i.e. ab/|a||b|=1 (to within floating-point tolerance; also make sure that neither are zero first)
(ii) determine that the normalised vectors a/|a| and b/|b| are the same (the L2 norm of their difference is within tolerance of zero)
(iii) show that their cross product is zero (to within floating-point tolerance) and their dot product is >= 0. The latter is to distinguish in the same direction from in the diametrically opposed direction.


After ideal oblique collision an initial velocity V0 becomes a reflected velocity
V0+2(V0n)n,
where n is a unit vector normal to the wall (in a sense opposing the onset velocity). It comes from restitution (with coefficient of restitution e=1), not conservation of momentum. The latter would require the wall to move.
Last edited on
The above answers are correct in the general case, where a vector is reflected off an arbitrary surface, but if you know the surface in question is parallel to an axis of the Cartesian coordinate system, all you need to do is flip the sign of the orthogonal axis (when in 2D).
So, when bouncing off a vertical wall, you flip the sign of the x component's sign, and when bouncing off a horizontal wall, you flip the y component's sign.
Topic archived. No new replies allowed.