libgdx Timer countdown implmentation

2019-06-04 23:08发布

I want to create efficienty timer in LibGDX framework, that will count the time left for my character. The doSmth() method should be called as many times as some flag is set to true. I know that the third parametr of Timer is that, how many times should it trigger. For now one Im calling the method recursive, but I dont think it is the efficient way.

 public void updateTimer(){
        new Timer().scheduleTask(new Timer.Task() {
    @Override
    public void run() {
      doSmth();
     updateTimer();
    }
},1);
            }

2条回答
淡お忘
2楼-- · 2019-06-04 23:17

The com.badlogic.gdx.utils.Timer executes tasks in the future on the main loop thread,even if your game is in a pause screen, a menu or in another state, you can simply control time in the render method by adding delta time.

    private float timeSeconds = 0f;
    private float period = 1f;

    public void render() {
        //Execute handleEvent each 1 second
        timeSeconds +=Gdx.graphics.getRawDeltaTime();
        if(timeSeconds > period){
            timeSeconds-=period;
            handleEvent();
        }

        [...]

    }

    public void handleEvent() {
         [...]
    }

To keep organized i personally have an array on my main game class that holds all my timed events and process everything on the render cycle. In your case you can put some control variables as you wish.

my implementation example:

// MainGame.java

 private ObjectMap<TimedEventEnum, TimedEvent> hshTimedEvent;

 public void render(){
    executeTimedEvents();
 }

 private void executeTimedEvents() {
    for (ObjectMap.Entry<TimedEventEnum, TimedEvent> entry : hshTimedEvent) {
            TimedEvent event = entry.value;
            event.process();
    }
 }

 public void killEvent(TimedEventEnum event) {
        hshTimedEvent.remove(event);
 }

// TimedEventEnum.java

public enum TimedEventEnum {
        COUNT_MONEY,
        CHECK_FOR_ACHIEVS,
        ANOTHER_EVENT_EXAMPLE
    }

//CountMoneyTimedEvent.java

public class CountMoneyTimedEvent extends Timer implements TimedEvent {

        public CountMoneyTimedEvent() {
            super();
            init(this, 4f, false);
        }

        @Override
        public void execute() {
            //execute logic here
        }

        @Override
        public void reset() {
            this.timesFired = 0L;
        }
    }

//Timer.java

public abstract class Timer {

        private Float deltaCount;
        private Float timeToEvent;
        private Boolean isRepeatable;
        protected Long timesFired;

        private TimedEvent event;

        Timer() {
        }

        public void init(TimedEvent event, Float eventTime, Boolean isRepeatable) {
            this.deltaCount = 0f;
            this.timeToEvent = eventTime;
            this.isRepeatable = isRepeatable;
            this.timesFired = 0L;
            this.event = event;
        }

        public void process() {
            if (isEventTime()) {
                event.execute();
            }
        }

        private Boolean isEventTime() {
            if (event != null && (isRepeatable || timesFired == 0)) {
                deltaCount += Gdx.graphics.getRawDeltaTime();
                if (deltaCount > timeToEvent) {
                    deltaCount -= timeToEvent;
                    timesFired++;
                    return true;
                }
            }
            return false;
        }

        protected void executeNextEvent() {
            deltaCount = timeToEvent;
        }
    }

// TimedEvent.java

public interface TimedEvent {
    void execute();
    void reset();
    void process();
}
查看更多
迷人小祖宗
3楼-- · 2019-06-04 23:19

It would be more accurate to use a repeat count. Your method will introduce a bit of error each time the task is run, because the task is run on the GL thread, so it will occur just slightly after one second, but you are repeating it one second after that. So with each repeat you are slightly further behind.

private Timer.Task myTimerTask = new Timer.Task() {
    @Override
    public void run() {
      doSmth();
    }
};

public void startTimer(){
    Timer.schedule(myTimerTask, 1f, 1f);
}

And when you need to stop it:

myTimerTask.cancel();
查看更多
登录 后发表回答