|
@@ -79,66 +79,105 @@ class Text:
|
|
|
self.render(position=position)
|
|
self.render(position=position)
|
|
|
|
|
|
|
|
|
|
|
|
|
-class Scoreboard(Text):
|
|
|
|
|
- def __init__(self, prefix: str, score: int = 0, **kwargs):
|
|
|
|
|
- if not isinstance(prefix, str):
|
|
|
|
|
- raise TypeError(_('The prefix text must be a string.'))
|
|
|
|
|
|
|
+class Chronometer(Text):
|
|
|
|
|
+ def __init__(
|
|
|
|
|
+ self, initial: int = 0, in_milliseconds: bool = False, **kwargs
|
|
|
|
|
+ ):
|
|
|
|
|
+ if not isinstance(initial, int):
|
|
|
|
|
+ raise TypeError(_('The initial value must be an integer.'))
|
|
|
|
|
+ if initial < 0:
|
|
|
|
|
+ raise ValueError(_('The countdown cannot be negative.'))
|
|
|
|
|
+ if not isinstance(in_milliseconds, bool):
|
|
|
|
|
+ raise TypeError(_('in_milliseconds argument must be a boolean.'))
|
|
|
|
|
+
|
|
|
super().__init__(**kwargs)
|
|
super().__init__(**kwargs)
|
|
|
- self._prefix = prefix
|
|
|
|
|
- self.set_score(score)
|
|
|
|
|
|
|
+ self._initial = initial if in_milliseconds else initial * 1000
|
|
|
|
|
+ self._time = 0
|
|
|
|
|
+ self._timestamp = 0
|
|
|
|
|
+ self._onpause = True
|
|
|
|
|
+ self._message = self.format_clock()
|
|
|
|
|
+
|
|
|
if 'position' in kwargs:
|
|
if 'position' in kwargs:
|
|
|
self.render(position=kwargs['position'])
|
|
self.render(position=kwargs['position'])
|
|
|
else:
|
|
else:
|
|
|
self.render()
|
|
self.render()
|
|
|
|
|
|
|
|
def __int__(self):
|
|
def __int__(self):
|
|
|
- return int(self._score)
|
|
|
|
|
|
|
+ return self.get_milliseconds()
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
def __repr__(self):
|
|
|
- return f'Scoreboard <{self._message}>'
|
|
|
|
|
|
|
+ return f'Chronometer <{self.format_clock()}>'
|
|
|
|
|
|
|
|
def __str__(self):
|
|
def __str__(self):
|
|
|
return self._message
|
|
return self._message
|
|
|
|
|
|
|
|
@property
|
|
@property
|
|
|
- def score(self):
|
|
|
|
|
- return self._score
|
|
|
|
|
|
|
+ def time(self):
|
|
|
|
|
+ return self.get_milliseconds()
|
|
|
|
|
|
|
|
@property
|
|
@property
|
|
|
- def message(self):
|
|
|
|
|
- return self._message
|
|
|
|
|
|
|
+ def onpause(self) -> bool:
|
|
|
|
|
+ return self._onpause
|
|
|
|
|
|
|
|
- def set_score(self, score: int):
|
|
|
|
|
- """
|
|
|
|
|
- Set the character score.
|
|
|
|
|
|
|
+ def format_clock(self, include_millis: bool = False) -> str:
|
|
|
|
|
+ formatted_time = tuple(
|
|
|
|
|
+ map(lambda x: str(x).zfill(2), self.get_clock())
|
|
|
|
|
+ )
|
|
|
|
|
+ formatted_clock = ':'.join(formatted_time[:-1])
|
|
|
|
|
+ if include_millis:
|
|
|
|
|
+ formatted_clock += f'.{formatted_time[-1]}'
|
|
|
|
|
+ return formatted_clock
|
|
|
|
|
+
|
|
|
|
|
+ def get_clock(self) -> tuple:
|
|
|
|
|
+ millis = self.get_milliseconds()
|
|
|
|
|
+ if millis > 0:
|
|
|
|
|
+ quotient = millis // 1000
|
|
|
|
|
+ millis = millis % 1000
|
|
|
|
|
+ seconds = quotient % 60
|
|
|
|
|
+ quotient = quotient // 60
|
|
|
|
|
+ minutes = quotient % 60
|
|
|
|
|
+ hours = quotient // 60
|
|
|
|
|
+ return hours, minutes, seconds, millis
|
|
|
|
|
+ return 0, 0, 0, 0
|
|
|
|
|
+
|
|
|
|
|
+ def get_milliseconds(self) -> int:
|
|
|
|
|
+ if self._onpause:
|
|
|
|
|
+ current = (
|
|
|
|
|
+ self._initial - self._time if self._initial else self._time
|
|
|
|
|
+ )
|
|
|
|
|
+ else:
|
|
|
|
|
+ if self._initial:
|
|
|
|
|
+ current = self._initial - (
|
|
|
|
|
+ self._time + pygame.time.get_ticks() - self._timestamp
|
|
|
|
|
+ )
|
|
|
|
|
+ else:
|
|
|
|
|
+ current = (
|
|
|
|
|
+ self._time + pygame.time.get_ticks() - self._timestamp
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
- Parameters:
|
|
|
|
|
- score: the new character score
|
|
|
|
|
|
|
+ current = max(0, current)
|
|
|
|
|
+ return current
|
|
|
|
|
|
|
|
- Examples:
|
|
|
|
|
- >>> scoreboard = Scoreboard('My character: ')
|
|
|
|
|
- >>> scoreboard.set_score(100)
|
|
|
|
|
- """
|
|
|
|
|
- if not isinstance(score, int):
|
|
|
|
|
- raise TypeError(_('Score must be an integer.'))
|
|
|
|
|
- self._score = score
|
|
|
|
|
- self._message = f'{self._prefix}{self._score}'
|
|
|
|
|
- self.render()
|
|
|
|
|
|
|
+ def get_seconds(self) -> int:
|
|
|
|
|
+ return self.get_milliseconds() // 1000
|
|
|
|
|
|
|
|
- def add_score(self, score: int):
|
|
|
|
|
- """
|
|
|
|
|
- Increment the character score.
|
|
|
|
|
|
|
+ def init(self):
|
|
|
|
|
+ self._time = 0
|
|
|
|
|
+ self._timestamp = pygame.time.get_ticks()
|
|
|
|
|
+ self._onpause = False
|
|
|
|
|
|
|
|
- Parameters:
|
|
|
|
|
- score: the character score to be added
|
|
|
|
|
|
|
+ def pause(self):
|
|
|
|
|
+ if not self._onpause:
|
|
|
|
|
+ self._onpause = True
|
|
|
|
|
+ self._time = self._time + pygame.time.get_ticks() - self._timestamp
|
|
|
|
|
|
|
|
- Examples:
|
|
|
|
|
- >>> scoreboard = Scoreboard('My character: ')
|
|
|
|
|
- >>> scoreboard.add_score(5)
|
|
|
|
|
- """
|
|
|
|
|
- if not isinstance(score, int):
|
|
|
|
|
- raise TypeError(_('Score must be an integer.'))
|
|
|
|
|
- self._score += score
|
|
|
|
|
|
|
+ def resume(self):
|
|
|
|
|
+ if self._onpause:
|
|
|
|
|
+ self._onpause = False
|
|
|
|
|
+ self._timestamp = pygame.time.get_ticks()
|
|
|
|
|
+
|
|
|
|
|
+ def update(self):
|
|
|
|
|
+ self._message = self.format_clock()
|
|
|
|
|
|
|
|
|
|
|
|
|
class LevelBar(pygame.Surface):
|
|
class LevelBar(pygame.Surface):
|
|
@@ -300,3 +339,65 @@ class LevelBar(pygame.Surface):
|
|
|
self._thick,
|
|
self._thick,
|
|
|
)
|
|
)
|
|
|
self.rect = self.get_rect()
|
|
self.rect = self.get_rect()
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class Scoreboard(Text):
|
|
|
|
|
+ def __init__(self, prefix: str, score: int = 0, **kwargs):
|
|
|
|
|
+ if not isinstance(prefix, str):
|
|
|
|
|
+ raise TypeError(_('The prefix text must be a string.'))
|
|
|
|
|
+ super().__init__(**kwargs)
|
|
|
|
|
+ self._prefix = prefix
|
|
|
|
|
+ self.set_score(score)
|
|
|
|
|
+ if 'position' in kwargs:
|
|
|
|
|
+ self.render(position=kwargs['position'])
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.render()
|
|
|
|
|
+
|
|
|
|
|
+ def __int__(self):
|
|
|
|
|
+ return int(self._score)
|
|
|
|
|
+
|
|
|
|
|
+ def __repr__(self):
|
|
|
|
|
+ return f'Scoreboard <{self._message}>'
|
|
|
|
|
+
|
|
|
|
|
+ def __str__(self):
|
|
|
|
|
+ return self._message
|
|
|
|
|
+
|
|
|
|
|
+ @property
|
|
|
|
|
+ def score(self):
|
|
|
|
|
+ return self._score
|
|
|
|
|
+
|
|
|
|
|
+ @property
|
|
|
|
|
+ def message(self):
|
|
|
|
|
+ return self._message
|
|
|
|
|
+
|
|
|
|
|
+ def set_score(self, score: int):
|
|
|
|
|
+ """
|
|
|
|
|
+ Set the character score.
|
|
|
|
|
+
|
|
|
|
|
+ Parameters:
|
|
|
|
|
+ score: the new character score
|
|
|
|
|
+
|
|
|
|
|
+ Examples:
|
|
|
|
|
+ >>> scoreboard = Scoreboard('My character: ')
|
|
|
|
|
+ >>> scoreboard.set_score(100)
|
|
|
|
|
+ """
|
|
|
|
|
+ if not isinstance(score, int):
|
|
|
|
|
+ raise TypeError(_('Score must be an integer.'))
|
|
|
|
|
+ self._score = score
|
|
|
|
|
+ self._message = f'{self._prefix}{self._score}'
|
|
|
|
|
+ self.render()
|
|
|
|
|
+
|
|
|
|
|
+ def add_score(self, score: int):
|
|
|
|
|
+ """
|
|
|
|
|
+ Increment the character score.
|
|
|
|
|
+
|
|
|
|
|
+ Parameters:
|
|
|
|
|
+ score: the character score to be added
|
|
|
|
|
+
|
|
|
|
|
+ Examples:
|
|
|
|
|
+ >>> scoreboard = Scoreboard('My character: ')
|
|
|
|
|
+ >>> scoreboard.add_score(5)
|
|
|
|
|
+ """
|
|
|
|
|
+ if not isinstance(score, int):
|
|
|
|
|
+ raise TypeError(_('Score must be an integer.'))
|
|
|
|
|
+ self._score += score
|