Add health bars, WeaponHudC/ZombieInvasionHudC, redesign joystick, and clean up shared logic
- New HP-driven health bars for breakable crates (blue/white/black fill, floating damage numbers, world-tracked DOM overlay) - WeaponHudC and ZombieInvasionHudC HUD widgets, PassionOne-Black font, InstallBanner CSS restyle - Reworked PayZoneC's deposit flight to launch from the player's head with a lob arc into the Pay Zone's real center, instead of the HUD anchor - Redesigned the joystick visual (gradient ring, force-gated highlight that tracks the thumb, tuned sizing) and the follow camera framing - Extracted duplicated perspective-scale, screen<->world projection, tween-chain, and flash-overlay logic into src/utils/ - Removed dead code (PhysicsObjPair, PayZoneC.getTargetWorldPosition) and stray console.log calls, trimmed narrative comments across controllers Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,70 @@ export const beforeResourcesLoadedCb = () => {
|
||||
restJoystick: true,
|
||||
restOpacity: 0,
|
||||
follow: false,
|
||||
// nipplejs's own default is 100; the inner thumb is always exactly
|
||||
// half of this by nipplejs's own rule — irrelevant here since .front's
|
||||
// size is overridden independently in main.css.
|
||||
size: 105,
|
||||
// "front" (the thumb/finger position) is a single flat color. Its
|
||||
// actual on-screen SIZE is overridden separately in main.css, since
|
||||
// nipplejs ties it to a hardcoded half of "size" above with no
|
||||
// independent option. "back" (the ring) is a single flat, darkened
|
||||
// color around most of its circumference, except a wide arc right
|
||||
// where the thumb sits, which brightens toward the thumb's own color
|
||||
// as if lit by it. --joy-angle (WHERE) and --joy-force (HOW STRONG)
|
||||
// are live CSS vars driven from onJoysticMove below. The ring's
|
||||
// transparent middle and the thumb's forced-opaque override
|
||||
// (nipplejs hardcodes the thumb at 50% opacity) also live in
|
||||
// main.css, since `color` can't express either.
|
||||
//
|
||||
// Alpha is fixed (not interpolated to 0) at every stop, only the RGB
|
||||
// channels shift with --joy-force — interpolating alpha down to 0
|
||||
// at rest made the highlight's position read as a see-through gap
|
||||
// instead of matching the base color. Alpha itself still ramps up
|
||||
// slightly with force (0.75 -> 0.95) so the highlight reads as the
|
||||
// thumb's actual saturated color rather than diluted by the sandy
|
||||
// background showing through it.
|
||||
color: {
|
||||
back: "conic-gradient(from var(--joy-angle, 0deg), rgba(calc(70 + 185 * var(--joy-force, 0)), calc(55 + 85 * var(--joy-force, 0)), calc(45 - 5 * var(--joy-force, 0)), calc(0.75 + 0.2 * var(--joy-force, 0))) 0deg, rgba(70, 55, 45, 0.75) 85deg, rgba(70, 55, 45, 0.75) 275deg, rgba(calc(70 + 185 * var(--joy-force, 0)), calc(55 + 85 * var(--joy-force, 0)), calc(45 - 5 * var(--joy-force, 0)), calc(0.75 + 0.2 * var(--joy-force, 0))) 360deg)",
|
||||
front: "#ff8c28",
|
||||
},
|
||||
});
|
||||
|
||||
// Keeps --joy-angle/--joy-force (read by the conic-gradient above)
|
||||
// tracking the thumb in real time.
|
||||
//
|
||||
// Angle: uses the thumb's own pixel offset from center (frontPosition —
|
||||
// what nipplejs itself uses to `translate()` the thumb) through
|
||||
// Math.atan2, not nipplejs's own `angle` field (flipped into a
|
||||
// "human-readable" convention internally and rotated again for
|
||||
// orientation-lock logical space — neither matches plain CSS/screen
|
||||
// angle math). atan2 and CSS conic-gradient both sweep clockwise as the
|
||||
// angle increases, but their zero points differ by 90° (atan2's 0° is
|
||||
// 3 o'clock/east; conic-gradient's `from 0deg` is 12 o'clock/north) — the
|
||||
// fix is a flat +90 added once, not a sign flip.
|
||||
//
|
||||
// Force: nipplejs documents `force` as normalized 0..1, but it's
|
||||
// actually computed from the RAW pre-clamp touch distance, while
|
||||
// frontPosition (and so the angle above) uses the CLAMPED distance — so
|
||||
// force keeps climbing past 1 the further you drag beyond the ring's
|
||||
// edge even though the thumb itself is visibly pinned there. Every
|
||||
// calc() above assumes force is 0..1, so it's clamped once here rather
|
||||
// than in every calc() in the gradient string.
|
||||
//
|
||||
// `data.instance` isn't in the SDK's own (stale) type declaration for
|
||||
// this event, though it's really there on every nipplejs 1.x payload —
|
||||
// the cast below bridges that gap.
|
||||
JoystickC.onJoysticMove.addDelegate(({ data }) => {
|
||||
const { instance, force } = data as unknown as {
|
||||
instance?: { frontPosition: { x: number; y: number }; ui: { el: HTMLElement } };
|
||||
force?: number;
|
||||
};
|
||||
if (!instance) return;
|
||||
const { x, y } = instance.frontPosition;
|
||||
const angleDeg = Math.atan2(y, x) * (180 / Math.PI) + 90;
|
||||
const clampedForce = Math.min(Math.max(force ?? 0, 0), 1);
|
||||
instance.ui.el.style.setProperty("--joy-angle", `${angleDeg}deg`);
|
||||
instance.ui.el.style.setProperty("--joy-force", `${clampedForce}`);
|
||||
});
|
||||
|
||||
Template.updateVariableConfig.addDelegate(([category, variable, value]) => {
|
||||
|
||||
Reference in New Issue
Block a user