2010-03-27 19 views
9

Estoy trabajando en un pequeño juego de viaje de intercambio de cartas que imagino como un cruce entre Bejeweled y los 10 días de los juegos de geografía. Hasta ahora, la codificación ha ido bien, pero la velocidad de cuadros es bastante mala ... actualmente estoy obteniendo 20 puntos bajos en mi Core 2 Duo. Esto es un problema ya que estoy creando el juego para la competencia de desarrolladores de marzo de Intel, que está directamente dirigido a netbooks que empaquetan procesadores Atom sin potencia.Ayuda a obtener la velocidad de fotogramas (fps) en Python + Pygame

Aquí hay una pantalla del juego:

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

soy muy nuevo en Python y Pygame (este es el primero que he utilizado para), y estoy muy deficiente en la educación formal Entrenamiento de CS ... lo que quiere decir que creo que probablemente MUCHAS malas prácticas están pasando en mi código, y MUCHO que podría ser optimizado. Si a alguno de ustedes, personas mayores de Python, no les importaría echar un vistazo a mi código y ver si no pueden encontrar áreas obvias para la optimización, estaría sumamente agradecido.

Puede descargar el código fuente completo aquí (Python 2.6 + 1.9 Pygame): http://www.necessarygames.com/my_games/betraveled/betraveled_src0328.zip

EXE compilado aquí: www.necessarygames.com/my_games/betraveled/betraveled_src0328.zip

Una cosa que me preocupa es mi administrador de eventos, que creo que puede tener algunos detalles de rendimiento, y otra cosa es mi renderizado ... Estoy simplemente pasando todo a la pantalla todo el tiempo (ver el render routines en my game_components.py b elow); Recientemente me enteré de que solo debes actualizar las áreas de la pantalla que han cambiado, pero todavía estoy confundido sobre cómo se logró exactamente ... ¿podría ser un gran problema de rendimiento?

¡Cualquier idea es muy apreciada! Como siempre, me complace "darle propina" por su tiempo y energía a través de PayPal.

Jordan



EDIT: Gracias a los consejos a continuación, me encontré cprofile en mi código. Sería genial si alguien estuviera dispuesto a mirar este resultado y dejarme saber qué es y qué no se espera.



Aquí está la salida de p.strip_dirs() sort_stats ('acumulativo') 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) 

Aquí está la salida de p.strip_dirs (.sort_stats) ('tiempo') 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__) 





Éstos son algunos fragmentos de la fuente:

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

Es posible que desee ejecutar un generador de perfiles (la biblioteca estándar de Python tiene algunos, por ejemplo, el módulo 'profile') y publicar las partes del código que ocupan más tiempo. Tal como están las cosas, pocos se molestarán en leer todo ese código. –

+1

@Max Shawabkeh, 'cProfile' es un reemplazo directo para' profile' con menos sobrecarga de Profiler. –

+0

Gracias por su amable consejo Max! En mi ignorancia, ni siquiera había sido consciente de la existencia de estas herramientas de creación de perfiles. He hecho lo que sugeriste y he publicado las estadísticas anteriores. ¡Si tú u otra persona pudieran ayudarme a encontrarle sentido, sería genial! –

Respuesta

7

dejar que los acontecimientos vienen a usted con event.wait

¿Realmente necesita procesar cada tic? De lo contrario, use pygame.event.wait para su bucle de evento para procesar solo cuando se produzca un evento, y pygame.time.set_timer si necesita eventos periódicos como SecondEvent.

Esto significa que no dibujará muchos fotogramas durante segundos cuando los eventos no están entrando, pero está bien. El uso de event.wait disminuirá el uso de la CPU y le permitirá seguir respondiendo, y es probable que elimine la necesidad de tiempo. Espere allí.

no vuelva a dibujar el tablero entero desde cero cada tick

No tiene Room.render blit el fondo cada vez, lo que significa, entonces tiene que ir a través y volver a dibujar la totalidad tablero y todas las cartas. Haz eso una vez. Entonces no haga que las cartas se vuelvan a representar a sí mismas a menos que cambien la oscuridad o se muevan.

Cuando las cartas se están moviendo, debe poder restaurar el fondo al hacer clic en una parte del gráfico de fondo en lugar de en todo.

pasar una lista rectángulo para display.update

Una vez que sólo se va a actualizar ciertas áreas, puede pasar a esas áreas display.update por lo que no tiene que actualizar toda la pantalla. Por ejemplo, see the Solarwolf code y cómo marca los rectángulos sucios.

+0

Es cierto que los FPS no deberían importar mucho en un juego como este, pero hay áreas en las que he implementado una animación fluida, como en los intercambios de cartas, y una velocidad de cuadros entrecortada es definitivamente notable. Lo que me molesta es que FPS claramente no debería ser un ** problema ** para un juego como este, programado correctamente. El procesamiento de cada tic es para la animación, y también para los algoritmos de búsqueda de ruta algo computacionalmente pesados. –

+0

No sé si lo has notado, pero sí uso pygame.time.wait() en mi ciclo de evento principal, lo que ayudó a reducir el uso de la CPU. –

+0

ok, respuesta editada para incluir algunos punteros en sus métodos de renderizado. – keturn

2

En sus resultados de perfil:

Hace poco descubrí que sólo se debe actualizar las áreas de la pantalla que han cambiado, pero sigo siendo de niebla en la forma en que se logró exactamente ... puede ser esto un gran problema de rendimiento?

Sí. display.update y Surface.blit están en la parte superior de los resultados de su perfil. Hiciste más de un millón de blits, en aproximadamente 5000 ticks, lo que da 200 blits cada tic.

Además, sexto en los resultados de su perfil es display.set_caption, que supongo que es la visualización del contador de FPS en sí? A los 7 segundos de 157, este no es tu punto de acceso principal, pero aún es interesante saberlo.

+0

¡Muchas gracias Keturn! Todavía estoy confundido acerca de todo el proceso de actualización/blit, en términos de solo descifrar cosas que han cambiado ... ¿pueden orientarme en la dirección correcta sobre cómo lograr eso? –

0

Yo diría que una simple espera de 5-10ms es suficiente para atenuar seriamente el uso de la CPU que causa la reescritura constante de la pantalla.

Cuestiones relacionadas