anim overhaul, again
This commit is contained in:
parent
d89a1c2e71
commit
df5afe11c1
9 changed files with 179 additions and 157 deletions
|
@ -3,42 +3,51 @@ package engine
|
|||
import "encoding/gob"
|
||||
|
||||
// Ensure Anim satisfies Animer.
|
||||
var _ Animer = &Anim{}
|
||||
var _ interface {
|
||||
Cell() int
|
||||
Reset()
|
||||
Updater
|
||||
} = &Anim{}
|
||||
|
||||
func init() {
|
||||
gob.Register(&Anim{})
|
||||
}
|
||||
|
||||
// AnimFrame describes a frame in an animation.
|
||||
type AnimFrame struct {
|
||||
Frame int // show this frame
|
||||
// AnimDef defines an animation, as a sequence of steps and other information.
|
||||
type AnimDef struct {
|
||||
Steps []AnimStep
|
||||
OneShot bool
|
||||
}
|
||||
|
||||
// NewAnim spawns a new anim using this def, or nil if d is nil.
|
||||
func (d *AnimDef) NewAnim() *Anim {
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
return &Anim{Def: d}
|
||||
}
|
||||
|
||||
// AnimStep describes a step in an animation.
|
||||
type AnimStep struct {
|
||||
Cell int // show this cell
|
||||
Duration int // for this long, in ticks
|
||||
}
|
||||
|
||||
// Anim is n animation being displayed, together with the current state.
|
||||
// A nil *Anim can be used, but always returns 0 for the current frame.
|
||||
// Anim is the current state of an animation being played (think of it as an
|
||||
// instance of an AnimDef). nil *Anim can be used, but always returns 0 for the
|
||||
// current frame.
|
||||
type Anim struct {
|
||||
Frames []AnimFrame
|
||||
OneShot bool
|
||||
Index int
|
||||
Ticks int
|
||||
Def *AnimDef
|
||||
Index int // current step index
|
||||
Ticks int // ticks spent at this step
|
||||
}
|
||||
|
||||
// Copy makes a shallow copy of the anim.
|
||||
func (a *Anim) Copy() *Anim {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
a2 := *a
|
||||
return &a2
|
||||
}
|
||||
|
||||
// CurrentFrame returns the frame number for the current index.
|
||||
func (a *Anim) CurrentFrame() int {
|
||||
// Cell returns the cell index for the current step.
|
||||
func (a *Anim) Cell() int {
|
||||
if a == nil {
|
||||
return 0
|
||||
}
|
||||
return a.Frames[a.Index].Frame
|
||||
return a.Def.Steps[a.Index].Cell
|
||||
}
|
||||
|
||||
// Reset resets both Index and Ticks to 0.
|
||||
|
@ -55,15 +64,15 @@ func (a *Anim) Update() error {
|
|||
return nil
|
||||
}
|
||||
a.Ticks++
|
||||
if a.OneShot && a.Index == len(a.Frames)-1 {
|
||||
if a.Def.OneShot && a.Index == len(a.Def.Steps)-1 {
|
||||
// on the last frame of a one shot so remain on final frame
|
||||
return nil
|
||||
}
|
||||
if a.Ticks >= a.Frames[a.Index].Duration {
|
||||
if a.Ticks >= a.Def.Steps[a.Index].Duration {
|
||||
a.Ticks = 0
|
||||
a.Index++
|
||||
}
|
||||
if !a.OneShot && a.Index >= len(a.Frames) {
|
||||
if !a.Def.OneShot && a.Index >= len(a.Def.Steps) {
|
||||
a.Index = 0
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"io/fs"
|
||||
)
|
||||
|
||||
// TODO: tidy this crap up
|
||||
// Anims probably belong with Sheet
|
||||
|
||||
var (
|
||||
animCache = make(map[assetKey]Anim)
|
||||
|
||||
_ interface {
|
||||
Animer
|
||||
Loader
|
||||
} = &AnimRef{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
gob.Register(&AnimRef{})
|
||||
}
|
||||
|
||||
// AnimRef manages an Anim using a premade AnimDef from the cache.
|
||||
type AnimRef struct {
|
||||
Path string
|
||||
|
||||
anim Anim
|
||||
}
|
||||
|
||||
func (r *AnimRef) Load(assets fs.FS) error {
|
||||
// Fast path: set r.anim to a copy
|
||||
anim, found := animCache[assetKey{assets, r.Path}]
|
||||
if found {
|
||||
r.anim = anim
|
||||
return nil
|
||||
}
|
||||
// Slow path: load from gobz file
|
||||
if err := LoadGobz(&r.anim, assets, r.Path); err != nil {
|
||||
return err
|
||||
}
|
||||
animCache[assetKey{assets, r.Path}] = r.anim
|
||||
return nil
|
||||
}
|
||||
|
||||
// CurrentFrame returns the value of CurrentFrame from r.anim.
|
||||
func (r *AnimRef) CurrentFrame() int { return r.anim.CurrentFrame() }
|
||||
|
||||
// Reset calls Reset on r.anim.
|
||||
func (r *AnimRef) Reset() { r.anim.Reset() }
|
||||
|
||||
// Update calls Update on r.anim.
|
||||
func (r *AnimRef) Update() error { return r.anim.Update() }
|
|
@ -12,7 +12,6 @@ import (
|
|||
var (
|
||||
// TypeOf(pointer to interface).Elem() is "idiomatic" -
|
||||
// see https://pkg.go.dev/reflect#example-TypeOf
|
||||
AnimerType = reflect.TypeOf((*Animer)(nil)).Elem()
|
||||
BounderType = reflect.TypeOf((*Bounder)(nil)).Elem()
|
||||
ColliderType = reflect.TypeOf((*Collider)(nil)).Elem()
|
||||
DisablerType = reflect.TypeOf((*Disabler)(nil)).Elem()
|
||||
|
@ -28,7 +27,6 @@ var (
|
|||
|
||||
// Behaviours lists all the behaviours that can be queried with Game.Query.
|
||||
Behaviours = []reflect.Type{
|
||||
AnimerType,
|
||||
BounderType,
|
||||
ColliderType,
|
||||
DisablerType,
|
||||
|
@ -44,14 +42,6 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
// Animer components have a current frame index.
|
||||
type Animer interface {
|
||||
Updater
|
||||
|
||||
CurrentFrame() int
|
||||
Reset()
|
||||
}
|
||||
|
||||
// Bounder components have a bounding rectangle.
|
||||
type Bounder interface {
|
||||
BoundingRect() image.Rectangle
|
||||
|
|
|
@ -13,24 +13,33 @@ var _ interface {
|
|||
|
||||
// Sheet handles images that consist of a grid of equally sized regions
|
||||
// (cells) and can produce subimages for the cell at an index. This is useful
|
||||
// for various applications such as sprite animation and tile maps.
|
||||
// for various applications such as sprite animation and tile maps. Additionally
|
||||
// each sheet carries a collection of animations that use the sheet.
|
||||
type Sheet struct {
|
||||
AnimDefs map[string]*AnimDef
|
||||
CellSize image.Point
|
||||
Src ImageRef
|
||||
|
||||
w int // width as measured in number of cells
|
||||
}
|
||||
|
||||
// NewAnim returns a new Anim for the given key, or nil if not found in
|
||||
// AnimDefs.
|
||||
func (s *Sheet) NewAnim(key string) *Anim {
|
||||
return s.AnimDefs[key].NewAnim()
|
||||
}
|
||||
|
||||
// Prepare computes the width of the image (in cells).
|
||||
func (s *Sheet) Prepare(*Game) error {
|
||||
s.w, _ = s.Src.Image().Size()
|
||||
s.w /= s.CellSize.X
|
||||
return nil
|
||||
}
|
||||
|
||||
// Scan returns the Src.
|
||||
func (s *Sheet) Scan() []interface{} { return []interface{}{&s.Src} }
|
||||
|
||||
// SubImage returns an *ebiten.Image corresponding to the cell at the given
|
||||
// index.
|
||||
// SubImage returns an *ebiten.Image corresponding to the given cell index.
|
||||
func (s *Sheet) SubImage(i int) *ebiten.Image {
|
||||
p := pmul(image.Pt(i%s.w, i/s.w), s.CellSize)
|
||||
r := image.Rectangle{p, p.Add(s.CellSize)}
|
||||
|
|
|
@ -30,10 +30,12 @@ type Sprite struct {
|
|||
anim *Anim
|
||||
}
|
||||
|
||||
// Draw draws the current cell to the screen.
|
||||
func (s *Sprite) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||
screen.DrawImage(s.Sheet.SubImage(s.anim.CurrentFrame()), opts)
|
||||
screen.DrawImage(s.Sheet.SubImage(s.anim.Cell()), opts)
|
||||
}
|
||||
|
||||
// Scan returns the Actor and the Sheet.
|
||||
func (s *Sprite) Scan() []interface{} {
|
||||
return []interface{}{
|
||||
&s.Actor,
|
||||
|
@ -41,6 +43,8 @@ func (s *Sprite) Scan() []interface{} {
|
|||
}
|
||||
}
|
||||
|
||||
// SetAnim sets the Anim to use for the sprite. If it is not the same as the
|
||||
// one currently set, it resets the new anim.
|
||||
func (s *Sprite) SetAnim(a *Anim) {
|
||||
if s.anim != a {
|
||||
a.Reset()
|
||||
|
@ -48,11 +52,12 @@ func (s *Sprite) SetAnim(a *Anim) {
|
|||
s.anim = a
|
||||
}
|
||||
|
||||
// Transform returns a translation by the FrameOffset.
|
||||
func (s *Sprite) Transform() (opts ebiten.DrawImageOptions) {
|
||||
opts.GeoM.Translate(pfloat(s.Actor.Pos.Add(s.FrameOffset)))
|
||||
return opts
|
||||
}
|
||||
|
||||
// anim can change a bit so we don't tell Game about it, but that means it must
|
||||
// be updated here.
|
||||
// Update updates the Sprite's anim. anim can change a bit so we don't tell Game
|
||||
// about it, but that means it must be updated manually.
|
||||
func (s *Sprite) Update() error { return s.anim.Update() }
|
||||
|
|
|
@ -2,7 +2,9 @@ package engine
|
|||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"image"
|
||||
"io/fs"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
@ -23,7 +25,7 @@ var (
|
|||
_ interface {
|
||||
Tile
|
||||
Scanner
|
||||
} = AnimatedTile{}
|
||||
} = &AnimatedTile{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -77,11 +79,27 @@ func (t *Tilemap) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
|||
geom.Concat(og)
|
||||
opts.GeoM = geom
|
||||
|
||||
src := t.Sheet.SubImage(tile.CellIndex())
|
||||
src := t.Sheet.SubImage(tile.Cell())
|
||||
screen.DrawImage(src, opts)
|
||||
}
|
||||
}
|
||||
|
||||
// Load instantiates animations for all AnimatedTiles.
|
||||
func (t *Tilemap) Load(fs.FS) error {
|
||||
for _, tile := range t.Map {
|
||||
at, ok := tile.(*AnimatedTile)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
ad, found := t.Sheet.AnimDefs[at.AnimKey]
|
||||
if !found {
|
||||
return fmt.Errorf("anim key %q not in sheet AnimDefs", at.AnimKey)
|
||||
}
|
||||
at.anim = ad.NewAnim()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Scan returns a slice containing Src and all non-nil tiles.
|
||||
func (t *Tilemap) Scan() []interface{} {
|
||||
c := make([]interface{}, 1, len(t.Map)+1)
|
||||
|
@ -116,20 +134,22 @@ func (t *Tilemap) TileBounds(wc image.Point) image.Rectangle {
|
|||
|
||||
// Tile is the interface needed by Tilemap.
|
||||
type Tile interface {
|
||||
CellIndex() int
|
||||
Cell() int
|
||||
}
|
||||
|
||||
// StaticTile returns a fixed tile index.
|
||||
type StaticTile int
|
||||
|
||||
func (s StaticTile) CellIndex() int { return int(s) }
|
||||
func (s StaticTile) Cell() int { return int(s) }
|
||||
|
||||
// AnimatedTile uses an Anim to choose a tile index.
|
||||
type AnimatedTile struct {
|
||||
Anim Animer
|
||||
AnimKey string
|
||||
|
||||
anim *Anim
|
||||
}
|
||||
|
||||
func (a AnimatedTile) CellIndex() int { return a.Anim.CurrentFrame() }
|
||||
func (a *AnimatedTile) Cell() int { return a.anim.Cell() }
|
||||
|
||||
// Scan returns a.Anim.
|
||||
func (a AnimatedTile) Scan() []interface{} { return []interface{}{a.Anim} }
|
||||
// Scan returns a.anim.
|
||||
func (a *AnimatedTile) Scan() []interface{} { return []interface{}{a.anim} }
|
||||
|
|
|
@ -99,7 +99,7 @@ type WallUnit struct {
|
|||
|
||||
// Draw draws this wall unit.
|
||||
func (u *WallUnit) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||
screen.DrawImage(u.wall.Sheet.SubImage(u.Tile.CellIndex()), opts)
|
||||
screen.DrawImage(u.wall.Sheet.SubImage(u.Tile.Cell()), opts)
|
||||
}
|
||||
|
||||
// Scan returns the Tile.
|
||||
|
|
68
game/aw.go
68
game/aw.go
|
@ -2,6 +2,8 @@ package game
|
|||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"math"
|
||||
|
||||
|
@ -182,39 +184,41 @@ func (aw *Awakeman) realUpdate() error {
|
|||
}
|
||||
|
||||
func (aw *Awakeman) Prepare(game *engine.Game) error {
|
||||
aw.camera = game.Component(aw.CameraID).(*engine.Camera)
|
||||
aw.toast, _ = game.Component(aw.ToastID).(*engine.DebugToast)
|
||||
cam, ok := game.Component(aw.CameraID).(*engine.Camera)
|
||||
if !ok {
|
||||
return fmt.Errorf("component %q not *engine.Camera", aw.CameraID)
|
||||
}
|
||||
aw.camera = cam
|
||||
tst, ok := game.Component(aw.ToastID).(*engine.DebugToast)
|
||||
if !ok {
|
||||
return fmt.Errorf("component %q not *engine.DebugToast", aw.ToastID)
|
||||
}
|
||||
aw.toast = tst
|
||||
|
||||
aw.animIdleLeft = &engine.Anim{Frames: []engine.AnimFrame{
|
||||
{Frame: 1, Duration: 60},
|
||||
}}
|
||||
aw.animIdleRight = &engine.Anim{Frames: []engine.AnimFrame{
|
||||
{Frame: 0, Duration: 60},
|
||||
}}
|
||||
aw.animRunLeft = &engine.Anim{Frames: []engine.AnimFrame{
|
||||
{Frame: 14, Duration: 3},
|
||||
{Frame: 15, Duration: 5},
|
||||
{Frame: 16, Duration: 3},
|
||||
{Frame: 17, Duration: 3},
|
||||
}}
|
||||
aw.animRunRight = &engine.Anim{Frames: []engine.AnimFrame{
|
||||
{Frame: 10, Duration: 3},
|
||||
{Frame: 11, Duration: 5},
|
||||
{Frame: 12, Duration: 3},
|
||||
{Frame: 13, Duration: 3},
|
||||
}}
|
||||
aw.animWalkRight = &engine.Anim{Frames: []engine.AnimFrame{
|
||||
{Frame: 2, Duration: 6},
|
||||
{Frame: 3, Duration: 6},
|
||||
{Frame: 4, Duration: 6},
|
||||
{Frame: 5, Duration: 6},
|
||||
}}
|
||||
aw.animWalkLeft = &engine.Anim{Frames: []engine.AnimFrame{
|
||||
{Frame: 6, Duration: 6},
|
||||
{Frame: 7, Duration: 6},
|
||||
{Frame: 8, Duration: 6},
|
||||
{Frame: 9, Duration: 6},
|
||||
}}
|
||||
aw.animIdleLeft = aw.Sprite.Sheet.NewAnim("idle_left")
|
||||
if aw.animIdleLeft == nil {
|
||||
return errors.New("missing anim idle_left")
|
||||
}
|
||||
aw.animIdleRight = aw.Sprite.Sheet.NewAnim("idle_right")
|
||||
if aw.animIdleRight == nil {
|
||||
return errors.New("missing anim idle_right")
|
||||
}
|
||||
aw.animRunLeft = aw.Sprite.Sheet.NewAnim("run_left")
|
||||
if aw.animRunLeft == nil {
|
||||
return errors.New("missing anim run_left")
|
||||
}
|
||||
aw.animRunRight = aw.Sprite.Sheet.NewAnim("run_right")
|
||||
if aw.animRunRight == nil {
|
||||
return errors.New("missing anim run_right")
|
||||
}
|
||||
aw.animWalkRight = aw.Sprite.Sheet.NewAnim("walk_left")
|
||||
if aw.animWalkRight == nil {
|
||||
return errors.New("missing anim walk_left")
|
||||
}
|
||||
aw.animWalkLeft = aw.Sprite.Sheet.NewAnim("walk_right")
|
||||
if aw.animWalkLeft == nil {
|
||||
return errors.New("missing anim walk_right")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
82
main.go
82
main.go
|
@ -73,32 +73,21 @@ func main() {
|
|||
|
||||
// writeLevel1 dumps a test level into level1.gobz
|
||||
func writeLevel1() {
|
||||
redTileAnim := &engine.Anim{Frames: []engine.AnimFrame{
|
||||
{Frame: 3, Duration: 12},
|
||||
{Frame: 4, Duration: 12},
|
||||
{Frame: 5, Duration: 12},
|
||||
{Frame: 6, Duration: 12},
|
||||
}}
|
||||
greenTileAnim := &engine.Anim{Frames: []engine.AnimFrame{
|
||||
{Frame: 0, Duration: 16},
|
||||
{Frame: 1, Duration: 16},
|
||||
{Frame: 2, Duration: 16},
|
||||
}}
|
||||
denseTiles := [][]engine.Tile{
|
||||
{engine.StaticTile(9), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, engine.StaticTile(9)},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, engine.AnimatedTile{Anim: redTileAnim.Copy()}, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, engine.AnimatedTile{Anim: redTileAnim.Copy()}, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, &engine.AnimatedTile{AnimKey: "red_tile"}, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, &engine.AnimatedTile{AnimKey: "red_tile"}, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, engine.AnimatedTile{Anim: greenTileAnim.Copy()}, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, engine.AnimatedTile{Anim: redTileAnim.Copy()}, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, engine.AnimatedTile{Anim: greenTileAnim.Copy()}, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, engine.AnimatedTile{Anim: greenTileAnim.Copy()}, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, engine.AnimatedTile{Anim: greenTileAnim.Copy()}, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, engine.AnimatedTile{Anim: redTileAnim.Copy()}, nil, nil, nil, nil, nil, nil, engine.StaticTile(9), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, &engine.AnimatedTile{AnimKey: "green_tile"}, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, &engine.AnimatedTile{AnimKey: "red_tile"}, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, &engine.AnimatedTile{AnimKey: "green_tile"}, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, &engine.AnimatedTile{AnimKey: "green_tile"}, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, &engine.AnimatedTile{AnimKey: "green_tile"}, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, &engine.AnimatedTile{AnimKey: "red_tile"}, nil, nil, nil, nil, nil, nil, engine.StaticTile(9), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, engine.StaticTile(9), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, engine.StaticTile(9), nil, nil, nil},
|
||||
{nil, nil, nil, nil, engine.StaticTile(9), engine.StaticTile(9), engine.StaticTile(9), nil, nil, nil, engine.StaticTile(9), nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.AnimatedTile{Anim: redTileAnim.Copy()}, engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8)},
|
||||
{engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.AnimatedTile{Anim: redTileAnim.Copy()}, engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.AnimatedTile{Anim: greenTileAnim.Copy()}, engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7)},
|
||||
{engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), &engine.AnimatedTile{AnimKey: "red_tile"}, engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8), engine.StaticTile(8)},
|
||||
{engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), &engine.AnimatedTile{AnimKey: "red_tile"}, engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), &engine.AnimatedTile{AnimKey: "green_tile"}, engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7)},
|
||||
{engine.StaticTile(9), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(7), engine.StaticTile(9)},
|
||||
}
|
||||
tiles := make(map[image.Point]engine.Tile)
|
||||
|
@ -135,6 +124,22 @@ func writeLevel1() {
|
|||
ZOrder: 2,
|
||||
Map: tiles,
|
||||
Sheet: engine.Sheet{
|
||||
AnimDefs: map[string]*engine.AnimDef{
|
||||
"red_tile": {
|
||||
Steps: []engine.AnimStep{
|
||||
{Cell: 3, Duration: 12},
|
||||
{Cell: 4, Duration: 12},
|
||||
{Cell: 5, Duration: 12},
|
||||
{Cell: 6, Duration: 12},
|
||||
}},
|
||||
"green_tile": {
|
||||
Steps: []engine.AnimStep{
|
||||
{Cell: 0, Duration: 16},
|
||||
{Cell: 1, Duration: 16},
|
||||
{Cell: 2, Duration: 16},
|
||||
},
|
||||
},
|
||||
},
|
||||
CellSize: image.Pt(16, 16),
|
||||
Src: engine.ImageRef{Path: "assets/boxes.png"},
|
||||
},
|
||||
|
@ -160,12 +165,45 @@ func writeLevel1() {
|
|||
Pos: image.Pt(100, 100),
|
||||
Size: image.Pt(8, 16),
|
||||
},
|
||||
ZOrder: 3,
|
||||
FrameOffset: image.Pt(-1, 0),
|
||||
Sheet: engine.Sheet{
|
||||
AnimDefs: map[string]*engine.AnimDef{
|
||||
|
||||
"idle_left": {Steps: []engine.AnimStep{
|
||||
{Cell: 1, Duration: 60},
|
||||
}},
|
||||
"idle_right": {Steps: []engine.AnimStep{
|
||||
{Cell: 0, Duration: 60},
|
||||
}},
|
||||
"run_left": {Steps: []engine.AnimStep{
|
||||
{Cell: 14, Duration: 3},
|
||||
{Cell: 15, Duration: 5},
|
||||
{Cell: 16, Duration: 3},
|
||||
{Cell: 17, Duration: 3},
|
||||
}},
|
||||
"run_right": {Steps: []engine.AnimStep{
|
||||
{Cell: 10, Duration: 3},
|
||||
{Cell: 11, Duration: 5},
|
||||
{Cell: 12, Duration: 3},
|
||||
{Cell: 13, Duration: 3},
|
||||
}},
|
||||
"walk_left": {Steps: []engine.AnimStep{
|
||||
{Cell: 2, Duration: 6},
|
||||
{Cell: 3, Duration: 6},
|
||||
{Cell: 4, Duration: 6},
|
||||
{Cell: 5, Duration: 6},
|
||||
}},
|
||||
"walk_right": {Steps: []engine.AnimStep{
|
||||
{Cell: 6, Duration: 6},
|
||||
{Cell: 7, Duration: 6},
|
||||
{Cell: 8, Duration: 6},
|
||||
{Cell: 9, Duration: 6},
|
||||
}},
|
||||
},
|
||||
CellSize: image.Pt(10, 16),
|
||||
Src: engine.ImageRef{Path: "assets/aw.png"},
|
||||
},
|
||||
ZOrder: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue