Timer and animation |
The mini-app framework only calls onDraw() when the screen needs to be redrawn. As we saw before, you can request this using update. Since you can only call update from one of your methods, which are only called during a tap handler, this means that the screen will remain static until the user performs some action.
If you want the display to change over time, you need to use a timer. A timer is set by calling the context method after. It takes two arguments, the first indicates a number \(m\) of milliseconds, the second is a function object taking no parameters. The function object will be called automatically \(m\) milliseconds later.
Here is an example that uses a timer to let a ball drop down on the screen: (animation.kt):
// // Animation with "after" // import org.otfried.cs109.Context import org.otfried.cs109.MiniApp import org.otfried.cs109.Canvas import org.otfried.cs109.Color import org.otfried.cs109.DrawStyle import org.otfried.cs109.TextAlign class Main(val ctx: Context) : MiniApp { var y: Double = 0.0 var dead = false init { ctx.setTitle("Animation demo") ctx.onFling { x0, y0, dir, dist -> if (dir == 'u') y = 0.0; ctx.update() } ctx.after(20) { animate() } } fun animate() { y += 6.0 ctx.update() if (y > ctx.height) dead = true else ctx.after(20) { animate() } } override fun onDraw(canvas: Canvas) { if (dead) { canvas.clear(Color(172, 0, 0)) // blood-red } else { val x = canvas.width / 2.0 canvas.clear(Color(255, 255, 192)) canvas.setColor(Color.BLUE) canvas.drawCircle(x, y, 30.0) } } }
You can fling upwards to move the ball back to the beginning. If you fail to do so before it reaches the bottom, the animation ends.
Note that we need to call ctx.after again inside the animate method to keep the animation running.
Some practical considerations:
Timer and animation |