Помогите получить частоту кадров (fps) в Python + Pygame
Я работаю над маленькой карточной игрой для путешествий по миру, которую я представляю как нечто среднее между Bejeweled и настольными играми 10 Days geography. До сих пор кодирование шло хорошо, но частота кадров очень плохо... в настоящее время я получаю низкие 20 на моем Core 2 Duo. Это проблема, так как я создаю игру для мартовского конкурса разработчиков Intel, который прямо нацелен на нетбуки, упаковывающие недостаточно мощные процессоры Atom.
здесь экран от игра:
alt текст http://www.necessarygames.com/my_games/betraveled/betraveled-fps.png
Я очень новичок в Python и Pygame (это первое, для чего я их использовал), и мне, к сожалению, не хватает формального обучения CS... то есть я думаю, что в моем коде, вероятно, много плохих практик, и многое можно было бы оптимизировать. Если некоторые из вас старше Python руки не возражали бы взглянуть на мой код и посмотреть, если вы не можете найдите какие-либо очевидные области для оптимизации, я был бы чрезвычайно благодарен.
можно скачать исходный код здесь (Python 2.6 + Pygame 1.9): http://www.necessarygames.com/my_games/betraveled/betraveled_src0328.zip
скомпилированный exe здесь: www.necessarygames.com/my_games/betraveled/betraveled_src0328.zip
одна вещь, о которой я беспокоюсь, - это мой менеджер событий, который, как я чувствую, может иметь некоторую производительность целые в нем, и еще одна вещь-мой рендеринг... Я в значительной степени просто blitting все на экран все время (см. процедуры рендеринга в моем game_components.py ниже); недавно я узнал, что вы должны обновлять только области экрана, которые изменились, но я все еще туманен о том, как это было сделано... может ли это быть огромной проблемой производительности?
любые мысли очень ценятся! как обычно, я рад "чаевые" вам за ваше время и энергию через система paypal.
Иордания
EDIT:
Благодаря приведенному ниже совету я запустил cprofile в своем коде. Было бы здорово, если бы кто-нибудь захотел посмотреть на этот результат и сообщить мне, что есть и чего не следует ожидать.
вот результат п.strip_dirs().sort_stats('накопительный').print_stats():
pydev debugger: starting
Sun Mar 28 04:46:16 2010 cprofile
8383715 function calls (8264821 primitive calls) in 157.732 CPU seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 157.732 157.732 <string>:1(<module>)
1 0.000 0.000 157.732 157.732 main.py:47(main)
1 0.074 0.074 157.280 157.280 event_manager.py:101(run)
4911/2414 11.837 0.002 156.984 0.065 event_manager.py:32(post)
4786/4681 0.238 0.000 94.852 0.020 rooms.py:251(notify)
2187 0.523 0.000 51.136 0.023 rooms.py:329(render)
4911/2959 0.220 0.000 35.732 0.012 event_manager.py:54(notify)
2271 33.996 0.015 33.996 0.015 {pygame.display.update}
2271 0.060 0.000 23.664 0.010 app.py:178(paint)
37347/2271 1.580 0.000 23.587 0.010 container.py:83(paint)
70236/2271 3.609 0.000 23.448 0.010 theme.py:275(func)
1078950 16.926 0.000 16.926 0.000 {method 'blit' of 'pygame.Surface' objects}
2187 2.131 0.001 16.875 0.008 game_components.py:666(render)
19635/17756 0.187 0.000 13.852 0.001 game_components.py:641(notify)
733820 7.710 0.000 13.643 0.000 game_components.py:1151(notify)
2271 12.254 0.005 12.254 0.005 {pygame.time.wait}
64112 3.174 0.000 11.252 0.000 game_components.py:1186(render)
9 0.002 0.000 10.151 1.128 game_components.py:286(deal_new_board)
1934 0.095 0.000 8.489 0.004 app.py:144(event)
4359/2146 0.178 0.000 8.375 0.004 container.py:112(event)
2335/2146 0.056 0.000 8.251 0.004 widget.py:346(_event)
2335/2146 0.048 0.000 8.193 0.004 theme.py:320(func)
4883/4691 0.018 0.000 8.049 0.002 widget.py:313(send)
229 0.139 0.001 8.017 0.035 game_components.py:632(refresh_darkness)
7258 0.499 0.000 7.844 0.001 game_components.py:963(test_close_to_trip)
2271 7.378 0.003 7.378 0.003 {pygame.display.set_caption}
19347 3.313 0.000 6.687 0.000 game_components.py:928(get_next_to)
2187 1.529 0.001 6.629 0.003 game_components.py:130(render)
2011729 5.938 0.000 5.938 0.000 {isinstance}
3 0.000 0.000 5.906 1.969 my_gui.py:274(clicked)
219456 3.060 0.000 5.680 0.000 surface.py:5(subsurface)
1290 0.506 0.000 5.416 0.004 game_components.py:683(__init__)
8748 2.891 0.000 5.340 0.001 theme.py:400(render)
70236 2.232 0.000 4.945 0.000 theme.py:186(box)
1357 0.097 0.000 4.391 0.003 game_components.py:742(set_image)
9 0.054 0.006 3.450 0.383 game_components.py:209(deal_connection_matrix)
8748 0.325 0.000 3.318 0.000 theme.py:479(paint)
1051 0.015 0.000 3.262 0.003 game_components.py:1232(__init__)
386467 3.148 0.000 3.148 0.000 {method 'fill' of 'pygame.Surface' objects}
245332 2.470 0.000 3.117 0.000 game_components.py:495(get_card)
55761 3.068 0.000 3.068 0.000 {pygame.draw.aaline}
2271 2.968 0.001 2.968 0.001 {pygame.event.get}
9 0.007 0.001 2.946 0.327 game_components.py:416(clone)
2187 0.089 0.000 2.717 0.001 misc.py:28(paint)
803701 2.483 0.000 2.497 0.000 weakref.py:302(iterkeys)
2739 2.441 0.001 2.441 0.001 {pygame.imageext.load_extended}
1470 1.108 0.001 2.432 0.002 game_components.py:450(set_pos)
29 0.029 0.001 2.270 0.078 game_components.py:433(clear)
2 0.000 0.000 2.158 1.079 main.py:22(set_room)
4911/4862 0.027 0.000 2.141 0.000 main.py:37(notify)
1 0.000 0.000 2.099 2.099 my_gui.py:164(clicked)
1 0.001 0.001 2.099 2.099 rooms.py:117(__init__)
1120 0.039 0.000 1.978 0.002 game_components.py:484(place_card)
27 0.013 0.000 1.963 0.073 game_components.py:339(merge_board_stack)
311 0.018 0.000 1.939 0.006 game_components.py:443(remove)
125 0.007 0.000 1.848 0.015 rooms.py:18(notify)
224 0.003 0.000 1.806 0.008 game_components.py:721(clone)
219456 1.638 0.000 1.638 0.000 {method 'subsurface' of 'pygame.Surface' objects}
183 0.004 0.000 1.313 0.007 game_components.py:1240(__init__)
4374 0.106 0.000 1.224 0.000 button.py:97(paint)
46765 0.967 0.000 1.137 0.000 game_components.py:784(set_pos)
229 0.109 0.000 1.111 0.005 game_components.py:594(refresh_trip)
4076 1.076 0.000 1.076 0.000 {method 'convert_alpha' of 'pygame.Surface' objects}
9 0.015 0.002 1.018 0.113 game_components.py:542(displace_cards)
17496 0.360 0.000 0.953 0.000 basic.py:102(paint)
66299 0.948 0.000 0.948 0.000 {pygame.draw.rect}
1357 0.024 0.000 0.945 0.001 game_components.py:736(set_text)
1357 0.052 0.000 0.917 0.001 game_components.py:841(render_text_rec)
5815 0.455 0.000 0.881 0.000 game_components.py:1108(get_connections)
6610 0.869 0.000 0.869 0.000 {method 'replace' of 'pygame.PixelArray' objects}
56 0.001 0.000 0.861 0.015 game_components.py:1252(__init__)
10 0.001 0.000 0.857 0.086 game_components.py:377(__init__)
540 0.484 0.001 0.828 0.002 game_components.py:613(refresh_connections)
189431 0.730 0.000 0.730 0.000 game_components.py:500(test_index_on_board)
161329 0.632 0.000 0.727 0.000 matrix.py:33(__iter__)
309968 0.710 0.000 0.710 0.000 {method 'get_width' of 'pygame.Surface' objects}
308567 0.675 0.000 0.675 0.000 {method 'get_height' of 'pygame.Surface' objects}
109626 0.646 0.000 0.670 0.000 style.py:18(__getattr__)
241697 0.646 0.000 0.646 0.000 matrix.py:24(getitem)
21084 0.601 0.000 0.601 0.000 {method 'render' of 'pygame.font.Font' objects}
327 0.006 0.000 0.580 0.002 game_components.py:490(place_card_first_time)
26 0.001 0.000 0.561 0.022 game_components.py:1259(__init__)
166 0.002 0.000 0.536 0.003 game_components.py:608(get_longest_trip)
1491/166 0.075 0.000 0.534 0.003 game_components.py:989(get_longest_trip)
5702 0.533 0.000 0.533 0.000 {method 'size' of 'pygame.font.Font' objects}
1 0.000 0.000 0.478 0.478 game_components.py:141(__init__)
1 0.001 0.001 0.478 0.478 game_components.py:165(rebuild)
67 0.005 0.000 0.457 0.007 game_components.py:713(change_size)
1 0.001 0.001 0.420 0.420 game_components.py:347(change_card_size)
1210/166 0.044 0.000 0.412 0.002 game_components.py:982(add_to_trip)
7654 0.275 0.000 0.405 0.000 game_components.py:938(get_bounding_box)
14969 0.101 0.000 0.385 0.000 game_components.py:1305(render)
149709 0.341 0.000 0.341 0.000 {method 'append' of 'list' objects}
87958 0.341 0.000 0.341 0.000 {hasattr}
1362 0.068 0.000 0.336 0.000 textrect.py:12(render_textrect)
30 0.001 0.000 0.301 0.010 game_components.py:1282(__init__)
47795 0.257 0.000 0.257 0.000 game_components.py:1024(test_connection)
14849 0.098 0.000 0.251 0.000 my_gui.py:209(notify)
17498 0.158 0.000 0.242 0.000 basic.py:22(is_color)
87480 0.224 0.000 0.224 0.000 {method 'set_clip' of 'pygame.Surface' objects}
9 0.003 0.000 0.209 0.023 game_components.py:279(deal_to_blank_squares)
1 0.114 0.114 0.208 0.208 {pygame.display.set_mode}
56617 0.206 0.000 0.206 0.000 game_components.py:837(get_center)
84 0.005 0.000 0.206 0.002 rooms.py:110(render)
здесь вывод п.strip_dirs().sort_stats ("время").print_stats():
Sun Mar 28 04:46:16 2010 cprofile
8383715 function calls (8264821 primitive calls) in 157.732 CPU seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
2271 33.996 0.015 33.996 0.015 {pygame.display.update}
1078950 16.926 0.000 16.926 0.000 {method 'blit' of 'pygame.Surface' objects}
2271 12.254 0.005 12.254 0.005 {pygame.time.wait}
4911/2414 11.837 0.002 156.984 0.065 event_manager.py:32(post)
733820 7.710 0.000 13.643 0.000 game_components.py:1151(notify)
2271 7.378 0.003 7.378 0.003 {pygame.display.set_caption}
2011729 5.938 0.000 5.938 0.000 {isinstance}
70236/2271 3.609 0.000 23.448 0.010 theme.py:275(func)
19347 3.313 0.000 6.687 0.000 game_components.py:928(get_next_to)
64112 3.174 0.000 11.252 0.000 game_components.py:1186(render)
386467 3.148 0.000 3.148 0.000 {method 'fill' of 'pygame.Surface' objects}
55761 3.068 0.000 3.068 0.000 {pygame.draw.aaline}
219456 3.060 0.000 5.680 0.000 surface.py:5(subsurface)
2271 2.968 0.001 2.968 0.001 {pygame.event.get}
8748 2.891 0.000 5.340 0.001 theme.py:400(render)
803701 2.483 0.000 2.497 0.000 weakref.py:302(iterkeys)
245332 2.470 0.000 3.117 0.000 game_components.py:495(get_card)
2739 2.441 0.001 2.441 0.001 {pygame.imageext.load_extended}
70236 2.232 0.000 4.945 0.000 theme.py:186(box)
2187 2.131 0.001 16.875 0.008 game_components.py:666(render)
219456 1.638 0.000 1.638 0.000 {method 'subsurface' of 'pygame.Surface' objects}
37347/2271 1.580 0.000 23.587 0.010 container.py:83(paint)
2187 1.529 0.001 6.629 0.003 game_components.py:130(render)
1470 1.108 0.001 2.432 0.002 game_components.py:450(set_pos)
4076 1.076 0.000 1.076 0.000 {method 'convert_alpha' of 'pygame.Surface' objects}
46765 0.967 0.000 1.137 0.000 game_components.py:784(set_pos)
66299 0.948 0.000 0.948 0.000 {pygame.draw.rect}
6610 0.869 0.000 0.869 0.000 {method 'replace' of 'pygame.PixelArray' objects}
189431 0.730 0.000 0.730 0.000 game_components.py:500(test_index_on_board)
309968 0.710 0.000 0.710 0.000 {method 'get_width' of 'pygame.Surface' objects}
308567 0.675 0.000 0.675 0.000 {method 'get_height' of 'pygame.Surface' objects}
109626 0.646 0.000 0.670 0.000 style.py:18(__getattr__)
241697 0.646 0.000 0.646 0.000 matrix.py:24(getitem)
161329 0.632 0.000 0.727 0.000 matrix.py:33(__iter__)
21084 0.601 0.000 0.601 0.000 {method 'render' of 'pygame.font.Font' objects}
5702 0.533 0.000 0.533 0.000 {method 'size' of 'pygame.font.Font' objects}
2187 0.523 0.000 51.136 0.023 rooms.py:329(render)
1290 0.506 0.000 5.416 0.004 game_components.py:683(__init__)
7258 0.499 0.000 7.844 0.001 game_components.py:963(test_close_to_trip)
540 0.484 0.001 0.828 0.002 game_components.py:613(refresh_connections)
5815 0.455 0.000 0.881 0.000 game_components.py:1108(get_connections)
17496 0.360 0.000 0.953 0.000 basic.py:102(paint)
149709 0.341 0.000 0.341 0.000 {method 'append' of 'list' objects}
87958 0.341 0.000 0.341 0.000 {hasattr}
8748 0.325 0.000 3.318 0.000 theme.py:479(paint)
7654 0.275 0.000 0.405 0.000 game_components.py:938(get_bounding_box)
47795 0.257 0.000 0.257 0.000 game_components.py:1024(test_connection)
4786/4681 0.238 0.000 94.852 0.020 rooms.py:251(notify)
87480 0.224 0.000 0.224 0.000 {method 'set_clip' of 'pygame.Surface' objects}
4911/2959 0.220 0.000 35.732 0.012 event_manager.py:54(notify)
56617 0.206 0.000 0.206 0.000 game_components.py:837(get_center)
1 0.200 0.200 0.200 0.200 {pygame.base.quit}
19635/17756 0.187 0.000 13.852 0.001 game_components.py:641(notify)
1 0.184 0.184 0.184 0.184 {pygame.base.init}
4359/2146 0.178 0.000 8.375 0.004 container.py:112(event)
17498 0.158 0.000 0.242 0.000 basic.py:22(is_color)
1358 0.151 0.000 0.151 0.000 {pygame.transform.smoothscale}
229 0.139 0.001 8.017 0.035 game_components.py:632(refresh_darkness)
1 0.114 0.114 0.208 0.208 {pygame.display.set_mode}
37862 0.112 0.000 0.112 0.000 {method 'set_alpha' of 'pygame.Surface' objects}
6561 0.111 0.000 0.195 0.000 button.py:236(paint)
229 0.109 0.000 1.111 0.005 game_components.py:594(refresh_trip)
4374 0.106 0.000 1.224 0.000 button.py:97(paint)
14969 0.101 0.000 0.385 0.000 game_components.py:1305(render)
14849 0.098 0.000 0.251 0.000 my_gui.py:209(notify)
1357 0.097 0.000 4.391 0.003 game_components.py:742(set_image)
24072 0.096 0.000 0.096 0.000 game_components.py:913(test_pos_on_card)
4926 0.095 0.000 0.132 0.000 game_components.py:1292(__init__)
33286 0.095 0.000 0.095 0.000 {range}
1934 0.095 0.000 8.489 0.004 app.py:144(event)
2187 0.089 0.000 2.717 0.001 misc.py:28(paint)
2135 0.087 0.000 0.091 0.000 matrix.py:21(setitem)
4374 0.076 0.000 0.131 0.000 button.py:182(paint)
1491/166 0.075 0.000 0.534 0.003 game_components.py:989(get_longest_trip)
1 0.074 0.074 157.280 157.280 event_manager.py:101(run)
301 0.069 0.000 0.107 0.000 game_components.py:508(clear_selection)
1362 0.068 0.000 0.336 0.000 textrect.py:12(render_textrect)
2227 0.066 0.000 0.150 0.000 game_components.py:809(move)
5740 0.062 0.000 0.165 0.000 misc.py:34(__setattr__)
2271 0.060 0.000 23.664 0.010 app.py:178(paint)
2335/2146 0.056 0.000 8.251 0.004 widget.py:346(_event)
4786 0.055 0.000 0.099 0.000 game_components.py:97(notify)
9 0.054 0.006 3.450 0.383 game_components.py:209(deal_connection_matrix)
1357 0.052 0.000 0.917 0.001 game_components.py:841(render_text_rec)
5 0.052 0.010 0.052 0.010 {method 'convert' of 'pygame.Surface' objects}
2335/2146 0.048 0.000 8.193 0.004 theme.py:320(func)
1210/166 0.044 0.000 0.412 0.002 game_components.py:982(add_to_trip)
1120 0.039 0.000 1.978 0.002 game_components.py:484(place_card)
2871/465 0.037 0.000 0.070 0.000 container.py:77(reupdate)
11862 0.037 0.000 0.037 0.000 {method 'collidepoint' of 'pygame.Rect' objects}
13602/13558 0.035 0.000 0.035 0.000 {len}
4493 0.035 0.000 0.047 0.000 button.py:71(__setattr__)
Вот некоторые биты источника:
Main.py
#Remote imports
import pygame
from pygame.locals import *
#Local imports
import config
import rooms
from event_manager import *
from events import *
class RoomController(object):
"""Controls which room is currently active (eg Title Screen)"""
def __init__(self, screen, ev_manager):
self.room = None
self.screen = screen
self.ev_manager = ev_manager
self.ev_manager.register_listener(self)
self.room = self.set_room(config.room)
def set_room(self, room_const):
#Unregister old room from ev_manager
if self.room:
self.room.ev_manager.unregister_listener(self.room)
self.room = None
#Set new room based on const
if room_const == config.TITLE_SCREEN:
return rooms.TitleScreen(self.screen, self.ev_manager)
elif room_const == config.GAME_MODE_ROOM:
return rooms.GameModeRoom(self.screen, self.ev_manager)
elif room_const == config.GAME_ROOM:
return rooms.GameRoom(self.screen, self.ev_manager)
elif room_const == config.HIGH_SCORES_ROOM:
return rooms.HighScoresRoom(self.screen, self.ev_manager)
def notify(self, event):
if isinstance(event, ChangeRoomRequest):
if event.game_mode:
config.game_mode = event.game_mode
self.room = self.set_room(event.new_room)
def render(self, surface):
self.room.render(surface)
#Run game
def main():
pygame.init()
screen = pygame.display.set_mode(config.screen_size)
ev_manager = EventManager()
spinner = CPUSpinnerController(ev_manager)
room_controller = RoomController(screen, ev_manager)
pygame_event_controller = PyGameEventController(ev_manager)
spinner.run()
# this runs the main function if this script is called to run.
# If it is imported as a module, we don't run the main function.
if __name__ == "__main__":
main()
event_manager.py
#Remote imports
import pygame
from pygame.locals import *
#Local imports
import config
from events import *
def debug( msg ):
print "Debug Message: " + str(msg)
class EventManager:
#This object is responsible for coordinating most communication
#between the Model, View, and Controller.
def __init__(self):
from weakref import WeakKeyDictionary
self.listeners = WeakKeyDictionary()
self.eventQueue= []
self.gui_app = None
#----------------------------------------------------------------------
def register_listener(self, listener):
self.listeners[listener] = 1
#----------------------------------------------------------------------
def unregister_listener(self, listener):
if listener in self.listeners:
del self.listeners[listener]
#----------------------------------------------------------------------
def post(self, event):
if isinstance(event, MouseButtonLeftEvent):
debug(event.name)
#NOTE: copying the list like this before iterating over it, EVERY tick, is highly inefficient,
#but currently has to be done because of how new listeners are added to the queue while it is running
#(eg when popping cards from a deck). Should be changed. See: http://dr0id.homepage.bluewin.ch/pygame_tutorial08.html
#and search for "Watch the iteration"
for listener in list(self.listeners):
#NOTE: If the weakref has died, it will be
#automatically removed, so we don't have
#to worry about it.
listener.notify(event)
#------------------------------------------------------------------------------
class PyGameEventController:
"""..."""
def __init__(self, ev_manager):
self.ev_manager = ev_manager
self.ev_manager.register_listener(self)
self.input_freeze = False
#----------------------------------------------------------------------
def notify(self, incoming_event):
if isinstance(incoming_event, UserInputFreeze):
self.input_freeze = True
elif isinstance(incoming_event, UserInputUnFreeze):
self.input_freeze = False
elif isinstance(incoming_event, TickEvent):
#Share some time with other processes, so we don't hog the cpu
pygame.time.wait(5)
#Handle Pygame Events
for event in pygame.event.get():
#If this event manager has an associated PGU GUI app, notify it of the event
if self.ev_manager.gui_app:
self.ev_manager.gui_app.event(event)
#Standard event handling for everything else
ev = None
if event.type == QUIT:
ev = QuitEvent()
elif event.type == pygame.MOUSEBUTTONDOWN and not self.input_freeze:
if event.button == 1: #Button 1
pos = pygame.mouse.get_pos()
ev = MouseButtonLeftEvent(pos)
elif event.type == pygame.MOUSEMOTION:
pos = pygame.mouse.get_pos()
ev = MouseMoveEvent(pos)
#Post event to event manager
if ev:
self.ev_manager.post(ev)
#------------------------------------------------------------------------------
class CPUSpinnerController:
def __init__(self, ev_manager):
self.ev_manager = ev_manager
self.ev_manager.register_listener(self)
self.clock = pygame.time.Clock()
self.cumu_time = 0
self.keep_going = True
#----------------------------------------------------------------------
def run(self):
if not self.keep_going:
raise Exception('dead spinner')
while self.keep_going:
time_passed = self.clock.tick()
fps = self.clock.get_fps()
self.cumu_time += time_passed
self.ev_manager.post(TickEvent(time_passed, fps))
if self.cumu_time >= 1000:
self.cumu_time = 0
self.ev_manager.post(SecondEvent())
pygame.quit()
#----------------------------------------------------------------------
def notify(self, event):
if isinstance(event, QuitEvent):
#this will stop the while loop from running
self.keep_going = False
rooms.py
#Remote imports
import pygame
#Local imports
import config
import continents
from game_components import *
from my_gui import *
from pgu import high
class Room(object):
def __init__(self, screen, ev_manager):
self.screen = screen
self.ev_manager = ev_manager
self.ev_manager.register_listener(self)
def notify(self, event):
if isinstance(event, TickEvent):
pygame.display.set_caption('FPS: ' + str(int(event.fps)))
self.render(self.screen)
pygame.display.update()
def get_highs_table(self):
fname = 'high_scores.txt'
highs_table = None
config.all_highs = high.Highs(fname)
if config.game_mode == config.TIME_CHALLENGE:
if config.difficulty == config.EASY:
highs_table = config.all_highs['time_challenge_easy']
if config.difficulty == config.MED_DIF:
highs_table = config.all_highs['time_challenge_med']
if config.difficulty == config.HARD:
highs_table = config.all_highs['time_challenge_hard']
if config.difficulty == config.SUPER:
highs_table = config.all_highs['time_challenge_super']
elif config.game_mode == config.PLAN_AHEAD:
pass
return highs_table
class TitleScreen(Room):
def __init__(self, screen, ev_manager):
Room.__init__(self, screen, ev_manager)
self.background = pygame.image.load('assets/images/interface/background.jpg').convert()
#Initialize
#---------------------------------------
self.gui_form = gui.Form()
self.gui_app = gui.App(config.gui_theme)
self.ev_manager.gui_app = self.gui_app
c = gui.Container(align=0,valign=0)
#Quit Button
#---------------------------------------
b = StartGameButton(ev_manager=self.ev_manager)
c.add(b, 0, 0)
self.gui_app.init(c)
def render(self, surface):
surface.blit(self.background, (0, 0))
#GUI
self.gui_app.paint(surface)
class GameModeRoom(Room):
def __init__(self, screen, ev_manager):
Room.__init__(self, screen, ev_manager)
self.background = pygame.image.load('assets/images/interface/background.jpg').convert()
self.create_gui()
#Create pgu gui elements
def create_gui(self):
#Setup
#---------------------------------------
self.gui_form = gui.Form()
self.gui_app = gui.App(config.gui_theme)
self.ev_manager.gui_app = self.gui_app
c = gui.Container(align=0,valign=-1)
#Mode Relaxed Button
#---------------------------------------
b = GameModeRelaxedButton(ev_manager=self.ev_manager)
self.b = b
print b.rect
3 ответов
пусть события приходят к вам с события.ждать
вам действительно нужно обрабатывать каждый тик? Если нет, используйте pygame.event.wait
для вашего цикла событий только обрабатывать, когда событие приходит, и pygame.time.set_timer
Если вам нужны периодические события, как ваш SecondEvent
.
это означает, что вы не будете рисовать много кадров в течение секунд, когда события не приходят, но это нормально. Использование события.ожидание уменьшит использование ЦП и позволит вам все еще быть отзывчивым, и, вероятно, устраняет необходимость на время.подождите, у вас там вместо этого.
не перерисовывайте всю доску с нуля каждый тик
нет места.рендер Блит фон каждый раз, что означает, что он должен пройти и повторно нарисовать всю доску и все карты. Сделай это один раз. Тогда у карт не будет повторного рендеринга, если они не изменили темноту или не двигаются.
когда карты двигаются, вы должны быть в состоянии восстановить фон, blitting просто кусок фоновой графики вместо всего этого.
передайте список прямоугольников в display.update
как только вы обновляете только определенные области, вы можете передать эти области в display.update
поэтому ему не нужно обновлять весь экран. Например, см. код Solarwolf и как он отмечает грязные прямоугольники.
в результатах вашего профиля:
недавно я узнал, что вы должны обновлять только те области экрана, которые изменились, но я все еще туманен о том, как это произошло... может ли это быть огромной проблемой производительности?
Да. display.update
и Surface.blit
находятся в верхней части результатов вашего профиля. Вы сделали более миллиона блитов, примерно за 5000 тиков, что составляет 200 блитов каждый тик.
кроме того, шестой по результатам вашего профиля display.set_caption
, который, я думаю, является отображением самого счетчика FPS? В 7 секунд 157 это не ваша основная точка доступа, но все же интересно знать.
Я бы сказал, что простое ожидание 5-10ms достаточно, чтобы серьезно снизить использование процессора, который постоянно рендеринг причины экрана.