Сделал сниппет, в котором шарик бегает за мышкой. Особенность этого сниппета в том, что шарик поворачивается в сторону мышки не сразу, а с заданной угловой скоростью. За счёт этого добавляется эффект инерции при перемещении по экрану.
Красная линия показывает направление вектора скорости.
import pygame as pg
from math import copysign
from pygame import QUIT, KEYDOWN, K_ESCAPE
from pygame.math import Vector2
from pygame.time import Clock
UPDATE_RATE = 1 / 120
MAX_UPDATE_RATE = 1 / 20
class Follower:
def __init__(self, surface, position, speed):
self.surface = surface
self.position = Vector2(position)
self.speed = speed
self.direction = Vector2(0, 1)
self.angle_speed = 90 # Градусов в секунду
self.color = (44, 44, 44)
self.line_color = (244, 22, 22)
self.radius = 20
def update(self, delta_time):
mouse_position = Vector2(pg.mouse.get_pos())
direction_to_mouse = (mouse_position - self.position).normalize()
if mouse_position.distance_to(self.position) > self.radius:
angle = self.direction.angle_to(direction_to_mouse)
if abs(angle) > 180:
angle = -copysign((360 - abs(angle)), angle)
self.direction = self.direction.rotate(copysign(min(abs(angle), self.angle_speed * delta_time), angle))
else:
self.direction = direction_to_mouse
self.position += (self.direction * self.speed) * delta_time
def render(self):
pg.draw.circle(self.surface, self.color, self.position, self.radius)
pg.draw.line(
self.surface,
self.line_color,
self.position,
self.position + self.direction * (self.radius + 10),
5
)
class Game:
def __init__(self, surface):
self.surface = surface
self.bg_color = (220, 220, 220)
self.follower = Follower(surface, (surface.get_width() / 2, 100), 200)
self.clock = Clock()
self.time_bucket = 0
self.working = True
def handle_events(self):
for e in pg.event.get():
if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE):
self.working = False
def update(self, delta_time):
self.time_bucket += delta_time
while self.time_bucket >= UPDATE_RATE:
self.time_bucket -= UPDATE_RATE
self.follower.update(UPDATE_RATE)
def draw_direction(self):
pg.draw.line(self.surface, (44, 200, 44), self.follower.position, pg.mouse.get_pos())
def render(self):
self.surface.fill(self.bg_color)
self.follower.render()
self.draw_direction()
pg.display.update()
def run(self):
delta_time = 0
self.clock.tick()
while self.working:
self.handle_events()
self.update(min(delta_time, MAX_UPDATE_RATE))
self.render()
delta_time = self.clock.tick() / 1000
def main():
pg.init()
Game(pg.display.set_mode((1920, 1080), flags=pg.FULLSCREEN)).run()
pg.quit()
if __name__ == "__main__":
main()