A delegate called every frames?

I want to replace

var timer = 100
//function called in an endless loop
fun update() {
    timer --
    println(timer)        
}

with

var timer: Int by TimedVarDelegate(100)
//function called in an endless loop
fun update() {
    println(timer)        
}

Where the printed value is “100”, then “99”, etc…
The ‘update’ function is called every frames

Is it possible to create that “TimedVarDelegate” delegate ?

Do you want a delegate that just decrements the value every time it is accessed? If so, it’s possible:

import kotlin.reflect.*
class Delegate (start: Int) {
    private var value: Int = start
    operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
        return value--
    }
 
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
        this.value = value
    }
}
 fun main() {
   val timer by Delegate(100)
   println(timer)
   // next frame
   println(timer)
}

This delegate will not work however if you access the timer variable more than once per frame. You could however use something like this

import kotlin.reflect.*
class Delegate (start: Int) {
    private var value: Int = start
    operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
        return value
    }
 
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
        this.value = value
    }
    fun nextFrame() { value-- }
}
val timer by Delegate(100)
fun main() {
   val timerDelegate = ::timer.getDelegate() as Delegate
   println(timer)
   timerDelegate.nextFrame() // next frame
   println(timer)
}

It’s the behaviour of your second example that I want.

My program have a lot of these timers and the idea was to eliminate the need to write “aTimedVar --” every time I create a new var like this.

I believe your example works well but it doesn’t seem to make the code more concise though

Well if you have many of those timers you need to decrement at the end of each frame you can just create a list with their delegates and then do something like timerDelegates.forEach(::nextFrame).

But you won’t get around an implicit call for decrementing the values.
Maybe one advantage to the delegate approach is that you can pass a nextFrame function to the delegate to create some custom changes, eg. increment one of the timers instead of decrementing or whatever you want to do. In that case you can also switch the delegate to be generic. Not sure if this is helpful in you current situation though.

Yes, making a list of timers would do the trick. Is there a way to not have to write “list.add(aTimedVar)” for each variables we have ?

If you are 100% sure that you will always update all timers at once you could put the list of timers in the companion object of the Delegate and then automatically add the timer to the list in the constructor

class TimerDelegate {
    init {
        allTimers.add(this)
    }
    // delegate functions ...
    companion object {
        private val allTimers = mutableListOf<TimerDelegate>()
        fun updateAllTimers() = TODO()
   }
}
1 Like

Seems good ! Can’t wait to try it out, thanks