views:

204

answers:

2

I'm working on recreating "Legend of Zelda a Link to the Past" as part of an assignment.

And I've got the following problem, the game world is a BufferedImage of which I subImage() the part I need for the current location of the player. The game works but uses 80 / 110 percent of the CPU. A profile revealed that the culprit is the drawing of the image.

So I figured I put the background in a separate JPanel from the Player, enemies etc JPanel. Render them on top off each other (JLayeredPane) and repaint the background panel far less often.

But how do I do this how do I tell swing to draw one panel x times a sec and the other y times? If you have a better way of optimizing let me know.

Here's what I've got at the moment:

public class Main extends JFrame
{
    private ZeldaGame game = new ZeldaGame();
    private View view = new View(game);
    private BackgroundView bckView = new BackgroundView(game);
    private Controller ctl = new Controller(game, view, bckView, this);

    public Main()
    {
        setLayout(null);

        view.setBounds(0, 0, game.getWidth(), game.getHeight());
        bckView.setBounds(0, 0, game.getWidth(), game.getHeight());

        JLayeredPane pane = new JLayeredPane();
        pane.add(bckView, 1);
        pane.add(view, 0);

        setLayeredPane(pane);

        setSize(game.getWidth(), game.getHeight());
        setResizable(false);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        setVisible(true);
    }

    public static void main(String[] args)
    {
        new Main();
    }
}

Thank You.

+3  A: 

It's not really possible to have different render times because of the way the framebuffer works -- what the result would be is loads of nasty flickering. What you need to do is using Canvas instead of JPanel and JLayeredPane and you can either override the paint() method of the canvas or use bi.getGraphics() and blit the background and the characters on a loop using either of these methods in the correct order. I'd advise using a thin engine like GTGE which will abstract from all the messy details of optimisation. These high level components you're using seriously aren't designed for games, and you shouldn't be using them at all.

Chris Dennett
Thanks I've found an article thanks to your suggestion on bi.getGraphics see my answer. And GTGE sounds great but I'm doing it myself for the experience. Its a assignment anyway.PS JCanvas is not part of Java so did you mean Canvas or the JCanvas project?
MrHus
GTGE is now open source, have a look inside (http://code.google.com/p/gtge) -- it's where I learnt a lot of efficient techniques for doing Java2D games, plus its *very* close to what you would do anyway if doing it from scratch yourself :) And sorry, I meant Canvas rather than JCanvas (oops).
Chris Dennett
A: 

Ok I've found the error of my ways. I was using passive rendering while I should have used active rendering. Active rendering basically shuts down the automatic repaints by calling setIgnoreRepaint(true); on the frame and do the loop yourself.

And as an added bonus I don't need to use JPanels.

MrHus
Even passive rendering is okay, and sometimes can be more efficient. Basically, with passive rendering all you do is override the paint(Graphics g) method of Canvas and allow that to update the view. However, due to game organisation, structure, it isn't always possible to have the view rendering code in here (perhaps your code structure (might not be Model-View-Controller) limits you to rendering at the end of each update). But basically, with the passive rendering, you can invalidate the canvas anyway and it will realise that it needs to repaint.
Chris Dennett