def __init__(self, previousScene): """ @param previousScene: The scene which should come after this help @summary: Initializes a help frame """ Scene.__init__(self) self.previousScene = previousScene self.frame = Frame() text = "Welcome to gravity snails\n" text += "=========================\n" text += "\n" text += "You can shoot the snails and the terrain beneath them\n" text += "Snails die if they touch the salt\nor when they are out of hitpoints\n" text += "\nCONTROLS\n=========================\n\n" text += "LEFT MOUSE BUTTON:\nplace snails in the screen\n\n" text += "ARROW KEYS:\nmove and target\n\n" text += "SPACE BAR:\nfire the active weapon\n\n" text += "RIGHT MOUSE BUTTON:\nswitch weapon\n\n" text += "\n" labelText = Label(text) labelText.centerLines = False labelText.rect.center = (self.frame.rect.width / 2, self.frame.rect.height / 2) self.frame.addWidget(labelText) buttonBack = Button("Back", self.runPreviousScene) buttonBack.rect.size = (128, 32) buttonBack.rect.centerx = self.frame.rect.width / 2 buttonBack.rect.bottom = self.frame.rect.height - 32 self.frame.addWidget(buttonBack)
def __init__(self, x=0, y=0, ai=False, t=0): self.x, self.y = x, y # position to draw troop self.health = 100 # troop's health self.ai = ai # flag for specifying if troop is ai self.type = t # 0 = default, 1 = medic, 2 = sniper if self.type == 2: self.health = 75 self.default_stats() # default all troops state # read in sprite image for troop # if ai, flip the image if self.ai and self.type == 0: self.image = pygame.transform.flip(pygame.image.load(os.path.join('assets', 'ai_commando.png')), True, False) elif self.ai and self.type == 1: self.image = pygame.transform.flip(pygame.image.load(os.path.join('assets', 'ai_medic.png')), True, False) elif self.ai and self.type == 2: self.image = pygame.transform.flip(pygame.image.load(os.path.join('assets', 'ai_soldier.png')), True, False) elif not self.ai and self.type == 0: self.image = pygame.image.load(os.path.join('assets', 'player_commando.png')) elif not self.ai and self.type == 1: self.image = pygame.image.load(os.path.join('assets', 'player_medic.png')) else: self.image = pygame.image.load(os.path.join('assets', 'player_soldier.png')) # rectangle surrounding troop (useful for detecting clicks) self.rect = self.image.get_rect() self.rect.center = int(self.x), int(self.y) # label for drawing troops health self.health_label = Label(str(int(self.health)), size=15)
def __init__(self, position_rect, images): global combat_event_types super(CombatRenderer, self).__init__(position_rect, True) self.mask = None self.active = False self.images = images self.phase = None attacker_rect = Rect(self.rect.x, self.rect.y + 30, self.rect.width, self.rect.height / 2 - 15) self.attacker_renderer = group_panel.CombatRenderer( "Attackers:", attacker_rect) defender_rect = Rect(self.rect.x, attacker_rect.y + attacker_rect.height, self.rect.width, self.rect.height / 2 - 15) self.defender_renderer = group_panel.CombatRenderer( "Defenders:", defender_rect) width, height = 120, 20 x, y = self.rect.x + self.rect.width / 2 - width / 2, attacker_rect.y + attacker_rect.height - 20 self.attacker_label = Label(Rect(x, y, width, height), None) y = defender_rect.y + defender_rect.height - 28 self.defender_label = Label(Rect(x, y, width, height), None) self.add_child(self.attacker_renderer) self.add_child(self.defender_renderer) self.add_child(self.attacker_label) self.add_child(self.defender_label) event_manager.add_listener_multi(self.handle_game_events, combat_event_types)
def render(self): self.clear() self.cursor.draw(self.mouse_x, self.mouse_y) self.cursor_info = Label(f'x: {self.mouse_x}, y: {self.mouse_y}', self.width - 310, self.height - 36) self.cursor_info.draw() self.flip()
class MainWindow(pyglet.window.Window): def __init__(self, *args, **kwrgs): super().__init__(*args, **kwrgs) pyglet.gl.glClearColor(0.9, 0.9, 0.9, 1) self.background = pyglet.graphics.Batch() self.cursor = Cursor(self.background) self.x, self.y = 0, 0 self.cursor_info = Label(f'x: {self.x}, y: {self.y}', self.width - 50, self.height - 36) self.keys = {} self.mouse_x = 0 self.mouse_y = 0 self.alive = 1 def on_draw(self): self.render() def on_close(self): self.alive = 0 def on_mouse_motion(self, x, y, dx, dy): self.mouse_x = x self.mouse_y = y def on_key_release(self, symbol, modifiers): try: del self.keys[symbol] except: pass def on_key_press(self, symbol, modifiers): if symbol == key.ESCAPE: # [ESC] self.alive = 0 self.keys[symbol] = True def render(self): self.clear() self.cursor.draw(self.mouse_x, self.mouse_y) self.cursor_info = Label(f'x: {self.mouse_x}, y: {self.mouse_y}', self.width - 310, self.height - 36) self.cursor_info.draw() self.flip() def run(self): while self.alive == 1: self.render() event = self.dispatch_events()
def __init__(self, text='', x=0, y=0, rad=5, fc=(255, 255, 255), bc=(0, 0, 0), ai=False): self.x = x self.y = y self.label = Label(text, x, y, size=(rad - 1)) self.fill_color = fc self.border_color = bc self.radius = rad if rad > 5 else 5 # minimum radius is 5 self.ai = ai
def __init__(self, *args, **kwrgs): super().__init__(*args, **kwrgs) pyglet.gl.glClearColor(0.9, 0.9, 0.9, 1) self.background = pyglet.graphics.Batch() self.cursor = Cursor(self.background) self.x, self.y = 0, 0 self.cursor_info = Label(f'x: {self.x}, y: {self.y}', self.width - 50, self.height - 36) self.keys = {} self.mouse_x = 0 self.mouse_y = 0 self.alive = 1
def createWidgets(self): """Creates all widgets for the dialog. Depending on wether we're a server or a client different widgets will be shown.""" # are we a server? if not scenario.run_as_server: # we're running as client. need an additional label and editfield for the hostname self.wm.register( Label(self.smallfont, "Server host: ", (250, 240), color=(255, 255, 255))) self.host = EditField(self.smallfont, "localhost", 200, (450, 240), color=(255, 255, 0), background=(80, 80, 80)) self.wm.register(self.host) # common widgets self.wm.register( Label(self.titlefont, "Setup network information", (10, 10), color=(255, 0, 0))) self.wm.register( Label(self.smallfont, "Server port: ", (250, 300), color=(255, 255, 255))) self.port = EditField(self.smallfont, str(properties.network_port), 200, (450, 300), color=(255, 255, 0), background=(80, 80, 80)) self.wm.register(self.port) # buttons self.wm.register( Button(properties.path_dialogs + "butt-ok-moff.png", properties.path_dialogs + "butt-ok-mover.png", (284, 650), {widget.MOUSEBUTTONUP: self.ok})) self.wm.register( Button(properties.path_dialogs + "butt-back-moff.png", properties.path_dialogs + "butt-back-mover.png", (528, 650), {widget.MOUSEBUTTONUP: self.back}))
def __init__(self, position_rect): super(StatusRenderer, self).__init__(position_rect) self.pad = 4 self.last_event = None event_manager.add_listener(self.handle_events, event_manager.DAY_START) event_manager.add_listener(self.handle_events, event_manager.RANDOM_EVENT) event_manager.add_listener(self.handle_events, event_manager.PLAYER_STATUS_CHANGE) event_manager.add_listener(self.handle_events, event_manager.HEX_SELECTED) # x = self.rect.x + 164 + 2*(image.UI_ICON_WIDTH + 10) # y = self.rect.y + 8 x = self.rect.x + 114 + image.UI_ICON_WIDTH y = self.rect.y + self.pad width = 50 height = self.rect.height - self.pad self.gold_label = Label(Rect(x, y, width, height), "", font=text.lg_font) x += image.UI_ICON_WIDTH + 55 self.income_label = Label(Rect(x, y, width, height), "", font=text.lg_font) x += image.UI_ICON_WIDTH + 55 self.rep_label = Label(Rect(x, y, width, height), "", font=text.lg_font) x += image.UI_ICON_WIDTH + 53 self.fame_label = Label(Rect(x, y, width, height), "", font=text.lg_font) x += 400 self.zone_label = Label(Rect(x, y, width, height), "", font=text.lg_font) self.add_child(self.income_label) self.add_child(self.gold_label) self.add_child(self.rep_label) self.add_child(self.fame_label) self.add_child(self.zone_label)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Whether or not the window exclusively captures the mouse. self.exclusive = False # The crosshairs at the center of the screen. self.reticle = Reticle(1.0) # Instance of the model that handles the world. self.model = Model() # Instance of Player object self.player = Player(self.model) # The label that is displayed in the top left of the canvas. self.label = Label(x=20, y=self.height - 20) # The label that is displayed in the bottom left of the canvas. self.label_bottom = Label(x=20, y=20) # The command console where you can input things. self.console = Console(self, "", 100, 100) # Whether are you typing in the console, or not. self.is_typing = False self.FOV = MAX_FOV self.input = InputHandler(self) self.renderer = Renderer(self) self.vector = self.player.get_sight_vector() self.target_block = self.model.hit_test(self.player.position, self.vector)[0] self.reticle.create(self.width / 2, self.height / 2) self.prev_pos = 0, 0, 0 self.schedule_updates()
def mark_selected(self, index): if self.selected_item != None and self.selected_item != index: # deselect previous selection self.item_icons[self.selected_item[0] * hero.BACKPACK_SIZE + self.selected_item[1]].mark_selected(False) self.selected_item = index # clear old trait labels for trait_label in self.trait_labels: self.remove_child(trait_label) self.trait_labels = [] if index == None: return column, row = self.selected_item selected_item = self.unit.get_equipped_item(row) if column == EQUIP_SLOT else self.unit.get_backpack_item(row) if selected_item == None: return x = self.rect.x + 32 + image.ITEM_ICON_WIDTH * 2 + 20 y = self.rect.y + 32 name_label = Label(Rect(x, y, self.rect.width/2, 20), selected_item.get_name()) #,font = text.lg_font) self.trait_labels.append(name_label) self.add_child(name_label) traits = selected_item.get_traits() #x_index = 0 y += 18 value_label = Label(Rect(x, y, self.rect.width/2, 12), "Value: " + str(selected_item.get_gold_value())) self.trait_labels.append(value_label) self.add_child(value_label) y += 18 for curr_trait in traits: trait_text = trait.trait_str(curr_trait, traits[curr_trait]) trait_label = Label(Rect(x, y, self.rect.width/2, 12), trait_text, tool_tip_text = trait.tool_tip_table[curr_trait]) self.add_child(trait_label) self.trait_labels.append(trait_label) y += 14 self.show()
class CircleLabel: def __init__(self, text='', x=0, y=0, rad=5, fc=(255, 255, 255), bc=(0, 0, 0), ai=False): self.x = x self.y = y self.label = Label(text, x, y, size=(rad - 1)) self.fill_color = fc self.border_color = bc self.radius = rad if rad > 5 else 5 # minimum radius is 5 self.ai = ai def render(self, surface): pygame.draw.circle(surface, self.border_color, (self.x, self.y), self.radius) pygame.draw.circle(surface, self.fill_color, (self.x, self.y), self.radius - 3) if not self.ai: self.label.render(surface) def set_text(self, text): self.label.set_text(text) def set_pos(self, pos): self.x, self.y = pos def set_radius(self, radius): self.radius = radius def set_fill_color(self, fc): self.fill_color = fc def set_border_color(self, bc): self.border_color = bc
def update_labels(self, labels): if len(labels) == 3: self.left = Label(labels[0], x=(self.width * 0.2), y=(self.y + self.height / 2)) self.middle = Label(labels[1], x=(self.width * 0.5), y=(self.y + self.height / 2)) self.right = Label(labels[2], x=(self.width * 0.8), y=(self.y + self.height / 2))
def __init__(self, position_rect, images): super(HexInfoRenderer, self).__init__(position_rect) self.engineering_active = False self.selected_hex = None # probably need to allow for some padding in these calculations self.site_rect = Rect(self.rect.x, self.rect.y, self.rect.width / 4, self.rect.height) def hire_callback(toggle_down): if toggle_down: self.for_hire_renderer.show() self.garrison_renderer.hide() else: self.for_hire_renderer.hide() self.garrison_renderer.show() def upgrade_callback(): upgrade_dialog = UpgradeDialog(250, 300, "Site Upgrades", self.selected_hex.site) upgrade_dialog.show() x, y = self.site_rect.x + self.site_rect.width / 4, self.site_rect.y + ( self.site_rect.height * 3) / 4 width, height = self.site_rect.width / 4, self.site_rect.height / 8 self.upgrade_button = Button(Rect(x, y, width, height), "Upg.", upgrade_callback) self.hire_button = Toggle(Rect(x + width + 8, y, width, height), "Hire", hire_callback) self.add_child(self.hire_button) self.add_child(self.upgrade_button) active_group_rect = Rect(self.rect.x + self.site_rect.width, self.rect.y + 1, (3 * self.rect.width) / 4, image.UNIT_HEIGHT + 8) self.active_group_renderer = group_panel.OccupantRenderer( "Active", active_group_rect, False) x = active_group_rect.x + (active_group_rect.width) / 2 y = active_group_rect.y + active_group_rect.height + 12 def transfer_callback(): component.post_ui_event(component.KEY_DOWN, unicode='t', key='t') self.transfer_button = Button(Rect(x, y, image.SM_BUTTON_WIDTH, image.SM_BUTTON_HEIGHT), images.transfer, transfer_callback, image_label=True, tool_tip_text="transfer (t)") x += image.SM_BUTTON_WIDTH + 4 def disband_callback(): component.post_ui_event(component.KEY_DOWN, unicode='x', key='x') self.disband_button = Button(Rect(x, y, image.SM_BUTTON_WIDTH, image.SM_BUTTON_HEIGHT), images.disband, disband_callback, image_label=True, tool_tip_text="disband (x)") self.add_child(self.transfer_button) self.add_child(self.disband_button) self.transfer_button.hide() self.disband_button.hide() y = self.disband_button.rect.y + self.disband_button.rect.height + 2 second_group_rect = Rect(self.rect.x + self.site_rect.width, y, (3 * self.rect.width) / 4, self.rect.height - (y - self.rect.y)) self.garrison_renderer = group_panel.OccupantRenderer( "Garrison", second_group_rect, True) self.for_hire_renderer = group_panel.HireRenderer( "Hire", second_group_rect) self.add_child(self.active_group_renderer) self.add_child(self.garrison_renderer) self.add_child(self.for_hire_renderer) self.garrison_renderer.set_partner(self.active_group_renderer) self.active_group_renderer.set_partner(self.garrison_renderer) x = self.rect.x + 34 + image.UI_ICON_WIDTH + 25 y = self.rect.y + 50 + image.UNIT_HEIGHT self.revolt_icon = Label( Rect(x, y, image.UI_ICON_WIDTH, image.UI_ICON_HEIGHT), images.revolt, image_label=True, tool_tip_text="Revolt chance,\nchecked at week start") event_manager.add_listener(self.handle_game_events, event_manager.HEX_SELECTED)
def createLabels(self): "Creates all labels for the dialog." # create the labels report = Label(self.titlefont, "Battle report", (400, 120), color=(255, 255, 0)) result = Label(self.smallfont, self.summary, (400, 160), color=(255, 255, 255)) # create the side headers men = Label(self.titlefont, "Men", (250, 240), color=(255, 180, 100)) guns = Label(self.titlefont, "Guns", (250, 270), color=(255, 180, 100)) score = Label(self.titlefont, "Score", (250, 320), color=(255, 180, 100)) # create the top headers union = Label(self.titlefont, "Union", (350, 200), color=(255, 255, 0)) rebel = Label(self.titlefont, "Confederate", (500, 200), color=(255, 255, 0)) # create result strings for mens and guns unionmenstr = "%d of %d" % (self.men_destroyed[UNION], self.men_ok[UNION]) rebelmenstr = "%d of %d" % (self.men_destroyed[REBEL], self.men_ok[REBEL]) uniongunsstr = "%d of %d" % (self.guns_destroyed[UNION], self.guns_ok[UNION]) rebelgunsstr = "%d of %d" % (self.guns_destroyed[REBEL], self.guns_ok[REBEL]) scorestr = "%d vs %d" % (self.score[UNION], self.score[REBEL]) # and labels too unionmen = Label(self.smallfont, unionmenstr, (350, 250), color=(255, 255, 255)) unionguns = Label(self.smallfont, uniongunsstr, (350, 280), color=(255, 255, 255)) rebelmen = Label(self.smallfont, rebelmenstr, (500, 250), color=(255, 255, 255)) rebelguns = Label(self.smallfont, rebelgunsstr, (500, 280), color=(255, 255, 255)) score2 = Label(self.smallfont, scorestr, (425, 325), color=(255, 255, 255)) # register our labels self.wm.register(report) self.wm.register(result) self.wm.register(union) self.wm.register(rebel) self.wm.register(men) self.wm.register(guns) self.wm.register(score) self.wm.register(score2) self.wm.register(unionmen) self.wm.register(rebelmen) self.wm.register(unionguns) self.wm.register(rebelguns) # buttons self.wm.register( Button(properties.path_dialogs + "butt-ok-moff.png", properties.path_dialogs + "butt-ok-mover.png", (406, 650), {widget.MOUSEBUTTONUP: self.ok}))
class HexInfoRenderer(component.Window): ''' panel that renders info about selected hex, including any site there, any active group of characters/units, and garrison, and any units available for hire. ''' def __init__(self, position_rect, images): super(HexInfoRenderer, self).__init__(position_rect) self.engineering_active = False self.selected_hex = None # probably need to allow for some padding in these calculations self.site_rect = Rect(self.rect.x, self.rect.y, self.rect.width / 4, self.rect.height) def hire_callback(toggle_down): if toggle_down: self.for_hire_renderer.show() self.garrison_renderer.hide() else: self.for_hire_renderer.hide() self.garrison_renderer.show() def upgrade_callback(): upgrade_dialog = UpgradeDialog(250, 300, "Site Upgrades", self.selected_hex.site) upgrade_dialog.show() x, y = self.site_rect.x + self.site_rect.width / 4, self.site_rect.y + ( self.site_rect.height * 3) / 4 width, height = self.site_rect.width / 4, self.site_rect.height / 8 self.upgrade_button = Button(Rect(x, y, width, height), "Upg.", upgrade_callback) self.hire_button = Toggle(Rect(x + width + 8, y, width, height), "Hire", hire_callback) self.add_child(self.hire_button) self.add_child(self.upgrade_button) active_group_rect = Rect(self.rect.x + self.site_rect.width, self.rect.y + 1, (3 * self.rect.width) / 4, image.UNIT_HEIGHT + 8) self.active_group_renderer = group_panel.OccupantRenderer( "Active", active_group_rect, False) x = active_group_rect.x + (active_group_rect.width) / 2 y = active_group_rect.y + active_group_rect.height + 12 def transfer_callback(): component.post_ui_event(component.KEY_DOWN, unicode='t', key='t') self.transfer_button = Button(Rect(x, y, image.SM_BUTTON_WIDTH, image.SM_BUTTON_HEIGHT), images.transfer, transfer_callback, image_label=True, tool_tip_text="transfer (t)") x += image.SM_BUTTON_WIDTH + 4 def disband_callback(): component.post_ui_event(component.KEY_DOWN, unicode='x', key='x') self.disband_button = Button(Rect(x, y, image.SM_BUTTON_WIDTH, image.SM_BUTTON_HEIGHT), images.disband, disband_callback, image_label=True, tool_tip_text="disband (x)") self.add_child(self.transfer_button) self.add_child(self.disband_button) self.transfer_button.hide() self.disband_button.hide() y = self.disband_button.rect.y + self.disband_button.rect.height + 2 second_group_rect = Rect(self.rect.x + self.site_rect.width, y, (3 * self.rect.width) / 4, self.rect.height - (y - self.rect.y)) self.garrison_renderer = group_panel.OccupantRenderer( "Garrison", second_group_rect, True) self.for_hire_renderer = group_panel.HireRenderer( "Hire", second_group_rect) self.add_child(self.active_group_renderer) self.add_child(self.garrison_renderer) self.add_child(self.for_hire_renderer) self.garrison_renderer.set_partner(self.active_group_renderer) self.active_group_renderer.set_partner(self.garrison_renderer) x = self.rect.x + 34 + image.UI_ICON_WIDTH + 25 y = self.rect.y + 50 + image.UNIT_HEIGHT self.revolt_icon = Label( Rect(x, y, image.UI_ICON_WIDTH, image.UI_ICON_HEIGHT), images.revolt, image_label=True, tool_tip_text="Revolt chance,\nchecked at week start") event_manager.add_listener(self.handle_game_events, event_manager.HEX_SELECTED) def handle_game_events(self, event): if event.type == event_manager.HEX_SELECTED: self.set_hex(event.data['loc']) def set_data(self, map_data, curr_player, curr_mask): self.map_data = map_data self.curr_mask = curr_mask self.curr_player = curr_player # reselect hex to reset what's shown according to new player data self.set_hex(self.selected_hex) def deselect_all(self): self.active_group_renderer.mark_selected(None) self.garrison_renderer.mark_selected(None) self.for_hire_renderer.mark_selected(None) def set_hex(self, new_hex_loc): self.deselect_all() self.upgrade_button.hide() self.hire_button.hide() self.hire_button.reset() self.engineering_active = False if new_hex_loc == None: return self.selected_hex = self.map_data.get_hex(new_hex_loc.x, new_hex_loc.y) if self.selected_hex == None: return self.active_group_renderer.set_data(self.selected_hex, self.curr_player, self.curr_mask) if self.selected_hex.deep_garrison(): self.garrison_renderer.set_data(None, self.curr_player, self.curr_mask) else: self.garrison_renderer.set_data(self.selected_hex, self.curr_player, self.curr_mask) self.for_hire_renderer.set_data(self.selected_hex, self.curr_player, self.curr_mask) self.for_hire_renderer.hide() if self.curr_mask.get_visibility(self.selected_hex.x, self.selected_hex.y) == mask.VISIBLE: self.active_group_renderer.show() self.garrison_renderer.show() else: self.active_group_renderer.hide() self.garrison_renderer.hide() if self.selected_hex.has_site() and self.selected_hex.site.hireable_by( self.curr_player): self.hire_button.show() if self.selected_hex.has_site() and self.selected_hex.site.get_owner( ) == self.curr_player: self.upgrade_button.show() if self.selected_hex.get_active_group() != None: self.transfer_button.show() self.disband_button.show() else: self.transfer_button.hide() self.disband_button.hide() else: self.transfer_button.hide() self.disband_button.hide() self.add_child(self.revolt_icon) self.revolt_icon.hide() def event_handler(self, event): if event.type == component.MOUSE_CLICK: self.deselect_all() return True return super(HexInfoRenderer, self).event_handler(event) def render_site(self, surface, images, active_site, curr_player, mask_player): x = self.site_rect.x + (self.site_rect.width / 2) y = self.site_rect.y + 14 images.text.draw_text(active_site.get_name(), text.lg_font, x, y, surface) y += 16 images.text.draw_text( "Lv. " + str(active_site.level) + " " + active_site.site_type.name, text.sm_font, x, y, surface) y += 16 if active_site.status == site_type.SACKED: status_text = "Sacked" else: status_text = active_site.owner.get_name() images.text.draw_text(status_text, text.sm_font, x, y, surface) # y += 10 x -= image.UNIT_WIDTH / 2 images.draw_site(active_site, surface, mask_player, (x, y)) y += image.UNIT_HEIGHT - 10 icon_y = y x = self.rect.x + 30 if active_site.is_active() and active_site.get_income() != 0: surface.blit(images.income, (x, y)) x += image.UI_ICON_WIDTH + 10 y += image.UI_ICON_WIDTH / 2 images.text.draw_text(str(active_site.get_income()), text.sm_font, x, y, surface) x = self.rect.x + 34 + image.UI_ICON_WIDTH + 25 y = icon_y if active_site.is_active() and active_site.revolt_chance() != 0: self.revolt_icon.show() x = self.revolt_icon.rect.x + image.UI_ICON_WIDTH + 16 y = self.revolt_icon.rect.y + image.UI_ICON_WIDTH / 2 images.text.draw_text( str(int(active_site.revolt_chance() * 100)) + "%", text.sm_font, x, y, surface) else: self.revolt_icon.hide() def render(self, surface, images): super(HexInfoRenderer, self).render(surface, images) if self.selected_hex == None: return mask_state = self.curr_mask.get_visibility(self.selected_hex.x, self.selected_hex.y) if mask_state == mask.NEVER_VISIBLE: return # render site info active_site = self.selected_hex.site if active_site != None: self.render_site(surface, images, active_site, self.curr_player, self.curr_mask.get_player()) # render groups in hex active_group = self.selected_hex.active_group if active_group != None and mask_state == mask.VISIBLE: x, y = self.active_group_renderer.rect.x + 4, self.active_group_renderer.rect.y + 24 if active_group.get_move_mode() == move_mode.NAVAL: surface.blit(images.naval_move, (x, y)) else: surface.blit(images.foot_move, (x, y)) images.text.draw_text(str(active_group.get_moves_left()), text.lg_font, x + image.UI_ICON_WIDTH + 10, y + (image.UI_ICON_HEIGHT / 2), surface) if active_group.get_owner() == self.curr_player: x = self.rect.x + (5 * self.rect.width) / 8 y = self.rect.y + self.rect.height / 2
def set_selected(self, selected_unit): self.selected_unit = selected_unit if self.selected_unit == None: self.hide() return self.clear_children() if selected_unit != None and selected_unit.can_use_items(): self.add_child(self.item_button) if self.can_build(): self.add_child(self.build_button) self.build_button.set_label("Build [" + str( misc_commands.get_build_cost( selected_unit.trait_value(trait.BUILD), selected_unit.get_level())) + "]") if self.can_embassy(): self.add_child(self.embassy_button) self.embassy_button.set_label("Embassy [" + str( misc_commands.get_embassy_cost( self.selected_unit, self.select_hex.site.get_level())) + "]") x = self.rect.x + (self.rect.width / 4) y = self.rect.y + 4 label_height = image.UI_ICON_HEIGHT new_label = Label(Rect(x, y, self.rect.width / 2, label_height), self.selected_unit.get_name(), font=text.lg_font) self.add_child(new_label) y += (label_height * 2) / 3 if self.selected_unit.has_trait(trait.HERO): level_text = "" else: level_text = "Lv. " + str(self.selected_unit.get_level()) new_label = Label(Rect(x, y, self.rect.width / 2, label_height / 2), level_text + " " + self.selected_unit.get_type_text(), font=text.sm_font) self.add_child(new_label) y += label_height / 3 image_icons = [ self.image_data.strength, self.image_data.armor, self.image_data.looting, self.image_data.health ] text_labels = [ str(self.selected_unit.get_strength()), str(self.selected_unit.get_armor()), str(self.selected_unit.get_looting()), str(self.selected_unit.get_health() - self.selected_unit.curr_wounds()) + "/" + str(self.selected_unit.get_health()) ] label_tooltips = [ "Strength (better chance to win combats)", "Armor (better chance block hits)", "Looting (more gold and better loot)", "Health (num. wounds)" ] x = self.rect.x + self.rect.width / 6 for i in range(len(image_icons)): new_label = Label(Rect(x, y, image.UI_ICON_WIDTH, image.UI_ICON_HEIGHT), image_icons[i], image_label=True) self.add_child(new_label) x += image.UI_ICON_WIDTH + 5 new_label = Label(Rect(x, y, 10, image.UI_ICON_HEIGHT), text_labels[i], tool_tip_text=label_tooltips[i]) self.add_child(new_label) x += 10 if x > self.rect.x + self.rect.width - (image.UI_ICON_WIDTH + 15): x = self.rect.x + self.rect.width / 6 y += image.UI_ICON_HEIGHT #y += image.UI_ICON_HEIGHT x += 10 #self.rect.x + self.rect.width / 6 #TODO: other image for flight mode move_icon = self.image_data.naval_move if self.selected_unit.get_move_mode( ) == move_mode.NAVAL else self.image_data.foot_move new_label = Label(Rect(x, y, image.UI_ICON_WIDTH, image.UI_ICON_HEIGHT), move_icon, image_label=True) self.add_child(new_label) x += image.UI_ICON_WIDTH + 10 new_label = Label(Rect(x, y, 15, image.UI_ICON_HEIGHT), str(self.selected_unit.get_moves_left()) + "/" + str(self.selected_unit.get_max_moves()), tool_tip_text="Move points left / Max move points") self.add_child(new_label) y += image.UI_ICON_HEIGHT traits = self.selected_unit.get_traits() x = self.rect.x + self.rect.width / 4 width = self.rect.width / 2 height = 12 for curr_trait in traits: if curr_trait == trait.HERO: continue # no need to display this, already shown in unit type trait_text = trait.trait_str(curr_trait, traits[curr_trait]) trait_label = Label(Rect(x, y, width, height), trait_text, tool_tip_text=trait.tool_tip_table[curr_trait]) self.add_child(trait_label) if curr_trait in trait.useable_traits: use_callback = lambda used_trait=curr_trait: event_manager.queue_event( Event(event_manager.COMMAND_ISSUED, [ misc_commands.UseTraitCommand(self.selected_unit, used_trait) ])) use_button = Button(Rect(x + width + 2, y, 25, height), "Use", use_callback) self.add_child(use_button) y += 14 self.show()
def __init__(self, titre, workplace_path=QDir.homePath() + "/workplace/"): """ Hérite de QWidget Class principale, dans laquelle tout est rassemblé. On appelle tout ce qui est nécessaire à la création de la fenêtre et au fonctionnement du programme. :param titre: Nom de la fenêtre :type titre: str :param workplace_path: Chemin absolu vers l'emplacement où sont placés les projets créés. :rtype: None """ super().__init__() self.ecran = QDesktopWidget() self.setWindowTitle(titre) self.setGeometry(20, 50, self.ecran.screenGeometry().width() - 100, self.ecran.screenGeometry().height() - 100) # Taille de la fenêtre self.workplace_path = workplace_path self.project_path = "" self.project_type = "" # A changer un fonction du XML self.def_functions = {} self.def_structs = {} self.def_vars = {} self.aller_en_haut_lignes = False self.gridLayout = QGridLayout() self.gridLayout.setContentsMargins(0, 0, 0, 0) # No spacing around widgets # Ajout du logo pieuvre # self.label_img = QLabel() # self.pixmap_img = QPixmap("images/pieuvre.jpg") # self.label_img.setPixmap(self.pixmap_img) self.treeview = navigateur.TreeView(self) self.codes = [] self.highlighters = [] self.docs = [] self.tab_widget = onglet.TabWidget(self) # Lines number self.tab_widget.currentChanged.connect(self.defaut_info_message) self.nb_lignes = editeur.Lignes(self, "ABeeZee", 14) self.anim_line = False self.last = 0 # Last number of lines self.is_show_line = True self.line_tab = editeur.LignesAndTab(self, self.nb_lignes) if self.is_show_line: self.line_tab.setMaximumWidth(60) else: self.line_tab.setMaximumWidth(1) self.img_logo = LabelLogo(self, "content/logo.png") self.central_area = QSplitter() self.central_area.addWidget(self.line_tab) self.central_area.addWidget(self.tab_widget) self.central_area.addWidget(self.img_logo) self.central_area.setOrientation(Qt.Horizontal) self.central_area.setHandleWidth(1) self.central_area.setChildrenCollapsible(False) self.cheminee = Label(self, get_text("text_cheminee_hover")) self.cheminee.setFixedHeight(1) self.inspecteur = inspecteur.Inspecteur(self) # Les boutons self.bouton_analyse = Bouton(get_text("text_bout_analyse"), self.pre_analyse) self.bouton_change = Bouton(get_text("text_bout_nav"), self.change_affichage) self.boutons = QSplitter() self.boutons.addWidget(self.bouton_change) self.boutons.addWidget(self.bouton_analyse) self.boutons.setOrientation(Qt.Horizontal) self.boutons.setChildrenCollapsible(False) self.boutons.setHandleWidth(1) self.boutons.setFixedWidth(100) # Le QSplitter contenant le QTreeView et le QPushButton self.split_gauche = QSplitter() self.split_gauche.addWidget(self.cheminee) self.split_gauche.addWidget(self.inspecteur) self.split_gauche.addWidget(self.treeview) self.split_gauche.addWidget(self.boutons) self.split_gauche.setOrientation(Qt.Vertical) self.split_gauche.setChildrenCollapsible(False) self.split_gauche.setHandleWidth(1) # Le QSplitter contenant le QTabWidget et le QSplitter (cf. ci-dessus) self.splitter = QSplitter() self.splitter.addWidget(self.split_gauche) self.splitter.addWidget(self.central_area) self.splitter.setSizes([100, 400]) self.splitter.setMinimumSize(self.width(), self.height() - 50) # Les barres de statut self.statusbar = statusbar.StatusBar() self.infobar = statusbar.StatusBar(200) # La barre de progression self.progress_bar = QProgressBar() self.progress_bar.setRange(0, 100) self.progress_bar.setStyleSheet(style.get("progress_bar")) name = "" if "darwin" in sys.platform: name = os.environ["USER"] self.status_message(get_text("text_bienvenue") + name) # self.statusbar.addWidget(MyReadWriteIndication) self.menuBar = menu.MenuBar(self) # Positionnement des Layouts y = 0 if "win" in sys.platform.lower(): self.gridLayout.addWidget(self.menuBar, y, 0) y += 1 self.gridLayout.addWidget(self.splitter, y + 1, 0, 1, 2) self.gridLayout.addWidget(self.statusbar, y + 2, 0) self.gridLayout.addWidget(self.infobar, y + 2, 1) self.setLayout(self.gridLayout) # if sys.platform == "linux": # self.show() self.show() self.maj_style() # Connection des signaux self.sig_message.connect(self.prog_mess) self.sig_progress.connect(self.prog_val) self.sig_update_lines.connect(self.change_lines) self.show_img()
class Troop: def __init__(self, x=0, y=0, ai=False, t=0): self.x, self.y = x, y # position to draw troop self.health = 100 # troop's health self.ai = ai # flag for specifying if troop is ai self.type = t # 0 = default, 1 = medic, 2 = sniper if self.type == 2: self.health = 75 self.default_stats() # default all troops state # read in sprite image for troop # if ai, flip the image if self.ai and self.type == 0: self.image = pygame.transform.flip(pygame.image.load(os.path.join('assets', 'ai_commando.png')), True, False) elif self.ai and self.type == 1: self.image = pygame.transform.flip(pygame.image.load(os.path.join('assets', 'ai_medic.png')), True, False) elif self.ai and self.type == 2: self.image = pygame.transform.flip(pygame.image.load(os.path.join('assets', 'ai_soldier.png')), True, False) elif not self.ai and self.type == 0: self.image = pygame.image.load(os.path.join('assets', 'player_commando.png')) elif not self.ai and self.type == 1: self.image = pygame.image.load(os.path.join('assets', 'player_medic.png')) else: self.image = pygame.image.load(os.path.join('assets', 'player_soldier.png')) # rectangle surrounding troop (useful for detecting clicks) self.rect = self.image.get_rect() self.rect.center = int(self.x), int(self.y) # label for drawing troops health self.health_label = Label(str(int(self.health)), size=15) # detect if troop was clicked on def get_event(self, event): if event.type == pygame.MOUSEBUTTONUP and self.rect.collidepoint(event.pos): return True return False # update health label to display current health def update(self): self.health_label.set_text(str(int(self.health))) # draw troop to screen def render(self, surface): surface.blit(self.image, self.rect) self.health_label.render(surface) # add attack boost to troop def attack_boost(self): self.attack += 10 if self.type == 2: self.attack += 10 self.defense = 0 if self.type == 0 and self.attack > 40: self.attack = 40 elif self.type == 1 and self.attack > 30: self.attack = 30 elif self.type == 2 and self.attack > 70: self.attack = 70 # add defense boost to troop def defense_boost(self): self.defense += 10 if self.type == 2: self.attack += 10 self.defense -= 5 if self.type == 0 and self.defense > 40: self.defense = 40 elif self.type == 1 and self.defense > 20: self.defense = 30 elif self.type == 2 and self.defense > 10: self.defense = 20 # add healing property def heal(self,num): self.health += num if self.health > 100: self.health = 100 if self.type == 2 and self.health > 75: self.health = 75 # set stats to default values def default_stats(self): self.attack = 20 if self.type == 2: self.attack = 10 self.defense = 10 # set pos to draw troop def set_pos(self, pos): self.x, self.y = pos self.rect.center = int(self.x), int(self.y) if not self.ai: self.health_label.set_pos((int(self.x - self.rect.w/4), int(self.y - self.rect.h/2 - 15))) else: self.health_label.set_pos((int(self.x + self.rect.w / 4), int(self.y - self.rect.h / 2 - 15)))
def createWidgets(self): "Creates all widgets for the dialog." # labels self.wm.register( Label(self.titlefont, "Setup network information", (10, 10), color=(255, 0, 0))) self.wm.register( Label(self.smallfont, "My name: ", (250, 240), color=(255, 255, 255))) self.wm.register( Label(self.smallfont, "Run as server: ", (250, 300), color=(255, 255, 255))) # get the user name from the environment if it works try: name = os.environ['USER'] except: name = "My name" # the editfields self.user = EditField(self.smallfont, name, 200, (450, 230), color=(255, 255, 0), background=(80, 80, 80)) self.server = CheckBox( "Server", self.smallfont, properties.path_dialogs + "butt-radio-set.png", properties.path_dialogs + "butt-radio-unset.png", checked=1, position=(450, 290), color=(255, 255, 0), callbacks={widget.MOUSEBUTTONUP: self.toggleServer}) self.client = CheckBox( "Client", self.smallfont, properties.path_dialogs + "butt-radio-set.png", properties.path_dialogs + "butt-radio-unset.png", checked=0, position=(570, 290), color=(255, 255, 0), callbacks={widget.MOUSEBUTTONUP: self.toggleServer}) self.wm.register(self.user) self.wm.register(self.server) self.wm.register(self.client) # buttons self.wm.register( Button(properties.path_dialogs + "butt-ok-moff.png", properties.path_dialogs + "butt-ok-mover.png", (284, 650), {widget.MOUSEBUTTONUP: self.ok})) self.wm.register( Button(properties.path_dialogs + "butt-quit-moff.png", properties.path_dialogs + "butt-quit-mover.png", (528, 650), {widget.MOUSEBUTTONUP: self.cancel}))
def update_left(self, label): self.left = Label(label, x=(self.width * 0.2), y=(self.y + self.height / 2)) self.left.set_size(self.size1)
class Menu: def __init__(self, x=0, y=0, w=200, h=500, title='', buttons=None): # position and size self.x = x self.y = y self.w = w self.h = h # buttons and title self.set_title(title) self.set_buttons(buttons) # create actual menu self.menu = RoundedRect(pygame.Rect(0, 0, w, h)) self.menu.rect.center = self.x, self.y self.play_button = Button( pygame.display.get_surface().get_width() / 2, pygame.display.get_surface().get_height() * 0.4) self.play_button.set_text("Start Game", size=35) self.options_button = Button( pygame.display.get_surface().get_width() / 2, pygame.display.get_surface().get_height() * 0.55) self.options_button.set_text("Options", size=35) self.quit_button = Button( pygame.display.get_surface().get_width() / 2, pygame.display.get_surface().get_height() * 0.7) self.quit_button.set_text("Quit Game", size=35) def get_event(self, event): for b in self.buttons: if b.handle_event(event): return b.get_text() else: return None def update(self): for b in self.buttons: b.update() def render(self, surface): self.menu.render(surface) self.title.render(surface) for b in self.buttons: b.render(surface) def set_title(self, title): self.title = Label(title) self.title.set_pos((self.x, int(self.y - self.h / 2 + self.h * 0.15))) def set_pos(self, pos): self.x, self.y = pos self.menu.rect.center = self.x, self.y def set_buttons(self, buttons): self.buttons = [] if not isinstance(buttons, list): return base = self.h * 0.15 height = self.h - base base += self.y - self.h / 2 for (i, b) in enumerate(buttons): x = int(self.x) y = int(height * ((i + 1) / (len(buttons) + 1)) + base) self.buttons.append(Button(x, y)) self.buttons[i].set_text(b, size=35)
def update_middle(self, label): self.middle = Label(label, x=(self.width * 0.5), y=(self.y + self.height / 2)) self.middle.set_size(self.size2)
def set_title(self, title): self.title = Label(title) self.title.set_pos((self.x, int(self.y - self.h / 2 + self.h * 0.15)))
class MenuBar: def __init__(self, x, y, width, height, left='', middle='', right='', size1=23, size2=23, size3=23): self.x = x self.y = y self.width = width self.height = height self.size1 = size1 self.size2 = size2 self.size3 = size3 self.update_left(left) self.update_middle(middle) self.update_right(right) def get_event(self, event): pass def update(self): pass def render(self, surface): pygame.draw.rect(surface, pygame.Color("white"), (self.x, self.y, self.width, self.height)) self.left.render(surface) self.middle.render(surface) self.right.render(surface) def update_left(self, label): self.left = Label(label, x=(self.width * 0.2), y=(self.y + self.height / 2)) self.left.set_size(self.size1) def update_middle(self, label): self.middle = Label(label, x=(self.width * 0.5), y=(self.y + self.height / 2)) self.middle.set_size(self.size2) def update_right(self, label): self.right = Label(label, x=(self.width * 0.8), y=(self.y + self.height / 2)) self.right.set_size(self.size3) def update_labels(self, labels): if len(labels) == 3: self.left = Label(labels[0], x=(self.width * 0.2), y=(self.y + self.height / 2)) self.middle = Label(labels[1], x=(self.width * 0.5), y=(self.y + self.height / 2)) self.right = Label(labels[2], x=(self.width * 0.8), y=(self.y + self.height / 2))
class Fenetre(QWidget): sig_message = Signal(str) sig_progress = Signal(int) sig_update_lines = Signal(int) def __init__(self, titre, workplace_path=QDir.homePath() + "/workplace/"): """ Hérite de QWidget Class principale, dans laquelle tout est rassemblé. On appelle tout ce qui est nécessaire à la création de la fenêtre et au fonctionnement du programme. :param titre: Nom de la fenêtre :type titre: str :param workplace_path: Chemin absolu vers l'emplacement où sont placés les projets créés. :rtype: None """ super().__init__() self.ecran = QDesktopWidget() self.setWindowTitle(titre) self.setGeometry(20, 50, self.ecran.screenGeometry().width() - 100, self.ecran.screenGeometry().height() - 100) # Taille de la fenêtre self.workplace_path = workplace_path self.project_path = "" self.project_type = "" # A changer un fonction du XML self.def_functions = {} self.def_structs = {} self.def_vars = {} self.aller_en_haut_lignes = False self.gridLayout = QGridLayout() self.gridLayout.setContentsMargins(0, 0, 0, 0) # No spacing around widgets # Ajout du logo pieuvre # self.label_img = QLabel() # self.pixmap_img = QPixmap("images/pieuvre.jpg") # self.label_img.setPixmap(self.pixmap_img) self.treeview = navigateur.TreeView(self) self.codes = [] self.highlighters = [] self.docs = [] self.tab_widget = onglet.TabWidget(self) # Lines number self.tab_widget.currentChanged.connect(self.defaut_info_message) self.nb_lignes = editeur.Lignes(self, "ABeeZee", 14) self.anim_line = False self.last = 0 # Last number of lines self.is_show_line = True self.line_tab = editeur.LignesAndTab(self, self.nb_lignes) if self.is_show_line: self.line_tab.setMaximumWidth(60) else: self.line_tab.setMaximumWidth(1) self.img_logo = LabelLogo(self, "content/logo.png") self.central_area = QSplitter() self.central_area.addWidget(self.line_tab) self.central_area.addWidget(self.tab_widget) self.central_area.addWidget(self.img_logo) self.central_area.setOrientation(Qt.Horizontal) self.central_area.setHandleWidth(1) self.central_area.setChildrenCollapsible(False) self.cheminee = Label(self, get_text("text_cheminee_hover")) self.cheminee.setFixedHeight(1) self.inspecteur = inspecteur.Inspecteur(self) # Les boutons self.bouton_analyse = Bouton(get_text("text_bout_analyse"), self.pre_analyse) self.bouton_change = Bouton(get_text("text_bout_nav"), self.change_affichage) self.boutons = QSplitter() self.boutons.addWidget(self.bouton_change) self.boutons.addWidget(self.bouton_analyse) self.boutons.setOrientation(Qt.Horizontal) self.boutons.setChildrenCollapsible(False) self.boutons.setHandleWidth(1) self.boutons.setFixedWidth(100) # Le QSplitter contenant le QTreeView et le QPushButton self.split_gauche = QSplitter() self.split_gauche.addWidget(self.cheminee) self.split_gauche.addWidget(self.inspecteur) self.split_gauche.addWidget(self.treeview) self.split_gauche.addWidget(self.boutons) self.split_gauche.setOrientation(Qt.Vertical) self.split_gauche.setChildrenCollapsible(False) self.split_gauche.setHandleWidth(1) # Le QSplitter contenant le QTabWidget et le QSplitter (cf. ci-dessus) self.splitter = QSplitter() self.splitter.addWidget(self.split_gauche) self.splitter.addWidget(self.central_area) self.splitter.setSizes([100, 400]) self.splitter.setMinimumSize(self.width(), self.height() - 50) # Les barres de statut self.statusbar = statusbar.StatusBar() self.infobar = statusbar.StatusBar(200) # La barre de progression self.progress_bar = QProgressBar() self.progress_bar.setRange(0, 100) self.progress_bar.setStyleSheet(style.get("progress_bar")) name = "" if "darwin" in sys.platform: name = os.environ["USER"] self.status_message(get_text("text_bienvenue") + name) # self.statusbar.addWidget(MyReadWriteIndication) self.menuBar = menu.MenuBar(self) # Positionnement des Layouts y = 0 if "win" in sys.platform.lower(): self.gridLayout.addWidget(self.menuBar, y, 0) y += 1 self.gridLayout.addWidget(self.splitter, y + 1, 0, 1, 2) self.gridLayout.addWidget(self.statusbar, y + 2, 0) self.gridLayout.addWidget(self.infobar, y + 2, 1) self.setLayout(self.gridLayout) # if sys.platform == "linux": # self.show() self.show() self.maj_style() # Connection des signaux self.sig_message.connect(self.prog_mess) self.sig_progress.connect(self.prog_val) self.sig_update_lines.connect(self.change_lines) self.show_img() def compiler(self): if self.project_path != "": compilateur.compiler(self) else: QMessageBox.critical(self, get_text("no_project_on"), get_text("text_please_open_project")) def configuration_compilation(self): if self.project_path != "": compilateur.configuration_compilation(self) else: QMessageBox.critical(self, get_text("no_project_on"), get_text("text_please_open_project")) def prog_mess(self, message): """ Fonction recevant le signal "sig_message" émis lors de l'ouverture d'un projet. Le signal est un message à afficher dans la barre de status :type message: str """ self.status_message(message, -1, False) def prog_val(self, val): """ Fonction recevant le signal "sig_progress" émis lors de l'ouverture d'un projet. Le signal est la progression utilisée par la barre de progression située dans l'infoBar :type val: int """ self.progress_bar.setValue(val) def change_affichage(self): """ Change l'outil affiché sur la zone de gauche 0: Navigateur de fichiers 1: Inspecteurs d'éléments. """ if self.get_idx() == -1: self.status_message(get_text("text_please_open_doc")) else: widgets = [("Navigateur", "TreeView"), ("Inspecteur", "Inspector")] text_widgets = { "Navigateur": get_text("text_bout_insp"), "TreeView": get_text("text_bout_insp"), "Inspecteur": get_text("text_bout_nav"), "Inspector": get_text("text_bout_nav") } # On récupère le texte en fonction de la langue. actual = self.bouton_change.text() self.bouton_change.setText(text_widgets[actual]) self.status_message(self.bouton_change.text() + get_text("text_chang_bout") + actual) if actual in widgets[0]: # Affichage de l'inspecteur self.get_definitions() self.inspecteur.setMaximumHeight( self.ecran.screenGeometry().height()) self.inspecteur.load() self.inspecteur.maj_style() self.treeview.setMaximumHeight(1) elif actual in widgets[1]: # Affichage du navigateur de fichiers self.treeview.setMaximumHeight( self.ecran.screenGeometry().height()) self.inspecteur.setMaximumHeight(1) def get_definitions(self): idx = self.get_idx() doc = self.docs[idx] code = self.codes[idx].toPlainText() ext = doc.extension path = doc.chemin_enregistrement if ext in lex.plyPlusLexers: self.def_functions[path] = lex.get_def_functions(ext, code) self.def_structs[path] = lex.get_def_class(ext, code) self.def_vars[path] = lex.get_def_vars(ext, code) def get_current_widget_used(self): """ Renvoie le texte affiché dans le bouton servant à changer le contenu de la zone à gauche. Cela nous sert à passer à l'élément suivant lorsqu'on clique dessus :rtype: str """ return self.bouton_change.text() def comment_selection(self): """ Commente le texte sélectionné via une méthode de Editeur """ idx = self.tab_widget.currentIndex() if idx != -1: self.codes[idx].comment_selection() def find(self): """ Ouvre la boite de dialogue permettant de rechercher des éléments """ document.find_dialog(self) def get_idx(self): """ Renvoie l'index de l'onglet de code courant sur le tab_widget. :rtype: int """ return self.tab_widget.currentIndex() def duplicate(self): """ Duplique la séléction Appelle la fonction duplicate() de Editeur """ if self.get_idx() != -1: self.codes[self.get_idx()].duplicate() def insert_mode(self): """ Active ou désactive le mode insertion : remplacement du texte """ idx = self.get_idx() if self.codes[idx].overwriteMode(): self.codes[idx].setOverwriteMode(False) self.codes[idx].setCursorWidth(1) else: self.codes[idx].setOverwriteMode(True) self.codes[idx].setCursorWidth(5) def select_current_word(self): """ Sélectionne le mot sur lequel est le curseur Appelle la fonction select_current_word() de Editeur """ if self.get_idx() != -1: self.codes[self.get_idx()].select_current_word() def select_current_line(self): """ Sélectionne la ligne sur laquelle est le curseur Appelle la fonction select_current_line() de Editeur """ if self.get_idx() != -1: self.codes[self.get_idx()].select_current_line() def indent(self): """ Indente automatiquement le fichier Appelle la fonction indent() de Editeur """ if self.get_idx() != -1: self.codes[self.get_idx()].indent() def show_progress_bar(self): """ Affiche la barre de progression dans l'infoBar. Utilisée lors de l'ouverture d'un projet. """ self.infobar.clearMessage() self.progress_bar.setValue(0) self.progress_bar.setTextVisible(True) self.infobar.addWidget(self.progress_bar) self.progress_bar.show() def hide_progress_bar(self): """ Masque la barre de progression de l'infoBar. """ self.progress_bar.setValue(100) self.infobar.removeWidget(self.progress_bar) # Messages in status bars def info_message(self, message, time=-1): """ Affiche un message dans l'infoBar. :param message: message à afficher :type message: str :param time: temps de l'affichage. Par défaut à -1. Si -1 alors le message est affiché indéfiniment (jusqu'au prochain message) :type time: int """ self.infobar.clearMessage() if time == -1: self.infobar.showMessage(message) else: self.infobar.showMessage(message, time) def show_number_of_lines(self): """ Affiche le nombre de lignes dans l'infoBar (ainsi que sur le côté du code si on le souhaite). Pour l'affichage sur le côté on utilise un Thread qui va envoyer un signal pour actualiser l'affichage. """ prev = self.last self.last = 0 idx = self.tab_widget.currentIndex() if idx in range(len(self.docs)) and len( self.docs) > 0: # On affiche le nombre de lignes nblignes = self.docs[idx].get_nb_lignes() self.infobar.showMessage( str(nblignes) + get_text("infobar_line") + "s" * (nblignes != 1)) self.nb_lignes.retirer_erreurs() if nblignes != prev: self.nb_lignes.clear() self.update_lines_number = parallele.LinesActualise( self, nblignes, self.anim_line) self.update_lines_number.start() else: self.last = prev else: # On efface le nombre de lignes self.infobar.clearMessage() self.nb_lignes.clear() def show_line_column(self): """ Affiche et masque la colonne de numérotation des lignes. """ if configuration['numerote_lines'] == 'False': write_xml("conf.xml", "numerote_lines", "True") else: write_xml("conf.xml", "numerote_lines", "False") self.is_show_line = not self.is_show_line if self.is_show_line: self.line_tab.setMaximumWidth(60) else: self.line_tab.setMaximumWidth(1) self.splitter.update() def change_lines(self, e): """ Fonction recevant le signal "sig_update_lines" permettant d'actualiser le nombre de lignes sur le côté. :param e: événement reçu : nouveau numéro à ajouter :type e: int """ if self.last == self.docs[self.get_idx()].get_nb_lignes() - 1: self.nb_lignes.append(str(e)) self.last += 1 self.nb_lignes.go_top() elif e == self.last + 1: self.nb_lignes.append(str(e)) # addItem(str(e)) --> QListWidget self.last += 1 def defaut_info_message(self): """ Affiche le message par défaut dans l'infoBar : ici le nombre de ligne """ self.show_number_of_lines() def show_nb_found(self, text): """ Affiche le nombre de propositions trouvées au total lors de la recherche d'un terme :param text: Mot recherché :type text: str """ n = self.codes[self.get_idx()].toPlainText().count(text) self.info_message( str(n) + " occurrence%s %s '%s'" % ("s" * (n != 1), get_text("infobar_de"), text)) def status_message(self, message, time=2000, say=True): """ Affiche un message dans la barre de status :param message: Message à afficher :type message: str :param time: Temps d'affichage (par défaut 2s). Si -1 alors le message est affiché jusqu'au prochain message. :type time: int :rtype: None """ self.statusbar.clearMessage() if say and time != -1: if "darwin" in sys.platform: configuration = open_xml("conf.xml") if configuration['assistance_vocale'] == 'True': self.blabla = parallele.SayMessage(message) self.blabla.start() self.statusbar.showMessage(message, time) elif time != -1: self.statusbar.showMessage(message, time) else: self.statusbar.showMessage(message) def assist_voc(self): """ Active ou désactive l'assistance vocale et écrit la configuration actuelle dans un fichier XML. """ if "darwin" in sys.platform: configuration = open_xml("conf.xml") if configuration['assistance_vocale'] == 'True': self.status_message(get_text("status_voc_des")) write_xml("conf.xml", "assistance_vocale", "False") else: write_xml("conf.xml", "assistance_vocale", "True") self.status_message(get_text("status_voc_activ")) def new(self): """ Fonction de création de nouveau fichier reliée au sous-menu "Nouveau". On ajoute ici un nouvel onglet à nos codes déjà ouverts ( ou on créée un premier onglet ) qui s'appelle par défaut "Sans nom" + le numéro courant dans la liste des onglets. On appelle la fonction self.addCode() :rtype: None """ if self.project_path != "": document.new_document(self) self.show_img(False) else: self.status_message(get_text("text_please_open_project"), 1000) def save(self): """ Fonction de sauvegarde reliée au sous-menu "Sauvergarder". On sauvegarde un fichier en l'enregistrant dans un projet (ou non). On ouvre une QFileDialog qui affiche le navigateur du système habituel pour enregistrer des documents. :return: """ document.save_document(self) def close_tab_idx(self, idx): current_idx = self.get_idx() if current_idx > idx: current_idx -= 1 self.tab_widget.setCurrentIndex(idx) self.close_current_tab() self.tab_widget.setCurrentIndex(current_idx) def close_current_tab(self): """ Ferme l'onglet courant Appelle la fonction close_current_tab() de TabWidget. """ self.tab_widget.close_current_tab() if self.get_idx() == -1: # Affichage de l'image self.show_img() def show_img(self, display=True): """ Affiche l'image du logo de l'IDE si aucun fichier n'est ouvert :param display: Si on doit l'afficher ou la masquer :type display: bool """ if display and self.img_logo.width() == 1: self.img_logo.setFixedWidth(self.tab_widget.width()) self.tab_widget.setFixedWidth(1) elif not display and self.img_logo.width() > 1: self.tab_widget.setFixedWidth(self.img_logo.width()) self.img_logo.setFixedWidth(1) def change_worplace_location(self): """ Change l'emplacement du workplace """ self.docs = [] self.highlighters = [] self.codes = [] self.tab_widget.clear() self.project_path = "" widgets = [("Navigateur", "TreeView"), ("Inspecteur", "Inspector")] actual = self.bouton_change.text() if actual in widgets[1]: # Affichage du navigateur de fichiers self.treeview.setMaximumHeight( self.ecran.screenGeometry().height()) self.inspecteur.setMaximumHeight(1) chemin = QFileDialog.getExistingDirectory( self, get_text("chg_worplace"), self.workplace_path).replace( "\\", "/") + "/" print(chemin) if chemin != "/": self.treeview.change_worplace(chemin) self.workplace_path = chemin write_xml("conf.xml", "current_workplace", chemin) def deja_ouvert(self, chemin): """ Renvoie si un document est déjà ouvert :param chemin: Chemin vers le document :type chemin: str :rtype: bool """ return document.document_deja_ouvert(self, chemin) def open(self, chemin=False): """ Fonction d'ouverture d'un fichier reliée au sous-menu "Ouvrir un fichier" On utilise une QFileDialog qui affiche le navigateur du système habituel pour ouvrir des documents. :param chemin: N'existe pas si on appelle via le menu ou le raccourcis clavier. Il est spécifié si il appartient au projet courant et que l'on souhaite l'ouvrir sans passer par la fenetre de dialogue. :type chemin: str :rtype: None """ # debut = time() self.aller_en_haut_lignes = True document.open_document(self, chemin) if self.get_idx() != -1: self.show_img(False) # fin = time() # self.info_message(str(round((fin-debut), 3)), 1000) def open_img(self, chemin): """ Fonction d'ouverture d'une image :param chemin: Chemin vers l'image :type chemin: str """ f_im = QDialog() lab_img = QLabel() pixmap_im = QPixmap(chemin) lab_img.setPixmap(pixmap_im) lab_img.setMaximumSize(self.ecran.screenGeometry().width() - 100, self.ecran.screenGeometry().height() - 100) layout_im = QHBoxLayout() layout_im.addWidget(lab_img) f_im.setLayout(layout_im) f_im.exec_() def open_gif(self, chemin): """ Fonction d'ouverture d'un gif :param chemin: Chemin vers le GIF """ f_gif = QDialog() lab_gif = QLabel() mov = QMovie(chemin) lab_gif.setMovie(mov) layout_gif = QHBoxLayout() layout_gif.addWidget(lab_gif) f_gif.setLayout(layout_gif) mov.start() f_gif.exec_() def add_code(self, title, new=False, current_ext="c"): """ Fonction qui se charge d'ajouter à la liste des codes ouverts une nouvelle instance de la classe Editeur et de créer un nouvel onglet :param title: Nom du document :type title: str :param new: Vrai si il s'agit d'un nouveau document :type new: bool :param current_ext: l'extension du fichier courant :type current_ext: str :rtype: None """ self.codes += [ editeur.Editeur( "ABeeZee", 14, self.def_functions, list(lex.get_keywords(current_ext).keys()) + lex.get_know_functions(current_ext), self) ] self.highlighters += [ couleurs.CodeHighLighter(self.codes[-1], self.codes[-1].document()) ] self.codes[-1].tabPress.connect(self.highlighters[-1].test) self.tab_widget.addTab(self.codes[-1], title) self.tab_widget.setCurrentIndex(len(self.codes) - 1) if new: self.highlighters[-1].first_launch = False def new_project(self): """ Créée un nouveau projet Le projet créé doit avoir un nom différent d'un projet déjà existant, et ne doit pas comporter de "/" dans son nom. :rtype: None """ workplace.newproject(self) def clear_cache(self): """ Supprime le cache de la partie courante. """ workplace.delete_project_cache(self, self.project_path) def clear_global_cache(self): """ Supprime le cache de tout l'IDE. """ workplace.delete_global_cache(self) def delete_project(self): """ Supprime un projet. """ workplace.deleteproject(self) def infos_project(self): """ Affiche les informations du projet. """ workplace.infosproject(self) def import_project(self): """ Importe un projet. """ workplace.importproject(self) def close_document(self): """ Ferme un fichier. """ document.closedocument(self) def delete_document(self): """ Contient le bouton d'annimation de l'affichage des lignes ainsi que la zone de numérotation des lignes. """ document.deletedocument(self) def menu_raccourcis(self): """ Sous-menu permettant d'ouvrir la fenêtre de modification des raccourcis.""" fen_raccourcis = Raccourcis(self, "Paramètrage raccourcis") fen_raccourcis.exec() def a_propos(self): """ Donne des informations sur l'IDE :rtype: None """ apropos = open("content/apropos.txt", "r").readlines() QMessageBox.about(self, "À propos de SpaghettIDE ", "".join(apropos)) def contact(self): """ Ouvre l'appli mail pour envoyer un email aux développeurs """ if "darwin" in sys.platform: os.system("open mailto:[email protected]") if "linux" in sys.platform: os.system("xdg-open mailto:[email protected]") if "win32" in sys.platform: os.system("start mailto:[email protected]") # Bouton analyse def pre_analyse(self): """ Fonction appellée lors du clic sur le bouton analyse. Si un document est ouvert, on appelle la fonction analyse() de Editeur """ index = self.get_idx() if index == -1: self.status_message(get_text("text_please_open_doc")) else: self.codes[index].analyse() self.status_message(get_text("status_fic_analys")) # Thèmes def maj_style(self): """ Met à jour le style de la fenêtre principale. """ self.setStyleSheet("QObject::pane{background: " + themes.get_rgb( themes.get_color_from_theme("textedit")["text-back-color"]) + ";}") self.inspecteur.setStyleSheet("background: " + themes.get_rgb( themes.get_color_from_theme("treeview")["BACKGROUND"]) + ";") self.img_logo.setStyleSheet("background: " + themes.get_rgb( themes.get_color_from_theme("textedit")["text-back-color"]) + ";}") for onglets_ouverts in self.codes: onglets_ouverts.maj_style() def help_func(self): """ Page d'aide """ if "darwin" in sys.platform: os.system("open https://doc.qt.io/") if "linux" in sys.platform: os.system("xdg-open https://doc.qt.io/") if "win32" in sys.platform: os.system("start https://doc.qt.io/") def site(self): """ Lien vers notre site """ if "darwin" in sys.platform: os.system("open https://www.spaghettide.com") if "linux" in sys.platform: os.system("xdg-open https://www.spaghettide.com") if "win32" in sys.platform: os.system("start https://www.spaghettide.com") def full_maj_style(self): """ Met à jour le thème de tous les éléments de l'interface graphique """ l_objects = (self.treeview, self, self.tab_widget, self.statusbar, self.infobar, self.inspecteur, self.nb_lignes) for o in l_objects: o.maj_style() lex.update_token_color() self.token_recoloration() def show_cheminee(self): """ Affiche ou masque la cheminée. """ if self.cheminee.height() == 1: self.fire = QMovie("content/fireplace.gif") self.cheminee.setMovie(self.fire) self.cheminee.setFixedHeight(260) self.fire.start() self.status_message(get_text("status_cheminee_on")) else: self.cheminee.setFixedHeight(1) self.fire.stop() self.cheminee.clear() self.status_message(get_text("status_cheminee_off")) def show_loading(self): """ Affiche ou masque l'écran de chargement. """ if configuration['loading'] == 'False': write_xml("conf.xml", "loading", "True") else: write_xml("conf.xml", "loading", "False") def token_recoloration(self): """ On reprend tout le contenu du QTextEdit pour le recolorer. """ for highlighter in self.highlighters: # For each Editor instance, we change the text to recolorate it highlighter.rehighlight() def fullscreen(self): """ Mode plein écran """ if self.isFullScreen(): self.showNormal() else: self.showFullScreen() def quit_func(self): """ Fonction de fermeture de l'IDE. On affiche une petite boîte pour demander si l'on souhaite vraiment fermer l'IDE. Les touches "return" et "escape" sont respectivement reliées à "Fermer" et "Annuler". :rtype: None """ self.status_message(get_text("status_exit"), -1, False) # Message de statut box = QMessageBox() box.setText(get_text("box_exit")) box.setStandardButtons(QMessageBox.Cancel | QMessageBox.Close) box.setDefaultButton(QMessageBox.Close) box.setEscapeButton(QMessageBox.Cancel) box.setStyleSheet(style.get("buttons", "window")) val = box.exec_() if val == QMessageBox.Close: self.restart = False self.close() else: self.status_message(get_text("status_not_exit"), 1000, False) # Message de statut
class StatusRenderer(component.Window): ''' classdocs ''' def __init__(self, position_rect): super(StatusRenderer, self).__init__(position_rect) self.pad = 4 self.last_event = None event_manager.add_listener(self.handle_events, event_manager.DAY_START) event_manager.add_listener(self.handle_events, event_manager.RANDOM_EVENT) event_manager.add_listener(self.handle_events, event_manager.PLAYER_STATUS_CHANGE) event_manager.add_listener(self.handle_events, event_manager.HEX_SELECTED) # x = self.rect.x + 164 + 2*(image.UI_ICON_WIDTH + 10) # y = self.rect.y + 8 x = self.rect.x + 114 + image.UI_ICON_WIDTH y = self.rect.y + self.pad width = 50 height = self.rect.height - self.pad self.gold_label = Label(Rect(x, y, width, height), "", font=text.lg_font) x += image.UI_ICON_WIDTH + 55 self.income_label = Label(Rect(x, y, width, height), "", font=text.lg_font) x += image.UI_ICON_WIDTH + 55 self.rep_label = Label(Rect(x, y, width, height), "", font=text.lg_font) x += image.UI_ICON_WIDTH + 53 self.fame_label = Label(Rect(x, y, width, height), "", font=text.lg_font) x += 400 self.zone_label = Label(Rect(x, y, width, height), "", font=text.lg_font) self.add_child(self.income_label) self.add_child(self.gold_label) self.add_child(self.rep_label) self.add_child(self.fame_label) self.add_child(self.zone_label) #self.turn_label = self.font.render("Turn:", True, (255, 255, 255), (25, 25, 25)) #self.gold_label = self.font.render("Gold:", True, (255, 255, 255), (25, 25, 25)) #self.rep_label = self.font.render("Reputation:", True, (255, 255, 255), (25, 25, 25)) def set_data(self, map_data, curr_player, curr_mask, curr_turn): self.map_data = map_data self.curr_player = curr_player # self.mask_player = curr_mask.get_player() self.curr_mask = curr_mask self.mask_player = curr_mask.get_player() self.turn = curr_turn self.update_labels() def gen_tool_tip(self, top_label, value_dict): tool_tip_text = top_label + "\n" for key_name in value_dict: tool_tip_text += "\n" + key_name + ": " + str(value_dict[key_name]) return tool_tip_text def update_labels(self): tool_tip_text = self.gen_tool_tip("Income", self.mask_player.income_by_type) self.income_label.set_label(str(self.mask_player.get_income()), tool_tip_text=tool_tip_text) self.gold_label.set_label(str(self.mask_player.get_gold())) tool_tip_text = self.gen_tool_tip("Reputation", self.mask_player.reputation_by_type) self.rep_label.set_label(str(self.mask_player.get_reputation()), tool_tip_text=tool_tip_text) tool_tip_text = self.gen_tool_tip("Fame", self.mask_player.fame_by_type) self.fame_label.set_label(str(self.mask_player.get_fame()), tool_tip_text=tool_tip_text) def handle_events(self, event): if event.type == event_manager.DAY_START: self.last_event = None # clear event display at start of each day elif event.type == event_manager.RANDOM_EVENT: self.last_event = event.data['description'] # elif event.type == event_manager.PLAYER_WON: # self.last_event = "Game Over: " + event.data['player'].get_name() + " Won" # elif event.type == event_manager.PLAYER_LOST: # self.last_event = "Loss: " + event.data['player'].get_name() + " Lost" elif event.type == event_manager.PLAYER_STATUS_CHANGE: self.update_labels() elif event.type == event_manager.HEX_SELECTED: x, y = event.data['loc'] if self.curr_mask.get_visibility(x, y) == mask.NEVER_VISIBLE: label_text = "" else: hex_zone = self.map_data.get_zone(x, y) label_text = hex_zone.name + " (" + hex_zone.get_type( ).name + ")" self.zone_label.set_label(label_text) def render(self, surface, images): super(StatusRenderer, self).render(surface, images) x = self.rect.x + 64 y = self.rect.y + self.rect.height / 2 #surface.blit(self.turn_label, (x, y)) #x += self.turn_label.get_width() + 4 images.text.draw_text( "Week " + str(self.turn.week) + ", Day " + str(self.turn.day), text.lg_font, x, y, surface) #turn_text = image.lg_font.render("Week " + str(turn.week) + ", Day " + str(turn.day), True, (255, 255, 255), (25, 25, 25)) #surface.blit(turn_text, (x, y)) x += 60 # if self.curr_player.is_actor(): #surface.blit(self.gold_label, (x, y)) #x += self.gold_label.get_width() + 4 #image.text.draw_text("Gold : " + str(curr_player.get_gold()), image.text.lg_font, x, y, surface) surface.blit(images.gold, (x, y - self.rect.height / 2)) x += image.UI_ICON_WIDTH + 10 # images.text.draw_text(str(self.curr_player.get_gold()), images.text.lg_font, x, y, surface, color=text.LIGHT) x += 50 surface.blit(images.income, (x, y - self.rect.height / 2)) # images.text.draw_text(str(self.curr_player.get_income()), images.text.lg_font, x, y, surface, color=text.LIGHT) x += 50 + image.UI_ICON_WIDTH + 10 #surface.blit(self.rep_label, (x, y)) #x += self.rep_label.get_width() + 4 surface.blit(images.reputation, (x, y - self.rect.height / 2)) x += 50 + image.UI_ICON_WIDTH surface.blit(images.fame, (x, y - self.rect.height / 2)) x += image.UI_ICON_WIDTH + 10 # images.text.draw_text(str(self.curr_player.get_reputation()), images.text.lg_font, x, y, surface, color=text.LIGHT) x = self.rect.x + self.rect.width / 2 images.text.draw_text(self.curr_player.get_name(), text.vlg_font, x, y, surface) if self.last_event != None: x = self.rect.x + self.rect.width / 2 y += 30 images.text.draw_text(self.last_event, text.sm_font, x, y, surface, color=text.LIGHT)
def update_right(self, label): self.right = Label(label, x=(self.width * 0.8), y=(self.y + self.height / 2)) self.right.set_size(self.size3)
class CombatRenderer(component.Window): ''' classdocs ''' def __init__(self, position_rect, images): global combat_event_types super(CombatRenderer, self).__init__(position_rect, True) self.mask = None self.active = False self.images = images self.phase = None attacker_rect = Rect(self.rect.x, self.rect.y + 30, self.rect.width, self.rect.height / 2 - 15) self.attacker_renderer = group_panel.CombatRenderer( "Attackers:", attacker_rect) defender_rect = Rect(self.rect.x, attacker_rect.y + attacker_rect.height, self.rect.width, self.rect.height / 2 - 15) self.defender_renderer = group_panel.CombatRenderer( "Defenders:", defender_rect) width, height = 120, 20 x, y = self.rect.x + self.rect.width / 2 - width / 2, attacker_rect.y + attacker_rect.height - 20 self.attacker_label = Label(Rect(x, y, width, height), None) y = defender_rect.y + defender_rect.height - 28 self.defender_label = Label(Rect(x, y, width, height), None) self.add_child(self.attacker_renderer) self.add_child(self.defender_renderer) self.add_child(self.attacker_label) self.add_child(self.defender_label) event_manager.add_listener_multi(self.handle_game_events, combat_event_types) def set_data(self, map_renderer, curr_mask): self.mask = curr_mask self.map_renderer = map_renderer def handle_game_events(self, event): if event.type == event_manager.COMBAT_START: loc = event.data['hex_loc'] if self.mask != None and self.mask.get_visibility( loc.x, loc.y) == mask.VISIBLE: self.show() self.map_renderer.center(loc.x, loc.y) self.attacker_renderer.set_group(event.data['attackers']) self.defender_renderer.set_group(event.data['defenders']) try: self.attacker_renderer.set_label( event.data['attackers'].get_owner().name) self.defender_renderer.set_label( event.data['defenders'].get_owner().name) except AttributeError: self.hide() self.title_text = "Combat!" self.base_label = "" # elif self.is_shown() and event.type == event_manager.COMBAT_END: self.hide() elif self.is_shown() and event.type == event_manager.COMBAT_SPOILS: spoils_message = "For defeating this foe you earned \n" if event.data['reputation'] != 0: spoils_message += "\n " + str( event.data['reputation']) + " Reputation" if event.data['item'] != None: spoils_message += "\n " + event.data['item'].get_name() spoils_dialog = modal.TextDialog("Spoils", spoils_message) spoils_dialog.show() elif self.is_shown() and event.type == event_manager.COMBAT_RETREAT: self.title_text = "Retreat" retreat_text = "Retreat Chance: " + str( int(100 * event.data['retreat_chance'])) + "% , " + ( "Retreated" if event.data['retreated'] else "Didn't Retreat") self.defender_label.set_label(retreat_text, text_color=text.RED) elif self.is_shown(): if event.type == event_manager.COMBAT_UPDATE: self.phase = event.data['phase'] if self.phase != self.title_text: self.title_text = event.data['phase'] self.base_label = phase_labels[self.title_text] attack_label_val = event.data['attacker_strength'] defense_label_val = event.data['defender_strength'] if attack_label_val != None: attack_label_color = text.RED if attack_label_val <= 0 else text.DARK self.attacker_label.set_label( self.base_label + str(attack_label_val), text_color=attack_label_color) else: self.attacker_label.set_label(None) if defense_label_val != None: defense_label_color = text.RED if defense_label_val <= 0 else text.DARK self.defender_label.set_label( self.base_label + str(defense_label_val), text_color=defense_label_color) else: self.defender_label.set_label(None) self.attacker_renderer.mark_selected( event.data['attacker_index']) self.defender_renderer.mark_selected( event.data['defender_index']) # self.attacker_renderer.add_overlay(self.images.selected_unit, event.data['attacker_index']) # self.defender_renderer.add_overlay(self.images.selected_unit, event.data['defender_index']) self.attacker_renderer.swap_overlays() self.defender_renderer.swap_overlays() else: affected_group = event.data['group'] index = event.data['index'] image = self.images.combat_images.get(event.type, None) if affected_group == self.attacker_renderer.curr_group: self.attacker_renderer.add_overlay(image, index) else: assert ( affected_group == self.defender_renderer.curr_group) self.defender_renderer.add_overlay(image, index) def set_mask(self, new_mask): self.mask = new_mask def render(self, surface, images): super(CombatRenderer, self).render(surface, images) x = self.rect.x + self.rect.width / 2 y = self.rect.y + text.vlg_font.get_height() images.text.draw_text(self.title_text, text.vlg_font, x, y, surface) if self.phase != "Melee Combat" and self.phase != "Ranged Combat": return att_x, att_y = self.attacker_renderer.selected_anchor_point(True) def_x, def_y = self.defender_renderer.selected_anchor_point(False) if att_x == None or def_x == None: return dx = def_x - att_x dy = def_y - att_y distance = int(math.hypot(dx, dy)) line_width = images.fight_line.get_width() if self.phase == "Melee Combat": fight_line = images.fight_line else: # ranged combat fight_line = images.shoot_line if self.attacker_label.get_label() == None: if self.defender_label.get_label() == None: # no one actually shooting return # defender is active, point arrow other way fight_line = pygame.transform.rotate(fight_line, 180) fight_line = pygame.transform.smoothscale(fight_line, (line_width, distance)) if dx != 0: angle = math.degrees(math.atan(dy / float(dx))) # print "dx: " + str(dx) + " dy: " + str(dy) + " angle: " + str(angle) if angle < 0: angle = -90 - angle else: angle = 90 - angle # print "final angle: " + str(angle) fight_line = pygame.transform.rotate(fight_line, angle) if angle < 0: att_x -= fight_line.get_width() - line_width att_y += math.sin(math.radians(angle)) * (line_width / 2) else: att_y -= math.sin(math.radians(angle)) * (line_width / 2) surface.blit(fight_line, (att_x - line_width / 2, att_y))