Splatter: Angry-Birds slingshot serve — pull back to toss, dotted-line aim, release fires
The touch serve drag now inverts: pull toward yourself to launch up-court. The first pull past the deadzone starts the real toss animation (serveToss), dragServe fires straight from the toss phase without banishing its own fresh toss, and a held aim keeps the toss airborne instead of dropping. Render shows an Angry-Birds dotted trajectory racket->target (red = zombie locked). Two-stage tap serve, mid-rally re-toss/banish, and keyboard serve+arrow-aim unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
6df0ddb00f
commit
013fe8152d
3 files changed
+31
-16
No files matched your search
@@ -396,14 +396,20 @@ export function render() {
|
||||
if (l) drawRing(l.x, l.z, 'rgba(255,255,255,0.85)');
|
||||
}
|
||||
if (G.outMarker) drawRing(G.outMarker.x, G.outMarker.z, G.outMarker.out ? '#ff5050' : '#f8e048');
|
||||
// two-stage serve aim: the reticle tracks the thumb; red = the magnet has a zombie locked
|
||||
if (G.aim && G.mode === 'splatter' && !G.interlude && (G.phase === 'pretoss' || G.phase === 'rally')) {
|
||||
// slingshot serve aim: an angry-birds dotted trajectory from the racket to the aim point;
|
||||
// red = the magnet has a zombie locked, yellow = a free spot on the court
|
||||
if (G.aim && G.mode === 'splatter' && !G.interlude && (G.phase === 'pretoss' || G.phase === 'toss' || G.phase === 'rally')) {
|
||||
const ft = flickTarget(P, G.aim);
|
||||
if (ft.zt) { // locked: the ring rides the zombie itself, plus a marker over its head
|
||||
drawRing(ft.zt.x, ft.zt.z, '#ff5050');
|
||||
const hp = proj(ft.zt.x, 2.2, ft.zt.z);
|
||||
ctx.fillStyle = '#ff5050'; ctx.fillRect(hp.x - 1, hp.y - 4, 3, 3);
|
||||
} else if (ft.tx !== undefined) drawRing(ft.tx, ft.tz, '#f8e048');
|
||||
const tx = ft.zt ? ft.zt.x : ft.tx, tz = ft.zt ? ft.zt.z : ft.tz;
|
||||
if (tx !== undefined) {
|
||||
const col = ft.zt ? '#ff5050' : '#f8e048';
|
||||
const a = proj(P.x, 1.4, P.z), b = proj(tx, 0, tz);
|
||||
ctx.strokeStyle = col; ctx.lineWidth = 2; ctx.setLineDash([3, 5]);
|
||||
ctx.beginPath(); ctx.moveTo(a.x, a.y); ctx.lineTo(b.x, b.y); ctx.stroke();
|
||||
ctx.setLineDash([]);
|
||||
drawRing(tx, tz, col);
|
||||
if (ft.zt) { const hp = proj(ft.zt.x, 2.2, ft.zt.z); ctx.fillStyle = col; ctx.fillRect(hp.x - 1, hp.y - 4, 3, 3); }
|
||||
}
|
||||
}
|
||||
|
||||
// far-side drawables in z order (far → near), then the net, then the near side
|
||||
@@ -524,9 +530,9 @@ export function render() {
|
||||
const sel = ['PLAIN', 'BOMB', 'TRIPLE', 'FIRE', 'GUN'][G.weapon];
|
||||
const txt = G.mode === 'splatter'
|
||||
? (G.weapon === 4 ? (touch ? 'TAP TO UNLOAD THE GUN' : 'SPACE UNLOADS THE GUN')
|
||||
: G.aim ? 'RELEASE TO SERVE · DRAG BACK TO CANCEL'
|
||||
: G.aim ? 'PULL BACK TO AIM · RELEASE TO FIRE'
|
||||
: G.weapon > 0 ? `SERVE FIRES: ${sel} · ${switchHint}`
|
||||
: touch ? 'TAP TO SERVE · HOLD + DRAG TO AIM' : 'SPACE SERVES · ARROWS AIM')
|
||||
: touch ? 'TAP TO SERVE · PULL BACK TO AIM' : 'SPACE SERVES · ARROWS AIM')
|
||||
: G.serveNum === 2 ? (touch ? 'SECOND SERVE — TAP' : 'SECOND SERVE — SPACE')
|
||||
: (touch ? 'TAP TO TOSS, TAP TO SERVE' : 'SPACE TO TOSS, SPACE TO SERVE');
|
||||
ctx.fillText(txt, W / 2, H - TUNE.rackH - RACK_BOT - 17); // sit clear above the rack
|
||||
|
||||
Reference in new issue
Block a user