Added particles on splash.
This commit is contained in:
parent
a4ab1a265e
commit
d8c0f489aa
@ -1,6 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"opslag.de/schobers/geom"
|
"opslag.de/schobers/geom"
|
||||||
@ -50,3 +52,77 @@ func (a *sinkAnimation) Animate(start, now time.Duration) bool {
|
|||||||
a.e.scr.z = progress * 80
|
a.e.scr.z = progress * 80
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type splashAnimation struct {
|
||||||
|
particles []splashParticle
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSplashAnimation(pos geom.Point) *splashAnimation {
|
||||||
|
pos32 := pos.ToF32()
|
||||||
|
a := &splashAnimation{}
|
||||||
|
n := rand.Intn(20) + 4
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
angle := rand.Float32() * math.Pi * 2
|
||||||
|
a.particles = append(a.particles, splashParticle{
|
||||||
|
angle: angle,
|
||||||
|
origin: pos32.Add2D(.45*geom.Cos32(angle), .45*geom.Sin32(angle)), // [-0.45 .. 0.45]
|
||||||
|
speed: .5*math.Pi + 2*math.Pi*rand.Float32(), // [0.5*Pi .. 2.5*Pi)
|
||||||
|
height: .2 + .8*rand.Float32(), // [0.2 .. 1.0)
|
||||||
|
dist: .5 + .5*rand.Float32(), // [0.5 .. 1.0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *splashAnimation) Animate(start, now time.Duration) bool {
|
||||||
|
const duration = 1670 * time.Millisecond
|
||||||
|
|
||||||
|
progress := float32((now-start)*1000/duration) * .001
|
||||||
|
var opaq float32 = 1
|
||||||
|
if progress > .6 {
|
||||||
|
if progress > 1 {
|
||||||
|
opaq = 0
|
||||||
|
} else {
|
||||||
|
opaq = 2.5 - 2.5*progress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, p := range a.particles {
|
||||||
|
progress := geom.Min32(math.Pi, progress*p.speed) / math.Pi
|
||||||
|
a.particles[i].part = particle{
|
||||||
|
opaq: opaq,
|
||||||
|
pos: p.origin.Add2D(progress*p.dist*geom.Cos32(p.angle), progress*p.dist*geom.Sin32(p.angle)),
|
||||||
|
z: 20 + p.height*-100*geom.Sin32(progress*math.Pi),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if progress > 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
type particle struct {
|
||||||
|
pos geom.PointF32
|
||||||
|
z float32
|
||||||
|
opaq float32
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitParticles(y float32, particles []particle) (behind []particle, front []particle) {
|
||||||
|
for _, p := range particles {
|
||||||
|
if p.pos.Y > y {
|
||||||
|
front = append(front, p)
|
||||||
|
} else {
|
||||||
|
behind = append(behind, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type splashParticle struct {
|
||||||
|
origin geom.PointF32
|
||||||
|
angle float32
|
||||||
|
speed float32
|
||||||
|
height float32
|
||||||
|
dist float32
|
||||||
|
|
||||||
|
part particle
|
||||||
|
}
|
||||||
|
@ -156,7 +156,8 @@ func (g *game) loadAssets() error {
|
|||||||
"tile_lava_brick.png": "lava_brick",
|
"tile_lava_brick.png": "lava_brick",
|
||||||
"tile_magma.png": "magma",
|
"tile_magma.png": "magma",
|
||||||
|
|
||||||
"ui.png": "ui",
|
"particles.png": "particles",
|
||||||
|
"ui.png": "ui",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -178,7 +179,7 @@ func (g *game) loadAssets() error {
|
|||||||
log.Printf("Loaded %d fonts.\n", g.ui.Fonts().Len())
|
log.Printf("Loaded %d fonts.\n", g.ui.Fonts().Len())
|
||||||
|
|
||||||
log.Println("Loading sprites")
|
log.Println("Loading sprites")
|
||||||
err = g.loadSprites("brick", "dragon", "lava_brick", "magma", "ui", "villain")
|
err = g.loadSprites("brick", "dragon", "lava_brick", "magma", "particles", "ui", "villain")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -178,8 +178,21 @@ 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})
|
l.ctx.SpriteDrawer.Draw(name, partName, l.posToScreenF32(pos.pos, pos.z), DrawSpriteOptions{Scale: l.scale})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *playLevel) drawSpriteAlpha(name, partName string, pos entityLoc, alpha float32) {
|
||||||
|
a := byte(alpha * 255)
|
||||||
|
c := allg5.NewColorAlpha(a, a, a, a)
|
||||||
|
l.ctx.SpriteDrawer.Draw(name, partName, l.posToScreenF32(pos.pos, pos.z), DrawSpriteOptions{Scale: l.scale, Tint: &c})
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
drawParticles := func(particles []particle) {
|
||||||
|
for _, p := range particles {
|
||||||
|
l.drawSpriteAlpha("particles", "splash", entityLoc{p.pos, p.z}, p.opaq)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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}
|
scr := entityLoc{pos.ToF32(), 0}
|
||||||
@ -194,8 +207,11 @@ func (l *playLevel) Render(ctx *alui.Context, bounds geom.RectangleF32) {
|
|||||||
l.drawSprite("magma", "magma", scr)
|
l.drawSprite("magma", "magma", scr)
|
||||||
brick := l.state.FindSunkenBrick(pos)
|
brick := l.state.FindSunkenBrick(pos)
|
||||||
if brick != nil {
|
if brick != nil {
|
||||||
|
behind, front := splitParticles(scr.pos.Y, l.state.Particles(pos))
|
||||||
|
drawParticles(behind)
|
||||||
l.drawSprite("brick", "brick", brick.scr)
|
l.drawSprite("brick", "brick", brick.scr)
|
||||||
l.drawSprite("magma", "sunken_overlay", scr)
|
l.drawSprite("magma", "sunken_overlay", scr)
|
||||||
|
drawParticles(front)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ type playLevelState struct {
|
|||||||
villain *entity
|
villain *entity
|
||||||
bricks entityList
|
bricks entityList
|
||||||
sunken entityList
|
sunken entityList
|
||||||
|
splash map[geom.Point]*splashAnimation
|
||||||
|
|
||||||
steps int
|
steps int
|
||||||
complete bool
|
complete bool
|
||||||
@ -33,6 +34,20 @@ func (s *playLevelState) Entities() entityList {
|
|||||||
return entities.Add(s.player).Add(s.villain).AddList(s.bricks)
|
return entities.Add(s.player).Add(s.villain).AddList(s.bricks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *playLevelState) Particles(at geom.Point) []particle {
|
||||||
|
var particles []particle
|
||||||
|
for pos, ani := range s.splash {
|
||||||
|
if pos != at {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Println("Found particles at", at)
|
||||||
|
for _, p := range ani.particles {
|
||||||
|
particles = append(particles, p.part)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return particles
|
||||||
|
}
|
||||||
|
|
||||||
func (s *playLevelState) FindSunkenBrick(pos geom.Point) *entity {
|
func (s *playLevelState) FindSunkenBrick(pos geom.Point) *entity {
|
||||||
return s.sunken.FindEntity(pos)
|
return s.sunken.FindEntity(pos)
|
||||||
}
|
}
|
||||||
@ -50,6 +65,7 @@ func (s *playLevelState) Init(ctx *Context, pack, level string, onComplete func(
|
|||||||
s.level = s.pack.levels[level]
|
s.level = s.pack.levels[level]
|
||||||
s.bricks = nil
|
s.bricks = nil
|
||||||
s.sunken = nil
|
s.sunken = nil
|
||||||
|
s.splash = map[geom.Point]*splashAnimation{}
|
||||||
for i, e := range s.level.entities {
|
for i, e := range s.level.entities {
|
||||||
switch e {
|
switch e {
|
||||||
case entityTypeBrick:
|
case entityTypeBrick:
|
||||||
@ -116,6 +132,12 @@ func (s *playLevelState) TryPlayerMove(dir geom.Point, key allg5.Key) {
|
|||||||
s.bricks = s.bricks.Remove(brickTo)
|
s.bricks = s.bricks.Remove(brickTo)
|
||||||
s.sunken = s.sunken.Add(brick)
|
s.sunken = s.sunken.Add(brick)
|
||||||
s.ani.Start(s.ctx.Tick, newSinkAnimation(brick))
|
s.ani.Start(s.ctx.Tick, newSinkAnimation(brick))
|
||||||
|
|
||||||
|
splash := newSplashAnimation(brickTo)
|
||||||
|
s.splash[brickTo] = splash
|
||||||
|
s.ani.StartFn(s.ctx.Tick, splash, func() {
|
||||||
|
delete(s.splash, brickTo)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
BIN
cmd/krampus19/res/particles.png
Normal file
BIN
cmd/krampus19/res/particles.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
11
cmd/krampus19/res/sprites/particles.txt
Normal file
11
cmd/krampus19/res/sprites/particles.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
sprite:
|
||||||
|
texture: particles
|
||||||
|
|
||||||
|
part:
|
||||||
|
name: splash
|
||||||
|
sub_texture: 0,0,96,96
|
||||||
|
anchor: 48,48
|
||||||
|
scale: 6
|
||||||
|
:part
|
||||||
|
|
||||||
|
:sprite
|
Loading…
Reference in New Issue
Block a user