0

I'm having trouble using Maps in Haxe. I'm trying to create a grid of Tile objects and add them to the Map using their index on the grid as a key. However, when I try to retrieve a Tile from the map using an index I always get a value of null.

Could someone explain why this is happening? I've never used a map before and I don't understand what the issue is. I'm currently using a multidimensional array to get the same functionality, but maps seem more convenient.

private function initTiles():Void
{
    var tempTile:Tile;
    tileMap = new Map();

    for (i in 0...widthTiles)
    {
        for (j in 0...heightTiles)
        {
            tempTile = new Tile(i * 32, j * 32);
            tileMap.set([i,j],tempTile);
        }
    }
}
Gama11
  • 31,714
  • 9
  • 78
  • 100
  • Possible duplicate of [Using objects as Map keys in Haxe](https://stackoverflow.com/questions/27370043/using-objects-as-map-keys-in-haxe) – Gama11 Mar 13 '19 at 14:53

1 Answers1

1

The issue is that the you are not actually creating a multidimensional array, you are creating a single dimensional array where the key type is Array<Int>. If ever in doubt, you can use $type( tileMap ) to get the compiler to tell you what type it thinks you have.

In your case, you would get:

Map<Array<Int>,Tile>; // This is an ObjectMap, where the object is an Array

When what you really want is:

Map<Int, Map<Int,Tile>>; // This is an IntMap, each value holding another IntMap

The reason this is an issue can be seen with this line:

trace( [0,0] == [0,0] ); // False!

Basically, in Haxe equality of objects (including arrays) is based on if they are the exact same object, not if they hold the same values. In this case, you are comparing two different arrays. Even though they hold the same values, they are actually two different objects, and not equal. Therefore they don't make suitable keys for your map.

Here is a working sample for what you need to do:

class Test {
    static function main() {
        initTiles();
        trace( tileMap[3][6] );
    }

    static var tileMap:Map<Int,Map<Int,Tile>>;
    static function initTiles():Void {
        var widthTiles = 10;
        var heightTiles = 10;
        tileMap = new Map();
        for (i in 0...widthTiles) {
            if ( tileMap[i]==null ) {
                // Add the sub-map for this column
                tileMap[i] = new Map();
            }
            for (j in 0...heightTiles) {
                // Add the tile for this column & row
                tileMap[i][j] = new Tile(i*32, j*32);
            }
        }
    }
}

class Tile {
    var x:Int;
    var y:Int;
    public function new(x:Int, y:Int) {
        this.x = x;
        this.y = y;
    }
}

And to see it in action: http://try.haxe.org/#E14D5 (Open your browser console to see the trace).

Jason O'Neil
  • 5,908
  • 2
  • 27
  • 26