Skip to content

Commit

Permalink
Merge pull request #170 from arnauddupuis/arnauddupuis/issue165
Browse files Browse the repository at this point in the history
Add a sprite property to BoardComplexItem
  • Loading branch information
arnauddupuis committed Oct 23, 2021
2 parents 572bf3c + d102c13 commit cdf6c9a
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 21 deletions.
1 change: 1 addition & 0 deletions docs/source/pygamelib.board_items.BoardComplexItem.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ BoardComplexItem
~BoardComplexItem.height
~BoardComplexItem.model
~BoardComplexItem.row
~BoardComplexItem.sprite
~BoardComplexItem.width


81 changes: 61 additions & 20 deletions pygamelib/board_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,9 +747,9 @@ def __init__(
self.name = "Board Multi Item"
self.type = "multi_item"
super().__init__(**kwargs)
self.sprite = core.Sprite()
self.__sprite = core.Sprite()
if sprite is not None:
self.sprite = sprite
self.__sprite = sprite
self.null_sprixel = null_sprixel
if self.null_sprixel is None:
self.null_sprixel = core.Sprixel()
Expand All @@ -764,53 +764,96 @@ def __init__(
# if item in kwargs:
# setattr(self, item, kwargs[item])
if self._size is None:
self._size = self.sprite.size
if isinstance(self.sprite, core.Sprite) and self.sprite.parent is None:
self.sprite.parent = self
self._size = self.__sprite.size
if isinstance(self.__sprite, core.Sprite) and self.__sprite.parent is None:
self.__sprite.parent = self
self.update_sprite()

def __repr__(self): # pragma: no cover
return self.sprite.__repr__()
return self.__sprite.__repr__()

def __str__(self): # pragma: no cover
return self.sprite.__str__()
return self.__sprite.__str__()

@property
def sprite(self):
"""A property to easily access and update a complex item's sprite.
:param new_sprite: The sprite to set
:type new_sprite: :class:`~pygamelib.gfx.core.Sprite`
Example::
npc1 = board_items.ComplexNpc(
sprite=npc_sprite_collection['npc1_idle']
)
# to access the sprite:
if npc1.sprite.width * npc1.sprite.height > CONSTANT_BIG_GUY:
game.screen.place(
base.Text(
'Big boi detected!!!',
core.Color(255,0,0),
style=constants.BOLD,
),
notifications.row,
notifications.column,
)
# And to set it:
if game.player in game.neighbors(3, npc1):
npc1.sprite = npc_sprite_collection['npc1_fight']
"""
return self.__sprite

@sprite.setter
def sprite(self, new_sprite: core.Sprite):
if isinstance(new_sprite, core.Sprite):
self.__sprite = new_sprite
self.update_sprite()

def update_sprite(self):
"""
Update the complex item with the current sprite.
This method needs to be called everytime the sprite is changed.
.. note:: This method use to need to be called everytime the sprite was changed.
Starting with version 1.3.0, it is no longer a requirement as
BoardComplexItem.sprite was turned into a property that takes care of calling
update_sprite().
Example::
item = BoardComplexItem(sprite=position_idle)
for s in [walk_1, walk_2, walk_3, walk_4]:
# This is not only no longer required but also wasteful as
# update_sprite() is called twice here.
item.sprite = s
item.update_sprite()
board.move(item, constants.RIGHT, 1)
time.sleep(0.2)
"""
self._item_matrix = []
# Update sprite size.
self.sprite.calculate_size()
for row in range(0, self.sprite.size[1]):
self.__sprite.calculate_size()
for row in range(0, self.__sprite.size[1]):
self._item_matrix.append([])
for col in range(0, self.sprite.size[0]):
for col in range(0, self.__sprite.size[0]):
if (
self.null_sprixel is not None
and self.sprite.sprixel(row, col) == self.null_sprixel
and self.__sprite.sprixel(row, col) == self.null_sprixel
):
self._item_matrix[row].append(BoardItemVoid())
self._item_matrix[row][col].name = f"{self.name}_{row}_{col}"
self._item_matrix[row][col].parent = self
else:
self._item_matrix[row].append(self.base_item_type(**self.__kwargs))
self._item_matrix[row][col].name = f"{self.name}_{row}_{col}"
self._item_matrix[row][col].model = self.sprite.sprixel(
self._item_matrix[row][col].model = self.__sprite.sprixel(
row, col
).model
self._item_matrix[row][col].sprixel = self.sprite.sprixel(row, col)
self._item_matrix[row][col].sprixel = self.__sprite.sprixel(
row, col
)
self._item_matrix[row][col].parent = self
self._size = self.sprite.size
self._size = self.__sprite.size

def item(self, row, column):
"""
Expand Down Expand Up @@ -853,11 +896,11 @@ def render_to_buffer(self, buffer, row, column, height, width):
# For optimization's sakes we directly loop through the right places in the
# buffer and simply translate the coordinates back to the sprite.
# The loops takes clamped value to not render anything out of the buffer.
for sr in range(row, min(self.sprite.size[1] + row, height)):
for sc in range(column, min(self.sprite.size[0] + column, width)):
for sr in range(row, min(self.__sprite.size[1] + row, height)):
for sc in range(column, min(self.__sprite.size[0] + column, width)):
# TODO: If the Sprite has sprixels with length > 1 this is going to be
# A mess.
buffer[sr][sc] = self.sprite.sprixel(sr - row, sc - column).__repr__()
buffer[sr][sc] = self.__sprite.sprixel(sr - row, sc - column).__repr__()


class Movable(BoardItem):
Expand Down Expand Up @@ -1904,7 +1947,6 @@ def __init__(self, text=None, **kwargs):
else:
self._text = text
self.sprite = core.Sprite.from_text(self._text)
self.update_sprite()

def __repr__(self): # pragma: no cover
return self._text.__repr__()
Expand Down Expand Up @@ -1935,7 +1977,6 @@ def text(self, value):
"TextItem.text must be either a str or a pygamelib.base.Text object."
)
self.sprite = core.Sprite.from_text(self._text)
self.update_sprite()


class Wall(Immovable):
Expand Down
1 change: 0 additions & 1 deletion pygamelib/gfx/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1925,7 +1925,6 @@ def next_frame(self):
self.parent.sprixel = self.frames[self._frame_index]
elif isinstance(self.frames[self._frame_index], Sprite):
self.parent.sprite = self.frames[self._frame_index]
self.parent.update_sprite()
else:
raise base.PglInvalidTypeException(
"Animation.next_frame(): the frame is neither a string, a sprixel nor a"
Expand Down
1 change: 1 addition & 0 deletions tests/test_boardItem.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ def test_boardcomplexitem(self):
bic = board_items.BoardComplexItem(
size=[3, 3], null_sprixel=board_items.core.Sprixel()
)
self.assertIsInstance(bic.sprite, gfx_core.Sprite)
self.assertIsInstance(bic.item(1, 1), board_items.BoardItemVoid)
with self.assertRaises(board_items.base.PglOutOfItemBoundException):
bic.item(5, 6)
Expand Down

0 comments on commit cdf6c9a

Please sign in to comment.