[Python] The reverse animation system isn't working

Discussão em 'Python' iniciado por Stack, Março 15, 2025.

  1. Stack

    Stack Membro Participativo

    So, I've been working on this animation player kinda thing lately to make it reusable in future projects. After i attempted to implement the reverse feature, it just didn't work properly, i start from the last frame of the spritesheet, keeps going, reaches the first frame and boom suddenly it works for the rest of the time the project is run. Here is my code (if you have any questions about how it functions feel free to ask):

    class Spritesheet:
    def __init__(self, filename, pos, scale, frame_h, frame_v, current_frame: Vector2):
    self.filename = filename
    self.pos = pos
    self.scale = scale
    self.frame = current_frame
    self.frame_h = frame_h
    self.frame_v = frame_v
    self.image = load_image(self.filename)
    self.texture = load_texture_from_image(self.image)
    self.rect = Rectangle(self.frame.x * self.image.width / self.frame_h, self.frame.y * self.image.height / self.frame_v,
    self.texture.width / self.frame_h, self.texture.height / self.frame_v)

    def draw(self):
    draw_texture_pro(
    self.texture, self.rect,
    Rectangle(self.pos.x, self.pos.y, self.rect.width * self.scale, self.rect.height * self.scale),
    Vector2(0, 0), 0, WHITE
    )


    class Animation:
    def __init__(self, spritesheet, start_frame, end_frame, loop,
    vertical_anim: bool=False, speed: float = 10,
    reverse: bool = False):

    # Variables
    self.spritesheet = spritesheet
    self.start_frame = start_frame
    self.end_frame = end_frame
    self.loop = loop
    self.speed = speed
    self.reverse = reverse
    self.vertical_anim = vertical_anim


    self.frame_attr = 'y' if self.vertical_anim else 'x'
    self.initial_frame = self.end_frame if self.reverse else self.start_frame
    setattr(self.spritesheet.frame, self.frame_attr, self.initial_frame)

    self.current_frame = getattr(self.spritesheet.frame, self.frame_attr)

    self.frame_counter = 0

    def update(self):
    self.animate()

    self.current_frame = getattr(self.spritesheet.frame, self.frame_attr)
    print(self.initial_frame)

    self.spritesheet.rect.x = self.spritesheet.frame.x * (self.spritesheet.image.width / self.spritesheet.frame_h)
    self.spritesheet.rect.y = self.spritesheet.frame.y * (self.spritesheet.image.height / self.spritesheet.frame_v)

    def animate(self):
    if self.frame_counter >= (framerate / self.speed):
    step = -1 if self.reverse else 1
    new_frame = self.current_frame + step
    setattr(self.spritesheet.frame, self.frame_attr, new_frame)

    if self.is_finished():
    if self.loop:
    # Reset to the correct loop start
    new_frame = self.end_frame if self.reverse else self.start_frame
    setattr(self.spritesheet.frame, self.frame_attr, new_frame)
    else:
    # Ensure it stops at the correct frame
    new_frame = self.start_frame if self.reverse else self.end_frame
    setattr(self.spritesheet.frame, self.frame_attr, new_frame)

    self.current_frame = new_frame
    self.frame_counter = 0 # Reset counter

    self.frame_counter += 1





    def set_speed(self, new_speed):
    self.speed = new_speed

    def reset(self):
    setattr(self.spritesheet.frame, self.frame_attr, self.start_frame)
    self.frame_counter = 0

    def is_finished(self):
    if self.reverse:
    return self.current_frame <= self.start_frame # Stop at start when reversing
    return self.current_frame >= self.end_frame

    def draw(self):
    self.spritesheet.draw()

    def run(self):
    self.update()
    self.draw()

    class AnimationPlayer:
    def __init__(self, animation_dict, default_animation):
    self.animation_dict = animation_dict
    self.current_animation = self.animation_dict[default_animation]

    def play(self, animation_name):
    if animation_name in self.animation_dict:
    self.current_animation = self.animation_dict[animation_name]
    self.current_animation.reset() # Reset animation when switching

    def run(self):
    self.current_animation.update() # Update animation frames
    self.current_animation.draw() # Draw the updated frame


    Here is the settings.py:

    from pyray import *
    from raylib import *
    import math, os, sys, json

    screen_width = 1280
    screen_height = 720
    framerate = 60

    # Useful methods
    def clamp(value, min_value, max_value):
    return max(min_value, min(value, max_value))

    def lerp(start, end, t):
    return start + (end - start) * clamp(t, 0, 1)

    def is_empty(obj):
    return isinstance(obj, (list, tuple, dict, set)) and len(obj) == 0

    # Timer
    class Timer:
    def __init__(self, duration: int, repeat = False, autostart = False, func = None):
    self.duration = duration
    self.start_time = 0
    self.active = False
    self.repeat = repeat
    self.func = func

    if autostart:
    self.activate()

    def activate(self):
    self.active = True
    self.start_time = get_time()

    def deactivate(self):
    self.active = False
    self.start_time = 0
    if self.repeat:
    self.activate()

    def update(self):
    if self.active:
    if get_time() - self.start_time >= self.duration:
    if self.func and self.start_time: self.func()
    self.deactivate()


    I've tried to set the start_frame to the end_frame and vice versa with this piece of code: self.start_frame, self.end_frame = self.end_frame, self.start_frame

    But it just didn't work

    Continue reading...

Compartilhe esta Página