Пример #1
0
    def damage_in_area(self,
                       area: PhysicalRect,
                       damage,
                       type_,
                       impulse=None,
                       skip=None,
                       **kwargs):
        """
        Наносит урон всем сущностям в заданых границах
        :param area: границы
        :param damage: урон
        :param type_: тип урона
        :param impulse: импуль при нанесении урона (кулаком)
        :param skip: список id сущностей, которые по какой-либо причине не получат урон
        :return: True, если был нанесён урон, False иначе
        """

        if skip is None:
            skip = []

        # флаг, отвечающий за то, что был нанесён урон
        damaged = False

        # Пинаем объекты
        if impulse is not None:
            for object_ in self.objects:
                if area.check_intersection(object_.body_rect):
                    object_.body.apply_impulse_at_local_point(impulse)

        # Наносим урон сущностям и игроку
        for entity in self.entities_and_player:

            # Пропускаем нужных сущностей
            if id(entity) in skip:
                continue

            # Если сущность в области нанесения урона
            if area.check_intersection(entity.body_rect):

                # подробнее читать в документации на этот метод
                if 'object_' in kwargs:
                    kwargs['object_'].damaged()

                # нанесение урона
                entity.get_damage(damage, type_)
                # флаг, был нанесён урон
                damaged = True

                # Передаём импульс, если он есть
                if impulse is not None:
                    entity.body.apply_impulse_at_local_point(impulse)

        return damaged
Пример #2
0
    def __init__(self,
                 x,
                 y,
                 radius=0.3,
                 sprite=None,
                 scene=None,
                 angle=0,
                 mass=1,
                 moment=None,
                 elasticity=0,
                 friction=0.6):
        if moment is None:
            moment = pymunk.moment_for_box(mass, (radius, radius))

        body = pymunk.Body(mass, moment)
        shape = pymunk.Circle(body, radius=radius)

        super(DynamicCircularObject, self).__init__(x=x,
                                                    y=y,
                                                    width=radius,
                                                    height=radius,
                                                    scene=scene,
                                                    sprite=sprite,
                                                    body=body,
                                                    shape=shape,
                                                    angle=angle,
                                                    mass=mass,
                                                    moment=moment,
                                                    elasticity=elasticity,
                                                    friction=friction,
                                                    type_=pymunk.Body.DYNAMIC)

        self.body_rect = PhysicalRect(x - radius / 2, y - radius / 2,
                                      2 * radius, 2 * radius)
Пример #3
0
    def __init__(self,
                 screen: pygame.Surface,
                 x=0,
                 y=0,
                 h_fov=pi / 2,
                 distance=15):
        # Экран, на который будет выводиться изображение
        self.screen = screen
        # Временная поверхность для рисования, потом блитится на экран
        self.temp_surface = pygame.Surface(screen.get_rect().size)

        # Далее физические характеристики камеры
        # Физические координаты центра камеры
        self.__position = Vec2d(x, y)
        # Горизонтальный угол обзора камеры
        self.h_fov = h_fov
        # Расстояние от камеры до поверхности экрана
        self.__distance = distance
        # Физическая ширина области вилимости камеры
        self.window_width = 2 * self.__distance * tan(self.h_fov / 2)
        # Физическая высота области вилимости камеры
        self.window_height = self.window_width * SCREEN_HEIGHT / SCREEN_WIDTH
        # Вертикальный угол обзора камеры
        self.v_fov = atan(self.window_height / self.__distance / 2)
        # Физическая область видимости камеры
        self.camera_rect = PhysicalRect(
            self.__position[0] - self.window_width / 2,
            self.__position[1] - self.window_height / 2, self.window_width,
            self.window_height)

        # Коэффициент, на который умножаются координаты, чтобы отрисовать объекты на экране на экране
        self.scale_factor = SCREEN_WIDTH / self.window_width
        self.dev_font = pygame.font.SysFont(pygame.font.get_fonts()[0], 50)
Пример #4
0
    def __init__(self, x, y, width=0.3, height=0.3, sprite=None):
        """

        :param x: x координата левого нижнего угла объекта
        :param y: y координата левого нижнего угла объекта
        :param width: ширина описанного прямоугольника объекта
        :param height: высота описанного прямоугольника объекта
        :param sprite: спрайт объекта
        """
        self._position = Vec2d(x, y)
        self.width = width
        self.height = height
        self.sprite = sprite
        if self.sprite is not None:
            # Переворачиваем спрайт
            self.sprite = pygame.transform.flip(self.sprite, False,
                                                True).convert_alpha()

        self.body_rect = PhysicalRect(x, y, width, height)

        # Преобразованное изображения спрайта
        # Имеет размер, как проекция объекта на поверхность камеры
        # Нужно для оптимизации
        self.scaled_image = self.sprite
        self.last_camera_distance = -1  # Дистанция от камеры да сцены
Пример #5
0
    def load_level(self, username):
        """
        Функция загрузки уровня из файла
        На вход принимает название сейва
        Если названия нет, подгружает резервный сейв под именем DefaultName_save
        P.S. такого резервного сейва еще нет
        """
        lvl_path = os.path.join('src', 'Levels', 'Saved_Levels',
                                username + '_save')
        if not os.path.exists(lvl_path):
            lvl_path = os.path.join('src', 'Levels', 'Saved_Levels',
                                    'default_level_save')
        with open(lvl_path) as readfile:
            data = yaml.load(readfile, Loader=yaml.Loader)

        # Если нет данных выходим
        if data == {}:
            return

        # Загрузка границ
        self.borders = PhysicalRect(
            **data['borders']
        ) if data['borders'] is not None else PhysicalRect(-10, -5, 20, 10)
        self.invisible_segments = data['invisible_segments']
        self.add_borders()
        background = data['background']
        if background == 'dorm':
            self.bg = Dorm(self)
        if background == 'corr':
            self.bg = Corridor(self)
        if background == 'base':
            self.bg = Basment(self)
        # Загрузка объектов
        for object_ in data['objects'].values():
            self.load_object(object_)

        # Инициализация игрока
        self.init_player(*data['MainCharacter']['vector'],
                         **data['MainCharacter']['brain']['init'])

        # Загрузка сущностей
        for entity_config in data['entities'].values():
            self.load_entity(entity_config)
Пример #6
0
 def position(self, new_position):
     """
     Устанавливает новые физические координаты центра обзора
     :param new_position: новые физические координаты центра камеры
     :return: физические координаты центра камеры
     """
     # Изменение позиции
     self.__position = new_position
     # Пересчёт физической области видимости
     self.camera_rect = PhysicalRect(
         self.__position[0] - self.window_width / 2,
         self.__position[1] - self.window_height / 2, self.window_width,
         self.window_height)
Пример #7
0
    def __init__(self, scene, x=0, y=0, brain=ManualController, **kwargs):
        super(BaseCharacter, self).__init__(scene,
                                            x,
                                            y,
                                            brain=brain,
                                            **self.configs['init'],
                                            **kwargs)

        # Имя персонажа
        self.name = self.__class__.__name__
        # Описание персонажа
        self.description = None

        # Боёвка
        hits: dict = default_person['hits']
        # Удары рукой
        self.arming = hits['arming']
        # Бросания
        self.throwing = hits['throwing']

        # Список названий ударов рукой
        self.arming_types = list(self.arming)
        # Список названия бросков
        self.throwing_types = list(self.throwing)

        # Обновляем свойства, согласно конфигу
        if 'properties' in self.configs:
            self.__dict__ |= self.configs['properties']

        # Обновляем удары, согласно конфигу
        if 'hits' in self.configs:
            self.__dict__ |= self.configs['hit']

        # Обновляем описанные прямоугольники для разных состояний, согласно конфигу
        if 'rects' in self.configs:
            for name_, (width_, height_) in self.configs['rects'].items():
                self.__dict__[name_] = PhysicalRect(0, 0, width_, height_)

        # Атрибуты, которые в данный момент
        self.__arming_reload = 0
        self.__throwing_reload = 0
Пример #8
0
    def __init__(self, scene, x, y, angle=0, type_=Body.STATIC, lifetime=5,
                 damage=None, owner=None, if_damaged='none', if_damaged_many='disappear'):
        """
        Можно ещё передать параметр damage, если нужно, чтобы объект наносил урон
        :param scene: игровая сценв
        :param x: координата x объекта
        :param y: координата y объекта
        :param angle: начальный угол поворота объекта
        :param type_: тип объекта (статический, кинематический или динамический)
        :param lifetime: время жизни, через lifetime сек объект изчезнет.
        Чтобы он не изчес можно установить float('inf')
        :param damage: урон при попадании в сущность, не являющейся владельцем, мб None
        :param owner: владелеец (точнее id), мб None
        :param if_damaged: действие после нанесения урона 1 раз
        :param if_damaged_many: действие после нанесения урона на 1 итерации цикла проверки урона
        """
        sprite = None
        if self.configs['sprite'] is not None:
            sprite = pil_to_pygame(load_image(self.configs['sprite']))

        init_config: dict = self.configs['init']

        radius = init_config['radius']

        if init_config['moment'] is None:
            init_config['moment'] = pymunk.moment_for_circle(init_config['mass'], 0, radius)

        body = pymunk.Body(init_config['mass'], init_config['moment'])
        shape = pymunk.Circle(body, radius)

        super(CircularObject, self).__init__(x=x, y=y, width=radius, height=radius,
                                             scene=scene, sprite=sprite, lifetime=lifetime,
                                             body=body, shape=shape, angle=angle,
                                             mass=init_config['mass'], moment=init_config['moment'],
                                             elasticity=init_config['elasticity'],
                                             friction=init_config['friction'], type_=type_,
                                             damage=damage, owner=owner,
                                             if_damaged=if_damaged, if_damaged_many=if_damaged_many)

        self.body_rect = PhysicalRect(x - radius / 2, y - radius / 2, 2 * radius, 2 * radius)
Пример #9
0
    def distance(self, new_distance):
        """
        Возращает физическое расстояние от камеры до сцены
        :return:
        """
        if new_distance <= 0:
            # raise CameraError("Distance became negative")
            return

        # Расстояние от камеры до поверхности экрана
        self.__distance = new_distance
        # Физическая ширина области вилимости камеры
        self.window_width = 2 * self.__distance * tan(self.h_fov / 2)
        # Физическая высота области вилимости камеры
        self.window_height = self.window_width * SCREEN_HEIGHT / SCREEN_WIDTH
        # Вертикальный угол обзора камеры
        self.v_fov = atan(self.window_height / self.__distance / 2)
        # Физическая область видимости камеры
        self.camera_rect = PhysicalRect(
            self.__position[0] - self.window_width / 2,
            self.__position[1] - self.window_height / 2, self.window_width,
            self.window_height)
        # Коэффициент, на который умножаются координаты, чтобы отрисовать объекты на экране на экране
        self.scale_factor = SCREEN_WIDTH / self.window_width
Пример #10
0
 def _hit_box_to_physical_rect(self, box):
     physical_box = PhysicalRect(*box.values())
     physical_box.bottomleft += self.body_rect.bottomleft
     return physical_box
Пример #11
0
    def __init__(self,
                 scene,
                 x=0,
                 y=0,
                 width=0.7,
                 height=1.8,
                 mass=75,
                 brain=Idle,
                 animations=None,
                 sounds=None,
                 **kwargs):
        """
        :param scene: игровая сцена
        :param x: x координата левого нижнего края сущности
        :param y: y координата левого нижнего края сущности
        :param height: высота сущности
        :param width: ширина сущности
        :param brain: мозги сущности, подробнее смотри в Engine/EntityControllers.py
        """

        super(Entity, self).__init__(x=x,
                                     y=y,
                                     width=width,
                                     height=height,
                                     sprite=None,
                                     scene=scene,
                                     mass=mass,
                                     moment=float('inf'),
                                     elasticity=0,
                                     friction=0.6,
                                     type_=pymunk.Body.DYNAMIC)
        # float('inf'), чтобы исключить вращение

        # Сцена сущности
        self.scene = scene
        # Мозг сущности
        brain_init = {}
        if 'brain_init' in kwargs:
            brain_init = kwargs['brain_init']
        self.brain = brain(self, **brain_init)

        # Описанные прямоугольники для разных состояний игрока
        # Нужны для пересчёта геометрии при смене состояния игрока
        # Названия говорят сами за себя
        # Прописывание всего этого рукими можно удалить, но оно нужно для наглядности
        rects: dict = default_person['rects']
        self.idle_rect = PhysicalRect(0, 0, rects['idle_rect'][0],
                                      rects['idle_rect'][1])
        self.walking_rect = PhysicalRect(0, 0, rects['walking_rect'][0],
                                         rects['walking_rect'][1])
        self.running_rect = PhysicalRect(0, 0, rects['running_rect'][0],
                                         rects['running_rect'][1])

        self.sitting_rect = PhysicalRect(0, 0, rects['sitting_rect'][0],
                                         rects['sitting_rect'][1])
        self.squatting_rect = PhysicalRect(0, 0, rects['squatting_rect'][0],
                                           rects['squatting_rect'][1])
        self.lying_rect = PhysicalRect(0, 0, rects['lying_rect'][0],
                                       rects['lying_rect'][1])
        self.crawling_rect = PhysicalRect(0, 0, rects['crawling_rect'][0],
                                          rects['crawling_rect'][1])

        self.soaring_rect = PhysicalRect(0, 0, rects['soaring_rect'][0],
                                         rects['soaring_rect'][1])
        self.jumping_rect = PhysicalRect(0, 0, rects['jumping_rect'][0],
                                         rects['jumping_rect'][1])
        self.flying_rect = PhysicalRect(0, 0, rects['flying_rect'][0],
                                        rects['flying_rect'][1])
        self.landing_rect = PhysicalRect(0, 0, rects['landing_rect'][0],
                                         rects['landing_rect'][1])

        self.dying_rect = PhysicalRect(0, 0, rects['dying_rect'][0],
                                       rects['dying_rect'][1])
        self.win_rect = PhysicalRect(0, 0, rects['win_rect'][0],
                                     rects['win_rect'][1])

        # Не меняющиеся атрибуты
        # Свойства сущности
        properties: dict = default_person['properties']
        self.walk_speed = properties['walk_speed']  # Скорость ходьбы сущности
        self.run_speed = properties['run_speed']  # Скорость бега сущности
        self.jump_speed = properties['jump_speed']  # Скорость прыжка
        # Максимальное здоровье
        self.max_health = properties['max_health']
        # Вероятность уклонения
        self.dodge = properties['dodge']
        # Сопротивление урону
        self.resistance = properties['resistance']

        # Атрибуты, которые в данный момент
        self.__health = self.max_health

        # Далее флаги, нужные для удобной обработки

        # Состояние сущности
        self.__state = State.IDLE
        # Горизонтальное направление взгляда (влево, вправо)
        self.horizontal_view_direction = 'right'
        # Вертикальное направление взгляда (вверх, вниз)
        self.vertical_view_direction = 'up'

        # Сами анимации
        self.animations = EntityAnimations(self)
        if animations is not None:
            self.load_animations(animations)

        # Звуки
        self.sounds = EntitySounds(self)
        if sounds is not None:
            self.load_sounds(sounds)