Lennart Wijers
Lennart Wijers

Reputation: 235

How to stop overshooting a target position using deltatime and velocity

I'm trying to move a 'train' up and down a track. the track is a list of nodes with x and y coordinates.

The train moves up and down, but sometimes, depending on distance and its velocity, it overshoots a node in 1 deltatime step and starts jumping left and right (or up and down depending on direction) because the node isn't registered as reached.

I tried to build in a threshold. If the node is reached within the threshold amount of pixels it takes the next node as goal. This helps a but of course it keeps happening depending on distance and velocity:

if dist <= 5:
        self.currentGoalNode += self.iterateBy

I tried to separately calculate the distance traveled in in each millisecond instead of deltatime and check if the goal was reached in each one of those steps, but couldn't get it working and I stopped trying because it seems to lead to a lot of unnecessary code and calculations.

Is there an easy way to fix this or was I on the right "track" and do i need to take the extra code?

My entire code:

self.iterateBy = 1
self.floatPosition = self.rect.center

def move (self, dt):

    # calculate distance
    dist = math.hypot(self.path[self.currentGoalNode].x - self.rect.centerx,
                      self.path[self.currentGoalNode].y - self.rect.centery)

    # check if going up or down on path
    if self.currentGoalNode +1 >= self.totalNodes or self.currentGoalNode <= 0:
            self.iterateBy *= -1

    # attempt to eradicate the 'jumping' by making a treshold
    if dist <= 5:
        self.currentGoalNode += self.iterateBy

    diffx, diffy = (self.route[self.currentGoalNode][0] - self.rect.center[0],
                    self.route[self.currentGoalNode][1] - self.rect.center[1])

    angle = math.atan2(diffx, diffy)
    x = (math.sin(angle) * self.velocity) * dt
    y = (math.cos(angle) * self.velocity) * dt

    # keeping track of the position in floats
    self.floatPosition= tuple(map(sum, zip(self.floatPosition, (x,y))))

    # moving the rect and converting to ints
    self.rect.center = self.floatPosition

Upvotes: 1

Views: 117

Answers (1)

Prune
Prune

Reputation: 77837

If you're within a 1-delta step from the goal (1dist <= threshold), then don't add iterator. Instead, just set the position to the location of the goal.

Upvotes: 1

Related Questions