Add sinking animation for brick.

This commit is contained in:
Sander Schobers 2019-12-29 14:49:54 +01:00
parent 95bc1367c7
commit 214d08f2b3
3 changed files with 51 additions and 27 deletions

View File

@ -9,34 +9,59 @@ import (
type entity struct { type entity struct {
typ entityType typ entityType
pos geom.Point pos geom.Point
scr geom.PointF32 scr entityLoc
}
type entityLoc struct {
pos geom.PointF32
z float32
} }
func newEntity(typ entityType, pos geom.Point) *entity { func newEntity(typ entityType, pos geom.Point) *entity {
return &entity{typ, pos, pos.ToF32()} return &entity{typ, pos, entityLoc{pos.ToF32(), 0}}
} }
type entityMoveAnimation struct { type moveAnimation struct {
e *entity e *entity
from, to geom.Point from, to geom.Point
pos geom.PointF32 pos geom.PointF32
} }
func newEntityMoveAnimation(e *entity, to geom.Point) *entityMoveAnimation { func newMoveAnimation(e *entity, to geom.Point) *moveAnimation {
ani := &entityMoveAnimation{e: e, from: e.pos, to: to, pos: e.pos.ToF32()} ani := &moveAnimation{e: e, from: e.pos, to: to, pos: e.pos.ToF32()}
ani.e.pos = to ani.e.pos = to
return ani return ani
} }
func (a *entityMoveAnimation) Animate(start, now time.Duration) bool { func (a *moveAnimation) Animate(start, now time.Duration) bool {
const duration = 210 * time.Millisecond const duration = 210 * time.Millisecond
progress := float32((now-start)*1000/duration) * .001 progress := float32((now-start)*1000/duration) * .001
from, to := a.from.ToF32(), a.to.ToF32() from, to := a.from.ToF32(), a.to.ToF32()
if progress >= 1 { if progress >= 1 {
a.e.scr = to a.e.scr.pos = to
return false return false
} }
a.e.scr = to.Sub(from).Mul(progress).Add(from) a.e.scr.pos = to.Sub(from).Mul(progress).Add(from)
return true
}
type sinkAnimation struct {
e *entity
}
func newSinkAnimation(e *entity) *sinkAnimation {
return &sinkAnimation{e: e}
}
func (a *sinkAnimation) Animate(start, now time.Duration) bool {
const duration = 70 * time.Millisecond
progress := float32((now-start)*1000/duration) * .001
if progress >= 1 {
a.e.scr.z = 80
return false
}
a.e.scr.z = progress * 80
return true return true
} }

View File

@ -174,40 +174,38 @@ func (l *playLevel) Handle(e allg5.Event) {
} }
} }
func (l *playLevel) drawSprite(name, partName string, pos geom.PointF32) { func (l *playLevel) drawSprite(name, partName string, pos entityLoc) {
l.drawSpritePart(name, partName, pos, 0) l.ctx.SpriteDrawer.Draw(name, partName, l.posToScreenF32(pos.pos, pos.z), DrawSpriteOptions{Scale: l.scale})
}
func (l *playLevel) drawSpritePart(name, partName string, pos geom.PointF32, z float32) {
l.ctx.SpriteDrawer.Draw(name, partName, l.posToScreenF32(pos, z), DrawSpriteOptions{Scale: l.scale})
} }
func (l *playLevel) Render(ctx *alui.Context, bounds geom.RectangleF32) { func (l *playLevel) Render(ctx *alui.Context, bounds geom.RectangleF32) {
level := l.state.level level := l.state.level
for i, t := range level.tiles { for i, t := range level.tiles {
pos := geom.Pt(i%level.width, i/level.width) pos := geom.Pt(i%level.width, i/level.width)
scr := entityLoc{pos.ToF32(), 0}
switch t { switch t {
case tileBasic: case tileBasic:
if l.state.IsNextToMagma(pos) { if l.state.IsNextToMagma(pos) {
l.drawSprite("lava_brick", "magma", pos.ToF32()) l.drawSprite("lava_brick", "magma", scr)
} else { } else {
l.drawSprite("lava_brick", "lava_brick", pos.ToF32()) l.drawSprite("lava_brick", "lava_brick", scr)
} }
case tileMagma: case tileMagma:
l.drawSprite("magma", "magma", pos.ToF32()) l.drawSprite("magma", "magma", scr)
if l.state.IsFilledUp(pos) { brick := l.state.FindSunkenBrick(pos)
l.drawSpritePart("brick", "brick", pos.ToF32(), 80) if brick != nil {
l.drawSprite("magma", "sunken_overlay", pos.ToF32()) l.drawSprite("brick", "brick", brick.scr)
l.drawSprite("magma", "sunken_overlay", scr)
} }
} }
} }
entities := l.state.Entities() entities := l.state.Entities()
sort.Slice(entities, func(i, j int) bool { sort.Slice(entities, func(i, j int) bool {
if entities[i].scr.Y == entities[j].scr.Y { if entities[i].scr.pos.Y == entities[j].scr.pos.Y {
return entities[i].scr.X < entities[j].scr.X return entities[i].scr.pos.X < entities[j].scr.pos.X
} }
return entities[i].scr.Y < entities[j].scr.Y return entities[i].scr.pos.Y < entities[j].scr.pos.Y
}) })
for _, e := range entities { for _, e := range entities {

View File

@ -53,8 +53,8 @@ func (s *playLevelState) Entities() []*entity {
return entities return entities
} }
func (s *playLevelState) IsFilledUp(pos geom.Point) bool { func (s *playLevelState) FindSunkenBrick(pos geom.Point) *entity {
return findEntityAt(s.sunken, pos) != nil return findEntityAt(s.sunken, pos)
} }
func (s *playLevelState) IsNextToMagma(pos geom.Point) bool { func (s *playLevelState) IsNextToMagma(pos geom.Point) bool {
@ -113,7 +113,7 @@ func (s *playLevelState) TryPlayerMove(dir geom.Point, key allg5.Key) {
s.steps++ s.steps++
log.Printf("Moving player to %s", to) log.Printf("Moving player to %s", to)
s.ani.StartFn(s.ctx.Tick, newEntityMoveAnimation(s.player, to), func() { s.ani.StartFn(s.ctx.Tick, newMoveAnimation(s.player, to), func() {
log.Printf("Player movement finished") log.Printf("Player movement finished")
if s.player.pos == s.villain.pos { if s.player.pos == s.villain.pos {
s.complete = true s.complete = true
@ -129,13 +129,14 @@ func (s *playLevelState) TryPlayerMove(dir geom.Point, key allg5.Key) {
if brick := findEntityAt(s.bricks, to); brick != nil { if brick := findEntityAt(s.bricks, to); brick != nil {
log.Printf("Pushing brick at %s", to) log.Printf("Pushing brick at %s", to)
brickTo := to.Add(dir) brickTo := to.Add(dir)
s.ani.StartFn(s.ctx.Tick, newEntityMoveAnimation(brick, brickTo), func() { s.ani.StartFn(s.ctx.Tick, newMoveAnimation(brick, brickTo), func() {
log.Printf("Brick movement finished") log.Printf("Brick movement finished")
if s.checkTile(brickTo, s.wouldBrickSink) { if s.checkTile(brickTo, s.wouldBrickSink) {
log.Printf("Sinking brick at %s", brickTo) log.Printf("Sinking brick at %s", brickTo)
idx := findEntityIdx(s.bricks, brickTo) idx := findEntityIdx(s.bricks, brickTo)
s.bricks = append(s.bricks[:idx], s.bricks[idx+1:]...) s.bricks = append(s.bricks[:idx], s.bricks[idx+1:]...)
s.sunken = append(s.sunken, brick) s.sunken = append(s.sunken, brick)
s.ani.Start(s.ctx.Tick, newSinkAnimation(brick))
} }
}) })
} }