Skip to content

Commit 8b16163

Browse files
Enhance coin flip game with prediction and score system
1 parent bea8fb6 commit 8b16163

2 files changed

Lines changed: 385 additions & 271 deletions

File tree

web-app/js/projects.js

Lines changed: 2 additions & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Project Registry
1+
// Project Registry
22
// Each project's HTML and logic lives in its own file under js/projects/
33

44

@@ -339,229 +339,7 @@ function initDiceRolling() {
339339
// ============================================
340340
// COIN FLIP
341341
// ============================================
342-
function getCoinFlipHTML() {
343-
return `
344-
<div class="project-content">
345-
<h2>🪙 Coin Flip</h2>
346-
<div class="coin-container">
347-
<div class="coin-scene">
348-
<div class="coin" id="coin">
349-
<div class="coin-face heads">👑</div>
350-
<div class="coin-edge"></div>
351-
<div class="coin-face tails">🦅</div>
352-
</div>
353-
<div class="coin-shadow"></div>
354-
</div>
355-
356-
<div class="coin-result" id="coinResult">Click to Flip!</div>
357-
358-
<button class="btn-flip" id="flipCoin">Flip Coin</button>
359-
360-
<div class="coin-stats">
361-
<div class="stat-item">
362-
<span>Heads:</span>
363-
<span id="headsCount">0</span>
364-
</div>
365-
<div class="stat-item">
366-
<span>Tails:</span>
367-
<span id="tailsCount">0</span>
368-
</div>
369-
</div>
370-
</div>
371-
</div>
372-
373-
<style>
374-
.coin-container {
375-
text-align: center;
376-
padding: 3rem 2rem;
377-
}
378-
379-
.coin-scene {
380-
position: relative;
381-
width: 170px;
382-
height: 205px;
383-
perspective: 900px;
384-
margin: 1rem auto 2rem;
385-
transform-origin: center bottom;
386-
}
387-
388-
.coin {
389-
--flip-x: 0deg;
390-
--flip-y: 0deg;
391-
width: 170px;
392-
height: 170px;
393-
position: relative;
394-
transform-style: preserve-3d;
395-
transform: rotateX(var(--flip-x)) rotateY(var(--flip-y));
396-
transition: transform 1.6s cubic-bezier(0.2, 0.8, 0.15, 1);
397-
}
398-
399-
.coin-face {
400-
position: absolute;
401-
width: 100%;
402-
height: 100%;
403-
backface-visibility: hidden;
404-
display: flex;
405-
align-items: center;
406-
justify-content: center;
407-
font-size: 6rem;
408-
background: radial-gradient(circle at 35% 30%, #fff5a6, #ffd54f 45%, #e1a600 100%);
409-
border-radius: 50%;
410-
border: 5px solid #d79e00;
411-
box-shadow: inset -6px -8px 10px rgba(0, 0, 0, 0.22), inset 6px 8px 12px rgba(255, 255, 255, 0.45), 0 12px 25px rgba(0, 0, 0, 0.35);
412-
}
413-
414-
.heads { transform: translateZ(8px); }
415-
416-
.tails {
417-
transform: rotateY(180deg) translateZ(8px);
418-
}
419-
420-
.coin-edge {
421-
position: absolute;
422-
width: 100%;
423-
height: 100%;
424-
border-radius: 50%;
425-
border: 8px solid #b8860b;
426-
transform: translateZ(0);
427-
box-shadow: inset 0 0 0 2px rgba(255, 232, 145, 0.35);
428-
}
429-
430-
.coin-shadow {
431-
position: absolute;
432-
left: 50%;
433-
bottom: 6px;
434-
width: 110px;
435-
height: 16px;
436-
transform: translateX(-50%);
437-
border-radius: 50%;
438-
background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.42) 0%, rgba(0, 0, 0, 0.08) 72%, transparent 100%);
439-
}
440-
441-
.coin-scene.rolling .coin-shadow {
442-
animation: coinShadowFloat 1.6s ease;
443-
}
444-
445-
.coin-scene.impact {
446-
animation: coinLanding 0.45s ease-out;
447-
}
448-
449-
.coin-scene.impact .coin-shadow {
450-
animation: coinShadowImpact 0.45s ease-out;
451-
}
452-
453-
.coin-result {
454-
font-size: 2rem;
455-
font-weight: bold;
456-
margin: 2rem 0;
457-
min-height: 3rem;
458-
}
459-
460-
.btn-flip {
461-
background: linear-gradient(135deg, #ffd700, #ffed4e);
462-
color: #333;
463-
border: none;
464-
padding: 1rem 3rem;
465-
border-radius: 50px;
466-
font-size: 1.3rem;
467-
font-weight: bold;
468-
cursor: pointer;
469-
transition: var(--transition);
470-
}
471-
472-
.btn-flip:hover {
473-
transform: scale(1.05);
474-
box-shadow: 0 5px 20px rgba(255, 215, 0, 0.4);
475-
}
476-
477-
.coin-stats {
478-
display: flex;
479-
gap: 3rem;
480-
justify-content: center;
481-
margin-top: 2rem;
482-
font-size: 1.2rem;
483-
}
484-
485-
.stat-item {
486-
display: flex;
487-
gap: 1rem;
488-
align-items: center;
489-
}
490-
491-
@keyframes coinLanding {
492-
0% { transform: translateY(-12px); }
493-
55% { transform: translateY(5px); }
494-
82% { transform: translateY(-2px); }
495-
100% { transform: translateY(0); }
496-
}
497-
498-
@keyframes coinShadowFloat {
499-
0%, 100% { transform: translateX(-50%) scale(1); opacity: 0.4; }
500-
45% { transform: translateX(-50%) scale(0.68); opacity: 0.2; }
501-
}
502-
503-
@keyframes coinShadowImpact {
504-
0% { transform: translateX(-50%) scale(0.72); opacity: 0.2; }
505-
55% { transform: translateX(-50%) scale(1.12); opacity: 0.44; }
506-
100% { transform: translateX(-50%) scale(1); opacity: 0.4; }
507-
}
508-
</style>
509-
`;
510-
}
511-
512-
function initCoinFlip() {
513-
const coin = document.getElementById('coin');
514-
const coinScene = coin.closest('.coin-scene');
515-
const flipBtn = document.getElementById('flipCoin');
516-
const result = document.getElementById('coinResult');
517-
const headsCountEl = document.getElementById('headsCount');
518-
const tailsCountEl = document.getElementById('tailsCount');
519-
let headsCount = 0;
520-
let tailsCount = 0;
521-
let spinCount = 0;
522-
523-
function setCoinFace(isHeads, seed) {
524-
const targetY = isHeads ? 0 : 180;
525-
const flipX = 360 * (4 + (seed % 3));
526-
const flipY = 360 * (3 + (seed % 2)) + targetY;
527-
coin.style.setProperty('--flip-x', `${flipX}deg`);
528-
coin.style.setProperty('--flip-y', `${flipY}deg`);
529-
}
530-
531-
function triggerCoinLanding() {
532-
coinScene.classList.remove('impact');
533-
void coinScene.offsetWidth;
534-
coinScene.classList.add('impact');
535-
setTimeout(() => {
536-
coinScene.classList.remove('impact');
537-
}, 460);
538-
}
539-
540-
flipBtn.addEventListener('click', () => {
541-
flipBtn.disabled = true;
542-
result.textContent = 'Flipping...';
543-
coinScene.classList.add('rolling');
544-
545-
const isHeads = Math.random() < 0.5;
546-
spinCount += 1;
547-
setCoinFace(isHeads, spinCount);
548-
549-
setTimeout(() => {
550-
coinScene.classList.remove('rolling');
551-
triggerCoinLanding();
552-
if (isHeads) {
553-
result.textContent = '👑 Heads!';
554-
headsCount++;
555-
headsCountEl.textContent = headsCount;
556-
} else {
557-
result.textContent = '🦅 Tails!';
558-
tailsCount++;
559-
tailsCountEl.textContent = tailsCount;
560-
}
561-
flipBtn.disabled = false;
562-
}, 1600);
563-
});
564-
}
342+
// (Coin Flip HTML & Logic loaded from modular file js/projects/coin-flip.js)
565343

566344
// Continue with more projects in next message...
567345
// Additional Project Implementations

0 commit comments

Comments
 (0)