def METHOD_NAME(self):
    if not self.grounded and self.jumps_left <= 1:
        return
    if self._start_fall_sequence:
        self._start_fall_sequence.kill()
    # don't jump if there's a ceiling right above us
    if boxcast(self.position+(0,.1,0), self.up, distance=self.scale_y, thickness=.95, ignore=(self,), traverse_target=self.traverse_target).hit:
        return
    if hasattr(self, 'y_animator'):
        self.y_animator.kill()
    self.jump_dust = Entity(model=Circle(), scale=.5, color=color.white33, position=self.position)
    self.jump_dust.animate_scale(3, duration=.3, curve=curve.linear)
    self.jump_dust.fade_out(duration=.2)
    destroy(self.jump_dust, 2.1)
    self.jumping = True
    self.jumps_left -= 1
    self.grounded = False
    target_y = self.y + self.jump_height
    duration = self.jump_duration
    # check if we hit a ceiling and adjust the jump height accordingly
    hit_above = boxcast(self.position+(0,self.scale_y/2,0), self.up, distance=self.jump_height-(self.scale_y/2), thickness=.9, ignore=(self,))
    if hit_above.hit:
        target_y = min(hit_above.world_point.y-self.scale_y, target_y)
        try:
            duration *= target_y / (self.y+self.jump_height)
        except ZeroDivisionError as e:
            return e
    self.animate_y(target_y, duration, resolution=30, curve=curve.out_expo)
    self._start_fall_sequence = invoke(self.start_fall, delay=duration)