|
|
@@ -137,3 +137,158 @@ class Scoreboard(Text):
|
|
|
if not isinstance(score, int):
|
|
|
raise TypeError(_('Score must be an integer.'))
|
|
|
self.score += score
|
|
|
+
|
|
|
+
|
|
|
+class LevelBar(pygame.Surface):
|
|
|
+ def __init__(
|
|
|
+ self,
|
|
|
+ parts: int,
|
|
|
+ initial_level: int | None = None,
|
|
|
+ position: tuple | list = settings.LEVELBARS_DEFAULT_POSITION,
|
|
|
+ border_color: tuple | list = settings.LEVELBARS_DEFAULT_BORDER_COLOR,
|
|
|
+ fill_color: tuple | list = settings.LEVELBARS_DEFAULT_FILL_COLOR,
|
|
|
+ ):
|
|
|
+ if not isinstance(parts, int):
|
|
|
+ raise TypeError(_('The amount of parts must be an integer.'))
|
|
|
+ if not (0 < parts <= settings.LEVELBARS_MAX_PARTS):
|
|
|
+ raise TypeError(
|
|
|
+ _(
|
|
|
+ f'The amount of parts must be between 1 and {settings.LEVELBARS_MAX_PARTS}.'
|
|
|
+ )
|
|
|
+ )
|
|
|
+ super().__init__(
|
|
|
+ (
|
|
|
+ settings.LEVELBARS_DEFAULT_WIDTH,
|
|
|
+ settings.LEVELBARS_DEFAULT_HEIGHT,
|
|
|
+ )
|
|
|
+ )
|
|
|
+ self._parts = parts
|
|
|
+ if initial_level is None:
|
|
|
+ initial_level = parts
|
|
|
+ self.set(initial_level)
|
|
|
+ self.border_color = border_color
|
|
|
+ self.fill_color = fill_color
|
|
|
+ self.x, self.y = position
|
|
|
+ self._width = settings.LEVELBARS_DEFAULT_WIDTH
|
|
|
+ self._height = settings.LEVELBARS_DEFAULT_HEIGHT
|
|
|
+ self._thick = settings.LEVELBARS_DEFAULT_THICK
|
|
|
+
|
|
|
+ def __int__(self):
|
|
|
+ return int(self._level)
|
|
|
+
|
|
|
+ def __repr(self):
|
|
|
+ return f'LevelBar <{self._level}/{self._parts}>'
|
|
|
+
|
|
|
+ def __str__(self):
|
|
|
+ return f'{self._level}/{self._parts}'
|
|
|
+
|
|
|
+ def decrease(self, decrease: int):
|
|
|
+ """
|
|
|
+ Decrease the level for this bar.
|
|
|
+
|
|
|
+ Parameters:
|
|
|
+ decrease: amount to decrease
|
|
|
+
|
|
|
+ Examples:
|
|
|
+ >>> lifes = LevelBar(5, 3)
|
|
|
+ >>> lifes.decrease(1)
|
|
|
+ """
|
|
|
+ if not isinstance(decrease, int):
|
|
|
+ raise TypeError(_('The decrease level must be an integer.'))
|
|
|
+ if self._level - decrease < 0:
|
|
|
+ raise ValueError(_('The decrease cannot be less than zero.'))
|
|
|
+ self.set(self._level - decrease)
|
|
|
+
|
|
|
+ def increase(self, increase: int):
|
|
|
+ """
|
|
|
+ Increase the level for this bar.
|
|
|
+
|
|
|
+ Parameters:
|
|
|
+ increase: amount to increase
|
|
|
+
|
|
|
+ Examples:
|
|
|
+ >>> lifes = LevelBar(5)
|
|
|
+ >>> lifes.increase(1)
|
|
|
+ """
|
|
|
+ if not isinstance(increase, int):
|
|
|
+ raise TypeError(_('The increase level must be an integer.'))
|
|
|
+ if self._level + increase > self._parts:
|
|
|
+ raise ValueError(_('The increase cannot exceed the maximum level.'))
|
|
|
+ self.set(self._level + increase)
|
|
|
+
|
|
|
+ def set(self, level):
|
|
|
+ """
|
|
|
+ Set the new level for this bar.
|
|
|
+
|
|
|
+ Parameters:
|
|
|
+ level: the new level
|
|
|
+
|
|
|
+ Examples:
|
|
|
+ >>> lifes = LevelBar(5)
|
|
|
+ >>> lifes.set(3)
|
|
|
+ """
|
|
|
+ if not isinstance(level, int):
|
|
|
+ raise TypeError(_('The level must be an integer.'))
|
|
|
+ if not (0 <= level <= self._parts):
|
|
|
+ raise ValueError(
|
|
|
+ _(
|
|
|
+ 'The level range must be between zero and the number of parts.'
|
|
|
+ )
|
|
|
+ )
|
|
|
+ self._level = level
|
|
|
+
|
|
|
+ def draw(self, position: tuple | list | None = None):
|
|
|
+ if position is None:
|
|
|
+ position = (self.x, self.y)
|
|
|
+ else:
|
|
|
+ self.x, self.y = position
|
|
|
+
|
|
|
+ division = int(self._width / self._parts)
|
|
|
+ # left border
|
|
|
+ pygame.draw.line(
|
|
|
+ _globals._window,
|
|
|
+ self.border_color,
|
|
|
+ position,
|
|
|
+ (position[0], position[1] + self._height),
|
|
|
+ self._thick,
|
|
|
+ )
|
|
|
+ # right border
|
|
|
+ pygame.draw.line(
|
|
|
+ _globals._window,
|
|
|
+ self.border_color,
|
|
|
+ (position[0] + division * self._parts, position[1]),
|
|
|
+ (position[0] + division * self._parts, position[1] + self._height),
|
|
|
+ self._thick,
|
|
|
+ )
|
|
|
+ for part in range(self._parts):
|
|
|
+ # top border
|
|
|
+ pygame.draw.line(
|
|
|
+ _globals._window,
|
|
|
+ self.border_color,
|
|
|
+ (position[0] + division * part, position[1]),
|
|
|
+ (position[0] + division * (part+1), position[1]),
|
|
|
+ self._thick,
|
|
|
+ )
|
|
|
+ # inside
|
|
|
+ if part < self._level:
|
|
|
+ pygame.draw.line(
|
|
|
+ _globals._window,
|
|
|
+ self.fill_color,
|
|
|
+ (
|
|
|
+ position[0] + division * part + self._thick / 2,
|
|
|
+ position[1] + int(self._height / 2)),
|
|
|
+ (
|
|
|
+ position[0] + division * (part + 1) - self._thick / 2,
|
|
|
+ position[1] + int(self._height / 2)
|
|
|
+ ),
|
|
|
+ self._height,
|
|
|
+ )
|
|
|
+ # bottom border
|
|
|
+ pygame.draw.line(
|
|
|
+ _globals._window,
|
|
|
+ self.border_color,
|
|
|
+ (position[0] + division * part, position[1] + self._height),
|
|
|
+ (position[0] + division * (part + 1), position[1] + self._height),
|
|
|
+ self._thick,
|
|
|
+ )
|
|
|
+ self.rect = self.get_rect()
|