quickshell: redraw Archie at 2px, fix his paws, add a throwable ball and a bed
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
d53e491812
commit
36360544ee
1 changed files with 346 additions and 125 deletions
|
|
@ -1125,12 +1125,13 @@ in
|
|||
import QtQuick
|
||||
|
||||
// Archie — a black and tan dachshund with a red collar, living
|
||||
// along the bottom of the screen. He trots up and down, stops to
|
||||
// wag, and every so often remembers his bowl and goes for a snack.
|
||||
// along the bottom of the screen. He trots about, wags, naps in
|
||||
// his bed, visits his bowl, and fetches a ball you can pick up
|
||||
// and fling with the mouse.
|
||||
//
|
||||
// The art is plain text, one character per pixel, so he can be
|
||||
// redrawn by editing the picture instead of editing code. He walks
|
||||
// on all fours and never limps; that was deliberate.
|
||||
// evenly on all fours and never limps; that was deliberate.
|
||||
Item {
|
||||
id: archie
|
||||
anchors.fill: parent
|
||||
|
|
@ -1138,190 +1139,369 @@ in
|
|||
property bool primary: true
|
||||
visible: primary
|
||||
|
||||
// 4px pixels, not the worm's 6: he reads better with more
|
||||
// pixels in him, and at 112x48 he takes up a lot less of the
|
||||
// screen than the chunkier first pass did.
|
||||
readonly property int cell: 4
|
||||
readonly property int cols: 28
|
||||
readonly property int rows: 12
|
||||
// 2px pixels: plenty of resolution for a proper pointed
|
||||
// dachshund head, and he still lands smaller on screen than
|
||||
// the chunkier drawing did.
|
||||
readonly property int cell: 2
|
||||
readonly property int cols: 44
|
||||
readonly property int rows: 19
|
||||
|
||||
// Not themed — he looked how he looked.
|
||||
readonly property var pal: ({
|
||||
"K": "#2b2523", // black
|
||||
"T": "#a86a30", // tan
|
||||
"R": "#b3322c", // collar, and his bowl
|
||||
"N": "#14100f", // nose
|
||||
"W": "#efe7dd", // catchlight
|
||||
"B": "#96602f" // kibble
|
||||
"N": "#14100f", // nose and eye
|
||||
"B": "#96602f", // kibble
|
||||
"G": "#5a667a", // bed
|
||||
"D": "#3a4454", // bed cushion
|
||||
"Y": "#c8d84a", // ball
|
||||
"L": "#e4ee8c" // ball highlight
|
||||
})
|
||||
|
||||
// Trotting: legs out at full stride, tail up.
|
||||
// Trotting: front leg forward, hind leg back, tail up. Paws
|
||||
// point the way he is going — drawn trailing behind the leg
|
||||
// they read as feet on backwards, which is exactly how the
|
||||
// first pass looked.
|
||||
readonly property var walkA: [
|
||||
"....................KKKKK...",
|
||||
"...................KKTKKKK..",
|
||||
"KK.................KKNTTKKN.",
|
||||
".KKKKKKKKKKKKKKKKKRKKTTTTTN.",
|
||||
"..KKKKKKKKKKKKKKKKRKKTTTT...",
|
||||
"..KKKKKKKKKKKKKKKKRKKTT.....",
|
||||
"...KKKKKKKKKKKKKKTTT........",
|
||||
"....TKKKKKKKKKKKTTT.........",
|
||||
"....TTKKKKKKKKKTTT..........",
|
||||
"....TT..........TT..........",
|
||||
"....TT..........TT..........",
|
||||
"...TTT.........TTT.........."
|
||||
"...............................KKKKKKKK.....",
|
||||
"KK............................KKKKKKKKKK....",
|
||||
"KKKK..........................KKKKKKKKKKK...",
|
||||
".KKKK.........................KKKKK.KKKKK...",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKK..TTKKKKK.",
|
||||
".KKKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTTTTTT.",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTTTTT..",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTT.....",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTKKKK..........",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTTKKK..........",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKTTTT.............",
|
||||
".....KKKKKKKKKKKKKKKKKKKKKTTTT..............",
|
||||
"....TTKKKKKKKKKKKKKKKKKKKTTTT...............",
|
||||
".....TTTTT..............TTTT................",
|
||||
"......TTTT..............TTT.................",
|
||||
".....TTT................TTT.................",
|
||||
".....TTT................TTT.................",
|
||||
".....TTT................TTT.................",
|
||||
".....TTTTT..............TTTTT..............."
|
||||
]
|
||||
// Legs gathered underneath, tail level.
|
||||
// Legs gathered under him, tail level.
|
||||
readonly property var walkB: [
|
||||
"....................KKKKK...",
|
||||
"...................KKTKKKK..",
|
||||
"...................KKNTTKKN.",
|
||||
"KKKKKKKKKKKKKKKKKKRKKTTTTTN.",
|
||||
"..KKKKKKKKKKKKKKKKRKKTTTT...",
|
||||
"..KKKKKKKKKKKKKKKKRKKTT.....",
|
||||
"...KKKKKKKKKKKKKKTTT........",
|
||||
"....TKKKKKKKKKKKTTT.........",
|
||||
"....TTKKKKKKKKKTTT..........",
|
||||
"......TT......TT............",
|
||||
"......TT......TT............",
|
||||
".....TTT.....TTT............"
|
||||
"...............................KKKKKKKK.....",
|
||||
"..............................KKKKKKKKKK....",
|
||||
"KKKK..........................KKKKKKKKKKK...",
|
||||
"KKKK..........................KKKKK.KKKKK...",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKK..TTKKKKK.",
|
||||
".KKKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTTTTTT.",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTTTTT..",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTT.....",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTKKKK..........",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTTKKK..........",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKTTTT.............",
|
||||
".....KKKKKKKKKKKKKKKKKKKKKTTTT..............",
|
||||
"....TTKKKKKKKKKKKKKKKKKKKTTTT...............",
|
||||
"........TTTTT........TTTT...................",
|
||||
".........TTTT........TTT....................",
|
||||
"........TTT..........TTT....................",
|
||||
"........TTT..........TTT....................",
|
||||
"........TTT..........TTT....................",
|
||||
"........TTTTT........TTTTT.................."
|
||||
]
|
||||
// Standing still: walkA's planted legs, walkB's tail. Flipping
|
||||
// Standing: walkA's planted legs, walkB's tail. Flipping
|
||||
// between this and walkA is the wag.
|
||||
readonly property var wag: [
|
||||
"....................KKKKK...",
|
||||
"...................KKTKKKK..",
|
||||
"...................KKNTTKKN.",
|
||||
"KKKKKKKKKKKKKKKKKKRKKTTTTTN.",
|
||||
"..KKKKKKKKKKKKKKKKRKKTTTT...",
|
||||
"..KKKKKKKKKKKKKKKKRKKTT.....",
|
||||
"...KKKKKKKKKKKKKKTTT........",
|
||||
"....TKKKKKKKKKKKTTT.........",
|
||||
"....TTKKKKKKKKKTTT..........",
|
||||
"....TT..........TT..........",
|
||||
"....TT..........TT..........",
|
||||
"...TTT.........TTT.........."
|
||||
"...............................KKKKKKKK.....",
|
||||
"..............................KKKKKKKKKK....",
|
||||
"KKKK..........................KKKKKKKKKKK...",
|
||||
"KKKK..........................KKKKK.KKKKK...",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKK..TTKKKKK.",
|
||||
".KKKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTTTTTT.",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTTTTT..",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKRRKKKKTTTTT.....",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTKKKK..........",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTTKKK..........",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKTTTT.............",
|
||||
".....KKKKKKKKKKKKKKKKKKKKKTTTT..............",
|
||||
"....TTKKKKKKKKKKKKKKKKKKKTTTT...............",
|
||||
".....TTTTT..............TTTT................",
|
||||
"......TTTT..............TTT.................",
|
||||
".....TTT................TTT.................",
|
||||
".....TTT................TTT.................",
|
||||
".....TTT................TTT.................",
|
||||
".....TTTTT..............TTTTT..............."
|
||||
]
|
||||
// Head down in the bowl.
|
||||
readonly property var eat: [
|
||||
"............................",
|
||||
"............................",
|
||||
"KK..........................",
|
||||
".KKKKKKKKKKKKKKKKKRKK.......",
|
||||
"..KKKKKKKKKKKKKKKKRKKK......",
|
||||
"..KKKKKKKKKKKKKKKKRKKKK.....",
|
||||
"...KKKKKKKKKKKKKKTTKKKKK....",
|
||||
"....TKKKKKKKKKKKTTKKTKKK....",
|
||||
"....TTKKKKKKKKKTTTKKNTTKN...",
|
||||
"....TT..........TT.KKTTTTN..",
|
||||
"....TT..........TT..KTTN....",
|
||||
"...TTT.........TTT.........."
|
||||
"............................................",
|
||||
"KK..........................................",
|
||||
"KKKK........................................",
|
||||
".KKKK.......................................",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKKKKK............",
|
||||
".KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK...........",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK..........",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK..........",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTKKKK..........",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKTTTKKKK.........",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKTTTTKKKKKKKK.....",
|
||||
".....KKKKKKKKKKKKKKKKKKKKKTTTTKKKKKKKKKK....",
|
||||
"....TTKKKKKKKKKKKKKKKKKKKTTTT.KKKKK.KKKK....",
|
||||
".....TTTTT..............TTTT..KKKKK.TTTKK...",
|
||||
"......TTTT..............TTT...KKKKTTTTTTTTT.",
|
||||
".....TTT................TTT...KKKKKTTTTTTT..",
|
||||
".....TTT................TTT....KKKKTTTT.....",
|
||||
".....TTT................TTT.................",
|
||||
".....TTTTT..............TTTTT..............."
|
||||
]
|
||||
// Flat out in his bed, muzzle on the cushion.
|
||||
readonly property var sleepArt: [
|
||||
"............................................",
|
||||
"............................................",
|
||||
"............................................",
|
||||
"............................................",
|
||||
"............................................",
|
||||
"............................................",
|
||||
"............................................",
|
||||
"............................................",
|
||||
"............................................",
|
||||
"...............................KKKKKKKK.....",
|
||||
"..............................KKKKKKKKKKK...",
|
||||
"KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK.KKKKK...",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKTTTTTKKK..",
|
||||
"..KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKTTTTTTTTT.",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKTTTTTTT...",
|
||||
"...KKKKKKKKKKKKKKKKKKKKKKKKKKTTTT...........",
|
||||
"....KKKKKKKKKKKKKKKKKKKKKKKKTTTT............",
|
||||
".....TTTTTTTTKKKKKKKKKKKKTTTT...............",
|
||||
"......TTTTTT..........TTTTTT................"
|
||||
]
|
||||
readonly property var bowlArt: [
|
||||
"...BBB..",
|
||||
"..BBBBB.",
|
||||
".RBBBBBR",
|
||||
".RRRRRR.",
|
||||
"..RRRR.."
|
||||
".....BBBBBB.....",
|
||||
"...BBBBBBBBBB...",
|
||||
".BBBBBBBBBBBBBB.",
|
||||
"RRRRRRRRRRRRRRRR",
|
||||
".RRRRRRRRRRRRRR.",
|
||||
"..RRRRRRRRRRRR..",
|
||||
"...RRRRRRRRRR...",
|
||||
"....RRRRRRRR....",
|
||||
".....RRRRRR....."
|
||||
]
|
||||
readonly property var bedArt: [
|
||||
"GGGGGGG........................................GGGGGGG",
|
||||
"GGGGGGGGG....................................GGGGGGGGG",
|
||||
"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG",
|
||||
"DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
|
||||
"DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
|
||||
"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG",
|
||||
"..GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG.."
|
||||
]
|
||||
readonly property var ballArt: [
|
||||
"..YYY..",
|
||||
".YLYYY.",
|
||||
"YLYYYYY",
|
||||
"YYYYYYY",
|
||||
"YYYYYYY",
|
||||
".YYYYY.",
|
||||
"..YYY.."
|
||||
]
|
||||
|
||||
property var frame: walkA
|
||||
|
||||
// ── Where he lives: the strip along the bottom, the same
|
||||
// floor line the worm lands on.
|
||||
// ── His patch of floor ──────────────────────────────────
|
||||
readonly property real floorY: archie.height - Theme.frameWidth
|
||||
readonly property real roamL: Theme.barWidth + 12
|
||||
readonly property real roamR: Math.max(roamL,
|
||||
archie.width - Theme.frameWidth - cols * cell - 12)
|
||||
// Bowl parked over toward the right, clear of the launcher.
|
||||
readonly property real bowlX: Math.max(roamL, roamR - 150)
|
||||
// Stand so his muzzle lands in it rather than his shoulder:
|
||||
// head-down, his nose is about 22 cells along from his tail.
|
||||
readonly property real bowlStandX: bowlX - 18 * cell
|
||||
readonly property real bowlX: Math.max(roamL, roamR - 120)
|
||||
readonly property real bedX: Math.max(roamL, Math.min(bowlX - 500, roamL + 300))
|
||||
// Stand so his muzzle lands in the bowl, not his shoulder.
|
||||
readonly property real bowlStandX: bowlX - 32 * cell
|
||||
// Lying down, centred on the cushion.
|
||||
readonly property real bedLieX: bedX + 5 * cell
|
||||
|
||||
property real px: roamL
|
||||
property real px: 0
|
||||
property int facing: 1 // 1 = right, -1 = left
|
||||
property string mode: "walk"
|
||||
property real targetX: 0
|
||||
property bool toBowl: false
|
||||
property string errand: "" // "" | "bowl" | "bed" | "ball"
|
||||
property int hold: 0
|
||||
property int tick: 0
|
||||
// Legs swap on distance covered, not on a tick count, so the
|
||||
// gait stays in step whether he is ambling or running for the
|
||||
// ball. 3 cells is exactly how far the feet move in the art.
|
||||
property real stride: 0
|
||||
property bool stepped: false
|
||||
|
||||
// ── The ball ────────────────────────────────────────────
|
||||
readonly property int ballSize: 7 * cell
|
||||
property real ballX: 0
|
||||
property real ballY: 0
|
||||
property real ballVX: 0
|
||||
property real ballVY: 0
|
||||
property bool ballHeld: false // in your hand
|
||||
property bool ballCarried: false // in his mouth
|
||||
property bool ballThrown: false // he only fetches a fresh throw
|
||||
property real lastBX: 0
|
||||
property real lastBY: 0
|
||||
property int carry: 0
|
||||
|
||||
// Where his mouth is, mirrored with him.
|
||||
readonly property real mouthX: px + (facing > 0 ? 41 : 3) * cell
|
||||
readonly property real mouthY: floorY - 13 * cell
|
||||
|
||||
// Exposed so Bar.qml can punch the ball out of the window's
|
||||
// input mask — without it the whole surface is click-through
|
||||
// here and you could never grab the thing.
|
||||
readonly property real hitX: ballX - 6
|
||||
readonly property real hitY: ballY - 6
|
||||
readonly property real hitW: primary ? ballSize + 12 : 0
|
||||
|
||||
// At rest on the floor after a throw: that is his cue.
|
||||
readonly property bool ballLoose: ballThrown && !ballHeld && !ballCarried
|
||||
&& Math.abs(ballVX) < 0.3 && Math.abs(ballVY) < 0.3
|
||||
&& ballY >= floorY - ballSize - 1
|
||||
|
||||
function ballTick() {
|
||||
if (ballCarried) {
|
||||
ballX = mouthX - ballSize / 2;
|
||||
ballY = mouthY - ballSize / 2;
|
||||
return;
|
||||
}
|
||||
if (ballHeld) {
|
||||
// Velocity comes from how fast you are dragging it, so
|
||||
// letting go mid-swing throws it.
|
||||
ballVX = Math.max(-45, Math.min(45, ballX - lastBX));
|
||||
ballVY = Math.max(-45, Math.min(45, ballY - lastBY));
|
||||
return;
|
||||
}
|
||||
ballVY += 0.55;
|
||||
ballX += ballVX;
|
||||
ballY += ballVY;
|
||||
let ground = floorY - ballSize;
|
||||
if (ballY >= ground) {
|
||||
ballY = ground;
|
||||
if (Math.abs(ballVY) > 1.2) ballVY = -ballVY * 0.55;
|
||||
else ballVY = 0;
|
||||
ballVX *= 0.92; // rolling friction
|
||||
if (Math.abs(ballVX) < 0.08) ballVX = 0;
|
||||
}
|
||||
if (ballY < 0) { ballY = 0; ballVY = Math.abs(ballVY) * 0.4; }
|
||||
let bl = Theme.barWidth;
|
||||
let br = archie.width - Theme.frameWidth - ballSize;
|
||||
if (ballX < bl) { ballX = bl; ballVX = -ballVX * 0.6; }
|
||||
if (ballX > br) { ballX = br; ballVX = -ballVX * 0.6; }
|
||||
}
|
||||
|
||||
// ── What he does next ───────────────────────────────────
|
||||
function wander() {
|
||||
mode = "walk";
|
||||
// Not if he is already standing at it — otherwise he can
|
||||
// roll "go to the bowl" while stood in it and eat twice
|
||||
// over without moving.
|
||||
// Near enough to be worth it, but not already stood in it
|
||||
// — otherwise he either marches half a minute across the
|
||||
// screen for a snack, or rolls "go to the bowl" while his
|
||||
// head is in it and eats twice over without moving.
|
||||
errand = "";
|
||||
let dBowl = Math.abs(px - bowlStandX);
|
||||
toBowl = Math.random() < 0.3 && dBowl > 80 && dBowl < 900;
|
||||
// A short trip from wherever he is, not a random point on
|
||||
// the whole screen: picking uniformly meant single walks
|
||||
// most of a minute long across a wide monitor, which reads
|
||||
// as a patrol. Short hops read as pottering about.
|
||||
let dBed = Math.abs(px - bedLieX);
|
||||
// Near enough to be worth it, and not already stood there
|
||||
// — otherwise he marches half a minute for a snack, or
|
||||
// rolls "go to the bowl" with his head already in it. No
|
||||
// errands while he has the ball; he is busy.
|
||||
if (!ballCarried && Math.random() < 0.3 && dBowl > 80 && dBowl < 900) errand = "bowl";
|
||||
else if (!ballCarried && Math.random() < 0.25 && dBed > 80 && dBed < 900) errand = "bed";
|
||||
|
||||
if (errand === "bowl") { targetX = bowlStandX; return; }
|
||||
if (errand === "bed") { targetX = bedLieX; return; }
|
||||
|
||||
let dir = Math.random() < 0.5 ? -1 : 1;
|
||||
// Turn away from an end he is already near. Clamping the
|
||||
// target instead just parks him against the wall, picking
|
||||
// the same spot over and over.
|
||||
// Turn away from an end he is already near; clamping the
|
||||
// target instead just parks him against the wall.
|
||||
if (dir < 0 && px - roamL < 220) dir = 1;
|
||||
if (dir > 0 && roamR - px < 220) dir = -1;
|
||||
targetX = toBowl ? bowlStandX
|
||||
: Math.max(roamL, Math.min(roamR,
|
||||
px + dir * (150 + Math.random() * 550)));
|
||||
targetX = Math.max(roamL, Math.min(roamR,
|
||||
px + dir * (150 + Math.random() * 550)));
|
||||
}
|
||||
|
||||
function chase() {
|
||||
mode = "walk";
|
||||
errand = "ball";
|
||||
// Line his mouth up with it, approaching from whichever
|
||||
// side he is already on.
|
||||
let bc = ballX + ballSize / 2;
|
||||
targetX = (px + cols * cell / 2 < bc) ? bc - 41 * cell : bc - 3 * cell;
|
||||
targetX = Math.max(roamL - 60, Math.min(roamR + 60, targetX));
|
||||
}
|
||||
|
||||
function arrive() {
|
||||
if (toBowl) {
|
||||
if (errand === "ball") {
|
||||
ballCarried = true;
|
||||
ballThrown = false;
|
||||
carry = 400 + Math.random() * 500; // 13-30s of pride
|
||||
mode = "idle";
|
||||
hold = 40;
|
||||
} else if (errand === "bowl") {
|
||||
mode = "eat";
|
||||
hold = 100 + Math.random() * 80;
|
||||
facing = 1; // the bowl is off his nose
|
||||
facing = 1;
|
||||
} else if (errand === "bed") {
|
||||
mode = "sleep";
|
||||
hold = 600 + Math.random() * 900;
|
||||
facing = 1;
|
||||
} else {
|
||||
mode = "idle";
|
||||
hold = 45 + Math.random() * 130;
|
||||
}
|
||||
}
|
||||
|
||||
// Placed on the first real width, not on completion: anchors
|
||||
// have not resolved yet at that point, so roamR collapses to
|
||||
// roamL and he spawns pinned to the left edge.
|
||||
// Placed on the first real width: anchors have not resolved at
|
||||
// Component.onCompleted, so roamR collapses to roamL and he
|
||||
// spawns pinned to the left edge.
|
||||
property bool placed: false
|
||||
onWidthChanged: {
|
||||
if (placed || width <= 0) return;
|
||||
placed = true;
|
||||
px = roamL + Math.random() * (roamR - roamL);
|
||||
ballX = Math.min(roamR, px + 300);
|
||||
ballY = floorY - ballSize;
|
||||
wander();
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 33; running: archie.primary; repeat: true
|
||||
onTriggered: {
|
||||
archie.tick++;
|
||||
archie.ballTick();
|
||||
archie.lastBX = archie.ballX;
|
||||
archie.lastBY = archie.ballY;
|
||||
|
||||
// A thrown ball beats whatever else he was doing.
|
||||
if (archie.ballLoose && archie.errand !== "ball") archie.chase();
|
||||
|
||||
if (archie.ballCarried && --archie.carry <= 0) {
|
||||
archie.ballCarried = false;
|
||||
archie.ballVX = 0;
|
||||
archie.ballVY = 0;
|
||||
}
|
||||
|
||||
if (archie.mode === "walk") {
|
||||
// Arrival first: checking after the step makes him
|
||||
// take a stride backwards when he is already there.
|
||||
if (Math.abs(archie.targetX - archie.px) < 2) {
|
||||
// stride backwards when he is already there.
|
||||
if (Math.abs(archie.targetX - archie.px) < 2.5) {
|
||||
archie.arrive();
|
||||
} else {
|
||||
let dir = archie.targetX > archie.px ? 1 : -1;
|
||||
let sp = archie.errand === "ball" ? 3.0 : 1.5;
|
||||
archie.facing = dir;
|
||||
archie.px += dir * 1.6;
|
||||
// Swap legs every 5 ticks: at 1.6px a tick
|
||||
// that is exactly the 8px his feet move in the
|
||||
// art (2 cells), so he does not moonwalk.
|
||||
archie.frame = archie.tick % 10 < 5 ? archie.walkA : archie.walkB;
|
||||
archie.px += dir * sp;
|
||||
archie.stride += sp;
|
||||
if (archie.stride >= 3 * archie.cell) {
|
||||
archie.stride = 0;
|
||||
archie.stepped = !archie.stepped;
|
||||
}
|
||||
archie.frame = archie.stepped ? archie.walkB : archie.walkA;
|
||||
}
|
||||
} else {
|
||||
archie.frame = archie.mode === "eat" ? archie.eat
|
||||
: (archie.tick % 26 < 13 ? archie.walkA : archie.wag);
|
||||
: archie.mode === "sleep" ? archie.sleepArt
|
||||
: (archie.hold % 26 < 13 ? archie.walkA : archie.wag);
|
||||
if (--archie.hold <= 0) archie.wander();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Sprite. One Rectangle per pixel, colour looked up per
|
||||
// frame; switching frames just rebinds them.
|
||||
// ── Sprite: one Rectangle per pixel, colour looked up per
|
||||
// frame, so switching frames just rebinds them.
|
||||
component Sprite: Item {
|
||||
id: sp
|
||||
property var art: []
|
||||
|
|
@ -1349,32 +1529,65 @@ in
|
|||
}
|
||||
}
|
||||
|
||||
// Bed first, so he lies in it rather than behind it.
|
||||
Sprite {
|
||||
art: archie.bedArt; w: 54; h: 7
|
||||
x: Math.round(archie.bedX / archie.cell) * archie.cell
|
||||
y: archie.floorY - height
|
||||
}
|
||||
|
||||
Sprite {
|
||||
art: archie.frame
|
||||
w: archie.cols
|
||||
h: archie.rows
|
||||
// Snap to the pixel grid, same as the worm, or the art
|
||||
// shimmers as he walks.
|
||||
// Snap x to the pixel grid or the art shimmers as he
|
||||
// walks. y is exact: he never moves vertically, and
|
||||
// rounding sank his paws through the floor.
|
||||
x: Math.round(archie.px / archie.cell) * archie.cell
|
||||
// Exact, not grid-snapped: he never moves vertically, so
|
||||
// there is nothing to shimmer, and rounding sank his paws
|
||||
// a couple of pixels through the floor.
|
||||
y: archie.floorY - height
|
||||
// Mirror him when he heads back the other way.
|
||||
transform: Scale { origin.x: archie.cols * archie.cell / 2; xScale: archie.facing }
|
||||
}
|
||||
|
||||
// Drawn after him, so at the bowl his nose goes behind it.
|
||||
// Bowl after him, so at dinner his nose goes behind it.
|
||||
Sprite {
|
||||
art: archie.bowlArt
|
||||
w: 8
|
||||
h: 5
|
||||
art: archie.bowlArt; w: 16; h: 9
|
||||
x: Math.round(archie.bowlX / archie.cell) * archie.cell
|
||||
// Exact, not grid-snapped: he never moves vertically, so
|
||||
// there is nothing to shimmer, and rounding sank his paws
|
||||
// a couple of pixels through the floor.
|
||||
y: archie.floorY - height
|
||||
}
|
||||
|
||||
Sprite {
|
||||
art: archie.ballArt; w: 7; h: 7
|
||||
x: Math.round(archie.ballX / archie.cell) * archie.cell
|
||||
y: Math.round(archie.ballY / archie.cell) * archie.cell
|
||||
}
|
||||
|
||||
// Grab handle for the ball, a little larger than the ball so
|
||||
// it is catchable while it rolls.
|
||||
MouseArea {
|
||||
x: archie.hitX; y: archie.hitY
|
||||
width: archie.hitW; height: archie.hitW
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
property real grabDX: 0
|
||||
property real grabDY: 0
|
||||
onPressed: (m) => {
|
||||
let p = mapToItem(archie, m.x, m.y);
|
||||
grabDX = p.x - archie.ballX;
|
||||
grabDY = p.y - archie.ballY;
|
||||
archie.ballCarried = false; // you may take it off him
|
||||
archie.ballHeld = true;
|
||||
}
|
||||
onPositionChanged: (m) => {
|
||||
if (!archie.ballHeld) return;
|
||||
let p = mapToItem(archie, m.x, m.y);
|
||||
archie.ballX = p.x - grabDX;
|
||||
archie.ballY = p.y - grabDY;
|
||||
}
|
||||
onReleased: {
|
||||
archie.ballHeld = false;
|
||||
archie.ballThrown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
|
@ -1694,6 +1907,14 @@ in
|
|||
width: launcherPanel.visible ? launcherPanel.width : 0
|
||||
height: launcherPanel.visible ? launcherPanel.height : 0
|
||||
}
|
||||
// Archie's ball. The rest of this surface is click-through,
|
||||
// so without a hole here you could never pick it up.
|
||||
Region {
|
||||
x: archieDog.hitX
|
||||
y: archieDog.hitY
|
||||
width: archieDog.hitW
|
||||
height: archieDog.hitW
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
@ -7035,7 +7256,7 @@ in
|
|||
}
|
||||
|
||||
// Archie. One dog, primary screen only.
|
||||
Archie { primary: bar.screen === Quickshell.screens[0] }
|
||||
Archie { id: archieDog; primary: bar.screen === Quickshell.screens[0] }
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue