Search code examples
pythonmathmotion

Creating curvature animation in python


I am facing one problem for 2 weeks now and I still cannot figure it out even from where to start. The problem is about creating a curvature animation which is about two points chasing each other. one of them moves on a straight line on the x-axis and the other one starts from down from the x-axis(on y-axis e.g p(0:-10)) and by the principle of chasing, the second one tries to catch the first one while facing it continuously. I wrote some code that helped me to get actual answers but I am not able to visualize it in a very precious way. I am using python as my main coding language.

Thank you in advance Luka K.


Solution

  • It seems like enemy following player which was asked last week for tkinter and pygame

    enter image description here

    You calculate vector between objects

    diff_x = player_x - enemy_x
    diff_y = player_y - enemy_y
    

    and distance

    distance = (diff_x**2 + diff_y**2)**0.5  # Pythagoras: a**2 + b**2 = c**2
    

    to calculate normalized vector (vector which has length 1)

    normal_x = diff_x/distance
    normal_y = diff_y/distance
    

    which you can multiply by speed to calculate move_x and move_y for enemy

    enemy_move_x = enemy_speed * normal_x
    enemy_move_y = enemy_speed * normal_y
    

    and you can use it to move enemy and to draw line.


    To draw it you can use different modules - any GUI framework like tkinter, PyQt, wxPython or game/media library like pygame or pyglet. Eventually you could generate images which you could use to create animated GIF.


    import tkinter as tk
    
    def follow(player_x, player_y, enemy_x, enemy_y, enemy_speed=5):
        diff_x = player_x - enemy_x
        diff_y = player_y - enemy_y
    
        distance = (diff_x**2 + diff_y**2)**0.5  # Pythagoras: a**2 + b**2 = c**2
    
        if distance <= enemy_speed:
            return diff_x, diff_y
    
        normal_x = diff_x/distance
        normal_y = diff_y/distance
    
        enemy_move_x = enemy_speed * normal_x
        enemy_move_y = enemy_speed * normal_y
    
        return enemy_move_x, enemy_move_y
    
    def update_game():
        global player_x
        global player_y
        global enemy_x
        global enemy_y
    
        # draw line for player
        canvas.create_line(player_x, player_y, player_x+player_move_x, player_y+player_move_y, fill='green')
    
        # move player
        player_x += player_move_x
        player_y += player_move_y
        canvas.move(player_id, player_move_x, player_move_y)
    
        # calculate move for enemy
        enemy_move_x, enemy_move_y = follow(player_x, player_y, enemy_x, enemy_y, enemy_speed)
    
        # draw line for enemy
        canvas.create_line(enemy_x, enemy_y, enemy_x+enemy_move_x, enemy_y+enemy_move_y, fill='red')
    
        # move enemy
        enemy_x += enemy_move_x
        enemy_y += enemy_move_y
        canvas.move(enemy_id, enemy_move_x, enemy_move_y)
    
        root.after(100, update_game) # repeate after 100ms (0.1s)
    
    # --- main ---
    
    # player start position and move ("speed")
    player_x = 5
    player_y = 50
    player_move_x = 4
    player_move_y = 0 # try for `1`
    
    # enemy start position and speed
    enemy_x = 5
    enemy_y = 500
    enemy_speed = 5
    
    root = tk.Tk()
    
    canvas = tk.Canvas(root, width=750, height=500)#, bg='gray')
    canvas.pack()
    
    player_id = canvas.create_oval(player_x-5, player_y-5, player_x+5, player_y+5, fill='green')
    enemy_id = canvas.create_oval(enemy_x-5, enemy_y-5, enemy_x+5, enemy_y+5, fill='red')
    
    update_game()
    
    root.mainloop()
    

    BTW: in answer to question How to make enemy follow player you have the same code but you have to move player using keys WASD and it doesn't draw line.