У меня проблема с циклом событий в pygame

Я делаю игру, в которой игрок постоянно находится посередине, когда фон движется, чтобы казалось, что игрок движется. Когда я нажимаю две клавиши со стрелками Ex. вверх и вправо, он идет по диагонали, но когда я отпускаю стрелку вверх, он должен продолжать двигаться вправо. Иногда это работает, но в основном просто перестает двигаться.

Я понятия не имею, как это исправить.

цикл событий

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False
    key = pygame.key.get_pressed()

    if key[K_UP]:
        if key[K_RIGHT]:
            bg.move("up_right")
        elif key[K_LEFT]:
            bg.move("up_left")
        else:
            bg.move("up")

    elif key[K_DOWN]:
        if key[K_RIGHT]:
            bg.move("down_right")
        elif key[K_LEFT]:
            bg.move("down_left")
        else:
            bg.move("down")


    elif key[K_RIGHT]:
        if key[K_DOWN]:
            bg.move("down_right")
        elif key[K_UP]:
            bg.move("up_right")
        else:
            bg.move("right")


    elif key[K_LEFT]:
        if key[K_DOWN]:
            bg.move("down_left")
        elif key[K_UP]:
            bg.move("up_left")
        else:
            bg.move("left")

движение

Here the movement gets changed

def move(self, direction):
    if direction == "up_right":
        self.posY += self.speed
        self.posX -= self.speed

    if direction == "up_left":
        self.posY += self.speed
        self.posX += self.speed

    if direction == "down_right":
        self.posY -= self.speed
        self.posX -= self.speed

    if direction == "down_left":
        self.posY -= self.speed
        self.posX += self.speed
        
    if direction == "up":
        self.posY += self.speed+2
        
    if direction == "down":
        self.posY -= self.speed+2
        
    if direction == "right":
        self.posX -= self.speed+2
        
    if direction == "left":
        self.posX += self.speed+2

Сначала я не добавлял «up_left» и т. д., потому что думал, что он просто пройдет через оба if и отредактирует позицию на обоих. Но это не так.

Извините, если ответы на эту тему уже были, но я не нашел.

Спасибо

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
184
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваша основная проблема заключается в том, что вы проверяете нажатые клавиши внутри цикла событий:

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False

    # only executed if there's an event returned by pygame.event.get()
    # and possible executed multiple times per frame
    key = pygame.key.get_pressed()

    if key[K_UP]:
        ...

Поэтому ваш код, выполняющий движение (if key[K_UP]: ...), выполняется только тогда, когда в данный момент в очереди есть событие.

Просто переместите этот код за пределы цикла обработчика событий:

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False

# always executed every frame
key = pygame.key.get_pressed()

if key[K_UP]:
     ...

ИМХО, лучший способ справиться с вашим движением - использовать векторы, поскольку они позволяют легко обеспечить постоянную скорость движения и гораздо меньше кода.

Вот простой пример:

import pygame

def main():
    pygame.init()
    screen = pygame.display.set_mode((500, 500))

    clock = pygame.time.Clock()
    dt = 0

    movement = {
        pygame.K_UP:    ( 0, -1),
        pygame.K_DOWN:  ( 0,  1),
        pygame.K_LEFT:  (-1,  0),
        pygame.K_RIGHT: ( 1,  0)
    }

    pos = pygame.Vector2((100, 100))

    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        pressed = pygame.key.get_pressed()

        # calculate the movement vector
        move = pygame.Vector2()
        for dir in (movement[key] for key in movement if pressed[key]):
            move += dir

        if move.length() > 0: move.normalize_ip()
        # ensure we have a constant speed
        pos += move * dt/5

        screen.fill(pygame.Color('grey'))
        pygame.draw.circle(screen, pygame.Color('dodgerblue'), [int(x) for x in pos], 20, 0)
        pygame.display.update()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

Большое спасибо. Теперь все работает нормально. Я тоже попробую реализовать векторы.

Maniol102 28.03.2019 12:09

Другие вопросы по теме