Есть ли способ скопировать определенный участок поверхности с помощью Surface.copy ()? - PullRequest
2 голосов
/ 03 мая 2019

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

Я посмотрел документацию для Surface.copy (), но она не принимает аргументов, и я не смог найти ничего похожего, кроме pygame.pixelcopy ()что из того, что я понимаю, не то, что я ищу.Если Surface.copy () не то, что я ищу, пожалуйста, дайте мне знать об альтернативах.

import pygame, time
pygame.init()
screen = pygame.display.set_mode((500, 500))

screen.fill((128, 128, 128))
pygame.display.update()

#immagine a complex pattern being blit to the screen here
pygame.draw.rect(screen, (128, 0, 0), (0, 0, 50, 50))
pygame.draw.rect(screen, (0, 128, 0), (50, 0, 50, 50))
pygame.draw.rect(screen, (0, 0, 128), (200, 0, 50, 50))

#my complex background area that i want to save ()
area_to_save = pygame.Rect(0, 0, 100, 50)

rest_of_background = pygame.Rect(200, 0, 50, 50)

#updating for demo purposes
dirty_rects = [area_to_save, rest_of_background]
for rect in dirty_rects:
    pygame.display.update(rect)
temp_screen = screen.copy()

time.sleep(3)
#after some events happen and I draw the item thats being animated onto the background
item_to_animate = pygame.Rect(35, 10, 30, 30)
pygame.draw.rect(screen, (0, 0, 0), item_to_animate)
pygame.display.update(item_to_animate)

time.sleep(3)
item_to_animate = pygame.Rect(50, 60, 30, 30)
pygame.draw.rect(screen, (0, 0, 0), item_to_animate)
#now that the item has moved, draw back old frame, which draws over the whole surface
screen.blit(temp_screen, (0, 0))
pygame.display.update()

#I understand swapping the drawing of the new item location to after temp_surface blit
#will provide me the desired outcome in this scenario but this is a compressed version of my problem
#so for simplicity sake, is there a way of not saving the whole surface, only those rects defined?

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

PS: я новичок в этом сайте, дайте мне знать, если я что-то не так сделал, пожалуйста!

Редактировать: для всех, кто интересуется, является ли это решение (сохранения фона перед перетаскиванием элемента поверх него и затем перерисовки сохраненного фона до того, как переместится местоположение нового элемента) более эффективным, чем перерисовка всего фона и затем перетаскивание элемента с использованиемпростая квадратная анимация на клетчатом узоре с перерисовкой всего фона каждый раз уменьшала мои общие fps примерно на 50% с 1000 (до перерисовки фона) до 500 в среднем.При использовании грязных каналов и вышеописанного метода я получаю около 900 кадров в секунду.

Ответы [ 2 ]

0 голосов
/ 03 мая 2019

То, что вы хотите сделать, может быть достигнуто с помощью pygame.Surface.blit().

Создайте поверхность с заданным размером и blit область экрана к этой поверхности. Обратите внимание, что третий аргумент bilt является необязательным параметром, который выбирает прямоугольную область поверхности источника:

# create a surface with size 'area_to_save.size'
temp_screen = pygame.Surface(area_to_save.size)

# blit the rectangular area 'area_to_save' from 'screen' to 'temp_screen' at (0, 0) 
temp_screen.blit(screen, (0, 0), area_to_save) 
0 голосов
/ 03 мая 2019

Вы можете использовать subsurface, чтобы указать область, которую вы хотите скопировать, а затем вызвать copy для возвращенных Surface.

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

Также обратите внимание, что вы никогда не должны использовать time.sleep в своей игре.Пока sleep блокирует процесс вашей игры, ваша игра не может обрабатывать события, поэтому вы, например, не можете выйти из игры в это время.Также может случиться, что окно вашей игры просто не будет перерисовано, если вы не обрабатываете события, вызывая pygame.event.get;и как только очередь событий заполняется, потому что вы никогда не звоните pygame.event.get, ваша игра зависнет.

...