正确地悬停在等距图块精灵上
Properly hovering over isometric tile sprite
我有四个 类:Room、TileGrid、HoverTile 和 Tile。
房间由墙壁和 TileGrid 组成。 TileGrid 由 Tile 制成。目前,我使用此代码从 Tiles 生成 TileGrid:
this.mapArray = [[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1, 1, 1, 1, 1, 1, 1]];
this._mapHeight = this.mapArray.length;
this._mapWidth = this.mapArray[0].length;
this._tileHeight = 23;
this._tileWidth = 46;
var initialX:Number = 260;
var initialY:Number = 150;
for (var isoY:int = 0; isoY < mapArray.length; isoY++)
{
for (var isoX:int = 0; isoX < mapArray[isoY].length; isoX++)
{
if (isoX == 0 && isoY == 0)
{
var _tile:Tile = new Tile();
_tile.x = initialX;
_tile.y = initialY;
this.addChild(_tile);
}
if (this.mapArray[isoY][isoX] == 1)
{
var _tile:Tile = new Tile();
_tile.x = initialX - (isoX * 20) - (isoY * 20);
_tile.y = initialY - (isoX * 10) + (isoY * 10);
addChild(_tile);
_tile.addEventListener(MouseEvent.MOUSE_OVER, updateHover);
}
}
}
我当前的问题是我想在鼠标悬停的图块周围添加一个白色方块。我以前使用的代码还不够,因为 Tile 精灵的透明部分仍然算作它的一部分。因此,即使我指向另一个 Tile2(位于 Tile1 旁边),例如,如果我离 Tile2 不够远,它也会突出显示 Tile1。
所以,这是我当前使用的代码:
public function updateHover(e:MouseEvent):void
{
var mX:int = e.stageX - (_tileWidth / 2);
var tPoint:Point = pointToXY(mX, e.stageY);
var isoX = tPoint.x;
var isoY = tPoint.y;
if (isoX >= 0 && isoY >= 0)
{
if (isoY < mapArray.length)
{
if (isoX < mapArray[0].length)
{
tPoint = xyToPoint(isoX, isoY);
_tileHover.x = tPoint.x;
_tileHover.y = tPoint.y;
_tileHover.visible = true;
return;
}
}
}
_tileHover.visible = false;
}
public function pointToXY(x:int, y:int):Point
{
x -= 260;
y -= 150;
var pRatio:int = (_tileWidth / 2) / (_tileHeight / 2);
var tX:int = (y + x / pRatio) * (pRatio / 2) / (_tileWidth / 2);
var tY:int = (y - x / pRatio) * (pRatio / 2) / (_tileWidth / 2);
return new Point(tX, tY);
}
public function xyToPoint(x:int, y:int):Point
{
x -= 1;
var worldPoint:Point = new Point(0, 0);
worldPoint.x = (x * (_tileWidth / 2)) - (y * (_tileWidth / 2));
worldPoint.y = (x * (_tileHeight / 2)) + (y * (_tileHeight / 2));
worldPoint.x = worldPoint.x + (_tileWidth / 2);
worldPoint.y = worldPoint.y + (_tileHeight / 2);
worldPoint.x += 260;
worldPoint.y += 150;
return worldPoint;
}
抱歉,我不得不 post 这么多代码块。现在,260 和 150 是整个房间的默认起点。也就是说,我真的很困惑如何让最后两个功能发挥作用,以便它们能给我正确的答案。这是我对使用此代码的期望:
那就完美了。但是,同样,我不知道为什么代码不起作用。尺寸都是正确的,我相信偏移量也是正确的。所以,我
首先,您应该将侦听器添加到 this
,而不是 _tile
,因为这样您就会被锁定到舞台坐标以确定所选的图块,这并不好。其次,您的侦听器应该反对 MouseEvent.MOUSE_MOVE
事件,而不是结束,这样您将不断获得更新的鼠标坐标,以便在瓷砖上正确移动您的矩形。你有一个小错误,你创建了一个 (0,0) tile 两次,一次是不活动的。
for (var isoY:int = 0; isoY < mapArray.length; isoY++)
{
for (var isoX:int = 0; isoX < mapArray[isoY].length; isoX++)
{
if (this.mapArray[isoY][isoX] == 1)
{
var _tile:Tile = new Tile();
_tile.x = initialX - (isoX * 20) - (isoY * 20);
_tile.y = initialY - (isoX * 10) + (isoY * 10);
addChild(_tile);
}
}
}
this.addEventListener(MouseEvent.MOUSE_MOVE, updateHover);
此外,最好将 (x,y) 对存储在数组中(最有可能作为图块),这样您的初始数组 0 和 1 将转换为 Tile
对象。为此,您首先要这样做:
this.tileArray=[];
for (var i:int=0;i<this.mapArray.length;i++)
this.tileArray.push(new Array(this.mapArray[i].length));
这将创建一个与您的 mapArray
按维度匹配的空数组,它将作为创建的 Tile
对象的占位符。执行此操作后,调用 this.tileArray[isoY][isoX]=_tile;
将新创建的图块放置到位。之后,您可以将您的侦听器重写为:
public function updateHover(e:MouseEvent):void
{
var p:Point=pointToXY(e.localX,e.localY);
_tileHover.visible = false; // hide hover for now
if ((p.y<0) || (p.y>=tileArray.length)) return; // range error on Y
if ((p.x<0)||(p.x>=tileArray[p.y].length)) return; // range error on X
if (!tileArray[p.y][p.x]) return; // no tile
var _tile:Tile=tileArray[p.y][p.x];
_tileHover.x=_tile.x;
_tileHover.y=_tile.y; // no need to convert xyToPoint() we have coords stored in tile
_tileHover.visible=true;
}
我有四个 类:Room、TileGrid、HoverTile 和 Tile。
房间由墙壁和 TileGrid 组成。 TileGrid 由 Tile 制成。目前,我使用此代码从 Tiles 生成 TileGrid:
this.mapArray = [[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1, 1, 1, 1, 1, 1, 1]];
this._mapHeight = this.mapArray.length;
this._mapWidth = this.mapArray[0].length;
this._tileHeight = 23;
this._tileWidth = 46;
var initialX:Number = 260;
var initialY:Number = 150;
for (var isoY:int = 0; isoY < mapArray.length; isoY++)
{
for (var isoX:int = 0; isoX < mapArray[isoY].length; isoX++)
{
if (isoX == 0 && isoY == 0)
{
var _tile:Tile = new Tile();
_tile.x = initialX;
_tile.y = initialY;
this.addChild(_tile);
}
if (this.mapArray[isoY][isoX] == 1)
{
var _tile:Tile = new Tile();
_tile.x = initialX - (isoX * 20) - (isoY * 20);
_tile.y = initialY - (isoX * 10) + (isoY * 10);
addChild(_tile);
_tile.addEventListener(MouseEvent.MOUSE_OVER, updateHover);
}
}
}
我当前的问题是我想在鼠标悬停的图块周围添加一个白色方块。我以前使用的代码还不够,因为 Tile 精灵的透明部分仍然算作它的一部分。因此,即使我指向另一个 Tile2(位于 Tile1 旁边),例如,如果我离 Tile2 不够远,它也会突出显示 Tile1。
所以,这是我当前使用的代码:
public function updateHover(e:MouseEvent):void
{
var mX:int = e.stageX - (_tileWidth / 2);
var tPoint:Point = pointToXY(mX, e.stageY);
var isoX = tPoint.x;
var isoY = tPoint.y;
if (isoX >= 0 && isoY >= 0)
{
if (isoY < mapArray.length)
{
if (isoX < mapArray[0].length)
{
tPoint = xyToPoint(isoX, isoY);
_tileHover.x = tPoint.x;
_tileHover.y = tPoint.y;
_tileHover.visible = true;
return;
}
}
}
_tileHover.visible = false;
}
public function pointToXY(x:int, y:int):Point
{
x -= 260;
y -= 150;
var pRatio:int = (_tileWidth / 2) / (_tileHeight / 2);
var tX:int = (y + x / pRatio) * (pRatio / 2) / (_tileWidth / 2);
var tY:int = (y - x / pRatio) * (pRatio / 2) / (_tileWidth / 2);
return new Point(tX, tY);
}
public function xyToPoint(x:int, y:int):Point
{
x -= 1;
var worldPoint:Point = new Point(0, 0);
worldPoint.x = (x * (_tileWidth / 2)) - (y * (_tileWidth / 2));
worldPoint.y = (x * (_tileHeight / 2)) + (y * (_tileHeight / 2));
worldPoint.x = worldPoint.x + (_tileWidth / 2);
worldPoint.y = worldPoint.y + (_tileHeight / 2);
worldPoint.x += 260;
worldPoint.y += 150;
return worldPoint;
}
抱歉,我不得不 post 这么多代码块。现在,260 和 150 是整个房间的默认起点。也就是说,我真的很困惑如何让最后两个功能发挥作用,以便它们能给我正确的答案。这是我对使用此代码的期望:
那就完美了。但是,同样,我不知道为什么代码不起作用。尺寸都是正确的,我相信偏移量也是正确的。所以,我
首先,您应该将侦听器添加到 this
,而不是 _tile
,因为这样您就会被锁定到舞台坐标以确定所选的图块,这并不好。其次,您的侦听器应该反对 MouseEvent.MOUSE_MOVE
事件,而不是结束,这样您将不断获得更新的鼠标坐标,以便在瓷砖上正确移动您的矩形。你有一个小错误,你创建了一个 (0,0) tile 两次,一次是不活动的。
for (var isoY:int = 0; isoY < mapArray.length; isoY++)
{
for (var isoX:int = 0; isoX < mapArray[isoY].length; isoX++)
{
if (this.mapArray[isoY][isoX] == 1)
{
var _tile:Tile = new Tile();
_tile.x = initialX - (isoX * 20) - (isoY * 20);
_tile.y = initialY - (isoX * 10) + (isoY * 10);
addChild(_tile);
}
}
}
this.addEventListener(MouseEvent.MOUSE_MOVE, updateHover);
此外,最好将 (x,y) 对存储在数组中(最有可能作为图块),这样您的初始数组 0 和 1 将转换为 Tile
对象。为此,您首先要这样做:
this.tileArray=[];
for (var i:int=0;i<this.mapArray.length;i++)
this.tileArray.push(new Array(this.mapArray[i].length));
这将创建一个与您的 mapArray
按维度匹配的空数组,它将作为创建的 Tile
对象的占位符。执行此操作后,调用 this.tileArray[isoY][isoX]=_tile;
将新创建的图块放置到位。之后,您可以将您的侦听器重写为:
public function updateHover(e:MouseEvent):void
{
var p:Point=pointToXY(e.localX,e.localY);
_tileHover.visible = false; // hide hover for now
if ((p.y<0) || (p.y>=tileArray.length)) return; // range error on Y
if ((p.x<0)||(p.x>=tileArray[p.y].length)) return; // range error on X
if (!tileArray[p.y][p.x]) return; // no tile
var _tile:Tile=tileArray[p.y][p.x];
_tileHover.x=_tile.x;
_tileHover.y=_tile.y; // no need to convert xyToPoint() we have coords stored in tile
_tileHover.visible=true;
}