2010-03-03 13 views
1

Je travaille sur la recréation de "Legend of Zelda un lien vers le passé" dans le cadre d'une mission.Java optimisant la peinture d'une image de fond pour un jeu

Et j'ai le problème suivant, le monde du jeu est un BufferedImage dont je sous-image() la partie dont j'ai besoin pour l'emplacement actuel du joueur. Le jeu fonctionne mais utilise 80/110% du CPU. Un profil a révélé que le coupable est le dessin de l'image.

Donc je me suis dit que je mettais l'arrière-plan dans un JPanel séparé du Player, des ennemis etc JPanel. Rendez-les les uns au-dessus des autres (JLayeredPane) et repeignez le panneau d'arrière-plan beaucoup moins souvent.

Mais comment est-ce que je fais cela, comment puis-je dire à Swing de dessiner un panneau x fois par seconde et l'autre fois par y? Si vous avez une meilleure façon d'optimiser faites le moi savoir.

Voici ce que j'ai au 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(); 
    } 
} 

Merci.

Répondre

4

Il n'est pas vraiment possible d'avoir des temps de rendu différents en raison de la façon dont le framebuffer fonctionne - le résultat serait un tas de scintillement désagréable. Ce que vous devez faire est d'utiliser Canvas au lieu de JPanel et JLayeredPane et vous pouvez soit remplacer la méthode paint() de la toile ou utiliser bi.getGraphics() et de fondre l'arrière-plan et les caractères sur une boucle en utilisant une de ces méthodes dans le bon ordre. Je vous conseille d'utiliser un moteur mince comme GTGE qui résumera tous les détails désordonnés de l'optimisation. Ces composants de haut niveau que vous utilisez sérieusement ne sont pas conçus pour les jeux, et vous ne devriez pas les utiliser du tout.

+0

Merci J'ai trouvé un article grâce à votre suggestion sur bi.getGraphics voir ma réponse. Et GTGE sonne bien, mais je le fais moi-même pour l'expérience. C'est une mission de toute façon. PS JCanvas ne fait pas partie de Java, vouliez-vous dire Canvas ou le projet JCanvas? – MrHus

+0

GTGE est maintenant open source, jetez un oeil à l'intérieur (http://code.google.com/p/gtge) - c'est là que j'ai appris beaucoup de techniques efficaces pour faire des jeux Java2D, plus son * très * proche de vous feriez de toute façon si vous le faites à partir de rien :) Et désolé, je voulais dire Canvas plutôt que JCanvas (oups). –

0

Ok J'ai trouvé l'erreur de mes façons. J'utilisais le rendu passif alors que j'aurais dû utiliser active rendering. Le rendu actif arrête les repaints automatiques en appelant setIgnoreRepaint (true); sur le cadre et faites la boucle vous-même.

Et en bonus, je n'ai pas besoin d'utiliser JPanels.

+0

Même le rendu passif est correct, et peut parfois être plus efficace. Fondamentalement, avec le rendu passif, tout ce que vous faites est de surcharger la méthode paint (Graphics g) de Canvas et d'autoriser cela à mettre à jour la vue. Cependant, en raison de l'organisation du jeu, il n'est pas toujours possible d'avoir le code de rendu de la vue ici (peut-être votre structure de code (peut-être pas Model-View-Controller) vous limite au rendu à la fin de chaque mise à jour). Mais fondamentalement, avec le rendu passif, vous pouvez invalider la toile de toute façon et il se rendra compte qu'il doit repeindre. –