A Pen by fgouin2014 on CodePen.
Created
July 20, 2024 12:23
-
-
Save fgouin2014/15cf9fd028bec15c948ebdd95be2a3ff to your computer and use it in GitHub Desktop.
Green Counter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="fr"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Scoreboard VFD</title> | |
<style> | |
body { | |
background-color: #000; | |
color: #00ffcc; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
height: 100vh; | |
margin: 0; | |
font-family: monospace; | |
} | |
.scoreboard-container { | |
width: 80%; | |
max-width: 1200px; | |
margin: 20px auto; | |
padding: 20px; | |
border: 2px solid #00ffcc; | |
border-radius: 10px; | |
box-shadow: 0 0 10px rgba(0, 255, 204, 0.5); | |
background-color: #222; | |
overflow: hidden; | |
display: flex; | |
flex-wrap: wrap; | |
justify-content: space-around; | |
align-items: center; | |
} | |
.stat { | |
flex: 1 0 calc(25% - 20px); | |
text-align: center; | |
margin: 10px; | |
} | |
.led-score { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
flex-wrap: nowrap; | |
gap: 5px; | |
width: 100%; | |
} | |
.led-block { | |
width: 60%; | |
height: 50px; | |
position: relative; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
background-color: #222; | |
border: 1px solid #00ffcc; | |
overflow: hidden; | |
} | |
canvas { | |
width: 100%; | |
height: 100%; | |
font-size: calc(100% + 1vw); | |
text-align: center; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="scoreboard-container"> | |
<div class="stat"> | |
<span class="stat-title">High-Score:</span> | |
<div class="led-score high-score"> | |
<canvas class="led-block high-score-canvas"></canvas> | |
<canvas class="led-block high-score-canvas"></canvas> | |
<canvas class="led-block high-score-canvas"></canvas> | |
<canvas class="led-block high-score-canvas"></canvas> | |
<canvas class="led-block high-score-canvas"></canvas> | |
</div> | |
</div> | |
<div class="stat"> | |
<span class="stat-title">Score actuel:</span> | |
<div class="led-score current-score"> | |
<canvas class="led-block current-score-canvas"></canvas> | |
<canvas class="led-block current-score-canvas"></canvas> | |
<canvas class="led-block current-score-canvas"></canvas> | |
<canvas class="led-block current-score-canvas"></canvas> | |
<canvas class="led-block current-score-canvas"></canvas> | |
</div> | |
</div> | |
<div class="stat"> | |
<span class="stat-title">Nombre d'essais:</span> | |
<div class="led-score error-count"> | |
<canvas class="led-block error-count-canvas"></canvas> | |
<canvas class="led-block error-count-canvas"></canvas> | |
<canvas class="led-block error-count-canvas"></canvas> | |
</div> | |
</div> | |
<div class="stat"> | |
<span class="stat-title">Temps écoulé:</span> | |
<div class="led-score elapsed-time"> | |
<canvas class="led-block elapsed-time-canvas"></canvas></span>.</span> | |
<canvas class="led-block elapsed-time-canvas"></canvas> | |
<canvas class="led-block elapsed-time-canvas"></canvas> | |
</div> | |
</div> | |
</div> | |
<script> | |
const highScoreCanvas = document.querySelectorAll('.high-score-canvas'); | |
const currentScoreCanvas = document.querySelectorAll('.current-score-canvas'); | |
const errorCountCanvas = document.querySelectorAll('.error-count-canvas'); | |
const elapsedTimeCanvas = document.querySelectorAll('.elapsed-time-canvas'); | |
let highScore = 99999; | |
let currentScore = 0; | |
let errorCount = 0; | |
let elapsedTime = 5.00; // Initial countdown value in seconds | |
function drawVFDSquare(ctx, character) { | |
const rectWidth = ctx.canvas.width; | |
const rectHeight = ctx.canvas.height; | |
ctx.clearRect(0, 0, rectWidth, rectHeight); // Clear the canvas | |
ctx.fillStyle = '#00ffcc'; | |
ctx.textBaseline = 'middle'; | |
ctx.textAlign = 'center'; | |
const fontSize = Math.min(rectWidth / 2.5, rectHeight * 0.8); | |
ctx.font = `${fontSize}px monospace`; | |
const textX = rectWidth / 2; | |
const textY = rectHeight / 2; | |
ctx.fillText(character, textX, textY); | |
} | |
function drawScanlines(ctx) { | |
const rectWidth = ctx.canvas.width; | |
const rectHeight = ctx.canvas.height; | |
const scanlineThickness = 1; | |
const scanlineSpacing = 2; | |
ctx.fillStyle = 'rgba(0, 255, 204, 0.5)'; | |
for (let i = 0; i < rectHeight; i += scanlineSpacing) { | |
ctx.fillRect(0, i, rectWidth, scanlineThickness); | |
} | |
} | |
function updateHighScore() { | |
const scores = highScore.toString().padStart(5, '0').split(''); | |
highScoreCanvas.forEach((canvas, index) => { | |
const ctx = canvas.getContext('2d'); | |
drawVFDSquare(ctx, scores[index]); | |
drawScanlines(ctx); | |
}); | |
} | |
function updateCurrentScore() { | |
currentScore++; | |
const scores = currentScore.toString().padStart(5, '0').split(''); | |
currentScoreCanvas.forEach((canvas, index) => { | |
const ctx = canvas.getContext('2d'); | |
drawVFDSquare(ctx, scores[index]); | |
drawScanlines(ctx); | |
}); | |
} | |
function updateErrorCount() { | |
errorCount++; | |
const errors = '☠'.repeat(errorCount > 3 ? 3 : errorCount).split(''); | |
errorCountCanvas.forEach((canvas, index) => { | |
const ctx = canvas.getContext('2d'); | |
drawVFDSquare(ctx, errors[index] || ' '); | |
drawScanlines(ctx); | |
}); | |
} | |
function updateElapsedTime() { | |
elapsedTime -= 0.01; // Reduce elapsed time by 0.01 second | |
if (elapsedTime <= 0) { | |
elapsedTime = 0.00; // Set elapsed time to 0.00 when countdown ends | |
errorCount = 0; // Reset error count when time resets | |
} | |
const timeFormatted = elapsedTime.toFixed(2).replace('.', '').split(''); // Remove dot from time string | |
elapsedTimeCanvas.forEach((canvas, index) => { | |
const ctx = canvas.getContext('2d'); | |
drawVFDSquare(ctx, timeFormatted[index] || '0'); | |
drawScanlines(ctx); | |
}); | |
} | |
// Initial update | |
updateHighScore(); | |
updateCurrentScore(); | |
updateErrorCount(); | |
updateElapsedTime(); | |
// Simulation intervals | |
const highScoreInterval = setInterval(updateHighScore, 5000); // Simulate high score update every 5 seconds | |
const currentScoreInterval = setInterval(updateCurrentScore, 100); // Simulate current score increment every 100 milliseconds | |
const errorCountInterval = setInterval(updateErrorCount, 2000); // Simulate error count update every 2 seconds | |
const elapsedTimeInterval = setInterval(updateElapsedTime, 10); // Simulate elapsed time update every 10 milliseconds | |
// Stop intervals after 5 seconds | |
setTimeout(() => { | |
clearInterval(highScoreInterval); | |
clearInterval(currentScoreInterval); | |
clearInterval(errorCountInterval); | |
clearInterval(elapsedTimeInterval); | |
}, 5000); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link href="https://rs-sv1-03.vercel.app/fonts.css" rel="stylesheet" /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment