def main(): # set up window display stuff pygame.display.set_caption('Catan') screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) game_board = GameBoard(300, 100, WINDOW_WIDTH / 2, 100) running = True time_between_frames = 1 / FRAMES_PER_SECOND # ~~~~~ MAIN GAME LOOP ~~~~~ while running: screen.fill((100, 100, 200)) start_time = time.time() game_board.draw(screen) game_board.hex_board.select(game_board.hex_board.roads) pygame.display.flip() for event in pygame.event.get(): if event.type == pygame.QUIT: running = False sleep_time = (start_time + time_between_frames) - time.time() if sleep_time > 0: time.sleep(sleep_time)
class Game: def __init__(self): self.__running = False self.screen = pygame.display.set_mode( (Consts.WINDOW_WIDTH, Consts.WINDOW_HEIGHT)) self.__clock = pygame.time.Clock() # frame clock self.__game_board = GameBoard() self.player = Player() self.control_panel = ControlPanel(self.player) self.caretaker = Caretaker(self.player) def start_game(self): pygame.display.set_caption("Silesian Game") self.__running = True self.__game_loop() def __game_loop(self): while self.__running: self.__clock.tick(Consts.FPS) self.__key_control() self.__draw() self.player.income_gold() pygame.display.update() def __draw(self): self.control_panel.draw(self.screen, self.player.get_gold()) self.__game_board.draw(self.screen) self.player.draw_buildings(self.screen) def __build(self, building_type): if building_type == 0: if self.player.get_gold() >= Consts.WOODCUTTERS_HUT_COST: self.caretaker.store_snapshot() self.player.add_building( WoodcuttersHut(self.player.next_building_position())) self.player.spend_gold(Consts.WOODCUTTERS_HUT_COST) else: print("Dont have enough gold!") elif building_type == 1: if self.player.get_gold() >= Consts.QUARRY_COST: self.caretaker.store_snapshot() self.player.add_building( Quarry(self.player.next_building_position())) self.player.spend_gold(Consts.QUARRY_COST) else: print("Dont have enough gold!") elif building_type == 2: if self.player.get_gold() >= Consts.SAWMILL_COST: self.caretaker.store_snapshot() self.player.add_building( Sawmill(self.player.next_building_position())) self.player.spend_gold(Consts.SAWMILL_COST) else: print("Dont have enough gold!") elif building_type == 3: if self.player.get_gold() >= Consts.GOLD_MINE_COST: self.caretaker.store_snapshot() self.player.add_building( GoldMine(self.player.next_building_position())) self.player.spend_gold(Consts.GOLD_MINE_COST) else: print("Dont have enough gold!") elif building_type == 4: if self.player.get_gold() >= Consts.GOLD_MINT_COST: self.caretaker.store_snapshot() self.player.add_building( GoldMint(self.player.next_building_position())) self.player.spend_gold(Consts.GOLD_MINT_COST) else: print("Dont have enough gold!") def __key_control(self): for event in pygame.event.get(): if event.type == pygame.QUIT: self.__running = False elif event.type == pygame.MOUSEBUTTONDOWN: building_type = self.__is_onclick(event.pos) if building_type in [0, 1, 2, 3, 4]: if self.player.get_buildings_length( ) >= Consts.NUMBER_OF_ROWS * Consts.NUMBER_OF_COLUMNS: print("Cant build more!") continue self.__build(building_type) elif building_type == 5: self.caretaker.undo() elif building_type == 6: self.caretaker.redo() @staticmethod def __is_onclick(mouse_position): if (Consts.PANEL_BUILDING_0_POSITION[0] < mouse_position[0] < Consts.PANEL_BUILDING_0_POSITION[0] + Consts.ICON_SIZE and Consts.PANEL_BUILDING_0_POSITION[1] < mouse_position[1] < Consts.PANEL_BUILDING_0_POSITION[1] + Consts.ICON_SIZE): return 0 elif (Consts.PANEL_BUILDING_1_POSITION[0] < mouse_position[0] < Consts.PANEL_BUILDING_1_POSITION[0] + Consts.ICON_SIZE and Consts.PANEL_BUILDING_1_POSITION[1] < mouse_position[1] < Consts.PANEL_BUILDING_1_POSITION[1] + Consts.ICON_SIZE): return 1 elif (Consts.PANEL_BUILDING_2_POSITION[0] < mouse_position[0] < Consts.PANEL_BUILDING_2_POSITION[0] + Consts.ICON_SIZE and Consts.PANEL_BUILDING_2_POSITION[1] < mouse_position[1] < Consts.PANEL_BUILDING_2_POSITION[1] + Consts.ICON_SIZE): return 2 elif (Consts.PANEL_BUILDING_3_POSITION[0] < mouse_position[0] < Consts.PANEL_BUILDING_3_POSITION[0] + Consts.ICON_SIZE and Consts.PANEL_BUILDING_3_POSITION[1] < mouse_position[1] < Consts.PANEL_BUILDING_3_POSITION[1] + Consts.ICON_SIZE): return 3 elif (Consts.PANEL_BUILDING_4_POSITION[0] < mouse_position[0] < Consts.PANEL_BUILDING_4_POSITION[0] + Consts.ICON_SIZE and Consts.PANEL_BUILDING_4_POSITION[1] < mouse_position[1] < Consts.PANEL_BUILDING_4_POSITION[1] + Consts.ICON_SIZE): return 4 elif (Consts.BACK_BUTTON_POSITION[0] < mouse_position[0] < Consts.BACK_BUTTON_POSITION[0] + Consts.ICON_SIZE and Consts.BACK_BUTTON_POSITION[1] < mouse_position[1] < Consts.BACK_BUTTON_POSITION[1] + Consts.ICON_SIZE): return 5 elif (Consts.FORWARD_BUTTON_POSITION[0] < mouse_position[0] < Consts.FORWARD_BUTTON_POSITION[0] + Consts.ICON_SIZE and Consts.FORWARD_BUTTON_POSITION[1] < mouse_position[1] < Consts.FORWARD_BUTTON_POSITION[1] + Consts.ICON_SIZE): return 6 else: return 7
class Game(object): """ Responsible for managing the flow of a game and all of its entities. """ def __init__(self): # set up game parameters and initialize data structures logging.debug('initializing') self.player = Player() self.game_board = GameBoard() # The current round of play current_round = 1 # The number of rounds played before the game ends GAME_LENGTH = 14 HARVEST_ROUNDS = frozenset([4, 7, 9, 11, 13, 14]) def run(self): # execute the iterative flow of the game while self.current_round <= self.GAME_LENGTH: self.player.update() self.game_board.update() print 'Round: %s' % self.current_round while self.player.has_idle_family_members: action = self.get_action_input() if not self.game_board.available_actions[action].is_occupied: try: self.game_board.available_actions[action].take( self.player) except CancelledActionException as e: if e.message: print e.message continue self.player.send_family_member_to_work() else: print 'The %s space is already occupied. Type -a to see the board.' % action if self.current_round in self.HARVEST_ROUNDS: self.player.field.harvest(self.player) self.current_round += 1 self.end() def end(self): # calculate score, print results score = self.calculate_final_score() print 'Your score was: %s' % score def calculate_final_score(self): # calculate the player's final score logging.debug('calculating final score for player') score = 0 # get stuff here return score def get_action_input(self): action_input = raw_input('Please type an action: ').lower() if action_input in self.game_board.available_actions.keys(): return action_input elif action_input == '-p': self.player.draw() elif action_input == '-f': self.player.field.draw() elif action_input == '-a': self.game_board.draw() else: print 'invalid action: %s' % action_input print 'type -a to see a list of available actions, -p to see your resources, -f to see your field' return self.get_action_input()
from readchar import readchar from game_board import GameBoard if __name__ == '__main__': game_board = GameBoard(20, 10) print("WASD to move.") print("SPACE to shoot.") print("x to close.") print("Push any key to start!") while True: user_input = readchar().decode(encoding='utf-8') game_board.update(user_input) game_board.draw() if user_input == "x": exit(0)
class CatanClient(ConnectionListener): """Client for Catan game. Manages all displays""" def __init__(self, host='localhost', port=4200): pygame.init() self.game_board = None self.screen = None self.game_id = None self.my_player = None self.state = GameState.WAITING_FOR_PLAYERS self.state_functions = { GameState.SELECT_SETTLEMENT: self.select_settlement, GameState.SELECT_ROAD: self.select_road, GameState.ROLL_DICE_WAIT: self.roll_dice_wait, GameState.ROLL_DICE_STOP: self.roll_dice_stop } self.Connect((host, port)) self.server_response = False while not self.server_response: self.pump() sleep(0.01) print('You have connected to the central server!') # need to keep asking user self.accepted_by_server = False while not self.accepted_by_server: will_host = OptionGetter.hosting_preference() game_options = OptionGetter.game_specs() self.num_players = game_options['num_players'] # send the server these options self.send({ 'action': 'check_hosting', 'host': will_host, 'options': game_options }) # wait on the server for a response self.server_response = False print('Waiting on server...') while not self.server_response: self.pump() sleep(0.01) print('Ready to play at game: ' + str(self.game_id)) # user must now pick a username and color that are unique from # other players already in the game self.accepted_by_server = False while not self.accepted_by_server: username, color = OptionGetter.user_and_color() self.my_player = ClientMyPlayer(username, color) # send server this selection self.send({ 'action': 'user_color_selection', 'username': username, 'color': color }) # wait on server for a response self.server_response = False print('Waiting on server...') while not self.server_response: self.pump() sleep(0.01) self.screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) # the user's game specs have been accepted by the server. # must wait until the max # of players has been reached # to improve readability. adds the game id to what is being sent to # the server def send(self, message): if self.game_id is not None: message['game_id'] = self.game_id connection.Send(message) # the server is informing the client that they have connected def Network_init(self, data): self.server_response = True print('Connected to the server...') # receive message from server about whether the desired game specifications # exist. (note: if user is trying to host, their request will always be # accepted) def Network_check_hosting(self, data): self.server_response = True if data['accepted']: self.accepted_by_server = True self.game_id = data['game_id'] # the server is informing the client if their username / color choices # have already been taken def Network_check_user_color(self, data): self.server_response = True accept_username = data['accept_username'] accept_color = data['accept_color'] if accept_username and accept_color: print('Username and color have been accepted!') # add the client's own player to the sidebar self.accepted_by_server = True self.game_board.sidebar.add_player(self.my_player.username, self.my_player.color) pygame.display.set_caption('Settlers of Catan') elif accept_username and not accept_color: print('Color was already taken by another player') elif not accept_username and accept_color: print('Username was already taken by another player') else: print('Username and color already taken by another player, lmao') # the server is informing the client of the players who are already in the game def Network_current_players(self, data): for player in data['players']: self.game_board.sidebar.add_player(player['username'], player['color']) print('I have been informed of {}, who is {}'.format( player['username'], player['color'])) # the server is informing the client of a new player who has joined the game def Network_new_player(self, data): self.game_board.sidebar.add_player(data['username'], data['color']) print('I have been informed of {}, who is {}'.format( data['username'], data['color'])) # the server is giving the client the game board layout def Network_game_board(self, data): layout = data['layout'] for item in layout: print(item) self.game_board = GameBoard(200, 200, layout, self.num_players) # network signals from here below are those received during actually game-play # and mostly just change the client's state or screen. they are paired w/ the # appropriate state function # FROM SERVER # waiting on another player; nothing for the client to do def Network_wait(self, data): self.state = GameState.WAIT print('Waiting on player {}'.format(data['cur_player'])) # FROM SERVER # client must select a settlement def Network_select_settlement(self, data): self.state = GameState.SELECT_SETTLEMENT print('Please select a settlement') # FROM SERVER # a new settlement has been created def Network_new_settlement(self, data): settlement_index = data['settlement'] color = data['color'] self.game_board.new_settlement(settlement_index, color) # FROM SERVER # a new road has been created def Network_new_road(self, data): road_index = data['road'] color = data['color'] self.game_board.new_road(road_index, color) # FROM SERVER # client must select a road def Network_select_road(self, data): self.state = GameState.SELECT_ROAD print('Please select a road') # FROM SERVER # client made invalid selection def Network_invalid(self, data): print('Invalid {} selection, please try again'.format(data['message'])) # FROM SERVER # the user's resources have changed; update them def Network_update_resources(self, data): pass # FROM SERVER # clients begin rolling dice def Network_wait_dice(self, data): self.state = GameState.ROLL_DICE_WAIT self.dice_roll_count = 0 dice_stopper = data['roller'] print('Waiting for {} to stop the dice...'.format(dice_stopper)) def Network_roll_dice(self, data): self.state = GameState.ROLL_DICE_STOP self.dice_roll_count = 0 print('Please click to stop the dice') # FROM SERVER # result of dice roll def Network_dice_result(self, data): self.state = GameState.WAIT left = data['left'] right = data['right'] self.game_board.dice.set(left, right) print('Dice result: {} and {}'.format(left + 1, right + 1)) # GAME STATE # the user needs to select a road def select_settlement(self, mouse_pos, mouse_click): selection = self.game_board.select_settlement(mouse_pos) if mouse_click and selection is not None: # user has selected a settlement, send selection to server self.send({'action': 'select_settlement', 'settlement': selection}) # GAME STATE # the user needs to select a road def select_road(self, mouse_pos, mouse_click): selection = self.game_board.select_road(mouse_pos) if mouse_click and selection is not None: # user has selected a road, send selection to server self.send({'action': 'select_road', 'road': selection}) # GAME STATE # the user must wait for the current player to stop the dice # in the meantime, let the user observe the beautifully crafted dice at the top of the screen def roll_dice_wait(self, mouse_pos, mouse_click): if self.dice_roll_count == 16: self.game_board.dice.next() self.dice_roll_count = 0 self.dice_roll_count += 1 # GAME STATE # the user must click to stop the dice def roll_dice_stop(self, mouse_pos, mouse_click): if self.dice_roll_count == 16: self.game_board.dice.next() self.dice_roll_count = 0 self.dice_roll_count += 1 if mouse_click: # user wants to stop the dice self.send({'action': 'stop_dice'}) def draw(self, screen): self.game_board.draw(screen) def update(self): # do all management of key presses / mouse info here mouse_click = False for event in pygame.event.get(): if event.type == pygame.QUIT: exit(1) elif event.type == pygame.MOUSEBUTTONUP: # mouse has been clicked! mouse_click = True mouse_pos = pygame.mouse.get_pos() if self.state != GameState.WAITING_FOR_PLAYERS and self.state != GameState.WAIT: self.state_functions[self.state](mouse_pos, mouse_click) self.screen.fill((100, 100, 250)) self.draw(self.screen) pygame.display.flip() # if self.Pump() is called twice in a row events will occur twice, # which is bad. use this instead def pump(self): connection.Pump() self.Pump()
class Game(object): def __init__(self, manager, white_player='human', black_player='human'): # game state members self.game_manager = manager self.game_running = False self.needs_redraw = True self.screen = None self.clock = pygame.time.Clock() # game components self.game_logic = GameLogic(self) self.game_grid = GameGrid(self) self.game_board = None self.white_player = None self.black_player = None self.initialize_players(white_player, black_player) self.turn_manager = TurnManager(self) self.highlighter = Highlighter(self) self.logger = Logger(self) self.buttons = {} def init(self): self.screen = pygame.display.get_surface() self.game_running = True self.screen.fill(BLACK) # initialize game components self.game_board = GameBoard(self, self.game_grid) self.highlighter.init() self.initialize_buttons() def initialize_buttons(self): restart_button = Button(restart_coord, 'Restart', self.restart, restart_anchor, False) end_button = Button(end_coord, 'End Game', self.exit_game, end_anchor) self.buttons['restart'] = restart_button self.buttons['end'] = end_button def initialize_players(self, white, black): players = [] sides = ['white', 'black'] constructors = [] for p_type in (white, black): if p_type == 'human': constructors.append(Player) else: constructors.append(AIPlayer) for i in (0, 1): players.append(constructors[i](self, sides[i])) self.white_player = players[0] self.black_player = players[1] # main game loop def main(self): while self.game_running: self.handle_input() self.run_logic() if self.needs_redraw: self.draw_all() self.update_display() self.reset_redraw() self.tick() def handle_input(self): for event in pygame.event.get(): if event.type == QUIT: self.exit_program() elif event.type == MOUSEBUTTONDOWN: if self.active_player.is_human() and self.mouse_over_grid(): self.active_player.try_to_place_piece( self.mouse_grid_position()) else: for button in self.buttons.itervalues(): if button.active and button.mouse_is_over(): button.on_click() @property def active_player(self): return self.turn_manager.active_player def mouse_over_grid(self): mx, my = pygame.mouse.get_pos() return my > BOARD_Y_OFFSET def mouse_grid_position(self): mouse_pos = pygame.mouse.get_pos() return self.game_grid.translate_mouse_to_grid_coord(mouse_pos) def exit_game(self): self.game_running = False def exit_program(self): self.game_running = False self.game_manager.exit_game() print 'here' def run_logic(self): self.turn_manager.run() if not self.active_player.is_human( ) and self.turn_manager.game_running: self.active_player.run_logic() def draw_all(self): self.game_board.draw(self.screen) self.highlighter.draw(self.screen) self.logger.draw_scores(self.screen) self.logger.draw_log(self.screen) for button in self.buttons.itervalues(): if button.active: button.draw(self.screen) def update_display(self): pygame.display.update() def request_redraw(self): self.needs_redraw = True def reset_redraw(self): self.needs_redraw = False def tick(self): self.clock.tick(FPS) def black_score(self): return self.game_grid.get_score(BLACK_PIECE) def white_score(self): return self.game_grid.get_score(WHITE_PIECE) def activate_button(self, key): self.buttons[key].set_active() def hide_button(self, key): self.buttons[key].hide() def restart(self): self.game_grid.reset_state() self.turn_manager.reset_state() self.request_redraw() self.hide_button('restart')