投影鼠标坐标

时间:2016-02-29 07:34:57

标签: java swing canvas

这个问题可能已经得到解答,但是我发现它们似乎没有用,其他人实际上没有做出任何改变。

我正在创建游戏,游戏中有一个位于窗口内的屏幕(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();
}

提前感谢您的帮助。

2 个答案:

答案 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 ......

Scaled World View

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);
}