Exemple #1
0
class Driver:
    # Constructor function, creates new instance of class
    def __init__(self): # 0 additional arguments, self is self-reference
        pygame.init()

        # Renderer, handles rendering functions on behalf of the game
        rendererOptions = type('', (), {})()
        rendererOptions.width = 800
        rendererOptions.height = 600
        self.gameRenderer = Renderer(rendererOptions)
        # Renderer before GameState, since Spritesheet depends on display.set_mode
        
        # Game state object, tracks state of game and all objects in game
        self.gameState = GameState() # Example of tightly coupled code.
        # TODO: Refactor coupled code, separate dependencies
        self.gameRenderer.game = self.gameState

        # Internal variables to handle frame ticks/FPS
        self.clock = pygame.time.Clock()
        self.currentTime = 0

        # Event Handler dictionaries
        self.keydownHandlers = defaultdict(list)
        self.keyupHandlers = defaultdict(list)

    # Event Handler function
    def handle_events(self):
        # pygame.event.get() clears the event queue, prevents crashing/freezing
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit(0)
            elif event.type == pygame.KEYDOWN:
                for handler in self.keydownHandlers[event.key]:
                    handler(event.type)
            elif event.type == pygame.KEYUP:
                for handler in self.keyupHandlers[event.key]:
                    handler(event.type)
            elif event.type == VICTORY_EVENT:
                font = pygame.font.SysFont("sysfont10", 48)
                text = font.render("VICTORY!!!", False, (255, 255, 255))
                textRect = text.get_rect()
                textRect.center = (400, 300)
                self.gameRenderer.screen.blit(text, textRect)
                pygame.display.flip()
                pygame.time.wait(1500)
                pygame.quit()
                sys.exit(0)

    def start(self):
        # Initial Key Bindings
        # Sets actions for both key up and key down
        # Could also handle other events (mouse events, etc.)
        self.keydownHandlers[pygame.K_LEFT].append(self.gameState.action_left)
        self.keydownHandlers[pygame.K_RIGHT].append(self.gameState.action_right)
        self.keydownHandlers[pygame.K_UP].append(self.gameState.action_up)
        self.keydownHandlers[pygame.K_DOWN].append(self.gameState.action_down)

        self.keyupHandlers[pygame.K_LEFT].append(self.gameState.action_left)
        self.keyupHandlers[pygame.K_RIGHT].append(self.gameState.action_right)
        self.keyupHandlers[pygame.K_UP].append(self.gameState.action_up)
        self.keyupHandlers[pygame.K_DOWN].append(self.gameState.action_down)

        # Game Loop Start
        # TODO: Implement some kind of "done/not done", not infinite loop
        while True:
            # Increment time tracker with ms passed since last call
            self.currentTime += self.clock.get_time()
            # Process current event queue
            self.handle_events()

            # While enough time has passed to process at least one frame
            while self.currentTime >= LOOP_MS_PF:
                # Update the game state one tick for each frame time block
                self.gameState.update() # Passing in update MS diff?
                self.currentTime -= LOOP_MS_PF

            # Once game state is caught up, render the game
            self.gameRenderer.render() # TODO: Passing in leftover ticks for delta rendering?
            # self.gameRenderer.drawDebug() # TODO: Need to comment this out for live

            # Tracking FPS in window caption, should be for debug only
            fps = self.clock.get_fps()
            pygame.display.set_caption("FPS: {0:2f}".format(fps))

            # Tell the system to wait until enough time has passed to hit the next frame
            self.clock.tick(TARGET_FPS)