|
@@ -11,6 +11,14 @@ from jogai._globals import _window
|
|
|
from jogai.translations import gettext as _
|
|
from jogai.translations import gettext as _
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+class Velocity:
|
|
|
|
|
+ x = 0
|
|
|
|
|
+ y = 0
|
|
|
|
|
+
|
|
|
|
|
+ def __repr__(self):
|
|
|
|
|
+ return f'{self.x}, {self.y}'
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
class Character(pygame.sprite.Sprite):
|
|
class Character(pygame.sprite.Sprite):
|
|
|
"""
|
|
"""
|
|
|
A videogame character with a bunch of actions.
|
|
A videogame character with a bunch of actions.
|
|
@@ -43,7 +51,7 @@ class Character(pygame.sprite.Sprite):
|
|
|
raise TypeError(_('The character name must be a string.'))
|
|
raise TypeError(_('The character name must be a string.'))
|
|
|
|
|
|
|
|
self.scale_factor = 1.0
|
|
self.scale_factor = 1.0
|
|
|
- self.speed = 0
|
|
|
|
|
|
|
+ self.velocity = Velocity()
|
|
|
self.predefined_keys = {}
|
|
self.predefined_keys = {}
|
|
|
self.image_filename = image_filename
|
|
self.image_filename = image_filename
|
|
|
self.image = None
|
|
self.image = None
|
|
@@ -85,13 +93,17 @@ class Character(pygame.sprite.Sprite):
|
|
|
eval(f'self.set_{attribute}(data["{attribute}"])')
|
|
eval(f'self.set_{attribute}(data["{attribute}"])')
|
|
|
|
|
|
|
|
@property
|
|
@property
|
|
|
- def height(self):
|
|
|
|
|
|
|
+ def height(self) -> int:
|
|
|
return self.rect.height
|
|
return self.rect.height
|
|
|
|
|
|
|
|
@property
|
|
@property
|
|
|
- def width(self):
|
|
|
|
|
|
|
+ def width(self) -> int:
|
|
|
return self.rect.width
|
|
return self.rect.width
|
|
|
|
|
|
|
|
|
|
+ @property
|
|
|
|
|
+ def speed(self) -> float:
|
|
|
|
|
+ return (abs(self.velocity.x) + abs(self.velocity.y)) / 2
|
|
|
|
|
+
|
|
|
def _eval_predefined_function(
|
|
def _eval_predefined_function(
|
|
|
self, function: str, arguments: str | list | dict
|
|
self, function: str, arguments: str | list | dict
|
|
|
):
|
|
):
|
|
@@ -126,9 +138,9 @@ class Character(pygame.sprite.Sprite):
|
|
|
>>> protagonist.move()
|
|
>>> protagonist.move()
|
|
|
"""
|
|
"""
|
|
|
if x is None:
|
|
if x is None:
|
|
|
- x = self.speed
|
|
|
|
|
|
|
+ x = self.velocity.x
|
|
|
if y is None:
|
|
if y is None:
|
|
|
- y = self.speed
|
|
|
|
|
|
|
+ y = self.velocity.y
|
|
|
|
|
|
|
|
if not isinstance(x, int) or not isinstance(y, int):
|
|
if not isinstance(x, int) or not isinstance(y, int):
|
|
|
raise TypeError(_('Amount to move must be an integer.'))
|
|
raise TypeError(_('Amount to move must be an integer.'))
|
|
@@ -140,6 +152,12 @@ class Character(pygame.sprite.Sprite):
|
|
|
if relative:
|
|
if relative:
|
|
|
self.x += x
|
|
self.x += x
|
|
|
self.y += y
|
|
self.y += y
|
|
|
|
|
+ self.velocity.x = abs(self.velocity.x)
|
|
|
|
|
+ if x < 0:
|
|
|
|
|
+ self.velocity.x *= -1
|
|
|
|
|
+ self.velocity.y = abs(self.velocity.y)
|
|
|
|
|
+ if y < 0:
|
|
|
|
|
+ self.velocity.y *= -1
|
|
|
else:
|
|
else:
|
|
|
self.x = x
|
|
self.x = x
|
|
|
self.y = y
|
|
self.y = y
|
|
@@ -173,7 +191,11 @@ class Character(pygame.sprite.Sprite):
|
|
|
>>> protagonist.backward()
|
|
>>> protagonist.backward()
|
|
|
"""
|
|
"""
|
|
|
if amount is None:
|
|
if amount is None:
|
|
|
- amount = self.speed
|
|
|
|
|
|
|
+ amount = abs(self.velocity.x)
|
|
|
|
|
+
|
|
|
|
|
+ if not isinstance(amount, int):
|
|
|
|
|
+ raise TypeError(_('The amount to go up must be an integer.'))
|
|
|
|
|
+
|
|
|
self.move(-amount, 0, key)
|
|
self.move(-amount, 0, key)
|
|
|
|
|
|
|
|
def down(self, amount: int | None = None, key: str = ''):
|
|
def down(self, amount: int | None = None, key: str = ''):
|
|
@@ -190,7 +212,10 @@ class Character(pygame.sprite.Sprite):
|
|
|
>>> protagonist.down()
|
|
>>> protagonist.down()
|
|
|
"""
|
|
"""
|
|
|
if amount is None:
|
|
if amount is None:
|
|
|
- amount = self.speed
|
|
|
|
|
|
|
+ amount = abs(self.velocity.y)
|
|
|
|
|
+
|
|
|
|
|
+ if not isinstance(amount, int):
|
|
|
|
|
+ raise TypeError(_('The amount to go down must be an integer.'))
|
|
|
|
|
|
|
|
if not self.is_jumping:
|
|
if not self.is_jumping:
|
|
|
self.move(0, amount, key)
|
|
self.move(0, amount, key)
|
|
@@ -209,7 +234,11 @@ class Character(pygame.sprite.Sprite):
|
|
|
>>> protagonist.forward()
|
|
>>> protagonist.forward()
|
|
|
"""
|
|
"""
|
|
|
if amount is None:
|
|
if amount is None:
|
|
|
- amount = self.speed
|
|
|
|
|
|
|
+ amount = abs(self.velocity.x)
|
|
|
|
|
+
|
|
|
|
|
+ if not isinstance(amount, int):
|
|
|
|
|
+ raise TypeError(_('The amount to go forward must be an integer.'))
|
|
|
|
|
+
|
|
|
self.move(amount, 0, key)
|
|
self.move(amount, 0, key)
|
|
|
|
|
|
|
|
def up(self, amount: int | None = None, key: str = ''):
|
|
def up(self, amount: int | None = None, key: str = ''):
|
|
@@ -226,7 +255,10 @@ class Character(pygame.sprite.Sprite):
|
|
|
>>> protagonist.up()
|
|
>>> protagonist.up()
|
|
|
"""
|
|
"""
|
|
|
if amount is None:
|
|
if amount is None:
|
|
|
- amount = self.speed
|
|
|
|
|
|
|
+ amount = abs(self.velocity.y)
|
|
|
|
|
+
|
|
|
|
|
+ if not isinstance(amount, int):
|
|
|
|
|
+ raise TypeError(_('The amount to go up must be an integer.'))
|
|
|
|
|
|
|
|
if not self.is_jumping:
|
|
if not self.is_jumping:
|
|
|
self.move(0, -amount, key)
|
|
self.move(0, -amount, key)
|
|
@@ -265,6 +297,7 @@ class Character(pygame.sprite.Sprite):
|
|
|
not key or _get_keys()[utils.eval_key(key)]
|
|
not key or _get_keys()[utils.eval_key(key)]
|
|
|
):
|
|
):
|
|
|
self.is_jumping = True
|
|
self.is_jumping = True
|
|
|
|
|
+ self.velocity.y = -abs(self.velocity.y)
|
|
|
|
|
|
|
|
def rotate(self, increment: int = 1):
|
|
def rotate(self, increment: int = 1):
|
|
|
"""
|
|
"""
|
|
@@ -485,8 +518,10 @@ class Character(pygame.sprite.Sprite):
|
|
|
>>> protagonist = Character('protagonist.png')
|
|
>>> protagonist = Character('protagonist.png')
|
|
|
>>> protagonist.set_speed(10)
|
|
>>> protagonist.set_speed(10)
|
|
|
"""
|
|
"""
|
|
|
- if isinstance(speed, int):
|
|
|
|
|
- self.speed = speed
|
|
|
|
|
|
|
+ if not isinstance(speed, int):
|
|
|
|
|
+ raise TypeError(_('The speed must be an integer.'))
|
|
|
|
|
+ self.velocity.x = speed
|
|
|
|
|
+ self.velocity.y = speed
|
|
|
|
|
|
|
|
def set_width(self, width: int):
|
|
def set_width(self, width: int):
|
|
|
"""
|
|
"""
|
|
@@ -560,6 +595,12 @@ class Character(pygame.sprite.Sprite):
|
|
|
return True
|
|
return True
|
|
|
return False
|
|
return False
|
|
|
|
|
|
|
|
|
|
+ def collide(
|
|
|
|
|
+ self,
|
|
|
|
|
+ other_characters: Type['Character'] | Type['jogai.group.Group'] | list,
|
|
|
|
|
+ ):
|
|
|
|
|
+ ...
|
|
|
|
|
+
|
|
|
def load(self, filename: str):
|
|
def load(self, filename: str):
|
|
|
"""
|
|
"""
|
|
|
>>> protagonist = Character('protagonist.png')
|
|
>>> protagonist = Character('protagonist.png')
|
|
@@ -605,6 +646,8 @@ class Character(pygame.sprite.Sprite):
|
|
|
Calculate and update the character position during the jump.
|
|
Calculate and update the character position during the jump.
|
|
|
"""
|
|
"""
|
|
|
if self.is_jumping:
|
|
if self.is_jumping:
|
|
|
|
|
+ if self._jump_counter == 0:
|
|
|
|
|
+ self.velocity.y = abs(self.velocity.y)
|
|
|
if self._jump_counter >= -self.jump_force:
|
|
if self._jump_counter >= -self.jump_force:
|
|
|
self.move(
|
|
self.move(
|
|
|
0,
|
|
0,
|