Problèmes avec createImage(int largeur, int hauteur)
J'ai le code suivant, qui se déroule tous les 10ms dans le cadre d'un jeu:
private void gameRender()
{
if(dbImage == null)
{
//createImage() returns null if GraphicsEnvironment.isHeadless()
//returns true. (java.awt.GraphicsEnvironment)
dbImage = createImage(PWIDTH, PHEIGHT);
if(dbImage == null)
{
System.out.println("dbImage is null"); //Error recieved
return;
}
else
dbg = dbImage.getGraphics();
}
//clear the background
dbg.setColor(Color.white);
dbg.fillRect(0, 0, PWIDTH, PHEIGHT);
//draw game elements...
if(gameOver)
{
gameOverMessage(dbg);
}
}
Le problème est qu'il entre dans l'instruction if qui vérifie l'Image étant nulle, même après ma tentative de définition de l'image. J'ai regardé autour, et il semble que createImage() renvoie la valeur null si GraphicsEnvironment.isHeadless() renvoie la valeur true.
Je ne comprends pas exactement ce que l'isHeadless() la méthode du but, mais j'ai pensé qu'il pourrait avoir quelque chose à voir avec le compilateur ou l'IDE, j'ai donc essayé sur deux, tous deux obtenir la même erreur (Eclipse, et BlueJ). Quelqu'un a une idée de ce que la source de l'erreur est, et comment je pourrais résoudre ce problème?
Merci d'avance
Jonathan
...................................................................
EDIT:
Je suis à l'aide de java.awt.Composante.createImage(int largeur, int hauteur). Le but de cette méthode est d'assurer la création et la modification d'une Image qui contient le point de vue du joueur du jeu, qui sera plus tard d'être portée à l'écran par le biais d'un Composite.
Voici quelques plus de code si cela aide à tous:
public class Sim2D extends JPanel implements Runnable
{
private static final int PWIDTH = 500;
private static final int PHEIGHT = 400;
private volatile boolean running = true;
private volatile boolean gameOver = false;
private Thread animator;
//gameRender()
private Graphics dbg;
private Image dbImage = null;
public Sim2D()
{
setBackground(Color.white);
setPreferredSize(new Dimension(PWIDTH, PHEIGHT));
setFocusable(true);
requestFocus(); //Sim2D now recieves key events
readyForTermination();
addMouseListener( new MouseAdapter() {
public void mousePressed(MouseEvent e)
{ testPress(e.getX(), e.getY()); }
});
} //end of constructor
private void testPress(int x, int y)
{
if(!gameOver)
{
gameOver = true; //end game at mousepress
}
} //end of testPress()
private void readyForTermination()
{
addKeyListener( new KeyAdapter() {
public void keyPressed(KeyEvent e)
{ int keyCode = e.getKeyCode();
if((keyCode == KeyEvent.VK_ESCAPE) ||
(keyCode == KeyEvent.VK_Q) ||
(keyCode == KeyEvent.VK_END) ||
((keyCode == KeyEvent.VK_C) && e.isControlDown()) )
{
running = false; //end process on above list of keypresses
}
}
});
} //end of readyForTermination()
public void addNotify()
{
super.addNotify(); //creates the peer
startGame(); //start the thread
} //end of addNotify()
public void startGame()
{
if(animator == null || !running)
{
animator = new Thread(this);
animator.start();
}
} //end of startGame()
//run method for world
public void run()
{
while(running)
{
long beforeTime, timeDiff, sleepTime;
beforeTime = System.nanoTime();
gameUpdate(); //updates objects in game (step event in game)
gameRender(); //renders image
paintScreen(); //paints rendered image to screen
timeDiff = (System.nanoTime() - beforeTime) / 1000000;
sleepTime = 10 - timeDiff;
if(sleepTime <= 0) //if took longer than 10ms
{
sleepTime = 5; //sleep a bit anyways
}
try{
Thread.sleep(sleepTime); //sleep by allotted time (attempts to keep this loop to about 10ms)
}
catch(InterruptedException ex){}
beforeTime = System.nanoTime();
}
System.exit(0);
} //end of run()
private void gameRender()
{
if(dbImage == null)
{
dbImage = createImage(PWIDTH, PHEIGHT);
if(dbImage == null)
{
System.out.println("dbImage is null");
return;
}
else
dbg = dbImage.getGraphics();
}
//clear the background
dbg.setColor(Color.white);
dbg.fillRect(0, 0, PWIDTH, PHEIGHT);
//draw game elements...
if(gameOver)
{
gameOverMessage(dbg);
}
} //end of gameRender()
} //end of class Sim2D
Espère que cela aide à clarifier un peu les choses,
Jonathan
Vous devez vous connecter pour publier un commentaire.
Au lieu de createImage(...), j'ai l'habitude d'utiliser un BufferedImage.
J'ai eu exactement le même problème après j'ai essayé de mettre en œuvre le Doublebuffering pour un générateur de fractale. Ma solution:
J'ai pris l'exemple d'un livre, mais a changé (sans en connaître les conséquences) de la manière que j'ai couru createImage à l'INTÉRIEUR du constructeur. Cela a produit un nullpointer. Ensuite j'ai mis ce
à l'intérieur de la mise à jour de la méthode et cela a fonctionné !! Car la mise à jour est appelé APRÈS que l'objet a été construit.
Selon la doc de java.awt.Composant, createImage peut aussi retourner la valeur null si l'élément n'est pas affichable, ce qui est plus probable de ce qui se passe.
Pour ce que vous essayez de faire, vous devriez regarder la classe BufferedImage, que ce n'est pas lié à la composante.
Essayer de substitution de la addNotify() la méthode dans le Composite étendre. C'est un bon endroit pour "lancer" votre animation, plutôt que le constructeur par exemple. Assurez-vous d'inclure la ligne super.addNotify();
public void addNotify()
{
super.addNotify();
startGame();
}
Bonne chance
Ressemble le thread est en cours de démarrage plus tôt que le composant est réellement affiché sur l'écran. Pour que cela ne se produise pas, vous pouvez remplacer le paint(Graphics g) méthode de Composite et de mettre le code dans le fil de la méthode run() à l'intérieur de la méthode de peinture. Dans votre fil d'exécution() les méthodes, il suffit d'appeler repaint().
e.g:
et dans votre méthode run ():
isHeadless ne retourne true si vous exécutez dans un non-GUI environnement (par exemple, au sein d'un serveur ou d'un conteneur de servlet).
Je crois que votre problème est dans votre createImage méthode elle-même. Pouvez-vous nous donner plus de contexte? Qui createImage méthode est appelée et qu'est-ce que sa mise en œuvre?