How to constrain sprite movement within isometric boundaries in libgdx?

76 Views Asked by At

I am currently generating an isometric map which should allow some sprites to move randomly within its bounds. My sprites, or 'humans' do move within a specified constraint however it is not the correct boundaries I wish to set it to. Below is my code.

public class Human implements Entity {

    private int[][] map;
    public static final int TILE_WIDTH = 34;
    public static final int TILE_HEIGHT = 34;
    private int min = 100;
    private int max = 200;

    private Texture img;

    // position variable
    private Vector2 pos;
    private float time;

    public Human() {
        img = new Texture(Gdx.files.internal("humanFF.png"));
        // coordinates of human initial position
        pos = new Vector2(9, 220);

        // for locking movement if need be.
        time = 2;

        map = randomGenerator();


    }

    @Override
    public void render(SpriteBatch batch) {
        batch.draw(img, pos.x, pos.y);
    }

    @Override
    public void update(float delta) {

        time += delta;

        Random rand = new Random();

        int upperbound = 2;
        double double_random = rand.nextDouble(upperbound);

        // lock human, can only move once every 2 secs.
        if (time > 0) {
            move();
            time = 0;
        }
    }


    private void move() {


        /** Calculation **/

        for (int row = map.length - 1; row >= 0; row--) {
            for (int col = map.length - 1; col >= 0; col--) {
                float x = (col - row) * (TILE_WIDTH / 2f - 2);
                float y = (col + row) * (TILE_HEIGHT / 4f);
            }
        }

        // after calculation, mapWidth is 525 pixels.
        int mapWidth = map.length * (TILE_WIDTH / 2 - 2);

        // after calculation, mapHeight is 280 pixels.
        int mapHeight = map.length * (TILE_HEIGHT / 4);

        // Calculate the minimum and maximum x-coordinates.
        float minX = 0;
        float maxX = mapWidth - TILE_WIDTH;
        if (maxX < 0) {
            maxX = 0;
        }

        // max-x coordinate is 491.0. min-x coordinate is 0.0.


        // Calculate the minimum and maximum y-coordinates.
        float minY = 0;
        float maxY = mapHeight - TILE_HEIGHT;
        if (maxY < 0) {
            maxY = 0;
        }


        // check the position of human against map boundaries
        if (pos.x < minX) {
            pos.x = minX;
        } else if (pos.x > maxX) {
            pos.x = maxX;
        }
        if (pos.y < minY) {
            pos.y = minY;
        } else if (pos.y > maxY) {
            pos.y = maxY;
        }

        // min-y coordinate is 0.0, max-y coordinate is 246.0.


        // a variable to store a random generated value between 100 and 200.
        int a = (int) (Math.random() * (max - min + 1) + min);

        float newX = pos.x;
        float newY = pos.y;

        // move up
        if (a <= 125) {
            newX -= 15;
            newY += 8.5;
        }
        // move down
        else if (a <= 150 && a > 125) {
            newX += 15;
            newY -= 8.5;
        }
        // move left
        else if (a <= 175 && a > 150) {
            newX -= 15;
            newY -= 8.5;
        }
        // move right
        else if (a <= 200 && a > 175) {
            newX += 15;
            newY += 8.5;
        }

        if (newX >= minX && newX <= maxX && newY >= minY && newY <= maxY) {
            pos.x = newX;
            pos.y = newY;
        }
    }
    
    public int[][] randomGenerator() {
        Random r = new Random();
        int Size = r.nextInt(35, 36);
        int[][] map = new int[Size][Size];

        for(int row = 0; row < map.length; row++) {
            for(int col = 0; col < map.length; col++) {
                int Number = r.nextInt(10);
                if(Number == 0) {
                    map[row][col] = 0;
                } else if (Number == 1) {
                    map[row][col] = 1;
                }
                else if (Number == 2) {
                    map[row][col] = 2;
                }
                else if (Number == 3) {
                    map[row][col] = 3;
                }
                else if (Number == 4) {
                    map[row][col] = 4;
                }
                else if (Number == 5) {
                    map[row][col] = 5;
                }
                else if (Number < 8) {
                    map[row][col] = 6;
                }
                else {
                    map[row][col] = 7;
                }
            }
        }
        map[0][0] = 1;
        return map;
    }
}

Based on the above, I am generating a random value which defines the movement of my 'humans' thus adding or subtracting from their x and y positions. In my attempt to tackle the problem of these sprites moving outside of my isometric map, I tried to calculate my mapWidth, mapHeight, min-x, max-x, min-y and max-x and then checking the position of my human against these boundaries to determine their movement.

Although these sprites now move within a constraint, it is not same dimension as my isometric map, but are now constrained to a rectangular-shaped boundary. How do I modify my code so that the sprites only move within the isometric map I have generated?

Below is a photo for visualisation.enter image description here

1

There are 1 best solutions below

2
londonBadger On

The coordinate system you use for Human enties is ordinary orthogonal, you don't map these coordinates to an isometric view but you -have to- map them onto the isometric background. Screen coordinate system is basically different from the isometric one. When you render you need to map coordinates so that

(0,0)-> left corner
(0,maxY)->top corner
(maxX,maxY)->right corner
(maxX,0)->bottom corner

See here for to and back(map screen touch events to the map etc) conversion LibGdx render a sprite on top of a isometric tile