Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (577)
games submitted by our members
Games in WIP (498)
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  
  Measuring time inside render loop.  (Read 622 times)
0 Members and 1 Guest are viewing this topic.
Offline brollysan

Junior Member


Medals: 1



« Posted 2013-04-10 16:26:15 »

I have different sprites that I want to render at different speeds by changing to the next frame in the spritesheet if a delta time has passed. The problem is I have no idea how to get this delta, I cannot measure it inside the frameUpdate method of the sprite because it is called all the time inside my gameloop. I cannot measure it inside the gameloop because the game loops condition is while(game.isRunning()).

Essentially:

1  
2  
3  
4  
5  
6  
1) Somewhere in code, create animatedsprite with framedelay 250ms.
In gameloop:
2) Measure time after updating
3) Pass delta to animatedsprite
4) In animatedSprite, check if 250 ms has passed
5) Has 250 ms passed? Then draw next frame


Stuck on 3). I am currently solving this by clever use of math, if a multiple of the framedelay has passed then I curentFrame++ but since the Thread.sleep in the gameloop is not continious (1 ms resolution but usually determined by fps, eg if 100 fps then 10 ms resolution) this will not work if I do not provide a margin, my current margin is 10 ms. This assumes that the game MUST run under 100 fps and that there is no sprite that is rendered above 100 fps (framedelay < 10 ms).

Any solutions? Current SCCE:
Sprite
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 Animated implements Renderable {
   private ArrayList<BufferedImage> sheet;
   private int cols;
   private int rows;
   private int x;
   private int y;
   private int frameDelay;
   private int currentFrame;
   private int lastFrame;
   private BufferedImage currentImage;

   public Animated(ArrayList<BufferedImage> spritesheet, int cols,
         int rows, int frameDelay) {

      this.sheet = spritesheet;
      this.cols = cols;
      this.rows = rows;
      this.frameDelay = frameDelay;
      this.lastFrame = sheet.size() - 1;
      this.currentImage = sheet.get(0);
   }

   private void frameUpdate(int deltaTime) {
      System.out.println(deltaTime % frameDelay);
      if ((deltaTime % frameDelay) < 10) {
         if (currentFrame == lastFrame) {
            currentFrame = 0;
         }
         else {
            currentFrame++;
         }
         currentImage = sheet.get(currentFrame);

      }
   }

   @Override
   public void render(Graphics2D g) {

   }

   @Override
   public void setPosition(int x, int y) {
      this.x = x;
      this.y = y;
   }

   @Override
   public void render(Graphics2D g, int deltaTime) {
      frameUpdate(deltaTime);
      g.drawImage(currentImage, x, y, null);

   }

}

Render in loop:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
public void render() {
      Renderable bahamut = new Animated(images.get("bahamutANIMATED"), 4, 4,
            250);
      bahamut.setPosition(0, 500);
      Renderable bahamut2 = new Animated(images.get("bahamutANIMATED"), 4, 4,
            5000);
      bahamut2.setPosition(0, 0);
      long t0 = System.currentTimeMillis();

      while (true) {
         clearScreen();

         long t1 = System.currentTimeMillis();
         int delta = (int) (t1 - t0);
         bahamut.render(g, delta);
         bahamut2.render(g, delta);

         showBuffer();
         try {
            Thread.sleep(10);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
   }
Offline brollysan

Junior Member


Medals: 1



« Reply #1 - Posted 2013-04-10 18:36:30 »

After extensive testing it seems I can keep complete control over the margin (eg this works completely), using the code above but keeping control over the margin by setting a limit on how fast the sprites can render, I wanted to avoid doing this but it works and the % operator is very cheap.

1  
2  
3  
margin = fpsDelay;
if (frameDelay<fpsDelay) {
 frameDelay = fpsDelay; }



Online StumpyStrust
« Reply #2 - Posted 2013-04-10 20:33:34 »

I told myself I would stop trolling here so much but I give in.

Normally, you do not do any sort of logic in the rendering thread. That is to say, you do not care about delta or anything like that. For animation rendering, you would set which frame is to be render in your logic (update). Then when rendering comes, you render is. If this code is working fine for you, use it but do not try measuring delta time stuff in renderloop.

Here is how I do animations or any form of timing. (no interpolation)

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
int currentUpdate = 0;
int frameRate = 60; //(1 frame every second)

updateMethod(delta)
{
    currentUpdate++;
    currentUpdate *= delta; //
   if(currentUpdate >= frameRate)
    {
         currentUpdate = 0;
         nextFrame();
         //check to see if you need to loop back to start when updating frame
   }
}


This is just some psudo code. It will not take into account huge deltas but the key is to keep logic away from rendering.

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

Junior Member


Medals: 1



« Reply #3 - Posted 2013-04-10 21:10:55 »

That was in the SCCE, the actual game has no logic in the rendering, in the gameloop after updating the entities renderer.render(delta) is called where the renderer keeps an arraylist with references to all the objects in the game that implement the Renderable interface. AnimatedSprite is only one type that implements the interface, I have stuff like "GameString" which draws a spritelike string and questpanels etc. The idea was to remove intercoupling of objects ( or reduce it to a minimum level) letting me expand and implement new futures without breaking stuff all the time. This is why most objects take care of themselves in my code, like how the animatedsprite only needs a delta and a reference to the Graphics2D.
Online StumpyStrust
« Reply #4 - Posted 2013-04-11 02:12:21 »

Cool then. If it works then don't do anything. If it is slow, ask yourself "is it REALLY slow?"

Keep up the work.

Offline Grunnt

JGO Wizard


Medals: 55
Projects: 9
Exp: 5 years


Complex != complicated


« Reply #5 - Posted 2013-04-11 12:59:35 »

One thing that confuses me is that you appear to use the time since the start of the game as your time delta. Normally you would use the time between the previous update and the current update as your time delta for calculations. For example, in your code you could simply add t0 = t1:
1  
2  
3  
long t1 = System.currentTimeMillis();
int delta = (int) (t1 - t0);
t0 = t1;


Offline brollysan

Junior Member


Medals: 1



« Reply #6 - Posted 2013-04-11 20:37:26 »

You are of course right that it would be better, especially if the rendering takes any measurable time as in my current loop I don't take that into consideration.
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.

xsi3rr4x (25 views)
2014-04-15 18:08:23

BurntPizza (20 views)
2014-04-15 03:46:01

UprightPath (36 views)
2014-04-14 17:39:50

UprightPath (18 views)
2014-04-14 17:35:47

Porlus (34 views)
2014-04-14 15:48:38

tom_mai78101 (60 views)
2014-04-10 04:04:31

BurntPizza (118 views)
2014-04-08 23:06:04

tom_mai78101 (218 views)
2014-04-05 13:34:39

trollwarrior1 (185 views)
2014-04-04 12:06:45

CJLetsGame (192 views)
2014-04-01 02:16:10
List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:05:20
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!