-1

I'm working with movements and I have made the red block follow the white block which is the player when ever the white block changes directions I have the red block also change directions is there a way I could make it smoothier other then it teleporting the tail to the direction of the player? Video Link

here is how the red tail moves based on the white block if the player is moving down the x and y of the tail changes and same for the up ,left,right I want a better way to do this without it instantly teleporting to those position like smoothly move there

    if down:
       #-- the tail red change directions
        tail.y = player1.y - 80
        tail.x = player1.x

    if up:
       #-- the tail red change directions
        tail.y = player1.y + 80
        tail.x = player1.x
        
    if left:
       #-- the tail red change directions
        tail.y = player1.y 
        tail.x = player1.x + 80

    if right:
       #-- the tail red change directions
        tail.y = player1.y 
        tail.x = player1.x - 80

my full code


import pygame
pygame.init()


# draw the iwndow
width = 500
height = 750

window = pygame.display.set_mode((height,width))


# the player class
class player:
    def __init__(self,x,y,height,width,color):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color
        self.rect = pygame.Rect(x,y,height,width)
        self.speed = 5
    def draw(self):
        self.rect.topleft = (self.x,self.y)
        pygame.draw.rect(window,self.color,self.rect)

# display the player
color = (255,255,255)
player1 = player(180,190,40,40,color)


# bg

bg = pygame.image.load('2.png')

# the colision to determine the direction the player should move
class player:
    def __init__(self,x,y,height,width,color):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color
        self.rect = pygame.Rect(x,y,height,width)
        self.speed = .9
    def draw(self):
        self.rect.topleft = (self.x,self.y)
        pygame.draw.rect(window,self.color,self.rect)

# display the player
color = (255,255,255)
tailcolor = (176, 58, 46)
player1 = player(180,170,50,50,color)

tail = player(100,170,50,50,tailcolor)

def draw():
    window.fill((0,0,0))
    window.blit(bg,(0,0))
    player1.draw()

    
    tail.draw()
    

# make movements True
right = False
left = False
up = False
down = False
only_up = False
only_left = False

# get position
pos = True
pos2 = 0
# the main loop
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False




    # check for key press
    keys = pygame.key.get_pressed()


    if down:
       #-- the tail red change directions
        tail.y = player1.y - 80
        tail.x = player1.x

    if up:
       #-- the tail red change directions
        tail.y = player1.y + 80
        tail.x = player1.x
        
    if left:
       #-- the tail red change directions
        tail.y = player1.y 
        tail.x = player1.x + 80

    if right:
       #-- the tail red change directions
        tail.y = player1.y 
        tail.x = player1.x - 80
        
    #--------------------------------------------------- player movement
    if left == False:
        if keys[pygame.K_RIGHT]:
            if  not keys[pygame.K_UP]:
                if not keys[pygame.K_DOWN]:
                    right = True


    if right:
        left = False
        down = False
        up = False
        player1.x += player1.speed



        
    if right == False:
        if keys[pygame.K_LEFT]:
            if not keys[pygame.K_UP]:
                if not keys[pygame.K_DOWN]:
                    left = True

    if left:
        right = False
        down = False
        up = False
        player1.x -= player1.speed
        


    if down == False:
        if keys[pygame.K_UP]:
            up = True       
    if up:
        down = False
        left = False
        right = False
        
        player1.y -= player1.speed


        
    if up == False:
        if keys[pygame.K_DOWN]:
            down = True

    if down:
        up = False
        left = False
        right = False
        player1.y += player1.speed


    

        
    #--------------------------------------------------- player movement



            
    # show everything drawn
    draw()

    pygame.display.update()

pygame.quit()


0

1 Answer 1

0

I think you can achieve that by using some sort of delay. Instead of getting the position of the tail based on the current position of the player, you want to get the position of the tail based on an "old position of the player".

Also, the delay should be a variable that you can change at will later, in case you want to adjust how close the tail follows the player.

Here is what I would try:

  • Outside the infinite loop, define a variable called tail_delay, and assign it a specific amount of time.
  • You can have an object to record the "current position" of player1 with timestamps (it will be a collection of positions in the end). That object, let's call it player1_positions_record, will be updated constantly in the infinite loop (this can be a waste of memory - don't save all positions, you only need a few seconds, and older than that you discard).
  • In the infinite loop, assign the position of the tail based on the tail_delay and the player1_positions_record. That way you'll use a past position of player1.

As mentioned in the comments, this is not a perfect solution but it works:

import pygame
from datetime import datetime, timedelta
pygame.init()

# tail delay in seconds
tail_delay=timedelta(seconds=0.3)

# draw the iwndow
width = 900
height = 1200

window = pygame.display.set_mode((height,width))


# the player class
class player:
    def __init__(self,x,y,height,width,color):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color
        self.rect = pygame.Rect(x,y,height,width)
        self.speed = 5
    def draw(self):
        self.rect.topleft = (self.x,self.y)
        pygame.draw.rect(window,self.color,self.rect)

# display the player
color = (255,255,255)
player1 = player(180,190,40,40,color)


# bg

bg = pygame.image.load('2.png')

# the colision to determine the direction the player should move
class player:
    def __init__(self,x,y,height,width,color):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color
        self.rect = pygame.Rect(x,y,height,width)
        self.speed = .9
    def draw(self):
        self.rect.topleft = (self.x,self.y)
        pygame.draw.rect(window,self.color,self.rect)

# display the player
color = (255,255,255)
tailcolor = (176, 58, 46)
player1 = player(180,170,50,50,color)

tail = player(100,170,50,50,tailcolor)

def draw():
    window.fill((0,0,0))
    window.blit(bg,(0,0))
    player1.draw()

    
    tail.draw()
    

# make movements True
right = False
left = False
up = False
down = False
only_up = False
only_left = False

# get position
pos = True
pos2 = 0
# the main loop
run = True

player1_positions_record=[]
test_time=datetime.now()

while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
    
    # add current position, and delete the positions that are old
    # in 1 second, I counted 270 timestamps approx, so I will cut the timestamps in 500 (don't think we need more than that)
    player1_positions_record.append((datetime.now(), (player1.x, player1.y)))
    if len(player1_positions_record) > 500:
        player1_positions_record = player1_positions_record[-500:]
    # now it's time to find the position of the tail. It will be an old position of the player
    right_now=datetime.now()
    for position in player1_positions_record:
        position_timestamp=position[0]
        print(type(position_timestamp))
        if position[0]>right_now-tail_delay:
            tail.y = position[1][1] # second element of the tuple containing the old position 
            tail.x = position[1][0] # first element
            break

    # check for key press
    keys = pygame.key.get_pressed()


    # if down:
    #    #-- the tail red change directions
    #     tail.y = player1.y - 80
    #     # tail.x = player1.x

    # if up:
    #    #-- the tail red change directions
    #     tail.y = player1.y + 80
    #     # tail.x = player1.x
        
    # if left:
    #    #-- the tail red change directions
    #     tail.y = player1.y 
    #     tail.x = player1.x + 80

    # if right:
    #    #-- the tail red change directions
    #     tail.y = player1.y 
    #     tail.x = player1.x - 80
        
    #--------------------------------------------------- player movement
    if left == False:
        if keys[pygame.K_RIGHT]:
            if  not keys[pygame.K_UP]:
                if not keys[pygame.K_DOWN]:
                    right = True


    if right:
        left = False
        down = False
        up = False
        player1.x += player1.speed



        
    if right == False:
        if keys[pygame.K_LEFT]:
            if not keys[pygame.K_UP]:
                if not keys[pygame.K_DOWN]:
                    left = True

    if left:
        right = False
        down = False
        up = False
        player1.x -= player1.speed
        


    if down == False:
        if keys[pygame.K_UP]:
            up = True       
    if up:
        down = False
        left = False
        right = False
        
        player1.y -= player1.speed


        
    if up == False:
        if keys[pygame.K_DOWN]:
            down = True

    if down:
        up = False
        left = False
        right = False
        player1.y += player1.speed


    

        
    #--------------------------------------------------- player movement



            
    # show everything drawn
    draw()

    pygame.display.update()

pygame.quit()
Sign up to request clarification or add additional context in comments.

2 Comments

I undersatnd but a little confused on how I should implement this so your saying to add a delay before the red tail moves to the position of the player for example delay = 50 and when the player moves any position start the delay timer and then add then update the tails position?
I made it work - it's now perfect, but it works ( you can do some improvements on top of it :) ). I will update the answer

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.