python - 如何在 Python + Pygame 中提高帧率 (fps)?

标签 python performance pygame frame-rate

我正在开发一款小型卡片交换世界旅行游戏,我将其设想为 gem 迷阵和 10 天地理棋盘游戏的混合体。到目前为止,编码一直没问题,但帧率非常糟糕……目前我的 Core 2 Duo 的帧率已经降到 20 多岁了。这是一个问题,因为我正在为英特尔 3 月的开发者竞赛创建游戏,该竞赛直接针对搭载动力不足的 Atom 处理器的上网本。

这是游戏的屏幕:

alt text
(来源:necessarygames.com)

我是 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“打赏”您的时间和精力。

乔丹



编辑: 多亏了下面的建议,我对我的代码运行了 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__)





以下是部分来源:

主.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            

房间.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

最佳答案

让事件通过 event.wait 来找你

您真的需要在每次报价时都进行处理吗?如果不是,请使用 pygame.event.wait让你的事件循环只在事件进入时处理,并且pygame.time.set_timer如果您需要像 SecondEvent 这样的周期性事件.

这意味着您不会在没有事件进入的几秒钟内绘制很多帧,但这没关系。使用 event.wait 会降低 CPU 使用率并让您仍然保持响应,并且可能会消除对 time.wait 的需求。

不要每次都从头开始重新绘制整个棋盘

不要让 Room.render 每次都 blit 背景,这意味着它必须重新绘制整个棋盘和所有卡片。这样做一次。然后不要让卡片重新渲染自己,除非它们改变了黑暗或正在移动。

当牌在移动时,您应该能够通过只传送背景图形的一部分而不是整个图形来恢复背景。

将矩形列表传递给 display.update

一旦您只更新某些区域,您可以将这些区域传递给 display.update所以它不必更新整个屏幕。例如,see the Solarwolf code以及它如何标记脏矩形。

关于python - 如何在 Python + Pygame 中提高帧率 (fps)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2530478/

相关文章:

Python 与 Perl : performance reading a gzipped file

android - 如何在android中显示数学符号、物理、化学方程式?

python - Pygame 错误未显示缩放图像

python - 用Python 3编写iOS游戏的最佳库是什么?

python - pygame听觉和视觉正弦波

python - 如何在python中提取两个不同标签之间的html?

python - 如何在从 cmd 提示符打开时将变量输入到 python 脚本中?

mysql - 优化凌乱的查询

python - 使用 Shell 脚本在 mySQL Workbench 模型中添加列

Python理论——不使用len函数的列表比较