package com.indyforge.twod.engine.graphics.sprite; import java.awt.Point; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; import java.util.Collections; import java.util.List; import java.util.RandomAccess; /** * This class represents a single Animation * * @author Matthias Hesse * @see AnimationBundle * @see Sprite */ public final class Animation implements Serializable { /** * */ private static final long serialVersionUID = 1L; // The sprite which created this animation private final Sprite sprite; // This list saves all image coords used by this animation private final List<Point> imageCoords; // The name of this animation private final String name; // Should this animation loop ? private boolean loop = false; // Is this animation paused ? private boolean paused = true; // The duration of the animation private final long duration, timePerImage; // The step counter private int step; // FastBomb vars private transient long timeStamp; /* * When deserializing reset the animation. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // Read the default stuff in.defaultReadObject(); // Set the TimeStep to the actual time timeStamp = System.currentTimeMillis(); } Animation(Sprite sprite, String name, List<Point> imageCoords, long timePerImage) { if (sprite == null) { throw new NullPointerException("sprite"); } else if (name == null) { throw new NullPointerException("name"); } else if (imageCoords == null) { throw new NullPointerException("images"); } else if (imageCoords.size() == 0) { throw new IllegalArgumentException( "there should be at least one image coord"); } else if (!(imageCoords instanceof RandomAccess)) { throw new IllegalArgumentException("For performance reasons we " + "only accepts random-access list here!"); } // Save the sprite this.sprite = sprite; // Save the name this.name = name; // Calculate the duration for the whole animation duration = imageCoords.size() * timePerImage; // Save the time per image this.timePerImage = timePerImage; // Save the image coords this.imageCoords = Collections.unmodifiableList(imageCoords); // Start... reset(); } public Animation duplicate() { // Create clone return new Animation(sprite, name, imageCoords, timePerImage); } public Sprite sprite() { return sprite; } public boolean isPaused() { return paused; } public Animation paused(boolean paused) { this.paused = paused; return this; } public boolean isLoop() { return loop; } public Animation loop(boolean loop) { this.loop = loop; return this; } public String name() { return name; } public long duration() { return duration; } public int step() { return step; } public int nextStep() { if (paused) { return step; } return step >= imageCoords.size() - 1 ? (loop ? 0 : -1) : step + 1; } public List<Point> imageCoords() { return imageCoords; } public long timePerImage() { return timePerImage; } public boolean isFirst() { return step == 0; } public Animation useLastStep() { step = imageCoords.size() - 1; return this; } public boolean isLast() { return step == imageCoords.size() - 1; } public boolean isValid() { return step != -1; } public BufferedImage image() { if (!isValid()) { throw new IllegalStateException("Animation is not valid anymore"); } Point coord = imageCoords.get(step); return sprite.getSubImages()[coord.x][coord.y]; } public Animation update() { if (!paused && isValid()) { // Read the actual time long time = System.currentTimeMillis(); /* * Calculate if the time difference from the last step is higher * then the time-per-image If yes the timeStamp will be incresed */ if (time - timeStamp >= timePerImage) { // Swap step = nextStep(); timeStamp = time; } } return this; } /** * This Method resets the current Animation. */ public Animation reset() { // Reset the step step = 0; // Set the TimeStep to the actual time timeStamp = System.currentTimeMillis(); return this; } }