Помогите увеличить частоту кадров (fps) в Python + Pygame - PullRequest
10 голосов
/ 27 марта 2010

Я работаю над маленькой карточной игрой в мир путешествий, которую я представляю себе как нечто среднее между Bejeweled и 10-дневной настольной игрой по географии. Пока что кодирование идет хорошо, но частота кадров довольно плохая ... в настоящее время я получаю низкие 20 на моем Core 2 Duo. Это проблема, так как я создаю игру для мартовского конкурса разработчиков Intel, которая нацелена на нетбуки с процессорами Atom.

Вот экран из игры :

альтернативный текст 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

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

Любые мысли очень ценятся! Как обычно, я рад сообщить вам за ваше время и энергию через PayPal.

Иордания



EDIT: Благодаря приведенному ниже совету я запустил cprofile для своего кода. Было бы здорово, если бы кто-нибудь захотел взглянуть на этот вывод и сообщить мне, что есть, а чего нет.



Вот вывод p.strip_dirs (). Sort_stats ('cumulative'). 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)

Вот вывод p.strip_dirs (). Sort_stats ('time'). 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__)





Вот несколько битов из источника:

* ** 1054 1055 * Main.py * ** 1056 1057 *
#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 * ** 1066 1067 * #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 ]

7 голосов
/ 27 марта 2010

Пусть события приходят к вам с event.wait

Вам действительно нужно обрабатывать каждый тик? Если нет, используйте pygame.event.wait, чтобы цикл обработки событий обрабатывался только при наступлении события, и pygame.time.set_timer, если вам нужны периодические события, такие как SecondEvent.

.

Это означает, что вы не будете рисовать много кадров в течение секунд, когда события не поступают, но это нормально. Использование event.wait уменьшит загрузку процессора и позволит вам по-прежнему реагировать, и, скорее всего, устранит необходимость использования времени. Wait у вас там.

Не перерисовывайте всю доску с нуля каждый тик

Не заставляйте Room.render каждый раз краснеть фон, а это значит, что он должен пройти и заново нарисовать всю доску и все карты. Сделай это один раз. Тогда не заставляйте карты перерисовывать себя, если они не изменили тьму или не двигаются.

Когда карты движутся, вы сможете восстановить фон, стряхивая только кусок фонового изображения вместо всего этого.

Передать список прямоугольников в display.update

Как только вы обновляете только определенные области, вы можете передать эти области на display.update, чтобы не обновлять весь экран. Например, см. Код Solarwolf и как он отмечает грязные прямоугольники.

2 голосов
/ 27 марта 2010

В вашем профиле результатов:

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

Да. display.update и Surface.blit вверху результатов вашего профиля. Вы сделали более миллиона блитов, примерно за 5000 тиков, что составляет 200 блитов за каждый тик.

Кроме того, шестой результат в вашем профиле - display.set_caption, который, как мне кажется, отображает сам счетчик FPS? На 7 секундах 157 это не ваша главная горячая точка, но все же интересно знать.

0 голосов
/ 28 ноября 2013

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

...