All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.brunothg.game.engine.d2.object.sprite.SpriteSceneObject Maven / Gradle / Ivy

The newest version!
package com.github.brunothg.game.engine.d2.object.sprite;

import com.github.brunothg.game.engine.d2.commons.Point;
import com.github.brunothg.game.engine.d2.commons.Size;
import com.github.brunothg.game.engine.d2.object.SceneObject;
import com.github.brunothg.game.engine.image.sprite.Sprite;

import java.awt.Graphics2D;

/**
 * Animates a sprite. Every row is treated as a single animation and can be switched.
 * 
 * @author Marvin Bruns
 *
 */
public class SpriteSceneObject extends SceneObject
{

	private Sprite sprite;
	private int[] frames;

	private long defaultTime;
	private long[][] time;

	private long timeBase;
	private int frame;

	private int animation;

	/**
	 * Create an {@link SpriteSceneObject} from a sprite. Only one row will be used for animation.
	 * The row used for this animation can be changed.
	 * 
	 * @param sprite The animated sprite
	 * @param defaultTime Nanosecond for animation used if no individual time is provided
	 * @param time Time for every frame. Long[row][frame]. Zero means stable image, it won't be
	 *        animated.
	 * @param frames An array containing the number of frames used for every row. If negative or too
	 *        high the sprite's maximum frame number is used.
	 */
	public SpriteSceneObject(Sprite sprite, long defaultTime, long[][] time, int[] frames)
	{

		if (defaultTime < 0)
		{
			throw new IllegalArgumentException("Negative default time is not allowed");
		}

		this.sprite = sprite;
		this.defaultTime = defaultTime;
		this.time = time;
		this.frames = frames;
		this.timeBase = 0;
		this.frame = 0;

		setAnimationRow(0);
		setSize(sprite.getTileWidth(), sprite.getTileHeight());
	}

	/**
	 * Create an {@link SpriteSceneObject} from a sprite with full frames per row.
	 * 
	 * @see #SpriteSceneObject(Sprite, long, long[][], int[])
	 * @param sprite The animated sprite
	 * @param defaultTime Time for each frame where not specified
	 * @param time individual time for every frame
	 */
	public SpriteSceneObject(Sprite sprite, long defaultTime, long[][] time)
	{

		this(sprite, defaultTime, time, null);
	}

	/**
	 * Create an {@link SpriteSceneObject} from a sprite with equal time for every frame.
	 * 
	 * @see #SpriteSceneObject(Sprite, long, long[][])
	 * @param sprite The animated sprite
	 * @param defaultTime Time for each frame
	 */
	public SpriteSceneObject(Sprite sprite, long defaultTime)
	{

		this(sprite, defaultTime, null, null);
	}

	/**
	 * Change animation row.
	 * 
	 * @param row The row of the sprite used for animation
	 * @param reset if true animation will be
	 * @see #resetAnimation()
	 */
	public void setAnimationRow(int row, boolean reset)
	{

		if (row < 0 || row >= getAnimationRowCount())
		{
			throw new ArrayIndexOutOfBoundsException(
				"animation out of bounds. Animations -> " + getAnimationRowCount());
		}

		animation = row;

		if (reset)
		{

			resetAnimation();
		}
	}

	/**
	 * Change animation row and reset the animation.
	 * 
	 * @param row The row of the sprite used for animation
	 * @see #setAnimationRow(int, boolean)
	 */
	public void setAnimationRow(int row)
	{

		setAnimationRow(row, true);
	}

	/**
	 * Get the current row used for animation
	 * 
	 * @return The row used for animation
	 */
	public int getAnimationRow()
	{

		return animation;
	}

	/**
	 * Get the number of rows in this animation
	 * 
	 * @return Number of animation rows
	 */
	public int getAnimationRowCount()
	{

		return getSprite().getRows();
	}

	/**
	 * Get the frame of the current row in animation
	 * 
	 * @return Current animated frame in row
	 */
	public int getAnimationFrame()
	{

		return frame;
	}

	/**
	 * Set the frame of the current row in animation. If it is greater than the available frames the
	 * next frame in animation is chosen. Remember, that this will it will take affect when the
	 * animation is painted the next time. So if the next frame is this which should be painted you
	 * might set to the frame before.
	 * 
	 * @param frame The current animated frame in row
	 */
	public void setAnimationFrame(int frame)
	{

		if (frame < 0)
		{
			throw new IllegalArgumentException("Negative frame numbers not allowed");
		}

		this.frame = frame;
	}

	/**
	 * Resets actual animation. The first frame in actual row will be painted next time.
	 */
	public void resetAnimation()
	{

		setAnimationFrame(0);
		timeBase = 0;
	}

	/**
	 * Get the height of one frame of the underlying sprite.
	 * 
	 * @return Height of one original frame
	 */
	public int getTileHeight()
	{

		return sprite.getTileHeight();
	}

	/**
	 * Get the width of one frame of the underlying sprite.
	 * 
	 * @return Width of one original frame
	 */
	public int getTileWidth()
	{

		return sprite.getTileWidth();
	}

	/**
	 * Get the size of one frame of the underlying sprite.
	 * 
	 * @return Dimension of one original frame
	 */
	public Size getTileSize()
	{

		return new Size(sprite.getTileWidth(), sprite.getTileHeight());
	}

	@Override
	protected void paint(Graphics2D g, long elapsedTime)
	{

		if (getTime(getAnimationRow(), frame) > 0)
		{
			recalculateFrame(elapsedTime);
		}

		getSprite().drawTile(g, frame, getAnimationRow(), getWidth(), getHeight());
	}

	/**
	 * 
	 * Recalculates the current visible frame depending on the elapsed time. Row restarts if it
	 * reaches end an the last frame has a time > 0.
	 */
	protected void recalculateFrame(long elapsedTime)
	{
		timeBase += elapsedTime;

		long tempTime;
		while (timeBase >= (tempTime = getTime(getAnimationRow(), getAnimationFrame())) && tempTime != 0)
		{

			timeBase -= tempTime;
			setAnimationFrame(getAnimationFrame() + 1);
			if (getAnimationFrame() >= getFrameCount(getAnimationRow()))
			{
				setAnimationFrame(0);
			}
		}
	}

	/**
	 * Animation time for a frame
	 */
	protected long getTime(int row, int frame)
	{

		if (time != null && row < time.length && frame < time[row].length)
		{

			long individuelTime = time[row][frame];

			if (individuelTime >= 0)
			{

				return individuelTime;
			}
		}

		return defaultTime;
	}

	/**
	 * Number of used frames of a row
	 */
	protected int getFrameCount(int row)
	{

		if (frames != null && row < frames.length)
		{

			int frameCount = frames[row];

			if (frameCount >= 0 && frameCount < sprite.getColumns())
			{

				return frameCount;
			}
		}

		return sprite.getColumns();
	}

	protected Sprite getSprite()
	{

		return sprite;
	}

	@Override
	public Point getOrigin()
	{

		return ORIGIN_TOP_LEFT;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy