Kaynağa Gözat

Scoreboard() added to texts and Text() rewrited.

Zero! Studio 1 yıl önce
ebeveyn
işleme
67d91e1a3f
7 değiştirilmiş dosya ile 172 ekleme ve 10 silme
  1. 1 0
      data/02.yaml
  2. 1 0
      jogai/_globals.py
  3. 31 1
      jogai/character.py
  4. 3 0
      jogai/settings.py
  5. 116 7
      jogai/texts.py
  6. 20 1
      jogai/videogame.py
  7. 0 1
      scripts/basics.py

+ 1 - 0
data/02.yaml

@@ -4,6 +4,7 @@ scene: test_large.png
 characters:
   protagonist:
     gravitative: True
+    score: 10
     speed: 20
     width: 50
     position: [465, 300]

+ 1 - 0
jogai/_globals.py

@@ -21,4 +21,5 @@ mark_font = None
 vg_scene = None
 vg_characters = []
 vg_groups = []
+vg_scoreboards = []
 vg_texts = []

+ 31 - 1
jogai/character.py

@@ -4,7 +4,7 @@ import pygame
 
 import jogai
 import jogai._globals as _globals
-from jogai import logger, settings, utils
+from jogai import logger, settings, texts, utils
 from jogai.translations import gettext as _
 from jogai.utils import _get_keys
 
@@ -44,6 +44,7 @@ class Character(pygame.sprite.Sprite):
         _('height'),
         _('keys'),
         _('position'),
+        _('score'),
         _('speed'),
         _('width'),
     ]
@@ -75,6 +76,7 @@ class Character(pygame.sprite.Sprite):
         self.angle = 0
         self.collidable = True
         self.flipped = {'horizontal': False, 'vertical': False}
+        self.score = None
 
         super().__init__()
         self.load(image_filename)
@@ -579,6 +581,34 @@ class Character(pygame.sprite.Sprite):
 
         self.move(position[0], position[1], key, relative=False)
 
+    def set_score(self, score: int):
+        """
+        Set the character score and the scoreboard.
+
+        Parameters:
+            score: the new character score
+
+        Examples:
+            >>> protagonist = Character('protagonist.png')
+            >>> protagonist.set_score(5)
+        """
+        if not isinstance(score, int):
+            raise TypeError(_('The score must be an integer.'))
+        scoreboard_pos = len(_globals.vg_scoreboards)
+        if self.score is None:
+            self.score = texts.Scoreboard(
+                f'{self.name} ',
+                score=score,
+                position=(
+                    settings.SCOREBOARD_POSITION[0],
+                    settings.SCOREBOARD_POSITION[1] + scoreboard_pos * 50,
+                ),
+            )
+            _globals.vg_scoreboards.append(self.score)
+        else:
+            self.score.set(score)
+
+
     def set_speed(self, speed: int):
         """
         Set the character speed.

+ 3 - 0
jogai/settings.py

@@ -27,3 +27,6 @@ DATA_DIR = _('data')
 
 # DEFAULT CHARACTER FEATURES
 DEFAULT_JUMP_FORCE = 10.0
+
+# SCOREBOARDS
+SCOREBOARD_POSITION = (50, 50)

+ 116 - 7
jogai/texts.py

@@ -3,7 +3,7 @@ from os.path import join
 import pygame
 
 from jogai import _globals, settings
-
+from jogai.translations import gettext as _
 
 class Text:
     def __init__(
@@ -17,14 +17,123 @@ class Text:
         italic: bool = False,
         shadow: tuple = (),
     ):
-        self.message = message
         self.color = color
-        self.x = position[0]
-        self.y = position[1]
         self.font = pygame.font.Font(join(settings.FONTS_DIR, font), size)
         self.font.set_bold(bold)
         self.font.set_italic(italic)
-        self.image = self.font.render(self.message, True, self.color)
+        self._message = message
+        self.render(position, message)
+
+    @property
+    def x(self):
+        return self.rect.x
+
+    @property
+    def y(self):
+        return self.rect.y
+
+    def render(self, position: tuple = (), message: str = ''):
+        if not isinstance(position, tuple) and not isinstance(position, list):
+            raise TypeError(_('The position must be a tuple or list (x, y).'))
+        if position and len(position) != 2:
+            raise ValueError(_('The position has two coordinates (x, y).'))
+        if not isinstance(message, str):
+            raise TypeError(_('The message must be a string.'))
+        if not position:
+            position = (self.rect.x, self.rect.y)
+        if message:
+            self._message = message
+        self.image = self.font.render(self._message, True, self.color)
         self.rect = self.image.get_rect()
-        self.rect.x = self.x
-        self.rect.y = self.y
+        self.rect.x, self.rect.y = position
+
+
+    def set_message(self, message: str, key: str = ''):
+        """
+        Set a new message for the text.
+
+        Parameters:
+            message: The new message
+
+        Examples:
+            >>> t = Text()
+            >>> t.set_message('Test')
+        """
+        if not key or _get_keys()[utils.eval_key(key)]:
+            self.render(message=message)
+
+    def set_position(self, position: tuple | list, key: str = ''):
+        """
+        Set the text position as tuple.
+
+        Parameters:
+            position: A tuple with abscissa and ordinate coordinates
+
+        Examples:
+            >>> t = Text('Test')
+            >>> t.set_position((200, 200))
+        """
+        if not key or _get_keys()[utils.eval_key(key)]:
+            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.'))
+        super().__init__(**kwargs)
+        self._prefix = prefix
+        self.set(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(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(self, score: int):
+        """
+        Increment the character score.
+
+        Parameters:
+            score: the character score to be added
+
+        Examples:
+            >>> scoreboard = Scoreboard('My character: ')
+            >>> scoreboard.add(5)
+        """
+        if not isinstance(score, int):
+            raise TypeError(_('Score must be an integer.'))
+        self.score += score

+ 20 - 1
jogai/videogame.py

@@ -165,6 +165,22 @@ def add_group(new_group: 'group.SquareGroup'):
     _globals.vg_groups.append(new_group)
 
 
+def add_scoreboard(new_text: 'texts.Text'):
+    """
+    Add a new text to the videogame.
+
+    Parameters:
+        new_text: the text to be added
+
+    Examples:
+        >>> text = texts.Text('Test')
+        >>> add_text(text) # doctest: +SKIP
+    """
+    if not isinstance(new_scoreboard, texts.Text):
+        raise TypeError(_('Only Scoreboard instances can be added.'))
+    _globals.vg_scobreboards.append(new_scoreboard)
+
+
 def add_text(new_text: 'texts.Text'):
     """
     Add a new text to the videogame.
@@ -177,7 +193,7 @@ def add_text(new_text: 'texts.Text'):
         >>> add_text(text) # doctest: +SKIP
     """
     if not isinstance(new_text, texts.Text):
-        raise TypeError(_('Only Group instances can be added.'))
+        raise TypeError(_('Only Text instances can be added.'))
     _globals.vg_texts.append(new_text)
 
 
@@ -380,6 +396,9 @@ def update():
     if _globals.vg_texts:
         for text_item in _globals.vg_texts:
             paint(text_item)
+    if _globals.vg_scoreboards:
+        for scoreboard_item in _globals.vg_scoreboards:
+            paint(scoreboard_item)
     if _globals.marks:
         _globals.marks.draw()
     pygame.display.flip()

+ 0 - 1
scripts/basics.py

@@ -6,7 +6,6 @@ def test_example01():
     prepare('02.yaml')
     sq = StairsGroup(brick, 5)
     add_group(sq)
-    # set_marks(25, debug=True)
 
     while is_running():
         update()