Разработка на коленке

"тут должна быть красивая цитата о программировании"

Перемещать "игрока" в сторону мыши

2024-03-15 20:30

Сделал сниппет, в котором шарик бегает за мышкой. Особенность этого сниппета в том, что шарик поворачивается в сторону мышки не сразу, а с заданной угловой скоростью. За счёт этого добавляется эффект инерции при перемещении по экрану.

Красная линия показывает направление вектора скорости.

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()

8/follow_mouse.py

  • 1 / 1