-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrender.go
More file actions
120 lines (111 loc) · 2.87 KB
/
render.go
File metadata and controls
120 lines (111 loc) · 2.87 KB
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
109
110
111
112
113
114
115
116
117
118
119
120
package main
import (
"fmt"
"image/color"
"math"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
)
// Draw renders the current wave field, ear indicators, and optional overlays.
func (g *Game) Draw(screen *ebiten.Image) {
if g.gpuSolver != nil {
pixels := g.gpuSolver.PixelBytes()
if len(pixels) == w*h*4 {
screen.WritePixels(pixels)
}
}
baseX := int(g.ex)
baseY := int(g.ey)
for _, offset := range emitterFootprint {
cx := baseX + offset.dx
cy := baseY + offset.dy
if cx >= 0 && cx < w && cy >= 0 && cy < h {
screen.Set(cx, cy, color.RGBA{255, 0, 0, 255})
}
}
g.drawEarIndicators(screen, int(g.ex), int(g.ey))
g.drawAudioSampleMarker(screen)
if *debugFlag {
fps := ebiten.ActualFPS()
tps := ebiten.ActualTPS()
if tps < 0 {
tps = 0
}
simMultiplier := 0.0
if defaultTPS > 0 {
simMultiplier = tps / defaultTPS
}
simMS := g.lastSimDuration.Seconds() * 1000
simSteps := g.simStepsPerSecond()
debugMsg := fmt.Sprintf("FPS: %.1f\nSim speed: %.2fx (%.1f TPS)\nSim steps: %.1f/s (mult %dx, +/-)\nSim: %.2f ms",
fps, simMultiplier, tps, simSteps, g.simStepMultiplier, simMS)
ebitenutil.DebugPrint(screen, debugMsg)
}
}
// Layout reports the logical screen size used by Ebiten.
func (g *Game) Layout(_, _ int) (int, int) { return w, h }
// drawEarIndicators renders the listener's ear offset visualization.
func (g *Game) drawEarIndicators(screen *ebiten.Image, cx, cy int) {
ox, oy := g.earOffsets()
leftX := clampCoord(cx-ox, 0, w-1)
leftY := clampCoord(cy-oy, 0, h-1)
rightX := clampCoord(cx+ox, 0, w-1)
rightY := clampCoord(cy+oy, 0, h-1)
drawLine(screen, cx, cy, leftX, leftY, color.RGBA{0, 255, 200, 200})
drawLine(screen, cx, cy, rightX, rightY, color.RGBA{0, 200, 255, 200})
if leftX >= 0 && leftX < w && leftY >= 0 && leftY < h {
screen.Set(leftX, leftY, color.RGBA{0, 255, 200, 255})
}
if rightX >= 0 && rightX < w && rightY >= 0 && rightY < h {
screen.Set(rightX, rightY, color.RGBA{0, 200, 255, 255})
}
}
func (g *Game) drawAudioSampleMarker(screen *ebiten.Image) {
centerX := w / 2
centerY := h / 2
dotColor := color.RGBA{255, 40, 40, 255}
for dy := -1; dy <= 1; dy++ {
y := centerY + dy
if y < 0 || y >= h {
continue
}
for dx := -1; dx <= 1; dx++ {
x := centerX + dx
if x < 0 || x >= w {
continue
}
screen.Set(x, y, dotColor)
}
}
}
// drawLine plots a line segment using Bresenham's integer algorithm.
func drawLine(screen *ebiten.Image, x0, y0, x1, y1 int, clr color.Color) {
dx := int(math.Abs(float64(x1 - x0)))
sx := -1
if x0 < x1 {
sx = 1
}
dy := -int(math.Abs(float64(y1 - y0)))
sy := -1
if y0 < y1 {
sy = 1
}
err := dx + dy
for {
if x0 >= 0 && x0 < w && y0 >= 0 && y0 < h {
screen.Set(x0, y0, clr)
}
if x0 == x1 && y0 == y1 {
break
}
e2 := 2 * err
if e2 >= dy {
err += dy
x0 += sx
}
if e2 <= dx {
err += dx
y0 += sy
}
}
}