I'm trying to extend an isometric Flash game based on as3isolib. The game does only support diamond shaped grids but I have to implement the possibility to have rectangular shaped grids, too. Please see my example grid.
I already managed to create the开发者_如何学编程 grid. Here is the code:
private function createRectangularGrid():void
{
var c:int, r:int;
var node:DataNode;
var pt:Pt;
var nodePos:Point;
var isEvenRow:Boolean;
for (c=0; c<cols; c++) {
nodePos = new Point(c*_cellSize, -c*_cellSize);
for (r=0; r<rows; r++) {
node = new DataNode();
node.col = c;
node.row = r;
node.x = nodePos.x;
node.y = nodePos.y;
node.z = z;
node.width = _cellSize;
node.length = _cellSize;
node.height = 0;
pt = new Pt(node.x, node.y, node.z);
IsoMath.isoToScreen(pt);
node.screenX = pt.x;
node.screenY = pt.y;
_nodes.set(c, r, node);
isEvenRow = r % 2 == 0;
if (isEvenRow) nodePos.x += _cellSize;
else nodePos.y += _cellSize;
}
}
}
With a cellsize (isometric width and length) of 20px, the isometric positions of the grid cells shown above are:
- [DataNode (col:0, row:0, x:0, y:0)]
- [DataNode (col:0, row:1, x:20, y:0)]
- [DataNode (col:0, row:2, x:20, y:20)]
- [DataNode (col:0, row:3, x:40, y:20)]
- [DataNode (col:0, row:4, x:40, y:40)]
- [DataNode (col:0, row:5, x:60, y:40)]
- [DataNode (col:0, row:6, x:60, y:60)]
- [DataNode (col:1, row:0, x:20, y:-20)]
- [DataNode (col:1, row:0, x:20, y:-20)]
- [DataNode (col:1, row:1, x:40, y:-20)]
- [DataNode (col:1, row:2, x:40, y:0)]
- [DataNode (col:1, row:3, x:60, y:0)]
- [DataNode (col:1, row:4, x:60, y:20)]
- [DataNode (col:1, row:5, x:80, y:20)]
- [DataNode (col:1, row:6, x:80, y:40)]
- [DataNode (col:2, row:0, x:40, y:-40)]
- [DataNode (col:2, row:1, x:60, y:-40)]
- [DataNode (col:2, row:2, x:60, y:-20)]
- [DataNode (col:2, row:3, x:80, y:-20)]
- [DataNode (col:2, row:4, x:80, y:0)]
- [DataNode (col:2, row:5, x:100, y:0)]
- [DataNode (col:2, row:6, x:100, y:20)]
The problem is that all objects and avatars are still placed like as the grid were diamond shaped. This is because the formula for calculating the column and row number based on an isometric x/y position is only working for diamond grids:
var isoPt:Pt = IsoMath.screenToIso(new Pt(avatar.x, avatar.y));
var col:uint = Math.floor(isoPt.x / CELLSIZE);
var row:uint = Math.floor(isoPt.y / CELLSIZE);
Does anybody know how the formula should be for a rectangular shaped grid?
I figured it out. The following method will return the column and row number of the tile lying under the isometric x/y position passed as parameters.
public function getNodeByIsoPos(x:Number, y:Number):DataNode
{
var c:uint, r:uint;
if (_shape == STAGGERED_SHAPE) {
// This calculates column and row for a rectangular map (also called staggered map or block map)
c = Math.floor((Math.floor(x / _cellSize) - Math.floor(y / _cellSize)) / 2);
r = Math.floor(x / _cellSize) + Math.floor(y / _cellSize);
} else {
// This calculates column and row for a diamond map
c = Math.floor(x / _cellSize);
r = Math.floor(y / _cellSize);
}
return getNode(c, r);
}
Works perfectly. Please let me know if there is a more elegant way.
精彩评论