这个问题可能已经得到解答,但是我发现它们似乎没有用,其他人实际上没有做出任何改变。
我正在创建游戏,游戏中有一个位于窗口内的屏幕(Canvas)(JFrame)。在这个游戏中,我想使用鼠标,以及允许用户最大化窗口。无论如何,游戏屏幕都保持相同的大小,但如果窗口重新调整大小,那么我将游戏图像缩放到窗口的大小。
我的问题是我无法找到合适的方式投影鼠标的坐标,因为当窗口最大化时,其坐标仍然被读取,好像窗口仍然是正常大小,创建一个偏移。
我试过了:
@Override public void mouseMoved(MouseEvent e){
MOUSE_X = Math.round((float) e.getX() / (float) RenderableCanvas.oldSizeX * (float) f.getWidth());
MOUSE_Y = Math.round((float) e.getY() / (float) RenderableCanvas.oldSizeY * (float) f.getHeight());
}
其中MOUSE_X / MOUSE_Y是静态变量,可以在程序中的任何位置引用以获取鼠标位置。
和RenderableCanvas是游戏窗口,包含一个嵌入的画布对象,该类还跟踪窗口的原始大小,表示为oldSizeX和oldSizeY
最后f.getHeight()和f.getWidth()是帧的当前大小,因为f是对RenderableCanvas类内部JFrame的引用。
但所有这些都与:
相同@Override public void mouseMoved(MouseEvent e){
MOUSE_X = e.getX();
MOUSE_Y = e.getY();
}
提前感谢您的帮助。
答案 0 :(得分:1)
基本思想是你需要能够在两个坐标系之间进行转换,在这种情况下,是" world"这是缩放的空间和"视图"这是用户看到的(或类似的东西)
基本数学是使用默认值和当前值来生成一个百分比值,然后您可以通过该百分比将目标值多个,例如从视图转换到世界可能看起来像...
pointInView * (staticSize / currentSize)
所以,考虑到"世界"坐标,你需要缩小到"查看"坐标...
protected Point toView(int x, int y) {
return toView(new Point(x, y));
}
protected Point toView(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) getWidth() / (float) DEFAULT_WIDTH));
scaled.y = Math.round(p.y * ((float) getHeight() / (float) DEFAULT_HEIGHT));
return scaled;
}
给予"观看"坐标,你需要扩展到"世界"坐标...
protected Point toWorld(int x, int y) {
return toWorld(new Point(x, y));
}
protected Point toWorld(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) DEFAULT_WIDTH) / (float) getWidth());
scaled.y = Math.round(p.y * ((float) DEFAULT_HEIGHT) / (float) getHeight());
return scaled;
}
因此,例如,当您在"视图"上移动或点击鼠标时,您可以使用
Point world = toWorld(e.getPoint());
将鼠标点转换为世界坐标
...请随意重命名以满足您自己的需求,但基本上,视图是用户看到的物理视图,是您对该视图的虚拟概念......
基本概念适用于Dimension
,并且扩展名为Rectangle
......
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
protected static final int DEFAULT_WIDTH = 200;
protected static final int DEFAULT_HEIGHT = 200;
private Dimension preferredSize = new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
private JLabel properties;
private boolean highlighted = false;
private Rectangle hoverRect = new Rectangle(10, 10, 50, 50);
public TestPane() {
setLayout(new GridBagLayout());
properties = new JLabel("...");
add(properties);
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Point world = toWorld(e.getPoint());
highlighted = hoverRect.contains(world);
repaint();
properties.setText("<html>@" + format(e.getPoint())
+ "<br>world = " + format(world)
+ "<br>view = " + format(toView(world)));
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
preferredSize = new Dimension(DEFAULT_WIDTH * 2, DEFAULT_HEIGHT * 2);
SwingUtilities.windowForComponent(TestPane.this).pack();
}
});
}
protected String format(Point p) {
return p.x + "x" + p.y;
}
protected Point toView(int x, int y) {
return toView(new Point(x, y));
}
protected Point toView(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) getWidth() / (float) DEFAULT_WIDTH));
scaled.y = Math.round(p.y * ((float) getHeight() / (float) DEFAULT_HEIGHT));
return scaled;
}
protected Point toWorld(int x, int y) {
return toWorld(new Point(x, y));
}
protected Point toWorld(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) DEFAULT_WIDTH) / (float) getWidth());
scaled.y = Math.round(p.y * ((float) DEFAULT_HEIGHT) / (float) getHeight());
return scaled;
}
protected Rectangle toWorld(Rectangle bounds) {
return toWorld(bounds.x, bounds.y, bounds.width, bounds.height);
}
protected Rectangle toWorld(int x, int y, int width, int height) {
Rectangle scaled = new Rectangle();
scaled.setLocation(toWorld(x, y));
scaled.width = Math.round(width * ((float) DEFAULT_WIDTH / (float) getWidth()));
scaled.height = Math.round(height * ((float) DEFAULT_HEIGHT / (float) getHeight()));
return scaled;
}
protected Rectangle toView(Rectangle bounds) {
return toView(bounds.x, bounds.y, bounds.width, bounds.height);
}
protected Rectangle toView(int x, int y, int width, int height) {
Rectangle scaled = new Rectangle();
scaled.setLocation(toView(x, y));
scaled.width = Math.round(width * ((float) getWidth() / (float) DEFAULT_WIDTH));
scaled.height = Math.round(height * ((float) getHeight() / (float) DEFAULT_HEIGHT));
return scaled;
}
@Override
public Dimension getPreferredSize() {
return preferredSize;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = toView(hoverRect);
if (highlighted) {
g2d.setColor(Color.BLUE);
g2d.fill(bounds);
}
g2d.setColor(Color.BLACK);
g2d.draw(bounds);
}
}
}
答案 1 :(得分:0)
所以我认为我已经得到了它,我做了一些旧的笔和纸数学,并意识到我的方程式部分已经从我认为应该有的部分翻转过来。
这似乎有效:
@Override public void mouseMoved(MouseEvent e){
MOUSE_X = (int) ((float) e.getX() / (float) f.getWidth() * (float) RenderableCanvas.oldSizeX);
MOUSE_Y = (int) ((float) e.getY() / (float) f.getHeight() * (float) RenderableCanvas.oldSizeY);
}