Discography

My Music

VIP Lounge

VIPS: 3

Exclusive
Access

GUIDE THE ENTOURAGE TO THE DJ

// Gebruik een IIFE (Immediately Invoked Function Expression) om variabelen // in de scope te houden en conflicten met Carrd scripts te voorkomen. (function() { const container = document.getElementById('snake-game-container'); const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const scoreDisplay = document.getElementById('scoreDisplay'); const overlay = document.getElementById('overlay'); const overlayTitle = document.getElementById('overlayTitle'); const overlayText = document.getElementById('overlayText'); const startBtn = document.getElementById('startBtn'); const controlBtns = container.querySelectorAll('.control-btn'); const gridSize = 20; const tileCount = canvas.width / gridSize; let snake = []; let dx = 0; let dy = 0; let djX = 0; let djY = 0; let score = 3; let isPlaying = false; let baseSpeed = 160; let lastMoveTime = 0; let spotlights = []; let animFrameId; function initSpotlights() { spotlights = [ { x: 0, y: 0, baseAngle: Math.PI/4, sweep: 0.5, speed: 0.001 }, { x: canvas.width/2, y: 0, baseAngle: Math.PI/2, sweep: 0.3, speed: 0.0015 }, { x: canvas.width, y: 0, baseAngle: Math.PI*0.75, sweep: 0.5, speed: 0.0012 } ]; } function initGame() { // Forceer focus op de container zodat toetsenbord werkt in Carrd container.focus(); snake = [{x: 10, y: 10}, {x: 10, y: 11}, {x: 10, y: 12}]; dx = 0; dy = -1; score = 3; baseSpeed = 160; updateScore(); spawnDJ(); initSpotlights(); isPlaying = true; overlay.classList.add('opacity-0'); setTimeout(() => { overlay.classList.add('hidden'); }, 500); lastMoveTime = performance.now(); if (animFrameId) cancelAnimationFrame(animFrameId); animFrameId = requestAnimationFrame(gameLoop); } function gameLoop(timestamp) { if (!isPlaying) return; if (timestamp - lastMoveTime > baseSpeed) { updateSnake(); lastMoveTime = timestamp; } drawGame(timestamp); if (isPlaying) { animFrameId = requestAnimationFrame(gameLoop); } } function updateSnake() { const head = { x: snake[0].x + dx, y: snake[0].y + dy }; if (head.x < 0 || head.x >= tileCount || head.y < 0 || head.y >= tileCount) { gameOver(); return; } for (let i = 0; i < snake.length; i++) { if (head.x === snake[i].x && head.y === snake[i].y) { gameOver(); return; } } snake.unshift(head); if (head.x === djX && head.y === djY) { score++; updateScore(); spawnDJ(); if (baseSpeed > 80) baseSpeed -= 2; } else { snake.pop(); } } function drawGame(timestamp) { ctx.fillStyle = '#050505'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.strokeStyle = 'rgba(212, 175, 55, 0.05)'; ctx.lineWidth = 1; for(let i = 0; i < tileCount; i++) { ctx.beginPath(); ctx.moveTo(i * gridSize, 0); ctx.lineTo(i * gridSize, canvas.height); ctx.stroke(); ctx.beginPath(); ctx.moveTo(0, i * gridSize); ctx.lineTo(canvas.width, i * gridSize); ctx.stroke(); } spotlights.forEach(spot => { const currentAngle = spot.baseAngle + Math.sin(timestamp * spot.speed) * spot.sweep; const gradient = ctx.createLinearGradient( spot.x, spot.y, spot.x + Math.cos(currentAngle) * canvas.height, spot.y + Math.sin(currentAngle) * canvas.height ); gradient.addColorStop(0, 'rgba(212, 175, 55, 0.15)'); gradient.addColorStop(1, 'rgba(212, 175, 55, 0)'); ctx.beginPath(); ctx.moveTo(spot.x, spot.y); ctx.arc(spot.x, spot.y, canvas.height * 1.5, currentAngle - 0.15, currentAngle + 0.15); ctx.lineTo(spot.x, spot.y); ctx.fillStyle = gradient; ctx.fill(); }); const djPxX = djX * gridSize; const djPxY = djY * gridSize; ctx.shadowBlur = 10 + Math.sin(timestamp/200) * 5; ctx.shadowColor = 'rgba(212, 175, 55, 0.6)'; ctx.fillStyle = '#111'; ctx.fillRect(djPxX + 1, djPxY + 6, 18, 12); ctx.strokeStyle = '#D4AF37'; ctx.lineWidth = 1; ctx.strokeRect(djPxX + 1, djPxY + 6, 18, 12); ctx.fillStyle = '#D4AF37'; ctx.shadowBlur = 5; ctx.beginPath(); ctx.arc(djPxX + 10, djPxY + 5, 3, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#FFF8E7'; ctx.beginPath(); ctx.arc(djPxX + 6, djPxY + 12, 1.5, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.arc(djPxX + 14, djPxY + 12, 1.5, 0, Math.PI * 2); ctx.fill(); ctx.shadowBlur = 0; for (let i = 0; i < snake.length; i++) { const x = snake[i].x * gridSize; const y = snake[i].y * gridSize; const floatOffset = Math.sin((timestamp / 300) - (i * 0.3)) * 2; const lightness = Math.max(20, 70 - (i * 2)); ctx.fillStyle = i === 0 ? '#FFF8E7' : `hsl(45, 80%, ${lightness}%)`; ctx.shadowBlur = i === 0 ? 15 : 5; ctx.shadowColor = 'rgba(212, 175, 55, 0.5)'; ctx.beginPath(); ctx.arc(x + gridSize/2, y + gridSize/2 + floatOffset, gridSize/2 - 2, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#111'; ctx.beginPath(); ctx.arc(x + gridSize/2, y + gridSize/2 + floatOffset, i === 0 ? 1.5 : 2, 0, Math.PI * 2); ctx.fill(); } ctx.shadowBlur = 0; } function spawnDJ() { let validPosition = false; while (!validPosition) { djX = Math.floor(Math.random() * tileCount); djY = Math.floor(Math.random() * tileCount); validPosition = true; for (let i = 0; i < snake.length; i++) { if (snake[i].x === djX && snake[i].y === djY) { validPosition = false; break; } } } } function updateScore() { scoreDisplay.textContent = score; scoreDisplay.style.color = '#FFF'; setTimeout(() => { scoreDisplay.style.color = '#FACC15'; }, 300); } function gameOver() { isPlaying = false; overlayTitle.innerHTML = "CLUB
CLOSED"; overlayText.textContent = `YOUR ENTOURAGE GREW TO ${score} VIPS`; startBtn.textContent = "Book Next Event"; overlay.classList.remove('hidden'); setTimeout(() => { overlay.classList.remove('opacity-0'); }, 10); // Zorg dat je weer kunt klikken met de muis als je af bent container.blur(); } function changeDirection(newDx, newDy) { if (newDx !== 0 && dx !== 0) return; if (newDy !== 0 && dy !== 0) return; dx = newDx; dy = newDy; } // Toetsenbord besturing - Gekoppeld aan de CONTAINER ipv het hele document container.addEventListener('keydown', (e) => { if (!isPlaying) return; // Voorkom alleen default gedrag (scrollen) voor pijltjestoetsen if(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","w","a","s","d","W","A","S","D"].indexOf(e.key) > -1) { e.preventDefault(); } switch(e.key) { case 'ArrowUp': case 'w': case 'W': changeDirection(0, -1); break; case 'ArrowDown': case 's': case 'S': changeDirection(0, 1); break; case 'ArrowLeft': case 'a': case 'A': changeDirection(-1, 0); break; case 'ArrowRight': case 'd': case 'D': changeDirection(1, 0); break; } }); // Voorkom dat mobiel scrollt als je op de knoppen drukt controlBtns.forEach(btn => { const handlePress = (e) => { e.preventDefault(); // Voorkom tap-zoom en scrollen if (!isPlaying) return; const dir = btn.getAttribute('data-dir'); if (dir === 'up') changeDirection(0, -1); if (dir === 'down') changeDirection(0, 1); if (dir === 'left') changeDirection(-1, 0); if (dir === 'right') changeDirection(1, 0); }; btn.addEventListener('touchstart', handlePress, {passive: false}); btn.addEventListener('mousedown', handlePress); }); startBtn.addEventListener('click', initGame); // Om ervoor te zorgen dat mobiele gebruikers het spel niet per ongeluk weg scrollen // als ze IN het canvas swipen canvas.addEventListener('touchmove', function(e) { if(isPlaying) { e.preventDefault(); } }, {passive: false}); // Initiële setup initSpotlights(); animFrameId = requestAnimationFrame(drawGame); })();

    Felis eget

    Odio ut enim

    Quis viverra nibh cras pulvinar mattis nunc sed libero fermentum et sollicitudin orci. Purus in mollis nunc sed semper risus.

    Rutrum tellus

    Senectus netus

    Morbi quis commodo odio aenean sed adipiscing diam donec consectetur erat aenean sed adipiscing diam donec adipiscing.

    Mauris massa

    Proin sagittis

    Imperdiet proin fermentum leo orci porta pulvinar neque purus amet nunc congue nisi vitae. Ultrices dui sapien eget mi tellus ipsum.

    Maecenas

    Lobortis scelerisque fermentum dui faucibus in ornare quam viverra. Sit amet risus nullam eget felis eget nunc magna tempus.

    Amet integer

    Posuere urna nec tincidunt praesent semper feugiat nibh. Porttitor eget dolor morbi. Elementum integer enim neque volutpat.

    You Made it!

    You're a real explorer!
    You made it all the way down