Added particles on splash.
This commit is contained in:
parent
a4ab1a265e
commit
d8c0f489aa
@ -1,6 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"opslag.de/schobers/geom"
|
||||
@ -50,3 +52,77 @@ func (a *sinkAnimation) Animate(start, now time.Duration) bool {
|
||||
a.e.scr.z = progress * 80
|
||||
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_magma.png": "magma",
|
||||
|
||||
"ui.png": "ui",
|
||||
"particles.png": "particles",
|
||||
"ui.png": "ui",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@ -178,7 +179,7 @@ func (g *game) loadAssets() error {
|
||||
log.Printf("Loaded %d fonts.\n", g.ui.Fonts().Len())
|
||||
|
||||
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 {
|
||||
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})
|
||||
}
|
||||
|
||||
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) {
|
||||
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 {
|
||||
pos := geom.Pt(i%level.width, i/level.width)
|
||||
scr := entityLoc{pos.ToF32(), 0}
|
||||
@ -194,8 +207,11 @@ func (l *playLevel) Render(ctx *alui.Context, bounds geom.RectangleF32) {
|
||||
l.drawSprite("magma", "magma", scr)
|
||||
brick := l.state.FindSunkenBrick(pos)
|
||||
if brick != nil {
|
||||
behind, front := splitParticles(scr.pos.Y, l.state.Particles(pos))
|
||||
drawParticles(behind)
|
||||
l.drawSprite("brick", "brick", brick.scr)
|
||||
l.drawSprite("magma", "sunken_overlay", scr)
|
||||
drawParticles(front)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ type playLevelState struct {
|
||||
villain *entity
|
||||
bricks entityList
|
||||
sunken entityList
|
||||
splash map[geom.Point]*splashAnimation
|
||||
|
||||
steps int
|
||||
complete bool
|
||||
@ -33,6 +34,20 @@ func (s *playLevelState) Entities() entityList {
|
||||
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 {
|
||||
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.bricks = nil
|
||||
s.sunken = nil
|
||||
s.splash = map[geom.Point]*splashAnimation{}
|
||||
for i, e := range s.level.entities {
|
||||
switch e {
|
||||
case entityTypeBrick:
|
||||
@ -116,6 +132,12 @@ func (s *playLevelState) TryPlayerMove(dir geom.Point, key allg5.Key) {
|
||||
s.bricks = s.bricks.Remove(brickTo)
|
||||
s.sunken = s.sunken.Add(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