feat: implemented basic animation. (very raw)
This commit is contained in:
parent
60cd4e9e75
commit
f2d7feb8a4
7 changed files with 118 additions and 29 deletions
77
animation.go
77
animation.go
|
@ -1,15 +1,67 @@
|
||||||
package gg
|
package gg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Animation struct {
|
type Animation []*Image
|
||||||
Frames []*Image
|
|
||||||
|
type AnimationDefine struct{
|
||||||
|
Id AnimationId
|
||||||
|
Indexes []ImageRectIndex
|
||||||
|
}
|
||||||
|
// Animation define
|
||||||
|
func AD(id AnimationId, indexes ...ImageRectIndex) AnimationDefine {
|
||||||
|
return AnimationDefine{
|
||||||
|
Id: id,
|
||||||
|
Indexes: indexes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (ad AnimationDefine) DefRow(y int, xs ...int) AnimationDefine {
|
||||||
|
for _, x := range xs {
|
||||||
|
ad.Indexes = append(ad.Indexes, ImageRectIndex{x, y})
|
||||||
|
}
|
||||||
|
return ad
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad AnimationDefine) DefCol(x int, ys ...int) AnimationDefine {
|
||||||
|
for _, y := range ys {
|
||||||
|
ad.Indexes = append(ad.Indexes, ImageRectIndex{x, y})
|
||||||
|
}
|
||||||
|
return ad
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnimationId int
|
type AnimationId int
|
||||||
type AnimationSet map[AnimationId] *Animation
|
type AnimationSet map[AnimationId] Animation
|
||||||
|
func AnimationSetFromImage(
|
||||||
|
img *Image,
|
||||||
|
w, h int,
|
||||||
|
defines ...AnimationDefine,
|
||||||
|
) (AnimationSet, error) {
|
||||||
|
set := AnimationSet{}
|
||||||
|
|
||||||
|
r := img.Bounds()
|
||||||
|
fw, fh := r.Dx()/w, r.Dy()/h
|
||||||
|
|
||||||
|
for _, define := range defines {
|
||||||
|
fmt.Println("def-idx-len:", len(define.Indexes))
|
||||||
|
animation := make(Animation, len(define.Indexes))
|
||||||
|
for i := range animation {
|
||||||
|
idx := define.Indexes[i]
|
||||||
|
animation[i] = ebiten.NewImageFromImage(img.SubImage(
|
||||||
|
ImageRect{
|
||||||
|
Min: ImagePoint{idx.X*fw, idx.Y*fh},
|
||||||
|
Max: ImagePoint{(idx.X+1)*fw, (idx.Y+1)*fh},
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
fmt.Println("animation-len:", len(animation))
|
||||||
|
set[define.Id] = animation
|
||||||
|
}
|
||||||
|
|
||||||
|
return set, nil
|
||||||
|
}
|
||||||
|
|
||||||
// The type implements animated sprites.
|
// The type implements animated sprites.
|
||||||
type AnimatedSprite struct {
|
type AnimatedSprite struct {
|
||||||
|
@ -17,18 +69,31 @@ type AnimatedSprite struct {
|
||||||
Animations AnimationSet
|
Animations AnimationSet
|
||||||
AnimationId AnimationId
|
AnimationId AnimationId
|
||||||
CurrentFrame int
|
CurrentFrame int
|
||||||
TimeBetweenFrames time.Duration
|
// This is time between animation frames, not
|
||||||
|
// engine ones.
|
||||||
|
TimeBetweenFrames Duration
|
||||||
|
duration Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (as *AnimatedSprite) Animate(id AnimationId) bool {
|
func (as *AnimatedSprite) Animate(id AnimationId) bool {
|
||||||
_, ok := as.Animations[id]
|
_, ok := as.Animations[id]
|
||||||
if ok {
|
if ok {
|
||||||
|
as.duration = 0
|
||||||
as.AnimationId = id
|
as.AnimationId = id
|
||||||
}
|
}
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (as *AnimatedSprite) Draw(c *Context) []EVertex {
|
func (as *AnimatedSprite) Draw(c *Context) []EVertex {
|
||||||
return nil
|
as.duration += c.DrawDt()
|
||||||
|
frames := as.Animations[as.AnimationId]
|
||||||
|
fmt.Println("len:", len(frames))
|
||||||
|
fullTime := Duration(len(frames)) * as.TimeBetweenFrames
|
||||||
|
if as.duration > fullTime {
|
||||||
|
as.duration -= fullTime
|
||||||
|
}
|
||||||
|
as.Images[0] = frames[(as.duration/as.TimeBetweenFrames)%Duration(len(frames))]
|
||||||
|
|
||||||
|
return as.Sprite.Draw(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,13 @@ const (
|
||||||
LowestL
|
LowestL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Stand gg.AnimationId = iota
|
||||||
|
Walk
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
playerAnimations gg.AnimationSet
|
||||||
playerImg *gg.Image
|
playerImg *gg.Image
|
||||||
player *Player
|
player *Player
|
||||||
rectMove gg.Rectangle
|
rectMove gg.Rectangle
|
||||||
|
@ -45,6 +51,12 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
rect = NewRect()
|
rect = NewRect()
|
||||||
|
|
||||||
|
playerAnimations, _ = gg.AnimationSetFromImage(
|
||||||
|
playerImg,
|
||||||
|
8, 3,
|
||||||
|
gg.AD(Walk).DefRow(0, 0, 1, 2, 3, 4),
|
||||||
|
)
|
||||||
player = NewPlayer()
|
player = NewPlayer()
|
||||||
tri = NewTri()
|
tri = NewTri()
|
||||||
|
|
||||||
|
@ -82,6 +94,7 @@ func main() {
|
||||||
}
|
}
|
||||||
e.Spawn(txt)
|
e.Spawn(txt)
|
||||||
|
|
||||||
|
|
||||||
//fmt.Println(rect.GetLayer(), player.GetLayer())
|
//fmt.Println(rect.GetLayer(), player.GetLayer())
|
||||||
fmt.Println("Starting...")
|
fmt.Println("Starting...")
|
||||||
err = e.Run()
|
err = e.Run()
|
||||||
|
|
|
@ -3,12 +3,13 @@ package main
|
||||||
import (
|
import (
|
||||||
//"math/rand"
|
//"math/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
import "vultras.su/core/gg"
|
import "vultras.su/core/gg"
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
gg.Sprite
|
gg.AnimatedSprite
|
||||||
MoveSpeed gg.Float
|
MoveSpeed gg.Float
|
||||||
ScaleSpeed gg.Float
|
ScaleSpeed gg.Float
|
||||||
Spawned bool
|
Spawned bool
|
||||||
|
@ -17,17 +18,15 @@ type Player struct {
|
||||||
func NewPlayer() *Player {
|
func NewPlayer() *Player {
|
||||||
ret := &Player{}
|
ret := &Player{}
|
||||||
ret.Transform = gg.T()
|
ret.Transform = gg.T()
|
||||||
fmt.Println("transform:", ret.Transform)
|
|
||||||
//ret.Parent = rect
|
|
||||||
ret.Scale = gg.V2(1)
|
ret.Scale = gg.V2(1)
|
||||||
// Around center.
|
|
||||||
ret.Around = gg.V2(.5)
|
ret.Around = gg.V2(.5)
|
||||||
ret.MoveSpeed = 90.
|
ret.MoveSpeed = 90.
|
||||||
ret.ScaleSpeed = .2
|
ret.ScaleSpeed = .2
|
||||||
|
ret.Animations = playerAnimations
|
||||||
|
ret.TimeBetweenFrames = time.Second/5
|
||||||
|
fmt.Println("player-walk", ret.Animate(Walk))
|
||||||
|
|
||||||
ret.Visible = true
|
ret.Visible = true
|
||||||
|
|
||||||
ret.Images[0] = playerImg
|
|
||||||
ret.Layer = PlayerL
|
ret.Layer = PlayerL
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
@ -40,7 +39,7 @@ func (p *Player) Update(c *Context) {
|
||||||
if p.Spawned {
|
if p.Spawned {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dt := c.Dt()
|
dt := c.Dt().Seconds()
|
||||||
cam := c.Camera
|
cam := c.Camera
|
||||||
keys := c.Keys()
|
keys := c.Keys()
|
||||||
|
|
||||||
|
@ -124,7 +123,7 @@ func (p *Player) Update(c *Context) {
|
||||||
c.Camera.Position = pos.Sub(ec.Abs)
|
c.Camera.Position = pos.Sub(ec.Abs)
|
||||||
case *gg.WheelChange:
|
case *gg.WheelChange:
|
||||||
c.Camera.Scale = c.Camera.Scale.Add(gg.V2(
|
c.Camera.Scale = c.Camera.Scale.Add(gg.V2(
|
||||||
ec.Offset.Y * c.Dt() * p.ScaleSpeed * 40,
|
ec.Offset.Y * dt * p.ScaleSpeed * 40,
|
||||||
))
|
))
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ func NewTri() *Tri {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tri) Update(c *Context) {
|
func (t *Tri) Update(c *Context) {
|
||||||
dt := c.Dt()
|
dt := c.Dt().Seconds()
|
||||||
if t.ContainsPoint(c.AbsCursorPosition()) {
|
if t.ContainsPoint(c.AbsCursorPosition()) {
|
||||||
t.Color = gg.Rgba(0, 1, 0, 1)
|
t.Color = gg.Rgba(0, 1, 0, 1)
|
||||||
} else {
|
} else {
|
||||||
|
@ -53,12 +53,12 @@ func (t *Tri) Update(c *Context) {
|
||||||
case gg.KeyM:
|
case gg.KeyM:
|
||||||
absPos := t.AbsPosition()
|
absPos := t.AbsPosition()
|
||||||
t.SetAbsPosition(
|
t.SetAbsPosition(
|
||||||
absPos.Add(gg.V(0, 100*c.Dt()*d)),
|
absPos.Add(gg.V(0, 100*dt*d)),
|
||||||
)
|
)
|
||||||
case gg.KeyN:
|
case gg.KeyN:
|
||||||
absPos := t.AbsPosition()
|
absPos := t.AbsPosition()
|
||||||
t.SetAbsPosition(
|
t.SetAbsPosition(
|
||||||
absPos.Add(gg.V(100*c.Dt()*d, 0)),
|
absPos.Add(gg.V(100*dt*d, 0)),
|
||||||
)
|
)
|
||||||
case gg.KeyV:
|
case gg.KeyV:
|
||||||
t.Rotation += d * gg.Pi * 0.3 * dt
|
t.Rotation += d * gg.Pi * 0.3 * dt
|
||||||
|
|
24
engine.go
24
engine.go
|
@ -61,12 +61,12 @@ type Engine struct {
|
||||||
// If is set to nil then the engine will panic.
|
// If is set to nil then the engine will panic.
|
||||||
Camera *Camera
|
Camera *Camera
|
||||||
|
|
||||||
lastTime time.Time
|
drawLastTime time.Time
|
||||||
dt Float
|
drawdt Duration
|
||||||
|
|
||||||
// Frame delta time.
|
// Frame delta time.
|
||||||
fdt Float
|
dt Duration
|
||||||
fLastTime time.Time
|
lastTime time.Time
|
||||||
|
|
||||||
// Temporary stuff
|
// Temporary stuff
|
||||||
keys, prevKeys []Key
|
keys, prevKeys []Key
|
||||||
|
@ -228,7 +228,7 @@ func (e *Engine) AbsCursorPosition() Vector {
|
||||||
|
|
||||||
func (e *engine) Update() error {
|
func (e *engine) Update() error {
|
||||||
eng := (*Engine)(e)
|
eng := (*Engine)(e)
|
||||||
e.fdt = time.Since(e.fLastTime).Seconds()
|
e.dt = time.Since(e.lastTime)
|
||||||
|
|
||||||
// Buffering the context for faster.
|
// Buffering the context for faster.
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ func (e *engine) Update() error {
|
||||||
object.Input() <- c
|
object.Input() <- c
|
||||||
}
|
}
|
||||||
e.wg.Wait()
|
e.wg.Wait()
|
||||||
e.fLastTime = time.Now()
|
e.lastTime = time.Now()
|
||||||
e.frame++
|
e.frame++
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -323,7 +323,7 @@ var (
|
||||||
defaultTriOptions = &ebiten.DrawTrianglesOptions{}
|
defaultTriOptions = &ebiten.DrawTrianglesOptions{}
|
||||||
)
|
)
|
||||||
func (e *engine) Draw(img *ebiten.Image) {
|
func (e *engine) Draw(img *ebiten.Image) {
|
||||||
e.dt = time.Since(e.lastTime).Seconds()
|
e.drawdt = time.Since(e.drawLastTime)
|
||||||
eng := (*Engine)(e)
|
eng := (*Engine)(e)
|
||||||
m := map[Layer][]Drawer{}
|
m := map[Layer][]Drawer{}
|
||||||
for _, object := range eng.Objects.store {
|
for _, object := range eng.Objects.store {
|
||||||
|
@ -378,7 +378,7 @@ func (e *engine) Draw(img *ebiten.Image) {
|
||||||
|
|
||||||
// Empty the buff to generate it again.
|
// Empty the buff to generate it again.
|
||||||
eng.Camera.buffered = false
|
eng.Camera.buffered = false
|
||||||
e.lastTime = time.Now()
|
e.drawLastTime = time.Now()
|
||||||
e.dframe++
|
e.dframe++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,8 +391,8 @@ func (e *engine) Layout(ow, oh int) (int, int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the delta time.
|
// Return the delta time.
|
||||||
func (e *Engine) Dt() Float {
|
func (e *Engine) DrawDt() Duration {
|
||||||
return e.dt
|
return e.drawdt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) Dframe() uint {
|
func (e *Engine) Dframe() uint {
|
||||||
|
@ -400,8 +400,8 @@ func (e *Engine) Dframe() uint {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the current fixed delta time.
|
// Return the current fixed delta time.
|
||||||
func (e *Engine) Fdt() Float {
|
func (e *Engine) Dt() Duration {
|
||||||
return 1/60
|
return e.dt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) Frame() uint {
|
func (e *Engine) Frame() uint {
|
||||||
|
|
5
img.go
5
img.go
|
@ -9,6 +9,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Image = ebiten.Image
|
type Image = ebiten.Image
|
||||||
|
type ImageRect = image.Rectangle
|
||||||
|
type ImagePoint = image.Point
|
||||||
|
type ImageRectIndex struct {
|
||||||
|
X, Y int
|
||||||
|
}
|
||||||
|
|
||||||
type ColorV uint32
|
type ColorV uint32
|
||||||
type ColorM = ebiten.ColorM
|
type ColorM = ebiten.ColorM
|
||||||
|
|
7
time.go
7
time.go
|
@ -7,3 +7,10 @@ import (
|
||||||
type Time = time.Time
|
type Time = time.Time
|
||||||
type Duration = time.Duration
|
type Duration = time.Duration
|
||||||
|
|
||||||
|
const (
|
||||||
|
ZeroDuration Duration = 0
|
||||||
|
Microsecond = time.Microsecond
|
||||||
|
Millisecond = time.Millisecond
|
||||||
|
Second = time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue