Add physics/combat foundation, resource pickup flow, VFX polish, and HUD

- Cannon-es colliders for map/props/breakable crates (BreakablePropC,
  PhysicsC), AoE bat combat with facing-cone gating (PlayerC), camera
  follow with obstacle avoidance and facing-lock look-ahead
  (CameraFollowC).
- Resource pickups: scatter/bounce/hit-flash/sparkle-burst lifecycle with
  pooled sparkle VFX (ResourceC, SparkleFxC), flying to a screen-projected
  HUD anchor and on into the Pay Zone with perspective-corrected sizing
  (HudC, PayZoneC).
- Designer VFX playback via three.quarks for crate hit/destroy
  (PropVfxC), plus a procedural weapon-swing trail (WeaponTrailC).
- Resource-counter HUD UI (ui.css, images.ts) with CSS-driven mount/bump
  animations.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Oleksandr Vlasiuk
2026-08-12 18:52:40 +03:00
parent fe1192f4c9
commit 4a22a9b140
20 changed files with 3617 additions and 187 deletions
+98
View File
@@ -2,3 +2,101 @@
/* flex-basis: 60%; */
flex-grow: 1;
}
/* HudC — resource counter plate (dark background + diagonal wood-plank
icon baked into resourceCounterBgSrc, see images.ts/temp/Tool_15.webp).
184x71 source aspect ratio (~2.59:1) — aspect-ratio below derives height
from width automatically, so the two can never drift out of sync the way
two independently-tuned vh values could if only one got changed later.
background-image itself is set from HudC.ts (the asset path/base64 is
only known at runtime via the build's asset pipeline), everything else
lives here.
Split into two elements on purpose: .resource-hud only positions/sizes
and plays the one-shot mount animation; .resource-hud__plate (background
+ number together) is what the update-bump animates. Doing both on the
same element would fight each other — toggling a class that swaps
.resource-hud's own `animation-name` away from resource-hud-enter and
back again makes the browser replay resource-hud-enter every time
(a value change, even back to the same value, restarts a CSS animation),
so every resource pickup would re-trigger the fade/slide-in on top of
the bump. Two elements means two independent animation lifecycles. */
.resource-hud {
/* Single source of truth for the plate's scale — width below and the
count's font-size (see .resource-hud__count) both derive from this one
value, so resizing the whole HUD is a one-line change instead of
hunting down every place a size was independently tuned in vh. */
--hud-width: 9vh;
position: absolute;
top: 6%;
right: 10%;
width: var(--hud-width);
aspect-ratio: 184 / 71;
pointer-events: none;
z-index: 50;
/* Runs once as soon as the element mounts — no JS timing/opacity code
needed, the browser drives it (Day 8: "use built-in animations instead
of changing elements through code"). */
animation: resource-hud-enter 400ms ease-out;
}
@keyframes resource-hud-enter {
from {
opacity: 0;
transform: translateX(1.5rem);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.resource-hud__plate {
position: relative;
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-size: 100% 100%;
}
/* Toggled by HudC whenever the displayed number actually changes — a pure
CSS "pop" of the whole plate (background + number together), not a
JS-driven tween (Day 8 technical note) and not just the digit (see
chat: "не тільки на каунтер"). HudC removes and re-adds this class
(forcing a reflow in between) each time, which is what lets the
animation restart cleanly even if it retriggers before the previous run
finished — e.g. PayZoneC draining one resource every 0.3s while the
player stands in the zone. */
.resource-hud__plate.is-bumping {
animation: resource-hud-bump 220ms ease-out;
}
@keyframes resource-hud-bump {
0% {
transform: scale(1);
}
40% {
transform: scale(1.18);
}
100% {
transform: scale(1);
}
}
.resource-hud__count {
position: absolute;
left: 16%;
top: 46%;
width: 46%;
transform: translateY(-50%);
text-align: center;
color: #ffffff;
font-weight: bold;
/* Scales with --hud-width (set on .resource-hud, inherited down through
.resource-hud__plate) instead of a fixed vh value, so it tracks
whatever the plate is currently sized to — ratio matches the 2.1vh
that read well at the original 12vh plate width (2.1/12 ≈ 0.175). */
font-size: calc(var(--hud-width) * 0.175);
font-family: gameFont, sans-serif;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
}