add logo and cursor duck #1

Merged
ben merged 1 commits from cursor-thing into main 2024-09-10 08:19:38 -07:00
4 changed files with 200 additions and 1 deletions
Showing only changes of commit 45ee8f1134 - Show all commits

183
www/cursor-thing.js Normal file
View File

@ -0,0 +1,183 @@
const thing = document.getElementById('cursor-thing');
let updateTimerId;
let lastUpdate = 0;
// targeting
let mouseX = 0;
let mouseY = 0;
let scrollX = document.scrollingElement.scrollLeft;
let scrollY = document.scrollingElement.scrollTop;
const getTargetX = () => mouseX + scrollX;
const getTargetY = () => mouseY + scrollY;
// physics
let xPos = 0;
let yPos = 0;
let angle = 0;
let velocity = 0;
const maxVel = 600;
let accel = 0;
const maxAccel = 1500;
const accelCurve = (x) => maxAccel*(x/200)**3; // maxAccel when >150px distance
// more physics
const slideFric = .9; // coefficient of friction
const turnSpeedCoeff = .08; // coefficient of turning
// other stuff
let brake = false;
const brakeDist = 70;
// animation
let alt = false;
let lastAlt = 0;
function update() {
// timing
thisUpdate = Date.now();
deltaT = (thisUpdate - lastUpdate)/1000.0;
lastUpdate = thisUpdate;
// update trajectory
targetX = getTargetX();
targetY = getTargetY();
xDelta = targetX - xPos;
yDelta = targetY - yPos;
// find target angle
let targetAngle = Math.atan(yDelta/xDelta);
if (isNaN(targetAngle)) targetAngle = 0;
if (xDelta < 0) targetAngle = Math.PI*.5 - (targetAngle*-1);
else targetAngle = -((targetAngle*-1) - Math.PI*1.5);
// find shortest rotation delta
let aAngle = angle;
let aTargetAngle = targetAngle;
if (aTargetAngle > aAngle && aTargetAngle - aAngle > Math.PI) {
aAngle += Math.PI;
aTargetAngle -= Math.PI;
} else if (aAngle > aTargetAngle && aAngle - aTargetAngle > Math.PI) {
aAngle -= Math.PI;
aTargetAngle += Math.PI;
}
rDelta = aTargetAngle - aAngle;
// console.log(`myAngle: ${angle * (180 / Math.PI)} target angle: ${targetAngle * (180 / Math.PI)}`)
// console.log(`deelta: ${(rDelta) * (180 / Math.PI)} `);
// apply delta
angle += rDelta * turnSpeedCoeff;
// counter overflow
if (angle > 2*Math.PI) angle -= 2*Math.PI;
else if (angle < 0) angle += 2*Math.PI;
// stop when close
let dist = Math.sqrt((xPos-targetX)**2 + (yPos-targetY)**2);
brake = dist < brakeDist;
if (!brake) {
accel = accelCurve(dist);
if (accel > maxAccel) accel = maxAccel;
else if (accel < -maxAccel) accel = -maxAccel;
} else accel = 0;
// physics
velocity += accel * deltaT;
if (brake) {
// basic friction
velocity *= slideFric;
}
// vel limit
if (velocity > maxVel) velocity = maxVel;
else if (velocity < -maxVel) velocity = -maxVel
// translate vector to 2D
let hAngle = angle % Math.PI;
let right = angle > Math.PI;
let xVel = Math.sin(hAngle) * velocity;
let yVel = Math.cos(hAngle) * velocity;
if (right) {
yVel *= -1;
} else {
xVel *= -1;
}
// apply velocity
xPos += xVel * deltaT;
yPos += yVel * deltaT;
// console.log(`accel: ${accel}`);
// console.log(`velocity: ${velocity} (${xVel}, ${yVel})`)
let visualAngle = angle + (rDelta/2);
visualAngle = targetAngle;
thing.style.left = xPos + 'px';
thing.style.top = yPos + 'px';
// thing.style.rotate = visualAngle + 'rad';
// if (brake) {
// thing.style['background-color'] = '#00ff00';
// } else {
// thing.style['background-color'] = '#ff0000';
// }
let fuck = visualAngle + Math.PI/4;
if (fuck < Math.PI/2 || fuck > Math.PI * 2) {
// front-facing
thing.style['background-position-x'] = '100px';
} else if (fuck < Math.PI) {
// left-facing
thing.style['background-position-x'] = '0px';
} else if (fuck < Math.PI*3/2) {
// right-facing
thing.style['background-position-x'] = '150px';
} else {
// back-facing
thing.style['background-position-x'] = '50px';
}
if (thisUpdate - lastAlt > 70) {
lastAlt = thisUpdate;
alt = !alt;
}
if (velocity > 50) {
thing.style['background-position-y'] = alt ? '50px' : '100px';
} else {
thing.style['background-position-y'] = '0px';
}
}
document.addEventListener('mousemove', e => {
mouseX = e.clientX;
mouseY = e.clientY;
});
document.addEventListener('scroll', e => {
el = e.target.scrollingElement;
scrollX = el.scrollLeft;
scrollY = el.scrollTop;
});
let duck_start = false;
function click_duck() {
if (duck_start) return;
duck_start = true;
xPos = thing.offsetLeft;
yPos = thing.offsetTop;
thing.style.position = 'absolute';
thing.style.cursor = 'auto';
lastUpdate = Date.now();
updateTimerId = setInterval(update, 10);
}

BIN
www/img/duck-sprite.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -316,7 +316,7 @@
🄯 Copyleft 2024 Benjamin Wiegand
</div>
<div class="footer-logo">
&gt; insert cool logo here &lt;
<div id="cursor-thing" onclick="click_duck()"></div>
</div>
<div class="footer-contact">
<noscript>
@ -350,5 +350,7 @@
</p>
</div>
</footer>
<script src="/cursor-thing.js"></script>
</body>
</html>

View File

@ -288,6 +288,20 @@ body:has(.project-image > input:checked) {
animation: fly-up .5s ease-out 0s 1 normal none;
}
.footer-logo {
width: 50px;
height: 50px;
}
#cursor-thing {
position: relative;
cursor: pointer;
width: 50px;
height: 50px;
background-image: url('/img/duck-sprite.webp');
z-index: 1;
}
@keyframes fly-up {
0% {
transform: translateY(70%);