Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (498)
Games in Android Showcase (117)
games submitted by our members
Games in WIP (563)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Accurate Animation  (Read 2130 times)
0 Members and 1 Guest are viewing this topic.
Offline StumpyStrust
« Posted 2011-12-24 00:40:50 »

Hello peoples.

I was wondering if someone could tell me if this was a good idea of how to do animation and other time based tasks.

Its a work around I made so I would not have to use Threads to time things.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
/*
 * Manages different rates based on what the rate is for the main loop
 * of a game.
 */

public class RateManager
{
   // The current update step
  private int currentUpdate;
   // The rate that we will reset at.
  private int rate;
   // The main rate of the loop
  private int mainRate;
   
   /*
    * Takes the rate that you would like to update from and
    * divides it by the mainRate which will result in a fairly accurate
    * update rate.    
    * @param newRate         the rate of this manager
    * @param newMainRate      the mainRate for this manager
    */

   public RateManager( int newRate, int newMainRate )
   {
      this.rate = newRate / newMainRate;
      this.mainRate = newMainRate;
      this.currentUpdate = 0;
   }
   
   /*
    * This will return a boolean showing whether this Manager has reached the end of its
    * rate. It will then reset and wait for another update.
    * @return True if it hit the end and false if not.
    */

   public boolean update()
   {
      if( this.currentUpdate == this.rate )
      {
         this.currentUpdate = 0;
         return true;
      }
      else
      {
         this.currentUpdate++;
         return false;
      }
   }
   
   /*
    * Sets a new rate based on the  mainRate already in the manager.
    * @param newRate the new rate for this manager
    */

   public void setRate( int newRate )
   {
      this.rate = newRate / this.mainRate;
   }
   
   /*
    * Sets a new rate and a new mainRate for this manager
    * @param newRate         new rate
    * @param newMainRate      new mainRate
    */

   public void setRate( int newRate, int newMainRate )
   {
      this.rate = newRate / newMainRate;
      this.mainRate = newMainRate;
   }

}


Basically, if you were updating a loop with Thread.sleep(someTime)

you could animate/time/whatever by having an object that you create that would get the amount of updates
it would take for it to "update" based on what speed you're main loop is running at.

Lets say we are sleeping our loop every 33mils so about 30fps and we want something to shoot off every 280mils.
Then we create a object that will see how many times the main loop needs to update before it would shoot off.
So we update the object and it will return whether it has shot off or not.

Offline ra4king

JGO Kernel


Medals: 346
Projects: 3
Exp: 5 years


I'm the King!


« Reply #1 - Posted 2011-12-24 01:55:53 »

I don't quite understand what you are doing with the rate and mainRate.

How about this Animation class? I use a private internal class called Frame that stores the image and the time that frame ends. Then you call update every tick with the deltaTime and getFrame to get the current image.

Offline StumpyStrust
« Reply #2 - Posted 2011-12-24 02:55:29 »

So basically say you have your thread sleep every 16 milliseconds but you want a sprite/animation to change or update every 280 milliseconds.
Then you divide 280 by 16 and that will give you your "delta" the amount of updates n the main thread before you need to change frames.

My question is "is this a valid way of animating?"

I have tried it and it works for particles/emitters and it works for animations but I don't know if there is a better cleaner method that does not involve threads.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ra4king

JGO Kernel


Medals: 346
Projects: 3
Exp: 5 years


I'm the King!


« Reply #3 - Posted 2011-12-24 03:08:55 »

Well instead of doing all this math, my Animation class allows you just to set the number of milliseconds each frame runs at and updates accordingly. Your way depends on a steady game loop so if there is a slow down, things might get messed up.

Offline Nate

JGO Kernel


Medals: 147
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #4 - Posted 2011-12-24 03:54:20 »

Very simple animation class:
https://code.google.com/p/libgdx/source/browse/trunk/gdx/src/com/badlogic/gdx/graphics/g2d/Animation.java
Note this is structured to allow you to keep the state time in your model. You can store a state and a state time in your model, then when it comes time to draw, look up which animation to use based on the state and then pass the state time to the animation to get the correct frame, then draw that.

Offline StumpyStrust
« Reply #5 - Posted 2011-12-24 04:41:53 »

Interesting very similar to my idea but more polished.

Hmmm....basically you want the animation/timer to be able to update without much reliance on the main loop.


Offline counterp

Senior Member


Medals: 11



« Reply #6 - Posted 2011-12-24 16:48:20 »

Contributing...

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
public class Animation {

   public Animation(Frame[] frames) {
      this.frames = frames;
   }

   public Animation(BufferedImage[] frames, int delay) {
      this.frames = new Frame[frames.length];
      for (int i = 0; i < frames.length; i++) {
         this.frames[i] = new Frame(frames[i]);
         this.frames[i].delay = delay;
      }
   }

   public final Frame[] frames;

   private long start = -1;
   private int last = 0;

   public final BufferedImage lastImage() {
      return frames[last].image;
   }

   public final int frame() { // Gets the current frame's index position based on the internal 'frames' array
     if (start == -1) {
         start = System.nanoTime() / 1000000;
      }
      long now = System.nanoTime() / 1000000;
      long elapse = now - start;
      if (elapse >= frames[last].delay) {
         start = now;
         return last = ++last % frames.length;
      }
      return last;
   }

   public final int width(int frame) {
      return frames[frame].image.getWidth();
   }

   public final int height(int frame) {
      return frames[frame].image.getHeight();
   }

   public final int draw(Graphics2D g, int x, int y) {
      int frame = frame();
      g.drawImage(frames[frame].image, x, y, null);
      return frame;
   }

   public final void reset() {
      start = -1;
   }

}

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
public class Frame {

   public Frame() {
      this(128, 128);
   }

   public Frame(BufferedImage image) {
      this.image = image;
   }

   public Frame(int w, int h) {
      image = Misc.createBufferedImage(w, h);
   }

   public Frame(Frame copy) {
      image = Misc.clone(copy.image);
      delay = copy.delay;
      opacity = copy.opacity;
   }

   public final BufferedImage image;

   public int delay = 50;

   public int opacity = 100;

}


Your probably not gonna need a separate size for each frame, or that opacity variable in the Frame class either, I use them elsewhere in the program. This works well enough for me, it's pretty smooth, it's independent of game loop/rendering loop. I don't need to dynamically add frames once an animation object is created but it would be an easy edit.
Offline StumpyStrust
« Reply #7 - Posted 2011-12-24 19:30:38 »

I like that alot counterp.

But the code I was trying to make would be something that could be used not just for animation but for anything that needs a separate update time than the main loop.

Unfortunately my code relies on some constant amount of time that the main loop is updating at.

...Looks like I am going to look into the getNano time a bit more.

Offline counterp

Senior Member


Medals: 11



« Reply #8 - Posted 2011-12-24 20:41:33 »

Something like java.util.Timer?
Offline ra4king

JGO Kernel


Medals: 346
Projects: 3
Exp: 5 years


I'm the King!


« Reply #9 - Posted 2011-12-24 21:14:56 »

java.util.Timer uses separate threads....

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline counterp

Senior Member


Medals: 11



« Reply #10 - Posted 2011-12-24 21:55:07 »

no, it's single threaded

and what OP is doing is basically how Timer class works, except that the Timer class is not concerned about how many cycles there have been, but it works by waiting until the next task (the one with the shortest delay between now and its execution) is ready to be executed. (i would write my own implementation if you need really high accuracy)
Offline StumpyStrust
« Reply #11 - Posted 2011-12-27 02:51:21 »

So I could use the Timer class for animation?

Wow I always thought it ran a new Thread.

But no super accuracy is not important just want good timing for emitters and sprite animations for program I am making.

Offline ra4king

JGO Kernel


Medals: 346
Projects: 3
Exp: 5 years


I'm the King!


« Reply #12 - Posted 2011-12-27 02:52:59 »

The Timer class runs 1 thread for all its TimerTasks so it will be a different thread from your game loop, therefore you will have to turn your game loop into a TimerTask.

Offline counterp

Senior Member


Medals: 11



« Reply #13 - Posted 2011-12-27 05:20:25 »

I think the Timer class might be too clunky to use for your game loop, you shbould rip the implementation and strip it down if you can
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

radar3301 (12 views)
2014-09-21 14:33:17

BurntPizza (30 views)
2014-09-20 17:42:18

BurntPizza (22 views)
2014-09-20 16:30:30

moogie (20 views)
2014-09-20 15:26:15

UprightPath (28 views)
2014-09-20 11:14:06

BurntPizza (33 views)
2014-09-18 18:14:18

Dwinin (48 views)
2014-09-12 00:08:26

Norakomi (74 views)
2014-09-10 04:57:51

TehJavaDev (103 views)
2014-09-09 21:39:09

Tekkerue (50 views)
2014-09-08 17:24:56
List of Learning Resources
by Longor1996
2014-08-16 01:40:00

List of Learning Resources
by SilverTiger
2014-08-05 10:33:27

Resources for WIP games
by CogWheelz
2014-08-01 07:20:17

Resources for WIP games
by CogWheelz
2014-08-01 07:19:50

List of Learning Resources
by SilverTiger
2014-07-31 07:29:50

List of Learning Resources
by SilverTiger
2014-07-31 07:26:06

List of Learning Resources
by SilverTiger
2014-07-31 02:54:12

HotSpot Options
by dleskov
2014-07-07 16:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!