HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

"Ticker" for game timing

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
tickertiminggamefor

Problem

I designed a "Ticker" based on how I imagine Minecraft's tick system works. My ticker calls a method tickRate times a second and provides a Delta Time value (deltaTime) to the method being called.

The issue I have with my code is that I find the update method (which handles timing) to be ugly but I'm not sure what I can do.

My ticker class is designed to be instantiated and used whenever, it does not have to be used right away (which is why I don't set any time related information in the constructor). This is why there is a check for nextTick and lastTick being 0 inside update, as to ensure that the delta time does not go crazy on the first tick. The issue with this is that it looks a bit ugly, however I'm not sure what I could do. I could move the reset code into the reset method, however that would now mean that the reset method is time dependant, and must be only be called when you intend to use the ticker.

Ticker.java

`import java.util.HashSet;
import java.util.Set;

public class Ticker {
private long lastTick;
private long nextTick;
private int tickRate;

private Set tickListeners = new HashSet<>();

public Ticker(int tickRate) {
this.tickRate = tickRate;
}

public void addTickListener(TickListener listener) {
tickListeners.add(listener);
}

public void removeTickListener(TickListener listener) {
tickListeners.remove(listener);
}

public void setTickRate(int tickRate) {
this.tickRate = tickRate;
}

public int getTickRate() {
return tickRate;
}

public void reset() {
lastTick = 0;
nextTick = 0;
}

public boolean update() {
long currentTime = System.currentTimeMillis();

if (currentTime >= nextTick) {
long targetTimeDelta = 1000L / tickRate;

if (lastTick == 0 || nextTick == 0) {
lastTick = currentTime - targetTimeDelta;
nextTick = currentTime;

Solution

This is one of the cleanest code I have come across in a while. Congrats to your lovely, well-written code!

Just some points:

-
I don't like seeing this:

public class Ticker {
    private long lastTick;
    // ...
    }
}


It is more readable (IMO) when you put spaces after the beginning and before the end:

public class Ticker {

    private long lastTick;
    // ...
    }

}


I don't see a reason why not to do so, as the rest of your code is very well spaced.

-
This method:

public boolean update() {
    long currentTime = System.currentTimeMillis();

    if (currentTime >= nextTick) {
        long targetTimeDelta = 1000L / tickRate;

        if (lastTick == 0 || nextTick == 0) {
            lastTick = currentTime - targetTimeDelta;
            nextTick = currentTime;
        }

        float deltaTime = (float) (currentTime - lastTick) / targetTimeDelta;

        for (TickListener listener : tickListeners) {
            listener.onTick(deltaTime);
        }

        lastTick = currentTime;
        nextTick = currentTime + targetTimeDelta;

        return true;
    }

    return false;
}


Just my opinion, but I feel uncomfortable with that many spaces in code. The only place I would use spaces would be:

  • Between Node declarations in JavaFX, or JWhatever declarations in Swing.



  • Where there is an obvious change in what the code will do.



So it would be more like:

public boolean update() {
    long currentTime = System.currentTimeMillis();
    if (currentTime >= nextTick) {
        long targetTimeDelta = 1000L / tickRate;
        if (lastTick == 0 || nextTick == 0) {
            lastTick = currentTime - targetTimeDelta;
            nextTick = currentTime;
        }

        float deltaTime = (float) (currentTime - lastTick) / targetTimeDelta;
        for (TickListener listener : tickListeners) {
            listener.onTick(deltaTime);
        }

        lastTick = currentTime;
        nextTick = currentTime + targetTimeDelta;
        return true;
    }
    return false;
}

Code Snippets

public class Ticker {
    private long lastTick;
    // ...
    }
}
public class Ticker {

    private long lastTick;
    // ...
    }

}
public boolean update() {
    long currentTime = System.currentTimeMillis();

    if (currentTime >= nextTick) {
        long targetTimeDelta = 1000L / tickRate;

        if (lastTick == 0 || nextTick == 0) {
            lastTick = currentTime - targetTimeDelta;
            nextTick = currentTime;
        }

        float deltaTime = (float) (currentTime - lastTick) / targetTimeDelta;

        for (TickListener listener : tickListeners) {
            listener.onTick(deltaTime);
        }

        lastTick = currentTime;
        nextTick = currentTime + targetTimeDelta;

        return true;
    }

    return false;
}
public boolean update() {
    long currentTime = System.currentTimeMillis();
    if (currentTime >= nextTick) {
        long targetTimeDelta = 1000L / tickRate;
        if (lastTick == 0 || nextTick == 0) {
            lastTick = currentTime - targetTimeDelta;
            nextTick = currentTime;
        }

        float deltaTime = (float) (currentTime - lastTick) / targetTimeDelta;
        for (TickListener listener : tickListeners) {
            listener.onTick(deltaTime);
        }

        lastTick = currentTime;
        nextTick = currentTime + targetTimeDelta;
        return true;
    }
    return false;
}

Context

StackExchange Code Review Q#111855, answer score: 6

Revisions (0)

No revisions yet.