def __create_horn(self): self.horn = Horn((70, 300)) self.spells.append(self.horn) self.updateable_items.append(self.horn)
class SpellCraftingManager(Updateable): def __init__(self): self.updateable_items = list() self.spells = list() self.horn = None self.__create_horn() self.__create_all_spell_templates() def __create_horn(self): self.horn = Horn((70, 300)) self.spells.append(self.horn) self.updateable_items.append(self.horn) def __create_all_spell_templates(self): self.add_spell_as_template(SpellLumen((50, 550))) self.add_spell_as_template(SpellTemperatus((120, 550))) def add_spell_as_template(self, spell): spell.is_draggable = False spell.is_template = True self.updateable_items.append(spell) def create_new_spell_from_template(self, template): new_spell = template.create_instance() self.spells.append(new_spell) self.updateable_items.append(new_spell) return new_spell def destroy_spell(self, spell): self.spells.remove(spell) self.updateable_items.remove(spell) spell.unlink_chain() def __on_spell_clicked(self, spell): if spell.is_template: new_spell = self.create_new_spell_from_template(spell) new_spell.grab() else: for other_spell in spell.links_out: other_spell.grab() def __remove_dead_spells(self): for spell in [x for x in self.spells if x is not self.horn]: if not self.horn.is_linked_to(spell): self.destroy_spell(spell) def process_event(self, event): for item in self.updateable_items: item.process_event(event) if event.type == Event.SPELLCLICKED: self.__on_spell_clicked(event.spell) if event.type == pygame.MOUSEMOTION: self.__handle_floating_spell_links() if event.type == Event.SPELLRELEASED: self.__handle_floating_spell_links() self.__notify_remove_dead_spells() self.horn.update_power() if event.type == Event.REMOVEDEADSPELLS: self.__remove_dead_spells() if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: pass def update(self, time_step): for item in self.updateable_items: item.update(time_step) self.__handle_collisions_between_spells(time_step) def draw(self, surface): for item in self.updateable_items: item.draw(surface) def __handle_collisions_between_spells(self, time_step): for n, spell in enumerate(self.spells): for other_spell in self.spells[n + 1:]: if self.__spells_are_colliding(spell, other_spell): self.__move_spells_apart(spell, other_spell, time_step) def __handle_floating_spell_links(self): for spell in self.spells: spell.unlink_local() self.__relink_all_spells(150) def __relink_all_spells(self, max_link_range): for spell in self.spells: free_link_slots = spell.free_link_slots_in # create a list of key-value pairs as tuples. key=distance, value=spell object distance_spell_pairs = [(spell.distance_to_squared(x), x) for x in self.spells if x is not spell and x.position[0] < spell.position[0]] candidates = sorted((x for x in distance_spell_pairs if x[0] < max_link_range**2 and x[1].free_link_slots_out > 0), key=lambda y: y[0])[:free_link_slots] for distance, other_spell in candidates: spell.link_input_to(other_spell) @staticmethod def __notify_remove_dead_spells(): evt = pygame.event.Event(Event.REMOVEDEADSPELLS) pygame.event.post(evt) @staticmethod def __spells_are_colliding(spell, other_spell): dist = spell.radius + other_spell.radius if spell.distance_to_squared(other_spell) <= dist**2: return True return False @staticmethod def __move_spells_apart(spell, other_spell, time_step): # normalised direction vector direction = (spell.position[0] - other_spell.position[0], spell.position[1] - other_spell.position[1]) hypothenuse = (direction[0]**2 + direction[1]**2)**0.5 if hypothenuse > 0: direction = (direction[0] / hypothenuse, direction[1] / hypothenuse) else: direction = (0, 1) # push spells apart speed = time_step * 50 if spell.is_draggable and not spell.is_template and not spell.is_dragging: spell.position = (spell.position[0] + direction[0] * speed, spell.position[1] + direction[1] * speed) if other_spell.is_draggable and not other_spell.is_template and not other_spell.is_dragging: other_spell.position = (other_spell.position[0] - direction[0] * speed, other_spell.position[1] - direction[1] * speed)