[PR #1949] [MERGED] fix(site): make All-Reduce Rhythm chunks animate, taps flash, and game clean up #34673

Closed
opened 2026-07-14 19:28:34 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/harvard-edge/cs249r_book/pull/1949
Author: @farhan523
Created: 7/7/2026
Status: Merged
Merged: 7/10/2026
Merged by: @profvjreddi

Base: devHead: fix/allreduce-game-defects


📝 Commits (1)

  • 4924dba fix(site): make All-Reduce Rhythm chunks animate, taps flash, and game clean up

📊 Changes

1 file changed (+16 additions, -8 deletions)

View changed files

📝 site/assets/games/allreduce.mjs (+16 -8)

📄 Description

Problem

Three defects in the All-Reduce Rhythm mini-game (site/assets/games/allreduce.mjs):

1. Gradient chunks never animate — the game's core visual is broken.
tween() (runtime.mjs:307) has signature tween(target, prop, from, to, ms, ease). The call passed [chunk.position, chunk.position] as target with props ["x","y"], so the multi-prop branch assigned x/y onto the array, never onto chunk.position. On every perfect beat a chunk spawned at the source GPU, sat frozen for the whole beat, then vanished with a burst at the destination. The ring-transfer metaphor — data traveling GPU to GPU, the point of the game — never rendered.

2. Tap highlight is a no-op.
The GPU box was filled with COL.gpu and the "flash" set tint = 0xffffff (the identity tint in Pixi), then "reset" it to the same 0xffffff. Players got zero visual feedback that their tap registered.

3. No cleanup on unmount.
Unlike sibling games (cluster.mjs, pipeline.mjs), the module registered an anonymous global keydown listener and returned no destroy(). Remounting without a full page reload stacks permanent handlers bound to dead game state and leaks a WebGL context per mount.

Fix

  • tween(chunk, ["position.x", "position.y"], ...) — same pattern as moe.mjs:82. Also cancel the tween before chunk.destroy() so the tween's final tick can't touch a destroyed object.
  • Fill the box white and tint it down to COL.gpu at rest (Pixi tints can only darken). The white tint on tap now genuinely flashes the box; the 100 ms reset restores COL.gpu. Resting render is pixel-identical (0xffffff × COL.gpu = COL.gpu).
  • Named handleKeydown + destroy() in the returned object, matching the cluster.mjs convention: removes the listener and calls app.destroy(true, { children: true, texture: true }).

No scoring, timing, or gameplay logic touched. Verified with node --check; +16/−8 in one file.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/harvard-edge/cs249r_book/pull/1949 **Author:** [@farhan523](https://github.com/farhan523) **Created:** 7/7/2026 **Status:** ✅ Merged **Merged:** 7/10/2026 **Merged by:** [@profvjreddi](https://github.com/profvjreddi) **Base:** `dev` ← **Head:** `fix/allreduce-game-defects` --- ### 📝 Commits (1) - [`4924dba`](https://github.com/harvard-edge/cs249r_book/commit/4924dbad53b00e0d46ce8c0990d0054149aa7471) fix(site): make All-Reduce Rhythm chunks animate, taps flash, and game clean up ### 📊 Changes **1 file changed** (+16 additions, -8 deletions) <details> <summary>View changed files</summary> 📝 `site/assets/games/allreduce.mjs` (+16 -8) </details> ### 📄 Description ## Problem Three defects in the All-Reduce Rhythm mini-game (`site/assets/games/allreduce.mjs`): **1. Gradient chunks never animate — the game's core visual is broken.** `tween()` (`runtime.mjs:307`) has signature `tween(target, prop, from, to, ms, ease)`. The call passed `[chunk.position, chunk.position]` as `target` with props `["x","y"]`, so the multi-prop branch assigned `x`/`y` onto the *array*, never onto `chunk.position`. On every perfect beat a chunk spawned at the source GPU, sat frozen for the whole beat, then vanished with a burst at the destination. The ring-transfer metaphor — data traveling GPU to GPU, the point of the game — never rendered. **2. Tap highlight is a no-op.** The GPU box was filled with `COL.gpu` and the "flash" set `tint = 0xffffff` (the identity tint in Pixi), then "reset" it to the same `0xffffff`. Players got zero visual feedback that their tap registered. **3. No cleanup on unmount.** Unlike sibling games (`cluster.mjs`, `pipeline.mjs`), the module registered an **anonymous global `keydown` listener** and returned no `destroy()`. Remounting without a full page reload stacks permanent handlers bound to dead game state and leaks a WebGL context per mount. ## Fix - `tween(chunk, ["position.x", "position.y"], ...)` — same pattern as `moe.mjs:82`. Also cancel the tween before `chunk.destroy()` so the tween's final tick can't touch a destroyed object. - Fill the box **white** and tint it down to `COL.gpu` at rest (Pixi tints can only darken). The white tint on tap now genuinely flashes the box; the 100 ms reset restores `COL.gpu`. Resting render is pixel-identical (`0xffffff × COL.gpu = COL.gpu`). - Named `handleKeydown` + `destroy()` in the returned object, matching the `cluster.mjs` convention: removes the listener and calls `app.destroy(true, { children: true, texture: true })`. No scoring, timing, or gameplay logic touched. Verified with `node --check`; +16/−8 in one file. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-07-14 19:28:34 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/cs249r_book#34673