gpt4 book ai didi

java - 如何使用大小调整所有Graphics2D

转载 作者:行者123 更新时间:2023-12-02 08:55:16 27 4
gpt4 key购买 nike

在Java中,如何使游戏完全实现!但是逻辑和图形可以使用吗?我尝试使用SCALE方法。但这并不能为每台计算机提供完美的全屏显示。所以我做了这个:

    public void resize(int WIDTH, int HEIGHT, boolean UNDECORATED) {

frame.setPreferredSize(new Dimension(WIDTH, HEIGHT));
frame.setMaximumSize(new Dimension(WIDTH, HEIGHT));
frame.setMinimumSize(new Dimension(WIDTH, HEIGHT));

this.WIDTH = WIDTH;
this.HEIGHT = HEIGHT;
frame.setUndecorated(UNDECORATED);
frame.setSize(WIDTH, HEIGHT);
}


因此,您可以将屏幕大小设置为任意大小!它可以工作,但是图形不能工作吗? Graphics2D中是否可以拉伸所有图形以使其适合?例如,如果存在类似的方法:

            G2D.resize(WIDTH, HEIGHT, Image.NEAREST_PARENT_RESCALE);


任何想法?

我尝试过的事情:


将所有图形绘制为一个缓冲图像,然后将该图像绘制到屏幕尺寸上。
仅使用SCALE并执行WIDTH * SCALE等。
很多数学


我不介意的事情


如果您有WIDE-SCREEN,它会将graphic2D对象拉伸到该大小。
如果有SQUARE-SCREEN,则将graphics2D对象压缩到该大小。


因此,如何使用Graphics2D,JFrame制作一款可重新密封的游戏。

最佳答案

以最通用的形式,可以将其视为图形编程的经典问题,即从世界坐标到屏幕坐标的转换。您的世界坐标系中有一个大小为“ 1.0 x 1.0”的对象(无论该对象具有哪个单位)。并且应该绘制该对象,使其在屏幕上的大小为“ 600像素* 600像素”。

概括地说,在Swing中至少有三个选项可以实现此目的:


您可以绘制成图像,然后绘制图像的缩放版本
您可以绘制成比例的Graphics2D对象
您可以绘制比例对象


每种方法都有可能的优点和缺点以及隐藏的警告。

绘制成图像,然后绘制图像的缩放版本:

这看起来像是一个简单的解决方案,但有潜在的缺点:图像本身具有一定的分辨率(大小)。如果图像太小,并且您正在放大以填满整个屏幕,则它可能会显得块状。如果图像太大,并且您将其缩小以适合屏幕,则图像的像素可能会丢失。

在这两种情况下,都有用于缩放图像的几个调整参数。实际上,缩放图像比乍一看要棘手得多。有关详细信息,请参阅Chris Campbell的文章The Perils of Image.getScaledInstance()

绘制成比例的Graphics2D对象

Graphics2D class已经提供了创建世界坐标系和屏幕坐标系之间的转换所必需的全部功能。这是通过Graphics2D类通过内部存储AffineTransform(描述此转换)来完成的。该AffineTransform可以直接通过Graphics2D对象进行修改:

void paintSomething(Graphics2D g) {
...
g.draw(someShape);

// Everything that is painted after this line will
// be painted 3 times as large:
g.scale(3.0, 3.0);

g.draw(someShape); // Will be drawn larger
}


必须采取一些措施来正确管理存储在 Graphics2D对象中的转换。通常,应该在应用其他转换之前创建原始 AffineTransform的备份,然后再恢复该原始转换:

// Create a backup of the original transform
AffineTransform oldAT = g.getTransform();

// Apply some transformations
g.scale(3.0, 4.0);
g.translate(10.0, 20.0);

// Do custom painting the the transformed graphics
paintSomething(g):

// Restore the original transformation
g.setTransform(oldAT);


(关于最后一种方法的另一条建议:不应使用 Graphics2D#setTransform方法在现有变换之上应用新的坐标变换。它仅用于还原“旧”变换,如本示例所示(在该方法的文档))。

使用 Graphics2D类进行缩放的一个潜在缺点是,之后,所有内容都会进行缩放。特别是,此缩放比例还将影响线宽(即 Stroke的宽度)。例如,考虑如下调用序列:

// By default, this will paint a line with a width (stroke) of 1.0:
g.draw(someLine);

// Apply some scaling...
g.scale(10.0, 10.0);

// Now, this will paint the same line, but with a width of 10.
g.draw(someLine);


第二次调用将导致绘制一条10像素宽的线。在许多情况下,这可能是不希望的。使用第三个替代方法可以避免这种效果:

绘制比例对象

世界坐标系和屏幕坐标系之间的转换也可以手动维护。将其表示为 AffineTransform很方便。 AffineTransform类可用于创建 Shape对象的转换版本,然后可以将其直接绘制到(未转换的) Graphics2D对象中。这是通过 AffineTransform#createTransformedShape方法完成的:

void paintSomething(Graphics2D g) {
...
// Draw some shape in its normal size
g.draw(someShape);

// Create a scaling transform
AffineTransform at = AffineTransform.getScaleInstance(3.0, 3.0);

// Create a scaled version of the shape
Shape transformedShape = at.createTransformedShape(someShape);

// Draw the scaled shape
g.draw(transformedShape);
}


这可能是最通用的方法。唯一的潜在缺点是,当绘制许多小的简单形状时,这将导致创建许多小的临时变形形状,从而可能导致性能降低。 (有许多方法可以缓解此问题,但是详细的性能考虑和优化超出了此答案的范围)。



摘要

下面的图像显示了所有方法的比较。绘制了一些示例对象(表示为 Shape对象)。每行比较上述三种不同的缩放方法。使用其“默认”大小,对象将在世界坐标中填充大小为100x100的矩形。在前两行中,它们按比例放大以填充屏幕上190x190像素的区域。在最后两行中,将它们按比例缩小以填充屏幕上60x60像素的区域。 (选择这些大小是为了使“奇数”缩放因子为1.9和0.6。当缩放因子为整数或正好为0.5时,可能不会出现某些效果(伪像)。

对于放大和缩小,还需要在“标准”绘画方式和“高质量”绘画之间进行比较(由每个面板的标题中的“(HQ)”表示)。这里的“高质量”只是意味着渲染提示

KEY_ANTIALIAS = VALUE_ANTIALIAS_ON
KEY_RENDERING = VALUE_RENDER_QUALITY


已设置:



这是对应的程序,为 MCVE

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ScalingMethodComparison
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new GridLayout(0,1));

Dimension larger = new Dimension(190,190);
Dimension smaller = new Dimension(60,60);

f.getContentPane().add(createPanel(larger, false));
f.getContentPane().add(createPanel(larger, true));
f.getContentPane().add(createPanel(smaller, false));
f.getContentPane().add(createPanel(smaller, true));

f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}

private static JPanel createPanel(Dimension d, boolean highQuality)
{
JPanel p = new JPanel(new GridLayout(1,3));
for (ScalingMethodComparisonPanel.ScalingMethod scalingMethod :
ScalingMethodComparisonPanel.ScalingMethod.values())
{
p.add(createPanel(d, scalingMethod, highQuality));
}
return p;
}

private static JPanel createPanel(
Dimension d, ScalingMethodComparisonPanel.ScalingMethod scalingMethod,
boolean highQuality)
{
JPanel p = new JPanel(new GridLayout(1,1));
p.setBorder(BorderFactory.createTitledBorder(
scalingMethod.toString()+(highQuality?" (HQ)":"")));
JPanel scalingMethodComparisonPanel =
new ScalingMethodComparisonPanel(
createObjects(), d, scalingMethod, highQuality);
p.add(scalingMethodComparisonPanel);
return p;
}

// Returns a list of objects that should be drawn,
// occupying a rectangle of 100x100 in WORLD COORDINATES
private static List<Shape> createObjects()
{
List<Shape> objects = new ArrayList<Shape>();
objects.add(new Ellipse2D.Double(10,10,80,80));
objects.add(new Rectangle2D.Double(20,20,60,60));
objects.add(new Line2D.Double(30,30,70,70));
return objects;
}
}


class ScalingMethodComparisonPanel extends JPanel
{
private static final Color COLORS[] = {
Color.RED, Color.GREEN, Color.BLUE,
};

enum ScalingMethod
{
SCALING_IMAGE,
SCALING_GRAPHICS,
SCALING_SHAPES,
}

private final List<Shape> objects;
private final ScalingMethod scalingMethod;
private final boolean highQuality;

private final Dimension originalSize = new Dimension(100,100);
private final Dimension scaledSize;

private BufferedImage image;

public ScalingMethodComparisonPanel(
List<Shape> objects,
Dimension scaledSize,
ScalingMethod scalingMethod,
boolean highQuality)
{
this.objects = objects;
this.scaledSize = new Dimension(scaledSize);
this.scalingMethod = scalingMethod;
this.highQuality = highQuality;
}

@Override
public Dimension getPreferredSize()
{
return new Dimension(scaledSize);
}

@Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
g.setColor(Color.WHITE);
g.fillRect(0,0,getWidth(), getHeight());

if (highQuality)
{
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(
RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
}

if (scalingMethod == ScalingMethod.SCALING_IMAGE)
{
paintByScalingImage(g);
}
else if (scalingMethod == ScalingMethod.SCALING_GRAPHICS)
{
paintByScalingGraphics(g);
}
else if (scalingMethod == ScalingMethod.SCALING_SHAPES)
{
paintByScalingShapes(g);
}
}

private void paintByScalingImage(Graphics2D g)
{
if (image == null)
{
image = new BufferedImage(
originalSize.width, originalSize.height,
BufferedImage.TYPE_INT_ARGB);
}
Graphics2D ig = image.createGraphics();
paintObjects(ig, null);
ig.dispose();

g.drawImage(image, 0, 0, scaledSize.width, scaledSize.height, null);
}

private void paintByScalingGraphics(Graphics2D g)
{
AffineTransform oldAT = g.getTransform();
double scaleX = (double)scaledSize.width / originalSize.width;
double scaleY = (double)scaledSize.height / originalSize.height;
g.scale(scaleX, scaleY);
paintObjects(g, null);
g.setTransform(oldAT);
}

private void paintByScalingShapes(Graphics2D g)
{
double scaleX = (double)scaledSize.width / originalSize.width;
double scaleY = (double)scaledSize.height / originalSize.height;
AffineTransform at =
AffineTransform.getScaleInstance(scaleX, scaleY);
paintObjects(g, at);
}



private void paintObjects(Graphics2D g, AffineTransform at)
{
for (int i=0; i<objects.size(); i++)
{
Shape shape = objects.get(i);
g.setColor(COLORS[i%COLORS.length]);
if (at == null)
{
g.draw(shape);
}
else
{
g.draw(at.createTransformedShape(shape));
}
}
}
}

关于java - 如何使用大小调整所有Graphics2D,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27439225/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com