termfront 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/lib/termfront/adaptive_render_rate.rb +42 -0
- data/lib/termfront/audio_manager.rb +8 -0
- data/lib/termfront/config.rb +1 -0
- data/lib/termfront/game.rb +8 -5
- data/lib/termfront/network/client.rb +1 -0
- data/lib/termfront/network/wavesfight_client.rb +1 -0
- data/lib/termfront/version.rb +1 -1
- data/lib/termfront.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7e7d185736b70057b93c85c4196ddc96b63693b3f31fd58f9cf9e83cb96e10fa
|
|
4
|
+
data.tar.gz: 4583088200b878c1d0b51ef44123b6bf49891501c67aecadb1c8af93fbd4b64e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 49eb38ea263659290eb41fe10b6719fd4d9201528ee583badc1d511239b7abd364b60109c849fad983d15636bfa8f9ae64152308a700d45587556dfaee5da3a6
|
|
7
|
+
data.tar.gz: 955636242f49453baf156dc44caf6c9815f836fcbab68d0825471dae0d7e86c9832b858c0a9e45920e07fca9d77e07293f8fd1c8ba96019e7900fa073c80593c
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,16 @@ The format is based on Keep a Changelog, and this project follows Semantic Versi
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.1.8] - 2026-05-26
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Stop the `AudioManager` BGM and looping-SE threads from spinning at 100 % CPU when the audio player spawns but exits immediately (e.g. no usable audio device, codec missing, or backend not running). The non-looping playback loops now bail out if `spawn_player` returns `nil` or if the previous playback finished in under 500 ms, instead of relentlessly respawning a process that never plays anything. On a tester's CPU-bound host this was over 95 % of the process's CPU budget, making the renderer look heavy when the real culprit was the audio thread
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Adapt the in-game render rate to the host's headroom: an `AdaptiveRenderRate` module tracks how often a frame exceeds 85 % of the 60 Hz budget and, after 30 consecutive over-budget frames, downshifts the singleplayer / Wavesfight render rate to 30 Hz; if the host catches back up for 60 consecutive frames it upshifts back to 60 Hz. Capable machines keep running at 60 Hz, while testers on lower-spec CPUs / TDP-throttled laptops fall back to a steady 30 Hz instead of a stuttering 60 Hz, and the rate resets on every new game loop entry so a freshly launched match starts at 60 Hz
|
|
18
|
+
|
|
9
19
|
## [0.1.7] - 2026-05-26
|
|
10
20
|
|
|
11
21
|
### Changed
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Termfront
|
|
4
|
+
module AdaptiveRenderRate
|
|
5
|
+
OVER_BUDGET_RATIO = 0.85
|
|
6
|
+
UNDER_BUDGET_RATIO = 0.5
|
|
7
|
+
DOWNSHIFT_FRAMES = 30
|
|
8
|
+
UPSHIFT_FRAMES = 60
|
|
9
|
+
|
|
10
|
+
@current_dt = Config::RENDER_DT
|
|
11
|
+
@over_budget_count = 0
|
|
12
|
+
@under_budget_count = 0
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def current_dt
|
|
16
|
+
@current_dt
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def observe(spent)
|
|
20
|
+
if spent > Config::FRAME_DT * OVER_BUDGET_RATIO
|
|
21
|
+
@over_budget_count += 1
|
|
22
|
+
@under_budget_count = 0
|
|
23
|
+
if @over_budget_count >= DOWNSHIFT_FRAMES && @current_dt < Config::RENDER_DT_LOW
|
|
24
|
+
@current_dt = Config::RENDER_DT_LOW
|
|
25
|
+
end
|
|
26
|
+
elsif spent < Config::FRAME_DT * UNDER_BUDGET_RATIO
|
|
27
|
+
@under_budget_count += 1
|
|
28
|
+
@over_budget_count = 0
|
|
29
|
+
if @under_budget_count >= UPSHIFT_FRAMES && @current_dt > Config::RENDER_DT
|
|
30
|
+
@current_dt = Config::RENDER_DT
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def reset!
|
|
36
|
+
@current_dt = Config::RENDER_DT
|
|
37
|
+
@over_budget_count = 0
|
|
38
|
+
@under_budget_count = 0
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -41,9 +41,13 @@ module Termfront
|
|
|
41
41
|
loop do
|
|
42
42
|
break if channel_stopped?(:bgm)
|
|
43
43
|
|
|
44
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
44
45
|
@bgm_pid = spawn_player(@bgm_player, path, loop_playback: false)
|
|
46
|
+
break unless @bgm_pid
|
|
47
|
+
|
|
45
48
|
wait_for_channel(:bgm)
|
|
46
49
|
break if channel_stopped?(:bgm)
|
|
50
|
+
break if Process.clock_gettime(Process::CLOCK_MONOTONIC) - start < 0.5
|
|
47
51
|
end
|
|
48
52
|
end
|
|
49
53
|
rescue StandardError
|
|
@@ -101,9 +105,13 @@ module Termfront
|
|
|
101
105
|
loop do
|
|
102
106
|
break if channel_stopped?(:loop_se)
|
|
103
107
|
|
|
108
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
104
109
|
@loop_se_pid = spawn_player(@loop_se_player, path, loop_playback: false)
|
|
110
|
+
break unless @loop_se_pid
|
|
111
|
+
|
|
105
112
|
wait_for_channel(:loop_se)
|
|
106
113
|
break if channel_stopped?(:loop_se)
|
|
114
|
+
break if Process.clock_gettime(Process::CLOCK_MONOTONIC) - start < 0.5
|
|
107
115
|
end
|
|
108
116
|
end
|
|
109
117
|
rescue StandardError
|
data/lib/termfront/config.rb
CHANGED
data/lib/termfront/game.rb
CHANGED
|
@@ -130,9 +130,10 @@ module Termfront
|
|
|
130
130
|
end
|
|
131
131
|
|
|
132
132
|
def run_game_loop(show_complete_banner: true)
|
|
133
|
+
AdaptiveRenderRate.reset!
|
|
133
134
|
STDIN.raw do |stdin|
|
|
134
135
|
last_time = clock
|
|
135
|
-
last_render = last_time -
|
|
136
|
+
last_render = last_time - AdaptiveRenderRate.current_dt
|
|
136
137
|
|
|
137
138
|
loop do
|
|
138
139
|
now = clock
|
|
@@ -149,7 +150,7 @@ module Termfront
|
|
|
149
150
|
end
|
|
150
151
|
|
|
151
152
|
update(dt)
|
|
152
|
-
if now - last_render >=
|
|
153
|
+
if now - last_render >= AdaptiveRenderRate.current_dt
|
|
153
154
|
@renderer.render(
|
|
154
155
|
player: @player, map: @map,
|
|
155
156
|
enemies: @enemies, projectiles: @projectiles,
|
|
@@ -180,9 +181,10 @@ module Termfront
|
|
|
180
181
|
end
|
|
181
182
|
|
|
182
183
|
def run_wavesfight_loop
|
|
184
|
+
AdaptiveRenderRate.reset!
|
|
183
185
|
STDIN.raw do |stdin|
|
|
184
186
|
last_time = clock
|
|
185
|
-
last_render = last_time -
|
|
187
|
+
last_render = last_time - AdaptiveRenderRate.current_dt
|
|
186
188
|
|
|
187
189
|
loop do
|
|
188
190
|
now = clock
|
|
@@ -199,7 +201,7 @@ module Termfront
|
|
|
199
201
|
end
|
|
200
202
|
|
|
201
203
|
update(dt)
|
|
202
|
-
if now - last_render >=
|
|
204
|
+
if now - last_render >= AdaptiveRenderRate.current_dt
|
|
203
205
|
@renderer.render(
|
|
204
206
|
player: @player, map: @map,
|
|
205
207
|
enemies: @enemies, projectiles: @projectiles,
|
|
@@ -220,7 +222,7 @@ module Termfront
|
|
|
220
222
|
show_wave_clear
|
|
221
223
|
start_wavesfight_wave
|
|
222
224
|
last_time = clock
|
|
223
|
-
last_render = clock -
|
|
225
|
+
last_render = clock - AdaptiveRenderRate.current_dt
|
|
224
226
|
end
|
|
225
227
|
|
|
226
228
|
cap_frame(now)
|
|
@@ -659,6 +661,7 @@ module Termfront
|
|
|
659
661
|
|
|
660
662
|
def cap_frame(frame_start)
|
|
661
663
|
spent = clock - frame_start
|
|
664
|
+
AdaptiveRenderRate.observe(spent)
|
|
662
665
|
remain = Config::FRAME_DT - spent
|
|
663
666
|
sleep(remain) if remain > 0
|
|
664
667
|
end
|
data/lib/termfront/version.rb
CHANGED
data/lib/termfront.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: termfront
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- S-H-GAMELINKS
|
|
@@ -51,6 +51,7 @@ files:
|
|
|
51
51
|
- exe/termfront
|
|
52
52
|
- exe/termfront-server
|
|
53
53
|
- lib/termfront.rb
|
|
54
|
+
- lib/termfront/adaptive_render_rate.rb
|
|
54
55
|
- lib/termfront/async_writer.rb
|
|
55
56
|
- lib/termfront/audio_manager.rb
|
|
56
57
|
- lib/termfront/color.rb
|