Farming system design with ES

Hi

I am implementing farming mechanics into my game.

I am looking into other games to grasp some ideas

Screenshot_2021-04-20_13-36-53

I have a design question related to ES

In the above picture, does it sound a good idea to make each field (soil for growing crops) a separate entity? (each represents a cell in a grid)

And the plant grows on it with another entity that is linked to the field entity with an InField(fieldId) component?

1 Like

It seems fine.

I wonder where the doubt comes from. Maybe there is a hidden gotcha that I don’t see?

1 Like

Thanks for the response. :slightly_smiling_face:

Nothing important. Just wanted to know how other farming games do it and that I am not doing it wrong. :wink:

I am adding the plant growth simulation system. I want it to support offline growth as well. So plants will keep growing even when the player is not in the game. I want to do it by using the “time passed” approach.

The most basic form is to use a GrowthTime component with a start and end time

public class GrowthTime implements PersistentComponent {
   
    private final long startTime;
    private final long endTime;

    public GrowthTime(long startTime, long endTime) {
        this.startTime = startTime;
        this.endTime = endTime;
    }

    public long getStartTime() {
        return startTime;
    }

    public long getEndTime() {
        return endTime;
    }
}

The PlantGrowthSystem will watch for entities with GrowthTime and call the “OnGrowth” action on the plant object type when the time comes. This should work fine with offline growth as well.

But I want to add another factor and that is the WaterLevel of the field (soil). So I want the plant growth only when the water level is > 0, if the water level becomes 0 then the plant must stop growing.

public class WaterLevel implements PersistentComponent {
    private final int level;
    private final long reductionInterval;    // nano time
    private final long lastModifiedTime; // nano time

    /**
     * @param level The water level in [0, 100]
     * @param reductionIntervalSecond The time interval  after which the water level will be reduced by one. This will be
     *                                continued until the water level becomes 0.
     */
    public WaterLevel(int level, long reductionIntervalSecond) {
        if (level < 0 || level > 100) {
            throw new IllegalArgumentException("Level value must be in [0, 100]");
        }
        this.level = level;
        this.reductionInterval = reductionIntervalSecond * 1000000000;
        this.lastModifiedTime = System.nanoTime();
    }

    /**
     * @return The water level between [0, 100] at the current time.
     */
    public double getLevel() {
        return getLevel(System.nanoTime());
    }

    /**
     * @return The water level between [0, 100] at the specified time.
     */
    public double getLevel(long time) {
        if (reductionInterval > 0) {
            double timePassed = (time - lastModifiedTime);
            double reduction = timePassed / reductionInterval;
            return Math.max(0d, level - reduction);
        }

        return level;
    }

    public WaterLevel adjustLevel(int delta) {
        int newLevel = (int) (getLevel() + delta);
        return new WaterLevel(Math.min(Math.max(0, newLevel), 100), reductionInterval);
    }
}

So I need another entity set in PlantGrowthSystem to watch for the WaterLevel of fields and somehow stop the plant from growing and works when offline as well.

My previous implementation of the GrowthTime component (with a start time and end time) is not compatible with this as I need a way to stop the time when the water level is 0.

But I am not sure how should implement this in PlantGrowthSystem while making it compatible with offline growing.

Any idea how to implement this mechanic?

Regards

At some point don’t you end up with some kind of combinatorial complexity that can only be resolved by quickly iterating through time?

Either that, or you estimate.

I guess so. I can imagine other similar mechanics on the way. Quickly iterating through time seems very interesting. Thank you :slightly_smiling_face:

Yeah, these things have a way of chaining together.

It’s easy enough to say "plant will be grown at time x’.
And “water level will be low at time y”.
…and another thing entirely to have plant growth be stunted by water level… which might be consumed by animals… which might get eaten by wolves at a certain rate, etc…

Suddenly, determining what specific time something will happen gets quite tricky.

I will deal with this issue with my AI at some point. I hope to go with the “estimation” route in my case… on average, these x,y,z things will happen every day so if you get there at 2 PM, probably the state will be “this”. and so on.

…but I keep “fast forward the simulation” in my hip pocket. And sometimes they can be combined. Estimate by the hour, catch up to the minute, and so on.

2 Likes