Java 使用多个类渲染矩形
我正在做一个简单的游戏项目,当我试图创建一个在屏幕上移动的矩形时遇到了一个问题。 以下是主要课程: `公共类Main扩展画布实现Runnable{Java 使用多个类渲染矩形,java,graphics,Java,Graphics,我正在做一个简单的游戏项目,当我试图创建一个在屏幕上移动的矩形时遇到了一个问题。 以下是主要课程: `公共类Main扩展画布实现Runnable{ private static final long serialVersionUID = 1L; private JFrame frame; boolean running = false; Graphics g; static int HEIGHT = 500; static int WIDTH = HEIGHT * 16 / 9; Sou
private static final long serialVersionUID = 1L;
private JFrame frame;
boolean running = false;
Graphics g;
static int HEIGHT = 500;
static int WIDTH = HEIGHT * 16 / 9;
SoundHandler sh = new SoundHandler();
//Game state manager
private GameStateManager gsm;
public Main()
{
//window
frame = new JFrame("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(this, BorderLayout.CENTER);
frame.pack();
frame.setSize(WIDTH, HEIGHT);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
init();
}
void init()
{
gsm = new GameStateManager();
sh.playMusic("Undertale.wav", 1);
}
public synchronized void start(){
running = true;
new Thread(this).start();
}
public synchronized void stop(){
running = false;
}
//game loop
public void run()
{
//init time loop variables
long lastLoopTime = System.nanoTime();
final int TARGET_FPS = 60;
final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;
double lastFpsTime = 0;
int fps = 0;
while(running)
{
//work out how long its been since last update
//will be used to calculate how entities should
//move this loop
long now = System.nanoTime();
long updateLength = now - lastLoopTime;
lastLoopTime = now;
double delta = updateLength / ((double)OPTIMAL_TIME);
//update frame counter
lastFpsTime += updateLength;
fps++;
//update FPS counter
if(lastFpsTime >= 1000000000)
{
System.out.println("FPS " + fps);
lastFpsTime = 0;
fps = 0;
}
//game updates
update(delta);
//draw
draw(g);
try{
Thread.sleep((lastLoopTime - System.nanoTime() + OPTIMAL_TIME)/1000000 );
}catch(InterruptedException e){
System.out.println("Error in sleep");
}
}
}
private void update(double delta)
{
//updates game state code
gsm.update(delta);
}
public void draw(Graphics g)
{
gsm.draw(g);
}`
这是我想用来画矩形的类
package me.mangodragon.gamestate;
导入java.awt.Graphics
公共类主体扩展了游戏状态{
int x;
public MainState(GameStateManager gsm){
this.gsm = gsm;
}
public void init() {
}
public void update(double delta) {
x += 2 * delta;
}
public void draw(Graphics g) {
g.drawRect(x, 0, 50, 50);
g.dispose();
}
public void keyPressed(int k) {
}
public void keyReleased(int k) {
}
}
我不断地发现这个错误:
Exception in thread "Thread-4" java.lang.NullPointerException
at me.mangodragon.gamestate.MainState.draw(MainState.java:22)
at me.mangodragon.gamestate.GameStateManager.draw(GameStateManager.java:37)
at me.mangodragon.main.Main.draw(Main.java:118)
at me.mangodragon.main.Main.run(Main.java:100)
at java.lang.Thread.run(Unknown Source)
我试图修复它,但找不到问题所在
谢谢!您将
g
定义为:
Graphics g;
但从来没有给它一个价值
无论如何,这不是绘制形状的方式。相反,在类Main
中重写paint方法(从画布继承):
@Override
public void paint(Graphics2D g) {
//Drawing code goes in here. This runs whenever the Canvas is rendered.
}
然后,当您想要更新它时,例如在while
循环中,运行
this.repaint(); //note that this doesn't take arguments
如果要在另一个类中使用draw(Graphics g)
方法,请在paint()
中调用它
你从来没有给
g
(Graphics
)分配过任何东西。现在,在你跑开并试图弄清楚怎么做之前,我强烈建议你去掉这个变量,它会给你带来太多问题
通常,当系统希望绘制组件时,它会调用paint
方法,并向您传递它希望您绘制的Graphics
上下文。这种方法称为被动绘制,因为绘制请求随机出现,而这并不是您真正想要的。另一个问题是java.awt.Canvas
不是双缓冲的,这将导致组件更新时出现闪烁
您可能需要查看和了解更多详细信息
您可以使用JPanel
,它是双缓冲的,但是使用java.awt.Canvas
的主要原因是您可以使用API。这不仅提供了双缓冲,还提供了一种方法,您可以通过它直接控制绘制过程(或活动绘制)
有关更多详细信息,请参见和。问题在于您尚未定义
g
,因此它为空。在大多数情况下,您永远不应该创建新的图形
对象,而是从某处获取它
由于您继承的是画布
,因此可以非常轻松地完成此操作
首先,您应该将draw
方法更改为这样
private void draw() {
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
// Draw your game here, using the g declared above
g.dispose();
bs.show();
}
前几行创建了一个名为BufferStrategy
的东西,您可以阅读更多关于它的内容,但它本质上允许Java提前渲染接下来的几帧,这样您就不会看到任何闪烁
从BufferStrategy
中,您可以获得要绘制的图形
对象
最后,您必须处理
图形
对象,然后显示缓冲区
,这样您所做的一切都会显示在屏幕上。为什么技术上正确,使用画布的原因是您可以使用缓冲区策略,它可以直接控制绘制过程并提供双缓冲区ing,这不包括使用您建议的方法。所以答案是,要么使用JPanel(和paintComponent),要么使用BufferStratgeyOh,对吧,我更习惯使用JPanel而不是Canvas。对此我深表歉意!@MadProgrammer
private void draw() {
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
// Draw your game here, using the g declared above
g.dispose();
bs.show();
}