如果我没有把题目写得很好,很抱歉,让我来解释一下。
我正在创建一个游戏,实际上有几个,而且我看到在大多数情况下,我使用JPanel进行绘画,所以我去找了一种很好的绘画方法(即,当绘制多个精灵等时,它具有很好的性能)参见这里:https://stackoverflow.com/questions/1963494/java-2d-game-graphics。我在我自己的GameJPanel中实现了这一点,这将允许我在游戏JPanel
s上画画时始终保持性能。现在,我在绘图时添加了setDoubleBuffered(true)
和RenderHints这样的方法:
if (isTextRenderHintsOn()) {
bg.setRenderingHints(textRenderHints);
}
if (isImageRenderHintsOn()) {
bg.setRenderingHints(imageRenderHints);
}
if (isColorRenderHintsOn()) {
bg.setRenderingHints(colorRenderHints);
}
if (isInterpolationRenderHintsOn()) {
bg.setRenderingHints(iterpolationRenderHints);
}
if (isRenderHintsOn()) {
bg.setRenderingHints(renderHints);
}
现在,不去其他图书馆等,我还能做些什么来调整JPanel
s的质量和性能?
可能还需要了解一下,我使用GraphicsEnviroment
并将JFrame
与JPanel
设置为全屏,以便通过缓冲区策略(不是swing中的链接性能绘图也使用了一些很好的技术)获得硬件加速映像,下面是一个实现Java2D游戏图形链接方法和呈现提示的GameDrawLibrary
示例,FullScreen
类将用于设置全屏模式,测试驱动程序就是:):
测试司机:
import java.awt.BorderLayout;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
* Test Driver
*
* @author David
*/
public class PureSwingPaintingTest extends JFrame {
static GameDrawLibrary gdl;
static Image image;
static final FullScreen fs = new FullScreen();
static int width = fs.getWidth(), height = fs.getHeight();
public PureSwingPaintingTest() {
setSize(width, height);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gdl.createPanel();//create the panel
JPanel panel = gdl.getPanel();
JButton button = new JButton("Exit");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
getContentPane().add(button, BorderLayout.SOUTH);
getContentPane().add(panel, BorderLayout.CENTER);
}
public static void main(String[] args) {
try {
image = ImageIO.read(new File("c:/chess.jpg")).getScaledInstance(width, height, Image.SCALE_SMOOTH);
} catch (IOException ex) {
ex.printStackTrace();
}
gdl = new GameDrawLibrary(width, height, true, true, true, true, true, true) {
@Override
void updateGame() {
//update logic here
}
@Override
void renderGame(Graphics2D g) {
g.drawImage(image, 0, 0, this);
}
};
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (fs.isSupported()) {
fs.setFullScreen(new PureSwingPaintingTest());
} else {
fs.emulateFullScreen(new PureSwingPaintingTest());
}
gdl.showPanel();
}
});
}
}
游戏JPanel类库:
import java.awt.*;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
abstract class GameDrawLibrary extends JPanel {
private int width;
private int height;
private int scale;
private boolean isRunning = true;
private Canvas canvas;
private BufferStrategy strategy;
private BufferedImage background;
private Graphics2D backgroundGraphics;
private Graphics2D graphics;
private GraphicsConfiguration config = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
//graphics quaultiy settings
private boolean textRenderHintsOn;
private boolean imageRenderHintsOn;
private boolean colorRenderHintsOn;
private boolean interpolationRenderHintsOn;
private boolean renderHintsOn;
private RenderingHints textRenderHints = new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
private RenderingHints imageRenderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
private RenderingHints colorRenderHints = new RenderingHints(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
private RenderingHints iterpolationRenderHints = new RenderingHints(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
private RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
public GameDrawLibrary() {
setIgnoreRepaint(true);
this.textRenderHintsOn = false;
this.imageRenderHintsOn = false;
this.colorRenderHintsOn = false;
this.interpolationRenderHintsOn = false;
this.renderHintsOn = false;
}
GameDrawLibrary(int width, int height) {
setIgnoreRepaint(true);
this.width = width;
this.height = height;
this.scale = 1;
this.textRenderHintsOn = false;
this.imageRenderHintsOn = false;
this.colorRenderHintsOn = false;
this.interpolationRenderHintsOn = false;
this.renderHintsOn = false;
}
GameDrawLibrary(int width, int height, int scale) {
setIgnoreRepaint(true);
this.width = width;
this.height = height;
this.scale = scale;
this.textRenderHintsOn = false;
this.imageRenderHintsOn = false;
this.colorRenderHintsOn = false;
this.interpolationRenderHintsOn = false;
this.renderHintsOn = false;
}
public GameDrawLibrary(int width, int height, boolean textRenderHintsOn, boolean imageRenderHintsOn, boolean colorRenderHintsOn, boolean interpolationRenderHintsOn, boolean renderHintsOn, boolean isDoubleBuffered) {
super(isDoubleBuffered);
setIgnoreRepaint(true);
this.width = width;
this.height = height;
this.scale = 1;
this.textRenderHintsOn = textRenderHintsOn;
this.imageRenderHintsOn = imageRenderHintsOn;
this.colorRenderHintsOn = colorRenderHintsOn;
this.interpolationRenderHintsOn = interpolationRenderHintsOn;
this.renderHintsOn = renderHintsOn;
}
public GameDrawLibrary(int width, int height, int scale, boolean textRenderHintsOn, boolean imageRenderHintsOn, boolean colorRenderHintsOn, boolean interpolationRenderHintsOn, boolean renderHintsOn, boolean isDoubleBuffered) {
super(isDoubleBuffered);
this.width = width;
this.height = height;
this.scale = scale;
this.textRenderHintsOn = textRenderHintsOn;
this.imageRenderHintsOn = imageRenderHintsOn;
this.colorRenderHintsOn = colorRenderHintsOn;
this.interpolationRenderHintsOn = interpolationRenderHintsOn;
this.renderHintsOn = renderHintsOn;
}
// Screen and buffer stuff
private Graphics2D getBuffer() {
if (graphics == null) {
try {
graphics = (Graphics2D) strategy.getDrawGraphics();
} catch (IllegalStateException e) {
return null;
}
}
return graphics;
}
private boolean updateScreen() {
graphics.dispose();
graphics = null;
try {
strategy.show();
Toolkit.getDefaultToolkit().sync();
return (!strategy.contentsLost());
} catch (NullPointerException | IllegalStateException e) {
return true;
}
}
// update game logic here
abstract void updateGame();
//paint stuff here
abstract void renderGame(Graphics2D g);
//create and return the already sized JFrame
public void createPanel() {
setSize(getRealWidth(), getRealHeight());
}
public void showPanel() {
// Canvas
canvas = new Canvas(config);
canvas.setSize(width * scale, height * scale);
add(canvas, 0);
// Background & Buffer
background = create(width, height, false);
canvas.createBufferStrategy(2);
do {
strategy = canvas.getBufferStrategy();
} while (strategy == null);
startThread();//start thread to draw to the canvas
}
private void startThread() {
new Thread(new Runnable() {
@Override
public void run() {
backgroundGraphics = (Graphics2D) background.getGraphics();
long fpsWait = (long) (1.0 / 30 * 1000);
main:
while (isRunning) {
long renderStart = System.nanoTime();
updateGame();
// Update Graphics
do {
Graphics2D bg = getBuffer();
if (isTextRenderHintsOn()) {
bg.setRenderingHints(textRenderHints);
}
if (isImageRenderHintsOn()) {
bg.setRenderingHints(imageRenderHints);
}
if (isColorRenderHintsOn()) {
bg.setRenderingHints(colorRenderHints);
}
if (isInterpolationRenderHintsOn()) {
bg.setRenderingHints(iterpolationRenderHints);
}
if (isRenderHintsOn()) {
bg.setRenderingHints(renderHints);
}
if (!isRunning) {
break main;
}
renderGame(backgroundGraphics); // this calls your draw method
// thingy
if (scale != 1) {
bg.drawImage(background, 0, 0, width * scale, height * scale, 0, 0, width, height, null);
} else {
bg.drawImage(background, 0, 0, null);
}
bg.dispose();
} while (!updateScreen());
// Better do some FPS limiting here
long renderTime = (System.nanoTime() - renderStart) / 1000000;
try {
Thread.sleep(Math.max(0, fpsWait - renderTime));
} catch (InterruptedException e) {
Thread.interrupted();
break;
}
// renderTime = (System.nanoTime() - renderStart) / 1000000;
}
}
}).start();
}
public JPanel getPanel() {
return this;
}
// create a hardware accelerated image
public final BufferedImage create(final int width, final int height, final boolean alpha) {
return config.createCompatibleImage(width, height, alpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE);
}
public void setColorRenderHintsOn(boolean colorRenderHintsOn) {
this.colorRenderHintsOn = colorRenderHintsOn;
}
public void setRenderHintsOn(boolean renderHintsOn) {
this.renderHintsOn = renderHintsOn;
}
public void setInterpolationRenderHintsOn(boolean interpolationRenderHintsOn) {
this.interpolationRenderHintsOn = interpolationRenderHintsOn;
}
public void setImageRenderHintsOn(boolean imageRenderHintsOn) {
this.imageRenderHintsOn = imageRenderHintsOn;
}
public void setTextRenderHintsOn(boolean textRenderHintsOn) {
this.textRenderHintsOn = textRenderHintsOn;
}
public boolean isColorRenderHintsOn() {
return colorRenderHintsOn;
}
public boolean isInterpolationRenderHintsOn() {
return interpolationRenderHintsOn;
}
public boolean isTextRenderHintsOn() {
return textRenderHintsOn;
}
public boolean isImageRenderHintsOn() {
return imageRenderHintsOn;
}
public boolean isRenderHintsOn() {
return renderHintsOn;
}
public int getRealHeight() {
return height * scale;
}
public int getRealWidth() {
return width * scale;
}
@Override
public int getHeight() {
return height;
}
@Override
public int getWidth() {
return width;
}
public int getScale() {
return scale;
}
public void setHeight(int height) {
this.height = height;
}
public void setWidth(int width) {
this.width = width;
}
public void setScale(int scale) {
this.scale = scale;
}
}
全屏课程:
import java.awt.Dimension;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import javax.swing.JFrame;
/**
*
* @author David
*/
public class FullScreen {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
Dimension screenSize;
public FullScreen() {
screenSize = Toolkit.getDefaultToolkit().getScreenSize();
}
public void setFullScreen(JFrame frame) {
if (gs.getFullScreenWindow() == null) {
frame.dispose();
frame.setUndecorated(true);
gs.setFullScreenWindow(frame);
frame.setVisible(true);
} else {// back to windowed mode
emulateFullScreen(frame);
}
}
public void emulateFullScreen(JFrame frame) {
frame.dispose();
frame.setUndecorated(false);
gs.setFullScreenWindow(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(screenSize);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public int getWidth() {
return gs.getDisplayMode().getWidth();
}
public int getHeight() {
return gs.getDisplayMode().getHeight();
}
public boolean isSupported() {
return gs.isFullScreenSupported();
}
}
发布于 2012-08-08 08:10:27
这是一段相当有趣的代码,当我有更多的时间时,我会更喜欢阅读它;)
关于唯一的事情跳出我是你是如何缩放你的图形。在讨论http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html和一些替代算法时,我建议阅读一下getScaledInstance
。
除此之外,我几年前被告知,你可以通过将图像缩小4来伪造反混叠。也就是说,如果你想要一个800*600的图像输出,你需要从一个4倍大小的图像开始,然后缩小它,这将产生一个“假的”反混叠,不依赖于硬件渲染。
这也许不再成立,但对你来说可能是有价值的。
https://codereview.stackexchange.com/questions/14460
复制相似问题