2017-08-19 4 views
0

Mon problème est, j'ai un jeu avec une carte générée aléatoirement et il a seulement 30-40 fps à cause du nombre de blocs. (Vous pouvez imaginer mon jeu comme un minecraft 2d).Comment puis-je optimiser mon rendu de jeu java 2d?

Je recherche d'abord le premier carreau ce qui est dans l'écran. Ensuite, commencez une tuile de rendu de la boucle suivante ... jusqu'à ce que j'atteigne la dernière tuile que vous pouvez voir.

(Je n'utilise aucune des classes Java comme graphics/graphics2d J'utilise mon propre code qu'est-ce qu'un int [] avec les lignes de l'écran et quand je rends un tile je change le int [x + y * largeur] position de l'écran au bon pixel du bloc)

Je pense logiquement que c'est la meilleure façon de rendre ma carte et je ne comprends pas pourquoi les fps sont faibles. Je me trompe ou dois-je chercher un autre problème dans mon code? Ou y at-il une meilleure méthode de rendu?

Si je saute le rendu du monde, il y a 120 fps stabile ce qui est plafonné là. Quel peut être le problème?

+0

Vous avez vraiment besoin d'ajouter plus de détails et du code. Nous ne savons rien pour le moment. Ni le nombre de carreaux sur votre écran, ni leur taille, ni à quelle vitesse ils changent ... et je ne comprends pas comment vous dessinez. Tout cela peut difficilement être expliqué en mots. Poster les parties pertinentes ici, idéalement un exemple de travail. – maaartinus

+0

Utilisez un profileur tel que VisualVM pour savoir où l'heure est passée. Pensez ensuite aux opérations lentes - peuvent-elles être remplacées par quelque chose de plus rapide?Sont-ils tous nécessaires (par exemple, j'ai une fois énormément accéléré un programme Game of Life en gardant une liste de cellules changées, et en dessinant seulement celles-ci). – slim

Répondre

1

Je sais que vous n'utilisez pas les fonctions Gaphics et que vous choisissez de manipuler une matrice de pixels à la place. Essayez de changer votre jeu pour utiliser l'objet Graphics car il n'y a pas de moyen (facile et efficace) de le contourner. Si vous choisissez toujours pas à le faire, comme vous essayez d'ajouter

System.setProperty("sun.java2d.opengl", "true");

au début même de votre code juste après

public static void main(String[] args) { 

J'ai essayé de le faire de la même façon quand je d'abord fait des jeux simples mais vous réaliserez plus tard que les fonctions graphiques intégrées sont largement supérieures en performance et en facilité d'utilisation.

EDIT:

Une courte explanaition sur la façon dont un jeu de base peut utiliser l'objet Graphics:

Supposons que vous avez créé un JFrame. Si vous ajoutez ensuite une classe qui s'étend de Canvas et ajoutez-y. Si vous voulez utiliser un menu, vous pouvez même créer un JPanel en premier et ajouter le Canvas dans le Jpanel afin de pouvoir le cacher plus facilement.

Ici vous avez un exemple comment nous créons une toile utilisable:

import java.awt.Canvas; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.image.BufferStrategy; 

import javax.swing.JFrame; 

public class Game extends Canvas implements Runnable{ 

    private static final long serialVersionUID = 1L; 

    public static final int WIDTH = 1920; 
    public static final int HEIGHT = WIDTH * 9/16; 
    public static final String TITLE = "YOUR GAMES NAME"; 
    public static final int TICKSPERS = 120; 
    public static final boolean ISFRAMECAPPED = false; 


    public static JFrame frame; 

    private Thread thread; 
    private boolean running = false; 

    public int frames; 
    public int lastFrames; 
    public int ticks; 

    public Game(){ 
     Dimension size = new Dimension(WIDTH, HEIGHT); 
     setPreferredSize(size); 
     setMaximumSize(size); 
     setMinimumSize(size); 
    } 

    public void render(){ 
     frames++; 
     BufferStrategy bs = getBufferStrategy(); 
     if (bs == null){ 
      createBufferStrategy(2); 
      return; 
     } 
     Graphics g = bs.getDrawGraphics(); 
     g.setColor(new Color(79,194,232)); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
     //Call your render funtions from here 

     g.setColor(Color.BLACK); 
     g.fillRect(120,70,35,90); 

     g.dispose(); 
     bs.show(); 
    } 

    public void tick(){ 
    } 

    public synchronized void start(){ 
     if(running) return; 
     running = true; 
     thread = new Thread(this, "Thread"); 
     thread.start(); 
    } 

    public synchronized void stop(){ 
     if(!running) return; 
     running = false; 
     try { 
      System.exit(1); 
      frame.dispose(); 
      thread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void init(){ 

    } 

    public void run() { 
     init(); 
     //Tick counter variable 
     long lastTime = System.nanoTime(); 
     //Nanoseconds per Tick 
     double nsPerTick = 1000000000D/TICKSPERS; 
     frames = 0; 
     ticks = 0; 
     long fpsTimer = System.currentTimeMillis(); 
     double delta = 0; 
     boolean shouldRender; 
     while(running){ 
      shouldRender = !ISFRAMECAPPED; 
      long now = System.nanoTime(); 
      delta += (now - lastTime)/nsPerTick; 
      lastTime = now; 
      //if it should tick it does this 
      while(delta >= 1){ 
       ticks++; 
       tick(); 
       delta -= 1; 
       shouldRender = true; 
      } 
      if (shouldRender){ 
      render(); 
      } 
      if (fpsTimer < System.currentTimeMillis() - 1000){ 
       System.out.println(ticks +" ticks, "+ frames+ " frames"); 
       ticks = 0; 
       lastFrames = frames; 
       frames = 0; 
       fpsTimer = System.currentTimeMillis(); 
      } 
     } 
    } 

    public static void main(String[] args){ 
     Game game = new Game(); 
     frame = new JFrame(TITLE); 
     frame.add(game); 
     frame.pack(); 
     frame.setResizable(false); 
     frame.setLocationRelativeTo(null); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
     game.start(); 
    } 

} 

Cette classe peut être votre base. Sa méthode tick est appelée 120 fois par seconde et sa méthode de rendu peut restituer des choses sur l'écran. Si vous n'êtes pas familier avec les fonctions de l'objet graphique, je vous suggère de les lire un peu.

Vous ne pouvez pas atteindre l'objet Graphics de l'extérieur. Vous devez appeler les fonctions de rendu à l'intérieur de la fonction de rendu des jeux avant que l'objet Graphics ne soit éliminé. Essayez de séparer votre logique de jeu des fonctions de rendu.

+0

Je comprends ce que vous dites, mais il y a des choses que je ne comprends pas ou que je ne peux pas faire. Comme comment puis-je faire une méthode de rendu de travail avec le Graphics intégré (je veux dire qu'il ya une classe qui utilise Graphics et comment puis-je l'atteindre de l'extérieur)? ou comment puis-je obtenir une couleur d'un pixel? – pocokknight

+0

Vous devez utiliser des fonctions à l'intérieur d'une boucle de rendu pour rendre vos objets. Disons que vous créez l'objet graphique au début d'un cycle en boucle. Vous devez ensuite le transmettre aux objets via une fonction avant qu'il ne soit éliminé à la fin du cycle. Si vous voulez que je l'explique plus en détail, je peux éditer ma réponse pour vous montrer. – C1bergh0st

+0

Je serais heureux si vous me l'avez expliqué. – pocokknight