Isometric Game Design.

I’ve been trying… and trying… and trying to find online information that will help me with creating an isometric game, but I’m the kind of person that needs to read over something that works to understand it… and it seems that that the devil himself is making sure that the amount of literature for isometric games is ridiculously scarce.

I’m willing to pay anywhere between $100->$200 for a good book on Java Isometric game development, at this point I really want to understand it and don’t care about the costs. I’m not even trying to make anything big, just an isometric tower defence, just so I can say that I did it.

Amit’s Info has a lot on isometric, esp. in the Tile Based Games section.

I’m not sure what you don’t understand… very little is specific to isometric games, isn’t is just a particular 2D (faux 3D) art style?

It’s the logic behind it I guess, everything that I read talks about just rotating an orthographical map 45 degres, but that doesn’t look right.

I understand how to draw a basic tile map, as it’s just


for(i = 0, i < colums; i++) { 
    for(y = 0, y < rows; y++) {
        drawhere
    }
}

But how do I go about understanding which tile the mouse is on at all times, how do I go about working on pathfinding with these tiles.

My main problem is understanding how to know which tile is what.

Like I said, Amit has you covered, there’s at least 2 or 3 links on how to do that; here’s one:
http://clintbellanger.net/articles/isometric_math/

Thank you for the links burnt! I’ll spend my next few hours reading up here.

I’ve read through numerous of his post(s), and while I still have my world drawing, I can’t figure out how to do much more with it. (Such as clicking on the tiles, etc). I understand the math behind it (Which is seems is all this guy talks about), but I don’t understand what I need to apply this math to.

I understand that I can do basic math to determine which tile my mouse is on based on the tile-size (which he talks about)…

but how do I go about getting that tile to modify it, or build ontop of it, or anything like that.

I’m trying to create a standard TD game before I move it to Isometric, as he seems to preach that a lot.

Well, to use the simple case of a Tile[][] data structure (Amit has data structure tips as well):


public Tile getTile(int screenX, int screenY) {
    int twh = TILE_WIDTH / 2;
    int thh = TILE_HEIGHT / 2;
    int worldX = (screenX / twh + screenY / thh) / 2;
    int worldY = (screenY / thh - (screenX / twh)) / 2;
    return tiles[worldY][worldX];
}

Boom. Now you can get the Tile instance that you are clicking on. Set it’s color field, get the list of entities occupying that tile and damage them, set the tile on fire, etc.

For instance:


public class Tile {

    public static enum Type {
        Grass, Dirt, Stone;
    }

    public Type type; // each Tile instance has a type

    public List<Entity> entities; // monsters etc. occupying this tile.

    public void attack(int damage) { // attack this tile
        for(Entity e : entities)
            e.damage(damage);
    }
}

Thank you, I’ve been playing with this; However the LibGDX Y axis flip is driving me absolutely insane. I’ve done my own math to try to calculate for it, but every step I take seems like it’s in the wrong direction.

I read that using the Orthographic Camera I can easily make the Y position 0 at the top left like it is in Java2D, however that doesn’t seem to be the case, either that or I’m missing something very simple.

Here’s my code:

SpriteBatch batch;
	GameWorld world;
	OrthographicCamera camera;
	
	@Override
	public void show() {
		batch = new SpriteBatch();
		world = new GameWorld();
		camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
		camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
	}
	
	
	@Override
	public void render(float delta) {
		Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		
		batch.setProjectionMatrix(camera.combined);
		
		batch.begin();
			world.render(batch, delta);
		batch.end();
	}

If you need anything other than this let me know, the tiles are still drawing from the bottom left.

No, I’m not using tiledmap. If you’re curious as to how I’m drawing my tiles

Generating the tile world:

	private void placeTiles() {
		for(int xAxis = 0; xAxis < worldColumns; xAxis++) {
			for(int yAxis = 0; yAxis < worldRows; yAxis++) {
				tiles[xAxis][yAxis] = new GameTile(
						GameTile.getTypeForID(mapData[yAxis][xAxis]),
						new Position(xAxis * GameTile.TILE_WIDTH, yAxis * GameTile.TILE_HEIGHT));
			}
		}
	}

Render method for tile:

	public void render(SpriteBatch batch, float delta) {
		myShape.begin(ShapeType.Filled);
		myShape.setColor(tileColor);
		myShape.rect(pos.getX(), pos.getY(), TILE_WIDTH, TILE_HEIGHT);
		myShape.end();
	}

This is still frustrating the hell out of me, and I can’t figure it out. I decided to just go ahead and do the math for the Y Axis, but even then I can’t get it to calculate the tile position correctly.

Attempts:

	public String getTile(int screenX, int screenY) {
		int worldX = (screenX / (GameTile.TILE_WIDTH / 2) + screenY / (GameTile.TILE_HEIGHT / 2) / 2);
		int worldY = (screenY / (GameTile.TILE_HEIGHT / 2) - (screenX / (GameTile.TILE_WIDTH / 2)) / 2);
		return "Tile X: " + worldX + " -- Tile Y: " + worldY;
	}
	public String getTile(int screenX, int screenY) {
	    int worldX = mapData[0].length - (int)(Gdx.graphics.getWidth() / screenX);
	    int worldY = mapData.length - (int)(Gdx.graphics.getHeight() / screenY);
	    
	    
	    if(worldX < 0) worldX = 0;
	    if(worldX > tiles[0].length)worldX = tiles[0].length-1;
	    if(worldY < 0) worldY = 0;
	    if(worldY > tiles.length)worldY = tiles.length-1; 
	    return "X: " + worldX + " Y: " + worldY;
//	    return tiles[worldX][worldY];
	}
	public GameTile getTile(int screenX, int screenY) {
	    int twh = GameTile.TILE_WIDTH / 2;
	    int thh = GameTile.TILE_HEIGHT / 2;
	    int worldX = (screenX / twh + screenY / thh) / 2;
	    int worldY = (screenY / thh - (screenX / twh)) / 2;
	    if(worldX >= (tiles[0].length - 1)) worldX = (tiles[0].length - 1);
	    if(worldX < 0) worldX = 0;
	    if(worldY >= (tiles.length - 1)) worldY = (tiles.length - 1);
	    if(worldY < 0) worldY = 0;
	    return tiles[worldY][worldX];
	}

and numerous more I can’t even remember.

You could try to get your function to turn screen co-ordinates into world-pixel co-ordinates, instead of world-tile co-ordinates, then you will be able to see what the numbers are doing more easily as you move your mouse around, then change it back to giving tile co-ords once it looks like its giving proper results.

I dont quite understand what you’re saying, but I’m debugging the mouses position and the tile that it’s in to check to see if the maths adding up, but I honestly just can’t even math. It’s not making the slightest bit of sense and feels like the numbers are all randomly generated.

This 0,0 y on the bottom thing is literally blood boiling. I might just go back to Java2D

what i mean is dont divide by tile size to get tile based co-ords. each tile is a certain size of pixels, so if you get the function to return the number of world-pixels that your mouse is pointing at, rather than an exact tile index, you can see how the values change more accurately as you move from one tile to another… printing tile-co-ords on the screen doesnt have enough resolution for you to get a good idea of where your function is going wrong.

as for the y-0-bottom thing, if you dont like that, just do your mouse: y = screenHeight - y. thatll flip it.

Isn’t that what I’m doing with the Gdx.graphics.getHeight/getWidth?

I’ve been doing Gdx.graphics.getHeight() - Gdx.input.getY() to determine the flipped Y value, that’s good enough.
But I still can’t get these calculations right.

I even wrote it in Java2D (Took less than ten minutes) and still can’t do it that way using the example I was given.

Got a Java2D version working using

	public GameTile getTile(int screenX, int screenY) {
		int worldX = (screenX / GameTile.TILE_WIDTH)-1;
		int worldY = (screenY / GameTile.TILE_HEIGHT)-1;
		return tiles[worldX][worldY];
	}

LibGDX

	public GameTile getTile(int screenX, int screenY) {
		int worldX = (screenX / GameTile.TILE_WIDTH);
		int worldY = (screenY / GameTile.TILE_HEIGHT);
		return tiles[worldX][worldY];
	}

Just did it in libGDX:

Render code: (tile is the instanced Sprite)


float mx = Gdx.input.getX();
float my = Gdx.input.getY();

my = Gdx.graphics.getHeight() - 1 - my; // invert y-axis

mx -= Gdx.graphics.getWidth() / 2;  // center it
my -= Gdx.graphics.getHeight() / 2;

// these are the world coords of the mouse
int worldX = (int) ((mx / (TILE_WIDTH / 2) + my / (TILE_HEIGHT / 2)) / 2 - .5f);
int worldY = (int) ((my / (TILE_HEIGHT / 2) - mx / (TILE_WIDTH / 2)) / 2 + .5f);

for (int y = 0; y < tiles.length; y++) {
	for (int x = 0; x < tiles[y].length; x++) {
		
		if (x == worldX && y == worldY)
			tile.setColor(1, 0, 0, 1);
		else
			tile.setColor(.5f, .5f, .5f, 1);
		
		float screenX = (x - y) * (TILE_WIDTH / 2);
		float screenY = (x + y) * (TILE_HEIGHT / 2);
		
		tile.setPosition(screenX, screenY);
		tile.draw(batch);
	}
}

I would like to point out that post above me deserves a medal for the GIF demo.

Developers seldom post GIF demos with their codes, when they are sharing codes, or when they are demonstrating concepts that other developers may have difficulty on. I think we should utilize GIFs even more.

Thanks, I do it fairly often. GifCam is excellent if you’re on windows.
EDIT: whoa, I’m a wizard!