Я делаю игру на python и pygame, и, поскольку моя игра включает в себя очень много спрайтов, я решил использовать отдельный поток для каждого вражеского \ персонажа, который запускает метод _mainloop. Я только начал с этого, и у меня возникла проблема. Я делаю базовый класс, который рисует крупье и пока может перемещаться по координатам X. он работает почти идеально, но проблема в том, что я думаю, что, поскольку крупье рисуется в методе класса _mainloop, и отображение обновляется в основном цикле обработки событий, из-за чего крупье иногда выглядит намного толще, что является немного странно. Я не хочу обновлять дисплей в _mainloop, потому что на экране будет около FPS * врагов + игроков, что может работать примерно до 500 pygame.display.updates в секунду, что немного перебор. Если кто-нибудь знает лучший способ сделать это, вы можете мне сказать? пожалуйста?
Я прочитал это:
Многопоточность Pygame
Многопоточность с Pygame
это не имеет отношения к моему вопросу. Я действительно ничего не мог найти на нем.
Вот мой код:
from random import randint
import threading
from pygame.locals import *
import pygame as pg
FPS = 60
CLOCK = pg.time.Clock()
COLOURS = {
'beige': (232, 202, 145),
'green': (0, 128, 0),
'blue': (0, 0, 128),
'red': (128, 0, 0),
'dark red': (255, 0, 0),
'dark blue': (0, 0, 255),
'dark green': (0, 255, 0),
'black': (0, 0, 0),
'aqua': (0, 255, 255),
'white': (255, 255, 255),
'teal': (0, 128, 128),
'purple': (128, 128, 0),
'dark purple': (255, 255, 0),
'yellow': (255, 255, 0),
'silver': (192, 192, 192),
'gold': (192, 192, 96),
'gray': (211, 211, 211),
}
class CharacterImage:
"""
this is a sprite that at this point, should really
just be able to move around.
"""
# lots of methods and properties and stuff
...
def build_image(self, surface):
"""
constructs and draws the stickman to the
screen.
"""
# really big function
...
def move_to(self, pos: 'x', surface, pixels=1):
"""
moves the character image by pixels
towards the destination.
INCOMPLETE: only X coordinates are supported
"""
current = self.topleft[0]
direction = 'b' if pos < current else 'f'
current_pos = current - pixels if direction == 'b' else current + pixels
self.update_coords((current_pos, self.topleft[1]))
self.build_image(surface)
return current_pos
def start_thread(self, pos, surface, pixels=1):
a = threading.Thread(target=lambda: self._mainloop(pos, surface, pixels), daemon=True)
self.mainthread = a
a.start()
def _mainloop(self, pos, surface, pixels, *args, **kwargs):
new_pos = pos
while self.topleft != new_pos:
new_pos = self.move_to(pos, surface, pixels, *args, **kwargs)
CLOCK.tick(FPS)
class WeaponDummy:
... # random code
def main():
a = pg.display.set_mode((800, 400))
testsurf = pg.surface.Surface((2, 2))
testsurf.fill(COLOURS['green'])
s = CharacterImage('test', WeaponDummy(testsurf), (10, 300))
d = CharacterImage('test', WeaponDummy(testsurf), (10, 320))
s.build_image(a)
d.build_image(a)
d.start_thread(880, a)
s.start_thread(880, a)
while True:
for i in pg.event.get():
if i.type == QUIT:
pg.quit()
raise Exception
pg.display.update()
a.fill(COLOURS['black'])
print('updated')
CLOCK.tick(FPS)
if __name__ == '__main__':
main()
если вам нужен полный код, который можно запустить, вы можете получить его здесь
любая помощь будет оценена по достоинству. большое спасибо!
Очень странно, что консоль вошла в updated только после того, как персонаж ушел. со мной это не так. То, что персонаж ушел за экран, - это всего лишь небольшая проблема с областью вокруг pos = new_pos. я могу это исправить. Что касается визуальных ошибок, просто они кажутся немного мерцающими, и я нахожу это раздражающим, но если вы думаете, что это даже не заметно, то, вероятно, это нормально. Благодарность!






Я запустил ваш код и не заметил никаких визуальных ошибок. Я заметил, что фигура полностью исчезла с экрана, прежде чем консоль зарегистрировала «обновлено» один раз.
pg.display.update()иCLOCK.tick(FPS)также не стреляют, пока не отойдут. Это имеет смысл для вас, исходя из того, как написан ваш код, не так ли? Это желательно?