好的,我的智慧结束了。我正在尝试创建一个小的等距瓷砖地图,它比屏幕更大,我可以通过鼠标拖动来修改。 我得到了正确的绘图(我认为),我得到了拖动工作,似乎无法让鼠标正确选择。 我已经做到这一点,我得到了几乎正确的瓷砖,但它的大约一半的瓷砖大小,我找不到弥补该偏移量的方法。
以下是代码:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MapView {
public static void main(String[] args) {
JFrame test = new JFrame("IsoView");
test.setSize(800, 600);
MapViewPane pane = new MapViewPane();
test.getContentPane().setLayout(new BorderLayout());
test.getContentPane().add(pane, BorderLayout.CENTER);
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test.setVisible(true);
}
private static class MapViewPane extends JPanel
implements MouseMotionListener, MouseListener {
private BufferedImage BackImage;
BufferedImage GrassTile, SelectedBorder;
private Point MousePoint, PrevView, ViewLocation, Selected;
private boolean Dragging;
private int mapwidth, mapheight, tilecount;
public MapViewPane() {
super();
this.setOpaque(true);
createAssets();
tilecount = 30;
mapwidth = GrassTile.getWidth() * tilecount;
mapheight = GrassTile.getHeight() * tilecount;
ViewLocation = new Point(0, mapheight / 2);
Selected = new Point(-1, -1);
addMouseListener(this);
addMouseMotionListener(this);
}
private void createAssets() {
GraphicsConfiguration gc =
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
GrassTile = gc.createCompatibleImage(128,
64, Transparency.TRANSLUCENT);
Graphics g = GrassTile.getGraphics();
Polygon poly = new Polygon();
poly.addPoint(0, 32);
poly.addPoint(64, 0);
poly.addPoint(128, 32);
poly.addPoint(64, 64);
g.setColor(Color.GREEN);
g.fillPolygon(poly);
g.setColor(Color.BLUE);
g.drawPolygon(poly);
g.dispose();
SelectedBorder = gc.createCompatibleImage(128,
64, Transparency.TRANSLUCENT);
g = SelectedBorder.getGraphics();
g.setColor(Color.red);
g.drawPolygon(poly);
g.dispose();
}
@Override
public void paint(Graphics g) {
//super.paint(g);
Rectangle visiblerec = this.getVisibleRect();
g.setColor(Color.BLACK);
g.fillRect(visiblerec.x, visiblerec.y,
visiblerec.width, visiblerec.height);
checkBackImage();
Graphics bg = BackImage.getGraphics();
drawGrassGrid(bg);
bg.dispose();
g.drawImage(BackImage, 0, 0, this);
}
private void drawGrassGrid(Graphics g) {
int dx = 0;
int dy = 0;
g.setColor(Color.BLACK);
g.fillRect(0, 0, BackImage.getWidth(), BackImage.getHeight());
for (int x = 0; x < tilecount; x++) {
for (int y = 0; y < tilecount; y++) {
dx = x * GrassTile.getWidth() / 2
- y * GrassTile.getWidth() / 2;
dy = x * GrassTile.getHeight() / 2
+ y * GrassTile.getHeight() / 2;
dx -= ViewLocation.x;
dy -= ViewLocation.y;
g.drawImage(GrassTile, dx, dy, this);
if ((x == Selected.x) && (y == Selected.y)) {
g.drawImage(SelectedBorder, dx, dy, this);
}
g.drawString("(" + x + "," + y + ")", dx, dy
+ GrassTile.getHeight() / 2);
}
}
}
private void checkBackImage() {
if ((BackImage == null) || (BackImage.getWidth() != this.getWidth())
|| (BackImage.getHeight() != this.getHeight())) {
GraphicsConfiguration gc =
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
BackImage = gc.createCompatibleImage(this.getWidth(),
this.getHeight(), Transparency.BITMASK);
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (Dragging) {
ViewLocation.x = PrevView.x + MousePoint.x - e.getX();
ViewLocation.y = PrevView.y + MousePoint.y - e.getY();
if (ViewLocation.x < -mapwidth / 2) {
ViewLocation.x = -mapwidth / 2;
}
if (ViewLocation.y < -mapheight / 2 + this.getHeight()) {
ViewLocation.y = -mapheight / 2 + this.getHeight();
}
if (ViewLocation.x > mapwidth / 2 - this.getWidth()
+ GrassTile.getWidth()) {
ViewLocation.x = mapwidth / 2 - this.getWidth()
+ GrassTile.getWidth();
}
if (ViewLocation.y > mapheight / 2 + this.getHeight()) {
ViewLocation.y = mapheight / 2 + this.getHeight();
}
repaint();
}
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
if (!Dragging) {
int x = (GrassTile.getWidth() * (e.getY() + ViewLocation.y)
+ GrassTile.getHeight() * (e.getX() + ViewLocation.x))
/ (GrassTile.getWidth() * GrassTile.getHeight());
int y = (GrassTile.getWidth() * (e.getY() + ViewLocation.y)
- GrassTile.getHeight() * (e.getX() + ViewLocation.x))
/ (GrassTile.getWidth() * GrassTile.getHeight());
// int x = (int) Math.floor((e.getY() + ViewLocation.y)
// / (double) GrassTile.getHeight() - (e.getX() + ViewLocation.x)
// / (double) GrassTile.getWidth());
// int y = (int) Math.floor((e.getY() + ViewLocation.y)
// / (double) GrassTile.getHeight() + (e.getX() + ViewLocation.x)
// / (double) GrassTile.getWidth());
Selected.setLocation(x, y);
repaint();
System.out.println("(" + x + "," + y + ")");
}
}
@Override
public void mousePressed(MouseEvent e) {
if ((e.getButton() == MouseEvent.BUTTON1) && !Dragging) {
MousePoint = e.getPoint();
PrevView = new Point(ViewLocation);
Dragging = true;
}
}
@Override
public void mouseReleased(MouseEvent e) {
Dragging = false;
MousePoint = null;
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
}
我在click方法中注释了一些我试过的公式,但是它们不起作用(x和y轴是这样颠倒的,还没有试图找出原因)。 如果有人可以指出我正在制造的错误,真的会感激不尽。
答案 0 :(得分:1)
Polygon
实现了Shape
界面,因此多个contain()
变体中的一个可能会简化您的计算。 AffineTransform
的createTransformedShape()
方法也可能会有所帮助,如example中所述。
答案 1 :(得分:1)
我设法为你修好了。首先,我做了一些代数(希望通过内联注释解释)来简化计算哪个图块被击中。你有点意识到的下一点;有铸造问题。在使用之前,您需要将所有转换为double。如果你做int/int
,那么你已经进行了投射并且精确度下降了。
让它击中正确的磁贴的技巧是1)早期投射和2)+/- 0.5
用于强制返回int
强制转换为某种方式。详细说明,(int)6.9 == 6
。
以下是工作答案:
@Override
public void mouseClicked(MouseEvent e) {
if (!Dragging) {
/*
// copy of the tile location assignment code as a reminder
dx = x * GrassTile.getWidth() / 2
- y * GrassTile.getWidth() / 2;
dy = x * GrassTile.getHeight() / 2
+ y * GrassTile.getHeight() / 2;
dx -= ViewLocation.x;
dy -= ViewLocation.y;
*/
int pickX = e.getX() + ViewLocation.x;
int pickY = e.getY() + ViewLocation.y;
int tileW = GrassTile.getWidth();
int tileH = GrassTile.getHeight();
/*
// assignment code refactored
x - y = 2 * pickX / tileW;
x + y = 2 * pickY / tileH;
// x+y= refactored to y=
y = (2*pickY / tileH) - x;
// substitute into x-y + refactor
2x = (2 * pickX / tileW) + (2 * pickY / tileH);
// x+y= refactored to x=
x = (2*pickY / tileH) - y;
// substitute x-y + refactor
-2y = (2 * pickX / tileW) - (2 * pickY / tileH);
2y = (2 * pickY / tileH) - (2 * pickX / tileW);
*/
int hitx = (int)(((double)pickX / (double)tileW) + ((double)pickY / (double)tileH) - 0.5);
int hity = (int)(((double)pickY / (double)tileH) - ((double)pickX / (double)tileW) + 0.5);
Selected.setLocation(hitx, hity);
repaint();
//System.out.println("(" + x + "," + y + ")");
}
}