Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added multi-jumps to jump method/can_jump interval test #1961

Draft
wants to merge 17 commits into
base: development
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
80 changes: 67 additions & 13 deletions arcade/physics_engines.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ def __init__(self,
gravity_constant: float = 0.5,
ladders: Optional[Union[SpriteList, Iterable[SpriteList]]] = None,
walls: Optional[Union[SpriteList, Iterable[SpriteList]]] = None,
jump_delay: int = 0
):
self._ladders: Optional[List[SpriteList]]
self._platforms: List[SpriteList]
Expand All @@ -322,6 +323,8 @@ def __init__(self,
self.gravity_constant: float = gravity_constant
self.jumps_since_ground: int = 0
self.allowed_jumps: int = 1
self.jump_delay = jump_delay
self.jump_ticks = jump_delay
self.allow_multi_jump: bool = False

# The property object for ladders. This allows us setter/getter/deleter capabilities in safe manner
Expand Down Expand Up @@ -378,17 +381,17 @@ def is_on_ladder(self):
# Check for touching a ladder
if self.ladders:
hit_list = check_for_collision_with_lists(self.player_sprite, self.ladders)
if len(hit_list) > 0:
if hit_list and self.jump_ticks >= self.jump_delay:
self.jumps_since_ground = 0
return True
return False

def can_jump(self, y_distance: float = 5) -> bool:
def is_on_ground(self, y_distance: float = 5) -> bool:
"""
Method that looks to see if there is a floor under
the player_sprite. If there is a floor, the player can jump
and we return a True.
the player_sprite. If there is a floor, we return a True.

:returns: True if there is a platform below us
:returns: True if there is a platform below us.
"""

# Move down to see if we are on a platform
Expand All @@ -399,10 +402,24 @@ def can_jump(self, y_distance: float = 5) -> bool:

self.player_sprite.center_y += y_distance

if len(hit_list) > 0:
if hit_list:
self.jumps_since_ground = 0
return True
else:
return False

if len(hit_list) > 0 or self.allow_multi_jump and self.jumps_since_ground < self.allowed_jumps:
def can_jump(self, y_distance: float = 5) -> bool:
"""
Method that looks to see if there is a floor under
the player_sprite. If there is a floor, the player can jump
and we return a True.

:returns: True if there is a platform below us
"""

if (self.is_on_ground(y_distance) or self.is_on_ladder() or self.allow_multi_jump and
self.jumps_since_ground < self.allowed_jumps and
self.jump_ticks >= self.jump_delay):
return True
else:
return False
Expand All @@ -414,9 +431,10 @@ def enable_multi_jump(self, allowed_jumps: int):
(1 allows only a single jump, 2 enables double-jump, etc)

If you enable multi-jump, you MUST call increment_jump_counter()
every time the player jumps. Otherwise they can jump infinitely.
every time the player jumps. Otherwise, they can jump infinitely.

:param allowed_jumps:
:param allowed_jumps: Maximum number of jumps allowed
:param jump_delay: Number of ticks before another jump is allowed
"""
self.allowed_jumps = allowed_jumps
self.allow_multi_jump = True
Expand All @@ -432,17 +450,51 @@ def disable_multi_jump(self):
self.allowed_jumps = 1
self.jumps_since_ground = 0

def jump(self, velocity: int):
""" Have the character jump. """
self.player_sprite.change_y = velocity
self.increment_jump_counter()
def jump(self, velocity: int,
air_jump_velocity: Optional[int] = None,
air_jump_style: Optional[str] = "set",
jump_velocity_limit: Optional[int] = None):
""" Have the character jump. Multijump can be set with a separate in-air velocity and air jumps can be
set to be additive, limited, or a set value. Additive only adds to the player's change_y velocity. Limited
will add to the players' change_y until the jump_velocity limit. Set always sets the players velocity
to their air jump speed. """

# Sets air_jump_velocity to the same as ground jumps if no velocity is specified
if not air_jump_velocity:
air_jump_velocity = velocity

if self.can_jump():
# Air Jump logic
if self.jumps_since_ground > 0:
if air_jump_style == "additive":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to use a constant/enum for this?>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking into it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the current version of the code better fulfill your intent?

self.player_sprite.change_y += air_jump_velocity
elif air_jump_style == "limited":
if not jump_velocity_limit:
jump_velocity_limit = air_jump_velocity
if self.player_sprite.change_y < 0:
self.player_sprite.change_y = air_jump_velocity
elif self.player_sprite.change_y + air_jump_velocity < jump_velocity_limit:
self.player_sprite.change_y += air_jump_velocity
else:
self.player_sprite.change_y = jump_velocity_limit
elif air_jump_style == "set":
self.player_sprite.change_y = air_jump_velocity
else:
raise ValueError("Air jump style set is not valid. Use additive, limited, or set.")

# Ground Jump Logic
else:
self.player_sprite.change_y = velocity

self.increment_jump_counter()

def increment_jump_counter(self):
"""
Updates the jump counter for multi-jump tracking
"""
if self.allow_multi_jump:
self.jumps_since_ground += 1
self.jump_ticks = 0

def update(self):
"""
Expand All @@ -460,6 +512,8 @@ def update(self):
# print(f"Spot F ({self.player_sprite.center_x}, {self.player_sprite.center_y})")

# print(f"Spot B ({self.player_sprite.center_x}, {self.player_sprite.center_y})")
if self.jump_ticks < self.jump_delay:
self.jump_ticks += 1

for platform_list in self.platforms:
for platform in platform_list:
Expand Down