Aesthetics: 3x render res, flatter lens, 4-frame walk cycles, tiered gore
- RES 2 -> 3: phone screens now DOWNSCALE the canvas (crisp pixels) instead of upscaling it (soft). Umpire-tap coords un-hardcoded from RES=2. - Flatter lens: camZ 36 -> 42 with camF scaled per orientation (406/580) so the PLAYER stays the same size — far-court zombies render ~25% bigger and finally read as individuals from the baseline. - Smoother animation: 4-frame walk cycles for both classic shamblers and the runner's sprint (new sheets, same style anchor; z_a1-4, z_b1-4, z_f1-4). Same cycle frequency — frames subdivide the stride. Render falls back to 2 frames per variant until its sheet loads. - Tiered gore (GORE_MUL): the more advanced the zombie, the more absurd the mess — classics 1x (base bumped 24 -> 30 particles), runner 1.8x, shield 2.5x, racket boss 3x, brute 4x (120 particles, a scatter of stains, an instant size-3 mound). Verified: fresh origin, canvas 1440px, umpire triple-tap works at RES 3, all 4 anim frames cycle at the old stride rate, brute kill = 120 parts / 2 stains / size-3 pile, far-court lineup screenshot clearly readable, portrait layout numbers correct (810x1440, camF 580), tennis 11/12, no console errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e75b3888de
commit
e948e8b36e
19 files changed
+28
-15
No files matched your search
@@ -30,7 +30,7 @@ function palette() {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- camera ----
|
||||
export const RES = 2; // physical pixels per logical pixel — sprites keep 2x detail
|
||||
export const RES = 3; // physical pixels per logical pixel — 3x so phone screens downscale (crisp) instead of upscaling (soft)
|
||||
export let W = 480, H = 270;
|
||||
|
||||
export function fitViewport() { // landscape 480x270, portrait 270x480 with a longer lens
|
||||
@@ -39,7 +39,9 @@ export function fitViewport() { // landscape 480x270, portrait 270x480 with a lo
|
||||
if (cv.width !== w * RES) {
|
||||
W = w; H = h;
|
||||
cv.width = w * RES; cv.height = h * RES;
|
||||
TUNE.camF = portrait ? 400 : 280;
|
||||
// flatter lens: camZ pushed back (config 42, was 36) with camF scaled to keep the PLAYER
|
||||
// the same size — far-court zombies render ~25% bigger and actually read as zombies
|
||||
TUNE.camF = portrait ? 580 : 406;
|
||||
TUNE.horizon = portrait ? 90 : 40;
|
||||
buildCrowd();
|
||||
}
|
||||
@@ -60,8 +62,8 @@ const SPR = {};
|
||||
for (const n of ['p_idle1','p_idle2','p_bounce','p_bounce2','p_toss','p_smash','p_run1','p_run2','p_swing1','p_swing2',
|
||||
'o_idle1','o_idle2','o_bounce','o_bounce2','o_toss','o_smash','o_run1','o_run2','o_swing1','o_swing2',
|
||||
'x_ump','x_boyrun1','x_boyrun2','x_boyrun3','x_boyrun4',
|
||||
'z_a1','z_a2','z_b1','z_b2','z_c1','z_c2',
|
||||
'z_f1','z_f2','z_g1','z_g2','z_s1','z_s2','z_s3']) {
|
||||
'z_a1','z_a2','z_a3','z_a4','z_b1','z_b2','z_b3','z_b4','z_c1','z_c2',
|
||||
'z_f1','z_f2','z_f3','z_f4','z_g1','z_g2','z_s1','z_s2','z_s3']) {
|
||||
const img = new Image();
|
||||
img.onload = () => SPR[n] = img;
|
||||
img.src = 'assets/' + n + '.png';
|
||||
@@ -129,10 +131,14 @@ function drawBoy(b) {
|
||||
ctx.drawImage(img, -w / 2, -h, w, h);
|
||||
ctx.restore();
|
||||
}
|
||||
const ZFRAMES = { a: 4, b: 4, f: 4 }; // 4-frame walk cycles where sheets exist; the rest stay 2
|
||||
function drawZombie(zb) {
|
||||
const rk = zb.variant === 'r';
|
||||
const v = rk ? 'c' : zb.variant; // the racket boss reuses the turned-CPU sprite (already holds a racket)
|
||||
let frame = rk && zb.pose === 'swing' ? 2 : Math.floor(zb.walkT * (zb.variant === 'f' ? 6 : 2.6)) % 2 + 1;
|
||||
let N = ZFRAMES[v] || 2;
|
||||
if (!SPR['z_' + v + N]) N = 2; // frames still loading (or sheet rejected): 2-frame fallback
|
||||
// same CYCLE frequency as before — more frames subdivide the stride, they don't speed it up
|
||||
let frame = rk && zb.pose === 'swing' ? 2 : Math.floor(zb.walkT * (zb.variant === 'f' ? 6 : 2.6) * N / 2) % N + 1;
|
||||
if (zb.variant === 's' && zb.shieldT > 0) frame = 3; // chair dropped — hit it NOW
|
||||
const h = zb.variant === 'g' ? 2.7 : rk ? 1.85 : 1.8; // the brute towers half again over the crowd
|
||||
drawStatic('z_' + v + frame, zb.x, zb.z, h, Math.floor(zb.walkT * 5.2) % 2);
|
||||
|
||||
Reference in new issue
Block a user