2016-02-29 4 views
0

На этот вопрос, вероятно, был дан ответ, но из тех, которые я нашел, они не работают, другие фактически не вносят никаких изменений.Проецирование координат мыши

Я создаю игру, в игре есть экран (холст), который находится внутри окна (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 является ссылкой на JFrame внутри класса RenderableCanvas.

, но все, что делает то же самое, как:

@Override public void mouseMoved(MouseEvent e){ 
    MOUSE_X = e.getX(); 
    MOUSE_Y = e.getY(); 
} 

Спасибо за любую помощь заранее.

+0

Я любопытно, что '' oldSizeX' и oldSizeY' является, являются постоянным представлением, что в масштабе 1: 1? – MadProgrammer

+0

oldSizeX и oldSizeY в основном являются стандартным размером окна, поэтому, скажем, если бы я должен был создать окно с разрешением 640x480, то oldSizeX и oldSizeY будут такими значениями, и они останутся неизменными, даже если окно будет перезаписано, размером 1280x200. так да. –

ответ

1

Основная идея заключается в том что вам нужно, чтобы иметь возможность конвертировать между двумя системами координат, в данном случае, «мир», который является пространством получения масштабируется и " вид ", который пользователь видит (или что-то в этом роде)

Базовая математика состоит в том, чтобы использовать значение по умолчанию и текущее значение для генерирования процентного значения, с помощью которого вы можете затем умножить целевое значение, например конвертировать из представления в мир может выглядеть так ...

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

    } 

} 
+0

Спасибо, если вы сами это поняли, по какой-то причине ваш ответ не появится на моем ПК, но будет на моем телефоне. –

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); 
} 
Смежные вопросы