3

BACKGROUND

I have the following:

class Fire extending Element,

class Wood extending Element,

class Tile which composites Element.

The Tile class represents a tile in a world/screen/canvas, and has some graphical and logical functionality in it. It composites an Element object, because every tile in the "world" is made out of some substance (=element).

I want to achieve the functionality of fire spreading - when a fire element "touches" a wood element, I want the wood element to become fire. Logically, this should be done within the fire element, but doing that, I'm unable to change the given Tile's element (e.g. from Wood to Fire).

The "world" is initialized as a grid of tiles that are composed of Wood elements, except for one tile that has a Fire element which is supposed to spread.

WHAT I'VE TRIED

I've tried Linking together elements, meaning each element has access to his four nearest neighbors. That way a fire can access a nearby piece of wood. This doesn't solve the problem of changing a Tile's element type when fire touches wood.

I've tried moving the entire functionality to the Tile class. Although it does solve the problem, I don't like it for two reasons:

  1. Logically, I want the fire to act autonomously, meaning the fire is what spreads, and not the tile.

  2. As a result, the Tile class has many methods that are only fire related (such as spread()), which requires me to check - "is this tile composed of a fire element?", which is bad practice.

CODE EXAMPLE

class Fire extends Element{
    public void spread(){
        // Move to all four neighbors and turn them into Fire elements
    }
}

class Wood extends Element{
}

class Tile{
    private Element _element;

}

IN DEPTH

  1. The 'grid' of tiles consists of a 2-dimensional array of Tiles (logic part), and a JavaFx Pane consisting of all tiles (visual part).

  2. A fire 'spreads' when it touches a neighbor tile and turns it from Wood to Fire. A fire ceases to spread when it consumed (=changed to fire) a given threshold of wood, e.g. after it consumed 30 pieces of wood. In a sense, the fire can keep track of the wood it consumed.

Thanks in advance!

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
Alon Emanuel
  • 172
  • 3
  • 10
  • Done so, although my question is pretty abstract making the code snippet kind of non informative – Alon Emanuel Apr 22 '19 at 19:58
  • who voted to close this? Please, explain your choice. Personally, I think it's a very good question about OO design – Andrew Tobilko Apr 22 '19 at 20:11
  • 2
    I think I understand your idea. However, the fire of a tile can consume only neighboring tiles. That means that spreading fire is nothing abstract. It works on the underlying geometry of tiles. Therefore you need to allow access to the neighborhood of tiles. Maybe you should think not about fire spreading, but about fire catching. So a tile made out of would will catch fire if it has a neighboring tile that burns. BTW, will your tiles burn forever, or will the fire cease after some time and become "ash" or something? – luksch Apr 22 '19 at 20:16
  • @luksch I added some answers to the bottom of my post. If I understood you correctly, you suggest the each element should have access to its neighboring *Tiles*, rather than *Elements*? Interesting. Using this logic, the problem can probably be solved, but how would I avoid an infinite circular composition? (Tile>Element and Element>Tile) – Alon Emanuel Apr 22 '19 at 20:33

1 Answers1

2

My instant thought was there should a class to manage fire spreading. Let's say, there's a World class, the one that is aware of the grid of tiles and their nature. Fire doesn't know anything about Wood, its location, its neighbours. The same goes for Wood. They are independent objects that live their lives. The World is up to decide where they reside and how they interact with each other.

Let's imagine Fire releases an event and tells

I wanna spread. Here are the locations I'd like to occupy. My height/my intensity/my frequency/my [any other characteristic of fire] is ..."

The World receives the message, takes into account the fire's characteristics, and modify the grid accordingly.

OK. With this intensity/height/[any other characteristic] of the fire, this and this Wood elements are going to be burnt. I will replace them with new Fire instances (or I will make a copy the existing Fire object and put a reference to it into the expected-to-be-burnt cells).

It would be interesting to have one instance of Fire and keep track of all the elements it burned. I can see a modified version of the copy constructor.

Fire(Fire current, Elements... newlyTakenElements)

Though, you're free to figure out your own way how to record it.

With this, you would be able to restore cells (fully or partially) when the fire comes to end. You could also analyse how the fire was developing. I am not sure if this may come in handy, but it's fascinating to design.


I am thinking of alternatives... I still believe giving too much information (the whole map of tiles) to Fire isn't a way to go and any interaction between Wood and Fire cells should go through the manager class.

Have a look at another scenario that suggests the World provides a partial view of itself as a list of contiguous to the fire elements.

-I wanna spread.

-OK. Here's a list of adjacent burnable elements. I am not aware of your characteristics. It's up to you to decide how many cells (and which ones) you are going to burn.

-I've burned them all. Give me more!

The world gives another list until the fire is sated.

Community
  • 1
  • 1
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • I initially had a 'world manager' class, and I tried to avoid handing it the control over the fire, with the reasoning being "The fire is an autonomous object and should be able to act on its own." Your explanation makes it more reasonable and unless a better solution arises, I think I'll go with it. Thanks! – Alon Emanuel Apr 22 '19 at 20:45
  • 1
    @AlonEmanuel Well, fire isn't *that* autonomous, it's influenced and controlled by many nature's factors/events, so our model of `Fire` consulting `World` is plausible enough to me. – Andrew Tobilko Apr 22 '19 at 21:20