tins2021/animation.go

118 lines
2.7 KiB
Go
Raw Normal View History

package tins2021
import (
"math/rand"
"time"
"opslag.de/schobers/geom"
"opslag.de/schobers/zntg/ui"
)
type AnimatedTexture struct {
Texture ui.Texture
Frames []geom.RectangleF32
}
func NewAnimatedTexture(texture ui.Texture, n int) AnimatedTexture {
frames := make([]geom.RectangleF32, 0, n)
height := float32(texture.Height())
width := float32(texture.Width())
for i := 0; i < n; i++ {
left := width * float32(i) / float32(n)
right := width * float32(i+1) / float32(n)
frames = append(frames, geom.RectF32(left, 0, right, height))
}
return AnimatedTexture{Texture: texture, Frames: frames}
}
func NewSquareAnimatedTexture(texture ui.Texture) AnimatedTexture {
var frames []geom.RectangleF32
height := float32(texture.Height())
width := float32(texture.Width())
for left := float32(0); left < width; left += height {
frames = append(frames, geom.RectF32(left, 0, left+height, height))
}
return AnimatedTexture{Texture: texture, Frames: frames}
}
func (t AnimatedTexture) Scale(scale float32) AnimatedTexture {
frames := make([]geom.RectangleF32, 0, len(t.Frames))
for _, frame := range t.Frames {
frames = append(frames, geom.RectangleF32{Min: frame.Min.Mul(scale), Max: frame.Max.Mul(scale)})
}
return AnimatedTexture{
Texture: t.Texture,
Frames: frames,
}
}
func (t AnimatedTexture) Draw(renderer ui.Renderer, pos geom.PointF32, frame int) {
renderer.DrawTexturePointOptions(t.Texture, pos, ui.DrawOptions{Source: &t.Frames[frame]})
}
type Animation struct {
LastUpdate time.Time
Frame int
}
type Animations struct {
Values map[geom.Point]*Animation
Interval time.Duration
Frames int
AutoReset bool
RandomInit bool
}
func NewAnimations(interval time.Duration, frames int, autoReset, randomInit bool) *Animations {
return &Animations{
Values: map[geom.Point]*Animation{},
Interval: interval,
Frames: frames,
AutoReset: autoReset,
RandomInit: randomInit,
}
}
func (a *Animations) Update() {
now := time.Now()
update := now.Add(-a.Interval)
for _, value := range a.Values {
if value.Frame == a.Frames {
break
}
for value.LastUpdate.Before(update) {
value.LastUpdate = value.LastUpdate.Add(a.Interval)
value.Frame = value.Frame + 1
if value.Frame == a.Frames {
if a.AutoReset {
value.Frame = 0
} else {
break
}
}
}
}
}
func (a *Animations) newAnimation() *Animation {
if a.RandomInit {
return &Animation{
LastUpdate: time.Now().Add(time.Duration(-rand.Int63n(int64(a.Interval)))),
Frame: rand.Intn(a.Frames),
}
}
return &Animation{
LastUpdate: time.Now(),
Frame: 0,
}
}
func (a *Animations) Frame(pos geom.Point) int {
value, ok := a.Values[pos]
if !ok {
value = a.newAnimation()
a.Values[pos] = value
}
return value.Frame
}