Add sinking animation for brick.
This commit is contained in:
parent
95bc1367c7
commit
214d08f2b3
@ -9,34 +9,59 @@ import (
|
||||
type entity struct {
|
||||
typ entityType
|
||||
pos geom.Point
|
||||
scr geom.PointF32
|
||||
scr entityLoc
|
||||
}
|
||||
|
||||
type entityLoc struct {
|
||||
pos geom.PointF32
|
||||
z float32
|
||||
}
|
||||
|
||||
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
|
||||
from, to geom.Point
|
||||
pos geom.PointF32
|
||||
}
|
||||
|
||||
func newEntityMoveAnimation(e *entity, to geom.Point) *entityMoveAnimation {
|
||||
ani := &entityMoveAnimation{e: e, from: e.pos, to: to, pos: e.pos.ToF32()}
|
||||
func newMoveAnimation(e *entity, to geom.Point) *moveAnimation {
|
||||
ani := &moveAnimation{e: e, from: e.pos, to: to, pos: e.pos.ToF32()}
|
||||
ani.e.pos = to
|
||||
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
|
||||
|
||||
progress := float32((now-start)*1000/duration) * .001
|
||||
from, to := a.from.ToF32(), a.to.ToF32()
|
||||
if progress >= 1 {
|
||||
a.e.scr = to
|
||||
a.e.scr.pos = to
|
||||
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
|
||||
}
|
||||
|
@ -174,40 +174,38 @@ func (l *playLevel) Handle(e allg5.Event) {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *playLevel) drawSprite(name, partName string, pos geom.PointF32) {
|
||||
l.drawSpritePart(name, partName, pos, 0)
|
||||
}
|
||||
|
||||
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) drawSprite(name, partName string, pos entityLoc) {
|
||||
l.ctx.SpriteDrawer.Draw(name, partName, l.posToScreenF32(pos.pos, pos.z), DrawSpriteOptions{Scale: l.scale})
|
||||
}
|
||||
|
||||
func (l *playLevel) Render(ctx *alui.Context, bounds geom.RectangleF32) {
|
||||
level := l.state.level
|
||||
for i, t := range level.tiles {
|
||||
pos := geom.Pt(i%level.width, i/level.width)
|
||||
scr := entityLoc{pos.ToF32(), 0}
|
||||
switch t {
|
||||
case tileBasic:
|
||||
if l.state.IsNextToMagma(pos) {
|
||||
l.drawSprite("lava_brick", "magma", pos.ToF32())
|
||||
l.drawSprite("lava_brick", "magma", scr)
|
||||
} else {
|
||||
l.drawSprite("lava_brick", "lava_brick", pos.ToF32())
|
||||
l.drawSprite("lava_brick", "lava_brick", scr)
|
||||
}
|
||||
case tileMagma:
|
||||
l.drawSprite("magma", "magma", pos.ToF32())
|
||||
if l.state.IsFilledUp(pos) {
|
||||
l.drawSpritePart("brick", "brick", pos.ToF32(), 80)
|
||||
l.drawSprite("magma", "sunken_overlay", pos.ToF32())
|
||||
l.drawSprite("magma", "magma", scr)
|
||||
brick := l.state.FindSunkenBrick(pos)
|
||||
if brick != nil {
|
||||
l.drawSprite("brick", "brick", brick.scr)
|
||||
l.drawSprite("magma", "sunken_overlay", scr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entities := l.state.Entities()
|
||||
sort.Slice(entities, func(i, j int) bool {
|
||||
if entities[i].scr.Y == entities[j].scr.Y {
|
||||
return entities[i].scr.X < entities[j].scr.X
|
||||
if entities[i].scr.pos.Y == entities[j].scr.pos.Y {
|
||||
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 {
|
||||
|
@ -53,8 +53,8 @@ func (s *playLevelState) Entities() []*entity {
|
||||
return entities
|
||||
}
|
||||
|
||||
func (s *playLevelState) IsFilledUp(pos geom.Point) bool {
|
||||
return findEntityAt(s.sunken, pos) != nil
|
||||
func (s *playLevelState) FindSunkenBrick(pos geom.Point) *entity {
|
||||
return findEntityAt(s.sunken, pos)
|
||||
}
|
||||
|
||||
func (s *playLevelState) IsNextToMagma(pos geom.Point) bool {
|
||||
@ -113,7 +113,7 @@ func (s *playLevelState) TryPlayerMove(dir geom.Point, key allg5.Key) {
|
||||
|
||||
s.steps++
|
||||
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")
|
||||
if s.player.pos == s.villain.pos {
|
||||
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 {
|
||||
log.Printf("Pushing brick at %s", to)
|
||||
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")
|
||||
if s.checkTile(brickTo, s.wouldBrickSink) {
|
||||
log.Printf("Sinking brick at %s", brickTo)
|
||||
idx := findEntityIdx(s.bricks, brickTo)
|
||||
s.bricks = append(s.bricks[:idx], s.bricks[idx+1:]...)
|
||||
s.sunken = append(s.sunken, brick)
|
||||
s.ani.Start(s.ctx.Tick, newSinkAnimation(brick))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user