quickshell: panels launch the worm instead of turning him around
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
bdb3ab0c75
commit
9b43f5f669
1 changed files with 40 additions and 40 deletions
|
|
@ -935,16 +935,9 @@ in
|
||||||
property bool loose: false // shoved off, ballistic
|
property bool loose: false // shoved off, ballistic
|
||||||
property real vx: 0
|
property real vx: 0
|
||||||
property real vy: 0
|
property real vy: 0
|
||||||
|
property real spin: 0 // rad/tick while airborne
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn around: the two ends swap roles, so the face leads in
|
|
||||||
// the new direction instead of the worm moonwalking.
|
|
||||||
function reverse() {
|
|
||||||
let f = worm.frontD;
|
|
||||||
worm.frontD = worm.backD;
|
|
||||||
worm.backD = f;
|
|
||||||
worm.step = -worm.step;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Every segment's position, rebuilt each tick. One array
|
// Every segment's position, rebuilt each tick. One array
|
||||||
// instead of per-segment bindings: the gait and the ballistic
|
// instead of per-segment bindings: the gait and the ballistic
|
||||||
|
|
@ -1005,11 +998,17 @@ in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (worm.loose) {
|
if (worm.loose) {
|
||||||
// Flying, he keeps whatever shape he was
|
// Airborne he keeps the shape he was caught
|
||||||
// caught in and simply travels — a curled-up
|
// in and tumbles about his own head: map()
|
||||||
// worm mid-air, not a swimming one.
|
// reads the old array throughout, so body[0]
|
||||||
let dx = hx - body[0].x, dy = hy - body[0].y;
|
// stays the pivot and the head lands exactly
|
||||||
body = body.map(p => Qt.point(p.x + dx, p.y + dy));
|
// on the new position.
|
||||||
|
let c = Math.cos(worm.spin), s = Math.sin(worm.spin);
|
||||||
|
let px = body[0].x, py = body[0].y;
|
||||||
|
body = body.map(p => {
|
||||||
|
let ox = p.x - px, oy = p.y - py;
|
||||||
|
return Qt.point(hx + ox * c - oy * s, hy + ox * s + oy * c);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
body = railBody();
|
body = railBody();
|
||||||
}
|
}
|
||||||
|
|
@ -1071,46 +1070,47 @@ in
|
||||||
// direction off of.
|
// direction off of.
|
||||||
property var pushers: []
|
property var pushers: []
|
||||||
property var prevRects: []
|
property var prevRects: []
|
||||||
readonly property real shoveSpeed: 18
|
readonly property real shoveSpeed: 26
|
||||||
|
// Ticks before a panel may launch him again. Without it he can
|
||||||
|
// land back inside the same rect with his head over the edge
|
||||||
|
// and get booted forever.
|
||||||
|
property int shoveCool: 0
|
||||||
|
|
||||||
|
function launch(p) {
|
||||||
|
worm.loose = true;
|
||||||
|
worm.vx = p.push.x * shoveSpeed;
|
||||||
|
worm.vy = p.push.y * shoveSpeed - 8; // -8: sent up, not slid along
|
||||||
|
worm.spin = (0.04 + Math.random() * 0.05) * (p.push.x >= 0 ? 1 : -1);
|
||||||
|
shoveCool = 45;
|
||||||
|
}
|
||||||
|
|
||||||
function inRect(p, r) {
|
function inRect(p, r) {
|
||||||
return Math.abs(p.x - r.x) <= r.z + 6 && Math.abs(p.y - r.y) <= r.w + 6;
|
return Math.abs(p.x - r.x) <= r.z + 6 && Math.abs(p.y - r.y) <= r.w + 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkShove() {
|
function checkShove() {
|
||||||
let head = body[0], tail = body[segments - 1];
|
if (shoveCool > 0) { shoveCool--; return; }
|
||||||
|
let tail = body[segments - 1];
|
||||||
for (let i = 0; i < pushers.length; i++) {
|
for (let i = 0; i < pushers.length; i++) {
|
||||||
let r = pushers[i].rect, q = prevRects[i];
|
let r = pushers[i].rect, q = prevRects[i];
|
||||||
if (!r || r.z < 0.5) continue;
|
if (!r || r.z < 0.5) continue;
|
||||||
// Any part of him in the way is enough to be swept;
|
// Any part of him in the way is enough to be caught.
|
||||||
// only the head decides a turn-around.
|
|
||||||
let touched = false;
|
let touched = false;
|
||||||
for (let s = 0; s < body.length && !touched; s++)
|
for (let s = 0; s < body.length && !touched; s++)
|
||||||
touched = inRect(body[s], r);
|
touched = inRect(body[s], r);
|
||||||
if (!touched) continue;
|
if (!touched) continue;
|
||||||
// Either it was not there a tick ago — the pop-out,
|
// A panel popping out on top of him and him crawling
|
||||||
// and the usual case given how fast the morph is — or
|
// into one already open both end the same way now:
|
||||||
// an edge has swept outward over him since. Both mean
|
// launched. Only the first is the moment you asked
|
||||||
// the panel arrived where he was standing.
|
// for, but a dropdown sits open for minutes while he
|
||||||
let appeared = !q || q.z < 0.5;
|
// crawls at well under a pixel a tick, so contact is
|
||||||
let grew = !appeared && (
|
// the event you actually see — and having that merely
|
||||||
(r.x + r.z) - (q.x + q.z) > 1 || (q.x - q.z) - (r.x - r.z) > 1
|
// turn him round is what read as never being knocked.
|
||||||
|| (r.y + r.w) - (q.y + q.w) > 1 || (q.y - q.w) - (r.y - r.w) > 1);
|
//
|
||||||
if (appeared || grew) {
|
// The exception is his whole body being inside, which
|
||||||
worm.loose = true;
|
// means he landed in there: walking out is the way
|
||||||
worm.vx = pushers[i].push.x * shoveSpeed;
|
// out, and kicking him again would only pin him.
|
||||||
worm.vy = pushers[i].push.y * shoveSpeed - 3; // -3: a little air
|
if (!inRect(tail, r)) launch(pushers[i]);
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Sitting still, it is simply solid: he walks into the
|
|
||||||
// panel and turns around rather than crawling through
|
|
||||||
// it, which is what made an open dropdown feel like it
|
|
||||||
// was not there at all. Only turn him when he is
|
|
||||||
// ENTERING — head in, tail still out. Whole body
|
|
||||||
// inside (he landed there) means walking on is the way
|
|
||||||
// out, and reversing on that would just buzz him in
|
|
||||||
// place against both edges.
|
|
||||||
if (inRect(head, r) && !inRect(tail, r)) reverse();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue