• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlange-42 / ark-pixel / 13728878286

07 Mar 2025 08:37PM CUT coverage: 89.367%. Remained the same
13728878286

push

github

web-flow
Remove monitors example (#10)

1454 of 1627 relevant lines covered (89.37%)

222401.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.79
/monitor/controls.go
1
package monitor
2

3
import (
4
        "fmt"
5
        "image/color"
6
        "math"
7

8
        px "github.com/gopxl/pixel/v2"
9
        "github.com/gopxl/pixel/v2/backends/opengl"
10
        "github.com/gopxl/pixel/v2/ext/imdraw"
11
        "github.com/gopxl/pixel/v2/ext/text"
12
        "github.com/mlange-42/ark-tools/app"
13
        "github.com/mlange-42/ark/ecs"
14
)
15

16
// Controls adds UI and keyboard input for controlling the simulation.
17
// UI controls are displayed in the bottom right corner of the window.
18
//
19
// Pause and resume the simulation via a button or by pressing SPACE.
20
// Manipulate simulation speed (TPS) using buttons or UP/DOWN keys.
21
//
22
// Expects a world resource of type Systems ([github.com/mlange-42/ark-tools/model.Systems]).
23
type Controls struct {
24
        Scale      float64 // Spatial scaling: cell size in screen pixels. Optional, default 1.
25
        drawer     imdraw.IMDraw
26
        systemsRes ecs.Resource[app.Systems]
27
        text       *text.Text
28
}
29

30
// Initialize the system
31
func (c *Controls) Initialize(w *ecs.World, win *opengl.Window) {
2✔
32
        c.systemsRes = ecs.NewResource[app.Systems](w)
2✔
33
        if !c.systemsRes.Has() {
2✔
34
                panic("resource of type Systems expected in Controls drawer")
×
35
        }
36

37
        if c.Scale <= 0 {
3✔
38
                c.Scale = 1
1✔
39
        }
1✔
40

41
        c.drawer = *imdraw.New(nil)
2✔
42
        c.text = text.New(px.V(0, 0), defaultFont)
2✔
43

44
}
45

46
// Update the drawer.
47
func (c *Controls) Update(w *ecs.World) {}
200✔
48

49
// UpdateInputs handles input events of the previous frame update.
50
func (c *Controls) UpdateInputs(w *ecs.World, win *opengl.Window) {
200✔
51
        sys := c.systemsRes.Get()
200✔
52
        if win.JustPressed(px.KeySpace) {
200✔
53
                sys.Paused = !sys.Paused
×
54
                return
×
55
        }
×
56
        if win.JustPressed(px.KeyUp) {
200✔
57
                sys.TPS = calcTps(sys.TPS, true)
×
58
                return
×
59
        }
×
60
        if win.JustPressed(px.KeyDown) {
200✔
61
                sys.TPS = calcTps(sys.TPS, false)
×
62
                return
×
63
        }
×
64

65
        if win.JustPressed(px.MouseButton1) {
200✔
66
                width := win.Canvas().Bounds().W()
×
67
                height := win.Canvas().Bounds().H()
×
68

×
69
                mouse := win.MousePosition()
×
70
                if c.pauseBounds(width, height).Contains(mouse.X, mouse.Y) {
×
71
                        sys.Paused = !sys.Paused
×
72
                } else if c.upButton(width, height).Contains(mouse.X, mouse.Y) {
×
73
                        sys.TPS = calcTps(sys.TPS, true)
×
74
                } else if c.downButton(width, height).Contains(mouse.X, mouse.Y) {
×
75
                        sys.TPS = calcTps(sys.TPS, false)
×
76
                }
×
77
        }
78
}
79

80
// Draw the system
81
func (c *Controls) Draw(w *ecs.World, win *opengl.Window) {
200✔
82
        width := win.Canvas().Bounds().W()
200✔
83
        height := win.Canvas().Bounds().H()
200✔
84

200✔
85
        sys := c.systemsRes.Get()
200✔
86
        text := "Pause"
200✔
87
        if sys.Paused {
200✔
88
                text = "Resume"
×
89
        }
×
90
        c.drawButton(c.pauseBounds(width, height), text, win)
200✔
91

200✔
92
        c.drawButton(c.upButton(width, height), "+", win)
200✔
93
        c.drawButton(c.downButton(width, height), "-", win)
200✔
94
        c.drawButton(c.tpsButton(width, height), fmt.Sprintf("%.0f TPS", sys.TPS), win)
200✔
95
}
96

97
func (c *Controls) drawButton(b *button, text string, win *opengl.Window) {
800✔
98
        dr := &c.drawer
800✔
99

800✔
100
        dr.Color = color.Black
800✔
101
        dr.Push(px.V(b.X, b.Y), px.V(b.X+b.W, b.Y+b.H))
800✔
102
        dr.Rectangle(0)
800✔
103
        dr.Reset()
800✔
104

800✔
105
        dr.Color = color.White
800✔
106
        dr.Push(px.V(b.X, b.Y), px.V(b.X+b.W, b.Y+b.H))
800✔
107
        dr.Rectangle(1)
800✔
108
        dr.Reset()
800✔
109

800✔
110
        dr.Draw(win)
800✔
111
        dr.Clear()
800✔
112

800✔
113
        c.text.Clear()
800✔
114
        fmt.Fprint(c.text, text)
800✔
115

800✔
116
        wTxt := c.text.Bounds().W()
800✔
117
        hTxt := c.text.Bounds().H()
800✔
118
        cx, cy := b.Center()
800✔
119
        c.text.Draw(win, px.IM.Scaled(px.V(wTxt/2, hTxt/2), c.Scale).Moved(px.V(math.Floor(cx-wTxt/2), math.Floor(cy-hTxt/2))))
800✔
120
}
800✔
121

122
func (c *Controls) pauseBounds(w, h float64) *button {
200✔
123
        return &button{
200✔
124
                w - 85*c.Scale,
200✔
125
                5 + 15*c.Scale,
200✔
126
                60 * c.Scale,
200✔
127
                30 * c.Scale,
200✔
128
        }
200✔
129
}
200✔
130

131
func (c *Controls) upButton(w, h float64) *button {
200✔
132
        return &button{
200✔
133
                w - 25*c.Scale,
200✔
134
                5 + 30*c.Scale,
200✔
135
                20 * c.Scale,
200✔
136
                15 * c.Scale,
200✔
137
        }
200✔
138
}
200✔
139

140
func (c *Controls) downButton(w, h float64) *button {
200✔
141
        return &button{
200✔
142
                w - 25*c.Scale,
200✔
143
                5 + 15*c.Scale,
200✔
144
                20 * c.Scale,
200✔
145
                15 * c.Scale,
200✔
146
        }
200✔
147
}
200✔
148

149
func (c *Controls) tpsButton(w, h float64) *button {
200✔
150
        return &button{
200✔
151
                w - 85*c.Scale,
200✔
152
                5,
200✔
153
                80 * c.Scale,
200✔
154
                15 * c.Scale,
200✔
155
        }
200✔
156
}
200✔
157

158
type button struct {
159
        X float64
160
        Y float64
161
        W float64
162
        H float64
163
}
164

165
func (b *button) Center() (float64, float64) {
800✔
166
        return b.X + b.W/2, b.Y + b.H/2
800✔
167
}
800✔
168

169
func (b *button) Contains(x, y float64) bool {
×
170
        return x >= b.X && y >= b.Y && x <= b.X+b.W && y <= b.Y+b.H
×
171
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc