Ответы пользователя по тегу pygame
  • Как int из rect float?

    @o5a
    Хранить эти положения отдельными переменными (где они будут float), и только потом присваивать их самим rect.x/y
    Тут для примера я завел отдельные (rx/ry), но можно использовать и уже заведенные x/y только с учетом, что это предполагалось как центр объекта.
    ..
        class Bullet(pygame.sprite.Sprite):
            def __init__(self, screen, speed_x):
                pygame.sprite.Sprite.__init__(self)
                self.x, self.y = 550.0, 450.0
                self.screen = screen
                self.image = pygame.image.load("img/bullet.png").convert()
                self.rect = self.image.get_rect(center=(self.x, self.y))
                # для хранения наших координат
                self.rx, self.ry = self.rect.x, self.rect.y
                self.speed_x = speed_x
                self.speed_y = 0.1
    
            def update(self):
                if self.ry > 0:
                    self.ry -= self.speed_y
                    self.rx += self.speed_x
                    # и вот теперь уже присваиваем значения
                    self.rect.x, self.rect.y = self.rx, self.ry
                else:
                    self.kill()


    Можно и напрямую присваивать x/y (без этих rx/ry) только работать с rect.centerx:
    ..
            def update(self):
                if self.y > 0:
                    self.y -= self.speed_y
                    self.x += self.speed_x
                    self.rect.centerx, self.rect.centery = self.x, self.y
                else:
                    self.kill()
    Ответ написан
    1 комментарий
  • Local variable 'font'?

    @o5a
    Вы берете font из pygame и заменяете его своей переменной в подобных строках:
    font = font.Font("freesansbold.ttf", 15)
    В результате для последующих вызовов перестает существовать pygame.font, который пытаетесь вызвать.
    Используйте для своего font другое название переменной.
    Ответ написан
    Комментировать
  • Не работает pygame.key,как исправить?

    @o5a
    Поправьте код (оберните тэгом для Python).

    Пока вижу такие ошибки:
    1. pygame.QUIT написан нижним регистром, поэтому программа не будет закрываться

    2. 2 отдельных цикла по эвентам, поэтому 2-й не отрабатывает (все в 1-м прокручивается)
    Нужно все проверки эвентов внести в один цикл, например так
    ...
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x -= velocity
    
                if event.key == pygame.K_RIGHT:
                    x += velocity
    
                if event.key == pygame.K_UP:
                    y -= velocity
    
                if event.key == pygame.K_DOWN:
                    y += velocity
            # здесь же и проверка на выход из программы
            elif event.type==pygame.QUIT:
                run = False
                pygame.quit()
                quit()


    3. Загрузку картинок (фона и игрока) лучше вынести за пределы цикла, неэффективно каждый раз их загружать. В цикле оставить только сам 'blit'.

    4. На отрисовку картинки заданы фиксированные координаты вместо x,y
    Т.е. должно быть
    screen.blit(player_img,(x,y))
    Ответ написан
    Комментировать
  • Спрайт снаряд после выстрела поворачивается по направлению другого спрайта(танка). Не знаю почему так происходит?

    @o5a
    Как уже заметили в комментариях, проблема в том, что для прироста положения снаряда (вектора скорости) используется одна и та же глобальная переменная. Поэтому при обновлении все снаряды изменяют вектор на одинаковый. Нужно было использовать локальный аттрибут каждого снаряда для хранения скорости (фиксированный на момент создания, как я понимаю скорость и направление уже не должна меняться).
    Навскидку вижу можно просто сделать так:
    ...
        class Projectile(pygame.sprite.Sprite):
            def __init__(self, weigth, heigth, corner):
                ...
                # добавляем каждому снаряду свою скорость. вычисляем поворотом на передаваемый угол
                self.projectile_speed = pygame.math.Vector2((4, 0)).rotate(-corner)
    
            def update(self):
                # и тут соответственно используем вектор скорости собственный для каждого снаряда
                self.projectile += self.projectile_speed

    spoiler
    Еще заметил, что английские названия ошибочны
    heigth => height (высота)
    weigth => weight (вес)
    видимо имелось в виду width (ширина)
    corner - в английском тоже значит "угол" но это не тот угол (как угол поворота), а как угол квадрата, угол комнаты.
    для угла как направления используется angle
    see = "видеть", наверное имелось в виду sea = "море".
    Не критично конечно, но лучше привыкать к правильным названиям, чтобы у других изучающих код потом не возникло недопонимания.
    Ответ написан
    1 комментарий
  • Почему не двигается объект в pygame?

    @o5a
    Потому что сравниваете координаты не объекта hunter_1, а не связанные с ним координаты
    if hunter_pos_y < pos_y_rand:
            hunter_pos_y += 1

    когда должно быть примерно так
    if hunter_1.y < pos_y_rand:
            hunter_1.y += 1

    Аналогично и координаты целей (pos_y_rand). Сейчас координаты охотника сравниваются просто с этой рандомной точкой каждый раунд, а не с координатами реального объекта - цели.
    К тому же этот самый hunter каждый цикл создается заново, хотя по логике предполагаю он должен быть только 1.
    Т.е. создание объекта hunter нужно вынести наружу цикла, а координаты проверять по аттрибутам объекта, его же и двигать.
    Во-вторых, эти цели (звёзды?) в текущем виде нигде не сохраняются, каждый цикл предыдущие объекты-цели перезаписываются, остается только их изображение на экране. Т.е. координаты ранее созданных целей взять будет негде. Если все же логика работы была - ходить за этими целями, то их нужно хранить (самое простое - добавлять к списку).
    Ответ написан
    3 комментария
  • Как сделать бесконечную стрельбу в pygame?

    @o5a
    Проблема в том, что событие нажатия на кнопку срабатывает только в момент нажатия. Так что если просто держать пробел, то в каждом последующем цикле событие нажатия не срабатывает, но флаг fire сбрасывается в False каждый цикл, поэтому стрельба останавливается.
    Можно флаг fire привязать к самому кораблю как аттрибут, т.е. в __init__
    self.fire = False
    И в событиях работать именно с атрибутом класса, а не передавать отдельную переменную fire.
    def check_keydown_events(event, ship, settings, screen, bullets):
        if event.key == pygame.K_LEFT:
            # left arrow keydown events
            ship.move_left = True  # moves ship left when key's keeping pressed
        if event.key == pygame.K_RIGHT:
            # right arrow keydown events
            ship.move_right = True  # moves ship right when key's keeping pressed
        if event.key == pygame.K_DOWN:
            # down arrow keydown events
            ship.move_down = True  # moves ship down when key's keeping pressed
        if event.key == pygame.K_UP:
            # up arrow keydown events
            ship.move_up = True  # moves ship up when key's keeping pressed
        if event.key == pygame.K_SPACE:
            ship.fire = True

    Аналогично изменить в функции отпускания кнопки.
    Но т.к. событие нажатия не срабатывает повторно каждый цикл, то и само создание новых пуль не будет работать в той функции, так что ее нужно перенести туда, где срабатывает каждый цикл, например в тот же check_events
    def check_events(ship, settings, screen, bullets):
        """main event checker function"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                # working on keydown events
                check_keydown_events(event, ship, settings, screen, bullets)
                # function that checks keydown event type and works according event type
            elif event.type == pygame.KEYUP:
                check_keyup_events(event, ship)
                # function that checks keyup event type and works according event type
        print(len(bullets))  # to check amount of bullets on screen
        if ship.fire and len(bullets) < settings.bullets_allowed:
            # continues firing until amount of bullets reaches limit
            new_bullet = Bullet(settings, ship, screen)  # creating new bullet
            bullets.add(new_bullet)  # adding created bullet to Group
    Ответ написан
    3 комментария
  • Как в python pygame как сделать чтобы объект поворачивался до курсора мыши?

    @o5a
    Проблем 2.
    1. Вращать нужно оригинал изображения, а не уже измененную предыдущем вращением копию. Из-за этого будет забиваться память, и скорее всего поэтому он
    иногда еле-ели вертится!)

    Т.е. сменить примерно так:
    bmp_дерево_rot = pygame.transform.rotate(bmp_дерево, rotate(bmp_image))
    bmp_image = bmp_дерево_rot.get_rect(center=(150, 700))
    sc.blit(bmp_дерево_rot, bmp_image)

    2. Для расчета угла вращения нужно помимо координат мыши указывать и правильные координаты самой картинки, а не 0,0.
    def rotate(oject2):
        mouse_x, mouse_y = pygame.mouse.get_pos()
        x, y = bmp_image.center
        rel_x, rel_y = mouse_x - x, mouse_y - y
        angle = (180 / math.pi) * -math.atan2(rel_y, rel_x)
        return angle
    Ответ написан
    Комментировать
  • Как с помощью python рисовать графические примитивы?

    @o5a
    Тогда зачем tkinter, в pygame можно и рисовать эти примитивы
    https://www.pygame.org/docs/ref/draw.html
    Ответ написан
    Комментировать
  • Как написать отскок квадрата по горизонтали(pygame)?

    @o5a
    Потому что эта проверка зацикливает квадрат у границы: как только он начинает идти в обратную сторону, срабатывает первое условие и он снова меняет направление.
    Отскок обычное делается сменой знака прироста расстояния (скорости) на каждой из границ.
    def __init__(self):
       ....
        self.speed = SPEED
    
    
    def update(self):
        self.rect.x += self.speed
        if self.rect.left < 0 or self.rect.right > WIDTH:
            self.speed = -self.speed
    Ответ написан
    Комментировать
  • Почему вместо изображений черный экран в pygame?

    @o5a
    Отрисовка drawWindow() должна происходить внутри основного цикла игры (т.е. поправьте отступ).
    Ответ написан
  • Почему окно pygame не отвечает?

    @o5a
    Так не нужно включать консольный ввод input() в цикл работы pygame, у Вас окно "зависает" потому что постоянно ждет ввод в консоль. Никаких input быть не должно.

    Заодно, если рисуете квадрат, стоит добавить очистку экрана перед pygame.draw..., чтобы за ним не тащился "след".
    win.fill((0,0,0))
    Ответ написан
    1 комментарий
  • Не могу найти в чем ошибка. кто поможет?

    @o5a
    Ну, смотри. Сообщение
    self.x >= -self.width:
    TypeError: '>=' not supported between instances of 'NoneType' and 'int'

    указывает нам на то, что во время ошибки self.x = None
    Изначально вижу x заполняется. Значит в процессе работы он в какой-то момент устанавливается в None.
    Такой проблемный момент видно только в return_self, где его значение устанавливается в некий передаваемый radius
    self.x = radius
    который в свою очередь получается из функции find_radius.
    При беглом взгляде на эту функцию бросается в глаза, что единственный return в ней из-за отступов находится внутри блока if. Т.е. если условие не выполняется, функция как раз и возвращает None, вызывая ошибку программы.
    Так что проблему надо искать там. Так как запланированной логики работы игры я не знаю, предположу, что достаточно просто поправить эту строку с return radius (убрать лишний отступ), логично, чтобы она возвращала результат независимо от условия.
    Ответ написан
    Комментировать