Pregunta

Tengo el siguiente código, que se ejecuta cada 10 ms, como parte de un juego:

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);
    }
}

El problema es que entra en la sentencia if que comprueba la imagen que está siendo nula, incluso después de que intento definir la imagen. Miré a mi alrededor, y parece que createImage () devolverá un valor nulo si GraphicsEnvironment.isHeadless () devuelve verdadero.

No entiendo exactamente lo que el isHeadless () El propósito del método es, pero pensé que podría tener algo que ver con el compilador o IDE, por lo que intentó en dos, ambos de los cuales sale el mismo error (Eclipse, y BlueJ). Alguien tiene alguna idea de lo que es el origen del error, y cómo podría solucionarlo?

Gracias de antemano

Jonathan

............................................... ....................

EDIT: Estoy utilizando java.awt.Component.createImage (ancho int, altura int). El propósito de este método es garantizar la creación de, y editar una imagen que contendrá el punto de vista del jugador del juego, que posteriormente se extrae a la pantalla por medio de un JPanel. Aquí hay un código más si esto ayuda en absoluto:

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

Espero que esto ayude a aclarar las cosas un poco, Jonathan

¿Fue útil?

Solución

En lugar de createImage (...), por lo general uso un BufferedImage.

Otros consejos

Yo tenía exactamente el mismo problema después de que trató de implementar Doublebuffering para un generador de fractales. Mi solución: Tomé el ejemplo de un libro, pero lo cambió (sin saber las consecuencias) en la forma en que me encontré createImage dentro del constructor. Esto produjo el NullPointer. Entonces pongo esto

if (_dbImage == null) {
_dbImage = createImage(getSize().width, getSize().height);
_dbGraphics = (Graphics2D)_dbImage.getGraphics();
}

Dentro de la actualización del método y funcionó !! Debido a que la actualización se llama después del objeto ha sido construida.

De acuerdo con la documentación para java.awt.Component, createImage también puede devolver un valor nulo si el componente no es visualizable, que es muy probable que lo que está sucediendo.

Por lo que estamos tratando de hacer usted debe buscar en la clase BufferedImage, ya que esto no está ligado al componente.

Trate reemplazando el método addNotify () en el JPanel está extendiendo. Este es un buen lugar para 'lanzamiento' de la animación, en lugar de que el constructor por ejemplo. Asegúrese de incluir la línea super.addNotify ();

public void addNotify () {       super.addNotify ();      empezar juego(); }

Lo mejor de la suerte

Parece que el hilo se está iniciando antes que el componente se muestra realmente en la pantalla. Para asegurarse de que esto no ocurra, se puede reemplazar el método paint (Graphics g) de JPanel y poner el código en la carrera del hilo método () dentro del método de pintura. En la carrera de su rosca () métodos, simplemente llame a pintar ().

por ejemplo:

public void paint(Graphics g){
        **gameUpdate(); //updates objects in game (step event in game)
        gameRender(); //renders image
        paintScreen(); //paints rendered image to screen**
}

y en su método run ():

public void run(){
 while(running)
    {
        long beforeTime, timeDiff, sleepTime;

        beforeTime = System.nanoTime();

        **repaint();**

        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();
    }
}

isHeadless sólo devolverá cierto si se está ejecutando en un entorno no-GUI (por ejemplo, dentro de un contenedor de servidor o servlet).

Creo que su problema está dentro de su propio método createImage. ¿Nos puede dar más contexto? ¿Qué método createImage está siendo llamado y cuál es su aplicación?

package javagame;

import java.awt.BorderLayout;
import javax.swing.JFrame;

/**
 *
 * @author stuart
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        JFrame frame= new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(100, 100, 500, 400);

        frame.add(new GamePanel(), BorderLayout.CENTER);
        frame.setVisible(true);
    }

}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top