for scipt.js is
const canvas = document.getElementById("snakeCanvas");
const ctx = canvas.getContext("2d");
let w = window.innerWidth;
let h = window.innerHeight;
canvas.width = w;
canvas.height = h;
// Snake trail points
let points = [];
const maxPoints = 160; // longer snake
const minDist = 4; // spacing between points
// Mouse position
let mouseX = w / 2;
let mouseY = h / 2;
// Snake animation variables
let hue = 120; // starting color
let hueSpeed = 0.4; // color cycling speed
let glowStrength = 15; // shadow blur
let breathing = 0; // breathing animation
let autoSlither = false; // toggle auto movement
let slitherAngle = 0; // internal wave motion
// FPS meter
let lastTime = performance.now();
let fps = 0;
// Resize canvas
window.addEventListener("resize", () => {
w = window.innerWidth;
h = window.innerHeight;
canvas.width = w;
canvas.height = h;
});
// Mouse movement
window.addEventListener("mousemove", e => {
updatePointer(e.clientX, e.clientY);
});
// Touch support
window.addEventListener("touchmove", e => {
const t = e.touches[0];
updatePointer(t.clientX, t.clientY);
});
// Click to teleport head
window.addEventListener("click", e => {
points.push({ x: e.clientX, y: e.clientY });
});
// Update pointer and add snake points
function updatePointer(x, y) {
const last = points[points.length - 1];
if (!last || distance(last.x, last.y, x, y) > minDist) {
points.push({ x, y });
if (points.length > maxPoints) points.shift();
}
mouseX = x;
mouseY = y;
}
// Distance helper
function distance(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
// Draw snake
function drawSnake() {
ctx.clearRect(0, 0, w, h);
if (points.length < 2) return;
ctx.lineCap = "round";
ctx.lineJoin = "round";
// Breathing animation
breathing += 0.03;
const breath = Math.sin(breathing) * 2;
// Glow
ctx.shadowBlur = glowStrength;
ctx.shadowColor = "rgba(120,255,140,0.8)";
// Draw body segments
for (let i = 0; i < points.length - 1; i++) {
const p1 = points[i];
const p2 = points[i + 1];
const t = i / points.length; // 0 → tail, 1 → head
// Width breathing + taper
const width = 4 + t * 12 + breath;
// Color cycling
const segmentHue = (hue + t * 60) % 360;
const grad = ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);
grad.addColorStop(0, `hsla(${segmentHue}, 80%, 45%, 0.3)`);
grad.addColorStop(1, `hsla(${segmentHue}, 90%, 60%, 1)`);
ctx.strokeStyle = grad;
ctx.lineWidth = width;
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.stroke();
}
// Draw head
const head = points[points.length - 1];
ctx.beginPath();
ctx.fillStyle = `hsla(${hue}, 100%, 70%, 1)`;
ctx.arc(head.x, head.y, 10 + breath * 0.5, 0, Math.PI * 2);
ctx.fill();
// Update color cycle
hue += hueSpeed;
}
// Auto slither movement (optional)
function autoMove() {
if (!autoSlither) return;
slitherAngle += 0.05;
const radius = 80;
const x = w / 2 + Math.cos(slitherAngle) * radius;
const y = h / 2 + Math.sin(slitherAngle * 1.5) * radius;
updatePointer(x, y);
}
// FPS counter
function drawFPS() {
const now = performance.now();
fps = 1000 / (now - lastTime);
lastTime = now;
ctx.fillStyle = "white";
ctx.font = "14px monospace";
ctx.fillText(`FPS: ${fps.toFixed(1)}`, 10, 20);
}
// Main loop
function loop() {
autoMove();
drawSnake();
drawFPS();
requestAnimationFrame(loop);
}
loop();
// Distance helper
function distance(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
// Draw snake
function drawSnake() {
ctx.clearRect(0, 0, w, h);
if (points.length < 2) return;
ctx.lineCap = "round";
ctx.lineJoin = "round";
// Breathing animation
breathing += 0.03;
const breath = Math.sin(breathing) * 2;
// Glow
ctx.shadowBlur = glowStrength;
ctx.shadowColor = "rgba(120,255,140,0.8)";
// Draw body segments
for (let i = 0; i < points.length - 1; i++) {
const p1 = points[i];
const p2 = points[i + 1];
const t = i / points.length; // 0 → tail, 1 → head
// Width breathing + taper
const width = 4 + t * 12 + breath;
// Color cycling
const segmentHue = (hue + t * 60) % 360;
const grad = ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);
grad.addColorStop(0, `hsla(${segmentHue}, 80%, 45%, 0.3)`);
grad.addColorStop(1, `hsla(${segmentHue}, 90%, 60%, 1)`);
ctx.strokeStyle = grad;
ctx.lineWidth = width;
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.stroke();
}
// Draw head
const head = points[points.length - 1];
ctx.beginPath();
ctx.fillStyle = `hsla(${hue}, 100%, 70%, 1)`;
ctx.arc(head.x, head.y, 10 + breath * 0.5, 0, Math.PI * 2);
ctx.fill();
// Update color cycle
hue += hueSpeed;
}
// Auto slither movement (optional)
function autoMove() {
if (!autoSlither) return;
slitherAngle += 0.05;
const radius = 80;
const x = w / 2 + Math.cos(slitherAngle) * radius;
const y = h / 2 + Math.sin(slitherAngle * 1.5) * radius;
updatePointer(x, y);
}
// FPS counter
function drawFPS() {
const now = performance.now();
fps = 1000 / (now - lastTime);
lastTime = now;
ctx.fillStyle = "white";
ctx.font = "14px monospace";
ctx.fillText(`FPS: ${fps.toFixed(1)}`, 10, 20);
}
// Main loop
function loop() {
autoMove();
drawSnake();
drawFPS();
requestAnimationFrame(loop);
}
loop();
i used ai cause there wasn’t much videos i could find with it and for the index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Point to Point Snake</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<canvas id="snakeCanvas"></canvas>
<script src="script.js"></script>
</body>
</html>
and for the style.cs
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #111;
overflow: hidden;
cursor: none;
}
#snakeCanvas {
display: block;
}