Java limiting fps in JPanel

I'm trying to limit the fps of my program, since the balls in the code are moving way too fast. I've been trying to do it with a timer and actionlistener, but I have no idea how to implement it correctly.

Main class

    package com.company;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;


public class Main extends JPanel implements ActionListener {


    Ball[] balls = new Ball[20];
    Random rand = new Random();
    private final Timer timer = new Timer(40, this);



    Main() {

        for(int i = 0; i<20;i++){
            float r = rand.nextFloat();
            float g = rand.nextFloat();
            float b = rand.nextFloat();
            Color randomColor = new Color(r, g, b);
            balls[i] = new Ball(Ball.randInt(0, 600),Ball.randInt(0, 600),Ball.randInt(10, 50),rand.nextInt(3-1)+1,randomColor,600,600);


        }
    }

    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        for(int i=0;i<20;i++) {
            balls[i].draw(g);
            balls[i].update();
        }

    }


    @Override
    public void actionPerformed(ActionEvent e) {
        this.repaint();
    }


    public static void main(String[] args) {


        Main m = new Main();
        JFrame frame = new JFrame("Title"); //create a new window and set title on window
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //set the window to close when the cross in the corner is pressed
        frame.setSize(600,600);
        frame.add(m); //add the content of the game object to the window
        frame.setVisible(true); //make the window visible



    }


}

Ball class

package com.company;

import javax.swing.*;
import java.awt.*;
import java.util.Random;
/**
 * Created by John on 25/02/2015.
 */

public class Ball extends JPanel{
    float _speedX;
    float _speedY;
    int _size;
    float _x;
    float _y;
    float _speed;
    Color _color;
    int _windowX;
    int _windowY;




    Ball(int x, int y, int sz, float speed, Color c, int windowX, int windowY){
        _x = x;
        _y = y;
        _speed=speed;
        _speedX = speed;
        _speedY = speed;
        _size = sz;
        _color = c;
        _windowX = windowX;
        _windowY = windowY;



    }



    public void update(){

            _x += _speedX;
            _y += _speedY;

            if (_x+_size<0 || _x+_size>_windowX-_size){
                _speedX*=-1;
            }

            if (_y+_size<0 || _y+_size>_windowY-_size){
                _speedY*=-1;
            }



this.repaint();


    }
    public static int randInt(int min, int max) {
        Random rand = new Random();
        int randomNum = rand.nextInt((max - min) + 1) + min;
        return randomNum;
    }

    public void draw(Graphics g) {
        g.setColor(_color);
        g.fillOval((int)_x,(int) _y, _size, _size);

    }
    }

Upvotes: 0

Views: 1835

Answers (2)

SomeJavaGuy
SomeJavaGuy

Reputation: 7347

you don´t need to lock your fps to a specific value to slow down your game, you just have to lock your updates on the values to be happening a specific amount of times in a defined interval. let me give you an example:

int UPDATES = 60;  // set the updates of the values to 60 per second
int UPDATEUNIT = 1000000; // Just the devider to calc up from nano
long executionStamp = System.nanoTime() / UPDATEUNIT; // the timestamp of the last execution
while(isRunning()) { 
    long now = System.nanoTime() / UPDATEUNIT; // get the current time
    long difference  = now - executionStamp; // get the difference between the last update and the current run
    long interval = MILLI / UPDATES; // a number representing the time that needs to pass for the next value update to happen
    if (difference > interval) {
        _game.updateValues();
        executionStamp = System.nanoTime() / UPDATEUNIT; // set new executiontimestamp
    }
    _game.updateUI(); // Upating the ui should allways be able to have unlimited FPS if you don´t want the user to lock it manually
}

Upvotes: 0

StanislavL
StanislavL

Reputation: 57381

Don't call update from paintComponent().

Balls should change their positions from actionPerformed() method (called from the Timer). Thus if you change the timer milliseconds you can make it faster/slower.

In fact the TImer should define how often you repaint the content (and change the model - contentn elements' locations/sizes)

Upvotes: 3

Related Questions