0
\$\begingroup\$

I'm creating a 2D game that uses a Tiled Map with an underlying 2D array to store where entities are in the world. At the moment, I'm just creating one instance of an entity, assigning it a number, and storing that in the array to determine what entity is at what position in the array/world. However, this is presenting some issues. The most prevalent being getting the position of an entity from the entity object, because there is only one object being used throughout the whole world.

Would it just be easier to have non-static entities and populate the array with many instances of the entity object or is there a simple way I could get the position of an entity on the tile map through the object?

\$\endgroup\$
  • \$\begingroup\$ if you , for what I understood from 'because there is only one object being used throughout the whole world', whant one istance for a static object (let's say a 'Wall') then assign it a number (let's say 1) so that all walls ar sored as 1 in your 2d array, I can't see a solution from one istance to get the N positions in the array. \$\endgroup\$ – dnk drone.vs.drones Jul 24 '15 at 6:59
  • \$\begingroup\$ That's exactly right. Do you think it would be better to skip the that altogether and make an instance of the object of every entity instead? \$\endgroup\$ – Panda Jul 24 '15 at 19:12
0
\$\begingroup\$

Just store the position in the entity object as well. For dynamic objects I am using both arrays and I store the position of the object inside the object as well for various reasons. One reason is to use the array for drawing, if I only want to draw from coordinate (10,10) to (26, 19) because my screen does not reach the others anyway I can use the various arrays. But if I have an object and want to know it's position I have to iterate the whole array if I do not store it inside it.

Sometimes I just use vectors for storing the position but a much better way is to create your own point/coordinate class with equals and hashtag overrides to compare. You can put (static) methods in this class to convert from screen and camera coordinates which are often vectors to your points for easy shifting between them.

You know what? Here is a basic one I use:

public class Point {
    public int x;
    public int y;

    /**
     * Creates point
     * @param x X - coordinate
     * @param y Y - coordinate
     */
    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    /**
     * Creates point from world vector
     * @param v World vector
     */
    public Point(Vector2 v)
    {
        this.x = (int)(v.x / tileWidth);
        this.y = (int)(v.y / tileHeight);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Point point = (Point) o;

        if (x != point.x) return false;
        if (y != point.y) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = x;
        result = 31 * result + y;
        return result;
    }

    @Override
    public String toString() {
        return "Point: (" + x + ", " + y;
    }

    /**
     * Returns the world coorinate of the point.
     * @return world vector.
     */
    public Vector2 toWorld()
    {
        return new Vector2(x * tileWidth, y* tileHeight);
    }

    /**
     * Returns point from world vector
     * @param v World vector
     * @return
     */
    public static Point getPoint(Vector2 v)
    {
        return new Point((int)(v.x / tileWidth), (int)(v.y / tileHeight));
    }

    /**
     * Returns point from Vector3 where Z is discarded.
     * @param v world vector
     * @return
     */
    public static Point getPoint(Vector3 v)
    {
        return new Point((int)(v.x / tileWidth), (int)(v.y / tileHeight));
    }
}

The only thing you need is to hookup tileWidth and tileHeight to your variables. You might want to change the variables to private with get/set, but since they are only coordinates I like to have quick access to them.

-Edit-

Here is a basic example of how a Tile class looks like.

public class Tile {
    boolean walkable;
    //here I make use of "your way" to lookup the texture of this tile.
    int textureId;
}

when I want to create the map, I populate and draw the array:

Tile[][] tileMap = new Tile[width][height];
        for (int y = 0; y < width; y++)
        {
            for (int x = 0; x <= height; x++)
            {                
                spriteBatch.draw(textureDictionary.get(tileMap[x][y].textureId), position, etc);                
            }
        }

Now this is not much different then your method, only mine stores if the tile can be walked upon too. Your walls should probably never be walked upon and floors should so why bother changing to my method?

Scalability is the answer. What if you decide that you want to add objects to your map? If you have say 10 objects like tables, chairs, pillars, etc then for each int that represents a floor you need 10 more of those. Where I just add another int for the objects texture or perhaps the object itself if it has more properties like a tile.

Yes you could add another array to represent your objects and draw that over your tiles. But then you decide that object a can damage the player in a certain state. Now you need to make another array or a extra int to refer too. Where I change the behavior of a object in it's class. This is why you use a object oriented language anyway.

\$\endgroup\$
  • \$\begingroup\$ I must be misunderstanding you. How can I add the position of the entity to the actual object if there is only one instance of the object? \$\endgroup\$ – Panda Jul 24 '15 at 17:15
  • \$\begingroup\$ You ad a x and y field to the class of the object you are instanciating. Or add a object of the class I just presented. \$\endgroup\$ – Madmenyo Jul 24 '15 at 17:26
  • \$\begingroup\$ However there is only one instance of each static entity object. Adding a position field to the object itself won't work because it will just be the position of the entity that was created last. I think dnk drone.vs.drones may be correct that I cannot easily do what I want. \$\endgroup\$ – Panda Jul 24 '15 at 19:14
  • \$\begingroup\$ It's not clear to me what you mean by instance of each static object. A object cannot be static. A class can have the static keyword but this would never belong to the object you create from the class. So I am not sure what you exactly want. Do you just have int[][] map = new int[width][height] where the int refers to the type of entity? You need to link that int somewhere to something, I mean you could link it to a texture but you can also link it to another object. You can also populate the array with objects you actually need like Tile[][] tileMap = new Tile[width][height]. \$\endgroup\$ – Madmenyo Jul 25 '15 at 4:28
  • \$\begingroup\$ Sorry for the strange wording, I couldn't come up with a better way to put it. Yes, I have an array of ints where each int represents an entity. My question is essentially if I should instead ditch the representation way of it and directly store the objects directly like you have shown in your example. \$\endgroup\$ – Panda Jul 25 '15 at 4:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.