AS3 数组瓦片引擎

AS3 Array Tile Engine

我一直在研究一个 Tile Map,它正在工作并根据数组中的关联数字在屏幕上显示图块。

瓷砖 0 用于草,1 用于水,2 用于硬币。当用户单击我需要的硬币磁贴时,它会打开一个菜单,用户可以单击按钮从磁贴中 'TAKE COINS'。

    var myMap: Array = [
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 2, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 2, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 2, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 1, 1, 0, 0, 0]
    ];


    for (var i: int = 0; i < mapHeight; i++) {
        for (var u: int = 0; u < mapWidth; u++) {
            var tile: MovieClip = new Tile();
            tile.gotoAndStop(myMap[i][u] + 1);
            tile.x = tileSize * u
            tile.y = tileSize * i
            tile.theIDi = i;
            tile.theIDu = u;
            tile.buttonMode = true;


            addChildAt(tile, 0);
            tile.addEventListener(MouseEvent.CLICK, clickTile);

        }
    }

    function clickTile(event: MouseEvent) {
         positionX = event.currentTarget.theIDu;
         positionY = event.currentTarget.theIDi;

         if(myMap[positionX][positionY] == 2) {
             openGoldMenu(positionX, positionY);                    
         }
    }

    function openGoldMenu() {
         takeCoinsMenu.x = 100;
         takeCoinsMenu.y = 200;
         buttonTake.addEventListener(MouseEvent.CLICK, takeCoins);
    }

    function takeCoins(event: MouseEvent) {
         myStats[0].gold = myStats[0].gold + 10;

         WHAT TO WRITE HERE? HOW CAN I ACCESS THE CURRENT TILE THAT WAS CLICKED WITH THE GOLD COIN ON? URGH CONFUSED!
     }

有很多方法可以做到这一点,但可能最简单的方法如下:

  1. 创建一个变量(确保它是在任何方法之外声明的,所以在你的 myMap var 旁边最好)存储最后一个被点击的图块

    var clickedTile:Tile;
    var myMap:Array = [.......
    
  2. 在您的 clickTile 函数中,填充该变量:

    function clickTile(event: MouseEvent) {
        clickedTile = event.currentTarget as Tile;
    
        var positionX:int = clickedTile.theIDu;
        var positionY:int = clickedTile.theIDi;
    
        if(myMap[positionX][positionY] == 2) {
            openGoldMenu(positionX, positionY);                    
        }
    }
    

现在,在您的 takeCoins 方法中,您可以引用存储在 clickedTile 中的图块。

注意到您的问题已经得到解答,但我想提供一个额外的提示,我希望我早就知道了。

看起来您的所有图块大小都相同,如果是这种情况,则不要向所有单个图块添加点击事件,只需将一个添加到图块容器中,在本例中为剪辑使用此 class 然后根据鼠标位置确定您单击了哪个图块...

addEventListener(MouseEvent.CLICK, clickEventHandler);

private function clickEventHandler(e:MouseEvent):void
{
var uId:int = Math.floor((mouseX - this.x) / tileSize);
var iId:int = Math.floor((mouseY - this.y) / tileSize);

if(myMap[uId][iId] == 2)
{
openGoldMenu(uId,iId);
}
}

这样你只需要设置一个事件侦听器,以后当你需要禁用它时管理起来会更快更容易,你也可以不再需要在图块中设置 theIDi 和 theIDu 变量,除非稍后你需要它们。

另外我会说不要使用 iId 或 uId,使用 xId 和 yId 或 xIndex 和 yIndex,在使用二维数组时更有意义并且以后更容易理解,您也可以使用与您的类似的东西循环变量只是为了让事情简单。

for(var yIndex:int = 0; yIndex < map.length ; xIndex++)
for(var xIndex:int = 0; xIndex < map[yIndex].length ; yIndex++)

将不同的图块存储在它们自己的二维数组中而不是创建它们并将它们添加到舞台上也是一个好主意,这将使 remove/update 个单独的图块更容易出现移动你的瓷砖,因为你可以从舞台上删除一行或一列,因为你仍然有参考,而不是遍历所有瓷砖并检查它们的 ID。

var tileArray:Array = new Array();

for(var yIndex:int = 0; yIndex < map.length; yIndex++)
{
if(tileArray[yIndex] == null) tileArray[yIndex] = new Array();
for(var xIndex:int = 0; xIndex < map[yIndex].length; xIndex++)
{
tileArray[yIndex][xIndex] = new Tile();
tileArray[yIndex][xIndex].x = xIndex * tileSize;
tileArray[yIndex][xIndex].y = yIndex * tileSize;
addChild(tileArray[yIndex][xIndex]);
}
}

然后当你想删除一个 tile 时,只需调用。

removeChild(tileArray[yIndex][xIndex]);
tileArray[yIndex][xIndex] = null;

这也消除了对 uId 和 iId 的需要,因为该数组中的位置就是 id。

希望这对您有所帮助:)