0

I'm somewhat new to creating games in Java, however my current setup is such that the FPS on the paint method is bounded only by the system. So, my FPS tends to be between 300 and 450. In order to standardize movement speeds on objects, I've been dividing the increment by the FPS so that it will increment that total amount in a one second time-frame.

I have the following code. What I want to do it make it so that map.addEntity() is not called 300 or 400 times per second, in accordance with the FPS; but rather make it so that I can choose, for example, to make the projectile fire at 10 RPS or so. How can I achieve this?

public void mousePressed(MouseEvent e) {
     if (gameStarted)
        shootProjectile = true;
  }
public void paint(Graphics g) {
if (shootProjectile)
           map.addEntity(new Projectile("projectile.png", x, y, 0, projectileSpeed));
}
fvgs
  • 21,412
  • 9
  • 33
  • 48

2 Answers2

2

I've been dividing the increment by the FPS

Don't do that! Use a Timer or a swingTimer to update everything at a constant rate. For example you could do something like this:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;

public class Test {   
    public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer(10,new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                updateProjectilePositions();
            }

        });
        timer.start(); 
    }

    private static void updateProjectilePositions() {
        // TODO Auto-generated method stub
    }
}

Note that if you use a swing Timer, your projectile updating will happen on the swing thread. If the updating hangs, your GUI will also hang.

You also should not call map.addEntity inside paint() since paint() does one thing and one thing only: paint everything. You can get around this but mixing up the code that updates things like position with code that renders the objects will eventually bite you.

Navin
  • 3,681
  • 3
  • 28
  • 52
  • It isn't actually in the paint() method. The rendering is fine, but I just wanted to simplify the code as much as possible for this example. – fvgs Jan 20 '13 at 05:35
  • Also, how would I use a timer without having the screen flicker? – fvgs Jan 20 '13 at 05:37
  • If double buffering is enabled, it should not flicker. I added some example code. – Navin Jan 20 '13 at 05:42
  • BTW you should also call `repaint()` after updating all the positions. That way, `paint()` will be called right after you have finished updating. If the computer you are running on is really slow, your logic will still run at the same rate, but `paint()` may only be called a few times per second, causing frame skipping. Usually, this is the intended outcome. – Navin Jan 20 '13 at 05:54
2

You should never use FPSs as your quantizer otherwise your game will run at different speeds on different machines and even on the same machine according to frame drops or spikes.

You can do two different things:

  • use a delta time between each frame update and update your game logic proportionally
  • use an accumulator in which you add the time delta and then you fire a logic update every fixed amount (so that you don't need to do things in proportion as your logic update will be fixed)
Jack
  • 131,802
  • 30
  • 241
  • 343
  • But how would I actually go about doing this? – fvgs Jan 20 '13 at 05:36
  • You need to store the elapsed time between each repaint so that you do know how many millisecs have passed and do your computations accordingly. Of course logic and graphics must be absolutely two different things. – Jack Jan 20 '13 at 05:38
  • How is this different from computing the FPS and dividing so that each step is executed the correct times per second? – fvgs Jan 20 '13 at 05:47
  • it is different because time is absolute, FPS is relative: every refresh could be shorter or longer so that's not a good measure to have a fixed time behavior. If FPS drop to half for a while then you logic will behave slower and that's not correct. – Jack Jan 20 '13 at 06:06