From 6c66ede9945f647ab9be47dcda8f8ab3cb3fde1d Mon Sep 17 00:00:00 2001 From: adrianna Date: Fri, 16 Sep 2016 00:58:40 +0200 Subject: [PATCH] added tooltips with information about light tools --- TODO.txt | 5 ++-- tabakrolletjie/lights.py | 34 +++++++++++++++++++++++++ tabakrolletjie/scenes/day.py | 14 +++++++---- tabakrolletjie/widgets.py | 49 +++++++++++++++++++++++++++++++++++- 4 files changed, 94 insertions(+), 8 deletions(-) diff --git a/TODO.txt b/TODO.txt index a38aa58..033052a 100644 --- a/TODO.txt +++ b/TODO.txt @@ -10,8 +10,8 @@ Features * Maybe configure lights in separate json file, to allow reuse of consistent models in multiple levels? * Allow going down to zero seeds by buying lights if a turnip is planted * Maybe make the mould weaker at the start -* Display power usage when lights are bought? Also other properties. -* Maybe also display information next to existing lights (on click?) +* Display average power usage in light tooltip +* Maybe also display information next to existing lights -- tooltip? * Generally balance the levels better and add more levels * Graphical level selection with screenshots * Fast forward button for night-time (calculate more steps between redraws; play sounds sped up and with higher pitch) @@ -49,3 +49,4 @@ Done * Different power usage for different lights (this was already done) * Different prices for different lights * Calculate both from # of colours, speed, beam width, etc.? +* added tooltips for lights diff --git a/tabakrolletjie/lights.py b/tabakrolletjie/lights.py index 44c9387..00f4c85 100644 --- a/tabakrolletjie/lights.py +++ b/tabakrolletjie/lights.py @@ -142,6 +142,11 @@ def seed_cost(light_config, num_colours): cls = BaseLight.find_cls(light_config["type"]) return cls.BASE_COST + int(cls.find_cost(light_config) / 10) + num_colours +def light_info(light_config): + """Generate info about a light to go in the tooltip. """ + cls = BaseLight.find_cls(light_config["type"]) + return cls.get_info(light_config) + class BaseLight(object): """ Common light functionality. """ @@ -216,6 +221,10 @@ class BaseLight(object): cost = 5 * config["intensity"] return cost + @classmethod + def get_info(cls, config): + return ["intensity: %g" % config["intensity"]] + def add(self, space): if self.body.space is not None: space.remove(self.body, *self.body.shapes) @@ -382,6 +391,17 @@ class PulsatingLamp(BaseLight): cost += 5 * (ir[1] - ir[0]) return cost + @classmethod + def get_info(cls, config): + pr = config.get("pulse_range", cls.DEFAULT_PULSE_RANGE) + pv = config.get("pulse_velocity", cls.DEFAULT_PULSE_VELOCITY) + ir = config.get("intensity_range", cls.DEFAULT_INTENSITY_RANGE) + iv = config.get("intensity_velocity", cls.DEFAULT_INTENSITY_VELOCITY) + return [ + "intensity: %g - %g, velocity %g" % (ir[0], ir[1], iv), + "pulse: %d - %d, velocity %g" % (pr[0], pr[1], pv), + ] + class SpotLight(BaseLight): @@ -417,4 +437,18 @@ class SpotLight(BaseLight): def find_cost(cls, config): cost = super(SpotLight, cls).find_cost(config) cost += config.get("angular_velocity", 0) + cost += config["spread"] / 10 + rl = config["radius_limits"] + cost += (rl[1] - rl[0]) / 10 return cost + + @classmethod + def get_info(cls, config): + info = super(SpotLight, cls).get_info(config) + rl = config["radius_limits"] + info.extend([ + "spread: %d" % config["spread"], + "length: %d" % (rl[1] - rl[0]), + "angular velocity: %g" % config.get("angular_velocity", 0), + ]) + return info diff --git a/tabakrolletjie/scenes/day.py b/tabakrolletjie/scenes/day.py index 8dd9c7b..a43517c 100644 --- a/tabakrolletjie/scenes/day.py +++ b/tabakrolletjie/scenes/day.py @@ -11,7 +11,7 @@ import pymunk.pygame_util from .base import BaseScene from ..battery import BatteryManager -from ..lights import LightManager, light_fitting_by_type, check_space_for_light, seed_cost +from ..lights import LightManager, light_fitting_by_type, check_space_for_light, seed_cost, light_info from ..infobar import InfoBar from ..obstacles import ObstacleManager from ..events import SceneChangeEvent @@ -21,7 +21,7 @@ from ..sound import sound from ..transforms import Overlay, Alpha, ColourWedges from ..constants import SCREEN_SIZE, FONTS, FPS, NIGHT_HOURS_PER_TICK, DEBUG -from ..widgets import ImageButton +from ..widgets import ImageButton, Tooltip from ..turnip import Turnip, TurnipInvalidPosition @@ -159,6 +159,7 @@ class DayScene(BaseScene): tool.render(surface) for light_tool in self._light_toolbar: light_tool.render(surface) + self._draw_cursor(surface) if self._game_over_text: for surf, pos in self._game_over_text: @@ -176,12 +177,15 @@ class DayScene(BaseScene): light_tool = ImageButton( "32", light_fitting, transform=ColourWedges(colours=colours), pos=(x, height), name=combo) - font = loader.load_font(FONTS["sans"], size=12) - tool_cost = font.render("%d" % cost, True, (0, 0, 0)) - light_tool._img.blit(tool_cost, (16, 12), None) light_tool.colours = colours light_tool.cost = cost + + tooltip_text = ["cost: %d" % cost] + light_info(light_config) + + tooltip = Tooltip(tooltip_text) + light_tool.tooltip = tooltip + self._light_toolbar.append(light_tool) x += 40 diff --git a/tabakrolletjie/widgets.py b/tabakrolletjie/widgets.py index 4341c70..166cfc0 100644 --- a/tabakrolletjie/widgets.py +++ b/tabakrolletjie/widgets.py @@ -3,12 +3,40 @@ # There is no implied container / window system (yet) import pygame.locals as pgl +import pygame.mouse +import pygame.surface from .loader import loader -from .constants import FONTS +from .constants import FONTS, COLOURS from .transforms import NullTransform, Multiply +class Tooltip(object): + def __init__(self, textparts, font='sans', size=12, padding=5, distance=10): + self._font = loader.load_font(FONTS[font], size=size) + self._text = [self._font.render(text, True, COLOURS["white"]) for text in textparts] + self._padding = padding + self._distance = distance + + def render(self, surface, tool_pos, tool_width): + width = max(t.get_size()[0] for t in self._text) + 2 * self._padding + height = sum(t.get_size()[1] for t in self._text) + 2 * self._padding + + tooltip = pygame.surface.Surface( + (width, height), pgl.SWSURFACE).convert_alpha() + tooltip.fill((0, 0, 0, 172)) + + ty = 0 + for t in self._text: + tooltip.blit(t, (self._padding, self._padding + ty), None) + ty += self._font.get_height() + + x = tool_pos[0] - width/2 + tool_width/2 + y = tool_pos[1] - height - self._distance + + surface.blit(tooltip, (x, y), None) + + class Button(object): def __init__(self, size, name=None, pos=None, padding=10): @@ -17,6 +45,7 @@ class Button(object): self.position = pos self.name = name self.enabled = True + self.tooltip = None def enable(self): self.enabled = True @@ -58,6 +87,20 @@ class Button(object): return True return False + def mouseover(self): + if not self.enabled: + return False + if self._pos is None: + # Unplaced buttons can't be moused over + return False + + mpos = pygame.mouse.get_pos() + + if self._min_x < mpos[0] < self._max_x: + if self._min_y < mpos[1] < self._max_y: + return True + return False + class SpacerButton(Button): """ Add a nothing object which can be used to space other things, @@ -85,6 +128,8 @@ class TextButton(Button): def render(self, surface): if self.enabled: surface.blit(self._text, self._pos, None) + if self.mouseover() and self.tooltip: + self.tooltip.render(surface, self._pos, self.get_width()) else: surface.blit(self._disabled_text, self._pos, None) @@ -112,5 +157,7 @@ class ImageButton(Button): def render(self, surface): if self.enabled: surface.blit(self._img, self._pos, None) + if self.mouseover() and self.tooltip: + self.tooltip.render(surface, self._pos, self.get_width()) else: surface.blit(self._disabled_img, self._pos, None) -- 2.34.1