/
Vibek
/
First_Game
Обзор
Документация
Войти
/
Vibek
/
First_Game
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
models/entity.py
109 строк
4 KB
Vibek
Оптимизация, иснхронизация хитбоксов
21 июн 2026, 17:09
21 июн 2026, 17:09
bbdda9b
Код
Авторство
О чём код?
import pygame from utils.collision import get_obb_corners from pygame.math import Vector2 from core.events import EventBus from models.hitbox import HitboxDef class Entity: """ Базовый класс для всех физических объектов игры (Игрок, Враги, Снаряды). """ def __init__( self, x: float, y: float, speed: float, size: tuple[int, int], bus: EventBus, hp: int = 1, hitbox: HitboxDef | None = None, art_angle_offset: float = 0.0, ) -> None: self.pos = Vector2(x, y) self.speed = speed self.hitbox = hitbox or HitboxDef(width=size[0], height=size[1]) self.size = self.hitbox.size self.angle = 0.0 self.art_angle_offset = art_angle_offset self.rect = pygame.Rect(int(x), int(y), self.size[0], self.size[1]) self.bus = bus self.max_hp = hp self.hp = hp self.is_alive = True @property def hitbox_center(self) -> Vector2: """Геометрический центр логического хитбокса.""" return self.pos + Vector2(self.hitbox.offset_x, self.hitbox.offset_y) + Vector2(self.hitbox.size) / 2 @property def facing_angle(self) -> float: """Единый угол для OBB-коллизий и отрисовки (логика + коррекция арта).""" return self.angle + self.art_angle_offset @property def center(self) -> Vector2: """Центр сущности для физики, прицеливания и коллизий.""" return self.hitbox_center def get_obb_corners(self) -> list[Vector2]: """Делегирует расчёт вершин в utils.""" return get_obb_corners(self.hitbox_center, self.hitbox.size, self.facing_angle) def take_damage(self, amount: float) -> None: if not self.is_alive: return self.hp -= amount if self.hp <= 0: self._die() def _die(self) -> None: """Внутренний метод: гарантирует атомарность перехода в DEAD.""" self.is_alive = False self.on_death() def on_death(self) -> None: """ Hook для подклассов. Базовая реализация пустая. Подклассы переопределяют для: - Эмиссии специфичных событий - Сброса ресурсов - Триггера UI/GameLoop """ pass def update(self, dt: float, direction: Vector2) -> None: """ Применяет движение к сущности за один кадр. :param dt: Delta time в секундах (время, прошедшее с прошлого кадра) :param direction: Нормализованный вектор направления. Длина должна быть 0 или 1. """ # Оптимизация: если направление нулевое, пропускаем расчеты if direction.length_squared() == 0: return delta = direction * self.speed * dt self.pos += delta # Синхронизируем математическую модель с графическим API PyGame self._sync_rect() def clamp_to_bounds(self, bounds: pygame.Rect) -> None: """Ограничивает логический хитбокс внутри прямоугольника арены.""" hitbox_x = self.pos.x + self.hitbox.offset_x hitbox_y = self.pos.y + self.hitbox.offset_y hitbox_x = max(bounds.left, min(hitbox_x, bounds.right - self.hitbox.width)) hitbox_y = max(bounds.top, min(hitbox_y, bounds.bottom - self.hitbox.height)) self.pos.x = hitbox_x - self.hitbox.offset_x self.pos.y = hitbox_y - self.hitbox.offset_y def _sync_rect(self) -> None: """Переносит точную float-позицию в целочисленный PyGame Rect.""" self.rect.x = int(self.pos.x) self.rect.y = int(self.pos.y)