-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathdrawFrequons.go
108 lines (97 loc) · 3.32 KB
/
drawFrequons.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package main
import (
"github.com/ArchRobison/FrequonInvaders/fourier"
"github.com/ArchRobison/FrequonInvaders/sprite"
"github.com/ArchRobison/FrequonInvaders/universe"
"github.com/ArchRobison/Gophetica/math32"
"github.com/ArchRobison/Gophetica/nimble"
)
var critterSeq [universe.MaxCritter][]sprite.Sprite
func initCritterSprites(width, height int32) {
// The factor .75/64. should yield the same size as the original game
// for a 1920x1080 display
radius := int32(math32.Sqrt(float32(width*height)) * (.75 / 64.))
const frameCount = 60
for k := range critterSeq {
critterSeq[k] = sprite.MakeAnimation(int(radius), k == 0, frameCount)
}
}
var harmonicStorage [universe.MaxCritter]fourier.Harmonic
var phaseRoll float32
func updatePhaseRoll(dt float32) {
const rate = 2 * math32.Pi * (0.25) // rate in cycles per second
phaseRoll += rate * dt
for phaseRoll > math32.Pi {
phaseRoll -= 2 * math32.Pi
}
}
// drawFrequonsFourier draws the frequency-domain representation of Frequons.
func drawFrequonsFourier(pm nimble.PixMap) {
c := universe.Zoo
h := harmonicStorage[:len(c)]
var ampScale float32
if autoGain.Value {
// Compute L1 norm of amplitudes
norm := float32(0)
for i := range c {
norm += math32.Abs(c[i].Amplitude)
}
ampScale = 1 / norm
} else {
ampScale = 1 / float32(len(c))
}
fracX, fracY := universe.BoxFraction()
fracX *= zoomCompression
fracY *= zoomCompression
sizeX, sizeY := pm.Size()
// Set up harmonics
// (cx,cy) is center of fourier view
cx, cy := 0.5*float32(sizeX)*fracX, 0.5*float32(sizeY)*fracY
α, β := -0.5*cx, -0.5*cy
ωScale := 200. / float32(sizeX*sizeY)
for i := range h {
ωx := (c[i].Sx - cx) * ωScale
ωy := (c[i].Sy - cy) * ωScale
h[i].Ωx = ωx
h[i].Ωy = ωy
h[i].Phase = α*ωx + β*ωy + phaseRoll
// Scale amplitude so that DFT values fit within domain of color lookup table.
h[i].Amplitude = c[i].Amplitude * ampScale
}
marginX := int32(math32.Round(0.5 * float32(sizeX) * (1 - fracX)))
marginY := int32(math32.Round(0.5 * float32(sizeY) * (1 - fracY)))
fourier.Draw(pm.Intersect(nimble.Rect{
Left: marginX,
Right: sizeX - marginX,
Top: marginY,
Bottom: sizeY - marginY,
}), h, universe.Scheme())
if marginX != 0 || marginY != 0 {
pm.DrawRect(nimble.Rect{Left: 0, Right: sizeX, Top: 0, Bottom: marginY}, nimble.Black)
pm.DrawRect(nimble.Rect{Left: 0, Right: sizeX, Top: sizeY - marginY, Bottom: sizeY}, nimble.Black)
pm.DrawRect(nimble.Rect{Left: 0, Right: marginX, Top: marginY, Bottom: sizeY - marginY}, nimble.Black)
pm.DrawRect(nimble.Rect{Left: sizeX - marginX, Right: sizeX, Top: marginY, Bottom: sizeY - marginY}, nimble.Black)
}
}
// drawFrequonsSpatial draws the spatial-domain representation of Frequons.
// (xf,yf) is the location of the player.
func drawFrequonsSpatial(pm nimble.PixMap, xf, yf int32) {
nPastel := pastels.Width()
for k := 1; k < len(universe.Zoo); k++ {
c := &universe.Zoo[k]
d := int32(math32.Hypot(float32(xf)-c.Sx, float32(yf)-c.Sy))
if c.Show || d < nPastel {
i := c.ImageIndex()
if i < len(critterSeq[k]) {
j := int32(0)
if !c.Show {
j = d
}
sprite.Draw(pm, int32(math32.Round(c.Sx)), int32(math32.Round(c.Sy)), critterSeq[k][i], pastels.Pixel(j, int32(c.Id)))
}
}
}
if fourierPort.Contains(mouseX, mouseY) {
sprite.Draw(pm, xf, yf, critterSeq[0][0], nimble.White)
}
}