Gamedev - Moving an object from point A to point B

his is more a beginner gamedev question... If this isn't the place to ask please let me know! Thank you

I want to create a function that places my game object at a given strating point (Point A) and move it towards and end point (Point B):

void Object::Move( Vector2 point_a, Vector2 point_b )
{
... // Set object's position to the starting point (point a)
this->position.x = point_a.x;
this->position.y = point_a.y

... //Move it towards point B
}

The main problem I have with this approach and the true reason behind my question here is that since the game is running its update loop constantly, say 60 times a second, the initial position gets reset over and over back to point A and that won't let my Object to move. I thought about creating a bool within the object's definition that becomes true once the position has been set but I don't want to include something like that in it but I can't figure out any other way to do it. Which is why I'm here.

Thanks for taking the time.
since the game is running its update loop constantly, say 60 times a second, the initial position gets reset over and over back to point A and that won't let my Object to move
The game updating at a regular rate should not mean that initial positions get reset.

Your function's behavior is odd.
Let's say you have a Player at position C.
You call Player.Move(A, B);
So now position C is thrown away, and the player's position becomes A, and then presumably increments toward B a little bit, depending on your timestep. So you're trying to do two different things at once, and in effect failing to do either effectively.

I would expect a function called "Move" to not abruptly reset any positions. You may want to consider using a 'velocity' vector. For example,

1
2
3
4
5
void Object::Move(Vector2 velocity)
{
    this->position.x += velocity.x;
    this->position.y += velocity.y;
}


So in each iteration in your loop, you need to call Move to move the character over a bit more each timestep.

____________________________

Or, another thing to consider. If you know you want to move to a particular target, then you can calculate this and move towards it by a given speed.

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
// Example program
#include <iostream>
#include <cmath>

struct Vector2 {
    double x;
    double y;
};

Vector2 operator*(double scale, const Vector2& vec)
{
    return Vector2{scale * vec.x, scale * vec.y};
}

std::ostream& operator<<(std::ostream& os, const Vector2& vec)
{
    return os << "(" << vec.x << ", " << vec.y << ")";   
}

Vector2 operator+(const Vector2& a, const Vector2& b)
{
    return Vector2{a.x + b.x, a.y + b.y};   
}
Vector2 operator-(const Vector2& a, const Vector2& b)
{
    return Vector2{a.x - b.x, a.y - b.y};   
}
Vector2 operator/(const Vector2& vec, double scale)
{
    return Vector2{vec.x / scale, vec.y / scale};
}

double magntiude_squared(const Vector2& vec)
{
    return vec.x * vec.x + vec.y * vec.y;
}

Vector2 normalize(const Vector2& vec)
{
    if (vec.x == 0.0 && vec.y == 0.0)
        return Vector2{0.0, 0.0};
        
    return vec / std::sqrt(magntiude_squared(vec));
}


class Object {
  public:
    void MoveTowards(const Vector2& target, double speed);
    
    Vector2 position;
};

void Object::MoveTowards(const Vector2& target, double speed)
{
    Vector2 delta = target - this->position;
    if (magntiude_squared(delta) < speed * speed)
    {
        // set to target if our speed would go beyond the target
        this->position = target;
    }
    else
    {
        this->position = this->position + speed * normalize(delta);  
    }
}

int main()
{
    double timestep = 1.0 / 60.0; // or whatever... see "fix your timestep" article
    Object player;
    player.position = Vector2{100, 100};
    
    Vector2 target {200, 300};
    double speed = 320;
    
    for (int i = 0; i < 50; i++)
    {
        player.MoveTowards(target, speed * timestep);
        std::cout << player.position << '\n';
    }
}

(102.385, 104.77)  
(104.77, 109.541)                          
(107.155, 114.311)          
(109.541, 119.081)    
(111.926, 123.851)   
(114.311, 128.622)    
(116.696, 133.392)      
(119.081, 138.162)    
(121.466, 142.933)   
(123.851, 147.703)                
(126.237, 152.473)               
(128.622, 157.243)        
(131.007, 162.014)            
(133.392, 166.784)                     
(135.777, 171.554)  
(138.162, 176.324)     
(140.547, 181.095)                   
(142.933, 185.865)         
(145.318, 190.635)            
(147.703, 195.406)    
(150.088, 200.176)                    
(152.473, 204.946)                      
(154.858, 209.716)      
(157.243, 214.487)             
(159.628, 219.257)     
(162.014, 224.027)          
(164.399, 228.798)   
(166.784, 233.568)      
(169.169, 238.338)          
(171.554, 243.108)      
(173.939, 247.879) 
(176.324, 252.649)     
(178.71, 257.419)  
(181.095, 262.189)                    
(183.48, 266.96)          
(185.865, 271.73)       
(188.25, 276.5)         
(190.635, 281.271)        
(193.02, 286.041)      
(195.406, 290.811)      
(197.791, 295.581)
(200, 300) 
(200, 300)    
(200, 300) 
(200, 300)         
(200, 300)        
(200, 300)           
(200, 300)    
(200, 300)       
(200, 300) 
Last edited on
Yeah you're right, now that you mention it what I had in mind sounds kind of dumb now.
Thanks a lot for taking the time to make such a good example I appreciate the heads up and the help. I'll take a very close look to the code
I would recommend something like this, instead. It more easily handles variable frame times while maintaining constant speed:
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
class Actor{
    Point2D position;
    Point2D source;
    Point2D destination;
    double movement_start_time = 0;
    double movement_length = 0;
    bool moving = false;
public:
    void move_to(double current_time, const Point2D &destination, double movement_length){
        this->source = this->position;
        this->destination = destination;
        this->movement_start_time = current_time;
        this->movement_length = movement_length;
        this->moving = true;
    }
    void update(double current_time){
        if (!this->moving)
            return;
        auto t = current_time - this->movement_start_time;
        if (t >= this->movement_length){
            this->position = this->destination;
            this->moving = false;
            return;
        }
        this->position = this->source + (this->destination - this->source) * (t / this->movement_length);
    }
    void draw();
};

void game_loop(){
    actors.front().move_to(0, {10, 10}, 1); //move to (10, 10) in 1 second
    while (true){
        double current_time = get_game_time();
        for (auto &actor : actors)
            actor.update(current_time);
        for (auto &actor : actors)
            actor.draw();
    }
}
Topic archived. No new replies allowed.