Персонаж должен двигаться пока зажата кнопка

Код на python, с использованием PyGame.
Персонаж двигается на одну клетку по нажатии кнопки (вверх, вниз, вправо и влево)
Нужно сделать так, чтобы при зажатии кнопки персонаж двигался пока кнопка не разжата.
Картинки - https://yadi.sk/d/9B_fYZkL4vNjvQ
Код:

import os
import sys
import pygame

pygame.init()
size = WIDTH, HEIGHT = 1280, 720
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Путь рыцаря")
pygame.display.set_icon(pygame.image.load("textures/icon.bmp"))
FPS = 30
clock = pygame.time.Clock()
all_sprites = pygame.sprite.Group()
tiles_group = pygame.sprite.Group()
player_group = pygame.sprite.Group()


def terminate():
    pygame.quit()
    sys.exit()


def load_image(name, color_key=None):
    fullname = os.path.join('textures', name)
    if not os.path.isfile(fullname):
        print(f'Файл с изображением \'{fullname}\' не найден')
        sys.exit()
    image = pygame.image.load(fullname)

    if color_key:
        image = image.convert()
        if color_key == -1:
            color_key = image.get_at((0, 0))
        image.set_colorkey(color_key)
    else:
        image = image.convert_alpha()
    return image


def load_level(filename):
    filename = "" + filename
    with open(filename, 'r') as mapFile:
        level_map = [line.strip() for line in mapFile]

    max_width = max(map(len, level_map))

    return list(map(lambda x: x.ljust(max_width, '.'), level_map))


def generate_level(level):
    new_player, x, y = None, None, None
    for y in range(len(level)):
        for x in range(len(level[y])):
            if level[y][x] == '.':
                Tile('road_not_up', x, y)
            elif level[y][x] == 'g':
                Tile('road_up_left', x, y)
            elif level[y][x] == 'r':
                Tile('road_up_right', x, y)
            elif level[y][x] == 'l':
                Tile('road_left', x, y)
            elif level[y][x] == 'd':
                Tile('road_left_down', x, y)
            elif level[y][x] == 'u':
                Tile('road_right_down', x, y)
            elif level[y][x] == 'x':
                Tile('road_x', x, y)
            elif level[y][x] == '=':
                Tile('road=', x, y)
            elif level[y][x] == '#':
                Tile('block', x, y)
            elif level[y][x] == '0':
                Tile('nothing', x, y)
            elif level[y][x] == '@':
                Tile('road_not_up', x, y)
                new_player = Player(x, y)
    return new_player, x, y


tile_images = {
    'block': load_image('Objects/block.png'),
    'road=': load_image('Objects/road=.png'),
    'road]': load_image('Objects/road].png'),
    'road_all': load_image('Objects/road_all.png'),
    'road_left': load_image('Objects/road_left.png'),
    'road_left_down': load_image('Objects/road_left_down.png'),
    'road_not_down': load_image('Objects/road_not_down.png'),
    'road_not_up': load_image('Objects/road_not_up.png'),
    'road_right_down': load_image('Objects/road_right_down.png'),
    'road_up_left': load_image('Objects/road_up_left.png'),
    'road_up_right': load_image('Objects/road_up_right.png'),
    'road_x': load_image('Objects/road_x.png'),
    'road[': load_image('Objects/roaf[.png'),
    'nothing': load_image('Objects/nothing.png')
}

tile_width = tile_height = 50


def move_hero(hero, movement):
    x, y = hero.pos
    if movement == "up":
        if y > 0 and level[y - 1][x] != '#' and y > 0 and level[y - 1][x] != '0':
            hero.move(x, y - 1)
    elif movement == "down":
        if y < level_y - 1 and level[y + 1][x] != '#' and y < level_y - 1 and level[y + 1][x] != '0':
            hero.move(x, y + 1)
    elif movement == "left":
        if x > 0 and level[y][x - 1] != '#' and x > 0 and level[y][x - 1] != '0':
            hero.move(x - 1, y)
    elif movement == "right":
        if x < level_x - 1 and level[y][x + 1] != '#' and x < level_x - 1 and level[y][x + 1] != '0':
            hero.move(x + 1, y)


class Tile(pygame.sprite.Sprite):
    def __init__(self, tile_type, pos_x, pos_y):
        super().__init__(tiles_group, all_sprites)
        self.image = tile_images[tile_type]
        self.rect = self.image.get_rect().move(
            tile_width * pos_x, tile_height * pos_y)


class Player(pygame.sprite.Sprite):
    def __init__(self, pos_x, pos_y):
        super().__init__(player_group, all_sprites)
        self.image = playerStand
        self.rect = self.image.get_rect().move(
            tile_width * pos_x + 15, tile_height * pos_y + 5)
        self.pos = pos_x, pos_y

    def move(self, x, y):
        self.pos = (x, y)
        self.rect = self.image.get_rect().move(
            tile_width * self.pos[0] + 15, tile_height * self.pos[1] + 5)


if __name__ == '__main__':
    player = None
    level = load_level('textures/level1.txt')
    player, level_x, level_y = generate_level(level)
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                terminate()
            keys = pygame.key.get_pressed()
            if keys[pygame.K_RIGHT]:
                move_hero(player, 'right')
                right, left, up, down = True, False, False, False
            elif keys[pygame.K_LEFT]:
                move_hero(player, 'left')
                right, left, up, down = False, True, False, False
            elif keys[pygame.K_UP]:
                move_hero(player, 'up')
                right, left, up, down = False, False, True, False
            elif keys[pygame.K_DOWN]:
                move_hero(player, 'down')
                right, left, up, down = False, False, False, True
            else:
                right, left, up, down = False, False, False, False
                animCount = 0
            screen.fill(pygame.Color('white'))
        tiles_group.draw(screen)
        player_group.draw(screen)
        pygame.display.flip()
        clock.tick(FPS)

В файле level1 находится такой блок текста:

g=r0g=r0
l#l0l#l0
l0l0l0l0
@0d=x=u0
#0#####0

Ответы (1 шт):

Автор решения: FotonPC

Попробуйте так:

import os
import sys
import pygame

pygame.init()
size = WIDTH, HEIGHT = 1280, 720
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Путь рыцаря")
pygame.display.set_icon(pygame.image.load("textures/icon.bmp"))
FPS = 30
clock = pygame.time.Clock()
all_sprites = pygame.sprite.Group()
tiles_group = pygame.sprite.Group()
player_group = pygame.sprite.Group()


def terminate():
    pygame.quit()
    sys.exit()


def load_image(name, color_key=None):
    fullname = os.path.join('textures', name)
    if not os.path.isfile(fullname):
        print(f'Файл с изображением \'{fullname}\' не найден')
        sys.exit()
    image = pygame.image.load(fullname)

    if color_key:
        image = image.convert()
        if color_key == -1:
            color_key = image.get_at((0, 0))
        image.set_colorkey(color_key)
    else:
        image = image.convert_alpha()
    return image


def load_level(filename):
    filename = "" + filename
    with open(filename, 'r') as mapFile:
        level_map = [line.strip() for line in mapFile]

    max_width = max(map(len, level_map))

    return list(map(lambda x: x.ljust(max_width, '.'), level_map))


def generate_level(level):
    new_player, x, y = None, None, None
    for y in range(len(level)):
        for x in range(len(level[y])):
            if level[y][x] == '.':
                Tile('road_not_up', x, y)
            elif level[y][x] == 'g':
                Tile('road_up_left', x, y)
            elif level[y][x] == 'r':
                Tile('road_up_right', x, y)
            elif level[y][x] == 'l':
                Tile('road_left', x, y)
            elif level[y][x] == 'd':
                Tile('road_left_down', x, y)
            elif level[y][x] == 'u':
                Tile('road_right_down', x, y)
            elif level[y][x] == 'x':
                Tile('road_x', x, y)
            elif level[y][x] == '=':
                Tile('road=', x, y)
            elif level[y][x] == '#':
                Tile('block', x, y)
            elif level[y][x] == '0':
                Tile('nothing', x, y)
            elif level[y][x] == '@':
                Tile('road_not_up', x, y)
                new_player = Player(x, y)
    return new_player, x, y


tile_images = {
    'block': load_image('Objects/block.png'),
    'road=': load_image('Objects/road=.png'),
    'road]': load_image('Objects/road].png'),
    'road_all': load_image('Objects/road_all.png'),
    'road_left': load_image('Objects/road_left.png'),
    'road_left_down': load_image('Objects/road_left_down.png'),
    'road_not_down': load_image('Objects/road_not_down.png'),
    'road_not_up': load_image('Objects/road_not_up.png'),
    'road_right_down': load_image('Objects/road_right_down.png'),
    'road_up_left': load_image('Objects/road_up_left.png'),
    'road_up_right': load_image('Objects/road_up_right.png'),
    'road_x': load_image('Objects/road_x.png'),
    'road[': load_image('Objects/roaf[.png'),
    'nothing': load_image('Objects/nothing.png')
}

tile_width = tile_height = 50


def move_hero(hero, movement):
    x, y = hero.pos
    if movement == "up":
        if y > 0 and level[y - 1][x] != '#' and y > 0 and level[y - 1][x] != '0':
            hero.move(x, y - 1)
    elif movement == "down":
        if y < level_y - 1 and level[y + 1][x] != '#' and y < level_y - 1 and level[y + 1][x] != '0':
            hero.move(x, y + 1)
    elif movement == "left":
        if x > 0 and level[y][x - 1] != '#' and x > 0 and level[y][x - 1] != '0':
            hero.move(x - 1, y)
    elif movement == "right":
        if x < level_x - 1 and level[y][x + 1] != '#' and x < level_x - 1 and level[y][x + 1] != '0':
            hero.move(x + 1, y)


class Tile(pygame.sprite.Sprite):
    def __init__(self, tile_type, pos_x, pos_y):
        super().__init__(tiles_group, all_sprites)
        self.image = tile_images[tile_type]
        self.rect = self.image.get_rect().move(
            tile_width * pos_x, tile_height * pos_y)


class Player(pygame.sprite.Sprite):
    def __init__(self, pos_x, pos_y):
        super().__init__(player_group, all_sprites)
        self.image = playerStand
        self.rect = self.image.get_rect().move(
            tile_width * pos_x + 15, tile_height * pos_y + 5)
        self.pos = pos_x, pos_y

    def move(self, x, y):
        self.pos = (x, y)
        self.rect.x = x
        self.rect.y = y


if __name__ == '__main__':
    player = None
    level = load_level('textures/level1.txt')
    player, level_x, level_y = generate_level(level)
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                terminate()
            
            screen.fill(pygame.Color('white'))
        keys = pygame.key.get_pressed()
        if keys[pygame.K_RIGHT]:
            move_hero(player, 'right')
            right, left, up, down = True, False, False, False
        elif keys[pygame.K_LEFT]:
            move_hero(player, 'left')
            right, left, up, down = False, True, False, False
        elif keys[pygame.K_UP]:
            move_hero(player, 'up')
            right, left, up, down = False, False, True, False
        elif keys[pygame.K_DOWN]:
            move_hero(player, 'down')
            right, left, up, down = False, False, False, True
        else:
            right, left, up, down = False, False, False, False
            animCount = 0
        tiles_group.draw(screen)
        player_group.draw(screen)
        pygame.display.flip()
        clock.tick(FPS)

У вас был неправильный Player.move(x,y)

→ Ссылка