Goo Tower and Zuma Changes
This commit is contained in:
parent
052417aa9a
commit
a6573726ff
|
|
@ -28,30 +28,89 @@
|
|||
1000
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "solid",
|
||||
"poly": [
|
||||
[
|
||||
287,
|
||||
847
|
||||
],
|
||||
[
|
||||
292,
|
||||
463
|
||||
],
|
||||
[
|
||||
517,
|
||||
460
|
||||
],
|
||||
[
|
||||
525,
|
||||
540
|
||||
],
|
||||
[
|
||||
335,
|
||||
553
|
||||
],
|
||||
[
|
||||
336,
|
||||
852
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "solid",
|
||||
"poly": [
|
||||
[
|
||||
648,
|
||||
461
|
||||
],
|
||||
[
|
||||
636,
|
||||
532
|
||||
],
|
||||
[
|
||||
958,
|
||||
534
|
||||
],
|
||||
[
|
||||
955,
|
||||
850
|
||||
],
|
||||
[
|
||||
1056,
|
||||
850
|
||||
],
|
||||
[
|
||||
1055,
|
||||
458
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"balls": [
|
||||
{
|
||||
"x": 300,
|
||||
"y": 836,
|
||||
"type": "common",
|
||||
"pinned": true
|
||||
"x": 516,
|
||||
"y": 828,
|
||||
"type": "ivy",
|
||||
"pinned": false
|
||||
},
|
||||
{
|
||||
"x": 362,
|
||||
"y": 836,
|
||||
"type": "common",
|
||||
"pinned": true
|
||||
"x": 609,
|
||||
"y": 827,
|
||||
"type": "ivy",
|
||||
"pinned": false
|
||||
},
|
||||
{
|
||||
"x": 331,
|
||||
"y": 782,
|
||||
"type": "common"
|
||||
"x": 563,
|
||||
"y": 757,
|
||||
"type": "ivy",
|
||||
"pinned": false
|
||||
}
|
||||
],
|
||||
"strands": [
|
||||
[
|
||||
2,
|
||||
1,
|
||||
0
|
||||
],
|
||||
[
|
||||
|
|
@ -59,117 +118,117 @@
|
|||
1
|
||||
],
|
||||
[
|
||||
0,
|
||||
1
|
||||
2,
|
||||
0
|
||||
]
|
||||
],
|
||||
"pipe": {
|
||||
"x": 660,
|
||||
"y": 560,
|
||||
"r": 46
|
||||
},
|
||||
"pile": [
|
||||
{
|
||||
"x": 540,
|
||||
"y": 834,
|
||||
"x": 702,
|
||||
"y": 822,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 570,
|
||||
"y": 834,
|
||||
"x": 743,
|
||||
"y": 820,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 600,
|
||||
"y": 834,
|
||||
"x": 779,
|
||||
"y": 824,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 630,
|
||||
"y": 834,
|
||||
"x": 848,
|
||||
"y": 825,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 660,
|
||||
"y": 834,
|
||||
"x": 891,
|
||||
"y": 822,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 690,
|
||||
"y": 834,
|
||||
"x": 866,
|
||||
"y": 795,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 540,
|
||||
"y": 804,
|
||||
"x": 821,
|
||||
"y": 792,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 570,
|
||||
"y": 804,
|
||||
"x": 785,
|
||||
"y": 789,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 600,
|
||||
"y": 804,
|
||||
"x": 752,
|
||||
"y": 784,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 630,
|
||||
"y": 804,
|
||||
"x": 727,
|
||||
"y": 786,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 660,
|
||||
"y": 804,
|
||||
"x": 810,
|
||||
"y": 825,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 690,
|
||||
"y": 804,
|
||||
"x": 743,
|
||||
"y": 742,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 860,
|
||||
"y": 834,
|
||||
"type": "common"
|
||||
"x": 785,
|
||||
"y": 764,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 890,
|
||||
"y": 834,
|
||||
"type": "common"
|
||||
"x": 825,
|
||||
"y": 762,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 920,
|
||||
"y": 834,
|
||||
"type": "common"
|
||||
"x": 851,
|
||||
"y": 762,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 950,
|
||||
"y": 834,
|
||||
"type": "common"
|
||||
"x": 791,
|
||||
"y": 728,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 980,
|
||||
"y": 834,
|
||||
"type": "common"
|
||||
"x": 845,
|
||||
"y": 742,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 1010,
|
||||
"y": 834,
|
||||
"type": "common"
|
||||
"x": 825,
|
||||
"y": 705,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 1040,
|
||||
"y": 834,
|
||||
"type": "common"
|
||||
"x": 762,
|
||||
"y": 707,
|
||||
"type": "ivy"
|
||||
},
|
||||
{
|
||||
"x": 1070,
|
||||
"y": 834,
|
||||
"type": "common"
|
||||
"x": 803,
|
||||
"y": 679,
|
||||
"type": "ivy"
|
||||
}
|
||||
],
|
||||
"pipe": {
|
||||
"x": 598,
|
||||
"y": 110,
|
||||
"r": 46
|
||||
},
|
||||
"required": 4,
|
||||
"ocdTarget": 9
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,5 +156,5 @@
|
|||
"powerUpRate": 0.07
|
||||
}
|
||||
],
|
||||
"background": "zuma-background-2"
|
||||
"background": "zuma-background-1"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,5 +71,6 @@
|
|||
"pushSpeed": 45,
|
||||
"powerUpRate": 0.06
|
||||
}
|
||||
]
|
||||
],
|
||||
"background": "zuma-background-1"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,5 +101,6 @@
|
|||
"pushSpeed": 30,
|
||||
"powerUpRate": 0.06
|
||||
}
|
||||
]
|
||||
],
|
||||
"background": "zuma-background-1"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,5 +80,6 @@
|
|||
"pushSpeed": 30,
|
||||
"powerUpRate": 0.06
|
||||
}
|
||||
]
|
||||
],
|
||||
"background": "zuma-background-4"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
990
|
||||
],
|
||||
"colors": 4,
|
||||
"background": "zuma-background-2",
|
||||
"background": "zuma-background-1",
|
||||
"seed": 48514,
|
||||
"starScores": [
|
||||
1120,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
770
|
||||
],
|
||||
"colors": 4,
|
||||
"background": "zuma-background-1",
|
||||
"background": "zuma-background-2",
|
||||
"seed": 56433,
|
||||
"starScores": [
|
||||
910,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
550
|
||||
],
|
||||
"colors": 5,
|
||||
"background": "zuma-background-1",
|
||||
"background": "zuma-background-2",
|
||||
"seed": 72271,
|
||||
"starScores": [
|
||||
1210,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
575
|
||||
],
|
||||
"colors": 5,
|
||||
"background": "zuma-background-1",
|
||||
"background": "zuma-background-2",
|
||||
"seed": 88109,
|
||||
"starScores": [
|
||||
1450,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
550
|
||||
],
|
||||
"colors": 5,
|
||||
"background": "zuma-background-1",
|
||||
"background": "zuma-background-3",
|
||||
"seed": 103947,
|
||||
"starScores": [
|
||||
1210,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
575
|
||||
],
|
||||
"colors": 5,
|
||||
"background": "zuma-background-2",
|
||||
"background": "zuma-background-3",
|
||||
"seed": 111866,
|
||||
"starScores": [
|
||||
1640,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
580
|
||||
],
|
||||
"colors": 6,
|
||||
"background": "zuma-background-1",
|
||||
"background": "zuma-background-3",
|
||||
"seed": 119785,
|
||||
"starScores": [
|
||||
1170,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
600
|
||||
],
|
||||
"colors": 6,
|
||||
"background": "zuma-background-2",
|
||||
"background": "zuma-background-3",
|
||||
"seed": 127704,
|
||||
"starScores": [
|
||||
1400,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
550
|
||||
],
|
||||
"colors": 6,
|
||||
"background": "zuma-background-1",
|
||||
"background": "zuma-background-3",
|
||||
"seed": 135623,
|
||||
"starScores": [
|
||||
1230,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
990
|
||||
],
|
||||
"colors": 6,
|
||||
"background": "zuma-background-2",
|
||||
"background": "zuma-background-3",
|
||||
"seed": 143542,
|
||||
"starScores": [
|
||||
1440,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
575
|
||||
],
|
||||
"colors": 6,
|
||||
"background": "zuma-background-1",
|
||||
"background": "zuma-background-4",
|
||||
"seed": 151461,
|
||||
"starScores": [
|
||||
1940,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
575
|
||||
],
|
||||
"colors": 6,
|
||||
"background": "zuma-background-2",
|
||||
"background": "zuma-background-4",
|
||||
"seed": 159380,
|
||||
"starScores": [
|
||||
2040,
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 343 KiB After Width: | Height: | Size: 347 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 MiB |
|
|
@ -102,6 +102,7 @@ export default class GooTowerGame extends Phaser.Scene {
|
|||
this.state = null;
|
||||
this.accum = 0;
|
||||
this.held = null;
|
||||
this.wasAttached = false; // true when held ball was detached from structure
|
||||
this.boardObjs = [];
|
||||
this.overlayUp = false;
|
||||
this.finished = false;
|
||||
|
|
@ -183,6 +184,7 @@ export default class GooTowerGame extends Phaser.Scene {
|
|||
this.viewMode = 'select';
|
||||
this.state = null;
|
||||
this.held = null;
|
||||
this.wasAttached = false;
|
||||
this.clearBoard();
|
||||
|
||||
const cx = GAME_WIDTH / 2;
|
||||
|
|
@ -328,6 +330,7 @@ export default class GooTowerGame extends Phaser.Scene {
|
|||
this.state = createState(def, 0x60071e + level);
|
||||
this.accum = 0;
|
||||
this.held = null;
|
||||
this.wasAttached = false;
|
||||
this.overlayUp = false;
|
||||
this.finished = false;
|
||||
|
||||
|
|
@ -561,6 +564,7 @@ export default class GooTowerGame extends Phaser.Scene {
|
|||
if (!ball) return;
|
||||
if (beginDrag(this.state, ball, null)) {
|
||||
this.held = ball;
|
||||
this.wasAttached = ball.wasDetached; // only true for detached balls
|
||||
playSound(this, SFX.UI_PICK);
|
||||
}
|
||||
}
|
||||
|
|
@ -584,9 +588,11 @@ export default class GooTowerGame extends Phaser.Scene {
|
|||
if (!this.held || !this.state) return;
|
||||
const w = this.toWorld(p);
|
||||
const ball = this.held;
|
||||
const wasAttached = this.wasAttached;
|
||||
this.held = null;
|
||||
this.wasAttached = false;
|
||||
const events = [];
|
||||
const stuck = endDrag(this.state, ball, w.x, w.y, events);
|
||||
const stuck = endDrag(this.state, ball, w.x, w.y, events, wasAttached);
|
||||
playSound(this, stuck ? SFX.UI_PLACE : SFX.SQUISH);
|
||||
this.handleEvents(events);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -315,6 +315,8 @@ export function addBall(state, x, y, type = 'common', opts = {}) {
|
|||
exploded: false,
|
||||
held: false, // under the player's cursor; physics leaves it alone
|
||||
grounded: false,
|
||||
wasDetached: false, // true when an attached ball was detached mid-drag
|
||||
detachTime: 0, // simulation clock time when detached (0 = not recently detached)
|
||||
// crawling
|
||||
walking: false,
|
||||
onStrand: -1,
|
||||
|
|
@ -979,24 +981,49 @@ export function placeBall(state, ball, x, y, events = null) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// The nearest ball the player is allowed to pick up: anything loose, plus
|
||||
// attached goo of a detachable type.
|
||||
// The nearest ball the player is allowed to pick up:
|
||||
//
|
||||
// 1. Loose (unattached) balls within reach — preferred so you can grab crawlers
|
||||
// without accidentally detaching structural balls.
|
||||
// 2. Attached detachable balls ONLY when clicked directly on them (center-to-
|
||||
// center distance ≤ ball radius). A glancing pick near the edge does NOT
|
||||
// detach them — this prevents the "oops I ripped off my ivy" problem.
|
||||
//
|
||||
// Non-detachable attached balls are never returned.
|
||||
export function pickBallAt(state, x, y, reach = 42) {
|
||||
let best = null;
|
||||
let bestD = Infinity;
|
||||
let bestLoose = null;
|
||||
let bestLooseD = Infinity;
|
||||
let bestDirect = null;
|
||||
let bestDirectD = Infinity;
|
||||
for (const b of state.balls) {
|
||||
if (b.dead) continue;
|
||||
if (b.attached && !gooType(b.type).detachable) continue;
|
||||
const d = Math.hypot(b.x - x, b.y - y);
|
||||
if (d > reach + b.r || d >= bestD) continue;
|
||||
bestD = d;
|
||||
best = b;
|
||||
if (b.attached) {
|
||||
// Attached detachable: only count if clicked DIRECTLY on the ball
|
||||
// (center-to-center ≤ radius). No grace perimeter.
|
||||
if (d <= b.r && d < bestDirectD) { bestDirectD = d; bestDirect = b; }
|
||||
} else {
|
||||
// Loose ball: standard reach radius
|
||||
if (d <= reach + b.r && d < bestLooseD) { bestLooseD = d; bestLoose = b; }
|
||||
}
|
||||
return best;
|
||||
}
|
||||
// Prefer a loose ball; only return an attached one if clicked directly on it
|
||||
// and there's no loose ball closer.
|
||||
if (bestLoose) return bestLoose;
|
||||
return bestDirect;
|
||||
}
|
||||
|
||||
export function beginDrag(state, ball, events = null) {
|
||||
if (!ball || ball.dead) return false;
|
||||
// Cooldown check: if recently detached, block pickup until cooldown expires
|
||||
if (ball.detachTime > 0) {
|
||||
const elapsed = state.clock - ball.detachTime;
|
||||
if (elapsed < DETACH_COOLDOWN) return false;
|
||||
// Cooldown expired — allow normal handling
|
||||
ball.wasDetached = false;
|
||||
ball.detachTime = 0;
|
||||
}
|
||||
if (ball.attached) {
|
||||
if (!gooType(ball.type).detachable) return false;
|
||||
for (const sid of ball.strands.slice()) {
|
||||
|
|
@ -1005,6 +1032,7 @@ export function beginDrag(state, ball, events = null) {
|
|||
}
|
||||
ball.strands = [];
|
||||
ball.attached = false;
|
||||
ball.wasDetached = true; // mark so endDrag knows to drop as loose
|
||||
if (!state.pile.includes(ball.id)) state.pile.push(ball.id);
|
||||
}
|
||||
ball.held = true;
|
||||
|
|
@ -1021,10 +1049,27 @@ export function dragTo(state, ball, x, y) {
|
|||
ball.px = x; ball.py = y; // dropped goo starts from rest, never flung
|
||||
}
|
||||
|
||||
// Cooldown in seconds before a detached ball can be re-attached.
|
||||
export const DETACH_COOLDOWN = 2;
|
||||
|
||||
// Returns true when the ball stuck to the structure; false means it was
|
||||
// released into the world as loose goo again.
|
||||
export function endDrag(state, ball, x, y, events = null) {
|
||||
//
|
||||
// When `wasAttached` is true the ball was detached mid-drag and must NOT
|
||||
// re-attach on drop — it goes straight back to the pile as loose goo.
|
||||
export function endDrag(state, ball, x, y, events = null, wasAttached = false) {
|
||||
if (!ball) return false;
|
||||
if (wasAttached) {
|
||||
// Detached ball drops as loose goo — no re-attachment.
|
||||
// Start the cooldown timer (use clock + 0.001 to avoid 0 issue).
|
||||
ball.wasDetached = false;
|
||||
ball.detachTime = state.clock + 0.001;
|
||||
ball.held = false;
|
||||
ball.x = x; ball.y = y; ball.px = x; ball.py = y;
|
||||
if (!ball.attached && !state.pile.includes(ball.id)) state.pile.push(ball.id);
|
||||
if (events) events.push({ type: 'placeFailed', ball: ball.id });
|
||||
return false;
|
||||
}
|
||||
if (placeBall(state, ball, x, y, events)) return true;
|
||||
ball.held = false;
|
||||
ball.x = x; ball.y = y; ball.px = x; ball.py = y;
|
||||
|
|
|
|||
Loading…
Reference in New Issue