Skip to content

Commit d9b5a1d

Browse files
committed
Simplify: review cleanup from code review agents
- Remove _prewarm_shapes() — results were discarded (flat cache, not keyed) - Make particle arrays private (_p_x, _p_y, etc.) - _exclusion_zones → local variable in render() (rebuilt every frame anyway) - BarSprite: avoid double-write of colors array in cached render path - Remove unused BoundingBox import
1 parent 405cfee commit d9b5a1d

File tree

1 file changed

+43
-66
lines changed

1 file changed

+43
-66
lines changed

clarvis/display/sprites/system.py

Lines changed: 43 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from .reel import Reel, ReelMode
1818
from .scenes import SceneManager
1919
from .weather_physics import (
20-
BoundingBox,
2120
Particle,
2221
Shape,
2322
compute_render_cells,
@@ -212,18 +211,17 @@ def __init__(
212211
self._weather_type: str | None = None
213212
self._intensity = 0.0
214213
self._wind_speed = 0.0
215-
self._exclusion_zones: list[BoundingBox] = []
216214

217215
# Particle SoA arrays
218216
n = self._batch_size
219-
self.p_x = np.zeros(n, dtype=np.float64)
220-
self.p_y = np.zeros(n, dtype=np.float64)
221-
self.p_vx = np.zeros(n, dtype=np.float64)
222-
self.p_vy = np.zeros(n, dtype=np.float64)
223-
self.p_age = np.zeros(n, dtype=np.int64)
224-
self.p_lifetime = np.zeros(n, dtype=np.int64)
225-
self.p_shape_idx = np.zeros(n, dtype=np.int64)
226-
self.p_count = 0
217+
self._p_x = np.zeros(n, dtype=np.float64)
218+
self._p_y = np.zeros(n, dtype=np.float64)
219+
self._p_vx = np.zeros(n, dtype=np.float64)
220+
self._p_vy = np.zeros(n, dtype=np.float64)
221+
self._p_age = np.zeros(n, dtype=np.int64)
222+
self._p_lifetime = np.zeros(n, dtype=np.int64)
223+
self._p_shape_idx = np.zeros(n, dtype=np.int64)
224+
self._p_count = 0
227225

228226
# Ambient clouds
229227
self._ambient_clouds: list[Particle] = []
@@ -238,22 +236,10 @@ def __init__(
238236
self._render_out_shape: np.ndarray = np.zeros(0, dtype=np.int32)
239237
self._render_out_cell: np.ndarray = np.zeros(0, dtype=np.int32)
240238

241-
# Prewarm shape arrays for all weather types
242-
self._prewarm_shapes()
243-
244239
@property
245240
def bbox(self) -> BBox:
246241
return BBox(0, 0, self._width, self._height)
247242

248-
def _prewarm_shapes(self) -> None:
249-
original = self._weather_type
250-
for name in self._registry.list_names("weather"):
251-
self._weather_type = name
252-
self._rebuild_shape_cache()
253-
self._weather_type = original
254-
if original:
255-
self._rebuild_shape_cache()
256-
257243
def _get_shape(self, name: str) -> Shape | None:
258244
elem = self._registry.get("particles", name)
259245
if not elem:
@@ -310,14 +296,14 @@ def _build_shape_arrays(self) -> None:
310296
self._render_out_cell = np.zeros(max_output, dtype=np.int32)
311297

312298
def _grow_arrays(self) -> None:
313-
old_size = len(self.p_x)
299+
old_size = len(self._p_x)
314300
new_size = old_size * 2
315-
for attr in ("p_x", "p_y", "p_vx", "p_vy"):
301+
for attr in ("_p_x", "_p_y", "_p_vx", "_p_vy"):
316302
old = getattr(self, attr)
317303
new = np.zeros(new_size, dtype=np.float64)
318304
new[:old_size] = old
319305
setattr(self, attr, new)
320-
for attr in ("p_age", "p_lifetime", "p_shape_idx"):
306+
for attr in ("_p_age", "_p_lifetime", "_p_shape_idx"):
321307
old = getattr(self, attr)
322308
new = np.zeros(new_size, dtype=np.int64)
323309
new[:old_size] = old
@@ -326,7 +312,7 @@ def _grow_arrays(self) -> None:
326312
def set_weather(self, weather_type: str, intensity: float = 0.6, wind_speed: float = 0.0):
327313
if weather_type != self._weather_type:
328314
self._weather_type = weather_type
329-
self.p_count = 0
315+
self._p_count = 0
330316
self._rebuild_shape_cache()
331317
self._intensity = intensity
332318
self._wind_speed = wind_speed
@@ -343,16 +329,16 @@ def tick(self, **ctx) -> None:
343329
if not self._weather_type or not self._shape_cache:
344330
return
345331

346-
if self.p_count > 0:
347-
self.p_count = tick_physics_batch(
348-
self.p_x,
349-
self.p_y,
350-
self.p_vx,
351-
self.p_vy,
352-
self.p_age,
353-
self.p_lifetime,
354-
self.p_shape_idx,
355-
self.p_count,
332+
if self._p_count > 0:
333+
self._p_count = tick_physics_batch(
334+
self._p_x,
335+
self._p_y,
336+
self._p_vx,
337+
self._p_vy,
338+
self._p_age,
339+
self._p_lifetime,
340+
self._p_shape_idx,
341+
self._p_count,
356342
1,
357343
float(self._width),
358344
float(self._height),
@@ -361,7 +347,7 @@ def tick(self, **ctx) -> None:
361347

362348
max_particles = int(self._intensity * self._max_particles_base)
363349
spawn_rate = self._intensity * 2.0
364-
spawn_count = min(np.random.poisson(spawn_rate * 3), max_particles - self.p_count)
350+
spawn_count = min(np.random.poisson(spawn_rate * 3), max_particles - self._p_count)
365351
if spawn_count > 0:
366352
self._spawn_batch(spawn_count)
367353

@@ -399,7 +385,7 @@ def _tick_ambient_clouds(self) -> None:
399385
)
400386

401387
def _spawn_batch(self, count: int) -> None:
402-
while self.p_count + count > len(self.p_x):
388+
while self._p_count + count > len(self._p_x):
403389
self._grow_arrays()
404390

405391
s = self._speed_multiplier
@@ -417,38 +403,30 @@ def _spawn_batch(self, count: int) -> None:
417403
params = (0, w, 0, h, -0.05 * s, 0.1 * s, -0.03 * s, 0.06 * s, 60, 90)
418404

419405
spawn_particles(
420-
self.p_x,
421-
self.p_y,
422-
self.p_vx,
423-
self.p_vy,
424-
self.p_age,
425-
self.p_lifetime,
426-
self.p_shape_idx,
427-
self.p_count,
406+
self._p_x,
407+
self._p_y,
408+
self._p_vx,
409+
self._p_vy,
410+
self._p_age,
411+
self._p_lifetime,
412+
self._p_shape_idx,
413+
self._p_count,
428414
count,
429415
len(self._shape_cache),
430416
*params,
431417
)
432-
self.p_count += count
433-
434-
def _build_exclusion_set(self) -> set:
435-
blocked = set()
436-
for zone in self._exclusion_zones:
437-
for x in range(zone.x, zone.x + zone.w):
438-
for y in range(zone.y, zone.y + zone.h):
439-
blocked.add((x, y))
440-
return blocked
418+
self._p_count += count
441419

442420
def render(self, out_chars: np.ndarray, out_colors: np.ndarray) -> None:
443-
# Build exclusion zones from face sprites in the registry
444-
self._exclusion_zones = []
421+
# Build exclusion set from face sprites in the registry
422+
blocked: set[tuple[int, int]] = set()
445423
if self._scene_registry:
446424
for s in self._scene_registry.alive():
447425
if isinstance(s, FaceCel):
448426
b = s.bbox
449-
self._exclusion_zones.append(BoundingBox(x=b.x, y=b.y, w=b.w, h=b.h))
450-
451-
blocked = self._build_exclusion_set()
427+
for x in range(b.x, b.x2):
428+
for y in range(b.y, b.y2):
429+
blocked.add((x, y))
452430
color = 15
453431
w, h = self._width, self._height
454432

@@ -467,7 +445,7 @@ def render(self, out_chars: np.ndarray, out_colors: np.ndarray) -> None:
467445
out_colors[cy, cx] = color
468446

469447
# Render JIT particles
470-
n = self.p_count
448+
n = self._p_count
471449
if n == 0 or self._shape_offsets is None:
472450
return
473451

@@ -481,9 +459,9 @@ def render(self, out_chars: np.ndarray, out_colors: np.ndarray) -> None:
481459
self._render_out_cell = np.zeros(new_size, dtype=np.int32)
482460

483461
num_cells = compute_render_cells(
484-
self.p_x,
485-
self.p_y,
486-
self.p_shape_idx,
462+
self._p_x,
463+
self._p_y,
464+
self._p_shape_idx,
487465
n,
488466
self._shape_offsets,
489467
self._shape_cell_counts,
@@ -635,8 +613,7 @@ def render(self, out_chars: np.ndarray, out_colors: np.ndarray) -> None:
635613
chars, colors = self._cache_percent(int_pct)
636614
filled = int(int_pct / 100 * self._bar_width)
637615
out_chars[self._y, self._x : self._x + self._bar_width] = chars
638-
out_colors[self._y, self._x : self._x + self._bar_width] = colors
639-
# Override empty portion color with status color
616+
out_colors[self._y, self._x : self._x + filled] = colors[:filled]
640617
out_colors[self._y, self._x + filled : self._x + self._bar_width] = empty_color
641618
else:
642619
filled = int(percent / 100 * self._bar_width)

0 commit comments

Comments
 (0)