WEBLEB
Accueil
Éditeur
Connexion
Pro
Français
English
Français
Español
HTML
CSS
JS
City Smash 2D Mini Sandbox
CITY SMASH SANDBOX
Click and drag across the buildings to smash them!
Rebuild City
* { margin: 0; padding: 0; box-sizing: border-box; user-select: none; } body { background: #0a0a16; overflow: hidden; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #fff; } #ui { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); text-align: center; pointer-events: none; z-index: 10; } h1 { font-size: 2rem; letter-spacing: 2px; text-shadow: 0 0 10px #ff3366; margin-bottom: 5px; } p { font-size: 0.9rem; opacity: 0.7; margin-bottom: 15px; } button { background: #ff3366; color: white; border: none; padding: 10px 20px; font-weight: bold; border-radius: 5px; cursor: pointer; pointer-events: auto; transition: 0.2s ease; } button:hover { background: #ff5588; box-shadow: 0 0 15px #ff3366; } canvas { display: block; width: 100vw; height: 100vh; }
const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const resetBtn = document.getElementById('resetBtn'); // Setup Canvas Size function resize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } window.addEventListener('resize', resize); resize(); // Game objects let blocks = []; let particles = []; let isSmashing = false; // Block Class representing building structural segments class Block { constructor(x, y, width, height, color) { this.x = x; this.y = y; this.width = width; this.height = height; this.color = color; this.alive = true; } draw() { if (!this.alive) return; ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.width, this.height); // Add tiny windows layout inside the buildings ctx.fillStyle = 'rgba(255, 255, 150, 0.4)'; for (let wx = 5; wx < this.width - 5; wx += 12) { for (let wy = 5; wy < this.height - 5; wy += 15) { ctx.fillRect(this.x + wx, this.y + wy, 5, 8); } } } } // Particle Class for demolition explosion effects class Particle { constructor(x, y, color) { this.x = x; this.y = y; this.vx = (Math.random() - 0.5) * 8; this.vy = (Math.random() - 0.5) * 8 - 3; // slight upward drift this.color = color; this.alpha = 1; this.gravity = 0.2; } update() { this.x += this.vx; this.y += this.vy; this.vy += this.gravity; this.alpha -= 0.02; } draw() { ctx.save(); ctx.globalAlpha = this.alpha; ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, 4, 4); ctx.restore(); } } // Generate Skyline function initCity() { blocks = []; particles = []; const blockWidth = 40; const blockHeight = 30; const totalWidth = canvas.width; // Spawn multiple adjacent buildings for (let x = 50; x < totalWidth - 80; x += 70) { const buildingWidth = 60; const buildingHeight = Math.floor(Math.random() * 10) + 5; // Rows high const hue = Math.floor(Math.random() * 40) + 200; // City blues/purples const color = `hsl(${hue}, 40%, 30%)`; for (let row = 0; row < buildingHeight; row++) { const bx = x; const by = canvas.height - (row * blockHeight) - blockHeight; blocks.push(new Block(bx, buildingWidth, blockWidth, blockHeight, color)); } } } // Smash Function function checkSmash(mx, my) { blocks.forEach(block => { if (block.alive && mx > block.x && mx < block.x + block.width && my > block.y && my < block.y + block.height) { block.alive = false; // Spawn fire and debris particles for (let i = 0; i < 15; i++) { particles.push(new Particle(block.x + block.width/2, block.y + block.height/2, block.color)); particles.push(new Particle(block.x + block.width/2, block.y + block.height/2, '#ff5500')); // fire debris } } }); } // Mouse and Touch Interaction Handlers window.addEventListener('mousedown', (e) => { isSmashing = true; checkSmash(e.clientX, e.clientY); }); window.addEventListener('mousemove', (e) => { if (isSmashing) checkSmash(e.clientX, e.clientY); }); window.addEventListener('mouseup', () => isSmashing = false); window.addEventListener('touchstart', (e) => { isSmashing = true; checkSmash(e.touches[0].clientX, e.touches[0].clientY); }); window.addEventListener('touchmove', (e) => { if (isSmashing) checkSmash(e.touches[0].clientX, e.touches[0].clientY); }); window.addEventListener('touchend', () => isSmashing = false); resetBtn.addEventListener('click', initCity); // Simulation Loop function animate() { ctx.fillStyle = 'rgba(10, 10, 22, 0.3)'; // creates motion blur trail effect ctx.fillRect(0, 0, canvas.width, canvas.height); // Draw Ground ctx.fillStyle = '#111125'; ctx.fillRect(0, canvas.height - 10, canvas.width, 10); // Render Assets blocks.forEach(block => block.draw()); particles.forEach((particle, index) => { particle.update(); particle.draw(); if (particle.alpha <= 0) particles.splice(index, 1); }); requestAnimationFrame(animate); } // Start Game initCity(); animate();
Preview
Open Advanced Editor
Publish Code
Full Screen
HTML
CSS
JS
City Smash 2D Mini Sandbox
CITY SMASH SANDBOX
Click and drag across the buildings to smash them!
Rebuild City
* { margin: 0; padding: 0; box-sizing: border-box; user-select: none; } body { background: #0a0a16; overflow: hidden; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #fff; } #ui { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); text-align: center; pointer-events: none; z-index: 10; } h1 { font-size: 2rem; letter-spacing: 2px; text-shadow: 0 0 10px #ff3366; margin-bottom: 5px; } p { font-size: 0.9rem; opacity: 0.7; margin-bottom: 15px; } button { background: #ff3366; color: white; border: none; padding: 10px 20px; font-weight: bold; border-radius: 5px; cursor: pointer; pointer-events: auto; transition: 0.2s ease; } button:hover { background: #ff5588; box-shadow: 0 0 15px #ff3366; } canvas { display: block; width: 100vw; height: 100vh; }
const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const resetBtn = document.getElementById('resetBtn'); // Setup Canvas Size function resize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } window.addEventListener('resize', resize); resize(); // Game objects let blocks = []; let particles = []; let isSmashing = false; // Block Class representing building structural segments class Block { constructor(x, y, width, height, color) { this.x = x; this.y = y; this.width = width; this.height = height; this.color = color; this.alive = true; } draw() { if (!this.alive) return; ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.width, this.height); // Add tiny windows layout inside the buildings ctx.fillStyle = 'rgba(255, 255, 150, 0.4)'; for (let wx = 5; wx < this.width - 5; wx += 12) { for (let wy = 5; wy < this.height - 5; wy += 15) { ctx.fillRect(this.x + wx, this.y + wy, 5, 8); } } } } // Particle Class for demolition explosion effects class Particle { constructor(x, y, color) { this.x = x; this.y = y; this.vx = (Math.random() - 0.5) * 8; this.vy = (Math.random() - 0.5) * 8 - 3; // slight upward drift this.color = color; this.alpha = 1; this.gravity = 0.2; } update() { this.x += this.vx; this.y += this.vy; this.vy += this.gravity; this.alpha -= 0.02; } draw() { ctx.save(); ctx.globalAlpha = this.alpha; ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, 4, 4); ctx.restore(); } } // Generate Skyline function initCity() { blocks = []; particles = []; const blockWidth = 40; const blockHeight = 30; const totalWidth = canvas.width; // Spawn multiple adjacent buildings for (let x = 50; x < totalWidth - 80; x += 70) { const buildingWidth = 60; const buildingHeight = Math.floor(Math.random() * 10) + 5; // Rows high const hue = Math.floor(Math.random() * 40) + 200; // City blues/purples const color = `hsl(${hue}, 40%, 30%)`; for (let row = 0; row < buildingHeight; row++) { const bx = x; const by = canvas.height - (row * blockHeight) - blockHeight; blocks.push(new Block(bx, buildingWidth, blockWidth, blockHeight, color)); } } } // Smash Function function checkSmash(mx, my) { blocks.forEach(block => { if (block.alive && mx > block.x && mx < block.x + block.width && my > block.y && my < block.y + block.height) { block.alive = false; // Spawn fire and debris particles for (let i = 0; i < 15; i++) { particles.push(new Particle(block.x + block.width/2, block.y + block.height/2, block.color)); particles.push(new Particle(block.x + block.width/2, block.y + block.height/2, '#ff5500')); // fire debris } } }); } // Mouse and Touch Interaction Handlers window.addEventListener('mousedown', (e) => { isSmashing = true; checkSmash(e.clientX, e.clientY); }); window.addEventListener('mousemove', (e) => { if (isSmashing) checkSmash(e.clientX, e.clientY); }); window.addEventListener('mouseup', () => isSmashing = false); window.addEventListener('touchstart', (e) => { isSmashing = true; checkSmash(e.touches[0].clientX, e.touches[0].clientY); }); window.addEventListener('touchmove', (e) => { if (isSmashing) checkSmash(e.touches[0].clientX, e.touches[0].clientY); }); window.addEventListener('touchend', () => isSmashing = false); resetBtn.addEventListener('click', initCity); // Simulation Loop function animate() { ctx.fillStyle = 'rgba(10, 10, 22, 0.3)'; // creates motion blur trail effect ctx.fillRect(0, 0, canvas.width, canvas.height); // Draw Ground ctx.fillStyle = '#111125'; ctx.fillRect(0, canvas.height - 10, canvas.width, 10); // Render Assets blocks.forEach(block => block.draw()); particles.forEach((particle, index) => { particle.update(); particle.draw(); if (particle.alpha <= 0) particles.splice(index, 1); }); requestAnimationFrame(animate); } // Start Game initCity(); animate();
Preview
Validating your code, please wait...