#!/usr/bin/env python3

import numpy as np
import matplotlib.pyplot as plt
import pygame

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)

pygame.init()
pygame.display.set_caption('Vector Animation')
window_surface = pygame.display.set_mode((800, 600))
text_font = pygame.font.SysFont('Brass Mono', 30)
if text_font is None:
    text_font = pygame.font.SysFont('Monospace', 30)

background = pygame.Surface((800, 600))
background.fill(WHITE)

is_running = True
origin = pygame.Vector2(400, 300)
# initial vector points straight up - pygame has the origin
# 0,0 of the screen in the upper left.
vector = np.array([0, -200])

transform = np.array([[0, 1], [-1, 0]]) # rotate 90° clockwise

### everything below here is graphics for drawing the arrow


def vec_from_array(vec):
    return pygame.Vector2(vec[0], vec[1])


# https://www.reddit.com/r/pygame/comments/v3ofs9/draw_arrow_function/
def draw_arrow(
        surface: pygame.Surface,
        start: pygame.Vector2,
        end: pygame.Vector2,
        color: pygame.Color,
        body_width: int = 2,
        head_width: int = 6,
        head_height: int = 6,
    ):
    """Draw an arrow between start and end with the arrow head at the end.

    Args:
        surface (pygame.Surface): The surface to draw on
        start (pygame.Vector2): Start position
        end (pygame.Vector2): End position
        color (pygame.Color): Color of the arrow
        body_width (int, optional): Defaults to 2.
        head_width (int, optional): Defaults to 4.
        head_height (float, optional): Defaults to 2.
    """
    arrow = start - end
    angle = arrow.angle_to(pygame.Vector2(0, -1))
    body_length = arrow.length() - head_height

    # Create the triangle head around the origin
    head_verts = [
        pygame.Vector2(0, head_height / 2),  # Center
        pygame.Vector2(head_width / 2, -head_height / 2),  # Bottomright
        pygame.Vector2(-head_width / 2, -head_height / 2),  # Bottomleft
    ]
    # Rotate and translate the head into place
    translation = pygame.Vector2(0, arrow.length() - (head_height / 2)).rotate(-angle)
    for i in range(len(head_verts)):
        head_verts[i].rotate_ip(-angle)
        head_verts[i] += translation
        head_verts[i] += start

    pygame.draw.polygon(surface, color, head_verts)

    # Stop weird shapes when the arrow is shorter than arrow head
    if arrow.length() >= head_height:
        # Calculate the body rect, rotate and translate into place
        body_verts = [
            pygame.Vector2(-body_width / 2, body_length / 2),  # Topleft
            pygame.Vector2(body_width / 2, body_length / 2),  # Topright
            pygame.Vector2(body_width / 2, -body_length / 2),  # Bottomright
            pygame.Vector2(-body_width / 2, -body_length / 2),  # Bottomleft
        ]
        translation = pygame.Vector2(0, body_length / 2).rotate(-angle)
        for i in range(len(body_verts)):
            body_verts[i].rotate_ip(-angle)
            body_verts[i] += translation
            body_verts[i] += start

        pygame.draw.polygon(surface, color, body_verts)

clock = pygame.time.Clock()
vector_clock = 0

radius = 10

while is_running:
    pygame.draw.ellipse(window_surface, BLACK, (origin[0]-(radius * 0.5), origin[1]-(radius*0.5), radius, radius))
    time_delta = clock.tick(60)/1000.0
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            is_running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                is_running = False
    draw_arrow(window_surface, origin, vec_from_array(vector+origin), BLACK)

    if (vector_clock == 0):
        window_surface.blit(background, (0, 0))
        vector = vector.dot(transform)
        text_surface = text_font.render('Rotate 90°', 100, 250)
        window_surface.blit(text_surface, (0, 0))

    if (vector_clock >= 1.0 and vector_clock <= 1.1):
        window_surface.blit(background, (0, 0))

    vector_clock += time_delta

    if (vector_clock >= 5.0) :
        vector_clock = 0

    pygame.display.update()

Generated by kyle using scpaste at Mon Oct 23 17:45:27 2023. PDT. (original)