/
explosion.go
92 lines (84 loc) · 2.02 KB
/
explosion.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package cgame
import (
"time"
"github.com/jf-tech/console/cutil"
)
type ExplosionCfg struct {
// required
MaxDuration time.Duration
// optional
AfterFinish func()
SpriteName string
}
func CreateExplosion(s Sprite, c ExplosionCfg) {
r := s.Rect()
name := s.Name() + "_explosion"
if len(c.SpriteName) > 0 {
name = c.SpriteName
}
newS := NewSpriteBase(s.Mgr().g, s.Base().win.Parent(), name, CopyFrame(s.Frame()), r.X, r.Y)
newS.AddAnimator(NewAnimatorFrame(newS, AnimatorFrameCfg{
Frames: &explosionFrameProvider{
s: newS,
frameCount: int((c.MaxDuration / time.Second) * time.Duration(explosionFPS)),
},
AnimatorCfgCommon: AnimatorCfgCommon{
AfterFinish: c.AfterFinish,
},
}))
newS.Mgr().AddSprite(newS)
s.Mgr().DeleteSprite(s)
}
var (
explosionRunes = []rune("\"~'`.")
fire = '🔥'
fireProb = "50%"
explosionFPS = 8
changeIntoExplosionRunesProb = "50%"
explosionRuneFwdProb = "80%"
)
type explosionFrameProvider struct {
s Sprite
frameCount int
}
func (e *explosionFrameProvider) Next() (Frame, time.Duration, bool) {
if e.frameCount <= 0 {
return nil, -1, false
}
f := FrameFromWin(e.s.Base().win)
if len(f) <= 0 {
return nil, -1, false
}
indexRune := func(rs []rune, r rune) int {
for i := 0; i < len(rs); i++ {
if rs[i] == r {
return i
}
}
return -1
}
for i := 0; i < len(f); i++ {
cellRemoval := false
if idx := indexRune(explosionRunes, f[i].Chx.Ch); idx >= 0 {
if cutil.CheckProbability(explosionRuneFwdProb) {
if idx >= len(explosionRunes)-1 {
cellRemoval = true
} else {
f[i].Chx.Ch = explosionRunes[idx+1]
}
}
} else if cutil.CheckProbability(changeIntoExplosionRunesProb) {
f[i].Chx.Ch = explosionRunes[0]
} else if cutil.CheckProbability(fireProb) {
f[i].Chx.Ch = fire
}
if cellRemoval {
copy(f[i:], f[i+1:])
f = f[:len(f)-1]
i--
continue
}
}
e.frameCount--
return f, time.Second / time.Duration(explosionFPS), true
}