我有以下代码,它作为游戏的一部分每10毫秒运行一次:
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);
}
}
问题是,即使在我尝试定义图像之后,它也会进入if语句,该语句检查Image是否为null。我环顾四周,如果GraphicsEnvironment.isHeadless()返回true,似乎createImage()将返回null。
我不明白isHeadless()方法的目的是什么,但我认为它可能与编译器或IDE有关,所以我尝试了两个,这两个都得到了同样的错误(Eclipse,和BlueJ的)。任何人都知道错误的来源是什么,以及我如何解决它?
提前致谢
乔纳森
............................................... ....................
编辑: 我正在使用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
希望这有助于清理一些事情, 乔纳森
答案 0 :(得分:3)
我通常使用BufferedImage。而不是createImage(...)。
答案 1 :(得分:3)
在我尝试为分形生成器实现Doublebuffering之后,我遇到了完全相同的问题。我的解决方案 我从一本书中拿了这个例子但是改变了它(不知道结果)我在构造函数中运行createImage INSIDE的方式。这产生了nullpointer。然后我把这个
if (_dbImage == null) {
_dbImage = createImage(getSize().width, getSize().height);
_dbGraphics = (Graphics2D)_dbImage.getGraphics();
}
在update-method中,它工作了!!因为在构造对象之后调用更新。
答案 2 :(得分:2)
根据java.awt.Component的文档,如果组件不可显示,createImage也可以返回null,这很可能是正在发生的事情。
对于您要执行的操作,您应该查看BufferedImage类,因为它与组件无关。
答案 3 :(得分:2)
尝试覆盖正在扩展的JPanel中的addNotify()方法。这是一个“启动”动画的好地方,而不是构造函数。确保包含super.addNotify();
行public void addNotify() { super.addNotify(); 开始游戏(); }
祝你好运
答案 4 :(得分:1)
看起来线程的启动时间早于组件实际显示在屏幕上。为了确保不会发生这种情况,您可以覆盖JPanel的paint(Graphics g)方法,并将代码放在paint方法中的线程run()方法中。在你的线程的run()方法中,只需调用repaint()。
e.g:
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();
}
}
答案 5 :(得分:0)
如果您在非GUI环境中运行(例如,在服务器或servlet容器中),isHeadless将仅返回true。
我相信你的问题在你的createImage方法本身。你能给我们更多的背景吗?正在调用哪个createImage方法以及它的实现是什么?
答案 6 :(得分:-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);
}
}