From 5298b7801b75414f38ccfa596c427d0302479cc3 Mon Sep 17 00:00:00 2001 From: Idrees Hassan Date: Thu, 23 Oct 2025 21:25:43 -0400 Subject: [PATCH] Treat ground as yet another element --- birb.js | 117 +++++++++++++++++++++++----------------------- dist/birb.js | 117 +++++++++++++++++++++++----------------------- dist/birb.user.js | 117 +++++++++++++++++++++++----------------------- 3 files changed, 177 insertions(+), 174 deletions(-) diff --git a/birb.js b/birb.js index bb028d0..0b0458b 100644 --- a/birb.js +++ b/birb.js @@ -685,6 +685,7 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI let targetY = 0; /** @type {HTMLElement|null} */ let focusedElement = null; + let focusedBounds = { left: 0, right: 0, top: 0 }; let lastActionTimestamp = Date.now(); /** @type {number[]} */ let petStack = []; @@ -1026,12 +1027,20 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI // Won't be restored on fullscreen exit } - if (currentState === States.IDLE) { - if (Math.random() < 1 / (60 * 3) && currentAnimation !== Animations.HEART && !isMenuOpen()) { + if (currentState === States.IDLE && !frozen && !isMenuOpen()) { + if (Math.random() < 1 / (60 * 3) && currentAnimation !== Animations.HEART) { hop(); - } else if (focusedElement !== null && Math.random() < 1 / (60 * 20) && Date.now() - lastActionTimestamp > AFK_TIME && !isMenuOpen()) { - focusOnElement(); - lastActionTimestamp = Date.now(); + } else if (Date.now() - lastActionTimestamp > AFK_TIME) { + // Idle for a while, do something + if (focusedElement === null) { + // Fly to an element + focusOnElement(); + lastActionTimestamp = Date.now(); + } else if (Math.random() < 1 / (60 * 20)) { + // Fly to another element if idle for a longer while + focusOnElement(); + lastActionTimestamp = Date.now(); + } } } else if (currentState === States.HOP) { if (updateParabolicPath(HOP_SPEED)) { @@ -1055,14 +1064,14 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI return; } + updateFocusedElementBounds(); + // Update the bird's position if (currentState === States.IDLE) { - if (focusedElement !== null) { - birdY = getFocusedElementY() - 0.5; - if (!isWithinHorizontalBounds()) { - focusOnGround(); - } + if (focusedElement && !isWithinHorizontalBounds()) { + focusOnGround(); } + birdY = getFocusedY(); } else if (currentState === States.FLYING) { // Fly to target location (even if in the air) if (updateParabolicPath(FLY_SPEED)) { @@ -1070,21 +1079,13 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI } } - if (focusedElement === null) { - if (currentState === States.IDLE && Date.now() - lastActionTimestamp > AFK_TIME && !isMenuOpen()) { - // Fly to an element if the user is AFK - focusOnElement(); - lastActionTimestamp = Date.now(); - } - } else if (focusedElement !== null) { - const oldTargetY = targetY; - targetY = getFocusedElementY(); - // Adjust startY to account for scrolling of the focused element - startY += targetY - oldTargetY; - if (targetY < 0 || targetY > window.innerHeight) { - // Fly to ground if the focused element moves out of bounds - focusOnGround(); - } + const oldTargetY = targetY; + targetY = getFocusedY(); + // Adjust startY to account for scrolling + startY += targetY - oldTargetY; + if (targetY < 0 || targetY > window.innerHeight) { + // Fly to ground if the focused element moves out of bounds + focusOnGround(); } ctx.clearRect(0, 0, canvas.width, canvas.height); @@ -1660,34 +1661,29 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI } function getFocusedElementRandomX() { - if (focusedElement === null) { - return Math.random() * window.innerWidth; - } - const rect = focusedElement.getBoundingClientRect(); - return Math.random() * (rect.right - rect.left) + rect.left; + return Math.random() * (focusedBounds.right - focusedBounds.left) + focusedBounds.left; } function isWithinHorizontalBounds() { - if (focusedElement === null) { - return true; - } - const rect = focusedElement.getBoundingClientRect(); - return birdX >= rect.left && birdX <= rect.right; + return birdX >= focusedBounds.left && birdX <= focusedBounds.right; } - function getFocusedElementY() { - if (focusedElement === null) { - return 0; - } - const rect = focusedElement.getBoundingClientRect(); - return window.innerHeight - rect.top; + // function getFocusedElementY() { + // if (focusedElement === null) { + // return 0; + // } + // const rect = focusedElement.getBoundingClientRect(); + // return window.innerHeight - rect.top; + // } + + function getFocusedY() { + return window.innerHeight - focusedBounds.top; } function focusOnGround() { - if (focusedElement === null) { - return; - } + console.log("Focusing on ground"); focusedElement = null; + focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight }; flyTo(Math.random() * window.innerWidth, 0); } @@ -1709,7 +1705,23 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI } const randomElement = largeElements[Math.floor(Math.random() * largeElements.length)]; focusedElement = randomElement; - flyTo(getFocusedElementRandomX(), getFocusedElementY()); + log("Focusing on element: ", focusedElement); + updateFocusedElementBounds(); + flyTo(getFocusedElementRandomX(), getFocusedY()); + } + + function updateFocusedElementBounds() { + if (focusedElement === null) { + // Update ground location to bottom of window + focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight }; + return; + } + const rect = focusedElement.getBoundingClientRect(); + focusedBounds = { + left: rect.left, + right: rect.right, + top: rect.top + }; } function getCanvasWidth() { @@ -1725,25 +1737,14 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI return; } if (currentState === States.IDLE) { - // Determine bounds for hopping - let minX = 0; - let maxX = window.innerWidth; - let y = 0; - if (focusedElement !== null) { - // Hop on the element - const rect = focusedElement.getBoundingClientRect(); - minX = rect.left; - maxX = rect.right; - y = window.innerHeight - rect.top; - } setState(States.HOP); setAnimation(Animations.FLYING); - if ((Math.random() < 0.5 && birdX - HOP_DISTANCE > minX) || birdX + HOP_DISTANCE > maxX) { + if ((Math.random() < 0.5 && birdX - HOP_DISTANCE > focusedBounds.left) || birdX + HOP_DISTANCE > focusedBounds.right) { targetX = birdX - HOP_DISTANCE; } else { targetX = birdX + HOP_DISTANCE; } - targetY = y; + targetY = getFocusedY(); } } diff --git a/dist/birb.js b/dist/birb.js index 98181e6..aa3204d 100644 --- a/dist/birb.js +++ b/dist/birb.js @@ -1024,6 +1024,7 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI let targetY = 0; /** @type {HTMLElement|null} */ let focusedElement = null; + let focusedBounds = { left: 0, right: 0, top: 0 }; let lastActionTimestamp = Date.now(); /** @type {number[]} */ let petStack = []; @@ -1365,12 +1366,20 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI // Won't be restored on fullscreen exit } - if (currentState === States.IDLE) { - if (Math.random() < 1 / (60 * 3) && currentAnimation !== Animations.HEART && !isMenuOpen()) { + if (currentState === States.IDLE && !frozen && !isMenuOpen()) { + if (Math.random() < 1 / (60 * 3) && currentAnimation !== Animations.HEART) { hop(); - } else if (focusedElement !== null && Math.random() < 1 / (60 * 20) && Date.now() - lastActionTimestamp > AFK_TIME && !isMenuOpen()) { - focusOnElement(); - lastActionTimestamp = Date.now(); + } else if (Date.now() - lastActionTimestamp > AFK_TIME) { + // Idle for a while, do something + if (focusedElement === null) { + // Fly to an element + focusOnElement(); + lastActionTimestamp = Date.now(); + } else if (Math.random() < 1 / (60 * 20)) { + // Fly to another element if idle for a longer while + focusOnElement(); + lastActionTimestamp = Date.now(); + } } } else if (currentState === States.HOP) { if (updateParabolicPath(HOP_SPEED)) { @@ -1394,14 +1403,14 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI return; } + updateFocusedElementBounds(); + // Update the bird's position if (currentState === States.IDLE) { - if (focusedElement !== null) { - birdY = getFocusedElementY() - 0.5; - if (!isWithinHorizontalBounds()) { - focusOnGround(); - } + if (focusedElement && !isWithinHorizontalBounds()) { + focusOnGround(); } + birdY = getFocusedY(); } else if (currentState === States.FLYING) { // Fly to target location (even if in the air) if (updateParabolicPath(FLY_SPEED)) { @@ -1409,21 +1418,13 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI } } - if (focusedElement === null) { - if (currentState === States.IDLE && Date.now() - lastActionTimestamp > AFK_TIME && !isMenuOpen()) { - // Fly to an element if the user is AFK - focusOnElement(); - lastActionTimestamp = Date.now(); - } - } else if (focusedElement !== null) { - const oldTargetY = targetY; - targetY = getFocusedElementY(); - // Adjust startY to account for scrolling of the focused element - startY += targetY - oldTargetY; - if (targetY < 0 || targetY > window.innerHeight) { - // Fly to ground if the focused element moves out of bounds - focusOnGround(); - } + const oldTargetY = targetY; + targetY = getFocusedY(); + // Adjust startY to account for scrolling + startY += targetY - oldTargetY; + if (targetY < 0 || targetY > window.innerHeight) { + // Fly to ground if the focused element moves out of bounds + focusOnGround(); } ctx.clearRect(0, 0, canvas.width, canvas.height); @@ -1999,34 +2000,29 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI } function getFocusedElementRandomX() { - if (focusedElement === null) { - return Math.random() * window.innerWidth; - } - const rect = focusedElement.getBoundingClientRect(); - return Math.random() * (rect.right - rect.left) + rect.left; + return Math.random() * (focusedBounds.right - focusedBounds.left) + focusedBounds.left; } function isWithinHorizontalBounds() { - if (focusedElement === null) { - return true; - } - const rect = focusedElement.getBoundingClientRect(); - return birdX >= rect.left && birdX <= rect.right; + return birdX >= focusedBounds.left && birdX <= focusedBounds.right; } - function getFocusedElementY() { - if (focusedElement === null) { - return 0; - } - const rect = focusedElement.getBoundingClientRect(); - return window.innerHeight - rect.top; + // function getFocusedElementY() { + // if (focusedElement === null) { + // return 0; + // } + // const rect = focusedElement.getBoundingClientRect(); + // return window.innerHeight - rect.top; + // } + + function getFocusedY() { + return window.innerHeight - focusedBounds.top; } function focusOnGround() { - if (focusedElement === null) { - return; - } + console.log("Focusing on ground"); focusedElement = null; + focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight }; flyTo(Math.random() * window.innerWidth, 0); } @@ -2048,7 +2044,23 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI } const randomElement = largeElements[Math.floor(Math.random() * largeElements.length)]; focusedElement = randomElement; - flyTo(getFocusedElementRandomX(), getFocusedElementY()); + log("Focusing on element: ", focusedElement); + updateFocusedElementBounds(); + flyTo(getFocusedElementRandomX(), getFocusedY()); + } + + function updateFocusedElementBounds() { + if (focusedElement === null) { + // Update ground location to bottom of window + focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight }; + return; + } + const rect = focusedElement.getBoundingClientRect(); + focusedBounds = { + left: rect.left, + right: rect.right, + top: rect.top + }; } function getCanvasWidth() { @@ -2064,25 +2076,14 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI return; } if (currentState === States.IDLE) { - // Determine bounds for hopping - let minX = 0; - let maxX = window.innerWidth; - let y = 0; - if (focusedElement !== null) { - // Hop on the element - const rect = focusedElement.getBoundingClientRect(); - minX = rect.left; - maxX = rect.right; - y = window.innerHeight - rect.top; - } setState(States.HOP); setAnimation(Animations.FLYING); - if ((Math.random() < 0.5 && birdX - HOP_DISTANCE > minX) || birdX + HOP_DISTANCE > maxX) { + if ((Math.random() < 0.5 && birdX - HOP_DISTANCE > focusedBounds.left) || birdX + HOP_DISTANCE > focusedBounds.right) { targetX = birdX - HOP_DISTANCE; } else { targetX = birdX + HOP_DISTANCE; } - targetY = y; + targetY = getFocusedY(); } } diff --git a/dist/birb.user.js b/dist/birb.user.js index 9d11b2c..bc1c881 100644 --- a/dist/birb.user.js +++ b/dist/birb.user.js @@ -1038,6 +1038,7 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI let targetY = 0; /** @type {HTMLElement|null} */ let focusedElement = null; + let focusedBounds = { left: 0, right: 0, top: 0 }; let lastActionTimestamp = Date.now(); /** @type {number[]} */ let petStack = []; @@ -1379,12 +1380,20 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI // Won't be restored on fullscreen exit } - if (currentState === States.IDLE) { - if (Math.random() < 1 / (60 * 3) && currentAnimation !== Animations.HEART && !isMenuOpen()) { + if (currentState === States.IDLE && !frozen && !isMenuOpen()) { + if (Math.random() < 1 / (60 * 3) && currentAnimation !== Animations.HEART) { hop(); - } else if (focusedElement !== null && Math.random() < 1 / (60 * 20) && Date.now() - lastActionTimestamp > AFK_TIME && !isMenuOpen()) { - focusOnElement(); - lastActionTimestamp = Date.now(); + } else if (Date.now() - lastActionTimestamp > AFK_TIME) { + // Idle for a while, do something + if (focusedElement === null) { + // Fly to an element + focusOnElement(); + lastActionTimestamp = Date.now(); + } else if (Math.random() < 1 / (60 * 20)) { + // Fly to another element if idle for a longer while + focusOnElement(); + lastActionTimestamp = Date.now(); + } } } else if (currentState === States.HOP) { if (updateParabolicPath(HOP_SPEED)) { @@ -1408,14 +1417,14 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI return; } + updateFocusedElementBounds(); + // Update the bird's position if (currentState === States.IDLE) { - if (focusedElement !== null) { - birdY = getFocusedElementY() - 0.5; - if (!isWithinHorizontalBounds()) { - focusOnGround(); - } + if (focusedElement && !isWithinHorizontalBounds()) { + focusOnGround(); } + birdY = getFocusedY(); } else if (currentState === States.FLYING) { // Fly to target location (even if in the air) if (updateParabolicPath(FLY_SPEED)) { @@ -1423,21 +1432,13 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI } } - if (focusedElement === null) { - if (currentState === States.IDLE && Date.now() - lastActionTimestamp > AFK_TIME && !isMenuOpen()) { - // Fly to an element if the user is AFK - focusOnElement(); - lastActionTimestamp = Date.now(); - } - } else if (focusedElement !== null) { - const oldTargetY = targetY; - targetY = getFocusedElementY(); - // Adjust startY to account for scrolling of the focused element - startY += targetY - oldTargetY; - if (targetY < 0 || targetY > window.innerHeight) { - // Fly to ground if the focused element moves out of bounds - focusOnGround(); - } + const oldTargetY = targetY; + targetY = getFocusedY(); + // Adjust startY to account for scrolling + startY += targetY - oldTargetY; + if (targetY < 0 || targetY > window.innerHeight) { + // Fly to ground if the focused element moves out of bounds + focusOnGround(); } ctx.clearRect(0, 0, canvas.width, canvas.height); @@ -2013,34 +2014,29 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI } function getFocusedElementRandomX() { - if (focusedElement === null) { - return Math.random() * window.innerWidth; - } - const rect = focusedElement.getBoundingClientRect(); - return Math.random() * (rect.right - rect.left) + rect.left; + return Math.random() * (focusedBounds.right - focusedBounds.left) + focusedBounds.left; } function isWithinHorizontalBounds() { - if (focusedElement === null) { - return true; - } - const rect = focusedElement.getBoundingClientRect(); - return birdX >= rect.left && birdX <= rect.right; + return birdX >= focusedBounds.left && birdX <= focusedBounds.right; } - function getFocusedElementY() { - if (focusedElement === null) { - return 0; - } - const rect = focusedElement.getBoundingClientRect(); - return window.innerHeight - rect.top; + // function getFocusedElementY() { + // if (focusedElement === null) { + // return 0; + // } + // const rect = focusedElement.getBoundingClientRect(); + // return window.innerHeight - rect.top; + // } + + function getFocusedY() { + return window.innerHeight - focusedBounds.top; } function focusOnGround() { - if (focusedElement === null) { - return; - } + console.log("Focusing on ground"); focusedElement = null; + focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight }; flyTo(Math.random() * window.innerWidth, 0); } @@ -2062,7 +2058,23 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI } const randomElement = largeElements[Math.floor(Math.random() * largeElements.length)]; focusedElement = randomElement; - flyTo(getFocusedElementRandomX(), getFocusedElementY()); + log("Focusing on element: ", focusedElement); + updateFocusedElementBounds(); + flyTo(getFocusedElementRandomX(), getFocusedY()); + } + + function updateFocusedElementBounds() { + if (focusedElement === null) { + // Update ground location to bottom of window + focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight }; + return; + } + const rect = focusedElement.getBoundingClientRect(); + focusedBounds = { + left: rect.left, + right: rect.right, + top: rect.top + }; } function getCanvasWidth() { @@ -2078,25 +2090,14 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI return; } if (currentState === States.IDLE) { - // Determine bounds for hopping - let minX = 0; - let maxX = window.innerWidth; - let y = 0; - if (focusedElement !== null) { - // Hop on the element - const rect = focusedElement.getBoundingClientRect(); - minX = rect.left; - maxX = rect.right; - y = window.innerHeight - rect.top; - } setState(States.HOP); setAnimation(Animations.FLYING); - if ((Math.random() < 0.5 && birdX - HOP_DISTANCE > minX) || birdX + HOP_DISTANCE > maxX) { + if ((Math.random() < 0.5 && birdX - HOP_DISTANCE > focusedBounds.left) || birdX + HOP_DISTANCE > focusedBounds.right) { targetX = birdX - HOP_DISTANCE; } else { targetX = birdX + HOP_DISTANCE; } - targetY = y; + targetY = getFocusedY(); } }