Как сделать этот спрайт интерактивным, а затем закрыть его, чтобы можно было отобразить новую карту?

Я пытаюсь сделать этот спрайт Button интерактивным. Он появляется после того, как игрок достиг цели, и после щелчка по нему спрайт должен исчезнуть для новой карты. Я также сделаю так, чтобы после щелчка по спрайту загружался новый уровень, но пока давайте оставим его при выполнении щелчка по спрайту и возникновению чего-либо из-за этого.

Вот интересующий код:

class Button(pg.sprite.Sprite):
    def __init__(self, game, x, y):
        self.groups = game.all_sprites, game.buttons
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = pg.Surface((450, 335))
        self.image = game.alert_img        
        self.rect = self.image.get_rect()
        self.x = x
        self.y = y
        self._layer = 2
        self.rect.x = x * TILESIZE
        self.rect.y = y * TILESIZE

def events(self):
    # catch all events here
    for event in pg.event.get():
        if event.type == pg.QUIT:
            self.quit()
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_ESCAPE:
                self.quit()
            if event.key == pg.K_LEFT:
                self.player.move(dx=-1)
            if event.key == pg.K_RIGHT:
                self.player.move(dx=1)
            if event.key == pg.K_UP:
                self.player.move(dy=-1)
            if event.key == pg.K_DOWN:
                self.player.move(dy=1)
        if event.type == pg.USEREVENT + 1:
            self.text_object.kill()
            self.text_object = Text((1760, 570), self.player.actions, self.font)
            self.all_sprites.add(self.text_object)
            Button(self, self.player.x -1.5, self.player.y - 2.4)

Имейте в виду, что события находятся в основном классе, а кнопка класса, ну, явно нет. Я хочу сказать, что события def не относятся к классу кнопок.

РЕДАКТИРОВАТЬ Оба варианта ниже работают, однако его ответ больше подходит для моего личного проекта, где мое решение может быть более подходящим для вас, в зависимости от того, что вы пытаетесь выполнить. Советую просмотреть оба.


person K. Groot    schedule 19.09.2017    source источник
comment
На этот вопрос немного сложно ответить, особенно для людей, которые не знают ваш проект целиком. Я бы дал классу Game атрибут self.button = None и назначил бы экземпляр кнопки этому атрибуту, когда цель будет достигнута. Сложная часть - проверить наличие столкновений с положением мыши из-за смещения камеры. Попробую придумать решение и выложу позже.   -  person skrx    schedule 20.09.2017
comment
Ого, спасибо! Кроме того, началась первая разработка микроконтроллера, и она идет хорошо!   -  person K. Groot    schedule 20.09.2017
comment
Может быть, вместо того, чтобы пользователь щелкнул спрайт, я мог бы запустить форму ожидания события, и событие было бы ключевым? Таким образом, он по-прежнему делает то, что я хочу, и мне не нужно проверять какое-либо столкновение между спрайтом и позицией мыши. Я посмотрю на это   -  person K. Groot    schedule 20.09.2017
comment
Я нашел кое-что, что может сработать, если я сделаю это так pygame.event.clear(), чтобы очистить кеш событий. event = pygame.event.wait() для ожидания события в кэше событий. А потом что-то в этом роде elif event.type == KEYDOWN: if event.key = K_f: do something...   -  person K. Groot    schedule 20.09.2017
comment
Да, вы можете просто позволить пользователю нажать клавишу.   -  person skrx    schedule 20.09.2017
comment
@skrx Я нашел способ сделать это, который работает, все щелкать по спрайту было бы слишком сложно для чего-то такого простого, в любом случае спасибо!   -  person K. Groot    schedule 20.09.2017
comment
Я тоже опубликую свое решение, но все еще есть небольшая ошибка, которую мне нужно исправить.   -  person skrx    schedule 20.09.2017


Ответы (2)


Я бы дал классу Game атрибут self.button = None и назначил бы экземпляр кнопки, когда пользователь достигнет цели. Чтобы проверить, сталкивается ли мышь с кнопкой, вы можете использовать event.pos события pg.MOUSEBUTTONDOWN и применить камеру. Мне пришлось передать классу Camera метод apply_mouse, потому что event.pos - это просто кортеж, и мне нужно было отрицательное положение камеры.

# In the `Game` class.
def events(self):
    for event in pg.event.get():
        if event.type == pg.QUIT:
            self.quit()
        elif event.type == pg.MOUSEBUTTONDOWN:
            if self.button is not None:
                mouse = self.camera.apply_mouse(event.pos)
                if self.button.rect.collidepoint(mouse):
                    print('Clicked!')
                    # Remove button from sprite groups and
                    # set self.button to None again.
                    button.kill()
                    self.button = None
        # KEYDOWN events omitted.
        elif event.type == pg.USEREVENT + 1:
            self.text_object.kill()
            self.text_object = Text((1760, 570), self.player.actions, self.font)
            self.all_sprites.add(self.text_object)
            # Check `if self.button is None` so that we don't add
            # several buttons to the groups.
            if self.button is None:
                self.button = Button(self, 1060, 670)


class Button(pg.sprite.Sprite):

    def __init__(self, game, x, y):
        self.groups = game.all_sprites, game.buttons
        pg.sprite.Sprite.__init__(self, self.groups)
        self.image = pg.Surface((450, 335))
        self.image.fill((0, 40, 200))  
        self.rect = self.image.get_rect(topleft=(x, y))
        self._layer = 6


class Camera:
    # I just added this method to the Camera class.
    def apply_mouse(self, pos):
        return (pos[0]-self.camera.x, pos[1]-self.camera.y)
person skrx    schedule 20.09.2017

Поэтому вместо того, чтобы пользователь щелкнул спрайт, я вместо этого создал функцию с именем continue_game, в которой игра останавливается и ждет, пока пользователь нажмет пробел, чтобы игра продолжилась, у меня нет существенного кода, запускаемого после пробела запущен, но kill удаляет спрайт так, как я хочу, чтобы я делал то, что я хочу.

def continue_game(self):
    user_continue = False
    while not user_continue:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.quit()
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_ESCAPE:
                    self.quit()
                if event.key == pg.K_SPACE:
                    self.button.kill()
                    user_continue = True

Ранее упомянутое userevent теперь выглядит так:

if event.type == pg.USEREVENT + 1:
            self.text_object.kill()
            self.text_object = Text((1760, 570), self.player.actions, self.font)
            self.all_sprites.add(self.text_object)
            self.button = Button(self, self.player.x -1.5, self.player.y - 2.4)
            self.draw()
            self.continue_game()
person K. Groot    schedule 20.09.2017
comment
Вам также необходимо вызвать self.clock.tick(FPS) в этом цикле while. - person skrx; 20.09.2017
comment
Сделал правку, в которой говорится, что ваше решение подходит для моего проекта, где мое в целом подходит, но все же хочу сказать, что ваше решение определенно лучше. - person K. Groot; 20.09.2017