Files
2026-11-03 21:58:12 -03:00

226 lines
8.0 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>faggot-chan | i'm gonna touch you</title>
<meta name="description" content="faggot-chan is a tiny browser game: move your cursor around and don't get touched. Easy, isn't it?">
<link rel="canonical" href="https://faggot-chan.online/">
<meta property="og:type" content="website">
<meta property="og:site_name" content="faggot-chan">
<meta property="og:title" content="faggot-chan | i'm gonna touch you">
<meta property="og:description" content="A tiny browser game: move your cursor around and don't get touched.">
<meta property="og:url" content="https://faggot-chan.online/">
<meta property="og:image" content="https://faggot-chan.online/creature.jpg">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "faggot-chan",
"alternateName": ["faggot-chan.online", "faggot chan"],
"url": "https://faggot-chan.online/",
"description": "faggot-chan is a tiny browser game: move your cursor around and don't get touched."
}
</script>
<link rel="icon" type="image/jpg" href="/bweeeeghg.jpg">
<style>
body { margin: 0; overflow: hidden; }
canvas {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.faggif{
position: fixed;
width: 100vw;
height: 100vh;
z-index: 0;
inset: 0;
object-fit: fill;
pointer-events: none;
}
.about {
position: fixed;
left: 8px;
bottom: 8px;
z-index: 2;
pointer-events: none;
color: #fff;
font: 12px/1.3 sans-serif;
text-shadow: 0 0 3px #000, 0 0 3px #000;
max-width: 90vw;
}
.about h1 { font-size: 14px; margin: 0; }
.about p { margin: 0; }
</style>
</head>
<body>
<img class="faggif" src="fagotni.gif" alt="if you are seeing this something went horribly wrong">
<canvas id="game"></canvas>
<div class="about">
<h1>faggot-chan</h1>
<p>A tiny browser game. Move the cursor around, don't get touched. Easy, isn't it?</p>
</div>
<noscript>faggot-chan: a tiny browser game that needs JavaScript. Move the cursor around and don't get touched.</noscript>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const chaserImg = new Image();
chaserImg.src = '/creature.jpg';
const spawnSound = new Audio('wah.ogg');
spawnSound.preload = 'auto';
let audioUnlocked = false;
function unlockAudio() {
if (!audioUnlocked) {
spawnSound.play().then(() => {
spawnSound.pause();
spawnSound.currentTime = 0;
audioUnlocked = true;
}).catch(() => {});
}
}
canvas.addEventListener('mousedown', unlockAudio);
canvas.addEventListener('touchstart', unlockAudio);
let chasers = [
{ x: canvas.width / 2, y: canvas.height / 2, vx: 0, vy: 0, lastRandom: 0, lastSpawn: 0 }
];
let target = { x: canvas.width / 2, y: canvas.height / 2 };
const maxSpeed = 15;
const moveForce = 0.8;
const inertia = 0.8;
const repulsionDist = 15; // Slightly larger hitbox for 15px chasers
const repulsionStrength = 2;
const spawnCooldown = 0.5;
const randomCooldown = 2;
const chaserSize = 20; // Bigger chasers (15px)
const maxChasers = 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
// rape input
canvas.addEventListener('touchstart', e => {
e.preventDefault();
target.x = e.touches[0].clientX;
target.y = e.touches[0].clientY;
});
canvas.addEventListener('touchmove', e => {
e.preventDefault();
target.x = e.touches[0].clientX;
target.y = e.touches[0].clientY;
});
// Mouse input (for desktop testing)
canvas.addEventListener('mousemove', e => {
target.x = e.clientX;
target.y = e.clientY;
});
function update() {
const now = performance.now() / 1000;
ctx.clearRect(0, 0, canvas.width, canvas.height);
let newChasers = [];
chasers.forEach(c => {
// Chase target
const dx = target.x - c.x;
const dy = target.y - c.y;
const dist = Math.max(Math.sqrt(dx * dx + dy * dy), 1);
const ax = (dx / dist) * moveForce;
const ay = (dy / dist) * moveForce;
c.vx = (c.vx * inertia) + ax;
c.vy = (c.vy * inertia) + ay;
// Cap speed
const speed = Math.sqrt(c.vx * c.vx + c.vy * c.vy);
if (speed > maxSpeed) {
c.vx = c.vx * maxSpeed / speed;
c.vy = c.vy * maxSpeed / speed;
}
// Repulsion
chasers.forEach(other => {
if (other !== c) {
const rDx = c.x - other.x;
const rDy = c.y - other.y;
const rDist = Math.sqrt(rDx * rDx + rDy * rDy);
if (rDist < repulsionDist && rDist > 0) {
const push = repulsionStrength * (repulsionDist - rDist) / rDist;
c.vx += (rDx / rDist) * push;
c.vy += (rDy / rDist) * push;
}
}
});
// Random moves
if (now - c.lastRandom > randomCooldown && Math.random() < 0.2) {
const moveType = Math.floor(Math.random() * 3);
if (moveType === 0) { // Jump
c.vx += (dx / dist) * 10;
c.vy += (dy / dist) * 10;
console.log(`Chaser ${chasers.indexOf(c)}: Jumping!`);
} else if (moveType === 1) { // Wiggle
c.vx += Math.random() * 4 - 2;
c.vy += Math.random() * 4 - 2;
console.log(`Chaser ${chasers.indexOf(c)}: Wiggling!`);
} else { // Dash
const perpDx = -dy / dist;
const perpDy = dx / dist;
const dir = Math.random() < 0.5 ? -1 : 1;
c.vx += perpDx * 5 * dir;
c.vy += perpDy * 5 * dir;
console.log(`Chaser ${chasers.indexOf(c)}: Dashing!`);
}
c.lastRandom = now;
}
// Update position
c.x += c.vx;
c.y += c.vy;
c.x = Math.max(chaserSize / 2, Math.min(c.x, canvas.width - chaserSize / 2));
c.y = Math.max(chaserSize / 2, Math.min(c.y, canvas.height - chaserSize / 2));
// Spawn only on touch proximity
if (dist < 45 && now - c.lastSpawn > spawnCooldown && chasers.length < maxChasers) {
newChasers.push({
x: c.x,
y: c.y,
vx: 0,
vy: 0,
lastRandom: now,
lastSpawn: now
});
if (audioUnlocked) {
const s = spawnSound.cloneNode(); // allow overlapping sounds
s.volume = 0.6;
s.play();
}
c.lastSpawn = now;
}
// Draw with image
ctx.drawImage(chaserImg, c.x - chaserSize / 2, c.y - chaserSize / 2, chaserSize, chaserSize);
});
chasers.push(...newChasers);
requestAnimationFrame(update);
}
// Start after image loads
chaserImg.onload = () => update();
</script>
</body>
</html>