class GameBotView(arcade.View): def __init__(self): super().__init__() arcade.set_background_color(arcade.color.AMAZON) self.game = GameProcess(2, self) self.deck = self.game.deck self.ui_manager = UIManager() self.held_cards = None self.held_cards_original_position = None self.pile_mat_list = None def setup(self): self.card_list = self.deck.card_list for card in self.card_list: card.position = START_X, MIDDLE_Y self.card_list[0].position = START_X + 20, MIDDLE_Y self.card_list[0].angle = 90 self.card_list[0].face_up() self.finish_turn_button = FinishAtackButton(START_X, BOTTOM_Y, self) self.take_button = FinishDefendButton(START_X, BOTTOM_Y, self) self.next_button = NextPlayerButton(START_X, BOTTOM_Y, self) self.card_counter = arcade.text self.current_player_hand = self.game.CurrentPlayer.hand self.opponent_player_hand = self.game.OpponentPlayer.hand self.redraw_hand() self.redraw_opp_hand() self.held_cards = [] self.held_cards_original_position = [] self.pile_mat_list: arcade.SpriteList = arcade.SpriteList() for i in range(PILE_COUNT): self.pile_mat_list.append( arcade.SpriteSolidColor(MAT_WIDTH, MAT_HEIGHT, arcade.csscolor.DARK_OLIVE_GREEN)) self.pile_mat_list[TOP_ROW_PILE_1].position = ( MIDDLE_X - MAT_WIDTH / 2) - X_SPACING, MIDDLE_Y self.pile_mat_list[TOP_ROW_PILE_2].position = (MIDDLE_X - MAT_WIDTH / 2), MIDDLE_Y self.pile_mat_list[TOP_ROW_PILE_3].position = ( MIDDLE_X - MAT_WIDTH / 2) + X_SPACING, MIDDLE_Y self.pile_mat_list[TOP_ROW_PILE_4].position = ( MIDDLE_X - MAT_WIDTH / 2) + (2 * X_SPACING), MIDDLE_Y self.pile_mat_list[BOTTOM_ROW_PILE_1].position = ( MIDDLE_X - MAT_WIDTH / 2) - X_SPACING, MIDDLE_Y - MAT_HEIGHT self.pile_mat_list[BOTTOM_ROW_PILE_2].position = ( MIDDLE_X - MAT_WIDTH / 2), MIDDLE_Y - MAT_HEIGHT self.pile_mat_list[BOTTOM_ROW_PILE_3].position = ( MIDDLE_X - MAT_WIDTH / 2) + X_SPACING, MIDDLE_Y - MAT_HEIGHT self.pile_mat_list[BOTTOM_ROW_PILE_4].position = ( MIDDLE_X - MAT_WIDTH / 2) + (2 * X_SPACING), MIDDLE_Y - MAT_HEIGHT self.piles = [] for i in range(PILE_COUNT): self.piles.append(arcade.SpriteList()) def on_draw(self): arcade.start_render() if self.game.winner is None: self.pile_mat_list.draw() for pile in self.piles: pile.draw() self.ui_manager.on_draw() self.card_list.draw() self.card_counter.render_text( arcade.CreateText(str(self.deck.Count()), (0, 0, 0), 20, 50), START_X - 15, MIDDLE_Y - MAT_HEIGHT / 1.5) self.current_player_hand.draw() self.opponent_player_hand.draw() else: self.window.show_view(GameOverView(self)) def redraw_hand(self): count = len(self.current_player_hand) new_middle_x = MIDDLE_X - CARD_HORIZONTAL_OFFSET * (count) / 2 i = 0 for card in self.current_player_hand: card.position = new_middle_x + i, BOTTOM_Y i += CARD_HORIZONTAL_OFFSET card.face_up() def redraw_opp_hand(self): count = len(self.opponent_player_hand) new_middle_x = MIDDLE_X - CARD_HORIZONTAL_OFFSET * (count) / 2 i = 0 for card in self.opponent_player_hand: card.position = new_middle_x + i, SCREEN_HEIGHT - BOTTOM_Y i += CARD_HORIZONTAL_OFFSET card.face_down() def show_top(self, card): self.index = self.current_player_hand.index(card) for i in range(self.index, len(self.current_player_hand) - 1): self.current_player_hand[i] = self.current_player_hand[i + 1] self.current_player_hand[len(self.current_player_hand) - 1] = card def return_down(self, card): for i in range(len(self.current_player_hand) - 1, self.index, -1): self.current_player_hand[i] = self.current_player_hand[i - 1] self.current_player_hand[self.index] = card def finish_round(self): result = self.game.FinishTurn() self.redraw_hand() self.redraw_opp_hand() self.piles = [] for i in range(PILE_COUNT): self.piles.append(arcade.SpriteList()) if result == self.game.NORMAL: self.game.roundStep = ATACK_ROUND self.redraw_hand() self.redraw_opp_hand() if self.game.botTurn == True: self.game.BotAtack() elif result == self.game.TOOK_CARDS: self.game.roundStep = ATACK_ROUND self.redraw_hand() self.redraw_opp_hand() if self.game.botTurn == True: self.game.BotAtack() elif result == self.game.TIE: endgame_label = arcade.gui.UILabel( 'Ничья!', center_x=MIDDLE_X, center_y=MIDDLE_Y, ) self.ui_manager.add_ui_element(endgame_label) elif result == self.game.GAME_OVER: self.window.show_view(GameOverView(self)) def swap_player_draw(self): if self.game.roundStep == ATACK_ROUND: self.game.roundStep = DEFEND_ROUND self.ui_manager.purge_ui_elements() if self.game.botTurn: self.game.BotDefend() else: self.game.takeAllButton = True else: self.game.roundStep = ATACK_ROUND self.game.takeAllButton = False self.game.nextPlayerButton = False self.ui_manager.purge_ui_elements() if self.game.botTurn: self.game.BotAtack() else: self.game.turnDownButton = True self.redraw_hand() self.redraw_opp_hand() def on_mouse_press(self, x, y, button, key_modifiers): if self.game.winner is not None: return if self.game.botTurn == True: return cards = arcade.get_sprites_at_point((x, y), self.current_player_hand) if len(cards) > 0: primary_card = cards[-1] self.held_cards = [primary_card] self.held_cards_original_position = [self.held_cards[0].position] self.show_top(self.held_cards[0]) def on_mouse_motion(self, x: float, y: float, dx: float, dy: float): if self.game.winner is not None: return if self.game.botTurn == True: return for card in self.held_cards: card.center_x += dx card.center_y += dy def on_mouse_release(self, x: float, y: float, button: int, modifiers: int): if self.game.winner is not None: return if len(self.held_cards) == 0: return if self.game.botTurn == True: return pile, distance = arcade.get_closest_sprite(self.held_cards[0], self.pile_mat_list) reset_position = True pile_index = self.pile_mat_list.index(pile) if arcade.check_for_collision( self.held_cards[0], pile) and self.game.roundStep == ATACK_ROUND and len( self.piles[pile_index]) == 0: if self.game.Attack(self.held_cards[0]): for i, dropped_card in enumerate(self.held_cards): dropped_card.position = pile.center_x, pile.center_y self.piles[pile_index].append(self.held_cards[0]) self.game.atackList.append(self.held_cards[0]) self.redraw_hand() self.redraw_opp_hand() self.game.turnDownButton = False reset_position = False elif arcade.check_for_collision( self.held_cards[0], pile) and self.game.roundStep == DEFEND_ROUND and len( self.piles[pile_index]) == 1: if self.piles[pile_index][0] in self.game.atackList: defend = self.game.atackList[self.game.atackList.index( self.piles[pile_index][0])] if self.game.Defend(self.held_cards[0], defend): for i, dropped_card in enumerate(self.held_cards): dropped_card.position = pile.center_x, pile.center_y - CARD_VERTICAL_OFFSET self.piles[pile_index].append(self.held_cards[0]) if len(self.game.atackList) == len(self.game.defendList): self.ui_manager.purge_ui_elements() if len(self.game.OpponentPlayer.hand) == 0: time.sleep(5) self.finish_round() return self.game.nextPlayerButton = True self.ui_manager.add_ui_element(self.next_button) self.game.takeAllButton = False self.redraw_hand() else: self.redraw_hand() self.redraw_opp_hand() reset_position = False if reset_position: for pile_index, card in enumerate(self.held_cards): card.position = self.held_cards_original_position[pile_index] self.return_down(self.held_cards[0]) self.held_cards = []
class Menu: def __init__(self, window, world, show=True): self.window = window self.world = world self.joystick_check = JOYSTICK_CHECK_FREQUENCY self.selected_button = None self.show = show self.ui_manager = UIManager(self.window) self.sprite_list = arcade.SpriteList() def style(button): button.set_style_attrs( font_color=arcade.color.WHITE, font_color_hover=arcade.color.WHITE, font_color_press=arcade.color.WHITE, bg_color=(51, 139, 57), bg_color_hover=(51, 139, 57), bg_color_press=(28, 71, 32), border_color=(51, 139, 57), border_color_hover=arcade.color.WHITE, border_color_press=arcade.color.WHITE, ) half_width = self.window.width / 2 half_height = self.window.height / 2 panel_height = len(BUTTONS) * (BUTTON_HEIGHT + BUTTON_MARGIN) half_panel_height = panel_height / 2 def button(num, name): offset_y = half_panel_height - (BUTTON_HEIGHT + BUTTON_MARGIN) * num b = UIFlatButton( name, center_x=half_width, center_y=half_height + offset_y, width=BUTTON_WIDTH, height=BUTTON_HEIGHT, ) style(b) self.ui_manager.add_ui_element(b) return b self.buttons = {} for num, name in enumerate(BUTTONS): self.buttons[name] = button(num, name) s = arcade.Sprite("data/images/help-image.png") s.center_x = 640 s.center_y = 150 self.sprite_list.append(s) def highlight_button(self, direction): button_count = len(BUTTONS) first_button = 0 last_button = button_count - 1 if self.selected_button is None: if direction > 0: self.selected_button = first_button else: self.selected_button = last_button else: self.selected_button += direction if self.selected_button < 0: self.selected_button = last_button if self.selected_button == button_count: self.selected_button = first_button for i, name in enumerate(BUTTONS): button = self.buttons[name] button.hovered = i == self.selected_button def update(self, dt): for _, input_source in self.world.get_component(InputSource): if input_source.state.get(MENU): self.show = True if self.show: self.joystick_check += dt menu_activator = None if self.joystick_check > JOYSTICK_CHECK_FREQUENCY: check_joysticks(self.world) self.joystick_check = 0 for e, source in self.world.get_component(InputSource): source.state.update() events = source.state.events for event in list(events): if event.input == DOWN: self.highlight_button(1) events.remove(event) if event.input == UP: self.highlight_button(-1) events.remove(event) if event.input == ACTIVATE and self.selected_button is not None: menu_activator = source arcade_button = self.buttons[BUTTONS[self.selected_button]] arcade_button.pressed = True arcade_button.hovered = False self.selected_button = None events.remove(event) if self.buttons[BUTTON_PLAY].pressed: self.show = False if menu_activator is None: for _, input_source in self.world.get_component(InputSource): if input_source.name == "Keyboard": menu_activator = input_source self.spawn_player(menu_activator) self.buttons[BUTTON_PLAY].pressed = False if self.buttons[BUTTON_RESTART].pressed: dispatch(self.world, RESTART_GAME) self.buttons[BUTTON_RESTART].pressed = False if self.buttons[BUTTON_EXIT].pressed: arcade.close_window() def draw(self): self.ui_manager.on_draw() self.sprite_list.draw() def is_started(self, input_source): for _, pc in self.world.get_component(Player): if pc.input_source == input_source: return True return False def spawn_player(self, input_source): is_started = self.is_started(input_source) if not is_started: player.create_player(self.world, input_source)
class Game(arcade.Window): # Играют по очереди, сначала делает ход первый игрок, потом второй и т.д. hosts: list = [ ] # список хостов (фракций) игроков (хост - играбельный объект, т.е. страна) hosts_num = 2 active_host: int # номер текущего активного хоста (тот, который играет) game_iteration: int # номер хода host_init_pos = {0: (1, 10), 1: (8, 1)} gamer_host: int state = None select_color = "BLUE" select2_color = "COLUMBIA_BLUE" ui_margin_left = None ui_margin_top = None game_over = False def __init__(self): self.state = GameState() self.map = HexMap(hex_radius=MAP_HEX_RADIUS) self.w, self.h = self.map.get_window_size() super().__init__(self.w + self.w // 4, self.h, "Poliyoy") arcade.set_background_color(arcade.color.BLACK) self.ui_manager = UIManager() self.ui_margin_left = self.w / 15 self.ui_margin_top = self.h / 10 self.game_iteration = 0 self.setup() def __new__(cls): if not hasattr(cls, 'instance'): cls.instance = super(Game, cls).__new__(cls) return cls.instance def init_hosts(self): for (e, frac) in enumerate(FRACTIONS_CONFIG.keys()): self.hosts.append(Fraction(**FRACTIONS_CONFIG[frac])) fraction = self.hosts[-1] self.state.append_fraction(fraction) if not fraction.isBot: self.active_host = e self.gamer_host = e self.map.place_fraction(fraction, self.host_init_pos[fraction.fraction_id]) self.state.set_fraction(self.gamer_host) def setup(self): """ Здесь рендеринг UI и инициализация пользовательской fraction Например, разместить сущности стран на карте :return: """ self.map.create_map() self.init_hosts() self.after_init() # размещение на карте деревьев и т.п. # self.map.after_init(self.hosts) # размещение на карте деревьев и т.п. self.ui_manager.purge_ui_elements() set_ui(self) # back = self.state.last_mouse_tile_pos # back2 = self.state.last_fraction # self.hosts[not self.active_host].money_amount = 9999 # # pos = self.hosts[not self.active_host].fraction_capital_pos # self.state.last_mouse_tile_pos = pos # self.state.last_fraction = self.hosts[not self.active_host] # obj = SpawnEntity(self.map, self.state, 1, UpdateGameState(self)) # obj.execute() # self.state.last_mouse_tile_pos = back # self.state.last_fraction = back2 # sys.exit() def after_init(self): """ Запуск после размещения fractions :return: """ trees = self.map.get_random_positions() from config import TREE_ID fr = self.state.get_last_fraction() for i in trees: self.map.spawn_tree(i, fr) def on_draw(self): """ Рендеринг различных объектов """ # This command has to happen before we start drawing arcade.start_render() self.map.draw() self.ui_manager.on_draw() def on_next_step_key_press(self): # print("before", self.hosts[1].money_amount) for host in self.hosts: for tile in host.tiles: self.map.unuse_entity(tile) self.game_over = self.state.get_last_fraction().make_step() self.update_screen_info() self.game_iteration += 1 self.active_host = not self.active_host self.state.set_fraction(self.active_host) # upd last host self.update_screen_info() fraction = self.state.get_last_fraction() # if fraction.village_cost_prev != fraction.village_cost: self.update_village_btn() def update_screen_info(self): self.ui_manager.find_by_id("money_amount").text = "Gold: " + str( self.state.get_last_fraction().money_amount) self.ui_manager.find_by_id("money_step").text = "Delta: " + str( self.state.get_last_fraction().step_delta) def update_village_btn(self): # Тяжелая операция, поэтому случай обрабатывается отдельно # # Дальше костыль для обновления текста кнопки (в либе такое, почему-то, не предусмотрено) update_ui(self) def on_mouse_press(self, x, y, button, modifiers): """ Обработка пользовательского действия """ col, row = self.map.locate(x, y) host = self.state.get_last_fraction() pos = (col, row) self.map.unselect_tiles() if button == 1: if self.map.is_in_map(col, row): self.map.add_tile_to_state(pos) self.map.select_tile(pos, self.select_color) self.state.set_pos(col, row) if pos in host.units_pos.keys(): self.map.show_move_range(pos, self.select_color, self.select2_color) elif button == 4: unit_pos = self.state.last_mouse_tile_pos if unit_pos in host.units_pos.keys(): self.state.last_mouse_right_tile_pos = pos command = MoveUnit(self.map, self.state, UpdateGameState(self)) command.execute() if pos in host.tiles.keys(): pass # print(self.active_host, self.state.get_last_fraction().fraction_id) def possible_moves(self, pos): return self.map.show_move_range_quiet(pos) def bot_move(self): pass