Updating tiles individually (of the same kind)?

Hello!

I have two tiles, a “power tile” that will power “lamp tiles”. When I place a “power tile” next to a “lamp tile” and there are multiple “lamp tiles” on the map, they all seem to turn on/off upon placement/removal of the “power tile”. I would like it to be that it only updates the “lamp tiles” around the “power tile” and not all of them.

gyfcat with issue being shown (few seconds long). http://gfycat.com/UnacceptablePowerlessCero
All relevant (I think) code files. https://gist.github.com/AndreasElia/575c39ad63d5daba98e3

This problem has been boggling me for the past 5 - 6 hours, some closure would be great!

Thank you!

You have a set of static tiles.

public static Tile grass = new GrassTile(Tile.grass, 0, 0);
public static Tile murkyGrass = new MurkyGrassTile(Tile.murkyGrass, 0, 0);
public static Tile redstone = new RedstoneTile(Tile.redstone, 0, 0);
public static Tile power = new PowerTile(Tile.power, 0, 0);
public static Tile lamp = new LampTile(Tile.lamp, 0, 0);

This means when you place any of these tiles the object is the same everywhere. (You really only have one of each of these tiles). You’ll need to actually make a new tile using the “new” keyword to get different objects.

Edit: to give you an idea of how to solve this instead of using

Tile.grass

to get that tile you could do something like

private static final int type_grass = 0;

public static Tile getGrassTile()
{
  return new GrassTile(type_grass, 0, 0);
}

Thanks for pointing that out thedanisaur.

But… how would one then go about using things like “type.onUpdate()” where “type” is “Tile type” variable, I would have to (I assume) use instanceof for every tile type?

Make Tile an abstract class with an abstract method ‘onUpdate’ so that you know that each tile instance (and therefore each type) inherits that method.

E.g.



public abstract class Tile extends Rectangle {
	
	public abstract void onUpdate(List<Tile> neighbours);
	
}


Also consider rewriting that tile class, it has some strange design issues. The tile class should really just be a generic skeleton that each tile subclass extends to ensure each tile has the same general structure. Like thedanisaur said, you should create a new instance of a tile each time you want to actually create a new tile in game. Each tile subclass should extend the abstract Tile class. Your Tile class is almost there, but you need to remove those static tiles, and figure out an alternative to passing in the Tile ‘type’ to the Tile constructor.

Edit: True, you actually do not need to make it abstract. I definitely do recommend a rewrite though!

I agree with Opiop, you should rewrite those classes, [s]but you don’t need to make it abstract. In each of your sub tile classes at the beginning of your onUpdate() just call super.onUpdate().

That way you’ll get both the funtionality of your super class as well as the sub classes, no need to do a cast.

Edit: Whoa, I just noticed what you’re actually doing, I’d do a rewrite. For now you could just remove the type.onUpdate(); from the Tile class and it should be…ok…[/s]

Edit 2:…yeah. I was initially confused by the design decisions. I assumed that you actually wanted to be able to make a generic “Tile” (for whatever reason). The Tile class should be abstract.

Yep, my apologies, poor code design! :frowning:

I’ve cleaned it up, but am kind of mine boggled at the suggested code you posted.

Why would I assign an int to grass_tile and why would I use getGrassTile by initializing a new one?

Well if you wanted access to a type it’d be better to just have an integer so you can do a switch on it (you don’t need a type field for inheritance and abstraction). As far as the getNewTile(), you don’t really need that. You can just say new GrassTile() or whatever, which is what you should be doing anyway.

Would you be able to take a look at the updated code below (Tile, GrassTile and Level) are in this gist.
https://gist.github.com/AndreasElia/0d075c247018c9c6c81d

Thanks for your help folks, I really do appreciate it.

Yeah it looks like you’ve got the idea.

One final question before I go to bed. In the level render, I do…

level[x][y].render(g, level, x * tileSize, y * tileSize);

But I can’t but help feel this is wrong since I do the same thing when setting the X and Y position in the constructor.

If I were to do…

level[x][y].render(g, level, level[x][y].x, level[x][y].y);

Then it works, but duplicates the tiles at what seems to be a 1 pixel grid at 0, 0.

You are correct, once you call setBounds() you no longer need to pass the x and y values into the render method.

- public void render(Graphics g, Tile[][] level, int x, int y)
+ public void render(Graphics g)