Member
Account Settings
Share AgencyGenius
Know someone who might benefit from AgencyGenius? We'd love it if you shared our platform with your networking group!

Documentation
Code
We've listed the code documentation below, making a tool for this one is somewhat pointless as a game is somewhat subjective in what you want it to do more so than any other type of component.
We've given you the code for our version and encourage you to input into your AI platform to change colours and such but our hope is that you have a bit of fun with it. It is a gimmick after all. We look forward to seeing what other games you create.
404 Gravity Drop Game Overview
The 404 Gravity Drop Game transforms a typical error page into an interactive physics-based experience. Users click to drop balls that destroy blocks arranged in a "404" pattern, utilizing GSAP's Physics2D plugin for realistic gravity simulation and particle effects for visual feedback.
HTML Structure
The game's HTML architecture consists of:
- A fixed wrapper container #gravity-drop-wrapper covering the entire viewport
- Header section with logo, navigation links, and CTA button
- Game area container .gd-game-area with data attribute data-gd-game
- Block container .gd-block-container for the 404 pattern
- Score display with counter elements using data-gd-count and data-gd-total
- Hidden completion screen .gd-complete for game end state
- Dynamic elements for balls, particles, and visual effects
Physics Implementation
The game leverages GSAP's Physics2D plugin for realistic motion:
- External script imports: gsap@3.13.0 and Physics2DPlugin
- Gravity setting of 800 pixels per second squared for balls
- Particle physics with random velocity 100-400 and angles -180 to 0
- Particle gravity of 600 for lighter falling effect
- Ball squeeze animation using scaleY: 0.8, scaleX: 1.2
- 5-second duration for ball physics simulation
404 Pattern Generation
The distinctive 404 block pattern is created programmatically:
- 2D array pattern with 1 representing blocks and 0 for empty spaces
- 5 rows by 13 columns grid structure
- Dynamic block sizing: 18px mobile, 30px tablet, 40px desktop
- Spacing calculation: blockSize + 3 for mobile, +4 tablet, +5 desktop
- Center positioning using transform: translate(-50%, -50%)
- Individual block positioning with (x * spacing - spacing * 6.5) formula
Collision Detection System
Real-time collision detection between balls and blocks:
- getBoundingClientRect() for precise position tracking
- AABB (Axis-Aligned Bounding Box) collision algorithm
- Collision check formula: ballRect.left < blockRect.right && ballRect.right > blockRect.left
- data-destroyed attribute prevents duplicate collisions
- Continuous checking via GSAP's onUpdate callback
- Frame-by-frame collision validation during ball movement
Visual Effects and Animations
The game features multiple layers of visual feedback:
- Block destruction: scale: 0, rotation: random(-180, 180) with 0.4s duration
- 8 particles per block explosion with random colors from palette
- Click indicator animation: scale: 0.5 to 1.5 with opacity fade
- Ball styling: radial-gradient(circle at 30% 30%, #ff69b4, #AD24A6)
- Shadow effects: box-shadow: 0 3px 15px rgba(173, 36, 166, 0.4)
- Hover states on blocks with transform: scale(1.05)
Combo System
Dynamic combo tracking rewards rapid block destruction:
- Combo counter increments on each block hit
- 300ms timeout window between hits using setTimeout
- Combo display animation: scale: 0.5 to 1.2 with back.out(1.7) easing
- Vertical movement: y: 0 to -30 during animation
- Text format: ${comboCount}x COMBO!
- Automatic fade out after display with opacity transition
Scoring and Statistics
Comprehensive game metrics tracking:
- Total blocks counted during pattern generation
- Destroyed blocks tracked via destroyedBlocks++
- Ball usage counter increments on each click
- Efficiency calculation: Math.round((totalBlocks / ballsUsed) * 100)
- Real-time counter display updates
- Completion screen shows final statistics
Responsive Design Implementation
The game adapts seamlessly across device sizes:
- Breakpoints: max-width: 768px mobile, max-width: 1024px tablet
- Dynamic block sizing based on window.innerWidth
- Navigation links hidden on tablet and mobile via display: none
- Header padding adjusts: 2rem 3rem desktop to 1rem 1.5rem mobile
- Logo height scales from 40px to 30px
- Game area height calculation: calc(100vh - 100px) to calc(100vh - 70px)
Event Handling and Interactions
User input management and interaction flow:
- Click event listener on .gd-game-area container
- Cursor style: cursor: crosshair for targeting feedback
- Ball spawn position calculated from e.clientX - rect.left
- Fixed Y spawn at 50px from top
- Double-tap prevention: touchend event with 300ms threshold
- e.preventDefault() blocks zoom on mobile devices
Performance Optimizations
Several techniques ensure smooth gameplay across devices:
- Automatic element removal after animations complete
- pointer-events: none on non-interactive elements
- Single collision check per block using dataset.destroyed flag
- Particle cleanup with onComplete: () => particle.remove()
- Ball removal after 5-second physics duration
- Efficient DOM queries using data attributes
- Hardware-accelerated CSS transforms for animations
Game State Management
The game tracks multiple state variables:
- totalBlocks : Initial block count from pattern
- destroyedBlocks : Current progress counter
- ballsUsed : Total balls dropped by player
- comboCount : Current combo chain length
- comboTimer : Timeout reference for combo reset
- blocks array: References to all block elements
- Completion trigger when destroyedBlocks === totalBlocks
<div id="gravity-drop-wrapper"> <header class="gd-header"> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/Group+203.svg" alt="Logo" class="gd-logo"> <nav class="gd-nav-links"> <a href="/">Home</a> <a href="/pricing">Pricing</a> <a href="/compare">Compare</a> <a href="/the-vault">The Vault</a> <a href="/faq">FAQ</a> </nav> <a href="/" class="gd-cta-btn">Return Home</a> </header> <div class="gd-game-area" data-gd-game=""> <div class="gd-score"> <h1>Oops, Page Not Found</h1> <p>Click to drop balls and clear the blocks!</p> <div class="gd-counter"> <span data-gd-count="">0</span> out of <span data-gd-total="">0</span> </div> </div> <div class="gd-block-container" data-gd-blocks=""></div> <div class="gd-combo" data-gd-combo=""></div> <div class="gd-click-indicator" data-gd-indicator=""></div> </div> <div class="gd-complete" data-gd-complete=""> <h2>🎉 404 Destroyed!</h2> <p>You've cleared all the blocks!</p> <div class="gd-stats"> <p>Balls used: <strong data-gd-balls="">0</strong></p> <p>Efficiency: <strong data-gd-efficiency="">0%</strong></p> </div> <button class="gd-cta-btn" onclick="location.reload()">Play Again</button> </div> <!-- GSAP Libraries --> <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/Physics2DPlugin.min.js"></script> </div>
/* Global font family for all elements in wrapper */ #gravity-drop-wrapper * { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } /* Main wrapper - full viewport coverage */ #gravity-drop-wrapper { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: #ffffff; overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } /* Header section */ #gravity-drop-wrapper .gd-header { position: relative; display: flex; justify-content: space-between; align-items: center; padding: 2rem 3rem; z-index: 10; background: white; } #gravity-drop-wrapper .gd-logo { height: 40px; width: auto; display: block; align-self: center; } /* Navigation links - centered */ #gravity-drop-wrapper .gd-nav-links { position: absolute; left: 50%; transform: translateX(-50%); display: flex; gap: 2rem; align-items: center; height: 100%; } #gravity-drop-wrapper .gd-nav-links a { color: #000; text-decoration: none; font-size: 20px; font-weight: 500; transition: all 0.3s ease; line-height: 40px; display: flex; align-items: center; position: relative; } #gravity-drop-wrapper .gd-nav-links a:hover { color: #AD24A6; transform: translateY(-2px); } /* CTA Button */ #gravity-drop-wrapper .gd-cta-btn { background: #AD24A6; color: white; border: none; padding: 12px 24px; border-radius: 8px; font-size: 16px; cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; transition: all 0.3s ease; align-self: center; } #gravity-drop-wrapper .gd-cta-btn:hover { background: #8e1d88; transform: translateY(-2px); } /* Game area */ #gravity-drop-wrapper .gd-game-area { position: relative; width: 100%; height: calc(100vh - 100px); cursor: crosshair; background: radial-gradient(ellipse at center bottom, rgba(173, 36, 166, 0.05), transparent); } /* Click indicator */ #gravity-drop-wrapper .gd-click-indicator { position: absolute; width: 40px; height: 40px; border: 2px solid #AD24A6; border-radius: 50%; pointer-events: none; opacity: 0; transform: translate(-50%, -50%) scale(0.5); } /* Block container */ #gravity-drop-wrapper .gd-block-container { position: absolute; top: 55%; left: 50%; transform: translate(-50%, -50%); } /* Individual blocks */ #gravity-drop-wrapper .gd-block { position: absolute; width: 30px; height: 30px; background: linear-gradient(135deg, #444, #222); box-shadow: 0 2px 8px rgba(0,0,0,0.2); border-radius: 3px; transition: transform 0.1s ease; } #gravity-drop-wrapper .gd-block:hover { transform: scale(1.05); } /* Ball styles */ #gravity-drop-wrapper .gd-ball { position: absolute; width: 30px; height: 30px; border-radius: 50%; background: radial-gradient(circle at 30% 30%, #ff69b4, #AD24A6); box-shadow: 0 3px 15px rgba(173, 36, 166, 0.4), inset 0 -5px 10px rgba(0,0,0,0.2); pointer-events: none; } /* Particle effects */ #gravity-drop-wrapper .gd-particle { position: absolute; width: 6px; height: 6px; border-radius: 50%; pointer-events: none; } /* Score display */ #gravity-drop-wrapper .gd-score { position: absolute; top: 120px; left: 50%; transform: translateX(-50%); text-align: center; color: #666; font-size: 1.2rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } #gravity-drop-wrapper .gd-score h1 { font-size: 1.5rem !important; margin: 0 0 1rem 0; color: #000; font-weight: 600; line-height: 1.2; } #gravity-drop-wrapper .gd-score p { margin: 0.5rem 0; } /* Counter display */ #gravity-drop-wrapper .gd-counter { background: #f5f5f5; border: 2px solid #AD24A6; border-radius: 12px; padding: 12px 24px; display: inline-block; margin-top: 1.5rem; font-weight: bold; color: #000; font-size: 1.4rem; } #gravity-drop-wrapper .gd-counter span { color: #AD24A6; } /* Combo display */ #gravity-drop-wrapper .gd-combo { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 3rem; font-weight: bold; color: #AD24A6; opacity: 0; pointer-events: none; } /* Completion screen */ #gravity-drop-wrapper .gd-complete { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.9); background: white; padding: 3rem; border-radius: 20px; text-align: center; opacity: 0; visibility: hidden; transition: all 0.3s ease; box-shadow: 0 10px 40px rgba(0,0,0,0.1); z-index: 100; } #gravity-drop-wrapper .gd-complete.show { opacity: 1; visibility: visible; transform: translate(-50%, -50%) scale(1); } #gravity-drop-wrapper .gd-complete h2 { color: #333; margin-bottom: 1rem; } #gravity-drop-wrapper .gd-complete .gd-stats { margin: 1.5rem 0; color: #666; } /* Tablet styles */ @media (max-width: 1024px) { #gravity-drop-wrapper .gd-nav-links { display: none; } #gravity-drop-wrapper .gd-block { width: 30px; height: 30px; } } /* Mobile styles */ @media (max-width: 768px) { #gravity-drop-wrapper .gd-header { padding: 1rem 1.5rem; } #gravity-drop-wrapper .gd-logo { height: 30px; } #gravity-drop-wrapper .gd-cta-btn { padding: 8px 16px; font-size: 14px; } #gravity-drop-wrapper .gd-game-area { height: calc(100vh - 70px); } #gravity-drop-wrapper .gd-score { top: 90px; font-size: 1rem; } #gravity-drop-wrapper .gd-score h1 { font-size: 1.2rem !important; } #gravity-drop-wrapper .gd-counter { font-size: 1.2rem; padding: 10px 20px; } #gravity-drop-wrapper .gd-block { width: 18px; height: 18px; } #gravity-drop-wrapper .gd-ball { width: 22px; height: 22px; } #gravity-drop-wrapper .gd-complete { padding: 2rem; width: 90%; max-width: 300px; } }
(function() { const wrapper = document.getElementById('gravity-drop-wrapper'); const gameArea = wrapper.querySelector('[data-gd-game]'); const blockContainer = wrapper.querySelector('[data-gd-blocks]'); const countDisplay = wrapper.querySelector('[data-gd-count]'); const totalDisplay = wrapper.querySelector('[data-gd-total]'); const completeScreen = wrapper.querySelector('[data-gd-complete]'); const comboDisplay = wrapper.querySelector('[data-gd-combo]'); const clickIndicator = wrapper.querySelector('[data-gd-indicator]'); const ballsDisplay = wrapper.querySelector('[data-gd-balls]'); const efficiencyDisplay = wrapper.querySelector('[data-gd-efficiency]'); let totalBlocks = 0; let destroyedBlocks = 0; let ballsUsed = 0; let comboCount = 0; let comboTimer = null; const blocks = []; // Create proper 404 pattern const pattern = [ [1,0,1,0,0,1,1,1,0,0,1,0,1], [1,0,1,0,0,1,0,1,0,0,1,0,1], [1,1,1,0,0,1,0,1,0,0,1,1,1], [0,0,1,0,0,1,0,1,0,0,0,0,1], [0,0,1,0,0,1,1,1,0,0,0,0,1] ]; // Determine block size based on screen width const isMobile = window.innerWidth <= 768; const isTablet = window.innerWidth <= 1024 && window.innerWidth > 768; let blockSize, spacing; if(isMobile) { blockSize = 18; spacing = blockSize + 3; } else if(isTablet) { blockSize = 30; spacing = blockSize + 4; } else { blockSize = 40; spacing = blockSize + 5; } // Generate blocks from pattern pattern.forEach((row, y) => { row.forEach((cell, x) => { if(cell === 1) { const block = document.createElement('div'); block.className = 'gd-block'; block.style.width = blockSize + 'px'; block.style.height = blockSize + 'px'; block.style.left = (x * spacing - spacing * 6.5) + 'px'; block.style.top = (y * spacing - spacing * 2.5) + 'px'; blockContainer.appendChild(block); blocks.push(block); totalBlocks++; } }); }); totalDisplay.textContent = totalBlocks; // Create particle effect function createParticle(x, y, color) { const particle = document.createElement('div'); particle.className = 'gd-particle'; particle.style.left = x + 'px'; particle.style.top = y + 'px'; particle.style.background = color; gameArea.appendChild(particle); gsap.to(particle, { physics2D: { velocity: gsap.utils.random(100, 400), angle: gsap.utils.random(-180, 0), gravity: 600 }, opacity: 0, scale: 0.5, duration: 2, onComplete: () => particle.remove() }); } // Show combo display function showCombo() { if(comboCount > 1) { comboDisplay.textContent = `${comboCount}x COMBO!`; gsap.fromTo(comboDisplay, { opacity: 1, scale: 0.5, y: 0 }, { scale: 1.2, y: -30, duration: 0.5, ease: "back.out(1.7)", onComplete: () => { gsap.to(comboDisplay, { opacity: 0, scale: 0.8, duration: 0.3 }); } }); } } // Check collision between ball and blocks function checkCollision(ball) { const ballRect = ball.getBoundingClientRect(); let hitThisFrame = false; blocks.forEach((block, index) => { if(!block.dataset.destroyed) { const blockRect = block.getBoundingClientRect(); if(ballRect.left < blockRect.right && ballRect.right > blockRect.left && ballRect.top < blockRect.bottom && ballRect.bottom > blockRect.top) { block.dataset.destroyed = 'true'; hitThisFrame = true; // Enhanced particle explosion for(let i = 0; i < 8; i++) { createParticle( blockRect.left + blockRect.width/2, blockRect.top + blockRect.height/2, ['#AD24A6', '#ff69b4', '#444', '#666'][Math.floor(Math.random() * 4)] ); } // Animate block destruction gsap.to(block, { scale: 0, opacity: 0, rotation: gsap.utils.random(-180, 180), duration: 0.4, ease: "power2.in", onComplete: () => block.remove() }); destroyedBlocks++; countDisplay.textContent = destroyedBlocks; // Combo system comboCount++; clearTimeout(comboTimer); comboTimer = setTimeout(() => { showCombo(); comboCount = 0; }, 300); // Check for game completion if(destroyedBlocks === totalBlocks) { const efficiency = Math.round((totalBlocks / ballsUsed) * 100); ballsDisplay.textContent = ballsUsed; efficiencyDisplay.textContent = efficiency + '%'; setTimeout(() => { completeScreen.classList.add('show'); }, 500); } } } }); } // Game click handler gameArea.addEventListener('click', (e) => { const rect = gameArea.getBoundingClientRect(); const x = e.clientX - rect.left; const y = 50; const isMobile = window.innerWidth <= 768; ballsUsed++; // Show click indicator clickIndicator.style.left = x + 'px'; clickIndicator.style.top = e.clientY - rect.top + 'px'; gsap.fromTo(clickIndicator, { opacity: 1, scale: 0.5 }, { opacity: 0, scale: 1.5, duration: 0.5, ease: "power2.out" }); // Create ball const ballSize = isMobile ? 22 : 30; const ball = document.createElement('div'); ball.className = 'gd-ball'; ball.style.left = (x - ballSize/2) + 'px'; ball.style.top = y + 'px'; gameArea.appendChild(ball); // Apply physics to ball gsap.to(ball, { physics2D: { velocity: 0, angle: 90, gravity: 800 }, duration: 5, onUpdate: function() { checkCollision(ball); }, onComplete: () => ball.remove() }); // Squeeze animation on drop gsap.to(ball, { scaleY: 0.8, scaleX: 1.2, duration: 0.1, yoyo: true, repeat: 1, ease: "power2.inOut" }); }); // Prevent zooming on mobile double-tap let lastTouchEnd = 0; document.addEventListener('touchend', (e) => { const now = (new Date()).getTime(); if (now - lastTouchEnd <= 300) { e.preventDefault(); } lastTouchEnd = now; }, false); })();
<div id="snippet-of7ouhe2"> <!-- HTML SECTION START --> <div id="gravity-drop-wrapper"> <header class="gd-header"> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/Group+203.svg" alt="Logo" class="gd-logo"> <nav class="gd-nav-links"> <a href="/">Home</a> <a href="/pricing">Pricing</a> <a href="/compare">Compare</a> <a href="/the-vault">The Vault</a> <a href="/faq">FAQ</a> </nav> <a href="/" class="gd-cta-btn">Return Home</a> </header> <div class="gd-game-area" data-gd-game=""> <div class="gd-score"> <h1>Oops, Page Not Found</h1> <p>Click to drop balls and clear the blocks!</p> <div class="gd-counter"> <span data-gd-count="">0</span> out of <span data-gd-total="">0</span> </div> </div> <div class="gd-block-container" data-gd-blocks=""></div> <div class="gd-combo" data-gd-combo=""></div> <div class="gd-click-indicator" data-gd-indicator=""></div> </div> <div class="gd-complete" data-gd-complete=""> <h2>🎉 404 Destroyed!</h2> <p>You've cleared all the blocks!</p> <div class="gd-stats"> <p>Balls used: <strong data-gd-balls="">0</strong></p> <p>Efficiency: <strong data-gd-efficiency="">0%</strong></p> </div> <button class="gd-cta-btn" onclick="location.reload()">Play Again</button> </div> <!-- GSAP Libraries --> <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/Physics2DPlugin.min.js"></script> </div> <!-- HTML SECTION END --> <!-- CSS SECTION START --> <style> /* Global font family for all elements in wrapper */ #gravity-drop-wrapper * { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } /* Main wrapper - full viewport coverage */ #gravity-drop-wrapper { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: #ffffff; overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } /* Header section */ #gravity-drop-wrapper .gd-header { position: relative; display: flex; justify-content: space-between; align-items: center; padding: 2rem 3rem; z-index: 10; background: white; } #gravity-drop-wrapper .gd-logo { height: 40px; width: auto; display: block; align-self: center; } /* Navigation links - centered */ #gravity-drop-wrapper .gd-nav-links { position: absolute; left: 50%; transform: translateX(-50%); display: flex; gap: 2rem; align-items: center; height: 100%; } #gravity-drop-wrapper .gd-nav-links a { color: #000; text-decoration: none; font-size: 20px; font-weight: 500; transition: all 0.3s ease; line-height: 40px; display: flex; align-items: center; position: relative; } #gravity-drop-wrapper .gd-nav-links a:hover { color: #AD24A6; transform: translateY(-2px); } /* CTA Button */ #gravity-drop-wrapper .gd-cta-btn { background: #AD24A6; color: white; border: none; padding: 12px 24px; border-radius: 8px; font-size: 16px; cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; transition: all 0.3s ease; align-self: center; } #gravity-drop-wrapper .gd-cta-btn:hover { background: #8e1d88; transform: translateY(-2px); } /* Game area */ #gravity-drop-wrapper .gd-game-area { position: relative; width: 100%; height: calc(100vh - 100px); cursor: crosshair; background: radial-gradient(ellipse at center bottom, rgba(173, 36, 166, 0.05), transparent); } /* Click indicator */ #gravity-drop-wrapper .gd-click-indicator { position: absolute; width: 40px; height: 40px; border: 2px solid #AD24A6; border-radius: 50%; pointer-events: none; opacity: 0; transform: translate(-50%, -50%) scale(0.5); } /* Block container */ #gravity-drop-wrapper .gd-block-container { position: absolute; top: 55%; left: 50%; transform: translate(-50%, -50%); } /* Individual blocks */ #gravity-drop-wrapper .gd-block { position: absolute; width: 30px; height: 30px; background: linear-gradient(135deg, #444, #222); box-shadow: 0 2px 8px rgba(0,0,0,0.2); border-radius: 3px; transition: transform 0.1s ease; } #gravity-drop-wrapper .gd-block:hover { transform: scale(1.05); } /* Ball styles */ #gravity-drop-wrapper .gd-ball { position: absolute; width: 30px; height: 30px; border-radius: 50%; background: radial-gradient(circle at 30% 30%, #ff69b4, #AD24A6); box-shadow: 0 3px 15px rgba(173, 36, 166, 0.4), inset 0 -5px 10px rgba(0,0,0,0.2); pointer-events: none; } /* Particle effects */ #gravity-drop-wrapper .gd-particle { position: absolute; width: 6px; height: 6px; border-radius: 50%; pointer-events: none; } /* Score display */ #gravity-drop-wrapper .gd-score { position: absolute; top: 120px; left: 50%; transform: translateX(-50%); text-align: center; color: #666; font-size: 1.2rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } #gravity-drop-wrapper .gd-score h1 { font-size: 1.5rem !important; margin: 0 0 1rem 0; color: #000; font-weight: 600; line-height: 1.2; } #gravity-drop-wrapper .gd-score p { margin: 0.5rem 0; } /* Counter display */ #gravity-drop-wrapper .gd-counter { background: #f5f5f5; border: 2px solid #AD24A6; border-radius: 12px; padding: 12px 24px; display: inline-block; margin-top: 1.5rem; font-weight: bold; color: #000; font-size: 1.4rem; } #gravity-drop-wrapper .gd-counter span { color: #AD24A6; } /* Combo display */ #gravity-drop-wrapper .gd-combo { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 3rem; font-weight: bold; color: #AD24A6; opacity: 0; pointer-events: none; } /* Completion screen */ #gravity-drop-wrapper .gd-complete { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.9); background: white; padding: 3rem; border-radius: 20px; text-align: center; opacity: 0; visibility: hidden; transition: all 0.3s ease; box-shadow: 0 10px 40px rgba(0,0,0,0.1); z-index: 100; } #gravity-drop-wrapper .gd-complete.show { opacity: 1; visibility: visible; transform: translate(-50%, -50%) scale(1); } #gravity-drop-wrapper .gd-complete h2 { color: #333; margin-bottom: 1rem; } #gravity-drop-wrapper .gd-complete .gd-stats { margin: 1.5rem 0; color: #666; } /* Tablet styles */ @media (max-width: 1024px) { #gravity-drop-wrapper .gd-nav-links { display: none; } #gravity-drop-wrapper .gd-block { width: 30px; height: 30px; } } /* Mobile styles */ @media (max-width: 768px) { #gravity-drop-wrapper .gd-header { padding: 1rem 1.5rem; } #gravity-drop-wrapper .gd-logo { height: 30px; } #gravity-drop-wrapper .gd-cta-btn { padding: 8px 16px; font-size: 14px; } #gravity-drop-wrapper .gd-game-area { height: calc(100vh - 70px); } #gravity-drop-wrapper .gd-score { top: 90px; font-size: 1rem; } #gravity-drop-wrapper .gd-score h1 { font-size: 1.2rem !important; } #gravity-drop-wrapper .gd-counter { font-size: 1.2rem; padding: 10px 20px; } #gravity-drop-wrapper .gd-block { width: 18px; height: 18px; } #gravity-drop-wrapper .gd-ball { width: 22px; height: 22px; } #gravity-drop-wrapper .gd-complete { padding: 2rem; width: 90%; max-width: 300px; } } </style> <!-- CSS SECTION END --> <!-- JAVASCRIPT SECTION START --> <script> (function() { const wrapper = document.getElementById('gravity-drop-wrapper'); const gameArea = wrapper.querySelector('[data-gd-game]'); const blockContainer = wrapper.querySelector('[data-gd-blocks]'); const countDisplay = wrapper.querySelector('[data-gd-count]'); const totalDisplay = wrapper.querySelector('[data-gd-total]'); const completeScreen = wrapper.querySelector('[data-gd-complete]'); const comboDisplay = wrapper.querySelector('[data-gd-combo]'); const clickIndicator = wrapper.querySelector('[data-gd-indicator]'); const ballsDisplay = wrapper.querySelector('[data-gd-balls]'); const efficiencyDisplay = wrapper.querySelector('[data-gd-efficiency]'); let totalBlocks = 0; let destroyedBlocks = 0; let ballsUsed = 0; let comboCount = 0; let comboTimer = null; const blocks = []; // Create proper 404 pattern const pattern = [ [1,0,1,0,0,1,1,1,0,0,1,0,1], [1,0,1,0,0,1,0,1,0,0,1,0,1], [1,1,1,0,0,1,0,1,0,0,1,1,1], [0,0,1,0,0,1,0,1,0,0,0,0,1], [0,0,1,0,0,1,1,1,0,0,0,0,1] ]; // Determine block size based on screen width const isMobile = window.innerWidth <= 768; const isTablet = window.innerWidth <= 1024 && window.innerWidth > 768; let blockSize, spacing; if(isMobile) { blockSize = 18; spacing = blockSize + 3; } else if(isTablet) { blockSize = 30; spacing = blockSize + 4; } else { blockSize = 40; spacing = blockSize + 5; } // Generate blocks from pattern pattern.forEach((row, y) => { row.forEach((cell, x) => { if(cell === 1) { const block = document.createElement('div'); block.className = 'gd-block'; block.style.width = blockSize + 'px'; block.style.height = blockSize + 'px'; block.style.left = (x * spacing - spacing * 6.5) + 'px'; block.style.top = (y * spacing - spacing * 2.5) + 'px'; blockContainer.appendChild(block); blocks.push(block); totalBlocks++; } }); }); totalDisplay.textContent = totalBlocks; // Create particle effect function createParticle(x, y, color) { const particle = document.createElement('div'); particle.className = 'gd-particle'; particle.style.left = x + 'px'; particle.style.top = y + 'px'; particle.style.background = color; gameArea.appendChild(particle); gsap.to(particle, { physics2D: { velocity: gsap.utils.random(100, 400), angle: gsap.utils.random(-180, 0), gravity: 600 }, opacity: 0, scale: 0.5, duration: 2, onComplete: () => particle.remove() }); } // Show combo display function showCombo() { if(comboCount > 1) { comboDisplay.textContent = `${comboCount}x COMBO!`; gsap.fromTo(comboDisplay, { opacity: 1, scale: 0.5, y: 0 }, { scale: 1.2, y: -30, duration: 0.5, ease: "back.out(1.7)", onComplete: () => { gsap.to(comboDisplay, { opacity: 0, scale: 0.8, duration: 0.3 }); } }); } } // Check collision between ball and blocks function checkCollision(ball) { const ballRect = ball.getBoundingClientRect(); let hitThisFrame = false; blocks.forEach((block, index) => { if(!block.dataset.destroyed) { const blockRect = block.getBoundingClientRect(); if(ballRect.left < blockRect.right && ballRect.right > blockRect.left && ballRect.top < blockRect.bottom && ballRect.bottom > blockRect.top) { block.dataset.destroyed = 'true'; hitThisFrame = true; // Enhanced particle explosion for(let i = 0; i < 8; i++) { createParticle( blockRect.left + blockRect.width/2, blockRect.top + blockRect.height/2, ['#AD24A6', '#ff69b4', '#444', '#666'][Math.floor(Math.random() * 4)] ); } // Animate block destruction gsap.to(block, { scale: 0, opacity: 0, rotation: gsap.utils.random(-180, 180), duration: 0.4, ease: "power2.in", onComplete: () => block.remove() }); destroyedBlocks++; countDisplay.textContent = destroyedBlocks; // Combo system comboCount++; clearTimeout(comboTimer); comboTimer = setTimeout(() => { showCombo(); comboCount = 0; }, 300); // Check for game completion if(destroyedBlocks === totalBlocks) { const efficiency = Math.round((totalBlocks / ballsUsed) * 100); ballsDisplay.textContent = ballsUsed; efficiencyDisplay.textContent = efficiency + '%'; setTimeout(() => { completeScreen.classList.add('show'); }, 500); } } } }); } // Game click handler gameArea.addEventListener('click', (e) => { const rect = gameArea.getBoundingClientRect(); const x = e.clientX - rect.left; const y = 50; const isMobile = window.innerWidth <= 768; ballsUsed++; // Show click indicator clickIndicator.style.left = x + 'px'; clickIndicator.style.top = e.clientY - rect.top + 'px'; gsap.fromTo(clickIndicator, { opacity: 1, scale: 0.5 }, { opacity: 0, scale: 1.5, duration: 0.5, ease: "power2.out" }); // Create ball const ballSize = isMobile ? 22 : 30; const ball = document.createElement('div'); ball.className = 'gd-ball'; ball.style.left = (x - ballSize/2) + 'px'; ball.style.top = y + 'px'; gameArea.appendChild(ball); // Apply physics to ball gsap.to(ball, { physics2D: { velocity: 0, angle: 90, gravity: 800 }, duration: 5, onUpdate: function() { checkCollision(ball); }, onComplete: () => ball.remove() }); // Squeeze animation on drop gsap.to(ball, { scaleY: 0.8, scaleX: 1.2, duration: 0.1, yoyo: true, repeat: 1, ease: "power2.inOut" }); }); // Prevent zooming on mobile double-tap let lastTouchEnd = 0; document.addEventListener('touchend', (e) => { const now = (new Date()).getTime(); if (now - lastTouchEnd <= 300) { e.preventDefault(); } lastTouchEnd = now; }, false); })(); </script> <!-- JAVASCRIPT SECTION END --> </div>

How to edit code using AI →
Resource Details:
404 Game transforms the frustration of landing on a broken link into an engaging mini-game experience that keeps visitors on your site. Instead of losing users to a standard error page, entertain them with interactive games ranging from simple click adventures to retro arcade classics, turning a potential bounce into extended engagement. While it's admittedly a playful gimmick, these unexpected moments of fun create memorable brand experiences and give users a reason to explore more of your site. Includes high score tracking, customizable game themes, and easy integration with fallback navigation options.

NO-ACCESS
Only for Desktop Users
This page is only available on desktop.
Please Log in on a desktop to gain access.