我正在尝试用Java制作2D游戏,但是当我在线程中调用repaint()方法时,会有一个奇怪的仅灰色窗口。
这是我到目前为止的源代码:
package spaceshooter;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Spaceshooter extends JFrame implements KeyListener, Runnable {
private Player player = new Player(5, 186, this);
private boolean up, down;
public Spaceshooter(String title) {
super(title);
this.setFocusable(true);
this.addKeyListener(this);
}
@Override
public void paint(Graphics gr) {
super.paint(gr);
gr.setColor(Color.BLACK);
gr.fillRect(0, 0, 800, 500);
player.paintPlayer(gr);
}
public static void main(String[] args) {
Spaceshooter shooter = new Spaceshooter("Spaceshooter");
new Thread(shooter).start();
shooter.setSize(800,500);
shooter.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
shooter.setVisible(true);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 38) {
up = true;
down = false;
} else if (e.getKeyCode() == 40) {
down = true;
up = false;
}
}
@Override
public void keyReleased(KeyEvent e) {
down = false;
up = false;
}
@Override
public void run() {
while(true) {
if (up) {
player.moveUp();
} else if (down) {
player.moveDown();
}
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
Logger.getLogger(Spaceshooter.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
package spaceshooter;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Toolkit;
public class Player {
private int x, y;
private Component comp;
public Player(int x, int y, Component comp) {
this.x = x;
this.y = y;
this.comp = comp;
}
public void moveUp() {
y -= 5;
}
public void moveDown() {
y += 5;
}
public void paintPlayer(Graphics gr) {
gr.drawImage(Toolkit.getDefaultToolkit().getImage("images/player.png"), x, y, comp);
}
}
预先感谢您的答复!
什么是EDT?
Swing事件处理代码在称为事件调度线程的特殊线程上运行。大多数调用Swing方法的代码也都在此线程上运行。这是必需的,因为大多数Swing对象方法都不是“线程安全的”。所有与GUI相关的任务,必须在EDT上进行绘画过程的同时对GUI进行任何更新,这涉及将请求包装在事件中并将其处理到上EventQueue
。然后,将事件从队列中的同一队列中逐一分派,即先入先出。就是说,如果也就是说,如果
Event A
排队到EventQueue
之前,Event B
则事件B将不会在事件A之前分派。
您执行的所有任务可能需要一段时间,可能会阻塞EDT,不会发生调度,不会进行任何更新,因此您的应用程序将冻结。您将不得不杀死它以摆脱这种冻结状态。
在您的程序中,除了创建您的代码JFrame
并使之从主线程可见(我们也不应该这样做):
while(true) {
if (up) {
player.moveUp();
} else if (down) {
player.moveDown();
}
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
Logger.getLogger(Spaceshooter.class.getName()).log(Level.SEVERE, null, ex);
}
}
您正在repaint()
从该线程发布请求,该线程紧随其后发送到睡眠状态。
SwingUtilities.invokeLater():
Swing提供了一个很好的功能SwingUtilities.invokeLater(new Runnable(){})
,repaint
可以将请求发布到EDT。您要做的就是写:
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
repaint();
}
});
现在要提些其他事情:
Runnable
。创建另一个类Runnable
,在其中进行计算,然后用于SwingUtilities
发布组件更新请求。JFrame
直接在其上进行定制绘画。JFrame是顶级组件。它更像是一个包含整个应用程序的容器。如果要自定义绘画,请使用自定义组件MyCanvas extends JComponent
。paint()
功能。相反,paintComponent(g)
它将很好地满足我们自定义绘画的目的。教程资源和参考:
我正在写一个简单的mandelbrot渲染器。在程序计算并绘制所有内容后,它将保存曲面并进行blits。这很好,但在我添加了更新显示功能后,它只显示一个黑屏。我需要更新每次迭代,因为我将添加一些文本和其他内容。我只包括了节目的重要部分。有人知道为什么会这样吗?
我正在开发一个基于2D图块的游戏,其中所有图块旋转45度。 我想这样做: 原因是为了在2D游戏中创建不同的视角。 有相当多的基于瓷砖的游戏教程,但我不知道有像这样的旋转瓷砖。 所以我的问题是:如何创建旋转45度的瓷砖?我会感谢任何代码或链接。 编辑:忘了说我用的是Java Graphics2D,不是OpenGL
我正在用pyplay写一个蛇游戏,但我只是提示一个黑色的窗口没有任何错误。 我检查了类似的问题,他们错误地使用了screen对象。然而,这里的情况似乎不是这样,因为它只创建了一次? 知道我做错了什么吗?因为我没有收到任何错误信息,所以我不明白为什么只显示一个黑屏。按键输入事件工作正常。
卡洛斯·巴罗斯 编辑:也许我应该这么说,但这个游戏是一个类似反击或英雄联盟的游戏,我没有做这个游戏。
我试图允许调整这个应用程序的大小,我把可调整大小的标志,但当我试图调整大小,它搞砸了!试试我的代码。 这是一个网格程序,当窗口调整大小时,我希望网格也调整大小/缩小。 请告诉我怎么了,谢谢。