Define frames for AnimatedSprite

  ... the case you feel the need for a new feature or want to submit one.

Define frames for AnimatedSprite

Postby ldebrasi » Fri Dec 17, 2010 11:48 pm

Hi, first I would like to congratulate Nicolas for this great engine! :)
But for my surprise when i started to play with the AnimatedSprite class i've found that i couldn't skip frames in a tiled (wich is a problem for my actual development)
For example: If I want to play frames 1,2,4,6 or in a descent orders like: 6,5,4

So here is a improvement of the AnimatedSprite class, I hope it will be useful.
How to use it:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. sprite.animate(new long[] { 200, 250, 100, 100 }, new int[] { 1, 2, 6, 5 },  0);
  2.  
Parsed in 0.011 seconds, using GeSHi 1.0.8.4


AnimatedSprite mod:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public class AnimatedSprite extends TiledSprite implements TimeConstants {
  2.         // ===========================================================
  3.         // Constants
  4.         // ===========================================================
  5.  
  6.         private static final int LOOP_CONTINUOUS = -1;
  7.  
  8.         // ===========================================================
  9.         // Fields
  10.         // ===========================================================
  11.  
  12.         private boolean mAnimationRunning;
  13.  
  14.         private long mAnimationProgress;
  15.         private long mAnimationDuration;
  16.         private long[] mFrameEndsInNanoseconds;
  17.  
  18.         private int mFirstTileIndex;
  19.         private int mInitialLoopCount;
  20.         private int mLoopCount;
  21.         private IAnimationListener mAnimationListener;
  22.  
  23.         private int mFrameCount;
  24.         private int[] mFrames;
  25.  
  26.         // ===========================================================
  27.         // Constructors
  28.         // ===========================================================
  29.  
  30.         public AnimatedSprite(final float pX, final float pY,
  31.                         final TiledTextureRegion pTiledTextureRegion) {
  32.                 super(pX, pY, pTiledTextureRegion);
  33.         }
  34.  
  35.         public AnimatedSprite(final float pX, final float pY,
  36.                         final float pTileWidth, final float pTileHeight,
  37.                         final TiledTextureRegion pTiledTextureRegion) {
  38.                 super(pX, pY, pTileWidth, pTileHeight, pTiledTextureRegion);
  39.         }
  40.  
  41.         public AnimatedSprite(final float pX, final float pY,
  42.                         final TiledTextureRegion pTiledTextureRegion,
  43.                         final RectangleVertexBuffer pRectangleVertexBuffer) {
  44.                 super(pX, pY, pTiledTextureRegion, pRectangleVertexBuffer);
  45.         }
  46.  
  47.         public AnimatedSprite(final float pX, final float pY,
  48.                         final float pTileWidth, final float pTileHeight,
  49.                         final TiledTextureRegion pTiledTextureRegion,
  50.                         final RectangleVertexBuffer pRectangleVertexBuffer) {
  51.                 super(pX, pY, pTileWidth, pTileHeight, pTiledTextureRegion,
  52.                                 pRectangleVertexBuffer);
  53.         }
  54.  
  55.         // ===========================================================
  56.         // Getter & Setter
  57.         // ===========================================================
  58.  
  59.         public boolean isAnimationRunning() {
  60.                 return this.mAnimationRunning;
  61.         }
  62.  
  63.         // ===========================================================
  64.         // Methods for/from SuperClass/Interfaces
  65.         // ===========================================================
  66.  
  67.         @Override
  68.         protected void onManagedUpdate(final float pSecondsElapsed) {
  69.                 super.onManagedUpdate(pSecondsElapsed);
  70.                 if (this.mAnimationRunning) {
  71.                         final long nanoSecondsElapsed = (long) (pSecondsElapsed * NANOSECONDSPERSECOND);
  72.                         this.mAnimationProgress += nanoSecondsElapsed;
  73.  
  74.                         if (this.mAnimationProgress > this.mAnimationDuration) {
  75.                                 this.mAnimationProgress %= this.mAnimationDuration;
  76.                                 if (this.mInitialLoopCount != LOOP_CONTINUOUS) {
  77.                                         this.mLoopCount--;
  78.                                 }
  79.                         }
  80.  
  81.                         if (this.mInitialLoopCount == LOOP_CONTINUOUS
  82.                                         || this.mLoopCount >= 0) {
  83.  
  84.                                 final int currentFrameIndex = this.calculateCurrentFrameIndex();
  85.                                 if (mFrames == null) {
  86.                                         this.setCurrentTileIndex(this.mFirstTileIndex
  87.                                                         + currentFrameIndex);
  88.                                 } else {
  89.                                         this.setCurrentTileIndex(mFrames[currentFrameIndex]);
  90.                                 }
  91.  
  92.                         } else {
  93.                                 this.mAnimationRunning = false;
  94.                                 if (this.mAnimationListener != null) {
  95.                                         this.mAnimationListener.onAnimationEnd(this);
  96.                                 }
  97.                         }
  98.                 }
  99.         }
  100.  
  101.         // ===========================================================
  102.         // Methods
  103.         // ===========================================================
  104.  
  105.         public void stopAnimation() {
  106.                 this.mAnimationRunning = false;
  107.         }
  108.  
  109.         public void stopAnimation(final int pTileIndex) {
  110.                 this.mAnimationRunning = false;
  111.                 this.setCurrentTileIndex(pTileIndex);
  112.         }
  113.  
  114.         private int calculateCurrentFrameIndex() {
  115.                 final long animationProgress = this.mAnimationProgress;
  116.                 final long[] frameEnds = this.mFrameEndsInNanoseconds;
  117.                 final int frameCount = this.mFrameCount;
  118.                 for (int i = 0; i < frameCount; i++) {
  119.                         if (frameEnds[i] > animationProgress) {
  120.                                 return i;
  121.                         }
  122.                 }
  123.  
  124.                 return frameCount - 1;
  125.         }
  126.  
  127.         public AnimatedSprite animate(final long pFrameDurationEach) {
  128.                 return this.animate(pFrameDurationEach, true);
  129.         }
  130.  
  131.         public AnimatedSprite animate(final long pFrameDurationEach,
  132.                         final boolean pLoop) {
  133.                 return this.animate(pFrameDurationEach, (pLoop) ? LOOP_CONTINUOUS : 0,
  134.                                 null);
  135.         }
  136.  
  137.         public AnimatedSprite animate(final long pFrameDurationEach,
  138.                         final int pLoopCount) {
  139.                 return this.animate(pFrameDurationEach, pLoopCount, null);
  140.         }
  141.  
  142.         public AnimatedSprite animate(final long pFrameDurationEach,
  143.                         final boolean pLoop, final IAnimationListener pAnimationListener) {
  144.                 return this.animate(pFrameDurationEach, (pLoop) ? LOOP_CONTINUOUS : 0,
  145.                                 pAnimationListener);
  146.         }
  147.  
  148.         public AnimatedSprite animate(final long pFrameDurationEach,
  149.                         final int pLoopCount, final IAnimationListener pAnimationListener) {
  150.                 final long[] frameDurations = new long[this.getTextureRegion()
  151.                                 .getTileCount()];
  152.                 Arrays.fill(frameDurations, pFrameDurationEach);
  153.                 return this.animate(frameDurations, pLoopCount, pAnimationListener);
  154.         }
  155.  
  156.         public AnimatedSprite animate(final long[] pFrameDurations) {
  157.                 return this.animate(pFrameDurations, true);
  158.         }
  159.  
  160.         public AnimatedSprite animate(final long[] pFrameDurations,
  161.                         final boolean pLoop) {
  162.                 return this.animate(pFrameDurations, (pLoop) ? LOOP_CONTINUOUS : 0,
  163.                                 null);
  164.         }
  165.  
  166.         public AnimatedSprite animate(final long[] pFrameDurations,
  167.                         final int pLoopCount) {
  168.                 return this.animate(pFrameDurations, pLoopCount, null);
  169.         }
  170.  
  171.         public AnimatedSprite animate(final long[] pFrameDurations,
  172.                         final boolean pLoop, final IAnimationListener pAnimationListener) {
  173.                 return this.animate(pFrameDurations, (pLoop) ? LOOP_CONTINUOUS : 0,
  174.                                 pAnimationListener);
  175.         }
  176.  
  177.         public AnimatedSprite animate(final long[] pFrameDurations,
  178.                         final int pLoopCount, final IAnimationListener pAnimationListener) {
  179.                 return this.animate(pFrameDurations, 0, this.getTextureRegion()
  180.                                 .getTileCount() - 1, pLoopCount, pAnimationListener);
  181.         }
  182.  
  183.         public AnimatedSprite animate(final long[] pFrameDurations,
  184.                         final int pFirstTileIndex, final int pLastTileIndex,
  185.                         final boolean pLoop) {
  186.                 return this.animate(pFrameDurations, pFirstTileIndex, pLastTileIndex,
  187.                                 (pLoop) ? LOOP_CONTINUOUS : 0, null);
  188.         }
  189.  
  190.         public AnimatedSprite animate(final long[] pFrameDurations,
  191.                         final int pFirstTileIndex, final int pLastTileIndex,
  192.                         final int pLoopCount) {
  193.                 return this.animate(pFrameDurations, pFirstTileIndex, pLastTileIndex,
  194.                                 pLoopCount, null);
  195.         }
  196.  
  197.         public AnimatedSprite animate(final long[] pFrameDurations,
  198.                         final int[] pFrames, final int pLoopCount) {
  199.                 return this.animate(pFrameDurations, pFrames, pLoopCount, null);
  200.         }
  201.  
  202.         /**
  203.          * New method to animate specifics frames
  204.          *
  205.          * @param pFrameDurations
  206.          *            must have the same length as pFrames.
  207.          * @param pFrames
  208.          *            index of the frames to animate.
  209.          * @param pLoopCount
  210.          * @param pAnimationListener
  211.          */
  212.         public AnimatedSprite animate(final long[] pFrameDurations,
  213.                         final int[] pFrames, final int pLoopCount,
  214.                         final IAnimationListener pAnimationListener) {
  215.  
  216.                 final int frameCount = pFrames.length;
  217.                 if (pFrameDurations.length != frameCount) {
  218.                         throw new IllegalArgumentException(
  219.                                         "pFrameDurations must have the same length as pFrames.");
  220.                 }
  221.  
  222.                 return init(pFrameDurations, frameCount, pFrames, 0, pLoopCount,
  223.                                 pAnimationListener);
  224.         }
  225.  
  226.         /**
  227.          * @param pFrameDurations
  228.          *            must have the same length as pFirstTileIndex to
  229.          *            pLastTileIndex.
  230.          * @param pFirstTileIndex
  231.          * @param pLastTileIndex
  232.          * @param pLoopCount
  233.          * @param pAnimationListener
  234.          */
  235.         public AnimatedSprite animate(final long[] pFrameDurations,
  236.                         final int pFirstTileIndex, final int pLastTileIndex,
  237.                         final int pLoopCount, final IAnimationListener pAnimationListener) {
  238.                 if (pLastTileIndex - pFirstTileIndex < 1) {
  239.                         throw new IllegalArgumentException(
  240.                                         "An animation needs at least two tiles to animate between.");
  241.                 }
  242.  
  243.                 final int frameCount = (pLastTileIndex - pFirstTileIndex) + 1;
  244.                 if (pFrameDurations.length != frameCount) {
  245.                         throw new IllegalArgumentException(
  246.                                         "pFrameDurations must have the same length as pFirstTileIndex to pLastTileIndex.");
  247.                 }
  248.  
  249.                 return init(pFrameDurations, frameCount, null, pFirstTileIndex,
  250.                                 pLoopCount, pAnimationListener);
  251.         }
  252.  
  253.         private AnimatedSprite init(final long[] pFrameDurations,
  254.                         final int frameCount, final int[] pFrames,
  255.                         final int pFirstTileIndex, final int pLoopCount,
  256.                         final IAnimationListener pAnimationListener) {
  257.  
  258.                 this.mFrameCount = frameCount;
  259.                 this.mAnimationListener = pAnimationListener;
  260.                 this.mInitialLoopCount = pLoopCount;
  261.                 this.mLoopCount = pLoopCount;
  262.                 this.mFrames = pFrames;
  263.                 this.mFirstTileIndex = pFirstTileIndex;
  264.  
  265.                 if (this.mFrameEndsInNanoseconds == null
  266.                                 || this.mFrameCount > this.mFrameEndsInNanoseconds.length) {
  267.                         this.mFrameEndsInNanoseconds = new long[this.mFrameCount];
  268.                 }
  269.  
  270.                 final long[] frameEndsInNanoseconds = this.mFrameEndsInNanoseconds;
  271.                 MathUtils.arraySumInto(pFrameDurations, frameEndsInNanoseconds,
  272.                                 NANOSECONDSPERMILLISECOND);
  273.  
  274.                 final long lastFrameEnd = frameEndsInNanoseconds[this.mFrameCount - 1];
  275.                 this.mAnimationDuration = lastFrameEnd;
  276.  
  277.                 this.mAnimationProgress = 0;
  278.                 this.mAnimationRunning = true;
  279.  
  280.                 return this;
  281.         }
  282.  
  283.         // ===========================================================
  284.         // Inner and Anonymous Classes
  285.         // ===========================================================
  286.  
  287.         public static interface IAnimationListener {
  288.                 // ===========================================================
  289.                 // Constants
  290.                 // ===========================================================
  291.  
  292.                 // ===========================================================
  293.                 // Fields
  294.                 // ===========================================================
  295.  
  296.                 public void onAnimationEnd(final AnimatedSprite pAnimatedSprite);
  297.         }
  298. }
  299.  
Parsed in 0.023 seconds, using GeSHi 1.0.8.4


Best Regards,
Leandro De Brasi
ldebrasi
 
Posts: 3
Joined: Thu Dec 16, 2010 11:54 pm
Location: Argentina

Re: Define frames for AnimatedSprite

Postby turnA » Sat Dec 18, 2010 4:47 pm

Thanks for sharing it. I also a bit surprised that such flexible implementation doesn't exist on the AnimatedSprite :)
Maybe it just need additional method to override boolean pLoop & IAnimationListener, and then it all set.

Hope this can find it's way to the latest build soon.
turnA
 
Posts: 16
Joined: Fri Oct 15, 2010 4:30 pm

Re: Define frames for AnimatedSprite

Postby Nicolas Gramlich » Thu Dec 23, 2010 3:18 am

Hi ldebrasi,

looks good :)
I'll add that. Maybe just like you did it (likely), maybe as a subclass (unlikely).

Do you guys also think there are WAY to many overloaded animate(...)s :?:

Best Regards,
Nicolas
Nicolas Gramlich
Site Admin
 
Posts: 1734
Joined: Mon Jun 07, 2010 6:20 pm
Location: Schriesheim, Germany

Re: Define frames for AnimatedSprite

Postby Nicolas Gramlich » Thu Dec 23, 2010 2:00 pm

Hi,

I chose to put your code 1:1 (+ formatting/cleanup).

Changeset: http://code.google.com/p/andengine/sour ... 81af2d6caa

Best Regards,
Nicolas
Nicolas Gramlich
Site Admin
 
Posts: 1734
Joined: Mon Jun 07, 2010 6:20 pm
Location: Schriesheim, Germany

Re: Define frames for AnimatedSprite

Postby ldebrasi » Mon Dec 27, 2010 1:48 am

Great Nicolas :P Thanks!
ldebrasi
 
Posts: 3
Joined: Thu Dec 16, 2010 11:54 pm
Location: Argentina

Re: Define frames for AnimatedSprite

Postby Zeldein » Fri Jan 28, 2011 11:30 am

sorry i know this thread is a month old, but I happened to find out that in the android 1.6 emulator, the method does not function properly. It just does not animate at all; thus, the onAnimationEnd handler is never called.

Anyone else tried this newly added animate() in 1.6 API yet??

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. //---- sample code
  2. m_sprCountDown1.animate(new long[] { 1000, 1000, 1000}, new int[] { 3, 2, 1 },  0, new IAnimationListener() {
  3.         @Override
  4.         public void onAnimationEnd(AnimatedSprite pAnimatedSprite) {
  5.                 pAnimatedSprite.setVisible(false);
  6.                 initGo(p_ICallbackFunction);
  7.         }
  8. });
  9. //----
Parsed in 0.010 seconds, using GeSHi 1.0.8.4
Zeldein
 
Posts: 7
Joined: Thu Dec 09, 2010 5:25 am

Re: Define frames for AnimatedSprite

Postby jar » Wed Feb 02, 2011 9:51 am

I think it should be possible to 'animate' a sprite even for only 1 frame, for a certain time. That would make it more usable, you could use it uniformly with other cases like many frame animations, in the same manner.
Calling isAnimationRunning() would return true if the time had not passed yet.
jar
 
Posts: 52
Joined: Wed Jan 12, 2011 5:22 pm
Location: Poland

Re: Define frames for AnimatedSprite

Postby AlexNunn » Wed Feb 02, 2011 6:15 pm

jar wrote:I think it should be possible to 'animate' a sprite even for only 1 frame, for a certain time. That would make it more usable, you could use it uniformly with other cases like many frame animations, in the same manner.
Calling isAnimationRunning() would return true if the time had not passed yet.

You want to be able to pause the animation for a specific amount of time???
AlexNunn
 
Posts: 604
Joined: Thu Oct 07, 2010 6:43 pm
Location: Kentucky


Return to Features

Who is online

Users browsing this forum: No registered users and 5 guests