[SDL] line not drawing to screen properly

Hi Guys,

I seem to be having a problem when trying to draw a line to the screen, so the line should be from the centre of the screen pointing in the direction of the mouse's position, when I don't normalise the vectors, and just use the mousePos.x,y values and centerPos.x,y values the line gets successfully drawn to the screen,

but by normalising the difference vector I should get a line just pointing in the direction of the mouse, I scale this number to make sure the line is clearly visible,

but something seems to be off, in theory this should work, I even printed the x and y values for debugging and they look ok to me, but the line is not being drawn in the direction of where the mouse is positioned

here is a video of what is exactly happening - https://www.youtube.com/watch?v=Ub6gkQW55FU&feature=youtu.be

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
  #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;
const int WIDTH = 800;
const int HEIGHT = 600;

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){

          return (x * other.x) + (y * other.y);
       }

       friend Vector2 subtractVectors(const Vector2& one,const Vector2& two);

       bool limit(Vector2& position,double magSize){

         Vector2 futurePosition(0,0);
         futurePosition.x = position.x;
         futurePosition.y = position.y;
         futurePosition.add(*this);
         Vector2 distanceVector = subtractVectors(futurePosition,position);

         double mag = distanceVector.magnitude();
         cout << "mag == " << mag << endl;

         if(mag < magSize)
            return false;
         else
            return true;
       }
};

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 Rect{

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


      Rect(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(){

    int mouseX;
    int mouseY;
    SDL_GetMouseState(&mouseX,&mouseY);

    Vector2 centerPos(WIDTH/2,HEIGHT/2);
    Vector2 mousePos(mouseX,mouseY);
    Vector2 difference = subtractVectors(mousePos,centerPos);
    Vector2 normalised = difference.normalize();
    cout << normalised.magnitude() << endl;
    normalised.scale(10);
    cout << normalised.x << " :: " << normalised.y << endl;

    SDL_RenderClear(renderer);
    SDL_SetRenderDrawColor(renderer,0,0,0,255);
    SDL_RenderDrawLine(renderer,centerPos.x,centerPos.y,normalised.x,normalised.y);
    SDL_SetRenderDrawColor(renderer,255,255,255,255);
    SDL_RenderPresent(renderer);
}


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

   init();
   bool quit = false;

   while(!quit){

      SDL_PollEvent(&event);

      if(event.type == SDL_QUIT)
        break;

      render();
      SDL_Delay(2);

   }
}
Last edited on
SDL_RenderDrawLine() accepts only screen coordinates, but normalized is relative to centerPos. You need to add centerPos to normalized to convert it back to screen coordinates.
That's what I was thinking but to no avail,

I tried the following, the line just gets stuck in one direction no matter where I move my mouse to,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    int mouseX;
    int mouseY;
    SDL_GetMouseState(&mouseX,&mouseY);

    Vector2 centerPos(WIDTH/2,HEIGHT/2);
    Vector2 mousePos(mouseX,mouseY);
    Vector2 difference = subtractVectors(mousePos,centerPos);
    Vector2 normalised = difference.normalize();
    Vector2 added(0,0);
    added.x = centerPos.x;
    added.y = centerPos.y;
    added.add(normalised);
    added.scale(1.25);


    SDL_RenderClear(renderer);
    SDL_SetRenderDrawColor(renderer,0,0,0,255);
    SDL_RenderDrawLine(renderer,centerPos.x,centerPos.y,added.x,added.y);
    SDL_SetRenderDrawColor(renderer,255,255,255,255);
    SDL_RenderPresent(renderer);

You're scaling the vector in screen coordinates. You need to scale the vector relative to centerPos.

This:
finalPosition = centerPos + scale * (mousePos - centerPos);

Not this:
finalPosition = scale * (centerPos + mousePos - centerPos);

Implement operator overloading for Vector2. No one wants to read vector operations in function call format.
wow thanks Helios that worked :), here is what I was doing, but I'm still not sure why it's wrong and why the order matters in this case,

ok so below is the working code, here I did scale * (mousePos - centerPos) then added it to centerPos

1
2
3
4
5
6
7
8
9
10
11
12
13
14
   
    int mouseX;
    int mouseY;
    SDL_GetMouseState(&mouseX,&mouseY);

    Vector2 centerPos(WIDTH/2,HEIGHT/2);
    Vector2 mousePos(mouseX,mouseY);
    Vector2 difference = subtractVectors(mousePos,centerPos);
    Vector2 normalised = difference.normalize();
    normalised.scale(20);
    Vector2 added(0,0);
    added.x = centerPos.x;
    added.y = centerPos.y;
    added.add(normalised);


but below I did centerPos + ( mousePos - centerPos), and then I scaled it, why was this order so important? ( how does this first example scale it relative to centerPos ? )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

    int mouseX;
    int mouseY;
    SDL_GetMouseState(&mouseX,&mouseY);

    Vector2 centerPos(WIDTH/2,HEIGHT/2);
    Vector2 mousePos(mouseX,mouseY);
    Vector2 difference = subtractVectors(mousePos,centerPos);
    Vector2 normalised = difference.normalize();
    Vector2 added(0,0);
    added.x = centerPos.x;
    added.y = centerPos.y;
    added.add(normalised);
    added.scale(1.25);


and yes a Vector2d is the perfect candidate for operator overloading but I'm just trying to get to grips with vector positioning first.
Last edited on
how does this first example scale it relative to centerPos ?
Because both centerPos and mousePos are in the same coordinate system (the screen's). Therefore (mousePos - centerPos) is relative to centerPos, and so is normalized(mousePos - centerPos), and also k * normalized(mousePos - centerPos), for any real k. To bring the vector back to screen coordinates, you add it to a vector in screen coordinates, thus centerPos + k * normalized(mousePos - centerPos).

Try and predict what happens when you do this:
(100, 100) + k * normalized(mousePos - centerPos)
or this:
centerPos + k * normalized(mousePos - (100, 100))
See if your prediction matches the actual result.
that makes sense, so what I was doing was just multiplying the x and y coordinates of the position instead of actually scaling the vector itself.

1: (100, 100) + k * normalized(mousePos - centerPos)

so here we get the difference vector and we normalise it, we then scale it by k, and add 100 to both the x and y axis,

2: centerPos + k * normalized(mousePos - (100, 100))

we subtract mousePos from the vector/pos 100,100, then normalise that new vector/pos, then scale it by k and add centerPos to it,

I didn't ask you to rephrase the formulas in English. I'm asking what the effect on the screen will be.
Last edited on
1: the line will be similar to the program at the moment but it will be a bit larger and further to the right/left of what k * normalized(mousePos - centerPos) would be?

2: second I'm not 100% sure on to be honest
Nope. Try it.


(100, 100) + k * normalized(mousePos - centerPos) I was way off with this one, I'm not sure even how this occurs, the size(magnitude) of the vector/line changes when I move the mouse around, not only this but the line fails to go past 180 degrees downward on the left side, and will only go about 75 degrees upward but no more.

not too sure why :/ but I'm fascinated to know why.

1
2
3
4
5
6
7
8
9
10
    Vector2 centerPos(WIDTH/2,HEIGHT/2);
    Vector2 mousePos(mouseX,mouseY);
    Vector2 difference = subtractVectors(mousePos,centerPos);
    Vector2 normalised = difference.normalize();
    normalised.scale(200);
    Vector2 added(0,0);
    added.x = 100;
    added.y = 100;
    added.add(normalised);



centerPos + k * normalized(mousePos - (100, 100)) - this one also kind of surprised me it just moved in whatever direction my mousex and mouse y position was in

1
2
3
4
5
6
7
8
9
10
11
    Vector2 centerPos(WIDTH/2,HEIGHT/2);
    Vector2 mousePos(mouseX,mouseY);
    Vector2 temp(100,100);
    Vector2 difference = subtractVectors(mousePos,temp);
    Vector2 normalised = difference.normalize();
    normalised.scale(200);
    Vector2 added(0,0);
    added.x = difference.x;
    added.y = difference.y;
    added.add(normalised);


here is a video of what is happening - https://youtu.be/kIrw_bEC5Jo
the size(magnitude) of the vector/line changes when I move the mouse around
Oops. I should have clarified that you should change the first point for the line to (100, 100).
See later
Last edited on
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
#include <iostream>
#include <string>
#include <cmath>


#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>


class Vector
{
public:
    double x{0};
    double y{0};
    
    Vector(double x = 0, double y = 0): x(x), y(y){};
    
    ~Vector(){};
    
    Vector add(const Vector& other)
    {
        Vector result;
        
        result.x = this->x + other.x;
        result.y = this->y + other.y;
        
        return result;
    }
    
    Vector subtract(const Vector& other)
    {
        Vector result;
        
        result.x = this->x - other.x;
        result.y = this->y - other.y;
        
        return result;
    }
    
    Vector scale(double scalar)
    {
        Vector result;
        result.x = this -> x * scalar;
        result.y = this -> y * scalar;
        return result;
    }
    
    double magnitude()
    {
        return sqrt( (x * x) +  (y * y) );
    }
    
    Vector normalize()
    {
        Vector result = this->scale(1/this->magnitude());
        return result;
    }
    
    void draw(Vector& c, SDL_Window *w, SDL_Renderer *r) // RENDER this VECTOR RELATIVE TO c
    {
        SDL_SetRenderDrawColor(r, 200, 200, 255, SDL_ALPHA_OPAQUE);
        SDL_RenderClear(r);
        
        SDL_SetRenderDrawColor(r, 255, 0, 0, SDL_ALPHA_OPAQUE); // RED
        SDL_RenderDrawLine(r, c.x, c.y, this->x, this->y);
        
        Vector norm = c.add( (this->subtract(c).normalize()).scale(50) );
        
        SDL_SetRenderDrawColor(r, 0, 255, 0, SDL_ALPHA_OPAQUE); // GREEN
        SDL_RenderDrawLine(r, c.x, c.y, norm.x, norm.y);
        
        SDL_RenderPresent(r);
        SDL_Delay(2);
        
        char str[80];
        sprintf(
                str, "Magnitude: %0.1f X: %0.0f Y: %0.0f",
                ( (this->subtract(c) ).normalize() ).magnitude(),
                this->x, this->y
                );
        SDL_SetWindowTitle(w, str);
    }
};


int main(int argc,char* argv[])
{
    const int WIDTH = 400;
    const int HEIGHT = 300;
    
    SDL_Event event;
    
    SDL_Init(SDL_INIT_VIDEO);
    
    SDL_Window *window = SDL_CreateWindow
    ("FOLLOW THE MOUSE", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
     WIDTH, HEIGHT, SDL_WINDOW_OPENGL);
    
    SDL_Renderer *renderer = SDL_CreateRenderer
    (window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    
    bool quit = false;
    
    int mouseX{0};
    int mouseY{0};
    
    Vector mouse_pos;
    Vector center(WIDTH/2, HEIGHT/2);
    Vector norm;
    
    while(!quit)
    {
        SDL_PollEvent(&event);
        if(event.type == SDL_QUIT)
            break;
        
        SDL_GetMouseState(&mouseX, &mouseY);
        mouse_pos.x = mouseX;
        mouse_pos.y = mouseY;
        
        mouse_pos.draw(center, window, renderer);
    }
    
    return 0;
}
Last edited on
Just wanted to make you aware that your dot product function is returning int.
Topic archived. No new replies allowed.