好吧,我已经无计可施了。我正在尝试创建一个小的等距贴图,它比屏幕更大,我可以用鼠标拖动修改视点。我的绘图是正确的(我认为),我的拖拽工作,只是似乎不能得到鼠标选择的权利。到目前为止,我已经得到了几乎正确的瓷砖,但它偏离了大约一半的瓷砖大小,我找不到一种方法来弥补这个偏移。
代码如下:
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) {
}
}
}
我有一些公式在点击方法注释出来,我尝试,但他们不工作(x和y轴倒过来的方式,还没有试图找出原因)。如果有人能指出我所犯的错误,我将不胜感激。
我已经帮你修好了。首先,我做了一些代数运算(希望通过内联注释来解释),以简化击中哪个贴图的计算。接下来你多少意识到了;选角有问题。在使用之前,需要将所有转换为双精度类型。如果你做了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 + ")");
}
}
Polygon
实现了Shape
接口,因此contain()
的几个变体之一可能会简化您的计算。如本例所示,AffineTransform
的createTransformedShape()
方法也可能很有帮助。