2009-10-09 2 views
1

У меня есть следующий код, который запускается каждые 10мс как часть игры:Проблемы с createImage (ширина Int, Int высота)

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

Проблема в том, что она входит в, если заявление, которое проверяет для Изображение равно нулю, даже после того, как я попытаюсь определить изображение. Я огляделся, и кажется, что createImage() вернет значение null, если GraphicsEnvironment.isHeadless() возвращает true.

Я не понимаю, что такое метод isHeadless(), но я подумал, что это может иметь какое-то отношение к компилятору или IDE, поэтому я попытался по два, оба из которых получают ту же ошибку (Eclipse, и BlueJ). Кто-нибудь имеет представление о том, что является источником ошибки, и как я могу это исправить?

Заранее спасибо

Джонатан

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

EDIT: Я использую java.awt.Component.createImage (int width, int height). Целью этого метода является создание и редактирование изображения, которое будет содержать представление игрока игры, которое позже будет выведено на экран с помощью JPanel. Вот еще какой-то код, если это помогает на всех:

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 

Надеется, что это помогает убрать вещи немного, Джонатан

ответ

3

Вместо createImage (...), я обычно использую BufferedImage.

+0

Я следую из текста в образовательных целях, и предпочел бы сохранить на использование изображения, если это вообще возможно, так что я могу держать как можно ближе к примерам коды и например. Возможно, есть другой способ? Существуют ли другие преимущества и/или причины использования BufferedImage? – Jonathan

+0

camickr делает хороший момент. Кроме того, изображение является абстрактным классом. Всякий раз, когда вы работаете с изображением, вы на самом деле имеете дело с одной из нескольких возможных реализаций изображения под капотом. BufferedImage - один из них, и это тот, который имеет смысл использовать. – z5h

+0

Хорошо, я попытаюсь использовать BufferedImage. Спасибо. – Jonathan

0

isHeadless только возвращает истину, если вы работаете в среде без графического интерфейса пользователя (например, в контейнере сервера или сервлета).

Я считаю, что ваша проблема заключается в вашем методе createImage. Можете ли вы дать нам больше контекста? Какой метод createImage вызывается и какова его реализация?

2

В соответствии с документами для java.awt.Component, createImage также может возвращать значение null, если компонент не отображается, что, скорее всего, происходит.

Для чего вы пытаетесь сделать это, вы должны посмотреть на класс BufferedImage, поскольку это не связано с компонентом.

+0

+1 для ссылки на компонент не отображаемый (+: – Everyone

1

Похоже, что поток запускается раньше, чем компонент фактически отображается на экране. Чтобы этого не произошло, вы можете переопределить метод рисования (Graphics g) JPanel и поместить код в метод run() потока в методе рисования. В методах run() вашего потока просто вызовите repaint().

например:

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

и в методе 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(); 
    } 
} 
3

Я был точно такой же проблемой после того, как я попытался реализовать Doublebuffering для фрактального генератора. Мое решение: Я взял пример из книги, но изменил его (не зная последствий) таким образом, что я запустил createImage INSIDE конструктор. Это дало нулевой указатель.Тогда я положил это

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

внутри метода обновления, и это сработало !! Поскольку update вызывается ПОСЛЕ создания объекта.

2

Попробуйте переопределить метод addNotify() в JPanel, который вы распространяете. Это хорошее место для запуска вашей анимации, а не для конструктора. Не забудьте включить строку super.addNotify();

public void addNotify() { super.addNotify(); startGame(); }

удачи

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

} 
Смежные вопросы