ludo-salenne / index.html
LudoSLN's picture
Add 2 files
f4beac0 verified
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>200K Brick Breaker - YouTube Celebration</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap');
body {
font-family: 'Poppins', sans-serif;
background: linear-gradient(135deg, #1a1a2e, #16213e);
overflow: hidden;
}
#gameCanvas {
box-shadow: 0 0 30px rgba(0, 150, 255, 0.5);
border-radius: 10px;
}
.brick {
transition: all 0.2s ease;
}
.brick-hit {
animation: hit 0.3s ease;
}
@keyframes hit {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.confetti {
position: absolute;
width: 10px;
height: 10px;
background-color: #f00;
border-radius: 50%;
pointer-events: none;
}
</style>
</head>
<body class="min-h-screen flex flex-col items-center justify-center text-white">
<div class="text-center mb-6">
<h1 class="text-4xl font-bold mb-2 bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-600">
Brick Breaker 200K
</h1>
<p class="text-lg text-blue-200">Cassez les briques pour célébrer nos 200 000 abonnés !</p>
</div>
<div class="relative">
<canvas id="gameCanvas" width="800" height="500" class="bg-gray-900 border-2 border-blue-500"></canvas>
<div id="startScreen" class="absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-70">
<div class="text-center p-8 rounded-xl bg-gray-800 border border-blue-500 max-w-md">
<i class="fas fa-gamepad text-5xl text-blue-400 mb-4"></i>
<h2 class="text-2xl font-bold mb-4">Brick Breaker 200K</h2>
<p class="mb-6">Utilisez les flèches ou la souris pour déplacer la raquette et cassez toutes les briques !</p>
<button id="startButton" class="px-6 py-3 bg-gradient-to-r from-blue-500 to-purple-600 rounded-full font-bold hover:from-blue-600 hover:to-purple-700 transition-all transform hover:scale-105 shadow-lg">
COMMENCER LE JEU
</button>
</div>
</div>
<div id="gameOverScreen" class="absolute inset-0 hidden flex-col items-center justify-center bg-black bg-opacity-70">
<div class="text-center p-8 rounded-xl bg-gray-800 border border-blue-500 max-w-md">
<i class="fas fa-trophy text-5xl text-yellow-400 mb-4"></i>
<h2 id="resultTitle" class="text-2xl font-bold mb-2">Félicitations !</h2>
<p id="resultMessage" class="mb-4">Vous avez cassé toutes les briques des 200K abonnés !</p>
<div class="flex justify-center space-x-4">
<button id="restartButton" class="px-4 py-2 bg-blue-500 rounded-full font-bold hover:bg-blue-600 transition">
Rejouer
</button>
<button id="shareButton" class="px-4 py-2 bg-purple-500 rounded-full font-bold hover:bg-purple-600 transition">
<i class="fas fa-share mr-2"></i>Partager
</button>
</div>
</div>
</div>
</div>
<div class="mt-6 flex items-center space-x-8">
<div class="flex items-center space-x-2">
<i class="fas fa-heart text-red-500"></i>
<span id="lives">3</span>
</div>
<div class="flex items-center space-x-2">
<i class="fas fa-bolt text-yellow-400"></i>
<span id="score">0</span>
</div>
<div class="flex items-center space-x-2">
<i class="fas fa-layer-group text-blue-400"></i>
<span id="level">1</span>
</div>
</div>
<div class="mt-8 text-center text-blue-300">
<p>Merci à nos 200 000 abonnés ! Abonnez-vous pour plus de jeux amusants.</p>
<div class="mt-2 flex justify-center space-x-4">
<button class="px-4 py-2 bg-red-600 rounded-full font-bold hover:bg-red-700 transition flex items-center">
<i class="fab fa-youtube mr-2"></i> YouTube
</button>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Canvas setup
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Game elements
const paddle = {
width: 100,
height: 15,
x: canvas.width / 2 - 50,
speed: 8,
isMoving: false,
direction: 0
};
const ball = {
x: canvas.width / 2,
y: canvas.height - 30,
radius: 8,
dx: 4,
dy: -4,
speed: 4
};
// Game state
let lives = 3;
let score = 0;
let level = 1;
let gameRunning = false;
let bricks = [];
let brickRowCount = 5;
let brickColumnCount = 10;
let brickWidth = 75;
let brickHeight = 20;
let brickPadding = 10;
let brickOffsetTop = 60;
let brickOffsetLeft = 30;
// DOM elements
const livesDisplay = document.getElementById('lives');
const scoreDisplay = document.getElementById('score');
const levelDisplay = document.getElementById('level');
const startScreen = document.getElementById('startScreen');
const gameOverScreen = document.getElementById('gameOverScreen');
const startButton = document.getElementById('startButton');
const restartButton = document.getElementById('restartButton');
const shareButton = document.getElementById('shareButton');
const resultTitle = document.getElementById('resultTitle');
const resultMessage = document.getElementById('resultMessage');
// Initialize bricks
function initBricks() {
bricks = [];
const colors = ['#FF5252', '#FFD740', '#69F0AE', '#40C4FF', '#E040FB'];
for (let c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for (let r = 0; r < brickRowCount; r++) {
const brickX = c * (brickWidth + brickPadding) + brickOffsetLeft;
const brickY = r * (brickHeight + brickPadding) + brickOffsetTop;
const colorIndex = Math.floor(Math.random() * colors.length);
bricks[c][r] = {
x: brickX,
y: brickY,
status: 1,
color: colors[colorIndex],
hit: false
};
}
}
}
// Draw paddle
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddle.x, canvas.height - paddle.height, paddle.width, paddle.height);
ctx.fillStyle = '#3D5AFE';
ctx.fill();
ctx.closePath();
// Add gradient effect
const gradient = ctx.createLinearGradient(paddle.x, 0, paddle.x + paddle.width, 0);
gradient.addColorStop(0, '#3D5AFE');
gradient.addColorStop(1, '#2962FF');
ctx.fillStyle = gradient;
ctx.fill();
// Add shine effect
ctx.beginPath();
ctx.moveTo(paddle.x + 5, canvas.height - paddle.height);
ctx.lineTo(paddle.x + paddle.width - 5, canvas.height - paddle.height);
ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
ctx.lineWidth = 2;
ctx.stroke();
}
// Draw ball
function drawBall() {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
// Add gradient to ball
const gradient = ctx.createRadialGradient(
ball.x - ball.radius / 3,
ball.y - ball.radius / 3,
ball.radius / 3,
ball.x,
ball.y,
ball.radius
);
gradient.addColorStop(0, '#FFFFFF');
gradient.addColorStop(1, '#00B0FF');
ctx.fillStyle = gradient;
ctx.fill();
ctx.closePath();
// Add shine to ball
ctx.beginPath();
ctx.arc(ball.x - ball.radius / 3, ball.y - ball.radius / 3, ball.radius / 4, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.fill();
}
// Draw bricks
function drawBricks() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
if (bricks[c][r].status === 1) {
const brick = bricks[c][r];
// Draw brick with shadow
ctx.shadowColor = 'rgba(0, 0, 0, 0.3)';
ctx.shadowBlur = 5;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.beginPath();
ctx.rect(brick.x, brick.y, brickWidth, brickHeight);
ctx.fillStyle = brick.color;
ctx.fill();
// Reset shadow
ctx.shadowColor = 'transparent';
// Add highlight to brick
ctx.beginPath();
ctx.moveTo(brick.x, brick.y);
ctx.lineTo(brick.x + brickWidth, brick.y);
ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
ctx.lineWidth = 2;
ctx.stroke();
// Add "200K" text to some bricks
if (Math.random() > 0.7) {
ctx.font = 'bold 10px Arial';
ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
ctx.fillText('200K', brick.x + brickWidth/2 - 15, brick.y + brickHeight/2 + 3);
}
// Animation when hit
if (brick.hit) {
ctx.beginPath();
ctx.rect(brick.x + 2, brick.y + 2, brickWidth - 4, brickHeight - 4);
ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
ctx.fill();
brick.hit = false;
}
}
}
}
}
// Collision detection
function collisionDetection() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
const brick = bricks[c][r];
if (brick.status === 1) {
if (
ball.x + ball.radius > brick.x &&
ball.x - ball.radius < brick.x + brickWidth &&
ball.y + ball.radius > brick.y &&
ball.y - ball.radius < brick.y + brickHeight
) {
brick.hit = true;
ball.dy = -ball.dy;
brick.status = 0;
score += 10;
scoreDisplay.textContent = score;
createParticles(brick.x + brickWidth/2, brick.y + brickHeight/2, brick.color);
// Check if all bricks are cleared
if (checkLevelComplete()) {
levelComplete();
}
}
}
}
}
}
// Check if level is complete
function checkLevelComplete() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
if (bricks[c][r].status === 1) {
return false;
}
}
}
return true;
}
// Level complete
function levelComplete() {
level++;
levelDisplay.textContent = level;
// Increase difficulty
ball.speed += 0.5;
ball.dx = ball.dx > 0 ? ball.speed : -ball.speed;
ball.dy = -ball.speed;
// Reset ball and paddle
ball.x = canvas.width / 2;
ball.y = canvas.height - 30;
paddle.x = canvas.width / 2 - paddle.width / 2;
// Create new bricks
setTimeout(() => {
initBricks();
}, 1000);
}
// Create particles when brick is hit
function createParticles(x, y, color) {
const particleCount = 8;
for (let i = 0; i < particleCount; i++) {
const particle = document.createElement('div');
particle.className = 'confetti absolute';
particle.style.left = `${x}px`;
particle.style.top = `${y}px`;
particle.style.backgroundColor = color;
particle.style.width = `${Math.random() * 8 + 4}px`;
particle.style.height = particle.style.width;
particle.style.borderRadius = '50%';
document.body.appendChild(particle);
const angle = Math.random() * Math.PI * 2;
const velocity = Math.random() * 5 + 2;
const xVelocity = Math.cos(angle) * velocity;
const yVelocity = Math.sin(angle) * velocity;
let opacity = 1;
const fadeInterval = setInterval(() => {
opacity -= 0.05;
particle.style.opacity = opacity;
if (opacity <= 0) {
clearInterval(fadeInterval);
particle.remove();
}
}, 30);
let posX = x;
let posY = y;
const moveInterval = setInterval(() => {
posX += xVelocity;
posY += yVelocity;
yVelocity += 0.1; // gravity
particle.style.left = `${posX}px`;
particle.style.top = `${posY}px`;
if (opacity <= 0) {
clearInterval(moveInterval);
}
}, 30);
}
}
// Create celebration confetti
function createConfetti() {
const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff'];
const count = 150;
for (let i = 0; i < count; i++) {
const confetti = document.createElement('div');
confetti.className = 'confetti absolute';
confetti.style.left = `${Math.random() * window.innerWidth}px`;
confetti.style.top = `${-10}px`;
confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
confetti.style.width = `${Math.random() * 10 + 5}px`;
confetti.style.height = `${Math.random() * 10 + 5}px`;
confetti.style.borderRadius = Math.random() > 0.5 ? '50%' : '0';
confetti.style.transform = `rotate(${Math.random() * 360}deg)`;
document.body.appendChild(confetti);
const animationDuration = Math.random() * 3 + 2;
confetti.style.animation = `fall ${animationDuration}s linear forwards`;
// Add animation
const keyframes = `
@keyframes fall {
to {
transform: translateY(${window.innerHeight + 10}px) rotate(${Math.random() * 360}deg);
opacity: 0;
}
}
`;
const styleEl = document.createElement('style');
styleEl.innerHTML = keyframes;
document.head.appendChild(styleEl);
// Remove after animation
setTimeout(() => {
confetti.remove();
styleEl.remove();
}, animationDuration * 1000);
}
}
// Ball movement
function moveBall() {
// Wall collision (left/right)
if (ball.x + ball.dx > canvas.width - ball.radius || ball.x + ball.dx < ball.radius) {
ball.dx = -ball.dx;
}
// Wall collision (top)
if (ball.y + ball.dy < ball.radius) {
ball.dy = -ball.dy;
}
// Paddle collision
if (
ball.y + ball.dy > canvas.height - ball.radius - paddle.height &&
ball.x > paddle.x &&
ball.x < paddle.x + paddle.width
) {
// Calculate bounce angle based on where ball hits paddle
const hitPosition = (ball.x - (paddle.x + paddle.width / 2)) / (paddle.width / 2);
ball.dx = hitPosition * 5;
ball.dy = -Math.abs(ball.dy);
// Add effect to paddle
const gradient = ctx.createLinearGradient(paddle.x, 0, paddle.x + paddle.width, 0);
gradient.addColorStop(0, '#FF4081');
gradient.addColorStop(1, '#7C4DFF');
ctx.fillStyle = gradient;
}
// Bottom wall (lose life)
if (ball.y + ball.dy > canvas.height - ball.radius) {
if (lives > 0) {
lives--;
livesDisplay.textContent = lives;
// Reset ball and paddle
ball.x = canvas.width / 2;
ball.y = canvas.height - 30;
ball.dx = 4;
ball.dy = -4;
paddle.x = canvas.width / 2 - paddle.width / 2;
// Flash screen red
document.body.style.backgroundColor = '#ff0000';
setTimeout(() => {
document.body.style.backgroundColor = '';
}, 100);
} else {
gameOver(false);
}
}
ball.x += ball.dx;
ball.y += ball.dy;
}
// Paddle movement
function movePaddle() {
if (paddle.isMoving) {
paddle.x += paddle.direction * paddle.speed;
// Keep paddle within canvas
if (paddle.x < 0) {
paddle.x = 0;
} else if (paddle.x + paddle.width > canvas.width) {
paddle.x = canvas.width - paddle.width;
}
}
}
// Draw game
function draw() {
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw elements
drawBricks();
drawPaddle();
drawBall();
// Collision detection
collisionDetection();
// Move elements
moveBall();
movePaddle();
// Continue animation if game is running
if (gameRunning) {
requestAnimationFrame(draw);
}
}
// Start game
function startGame() {
lives = 3;
score = 0;
level = 1;
livesDisplay.textContent = lives;
scoreDisplay.textContent = score;
levelDisplay.textContent = level;
initBricks();
gameRunning = true;
startScreen.classList.add('hidden');
gameOverScreen.classList.add('hidden');
// Reset ball and paddle
ball.x = canvas.width / 2;
ball.y = canvas.height - 30;
ball.dx = 4;
ball.dy = -4;
ball.speed = 4;
paddle.x = canvas.width / 2 - paddle.width / 2;
draw();
}
// Game over
function gameOver(win) {
gameRunning = false;
if (win) {
resultTitle.textContent = "Félicitations !";
resultMessage.textContent = "Vous avez cassé toutes les briques des 200K abonnés !";
createConfetti();
} else {
resultTitle.textContent = "Game Over";
resultMessage.textContent = "Vous avez perdu toutes vos vies. Essayez encore !";
}
gameOverScreen.classList.remove('hidden');
}
// Event listeners
startButton.addEventListener('click', startGame);
restartButton.addEventListener('click', startGame);
shareButton.addEventListener('click', () => {
if (navigator.share) {
navigator.share({
title: '200K Brick Breaker',
text: `J'ai marqué ${score} points dans le jeu Brick Breaker 200K !`,
url: window.location.href
}).catch(console.error);
} else {
alert(`Partagez votre score de ${score} points sur les réseaux sociaux !`);
}
});
// Keyboard controls
document.addEventListener('keydown', (e) => {
if (e.key === 'Right' || e.key === 'ArrowRight') {
paddle.isMoving = true;
paddle.direction = 1;
} else if (e.key === 'Left' || e.key === 'ArrowLeft') {
paddle.isMoving = true;
paddle.direction = -1;
} else if (e.key === ' ' && !gameRunning && !startScreen.classList.contains('hidden')) {
startGame();
}
});
document.addEventListener('keyup', (e) => {
if (e.key === 'Right' || e.key === 'ArrowRight' || e.key === 'Left' || e.key === 'ArrowLeft') {
paddle.isMoving = false;
}
});
// Mouse/touch controls
canvas.addEventListener('mousemove', (e) => {
if (!gameRunning) return;
const relativeX = e.clientX - canvas.getBoundingClientRect().left;
if (relativeX > 0 && relativeX < canvas.width) {
paddle.x = relativeX - paddle.width / 2;
// Keep paddle within canvas
if (paddle.x < 0) {
paddle.x = 0;
} else if (paddle.x + paddle.width > canvas.width) {
paddle.x = canvas.width - paddle.width;
}
}
});
// Touch controls for mobile
canvas.addEventListener('touchmove', (e) => {
if (!gameRunning) return;
e.preventDefault();
const touch = e.touches[0];
const relativeX = touch.clientX - canvas.getBoundingClientRect().left;
if (relativeX > 0 && relativeX < canvas.width) {
paddle.x = relativeX - paddle.width / 2;
// Keep paddle within canvas
if (paddle.x < 0) {
paddle.x = 0;
} else if (paddle.x + paddle.width > canvas.width) {
paddle.x = canvas.width - paddle.width;
}
}
});
// Initialize game
initBricks();
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=LudoSLN/ludo-salenne" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>