Tip of the day
Equipping a gear set while at a bank will automatically withdraw all the items from the bank.

MediaWiki:Gadget-AnimatedCursorFollower.js

From Walkscape Walkthrough
Revision as of 01:03, 23 May 2026 by Bonez565 (talk | contribs)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
 * Animated Cursor Follower
 * Clones the first WalkScape sprite on the page and makes it follow the cursor.
 */
(function () {
	'use strict';
	console.log('AnimatedCursorFollower gadget loaded');
	console.log('Sprites found:', document.querySelectorAll('span.ws-sprite').length);
	const CONFIG = {
		scale: 1.5,
		speed: 0.5,
		offsetX: 30,
		offsetY: 30
	};

	const state = {
		targetX: window.innerWidth / 2,
		targetY: window.innerHeight / 2,
		currentX: window.innerWidth / 2,
		currentY: window.innerHeight / 2,
		facingRight: true,
		reqId: null,
		running: false
	};

	let pet = null;
	let centerOffset = 36;

	function render() {
		if (!pet || !state.running) return;

		state.currentX += (state.targetX - state.currentX) * CONFIG.speed;
		state.currentY += (state.targetY - state.currentY) * CONFIG.speed;

		if (state.targetX > state.currentX + 1) {
			state.facingRight = true;
		} else if (state.targetX < state.currentX - 1) {
			state.facingRight = false;
		}

		const scaleX = state.facingRight ? 1 : -1;

		pet.style.transform = `translate3d(${state.currentX - centerOffset}px, ${state.currentY - centerOffset}px, 0) scaleX(${scaleX})`;

		state.reqId = requestAnimationFrame(render);
	}

	function start() {
		if (state.running) return;
		state.running = true;
		state.reqId = requestAnimationFrame(render);
	}

	function stop() {
		state.running = false;

		if (state.reqId) {
			cancelAnimationFrame(state.reqId);
			state.reqId = null;
		}
	}

	function mountPet(sourceNode) {
		if (pet) return;

		pet = sourceNode.cloneNode(true);

		const styles = window.getComputedStyle(sourceNode);
		const frameSize = parseInt(styles.getPropertyValue('--frame'), 10) || 48;

		centerOffset = (frameSize * CONFIG.scale) / 2;

		pet.classList.add('animated-cursor-follower');
		pet.style.setProperty('--scale', CONFIG.scale);

		Object.assign(pet.style, {
			position: 'fixed',
			top: '0',
			left: '0',
			pointerEvents: 'none',
			zIndex: '99999',
			margin: '0',
			willChange: 'transform',
			transition: 'none'
		});

		document.body.appendChild(pet);

		document.addEventListener('mousemove', function (e) {
			state.targetX = e.clientX + CONFIG.offsetX;
			state.targetY = e.clientY + CONFIG.offsetY;
		}, { passive: true });

		document.addEventListener('mouseleave', stop);
		document.addEventListener('mouseenter', start);

		start();
	}

	function init() {
		const sprite = document.querySelector('span.ws-sprite');

		if (!sprite) return;

		mountPet(sprite);
	}

	$(init);
}());