pygame - как медленно обновлять панель HP без времени.sleep () - PullRequest
0 голосов
/ 03 декабря 2018

Я создаю игру в pygame и хочу медленно, но в реальном времени уменьшать HP игрока.Для этого я знаю, что не могу использовать time.sleep(), потому что это останавливает всю игру.Я пытался использовать threading.Thread на pygame.MOUSEBUTTONDOWN, чтобы нанести урон игроку, но это не сработало.Имейте в виду, что я впервые использую темы.

Мой код:

#-*- coding-utf8 -*-
import pygame
import threading
import time
import os

os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.init()

SIZE = (1200, 600)
screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()

class Player:
    def __init__(self):
        self.HP = 100
        self.HP_BAR = pygame.Rect(10, 10, self.HP * 3, 10)

        self.X = 100
        self.Y = 100
        self.WIDTH = 50
        self.HEIGHT = 100
        self.COLOR = (255,255,0)
        self.PLAYER = pygame.Rect(self.X, self.Y, self.WIDTH, self.HEIGHT)

    def move(self):
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_w]: self.Y -= 1
        if pressed[pygame.K_s]: self.Y += 1
        if pressed[pygame.K_a]: self.X -= 1
        if pressed[pygame.K_d]: self.X += 1

        self.PLAYER = pygame.Rect(self.X, self.Y, self.WIDTH, self.HEIGHT)

    def draw(self):
        # clear screen
        screen.fill((0,0,0))

        # draw HP bar
        self.HP_BAR = pygame.Rect(10, 10, self.HP * 3, 10)
        pygame.draw.rect(screen, (50,0,0), self.HP_BAR)

        # draw player
        pygame.draw.rect(screen, self.COLOR, self.PLAYER)

        pygame.display.flip()

    def remove_HP(self, value):
        for x in range(value):
            self.HP -= 1
            self.draw()
            # time.sleep(0.1)

p1 = Player()

while True:  

    for event in pygame.event.get():
        if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
            exit()

        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            td2 = threading.Thread(target = p1.remove_HP(20), name = "td2")
            td2.daemon = True
            td2.start()

    p1.move()
    p1.draw()

    clock.tick(60)

Я неправильно использую темы?Я хочу выполнить p1.remove_HP() и p1.move() одновременно, но программа выполняет следующие действия:

пользователь нажимает, нажимая [A]

1º: p1.move()

2º: p1 перестает двигаться

3º: p1.remove_HP()

4º: p1 снова движется

Извините, если это глупо, ноЯ действительно пытаюсь и учусь.Заранее спасибо!

1 Ответ

0 голосов
/ 03 декабря 2018

Вам не нужны темы вообще.Не усложняйте свою жизнь.

Вам просто нужно по-другому подумать о том, как работает ваша игра.Это работает в цикле;в вашем случае он работает на скорости 60 кадров в секунду.

Так что если вы хотите что-то делать со временем, у вас есть разные варианты:

1) Создайте переменную, увеличивайте ее каждый кадр, и как только она достигнет 60, вы знаете, что прошла 1 секунда (просто, но не надежно, так как вы зависите от постоянной частоты кадров)

2) Используйте события.В pygame вы можете создавать пользовательские события, которые вы можете запускать вручную или периодически, и обрабатывать их в своем основном цикле, как встроенные в Pygame события (работает хорошо для простых случаев использования, но количество событий, которые вы можете создать, ограничено)

3) Создайте переменную и сохраните в ней отметку времени.Временной отметкой может быть системное время или что-то еще, например, количество тактов с момента запуска вашей игры (например, с помощью pygame.time.get_ticks в pygame. Затем каждый кадр сравнивает его с текущим системным временем или тактами, чтобы вычислить, сколько времени прошло *).1012 *

Я немного обновил ваш код. Обратите внимание, как я разделил различные проблемы на разные части кода:

  • Класс игрока заботится только о себе (позиция, движение, hp), а не как весь экран управляется
  • Класс GUI заботится только о рисовании графического интерфейса
  • Основному циклу не важно, что находится на экране

Я просто уменьшаю hp чуть-чуть каждый кадр (в основном это вариант варианта 1, который я перечислил выше), это достаточно хороший подход к вашей проблеме.

#-*- coding-utf8 -*-
import pygame
import threading
import time
import os

os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.init()

SIZE = (1200, 600)
screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()

class GUI(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((1200, 600))
        self.image.set_colorkey((12,34,56))
        self.image.fill((12,34,56))
        self.rect = self.image.get_rect()
        self.player = None

    def update(self):
        self.image.fill((12,34,56))
        if self.player:
            pygame.draw.rect(self.image, (50, 0, 0), pygame.Rect(10, 10, self.player.hp * 3, 10))

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()

        self.image = pygame.Surface((50, 100))
        self.image.fill((255,255,0))
        self.rect = self.image.get_rect(topleft=(100, 100))

        self.hp = 100

    def update(self):
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_w]: self.rect.move_ip( 0, -1)
        if pressed[pygame.K_s]: self.rect.move_ip( 0,  1)
        if pressed[pygame.K_a]: self.rect.move_ip(-1,  0)
        if pressed[pygame.K_d]: self.rect.move_ip( 1,  0)

        self.hp -= 0.05

p1 = Player()
gui = GUI()
gui.player = p1
sprites = pygame.sprite.Group(p1, gui)

while True:  

    for event in pygame.event.get():
        if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
            exit()

    screen.fill((0,0,0))
    sprites.update()
    sprites.draw(screen)
    pygame.display.flip()
    clock.tick(60)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...