class Game: def __init__(self, title='Checkers', log_level=log.INFO, show_fps=False): log.basicConfig(level=log_level) self.show_fps = show_fps self.window_title = title self.game = Board(BOARD_DIM) # Initialize Game Groups self.brown_spaces = RenderUpdates() self.pieces = RenderUpdates() self.piece_selected = GroupSingle() self.space_selected = GroupSingle() self.current_piece_position = ORIGIN self.screen = None self.fps_clock = None self.font = None self.font_rect = None self.background = None self.background_rect = None self.fps_text = None self.fps_rect = None self.winner_text = None self.winner_rect = None def _board_setup(self, **kwargs): """ initialize board state """ brown_spaces = kwargs.get('brown_spaces') for col, row in self.game.usable_positions(): loc = TILE_WIDTH * col + (BORDER_WIDTH / 2), TILE_WIDTH * row + (BORDER_WIDTH / 2) brown_spaces.add(SquareSprite(loc, "brown", row, col)) def _screen_init(self): """ Initialise screen """ pygame.init() self.screen = pygame.display.set_mode(SCREEN_RES) pygame.display.set_caption(self.window_title) return self.screen def _get_background(self): result = pygame.Surface(self.screen.get_size()) (bg_img, bg_rect) = ImageLoader.load_img('marble-board.jpg') result.blit(bg_img, bg_rect) return result.convert(), bg_rect def _get_fps_text(self): fps_text = self.font.render("%4.1f fps" % self.fps_clock.get_fps(), True, WHITE) rect = fps_text.get_rect() rect.right, rect.bottom = self.background_rect.right, self.background_rect.bottom return fps_text, rect def _draw_fps(self): if self.show_fps: self.fps_text, self.fps_rect = self._get_fps_text() self.screen.blit(self.fps_text, self.fps_rect) def _clear_fps(self): if self.show_fps: self.screen.blit(self.background, self.fps_rect, area=self.fps_rect) def _clear_items(self): self._clear_winner() self._clear_fps() self.piece_selected.clear(self.screen, self.background) self.pieces.clear(self.screen, self.background) def _draw_winner(self): winner = self.game.winner() if winner: self.winner_text = self.font.render("%s wins!" % winner.title(), True, WHITE) winner_rect = self.winner_text.get_rect() winner_rect.centerx = self.background.get_rect().centerx winner_rect.top = 100 self.winner_rect = winner_rect self.screen.blit(self.winner_text, winner_rect) def _clear_winner(self): winner = self.game.winner() if winner: self.screen.blit(self.background, self.winner_rect, area=self.winner_rect) def _quit(self): log.debug('quitting') sys.exit() def _select_piece(self, event): # select the piece by seeing if the piece collides with cursor self.piece_selected.add(piece for piece in self.pieces if piece.rect.collidepoint(event.pos)) # Capture piece's original position (at center) to determine move on drop if len(self.piece_selected) > 0: # Assumed: starting a move pygame.event.set_grab(True) self.pieces.remove(self.piece_selected) self.current_piece_position = ( self.piece_selected.sprite.rect.centerx, self.piece_selected.sprite.rect.centery) log.debug('grabbing input, picked up piece at %s', self.current_piece_position) def _drag_piece(self): # Until button is let go, move the piece with the mouse position self.piece_selected.update(pygame.mouse.get_pos()) log.debug('updated piece to %s', pygame.mouse.get_pos()) def _drop_piece(self, event): if pygame.event.get_grab(): pygame.event.set_grab(False) log.debug('releasing input') # center the piece on the valid space; if it is not touching a space, return it to its original position self.space_selected.add(space for space in self.brown_spaces if space.rect.collidepoint(event.pos)) if self.piece_selected and self.space_selected: log.debug('dropped a piece') piece, space = self.piece_selected.sprite, self.space_selected.sprite try: captured = self.game.move(piece.location, (space.col, space.row)) if captured: self.pieces.remove(captured) except InvalidMoveException as ce: log.debug(ce) log.debug("%s", str(self.game)) self.piece_selected.sprite.update_from_board() # Add piece back to stationary set self.pieces.add(self.piece_selected) # clean up for the next selected piece self.piece_selected.empty() self.space_selected.empty() def _draw_items(self): self.pieces.draw(self.screen) self.piece_selected.draw(self.screen) self._draw_winner() self._draw_fps() def run(self): log.debug('starting game') log.debug('initializing screen') self.screen = self._screen_init() log.debug('getting font') self.font = pygame.font.Font(None, 36) log.debug('loading background') self.background, self.background_rect = self._get_background() log.debug('building initial game board') self._board_setup(brown_spaces=self.brown_spaces) log.debug('initializing game pieces') for player, x, y in self.game.start_positions(): new_piece = PieceSprite(player) self.game.add_piece(new_piece, (x, y)) new_piece.update_from_board() self.pieces.add(new_piece) log.debug('drawing initial content to screen') self.screen.blit(self.background, ORIGIN) pygame.display.flip() self.piece_selected = GroupSingle() self.space_selected = GroupSingle() self.current_piece_position = ORIGIN self.fps_clock = Clock() self._draw_fps() # Event loop while True: self._clear_items() for event in pygame.event.get(): if event.type == QUIT: self._quit() if event.type == MOUSEBUTTONDOWN: # select a piece log.debug('mouse pressed') self._select_piece(event) if event.type == MOUSEBUTTONUP: # let go of a piece log.debug('mouse released') self._drop_piece(event) if pygame.event.get_grab(): # drag selected piece around log.debug('dragging') self._drag_piece() self._draw_items() self.fps_clock.tick(60) # Waits to maintain 60 fps # TODO: Use display.update instead pygame.display.flip()
class Game: def __init__(self, title='Checkers', log_level=log.INFO, show_fps=False): log.basicConfig(level=log_level) self.show_fps = show_fps self.window_title = title self.game = Board(BOARD_DIM) # Initialize Game Groups self.brown_spaces = RenderUpdates() self.pieces = RenderUpdates() self.piece_selected = GroupSingle() self.space_selected = GroupSingle() self.current_piece_position = ORIGIN self.screen = None self.fps_clock = None self.font = None self.font_rect = None self.background = None self.background_rect = None self.fps_text = None self.fps_rect = None self.winner_text = None self.winner_rect = None def _board_setup(self, **kwargs): """ initialize board state """ brown_spaces = kwargs.get('brown_spaces') for col, row in self.game.usable_positions(): loc = TILE_WIDTH * col + (BORDER_WIDTH / 2), TILE_WIDTH * row + (BORDER_WIDTH / 2) brown_spaces.add(SquareSprite(loc, "brown", row, col)) def _screen_init(self): """ Initialise screen """ pygame.init() self.screen = pygame.display.set_mode(SCREEN_RES) pygame.display.set_caption(self.window_title) return self.screen def _get_background(self): result = pygame.Surface(self.screen.get_size()) (bg_img, bg_rect) = ImageLoader.load_img('marble-board.jpg') result.blit(bg_img, bg_rect) return result.convert(), bg_rect def _get_fps_text(self): fps_text = self.font.render("%4.1f fps" % self.fps_clock.get_fps(), True, WHITE) rect = fps_text.get_rect() rect.right, rect.bottom = self.background_rect.right, self.background_rect.bottom return fps_text, rect def _draw_fps(self): if self.show_fps: self.fps_text, self.fps_rect = self._get_fps_text() self.screen.blit(self.fps_text, self.fps_rect) def _clear_fps(self): if self.show_fps: self.screen.blit(self.background, self.fps_rect, area=self.fps_rect) def _clear_items(self): self._clear_winner() self._clear_fps() self.piece_selected.clear(self.screen, self.background) self.pieces.clear(self.screen, self.background) def _draw_winner(self): winner = self.game.winner() if winner: self.winner_text = self.font.render("%s wins!" % winner.title(), True, WHITE) winner_rect = self.winner_text.get_rect() winner_rect.centerx = self.background.get_rect().centerx winner_rect.top = 100 self.winner_rect = winner_rect self.screen.blit(self.winner_text, winner_rect) def _clear_winner(self): winner = self.game.winner() if winner: self.screen.blit(self.background, self.winner_rect, area=self.winner_rect) def _quit(self): log.debug('quitting') sys.exit() def _select_piece(self, event): # select the piece by seeing if the piece collides with cursor self.piece_selected.add(piece for piece in self.pieces if piece.rect.collidepoint(event.pos)) # Capture piece's original position (at center) to determine move on drop if len(self.piece_selected) > 0: # Assumed: starting a move pygame.event.set_grab(True) self.pieces.remove(self.piece_selected) self.current_piece_position = (self.piece_selected.sprite.rect.centerx, self.piece_selected.sprite.rect.centery) log.debug('grabbing input, picked up piece at %s', self.current_piece_position) def _drag_piece(self): # Until button is let go, move the piece with the mouse position self.piece_selected.update(pygame.mouse.get_pos()) log.debug('updated piece to %s', pygame.mouse.get_pos()) def _drop_piece(self, event): if pygame.event.get_grab(): pygame.event.set_grab(False) log.debug('releasing input') # center the piece on the valid space; if it is not touching a space, return it to its original position self.space_selected.add(space for space in self.brown_spaces if space.rect.collidepoint(event.pos)) if self.piece_selected and self.space_selected: log.debug('dropped a piece') piece, space = self.piece_selected.sprite, self.space_selected.sprite try: captured = self.game.move(piece.location, (space.col, space.row)) if captured: self.pieces.remove(captured) except InvalidMoveException as ce: log.debug(ce) log.debug("%s", str(self.game)) self.piece_selected.sprite.update_from_board() # Add piece back to stationary set self.pieces.add(self.piece_selected) # clean up for the next selected piece self.piece_selected.empty() self.space_selected.empty() def _draw_items(self): self.pieces.draw(self.screen) self.piece_selected.draw(self.screen) self._draw_winner() self._draw_fps() def run(self): log.debug('starting game') log.debug('initializing screen') self.screen = self._screen_init() log.debug('getting font') self.font = pygame.font.Font(None, 36) log.debug('loading background') self.background, self.background_rect= self._get_background() log.debug('building initial game board') self._board_setup(brown_spaces=self.brown_spaces) log.debug('initializing game pieces') for player, x, y in self.game.start_positions(): new_piece = PieceSprite(player) self.game.add_piece(new_piece, (x, y)) new_piece.update_from_board() self.pieces.add(new_piece) log.debug('drawing initial content to screen') self.screen.blit(self.background, ORIGIN) pygame.display.flip() self.piece_selected = GroupSingle() self.space_selected = GroupSingle() self.current_piece_position = ORIGIN self.fps_clock = Clock() self._draw_fps() # Event loop while True: self._clear_items() for event in pygame.event.get(): if event.type == QUIT: self._quit() if event.type == MOUSEBUTTONDOWN: # select a piece log.debug('mouse pressed') self._select_piece(event) if event.type == MOUSEBUTTONUP: # let go of a piece log.debug('mouse released') self._drop_piece(event) if pygame.event.get_grab(): # drag selected piece around log.debug('dragging') self._drag_piece() self._draw_items() self.fps_clock.tick(60) # Waits to maintain 60 fps # TODO: Use display.update instead pygame.display.flip()
class Game(StatusHandler): def __init__(self, title='Checkers', log_drag=False, show_fps=False, ip='127.0.0.1', port=5000, spectate=False): self.game_running = True self.player = None self.log_drag = log_drag self.show_fps = show_fps self.window_title = title self.game = NetBoard(handler=self, ip=ip, port=port, spectate=spectate) # Initialize Game Groups self.board_spaces = set() self.pieces = RenderUpdates() self.piece_selected = GroupSingle() self.bg_text = RenderUpdates() self.fg_text = RenderUpdates() self.current_piece_position = ORIGIN self.screen = None self.fps_clock = None self.font = None self.background = None self.background_rect = None self.fps_text = None self.winner_text = None self.turn_text = None self.player_text = None self.game_id_text = None def handle_game_id(self, game_id): self.game_id_text.text = "Game: %s" % game_id def handle_list(self, game_list, list_type): if list_type == SPECTATE and game_list: game_id = game_list[0] self.game.client.spectate(game_id) self.player_text.text = 'You are a spectator' elif not list_type and game_list: game_id = game_list[0] self.game.client.join(game_id) elif not list_type and not game_list: self.game.client.new_game() def handle_board(self, board): for piece in board: new_piece = PieceSprite(piece.player) new_piece.king = piece.king self.game.add_piece(new_piece, piece.location) new_piece.update_from_board() self.pieces.add(new_piece) def handle_turn(self, player): self.game.turn = player def handle_you_are(self, player): self.player = player def handle_moved(self, src, dst): moved_pieces = [p for p in self.pieces if p.location == src] Board.move(self.game, src, dst) if moved_pieces: moved_pieces[0].update_from_board() Sounds.play('slap.ogg') log.debug("board after drop:\n%s", str(self.game)) def handle_captured(self, loc): captured_pieces = [p for p in self.pieces if p.location == loc] if captured_pieces: self.pieces.remove(captured_pieces[0]) def _board_space_setup(self): """ initialize board state """ for col, row in self.game.usable_positions(): self.board_spaces.add(Square(row, col)) def _screen_init(self): """ Initialise screen """ self.screen = pygame.display.set_mode(SCREEN_RES) pygame.display.set_caption(self.window_title) return self.screen def _get_background(self): result = pygame.Surface(self.screen.get_size()) (bg_img, bg_rect) = Images.load('marble-board.jpg') result.blit(bg_img, bg_rect) return result.convert(), bg_rect def _clear_items(self): self.fg_text.clear(self.screen, self.background) self.piece_selected.clear(self.screen, self.background) self.pieces.clear(self.screen, self.background) self.bg_text.clear(self.screen, self.background) def _quit(self): log.debug('quitting') self.game.client.quit() self.game_running = False def _select_piece(self, event): # select the piece by seeing if the piece collides with cursor self.piece_selected.add(piece for piece in self.pieces if piece.rect.collidepoint(event.pos) and piece.player == self.player and piece.player == self.game.turn) # Capture piece's original position (at center) to determine move on drop if len(self.piece_selected) > 0: # Assumed: starting a move pygame.event.set_grab(True) self.pieces.remove(self.piece_selected) self.current_piece_position = (self.piece_selected.sprite.rect.centerx, self.piece_selected.sprite.rect.centery) log.debug('grabbing input, picked up piece at %s', self.current_piece_position) Sounds.play('slide.ogg') def _drag_piece(self): # Until button is let go, move the piece with the mouse position if self.log_drag: log.debug('dragging') rect = self.piece_selected.sprite.rect rect.centerx, rect.centery = pygame.mouse.get_pos() if self.log_drag: log.debug('updated piece to %s', pygame.mouse.get_pos()) def _reset_selected_piece(self): self.piece_selected.sprite.update_from_board() Sounds.play('slap.ogg') log.debug("board after drop:\n%s", str(self.game)) def _drop_piece(self, event): if pygame.event.get_grab(): pygame.event.set_grab(False) log.debug('releasing input') # center the piece on the valid space; if it is not touching a space, return it to its original position space_selected = [space for space in self.board_spaces if space.collidepoint(event.pos)] if self.piece_selected and space_selected: log.debug('dropped a piece') piece, space = self.piece_selected.sprite, space_selected[0] try: self.game.move(piece.location, (space.col, space.row)) except InvalidMoveException as ce: log.debug(ce) self._reset_selected_piece() else: log.debug('dropped on unplayable game space') self._reset_selected_piece() # Add piece back to stationary set self.pieces.add(self.piece_selected) # clean up for the next selected piece self.piece_selected.empty() def _draw_items(self): self.bg_text.draw(self.screen) self.pieces.draw(self.screen) self.piece_selected.draw(self.screen) self.fg_text.draw(self.screen) def _update(self): self.game.update() self.fps_text.text = "%4.1f fps" % self.fps_clock.get_fps() if self.player: self.player_text.text = "Your pieces are %s" % self.player if self.game.turn not in players: self.turn_text.text = "Waiting for player" else: if self.player == self.game.turn: self.turn_text.text = "Your turn" else: self.turn_text.text = "%s's turn" % self.game.turn.title() if self.game.winner(): self.turn_text.text = '' self.winner_text.text = "%s wins!" % self.game.winner().title() else: self.winner_text.text = '' if not self.piece_selected and self.player == self.game.turn: highlight_player = self.game.turn else: highlight_player = None self.pieces.update(highlight_player) self.piece_selected.update(self.game.turn) self.bg_text.update() self.fg_text.update() def run(self): log.debug('pre-initializing sound') mixer.pre_init(buffer=32) log.debug('starting game') pygame.init() log.debug('initializing screen') self.screen = self._screen_init() log.debug('getting font') self.font = pygame.font.Font(None, 36) log.debug('loading background') self.background, self.background_rect = self._get_background() log.debug('setting up drop locations') self._board_space_setup() log.debug('building text') bg_rect = self.background_rect class FPSText(Text): def update(self, *args): Text.update(self, *args) self.rect.right, self.rect.bottom = bg_rect.right, bg_rect.bottom self.fps_text = FPSText('', self.font, WHITE) if self.show_fps: self.fg_text.add(self.fps_text) class TurnText(Text): def update(self, *args): Text.update(self, *args) self.rect.centerx, self.rect.centery = bg_rect.centerx, bg_rect.centery self.turn_text = TurnText('', self.font, WHITE) self.bg_text.add(self.turn_text) class WinnerText(Text): def update(self, *args): Text.update(self, *args) self.rect.centerx, self.rect.centery = bg_rect.centerx, bg_rect.centery self.winner_text = WinnerText('', self.font, WHITE) self.fg_text.add(self.winner_text) class PlayerText(Text): def update(self, *args): Text.update(self, *args) self.rect.centerx, self.rect.bottom = bg_rect.centerx, bg_rect.bottom self.player_text = PlayerText('', pygame.font.Font(None, 24), WHITE) self.bg_text.add(self.player_text) class GameIdText(Text): def update(self, *args): Text.update(self, *args) self.rect.centerx, self.rect.top = bg_rect.centerx, bg_rect.top + (0.25 * self.font.get_height()) self.game_id_text = GameIdText('', pygame.font.Font(None, 20), WHITE) self.bg_text.add(self.game_id_text) log.debug('drawing initial content to screen') self.screen.blit(self.background, ORIGIN) pygame.display.flip() self.piece_selected = GroupSingle() self.current_piece_position = ORIGIN self.fps_clock = Clock() # Event loop while self.game_running: self._clear_items() for event in pygame.event.get(): if event.type == QUIT: self._quit() if event.type == MOUSEBUTTONDOWN: # select a piece log.debug('mouse pressed') self._select_piece(event) if event.type == MOUSEBUTTONUP: # let go of a piece log.debug('mouse released') self._drop_piece(event) if pygame.event.get_grab(): # drag selected piece around self._drag_piece() self._update() self._draw_items() self.fps_clock.tick(60) # Waits to maintain 60 fps # TODO: Use display.update instead pygame.display.flip() log.debug('finishing game loop')