Refactor animations
This commit is contained in:
@@ -2,20 +2,141 @@ package com.bartlomiejpluta.base.api.animation;
|
||||
|
||||
import com.bartlomiejpluta.base.internal.program.Updatable;
|
||||
|
||||
/**
|
||||
* Represents an object that can be animated by cycling through multiple frames of a texture.
|
||||
*
|
||||
* <p>This interface provides a complete animation system for 2D sprites and other visual objects
|
||||
* in the game engine. Animated objects automatically cycle through their available frames at a
|
||||
* specified speed when animation is enabled.
|
||||
*
|
||||
* <p>The animation system works by:
|
||||
* <ul>
|
||||
* <li>Maintaining an internal timer that tracks elapsed time</li>
|
||||
* <li>Automatically advancing to the next frame when enough time has passed</li>
|
||||
* <li>Cycling through available frames in sequence</li>
|
||||
* <li>Supporting both full texture animation and subset-based animation</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Animation can be controlled in real-time through enable/disable methods and speed adjustments.
|
||||
* The animation automatically resets and pauses when disabled.
|
||||
*
|
||||
* <p>This interface extends {@link Updatable}, meaning animated objects are automatically
|
||||
* updated each frame by the game engine's update loop.
|
||||
*/
|
||||
public interface Animated extends Updatable {
|
||||
|
||||
/**
|
||||
* Returns whether animation is currently enabled for this object.
|
||||
*
|
||||
* <p>When animation is disabled, the object remains on its current frame
|
||||
* and the internal animation timer is reset to zero.
|
||||
*
|
||||
* @return {@code true} if animation is enabled, {@code false} otherwise
|
||||
*/
|
||||
boolean isAnimationEnabled();
|
||||
|
||||
/**
|
||||
* Enables or disables animation for this object.
|
||||
*
|
||||
* <p>When animation is disabled:
|
||||
* <ul>
|
||||
* <li>The object stops cycling through frames</li>
|
||||
* <li>The current frame remains displayed</li>
|
||||
* <li>The internal animation timer is reset to zero</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>When animation is enabled, the object resumes cycling through frames
|
||||
* at the configured animation speed.
|
||||
*
|
||||
* @param enabled {@code true} to enable animation, {@code false} to disable
|
||||
*/
|
||||
void setAnimationEnabled(boolean enabled);
|
||||
|
||||
void enableAnimation();
|
||||
/**
|
||||
* Enables animation for this object.
|
||||
*
|
||||
* <p>This is a convenience method equivalent to calling
|
||||
* {@code setAnimationEnabled(true)}.
|
||||
*
|
||||
* @see #setAnimationEnabled(boolean)
|
||||
*/
|
||||
default void enableAnimation() {
|
||||
setAnimationEnabled(true);
|
||||
}
|
||||
|
||||
void disableAnimation();
|
||||
/**
|
||||
* Disables animation for this object.
|
||||
*
|
||||
* <p>This is a convenience method equivalent to calling
|
||||
* {@code setAnimationEnabled(false)}. The object will remain on its
|
||||
* current frame and the animation timer will be reset.
|
||||
*
|
||||
* @see #setAnimationEnabled(boolean)
|
||||
*/
|
||||
default void disableAnimation() {
|
||||
setAnimationEnabled(false);
|
||||
}
|
||||
|
||||
void toggleAnimationEnabled();
|
||||
/**
|
||||
* Toggles the animation enabled state.
|
||||
*
|
||||
* <p>If animation is currently enabled, it will be disabled.
|
||||
* If animation is currently disabled, it will be enabled.
|
||||
*
|
||||
* @see #isAnimationEnabled()
|
||||
* @see #setAnimationEnabled(boolean)
|
||||
*/
|
||||
default void toggleAnimationEnabled() {
|
||||
setAnimationEnabled(!isAnimationEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current animation speed.
|
||||
*
|
||||
* <p>Animation speed determines how quickly the object cycles through its frames.
|
||||
* Higher values result in faster animation, while lower values create slower animation.
|
||||
*
|
||||
* <p>The speed is typically measured in relation to the game engine's target
|
||||
* update rate, where a speed of 1.0 represents normal timing.
|
||||
* If 60PFS (target update rate) is maintained, it should be measured in frames per second.
|
||||
*
|
||||
* @return the current animation speed as a positive float value
|
||||
*/
|
||||
float getAnimationSpeed();
|
||||
|
||||
/**
|
||||
* Sets the animation speed for this object.
|
||||
*
|
||||
* <p>Animation speed controls how quickly frames are cycled during animation.
|
||||
* The speed value is typically:
|
||||
* <ul>
|
||||
* <li>1.0 for normal speed animation</li>
|
||||
* <li>Greater than 1.0 for faster animation</li>
|
||||
* <li>Between 0.0 and 1.0 for slower animation</li>
|
||||
* <li>Values are automatically clamped to prevent invalid speeds</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>The actual frame timing is calculated based on the game engine's target
|
||||
* update rate and the specified speed multiplier.
|
||||
* If 60PFS (target update rate) is maintained, it should be measured in frames per second.
|
||||
*
|
||||
* @param speed the new animation speed as a positive float value
|
||||
* @throws IllegalArgumentException if speed is negative or zero
|
||||
*/
|
||||
void setAnimationSpeed(float speed);
|
||||
|
||||
/**
|
||||
* Manually sets the current animation frame.
|
||||
*
|
||||
* <p>This method allows direct control over which frame is currently displayed,
|
||||
* bypassing the automatic animation timing. The frame index is automatically
|
||||
* wrapped if it exceeds the available frame count.
|
||||
*
|
||||
*
|
||||
* <p>Frame indices are zero-based, and values that exceed the available frame
|
||||
* count are automatically wrapped using modulo operation.
|
||||
*
|
||||
* @param frame the zero-based index of the frame to display
|
||||
*/
|
||||
void setAnimationFrame(int frame);
|
||||
}
|
||||
|
||||
@@ -8,15 +8,103 @@ import com.bartlomiejpluta.base.api.move.Movement;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Represents a game world object that can face four cardinal directions and uses
|
||||
* a special texture format called a character set (charset).
|
||||
*
|
||||
* <p>A character set is a sprite sheet organized in a 4-row, multi-column format where:
|
||||
* <ul>
|
||||
* <li>Row 1: Graphics for facing DOWN</li>
|
||||
* <li>Row 2: Graphics for facing LEFT</li>
|
||||
* <li>Row 3: Graphics for facing RIGHT</li>
|
||||
* <li>Row 4: Graphics for facing UP</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Each column represents a different animation frame or object variant. For animated
|
||||
* characters, columns contain sequential animation frames. For static objects (like boxes),
|
||||
* each column may represent different object types or states (e.g., normal box, colored box,
|
||||
* damaged box).
|
||||
*
|
||||
* <p>This interface combines movement capabilities ({@link Movable}), animation features
|
||||
* ({@link Animated}), and entity properties ({@link Entity}) to create a complete
|
||||
* character system for 2D games.
|
||||
*/
|
||||
public interface Character extends Movable, Animated, Entity {
|
||||
|
||||
/**
|
||||
* Initiates movement in the specified direction.
|
||||
*
|
||||
* <p>This method handles the character's movement mechanics and automatically
|
||||
* updates the facing direction to match the movement direction.
|
||||
*
|
||||
* @param direction the direction to move towards
|
||||
* @return a {@link Movement} object representing the movement operation
|
||||
* @throws IllegalArgumentException if direction is null
|
||||
*/
|
||||
Movement move(Direction direction);
|
||||
|
||||
/**
|
||||
* Returns the current facing direction of the character.
|
||||
*
|
||||
* <p>The facing direction determines which row of the character set
|
||||
* is used for rendering and animation.
|
||||
*
|
||||
* @return the current facing direction
|
||||
*/
|
||||
Direction getFaceDirection();
|
||||
|
||||
/**
|
||||
* Sets the default sprite column to use from the character set.
|
||||
*
|
||||
* <p>This method is particularly useful for character sets that contain
|
||||
* multiple object variants in different columns. For example, if a character
|
||||
* set contains different box types in each column, this method selects
|
||||
* which box type to display.
|
||||
*
|
||||
* <p>The column index is zero-based and must be within the bounds of the
|
||||
* current character set.
|
||||
*
|
||||
* @param column the zero-based column index to use as default
|
||||
* @throws IndexOutOfBoundsException if the column index is invalid
|
||||
*/
|
||||
void setDefaultSpriteColumn(int column);
|
||||
|
||||
/**
|
||||
* Changes the character's facing direction without initiating movement.
|
||||
*
|
||||
* <p>This method updates which row of the character set is used for rendering.
|
||||
* It can be used to create custom animations by cycling through different
|
||||
* facing directions, or to orient the character without moving.
|
||||
*
|
||||
* @param direction the new facing direction
|
||||
* @throws IllegalArgumentException if direction is null
|
||||
*/
|
||||
void setFaceDirection(Direction direction);
|
||||
|
||||
/**
|
||||
* Changes the character set (sprite sheet) used by this character.
|
||||
*
|
||||
* <p>This allows dynamic switching between different visual representations
|
||||
* of the character, such as different costumes, character states, or
|
||||
* completely different character types.
|
||||
*
|
||||
* @param characterSetUid the unique identifier of the new character set
|
||||
* @throws IllegalArgumentException if characterSetUid is null or empty
|
||||
*/
|
||||
void changeCharacterSet(String characterSetUid);
|
||||
|
||||
/**
|
||||
* Performs an instant animation using all frames from the current facing direction.
|
||||
*
|
||||
* <p>This method executes an animation sequence by cycling through all columns
|
||||
* of the row corresponding to the character's current facing direction. For example,
|
||||
* if the character is facing UP, the animation will use all frames from the fourth
|
||||
* row of the character set.
|
||||
*
|
||||
* <p>The animation runs asynchronously and the returned {@link CompletableFuture}
|
||||
* completes when the animation finishes.
|
||||
*
|
||||
* @return a {@link CompletableFuture} that completes when the animation finishes
|
||||
*/
|
||||
CompletableFuture<Void> performInstantAnimation();
|
||||
}
|
||||
|
||||
@@ -293,6 +293,11 @@ public abstract class CharacterDelegate implements Character {
|
||||
character.setZIndex(zIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultSpriteColumn(int column) {
|
||||
character.setDefaultSpriteColumn(column);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends Event> void handleEvent(E event) {
|
||||
character.handleEvent(event);
|
||||
|
||||
@@ -42,7 +42,8 @@ public abstract class MapObject extends CharacterDelegate {
|
||||
this.frame = frame;
|
||||
setBlocking(true);
|
||||
disableAnimation();
|
||||
setAnimationFrame(frame);
|
||||
setDefaultSpriteColumn(frame);
|
||||
setFaceDirection(DOWN);
|
||||
pathExecutor.setRepeat(1);
|
||||
|
||||
initPath();
|
||||
|
||||
Reference in New Issue
Block a user