118 lines
2.7 KiB
Go
118 lines
2.7 KiB
Go
|
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
|
||
|
}
|