Java Swing game has poor performance when many sprites are on screen
animation, java, swing
Solution
Each target runs a Swing Timer to calculate its position. This is the ActionListener it calls:
This may be your problem - having each target/bullet (I assume?) responsible for keeping track of when to update itself and draw itself sounds like quite a bit of work. The more common approach is to have a loop along the lines of
while (gameIsRunning) {
int timeElapsed = timeSinceLastUpdate();
for (GameEntity e : entities) {
e.update(timeElapsed);
}
render(); // or simply repaint in your case, I guess
Thread.sleep(???); // You don't want to do this on the main Swing (EDT) thread though
}
Essentially, an object further up the chain has the responsibility to keep track of all entities in your game, tell them to update themselves, and render them.
Problem
I'm making a simple tower defense game in Swing and I've run into a performance problem when I try to put many sprites (more than 20) on screen. The whole game takes place on a JPanel which has setIgnoreRepaint(true). Here is the paintComponent method (con is the Controller): ``` public void paintComponent(Graphics g){ super.paintComponent(g); //Draw grid g.drawImage(background, 0, 0, null); if (con != null){ //Draw towers for (Tower t : con.getTowerList()){ t.paintTower(g); } //Draw targets if (con.getTargets().size() != 0){ for (Target t : con.getTargets()){ t.paintTarget(g); } //Draw shots for (Shot s : con.getShots()){ s.paintShot(g); } } } } ``` The Target class simple paints a BufferedImage at its current location. The getImage method doesn't create a new BufferedImage, it simply returns the Controller class's instance of it: ``` public void paintTarget(Graphics g){ g.drawImage(con.getImage("target"), getPosition().x - 20, getPosition().y - 20, null); } ``` Each target runs a Swing Timer to calculate its position. This is the ActionListener it calls: ``` public void actionPerformed(ActionEvent e) { if (!waypointReached()){ x += dx; y += dy; con.repaintArea((int)x - 25, (int)y - 25, 50, 50); } else{ moving = false; mover.stop(); } } private boolean waypointReached(){ return Math.abs(x - currentWaypoint.x) <= speed && Math.abs(y - currentWaypoint.y) <= speed; } ``` Other than that, repaint() is only called when placing a new tower. How can I improve the performance?