0

I'm trying to make sprite to follow another sprite flexible way.

If main sprite moves faster follower gets more behind, and if slower follower gets closer.

Movement itself works with following (pseudo) code:

target_vector = Vector2D(mainsprite_x, mainsprite_y)
follower_vector = Vector2D(follower_x, follower_y)

new_follower_vector = Vector2D.lerp(follower_vector, target_vector, LERP_FACTOR)

Currently I've been using various constants for LERP_FACTOR which works "okayish".

Now I would like to add limits how much behind follower can be and how close it can get.

I'm using Pygame but that shouldn't matter.

How I can achieve that?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
jtiai
  • 611
  • 5
  • 11

1 Answers1

0

I recommend to compute the distance from between the follower and the sprite and the unit direction vector from (follower_x, follower_y) to (mainsprite_x, mainsprite_y).
The distance can be get by computing the Euclidean distance. Pygame provides distance_to() for that. Th unit direction vector can be computed by dividing the direction vector by the distance or by normalizing (normalize()) the direction vector:

target_vector = Vector2(mainsprite_x, mainsprite_y)
follower_vector = Vector2(follower_x, follower_y)

distance = follower_vector.distance_to(target_vector)
direction_vector = target_vector - follower_vector
if distance > 0:
    direction_vector /= distance

Now you can define an exact step_distance and move to follower int direction of the sprite:

if distance > 0:
    new_follower_vector = follower_vector + direction_vector * step_distance.

Define a maximum_distance and a minimum_distance. The minimum step distance is:

min_step = max(0, distance - maximum_distance)

The maximum step distance is

max_step = distance - minimum_distance

Put it all together:

minimum_distance    = ???
maximum_distance    = ???
target_vector       = Vector2(mainsprite_x, mainsprite_y)
follower_vector     = Vector2(follower_x, follower_y)
new_follower_vector = Vector2(follower_x, follower_y)

distance = follower_vector.distance_to(target_vector)
if distance > minimum_distance:
    direction_vector    = (target_vector - follower_vector) / distance
    min_step            = max(0, distance - maximum_distance)
    max_step            = distance - minimum_distance
    step_distance       = min_step + (max_step - min_step) * LERP_FACTOR
    new_follower_vector = follower_vector + direction_vector * step_distance

Minimal example: repl.it/@Rabbid76/PyGame-FollowMouseSmoothly

import pygame

LERP_FACTOR      = 0.05
minimum_distance = 25
maximum_distance = 100

def FollowMe(pops, fpos):
    target_vector       = pygame.math.Vector2(*pops)
    follower_vector     = pygame.math.Vector2(*fpos)
    new_follower_vector = pygame.math.Vector2(*fpos)

    distance = follower_vector.distance_to(target_vector)
    if distance > minimum_distance:
        direction_vector    = (target_vector - follower_vector) / distance
        min_step            = max(0, distance - maximum_distance)
        max_step            = distance - minimum_distance
        step_distance       = min_step + (max_step - min_step) * LERP_FACTOR
        new_follower_vector = follower_vector + direction_vector * step_distance

    return (new_follower_vector.x, new_follower_vector.y) 

pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()

follower = (100, 100)
run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    player   = pygame.mouse.get_pos()
    follower = FollowMe(player, follower)

    window.fill(0)  
    pygame.draw.circle(window, (0, 0, 255), player, 10)
    pygame.draw.circle(window, (255, 0, 0), (round(follower[0]), round(follower[1])), 10)
    pygame.display.flip()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174