def draw(self, surface, left: int, top: int) -> None: self.calculate_rays(surface, left, top) for plop_id, plop in self.plops.items(): plop.draw(surface, 0, 0) get_state().set_plopped_towers(self.plops)
def next_frame(self, clock_tick) -> bool: """ Calculates the next frame of simulation of the game round. Returning True if the game round has a next frame Returns False if the game round has finished :param clock_tick: :return: """ state = get_state() if not get_state().is_paused(): state.set_round_finished(False) self.sim_time += clock_tick self.move_existing_critters(clock_tick) self.maybe_spawn_new_critter() self.maybe_kill_critters() self.reload_towers() all_critters_killed = self.all_critters_killed() if all_critters_killed: state.credit_money(state.get_round_number() * 3) state.set_round_finished(True) return not all_critters_killed
def __init__(self, game_board: Board, game_round: Round, round_number: int): logging.info(f"Starting round {round_number}") self.sim_time = 0 self.board = game_board self.spawn_timers = self.generate_spawn_timers(game_round, round_number) self.reload_timers = {} get_state().set_paused(True) get_state().set_round_number(round_number)
def update_mouse(self, mouse_position, mouse_clicked) -> None: state = get_state() if self.deselect_rect.collidepoint(mouse_position): state.set_hover(self, True) if mouse_clicked: get_state().set_selected_tower_definition(None) else: state.set_hover(self, False)
def maybe_spawn_new_critter(self): if len(self.spawn_timers) <= 0: return next_spawn_time, next_critter_partial = self.spawn_timers[0] if self.sim_time >= next_spawn_time: next_critter = next_critter_partial() logging.debug(f"Spawning new critter: {next_critter.critter_id}") next_critter.set_pixel_path(self.board.get_random_pixel_path()) get_state().add_critter(next_critter) self.spawn_timers.pop(0)
def draw(self, surface, left: int, top: int) -> None: cursor_to_draw = self.determine_cursor() ctd_rect = cursor_to_draw.get_rect() rectangle = pygame.Rect( self.mouse_position[0], self.mouse_position[1], ctd_rect.width, ctd_rect.height, ) get_state().set_cursor_rect(rectangle) surface.blit(cursor_to_draw, rectangle)
def update_mouse(self, mouse_position, mouse_clicked) -> None: state = get_state() if self.rect.colliderect(get_state().get_cursor_rect()): state.set_hover(self, True) state.set_cursor_in_buildable_space(False) if mouse_clicked: selected_tower_definition = state.get_selected_tower_definition( ) if selected_tower_definition is None: state.set_selected_ploppable(self.ploppable) else: state.set_hover(self, False)
def draw_upgrade_background(self, surface, left: int, top: int) -> None: background_rectangle = pygame.Rect(left + 1, top + 1, 58, 38) color_to_draw = ( BUTTON_COLOR_HOVER if get_state().get_hover(self) else BUTTON_COLOR ) pygame.draw.rect(surface, color_to_draw, background_rectangle)
def add_clock_tick(self, clock_tick: int) -> None: if not get_state().is_paused(): self.clock_tick_acc += clock_tick if self.slow_since > -1 and self.clock_tick_acc - self.slow_since >= 1000: logging.debug(f"Speeding up {self.critter_id} - {self.slow_since}") self.slow_since = -1
def all_critters_killed(self) -> bool: state = get_state() alive_critters = len(state.get_critters()) critters_left_to_spawn = len(self.spawn_timers) return alive_critters <= 0 and critters_left_to_spawn <= 0
def update_mouse_clicked(self, mouse_position, mouse_clicked) -> None: state = get_state() if get_state().is_cursor_in_buildable_space(): if self.rect.colliderect(get_state().get_cursor_rect()): if mouse_clicked: selected_tower_definition = state.get_selected_tower_definition() price = ( selected_tower_definition.level_one_price if selected_tower_definition else 0 ) plop_success = try_to_plop(mouse_position) if plop_success and price > 0: state.spend_money(price)
def draw_background( self, surface, left: int, top: int, is_selected: bool = False, is_enabled: bool = True, ) -> None: width = 148 height = 48 rectangle = pygame.Rect(left + 1, top + 1, width, height) self.rect = rectangle color_to_draw = BACKGROUND_COLOR if is_selected: color_to_draw = BACKGROUND_COLOR_SELECTED elif get_state().get_hover(self): color_to_draw = BACKGROUND_COLOR_HOVER if self.clicked: color_to_draw = BACKGROUND_COLOR_CLICKED if not is_enabled: color_to_draw = BACKGROUND_COLOR_DISABLED pygame.draw.rect(surface, color_to_draw, rectangle)
def update_mouse(self, mouse_position, mouse_clicked) -> None: state = get_state() is_enabled = (get_state().get_current_money() >= self.tower_definition.level_one_price) if self.rect.collidepoint(mouse_position) and is_enabled: state.set_hover(self, True) if mouse_clicked: state.set_selected_tower_definition(self.tower_definition) state.set_selected_ploppable(None) self.clicked = True else: self.clicked = False else: state.set_hover(self, False)
def maybe_kill_critters(): state = get_state() critters = state.get_critters() for critter in critters: if critter.health <= 0: state.mark_critter_for_despawn(critter) state.credit_money(int(critter.starting_health * 0.01))
def update_mouse(self, mouse_position, mouse_clicked) -> None: state = get_state() if self.rect.colliderect(state.get_cursor_rect()): if state.get_selected_tower_definition(): state.set_hover(self, True) else: state.set_hover(self, False)
def draw_lives(self, surface, left: int, top: int) -> None: lives_rect = pygame.Rect(left + 100, top + 15, 0, 0) surface.blit(self.lives_sprite, lives_rect) lives_label = LABEL_FONT.render( str(get_state().get_lives()), True, LABEL_FONT_COLOR ) lives_label_rect = pygame.Rect(left + 135, top + 18, 0, 0) surface.blit(lives_label, lives_label_rect)
def draw(self, surface, left: int, top: int) -> None: self.draw_border(surface, left, top) if not self.tower.is_upgradeable(): self.draw_tower_max_level_button(surface, left, top) elif self.tower.get_upgrade_price() > get_state().get_current_money(): self.draw_upgrade_unaffordable_button(surface, left, top) else: self.draw_upgrade_button(surface, left, top)
def delete_plop(plop_id: str) -> None: logging.info(f"Deleting plop - {plop_id}") state = get_state() if state.get_selected_ploppable().get_plop_id() == plop_id: state.set_selected_ploppable(None) plopped_master = get_plopped_master() plopped_master.remove_plopped(plop_id) logging.info(f"{plop_id} removed")
def update_mouse(self, mouse_position, mouse_clicked) -> None: state = get_state() selected_ploppable = state.get_selected_ploppable() selected_critter = state.get_selected_critter() if selected_ploppable: self.tower_manager.update_mouse(mouse_position, mouse_clicked) elif selected_critter: self.critter_viewer.update_mouse(mouse_position, mouse_clicked)
def create_new_reload_timers(self): state = get_state() for tower in state.get_all_plopped_towers(): if ( not tower.is_reloaded() and tower.get_plop_id() not in self.reload_timers ): reload_time = tower.ploppable.get_tower_stats()["reload_time"] self.reload_timers[tower.get_plop_id()] = self.sim_time + reload_time
def draw(self, surface, left: int, top: int) -> None: width = 40 height = 40 rectangle = pygame.Rect(left, top, width, height) self.rect = rectangle color_to_draw = (WATER_COLOR_HOVER if get_state().get_hover(self) else WATER_COLOR) pygame.draw.rect(surface, color_to_draw, rectangle)
def update_mouse(self, mouse_position, mouse_clicked) -> None: state = get_state() if self.close_button_rect.collidepoint(mouse_position): state.set_hover(self, True) if mouse_clicked: state.set_selected_critter(None) else: state.set_hover(self, False)
def update_mouse(self, mouse_position, mouse_clicked) -> None: state = get_state() if self.rect.collidepoint(mouse_position): state.set_hover(self, True) if mouse_clicked: if self.clock_tick - self.last_interacted_clock_tick > 250: state.set_paused(not state.is_paused()) self.last_interacted_clock_tick = self.clock_tick else: state.set_hover(self, False)
def draw(self, surface, left: int, top: int) -> None: self.draw_border(surface, left, top) self.draw_background(surface, left, top) state = get_state() selected_ploppable = state.get_selected_ploppable() selected_critter = state.get_selected_critter() if selected_ploppable: self.tower_manager.set_tower(selected_ploppable) self.tower_manager.draw(surface, left, top) elif selected_critter: self.critter_viewer.set_critter(selected_critter) self.critter_viewer.draw(surface, left, top)
def check_current_critters(self): state = get_state() expected_critter_ids = set(self.critter_elements.keys()) actual_critter_ids = set(state.get_critter_ids()) new_critter_ids = actual_critter_ids - expected_critter_ids dead_critter_ids = expected_critter_ids - actual_critter_ids for new_critter_id in new_critter_ids: self.critter_elements[new_critter_id] = CritterElement( state.get_critter(new_critter_id)) for dead_critter_id in dead_critter_ids: del self.critter_elements[dead_critter_id]
def update_mouse(self, mouse_position, mouse_clicked) -> None: state = get_state() if self.get_collision_rect().collidepoint(mouse_position): if self.is_button_enabled(): state.set_hover(self, True) if mouse_clicked: if self.clock_tick - self.last_interacted_clock_tick > 250: self.button_functionality() self.last_interacted_clock_tick = self.clock_tick else: state.set_hover(self, False) else: state.set_hover(self, False)
def draw_close_button(self, surface, left: int, top: int) -> None: border_rectangle = pygame.Rect(left + 65, top + 105, 60, 40) pygame.draw.rect(surface, CLOSE_BUTTON_BORDER_COLOR, border_rectangle) self.close_button_rect = border_rectangle background_rectangle = pygame.Rect(left + 66, top + 106, 58, 38) color_to_draw = (CLOSE_BUTTON_HOVER_COLOR if get_state().get_hover(self) else CLOSE_BUTTON_COLOR) pygame.draw.rect(surface, color_to_draw, background_rectangle) x_label = CLOSE_BUTTON_FONT.render("X", True, CLOSE_BUTTON_FONT_COLOR) x_rectangle = pygame.Rect(left + 80, top + 108, 0, 0) surface.blit(x_label, x_rectangle)
def draw(self, surface, left: int, top: int) -> None: # width = 60 # height = 50 # # rectangle = pygame.Rect(left, top, width, height) # pygame.draw.rect(surface, LIME, rectangle) is_paused = get_state().is_paused() self.draw_border(surface, left, top, is_paused) self.draw_background(surface, left, top, is_paused) if is_paused: self.draw_resume_icon(surface, left, top) else: self.draw_pause_icon(surface, left, top)
def update_mouse(self, mouse_position, mouse_clicked) -> None: state = get_state() if self.rect.collidepoint(mouse_position): state.set_cursor_in_playable_space(True) state.set_cursor_in_buildable_space(True) for column in range(0, 20): for row in range(0, 20): self.tiles[f"{column}~{row}"].update_mouse( mouse_position, mouse_clicked ) else: state.set_cursor_in_playable_space(False)
def reload_towers(self): state = get_state() self.create_new_reload_timers() mark_reloaded = [] for tower_id, reload_time in self.reload_timers.items(): if self.sim_time >= reload_time: plopped_tower = state.get_plopped_tower(tower_id) if plopped_tower: plopped_tower.reload() mark_reloaded.append(tower_id) for tower_id in mark_reloaded: if tower_id in self.reload_timers: del self.reload_timers[tower_id]