2010-03-27 4 views
9

Sto lavorando a un piccolo gioco di scambio di carte che immagino come un incrocio tra Bejeweled ei giochi da tavolo di geografia 10 giorni. Finora la codifica è andata a posto, ma il frame rate è piuttosto scadente ... attualmente sto ottenendo dei bassi 20 sul mio Core 2 Duo. Questo è un problema dal momento che sto creando il gioco per la concorrenza degli sviluppatori Intel di marzo, che è diretta ai netbook con processori Atom sottodimensionati.Aiuto per ottenere frame rate (fps) in Python + Pygame

Ecco una schermata dal gioco:

alt text http://www.necessarygames.com/my_games/betraveled/betraveled-fps.png

Sono molto nuovo a Python e Pygame (questa è la prima cosa che ho li ho usato per), e sto decisamente carente in contesti formali Addestramento CS ... il che significa che penso che ci siano probabilmente MOLTE pratiche sbagliate in corso nel mio codice e MOLTA che potrebbero essere ottimizzate. Se qualcuno di voi più anziani con le mani di Python non si preoccupasse di dare un'occhiata al mio codice e vedere se non è possibile trovare aree ovvie per l'ottimizzazione, sarei estremamente grato.

È possibile scaricare il codice sorgente completo qui (Python 2.6 + Pygame 1.9): http://www.necessarygames.com/my_games/betraveled/betraveled_src0328.zip

Compilato exe qui: www.necessarygames.com/my_games/betraveled/betraveled_src0328.zip

Una cosa di cui sono preoccupato è il mio gestore di eventi, che ritengo possa avere alcuni insiemi di prestazioni, e un'altra cosa è il mio rendering ... Sto praticamente bloggando tutto sullo schermo tutto il tempo (vedi rendering routine nel mio game_components.py b elow); Recentemente ho scoperto che dovresti solo aggiornare le aree dello schermo che sono cambiate, ma sono ancora annebbiato su come è stato realizzato esattamente ... potrebbe essere un enorme problema di prestazioni?

Ogni pensiero è molto apprezzato! Come al solito, sono felice di "darti la mancia" per il tuo tempo e la tua energia tramite PayPal.

Jordan



EDIT: grazie ai consigli di seguito, mi sono imbattuto cprofile sul mio codice. Sarebbe bello se qualcuno fosse disposto a guardare questo output e farmi sapere cosa è e cosa non ci si può aspettare.



Qui è l'uscita di p.strip_dirs() sort_stats ('cumulativo') 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) 

Qui è l'uscita del p.strip_dirs () .sort_stats ('tempo') 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__) 





Ecco alcuni bit della fonte:

principale.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 
+2

Si potrebbe voler eseguire un profiler (la libreria standard Python ne ha alcuni, ad esempio il modulo 'profile') e pubblicare le parti del codice che occupano più tempo. Così com'è, pochi si preoccuperanno di leggere tutto quel codice. –

+1

@Max Shawabkeh, 'cProfile' è una sostituzione drop-in per' profile' con meno overhead di profiler. –

+0

Grazie per il gentile consiglio Max! Nella mia ignoranza non ero nemmeno stato a conoscenza dell'esistenza di questi strumenti di profilazione. Ho fatto quello che mi hai suggerito e ho pubblicato le statistiche sopra. Se tu o qualcun altro potessi aiutarmi a dare un senso a loro, sarebbe fantastico! –

risposta

7

lasciare che gli eventi vengono a voi con event.wait

Hai davvero bisogno di elaborare ogni tick? In caso contrario, utilizzare pygame.event.wait affinché il loop eventi venga elaborato solo quando arriva un evento e pygame.time.set_timer se sono necessari eventi periodici come lo SecondEvent.

Ciò significa che non verranno disegnati molti fotogrammi durante i secondi in cui gli eventi non arrivano, ma va bene. L'uso di event.wait ridurrà l'utilizzo della CPU e ti consentirà comunque di essere reattivo e probabilmente rimuoverà la necessità del tempo.

Non ri-disegnare l'intera pensione da zero ogni tick

Non ha Room.render blit background ogni volta, il che significa allora deve passare attraverso e ri-disegnare l'intera tavola e tutte le carte. Fallo una volta. Quindi non avere re-rendering delle carte a meno che non cambino le tenebre o si muovano.

Quando le carte si stanno muovendo, dovresti essere in grado di ripristinare lo sfondo semplicemente inserendo una porzione della grafica di sfondo invece dell'intera cosa.

passare una lista rettangolo per display.update

Una volta entrato aggiornando solo alcune zone, è possibile passare quelle aree a display.update in modo da non dover aggiornare l'intero schermo. Per un esempio, see the Solarwolf code e come contrassegna i rettangoli sporchi.

+0

È vero che l'FPS non dovrebbe importare un grosso problema in un gioco come questo, ma ci sono aree in cui ho implementato un'animazione fluida, come negli swap delle carte, e un frame rate increspato è sicuramente notevole. Quello che mi infastidisce è che FPS chiaramente non dovrebbe essere un ** problema ** per un gioco come questo, programmato correttamente. L'elaborazione di ogni spunta è per l'animazione e anche per gli algoritmi di individuazione del percorso un po 'computazionalmente pesanti. –

+0

Non so se l'hai notato, ma io uso pygame.time.wait() nel mio ciclo degli eventi principale, che ha aiutato a ridurre l'uso della CPU. –

+0

ok, rispondi modificato per includere alcuni puntatori sui metodi di rendering. – keturn

2

sul proprio profilo di risultati:

di recente ho scoperto che è necessario aggiornare solo le aree dello schermo che hanno cambiato, ma io sono ancora nebbia su come è realizzato esattamente ... questo potrebbe essere un enorme problema di prestazioni?

Sì. display.update e Surface.blit sono in cima ai risultati del tuo profilo. Hai fatto oltre un milione di blit, in circa 5000 tick, che funziona fino a 200 blits ogni tick.

Inoltre, il sesto risultato del profilo è display.set_caption, che suppongo sia la visualizzazione del contatore FPS stesso? A 7 secondi di 157, questo non è il tuo principale punto di riferimento, ma è comunque interessante da sapere.

+0

Grazie mille Keturn! Sono ancora confuso sull'intero processo di aggiornamento/blit, in termini di sole cose che sono cambiate ... puoi indicarmi la giusta direzione su come ottenerlo? –

0

Direi che un'attesa semplice di 5-10 ms è sufficiente per attenuare seriamente l'utilizzo della CPU che provoca costantemente il re-rendering dello schermo.