1150 lines
35 KiB
HTML
1150 lines
35 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="nl">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>LAUPAN LUCHCD PEILTJUS</title>
|
||
<link rel="icon" href="data:image/webp;base64,UklGRjgWAABXRUJQVlA4ICwWAADwVQCdASoVAbQAPp1GnEqlo6MhqtcJcLATiWhu3V44Qz92/..." type="image/webp">
|
||
</head>
|
||
<style>
|
||
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=Chakra+Petch:wght@400;600;700&display=swap');
|
||
|
||
:root {
|
||
--crt-green: #39ff14;
|
||
--crt-amber: #ffb300;
|
||
--crt-red: #ff2244;
|
||
--crt-blue: #00d4ff;
|
||
--crt-pink: #ff00cc;
|
||
--bg: #020a04;
|
||
--panel: rgba(0,20,5,0.92);
|
||
}
|
||
|
||
* { margin:0; padding:0; box-sizing:border-box; }
|
||
|
||
html, body {
|
||
width:100%; height:100%;
|
||
background: var(--bg);
|
||
font-family: 'Press Start 2P', monospace;
|
||
overflow: hidden;
|
||
color: var(--crt-green);
|
||
}
|
||
|
||
/* CRT effects */
|
||
body::before {
|
||
content:'';
|
||
position:fixed; inset:0; z-index:9999; pointer-events:none;
|
||
background: repeating-linear-gradient(0deg, transparent, transparent 3px, rgba(0,0,0,0.18) 3px, rgba(0,0,0,0.18) 4px);
|
||
}
|
||
body::after {
|
||
content:'';
|
||
position:fixed; inset:0; z-index:9998; pointer-events:none;
|
||
background: radial-gradient(ellipse at center, transparent 60%, rgba(0,0,0,0.75) 100%);
|
||
}
|
||
|
||
.crt-flicker {
|
||
animation: flicker 8s infinite;
|
||
}
|
||
@keyframes flicker {
|
||
0%,95%,100% { opacity:1; }
|
||
96% { opacity:0.97; }
|
||
97% { opacity:1; }
|
||
98% { opacity:0.95; }
|
||
99% { opacity:1; }
|
||
}
|
||
|
||
/* ===== SCREENS ===== */
|
||
.screen {
|
||
position:fixed; inset:0;
|
||
display:flex; flex-direction:column;
|
||
align-items:center; justify-content:center;
|
||
z-index:10;
|
||
transition: opacity 0.4s;
|
||
}
|
||
.screen.hidden { display:none; }
|
||
|
||
/* ===== ATTRACT / TITLE SCREEN ===== */
|
||
#screen-attract {
|
||
background: var(--bg);
|
||
gap: 28px;
|
||
}
|
||
|
||
.title-logo {
|
||
text-align:center;
|
||
line-height:1.6;
|
||
}
|
||
.title-top {
|
||
font-size: clamp(1rem, 3vw, 1.5rem);
|
||
color: var(--crt-amber);
|
||
text-shadow: 0 0 10px var(--crt-amber), 0 0 30px rgba(255,179,0,0.5);
|
||
letter-spacing: 0.15em;
|
||
animation: glow-amber 1.5s ease-in-out infinite alternate;
|
||
}
|
||
.title-main {
|
||
display:block;
|
||
font-size: clamp(1.8rem, 5vw, 3.2rem);
|
||
color: var(--crt-green);
|
||
text-shadow: 0 0 15px var(--crt-green), 0 0 40px rgba(57,255,20,0.4);
|
||
letter-spacing: 0.08em;
|
||
animation: glow-green 1.5s ease-in-out infinite alternate;
|
||
margin: 8px 0;
|
||
}
|
||
.title-sub {
|
||
font-size: clamp(0.5rem, 1.5vw, 0.75rem);
|
||
color: var(--crt-blue);
|
||
letter-spacing: 0.3em;
|
||
text-shadow: 0 0 8px var(--crt-blue);
|
||
}
|
||
|
||
@keyframes glow-green {
|
||
from { text-shadow: 0 0 10px var(--crt-green), 0 0 20px rgba(57,255,20,0.3); }
|
||
to { text-shadow: 0 0 20px var(--crt-green), 0 0 50px rgba(57,255,20,0.6), 0 0 80px rgba(57,255,20,0.2); }
|
||
}
|
||
@keyframes glow-amber {
|
||
from { text-shadow: 0 0 10px var(--crt-amber); }
|
||
to { text-shadow: 0 0 25px var(--crt-amber), 0 0 50px rgba(255,179,0,0.4); }
|
||
}
|
||
|
||
.dart-icon {
|
||
font-size: clamp(3rem, 8vw, 5rem);
|
||
animation: spin-dart 3s ease-in-out infinite;
|
||
filter: drop-shadow(0 0 12px var(--crt-green));
|
||
}
|
||
@keyframes spin-dart {
|
||
0%,100% { transform: rotate(-15deg) scale(1); }
|
||
50% { transform: rotate(15deg) scale(1.1); }
|
||
}
|
||
|
||
.insert-coin {
|
||
font-size: clamp(0.5rem, 1.5vw, 0.8rem);
|
||
color: var(--crt-amber);
|
||
letter-spacing: 0.2em;
|
||
animation: blink 0.9s step-end infinite;
|
||
text-shadow: 0 0 10px var(--crt-amber);
|
||
}
|
||
@keyframes blink { 0%,100%{opacity:1;} 50%{opacity:0;} }
|
||
|
||
.highscore-box {
|
||
background: rgba(57,255,20,0.05);
|
||
border: 2px solid rgba(57,255,20,0.3);
|
||
padding: 12px 30px;
|
||
text-align:center;
|
||
}
|
||
.hs-label { font-size:0.45rem; color:rgba(57,255,20,0.6); letter-spacing:0.2em; margin-bottom:6px; }
|
||
.hs-value { font-size:1.2rem; color:var(--crt-green); text-shadow:0 0 10px var(--crt-green); }
|
||
|
||
/* ===== MENU SCREEN ===== */
|
||
#screen-menu {
|
||
background: var(--bg);
|
||
gap: 30px;
|
||
}
|
||
.menu-title {
|
||
font-size: clamp(0.7rem, 2vw, 1rem);
|
||
color: var(--crt-amber);
|
||
text-shadow: 0 0 15px var(--crt-amber);
|
||
letter-spacing: 0.2em;
|
||
text-align:center;
|
||
}
|
||
.menu-question {
|
||
font-size: clamp(0.55rem, 1.5vw, 0.75rem);
|
||
color: var(--crt-blue);
|
||
letter-spacing: 0.15em;
|
||
text-align:center;
|
||
line-height:2;
|
||
}
|
||
.menu-choices {
|
||
display:flex;
|
||
gap: 30px;
|
||
flex-wrap:wrap;
|
||
justify-content:center;
|
||
}
|
||
.choice-card {
|
||
width: clamp(160px, 25vw, 220px);
|
||
background: rgba(0,30,10,0.9);
|
||
border: 3px solid rgba(57,255,20,0.3);
|
||
padding: 24px 16px;
|
||
text-align:center;
|
||
cursor:pointer;
|
||
transition: all 0.15s;
|
||
position:relative;
|
||
overflow:hidden;
|
||
}
|
||
.choice-card::before {
|
||
content:'';
|
||
position:absolute; inset:0;
|
||
background: linear-gradient(135deg, transparent 50%, rgba(57,255,20,0.03) 100%);
|
||
}
|
||
.choice-card:hover, .choice-card.selected {
|
||
border-color: var(--crt-green);
|
||
background: rgba(57,255,20,0.1);
|
||
box-shadow: 0 0 20px rgba(57,255,20,0.3), inset 0 0 20px rgba(57,255,20,0.05);
|
||
transform: scale(1.04);
|
||
}
|
||
.choice-icon { font-size: clamp(2rem, 5vw, 3rem); margin-bottom:14px; display:block; }
|
||
.choice-name {
|
||
font-size: clamp(0.5rem, 1.2vw, 0.7rem);
|
||
color: var(--crt-green);
|
||
letter-spacing:0.1em;
|
||
margin-bottom:8px;
|
||
}
|
||
.choice-desc {
|
||
font-family: 'Chakra Petch', sans-serif;
|
||
font-size: clamp(0.6rem, 1.2vw, 0.75rem);
|
||
color: rgba(57,255,20,0.6);
|
||
line-height:1.6;
|
||
}
|
||
.choice-key {
|
||
display:inline-block;
|
||
margin-top:10px;
|
||
font-size:0.45rem;
|
||
background: rgba(57,255,20,0.15);
|
||
border: 1px solid rgba(57,255,20,0.4);
|
||
padding: 4px 10px;
|
||
color: var(--crt-amber);
|
||
letter-spacing:0.1em;
|
||
}
|
||
|
||
/* ===== DIFFICULTY SCREEN ===== */
|
||
#screen-difficulty {
|
||
background: var(--bg);
|
||
gap:24px;
|
||
}
|
||
.diff-cards {
|
||
display:flex; gap:20px; flex-wrap:wrap; justify-content:center;
|
||
}
|
||
.diff-card {
|
||
width: clamp(140px, 20vw, 180px);
|
||
border: 3px solid rgba(57,255,20,0.3);
|
||
background: rgba(0,20,5,0.9);
|
||
padding: 20px 12px;
|
||
text-align:center;
|
||
cursor:pointer;
|
||
transition:all 0.15s;
|
||
}
|
||
.diff-card:hover {
|
||
border-color:var(--crt-amber);
|
||
box-shadow:0 0 20px rgba(255,179,0,0.3);
|
||
transform:scale(1.05);
|
||
}
|
||
.diff-name { font-size: clamp(0.5rem,1.2vw,0.7rem); margin-bottom:10px; }
|
||
.diff-easy { color:#00ff88; }
|
||
.diff-medium { color:var(--crt-amber); }
|
||
.diff-hard { color:var(--crt-red); }
|
||
.diff-stars { font-size:1rem; margin-bottom:8px; }
|
||
.diff-info {
|
||
font-family:'Chakra Petch',sans-serif;
|
||
font-size:clamp(0.55rem,1vw,0.68rem);
|
||
color:rgba(57,255,20,0.55);
|
||
line-height:1.6;
|
||
}
|
||
|
||
/* ===== GAME SCREEN ===== */
|
||
#screen-game {
|
||
background: var(--bg);
|
||
flex-direction:row;
|
||
align-items:stretch;
|
||
justify-content:center;
|
||
gap:0;
|
||
padding:0;
|
||
}
|
||
|
||
.side-panel {
|
||
width: clamp(120px, 18vw, 200px);
|
||
background: rgba(0,15,5,0.95);
|
||
border-right: 2px solid rgba(57,255,20,0.2);
|
||
display:flex; flex-direction:column;
|
||
align-items:center;
|
||
padding:20px 10px;
|
||
gap:20px;
|
||
flex-shrink:0;
|
||
}
|
||
.side-panel.right {
|
||
border-right:none;
|
||
border-left: 2px solid rgba(57,255,20,0.2);
|
||
}
|
||
|
||
.panel-label {
|
||
font-size:0.4rem;
|
||
letter-spacing:0.2em;
|
||
color:rgba(57,255,20,0.5);
|
||
text-transform:uppercase;
|
||
margin-bottom:4px;
|
||
}
|
||
.panel-value {
|
||
font-size:clamp(1.2rem,3vw,2rem);
|
||
color:var(--crt-green);
|
||
text-shadow:0 0 12px var(--crt-green);
|
||
}
|
||
.panel-box {
|
||
text-align:center;
|
||
width:100%;
|
||
background:rgba(57,255,20,0.04);
|
||
border:1px solid rgba(57,255,20,0.15);
|
||
padding:10px 6px;
|
||
}
|
||
|
||
.darts-display {
|
||
display:flex; flex-wrap:wrap; gap:4px; justify-content:center;
|
||
}
|
||
.dart-pip {
|
||
width:12px; height:12px;
|
||
background:var(--crt-amber);
|
||
border-radius:50% 50% 50% 0;
|
||
transform:rotate(-45deg);
|
||
box-shadow:0 0 6px var(--crt-amber);
|
||
transition:all 0.2s;
|
||
}
|
||
.dart-pip.used {
|
||
background:rgba(57,255,20,0.1);
|
||
border:1px solid rgba(57,255,20,0.2);
|
||
box-shadow:none;
|
||
}
|
||
|
||
.streak-fire {
|
||
font-size:1.5rem;
|
||
text-align:center;
|
||
animation:streakPulse 0.5s ease-in-out infinite alternate;
|
||
}
|
||
@keyframes streakPulse {
|
||
from { transform:scale(1); }
|
||
to { transform:scale(1.2); }
|
||
}
|
||
|
||
.mult-badge {
|
||
font-size:clamp(0.5rem,1.2vw,0.7rem);
|
||
padding:4px 10px;
|
||
background:rgba(255,0,204,0.2);
|
||
border:1px solid var(--crt-pink);
|
||
color:var(--crt-pink);
|
||
text-shadow:0 0 8px var(--crt-pink);
|
||
text-align:center;
|
||
}
|
||
|
||
/* Center arena */
|
||
.arena-wrap {
|
||
flex:1;
|
||
display:flex;
|
||
flex-direction:column;
|
||
align-items:center;
|
||
justify-content:center;
|
||
gap:12px;
|
||
padding:16px 8px;
|
||
min-width:0;
|
||
}
|
||
|
||
/* Phase indicator */
|
||
.phase-bar {
|
||
display:flex;
|
||
gap:10px;
|
||
align-items:center;
|
||
}
|
||
.phase-step {
|
||
font-size:0.45rem;
|
||
letter-spacing:0.1em;
|
||
padding:6px 14px;
|
||
border:2px solid rgba(57,255,20,0.2);
|
||
color:rgba(57,255,20,0.35);
|
||
transition:all 0.3s;
|
||
}
|
||
.phase-step.active {
|
||
border-color:var(--crt-amber);
|
||
color:var(--crt-amber);
|
||
text-shadow:0 0 10px var(--crt-amber);
|
||
background:rgba(255,179,0,0.1);
|
||
animation:phaseGlow 0.7s ease-in-out infinite alternate;
|
||
}
|
||
.phase-step.done {
|
||
border-color:var(--crt-green);
|
||
color:var(--crt-green);
|
||
text-shadow:0 0 8px var(--crt-green);
|
||
background:rgba(57,255,20,0.08);
|
||
}
|
||
@keyframes phaseGlow {
|
||
from { box-shadow:0 0 5px rgba(255,179,0,0.3); }
|
||
to { box-shadow:0 0 20px rgba(255,179,0,0.7); }
|
||
}
|
||
|
||
.phase-arrow { color:rgba(57,255,20,0.4); font-size:0.6rem; }
|
||
|
||
/* Arena */
|
||
.arena {
|
||
position:relative;
|
||
width: min(420px, 82vw, 72vh);
|
||
height: min(420px, 82vw, 72vh);
|
||
border:3px solid rgba(57,255,20,0.25);
|
||
background: radial-gradient(ellipse at center, #001a06 0%, #000a02 100%);
|
||
box-shadow: 0 0 40px rgba(57,255,20,0.1), inset 0 0 60px rgba(0,0,0,0.6);
|
||
overflow:hidden;
|
||
flex-shrink:0;
|
||
}
|
||
|
||
/* Horizontal line (X-axis targeting) */
|
||
.h-line {
|
||
position:absolute;
|
||
left:0; right:0;
|
||
height:2px;
|
||
background: linear-gradient(90deg, transparent, var(--crt-blue), transparent);
|
||
box-shadow:0 0 8px var(--crt-blue), 0 0 20px rgba(0,212,255,0.4);
|
||
pointer-events:none;
|
||
z-index:6;
|
||
transition: top 0s;
|
||
}
|
||
/* Vertical line (Y-axis targeting) */
|
||
.v-line {
|
||
position:absolute;
|
||
top:0; bottom:0;
|
||
width:2px;
|
||
background: linear-gradient(180deg, transparent, var(--crt-amber), transparent);
|
||
box-shadow:0 0 8px var(--crt-amber), 0 0 20px rgba(255,179,0,0.4);
|
||
pointer-events:none;
|
||
z-index:6;
|
||
}
|
||
|
||
.crosshair-dot {
|
||
position:absolute;
|
||
width:16px; height:16px;
|
||
border-radius:50%;
|
||
border:2px solid rgba(255,255,255,0.8);
|
||
transform:translate(-50%,-50%);
|
||
pointer-events:none;
|
||
z-index:7;
|
||
display:none;
|
||
box-shadow:0 0 10px rgba(255,255,255,0.6);
|
||
}
|
||
|
||
#dartboard {
|
||
position:absolute;
|
||
image-rendering:pixelated;
|
||
}
|
||
|
||
.dart-marker {
|
||
position:absolute;
|
||
width:14px; height:14px;
|
||
border-radius:50%;
|
||
transform:translate(-50%,-50%);
|
||
pointer-events:none;
|
||
z-index:10;
|
||
animation:dartLand 0.25s ease-out forwards;
|
||
}
|
||
@keyframes dartLand {
|
||
0% { transform:translate(-50%,-70%) scale(2.5); opacity:0; }
|
||
60% { transform:translate(-50%,-50%) scale(1.3); opacity:1; }
|
||
100% { transform:translate(-50%,-50%) scale(1); opacity:1; }
|
||
}
|
||
|
||
.score-popup {
|
||
position:absolute;
|
||
pointer-events:none;
|
||
font-family:'Press Start 2P',monospace;
|
||
animation:floatScore 1.4s ease-out forwards;
|
||
z-index:20;
|
||
text-shadow:0 2px 6px rgba(0,0,0,0.9);
|
||
white-space:nowrap;
|
||
transform-origin:center;
|
||
}
|
||
@keyframes floatScore {
|
||
0% { opacity:1; transform:translate(-50%,-50%) scale(0.4); }
|
||
25% { opacity:1; transform:translate(-50%,-70%) scale(1.1); }
|
||
80% { opacity:1; transform:translate(-50%,-150%) scale(0.9); }
|
||
100% { opacity:0; transform:translate(-50%,-200%) scale(0.7); }
|
||
}
|
||
|
||
.screen-flash {
|
||
position:absolute; inset:0;
|
||
pointer-events:none; z-index:30;
|
||
animation:flashOut 0.3s ease-out forwards;
|
||
}
|
||
@keyframes flashOut { 0%{opacity:1;} 100%{opacity:0;} }
|
||
|
||
/* Action hint */
|
||
.action-hint {
|
||
font-size:clamp(0.45rem,1.2vw,0.6rem);
|
||
letter-spacing:0.15em;
|
||
text-align:center;
|
||
padding:8px 20px;
|
||
border:2px solid rgba(57,255,20,0.3);
|
||
color:var(--crt-green);
|
||
background:rgba(0,30,5,0.8);
|
||
animation:hintPulse 1s ease-in-out infinite alternate;
|
||
min-height:36px;
|
||
display:flex; align-items:center; justify-content:center;
|
||
}
|
||
@keyframes hintPulse {
|
||
from { border-color:rgba(57,255,20,0.3); }
|
||
to { border-color:rgba(57,255,20,0.8); box-shadow:0 0 15px rgba(57,255,20,0.3); }
|
||
}
|
||
|
||
/* ===== GAME OVER SCREEN ===== */
|
||
#screen-gameover {
|
||
background:rgba(0,5,0,0.97);
|
||
gap:20px;
|
||
}
|
||
.go-title {
|
||
font-size:clamp(1.5rem,4vw,2.8rem);
|
||
color:var(--crt-red);
|
||
text-shadow:0 0 20px var(--crt-red), 0 0 50px rgba(255,34,68,0.4);
|
||
animation:glow-red 1s ease-in-out infinite alternate;
|
||
letter-spacing:0.15em;
|
||
}
|
||
@keyframes glow-red {
|
||
from { text-shadow:0 0 10px var(--crt-red); }
|
||
to { text-shadow:0 0 30px var(--crt-red), 0 0 60px rgba(255,34,68,0.5); }
|
||
}
|
||
.go-score-wrap { text-align:center; }
|
||
.go-label { font-size:0.45rem; color:rgba(57,255,20,0.6); letter-spacing:0.2em; margin-bottom:6px; }
|
||
.go-score { font-size:clamp(1.8rem,4vw,2.5rem); color:var(--crt-amber); text-shadow:0 0 15px var(--crt-amber); }
|
||
.go-best { font-size:0.6rem; color:var(--crt-green); letter-spacing:0.1em; margin-top:6px; }
|
||
.go-grade { font-size:clamp(1rem,3vw,1.8rem); letter-spacing:0.2em; }
|
||
|
||
.btn-row { display:flex; gap:16px; flex-wrap:wrap; justify-content:center; }
|
||
.arcade-btn {
|
||
font-family:'Press Start 2P',monospace;
|
||
font-size:clamp(0.45rem,1.2vw,0.6rem);
|
||
letter-spacing:0.12em;
|
||
padding:12px 24px;
|
||
border:3px solid;
|
||
background:transparent;
|
||
cursor:pointer;
|
||
transition:all 0.15s;
|
||
text-transform:uppercase;
|
||
}
|
||
.arcade-btn-green {
|
||
border-color:var(--crt-green);
|
||
color:var(--crt-green);
|
||
text-shadow:0 0 8px var(--crt-green);
|
||
}
|
||
.arcade-btn-green:hover {
|
||
background:rgba(57,255,20,0.15);
|
||
box-shadow:0 0 20px rgba(57,255,20,0.4);
|
||
transform:scale(1.05);
|
||
}
|
||
.arcade-btn-amber {
|
||
border-color:var(--crt-amber);
|
||
color:var(--crt-amber);
|
||
text-shadow:0 0 8px var(--crt-amber);
|
||
}
|
||
.arcade-btn-amber:hover {
|
||
background:rgba(255,179,0,0.15);
|
||
box-shadow:0 0 20px rgba(255,179,0,0.4);
|
||
transform:scale(1.05);
|
||
}
|
||
|
||
/* Controls reminder */
|
||
.controls-reminder {
|
||
font-family:'Chakra Petch',sans-serif;
|
||
font-size:clamp(0.6rem,1.2vw,0.75rem);
|
||
color:rgba(57,255,20,0.5);
|
||
letter-spacing:0.1em;
|
||
text-align:center;
|
||
line-height:2;
|
||
}
|
||
.key-badge {
|
||
display:inline-block;
|
||
background:rgba(57,255,20,0.1);
|
||
border:1px solid rgba(57,255,20,0.4);
|
||
padding:2px 8px;
|
||
color:var(--crt-green);
|
||
font-family:'Press Start 2P',monospace;
|
||
font-size:0.5rem;
|
||
}
|
||
|
||
/* Score history */
|
||
.score-history {
|
||
display:flex; flex-direction:column; gap:4px; width:100%; padding:0 4px;
|
||
}
|
||
.score-entry {
|
||
font-family:'Chakra Petch',sans-serif;
|
||
font-size:0.65rem;
|
||
display:flex; justify-content:space-between;
|
||
padding:4px 8px;
|
||
background:rgba(57,255,20,0.04);
|
||
border-left:3px solid rgba(57,255,20,0.3);
|
||
color:rgba(57,255,20,0.7);
|
||
letter-spacing:0.05em;
|
||
animation:slideIn 0.3s ease-out;
|
||
}
|
||
@keyframes slideIn {
|
||
from { transform:translateX(-20px); opacity:0; }
|
||
to { transform:translateX(0); opacity:1; }
|
||
}
|
||
.score-entry .pts { color:var(--crt-amber); font-weight:700; }
|
||
</style>
|
||
</head>
|
||
<body class="crt-flicker">
|
||
|
||
<!-- ===== ATTRACT SCREEN ===== -->
|
||
<div class="screen" id="screen-attract">
|
||
<div class="dart-icon">🎯</div>
|
||
<div class="title-logo">
|
||
<div class="title-top">— ARCADE PRESENTS —</div>
|
||
<span class="title-main">LAUPAN LUCHCD</span>
|
||
<span class="title-main" style="font-size:clamp(1.2rem,3.5vw,2.2rem);color:var(--crt-amber);text-shadow:0 0 15px var(--crt-amber);">PEILTJUS</span>
|
||
<div class="title-sub" style="margin-top:10px;">THE ULTIMATE DART MACHINE</div>
|
||
</div>
|
||
<div class="highscore-box">
|
||
<div class="hs-label">— HIGH SCORE —</div>
|
||
<div class="hs-value" id="hs-display">00000</div>
|
||
</div>
|
||
<div class="insert-coin">[ DRUK OP SPATIE / KNOP OM TE STARTEN ]</div>
|
||
</div>
|
||
|
||
<!-- ===== MENU SCREEN (control choice) ===== -->
|
||
<div class="screen hidden" id="screen-menu">
|
||
<div class="menu-title">⚙ BESTURING KIEZEN</div>
|
||
<div class="menu-question">HOE WIL JE SPELEN?</div>
|
||
<div class="menu-choices">
|
||
<div class="choice-card" onclick="selectControl('buttons')" id="card-buttons">
|
||
<span class="choice-icon">⌨️</span>
|
||
<div class="choice-name">KNOPPEN</div>
|
||
<div class="choice-desc">Druk <strong>SPATIE</strong> of <strong>KNOP 1</strong><br>om de richtingen te stoppen</div>
|
||
<div class="choice-key">SPATIE / BTN1</div>
|
||
</div>
|
||
<div class="choice-card" onclick="selectControl('joystick')" id="card-joystick">
|
||
<span class="choice-icon">🕹️</span>
|
||
<div class="choice-name">JOYSTICK</div>
|
||
<div class="choice-desc">Druk de <strong>joystick in</strong><br>om de richtingen te stoppen</div>
|
||
<div class="choice-key">JS BUTTON</div>
|
||
</div>
|
||
</div>
|
||
<div class="controls-reminder">
|
||
OF KLIK OP DE KAART MET DE MUIS
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== DIFFICULTY SCREEN ===== -->
|
||
<div class="screen hidden" id="screen-difficulty">
|
||
<div class="menu-title" style="color:var(--crt-amber);text-shadow:0 0 15px var(--crt-amber);">MOEILIJKHEID</div>
|
||
<div class="diff-cards">
|
||
<div class="diff-card" onclick="selectDiff('easy')">
|
||
<div class="diff-stars">⭐</div>
|
||
<div class="diff-name diff-easy">MAKKELIJK</div>
|
||
<div class="diff-info">Langzame lijn<br>3 pijlen<br>Goede timing</div>
|
||
</div>
|
||
<div class="diff-card" onclick="selectDiff('medium')">
|
||
<div class="diff-stars">⭐⭐</div>
|
||
<div class="diff-name diff-medium">NORMAAL</div>
|
||
<div class="diff-info">Gemiddelde snelheid<br>3 pijlen<br>Let op!</div>
|
||
</div>
|
||
<div class="diff-card" onclick="selectDiff('hard')">
|
||
<div class="diff-stars">⭐⭐⭐</div>
|
||
<div class="diff-name diff-hard">MOEILIJK</div>
|
||
<div class="diff-info">Hoge snelheid<br>3 pijlen<br>Enkel voor pros</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== GAME SCREEN ===== -->
|
||
<div class="screen hidden" id="screen-game">
|
||
<!-- Left panel -->
|
||
<div class="side-panel left" id="left-panel">
|
||
<div class="panel-box">
|
||
<div class="panel-label">SCORE</div>
|
||
<div class="panel-value" id="score-disp">0</div>
|
||
</div>
|
||
<div class="panel-box">
|
||
<div class="panel-label">PIJLEN</div>
|
||
<div class="darts-display" id="darts-pips"></div>
|
||
</div>
|
||
<div class="panel-box">
|
||
<div class="panel-label">STREAK</div>
|
||
<div class="panel-value" id="streak-disp" style="color:var(--crt-amber);text-shadow:0 0 10px var(--crt-amber);">0</div>
|
||
<div class="streak-fire" id="streak-fire" style="display:none;">🔥</div>
|
||
</div>
|
||
<div class="mult-badge" id="mult-badge" style="display:none;">×1</div>
|
||
</div>
|
||
|
||
<!-- Center arena -->
|
||
<div class="arena-wrap">
|
||
<div class="phase-bar">
|
||
<div class="phase-step active" id="phase-x">① X-AS</div>
|
||
<div class="phase-arrow">▶</div>
|
||
<div class="phase-step" id="phase-y">② Y-AS</div>
|
||
<div class="phase-arrow">▶</div>
|
||
<div class="phase-step" id="phase-throw">③ GOOIEN</div>
|
||
</div>
|
||
|
||
<div class="arena" id="arena">
|
||
<canvas id="dartboard" width="420" height="420"></canvas>
|
||
<div class="h-line" id="h-line" style="top:50%"></div>
|
||
<div class="v-line" id="v-line" style="left:50%;display:none"></div>
|
||
<div class="crosshair-dot" id="crosshair-dot"></div>
|
||
</div>
|
||
|
||
<div class="action-hint" id="action-hint">WACHT...</div>
|
||
</div>
|
||
|
||
<!-- Right panel: score history -->
|
||
<div class="side-panel right" id="right-panel">
|
||
<div class="panel-label" style="color:var(--crt-green);">LAATSTE WORPEN</div>
|
||
<div class="score-history" id="score-history"></div>
|
||
|
||
<div style="margin-top:auto;width:100%;">
|
||
<div class="panel-box">
|
||
<div class="panel-label">BEST</div>
|
||
<div class="panel-value" id="best-disp" style="font-size:1rem;color:var(--crt-pink);text-shadow:0 0 10px var(--crt-pink);">0</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== GAME OVER SCREEN ===== -->
|
||
<div class="screen hidden" id="screen-gameover">
|
||
<div class="go-title">GAME OVER</div>
|
||
<div class="go-score-wrap">
|
||
<div class="go-label">— JOUW SCORE —</div>
|
||
<div class="go-score" id="go-score-val">0</div>
|
||
<div class="go-best" id="go-best-val"></div>
|
||
</div>
|
||
<div class="go-grade" id="go-grade"></div>
|
||
<div class="btn-row">
|
||
<button class="arcade-btn arcade-btn-green" onclick="goToMenu()">🕹 MENU</button>
|
||
<button class="arcade-btn arcade-btn-amber" onclick="restartGame()">↺ OPNIEUW</button>
|
||
</div>
|
||
<div class="controls-reminder">
|
||
SPATIE = OPNIEUW | ESC = MENU
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// ============================================================
|
||
// STATE
|
||
// ============================================================
|
||
let currentScreen = 'attract';
|
||
let controlMode = 'buttons'; // 'buttons' | 'joystick'
|
||
let difficulty = 'medium';
|
||
let highScore = 0;
|
||
|
||
// Game state
|
||
let score=0, dartsLeft=8, streak=0, mult=1;
|
||
let phase = 'x'; // 'x' | 'y' | 'locked'
|
||
let lineXPos = 50; // % across arena (for v-line)
|
||
let lineYPos = 50; // % down arena (for h-line)
|
||
let lineXDir = 1, lineYDir = 1;
|
||
let lineXSpeed=1, lineYSpeed=0.8;
|
||
let animFrame=null, lastTime=0;
|
||
let gamepads={};
|
||
let jsButtonWasDown=false;
|
||
|
||
const diffSettings = {
|
||
easy: { speed:0.6, darts:3 },
|
||
medium: { speed:1.1, darts:3 },
|
||
hard: { speed:1.9, darts:3 },
|
||
};
|
||
|
||
// Dart board
|
||
const SEG_VALUES=[20,1,18,4,13,6,10,15,2,17,3,19,7,16,8,11,14,9,12,5];
|
||
|
||
// ============================================================
|
||
// SCREEN MANAGEMENT
|
||
// ============================================================
|
||
function showScreen(id) {
|
||
document.querySelectorAll('.screen').forEach(s=>s.classList.add('hidden'));
|
||
document.getElementById('screen-'+id).classList.remove('hidden');
|
||
currentScreen = id;
|
||
}
|
||
|
||
// ============================================================
|
||
// ATTRACT SCREEN
|
||
// ============================================================
|
||
function initAttract() {
|
||
document.getElementById('hs-display').textContent = String(highScore).padStart(5,'0');
|
||
showScreen('attract');
|
||
}
|
||
|
||
// ============================================================
|
||
// MENU (control choice)
|
||
// ============================================================
|
||
function openMenu() {
|
||
showScreen('menu');
|
||
}
|
||
function selectControl(mode) {
|
||
controlMode = mode;
|
||
document.getElementById('card-buttons').classList.toggle('selected', mode==='buttons');
|
||
document.getElementById('card-joystick').classList.toggle('selected', mode==='joystick');
|
||
setTimeout(()=>showScreen('difficulty'), 220);
|
||
}
|
||
|
||
// ============================================================
|
||
// DIFFICULTY
|
||
// ============================================================
|
||
function selectDiff(d) {
|
||
difficulty = d;
|
||
startGame();
|
||
}
|
||
|
||
// ============================================================
|
||
// DRAW BOARD
|
||
// ============================================================
|
||
function drawBoard() {
|
||
const canvas=document.getElementById('dartboard');
|
||
const ctx=canvas.getContext('2d');
|
||
const SIZE=canvas.width, r=SIZE*0.43, cx=SIZE/2, cy=SIZE/2;
|
||
const seg=20, aps=(Math.PI*2)/seg, off=-Math.PI/2-aps/2;
|
||
|
||
ctx.clearRect(0,0,SIZE,SIZE);
|
||
|
||
// Outer surround
|
||
ctx.beginPath(); ctx.arc(cx,cy,r+16,0,Math.PI*2);
|
||
ctx.fillStyle='#0d1a0d'; ctx.fill();
|
||
ctx.strokeStyle='rgba(57,255,20,0.5)'; ctx.lineWidth=3; ctx.stroke();
|
||
|
||
// Segments
|
||
for(let i=0;i<seg;i++){
|
||
const a1=off+i*aps, a2=a1+aps, dark=i%2===0;
|
||
const cDark='#141a14', cLight='#c8b870';
|
||
const cHit=dark?'#8b1a1a':'#1a6b1a', cHit2=dark?'#661111':'#115511';
|
||
|
||
// Single (11-62%)
|
||
ctx.beginPath(); ctx.moveTo(cx,cy);
|
||
ctx.arc(cx,cy,r*0.62,a1,a2); ctx.closePath();
|
||
ctx.fillStyle=dark?cDark:cLight; ctx.fill();
|
||
// Triple (62-68%)
|
||
ctx.beginPath();
|
||
ctx.arc(cx,cy,r*0.68,a1,a2); ctx.arc(cx,cy,r*0.62,a2,a1,true); ctx.closePath();
|
||
ctx.fillStyle=cHit; ctx.fill();
|
||
// Single mid (68-88%)
|
||
ctx.beginPath();
|
||
ctx.arc(cx,cy,r*0.88,a1,a2); ctx.arc(cx,cy,r*0.68,a2,a1,true); ctx.closePath();
|
||
ctx.fillStyle=dark?cDark:cLight; ctx.fill();
|
||
// Double (88-95%)
|
||
ctx.beginPath();
|
||
ctx.arc(cx,cy,r*0.95,a1,a2); ctx.arc(cx,cy,r*0.88,a2,a1,true); ctx.closePath();
|
||
ctx.fillStyle=cHit2; ctx.fill();
|
||
|
||
// Number
|
||
const ma=a1+aps/2;
|
||
const nr=r*1.05;
|
||
ctx.save();
|
||
ctx.translate(cx+Math.cos(ma)*nr, cy+Math.sin(ma)*nr);
|
||
ctx.rotate(ma+Math.PI/2);
|
||
ctx.font=`bold ${Math.round(r*0.08)}px 'Press Start 2P',monospace`;
|
||
ctx.fillStyle='#fff'; ctx.textAlign='center'; ctx.textBaseline='middle';
|
||
ctx.shadowColor='rgba(0,0,0,0.9)'; ctx.shadowBlur=4;
|
||
ctx.fillText(SEG_VALUES[i],0,0);
|
||
ctx.restore();
|
||
}
|
||
|
||
// Wire lines
|
||
for(let i=0;i<seg;i++){
|
||
const a=off+i*aps;
|
||
ctx.beginPath();
|
||
ctx.moveTo(cx+Math.cos(a)*r*0.11, cy+Math.sin(a)*r*0.11);
|
||
ctx.lineTo(cx+Math.cos(a)*r*0.95, cy+Math.sin(a)*r*0.95);
|
||
ctx.strokeStyle='rgba(0,0,0,0.7)'; ctx.lineWidth=1.5; ctx.stroke();
|
||
}
|
||
[0.95,0.88,0.68,0.62,0.11].forEach(f=>{
|
||
ctx.beginPath(); ctx.arc(cx,cy,r*f,0,Math.PI*2);
|
||
ctx.strokeStyle='rgba(100,80,30,0.9)'; ctx.lineWidth=1.5; ctx.stroke();
|
||
});
|
||
|
||
// Bull outer
|
||
ctx.beginPath(); ctx.arc(cx,cy,r*0.11,0,Math.PI*2);
|
||
ctx.fillStyle='#1d7a1d'; ctx.fill();
|
||
// Bullseye
|
||
ctx.beginPath(); ctx.arc(cx,cy,r*0.05,0,Math.PI*2);
|
||
const bg=ctx.createRadialGradient(cx-2,cy-2,0,cx,cy,r*0.05);
|
||
bg.addColorStop(0,'#ff8800'); bg.addColorStop(1,'#cc0000');
|
||
ctx.fillStyle=bg; ctx.fill();
|
||
ctx.strokeStyle='rgba(255,255,255,0.7)'; ctx.lineWidth=1.5; ctx.stroke();
|
||
|
||
// Position canvas centered
|
||
const arena=document.getElementById('arena');
|
||
const aw=arena.clientWidth, ah=arena.clientHeight;
|
||
canvas.style.left=(aw/2-canvas.offsetWidth/2)+'px';
|
||
canvas.style.top =(ah/2-canvas.offsetHeight/2)+'px';
|
||
}
|
||
|
||
// ============================================================
|
||
// GAME
|
||
// ============================================================
|
||
function startGame() {
|
||
const s = diffSettings[difficulty];
|
||
score=0; streak=0; mult=1; dartsLeft=s.darts;
|
||
phase='x'; lineXPos=50; lineYPos=Math.random()*70+15;
|
||
lineXDir=Math.random()>0.5?1:-1; lineYDir=Math.random()>0.5?1:-1;
|
||
lineXSpeed = s.speed * (0.8+Math.random()*0.4);
|
||
lineYSpeed = s.speed * (0.8+Math.random()*0.4);
|
||
jsButtonWasDown=false;
|
||
|
||
showScreen('game');
|
||
drawBoard();
|
||
updateHUD();
|
||
updatePhaseUI();
|
||
updateDartPips();
|
||
document.getElementById('score-history').innerHTML='';
|
||
document.getElementById('best-disp').textContent=highScore;
|
||
|
||
// Position lines
|
||
document.getElementById('h-line').style.top = lineYPos+'%';
|
||
document.getElementById('h-line').style.display='block';
|
||
document.getElementById('v-line').style.left = lineXPos+'%';
|
||
document.getElementById('v-line').style.display='none';
|
||
document.getElementById('crosshair-dot').style.display='none';
|
||
|
||
cancelAnimationFrame(animFrame);
|
||
lastTime=0;
|
||
animFrame=requestAnimationFrame(gameLoop);
|
||
setHint();
|
||
}
|
||
|
||
function gameLoop(ts) {
|
||
if(currentScreen!=='game'){ return; }
|
||
const dt = lastTime ? Math.min((ts-lastTime)/16.67, 3) : 1;
|
||
lastTime = ts;
|
||
|
||
// Joystick polling
|
||
if(controlMode==='joystick') pollGamepad();
|
||
|
||
if(phase==='x'){
|
||
// Move Y-line (horizontal bar) up/down for X-aim
|
||
lineYPos += lineYDir * lineYSpeed * dt;
|
||
if(lineYPos<=3||lineYPos>=97){ lineYDir*=-1; lineYPos=Math.max(3,Math.min(97,lineYPos)); }
|
||
document.getElementById('h-line').style.top=lineYPos+'%';
|
||
} else if(phase==='y'){
|
||
// Move X-line (vertical bar) left/right for Y-aim
|
||
lineXPos += lineXDir * lineXSpeed * dt;
|
||
if(lineXPos<=3||lineXPos>=97){ lineXDir*=-1; lineXPos=Math.max(3,Math.min(97,lineXPos)); }
|
||
document.getElementById('v-line').style.left=lineXPos+'%';
|
||
// Update crosshair position
|
||
const ch=document.getElementById('crosshair-dot');
|
||
ch.style.left=lineXPos+'%'; ch.style.top=lineYPos+'%';
|
||
}
|
||
|
||
animFrame=requestAnimationFrame(gameLoop);
|
||
}
|
||
|
||
function pollGamepad() {
|
||
const gps=navigator.getGamepads?navigator.getGamepads():[];
|
||
for(const gp of gps){
|
||
if(!gp) continue;
|
||
const btnDown = gp.buttons[0]?.pressed||gp.buttons[1]?.pressed||gp.buttons[2]?.pressed||gp.buttons[3]?.pressed;
|
||
if(btnDown && !jsButtonWasDown){ fireAction(); }
|
||
jsButtonWasDown = btnDown;
|
||
}
|
||
}
|
||
|
||
function fireAction() {
|
||
if(currentScreen==='attract'){ openMenu(); return; }
|
||
if(currentScreen==='gameover'){ restartGame(); return; }
|
||
if(currentScreen!=='game') return;
|
||
|
||
if(phase==='x'){
|
||
// Lock Y position (horizontal line)
|
||
phase='y';
|
||
document.getElementById('v-line').style.display='block';
|
||
document.getElementById('v-line').style.left=lineXPos+'%';
|
||
document.getElementById('crosshair-dot').style.display='block';
|
||
document.getElementById('crosshair-dot').style.left=lineXPos+'%';
|
||
document.getElementById('crosshair-dot').style.top=lineYPos+'%';
|
||
// Speed up Y a bit
|
||
lineYSpeed *= 1.15;
|
||
updatePhaseUI();
|
||
setHint();
|
||
} else if(phase==='y'){
|
||
// Lock X → throw dart
|
||
phase='locked';
|
||
updatePhaseUI();
|
||
throwDart();
|
||
}
|
||
}
|
||
|
||
function throwDart() {
|
||
const arena=document.getElementById('arena');
|
||
const aw=arena.clientWidth, ah=arena.clientHeight;
|
||
const ax=lineXPos/100*aw, ay=lineYPos/100*ah;
|
||
|
||
// Board center
|
||
const canvas=document.getElementById('dartboard');
|
||
const bcx=canvas.offsetLeft+canvas.offsetWidth/2;
|
||
const bcy=canvas.offsetTop+canvas.offsetHeight/2;
|
||
const scale=canvas.width/canvas.offsetWidth;
|
||
const dx=(ax-bcx)*scale, dy=(ay-bcy)*scale;
|
||
|
||
const zone=getZone(dx,dy);
|
||
const hit=zone.pts>0;
|
||
|
||
// Update streak & mult
|
||
if(hit){ streak++; } else { streak=0; }
|
||
mult = streak>=6?3 : streak>=3?2 : 1;
|
||
const pts=zone.pts*mult;
|
||
|
||
// Dart marker
|
||
const m=document.createElement('div');
|
||
m.className='dart-marker';
|
||
m.style.left=ax+'px'; m.style.top=ay+'px';
|
||
if(hit){
|
||
m.style.background='radial-gradient(circle,#fff 25%,#ffdd00 55%,transparent 100%)';
|
||
m.style.boxShadow='0 0 10px #ffdd00, 0 0 25px rgba(255,200,0,0.5)';
|
||
} else {
|
||
m.style.background='radial-gradient(circle,#ff4444 30%,rgba(255,0,0,0.2) 100%)';
|
||
m.style.boxShadow='0 0 8px #ff4444';
|
||
}
|
||
arena.appendChild(m);
|
||
setTimeout(()=>m.remove(),3000);
|
||
|
||
// Flash
|
||
const fl=document.createElement('div');
|
||
fl.className='screen-flash';
|
||
fl.style.background=hit?'rgba(57,255,20,0.12)':'rgba(255,34,68,0.25)';
|
||
arena.appendChild(fl); setTimeout(()=>fl.remove(),300);
|
||
|
||
// Score popup
|
||
const pop=document.createElement('div');
|
||
pop.className='score-popup';
|
||
pop.style.left=ax+'px'; pop.style.top=ay+'px';
|
||
pop.style.color=zone.color;
|
||
let lbl=zone.label;
|
||
if(hit&&mult>1) lbl+=' ×'+mult+'!';
|
||
pop.textContent=hit?`+${pts} ${lbl}`:lbl;
|
||
pop.style.fontSize=pts>=100?'0.75rem':pts>=50?'0.6rem':'0.5rem';
|
||
arena.appendChild(pop);
|
||
setTimeout(()=>pop.remove(),1400);
|
||
|
||
// Score history
|
||
addScoreEntry(zone.label, pts, hit);
|
||
|
||
score+=pts; dartsLeft--;
|
||
updateHUD();
|
||
updateDartPips();
|
||
|
||
if(dartsLeft<=0){
|
||
setTimeout(endGame, 600);
|
||
return;
|
||
}
|
||
|
||
// Reset for next throw
|
||
setTimeout(()=>{
|
||
phase='x';
|
||
lineYPos=Math.random()*70+15;
|
||
lineXPos=50;
|
||
const s=diffSettings[difficulty];
|
||
const spd=s.speed*(1+score/400);
|
||
lineYSpeed=spd*(0.8+Math.random()*0.4);
|
||
lineXSpeed=spd*(0.8+Math.random()*0.4);
|
||
document.getElementById('v-line').style.display='none';
|
||
document.getElementById('crosshair-dot').style.display='none';
|
||
document.getElementById('h-line').style.top=lineYPos+'%';
|
||
updatePhaseUI();
|
||
setHint();
|
||
}, 350);
|
||
}
|
||
|
||
function getZone(dx,dy){
|
||
const r=420*0.43, dist=Math.sqrt(dx*dx+dy*dy), frac=dist/r;
|
||
if(frac>0.95) return {pts:0,label:'MISS',color:'#ff4444'};
|
||
const aps=(Math.PI*2)/20, off=-Math.PI/2-aps/2;
|
||
let ang=((Math.atan2(dy,dx)-off)%(Math.PI*2)+Math.PI*2)%(Math.PI*2);
|
||
const si=Math.floor(ang/aps)%20, v=SEG_VALUES[si];
|
||
if(frac<=0.05) return {pts:50,label:'BULLSEYE!',color:'#ff8800'};
|
||
if(frac<=0.11) return {pts:25,label:'BULL',color:'#ff4400'};
|
||
if(frac>0.62&&frac<=0.68) return {pts:v*3,label:`T${v}`,color:'#00ffcc'};
|
||
if(frac>0.88&&frac<=0.95) return {pts:v*2,label:`D${v}`,color:'#ffdd00'};
|
||
return {pts:v,label:`${v}`,color:'#fff'};
|
||
}
|
||
|
||
function addScoreEntry(label, pts, hit){
|
||
const hist=document.getElementById('score-history');
|
||
const e=document.createElement('div');
|
||
e.className='score-entry';
|
||
e.innerHTML=`<span>${hit?'✓':'✗'} ${label}</span><span class="pts">${hit?'+'+pts:'0'}</span>`;
|
||
if(!hit) e.style.borderLeftColor='var(--crt-red)';
|
||
hist.insertBefore(e, hist.firstChild);
|
||
// Keep max 7
|
||
while(hist.children.length>7) hist.removeChild(hist.lastChild);
|
||
}
|
||
|
||
function updateHUD(){
|
||
document.getElementById('score-disp').textContent=score;
|
||
const sv=document.getElementById('streak-disp');
|
||
sv.textContent=streak;
|
||
document.getElementById('streak-fire').style.display=streak>=3?'block':'none';
|
||
const mb=document.getElementById('mult-badge');
|
||
if(mult>1){
|
||
mb.style.display='block';
|
||
mb.textContent='×'+mult+' STREAK!';
|
||
} else { mb.style.display='none'; }
|
||
}
|
||
|
||
function updateDartPips(){
|
||
const container=document.getElementById('darts-pips');
|
||
container.innerHTML='';
|
||
const total=diffSettings[difficulty].darts;
|
||
for(let i=0;i<total;i++){
|
||
const pip=document.createElement('div');
|
||
pip.className='dart-pip'+(i>=dartsLeft?' used':'');
|
||
container.appendChild(pip);
|
||
}
|
||
}
|
||
|
||
function updatePhaseUI(){
|
||
const px=document.getElementById('phase-x');
|
||
const py=document.getElementById('phase-y');
|
||
const pt=document.getElementById('phase-throw');
|
||
px.className='phase-step'; py.className='phase-step'; pt.className='phase-step';
|
||
if(phase==='x') { px.classList.add('active'); }
|
||
else if(phase==='y') { px.classList.add('done'); py.classList.add('active'); }
|
||
else { px.classList.add('done'); py.classList.add('done'); pt.classList.add('active'); }
|
||
}
|
||
|
||
function setHint(){
|
||
const el=document.getElementById('action-hint');
|
||
const key=controlMode==='joystick'?'[JS KNOP]':'[SPATIE]';
|
||
if(phase==='x') el.textContent=`${key} = STOP X-AS (horizontale lijn)`;
|
||
else if(phase==='y') el.textContent=`${key} = STOP Y-AS (verticale lijn)`;
|
||
else el.textContent='GOOIEN...';
|
||
}
|
||
|
||
function endGame(){
|
||
cancelAnimationFrame(animFrame);
|
||
const isNew=score>highScore;
|
||
if(isNew) highScore=score;
|
||
|
||
document.getElementById('go-score-val').textContent=score;
|
||
document.getElementById('go-best-val').textContent = isNew?'★ NIEUW RECORD! ★':`Beste: ${highScore}`;
|
||
document.getElementById('go-best-val').style.color = isNew?'var(--crt-amber)':'var(--crt-green)';
|
||
|
||
// Grade
|
||
const grades=[
|
||
{min:300,g:'S',c:'#ffdd00'},{min:200,g:'A',c:'#00ffcc'},
|
||
{min:120,g:'B',c:'#39ff14'},{min:60,g:'C',c:'#ffb300'},
|
||
{min:0,g:'D',c:'#ff4444'}
|
||
];
|
||
const gr=grades.find(x=>score>=x.min);
|
||
const gradeEl=document.getElementById('go-grade');
|
||
gradeEl.textContent=`RANG: ${gr.g}`;
|
||
gradeEl.style.color=gr.c;
|
||
gradeEl.style.textShadow=`0 0 20px ${gr.c}`;
|
||
|
||
showScreen('gameover');
|
||
}
|
||
|
||
function goToMenu(){ cancelAnimationFrame(animFrame); initAttract(); }
|
||
function restartGame(){ startGame(); }
|
||
|
||
// ============================================================
|
||
// INPUT
|
||
// ============================================================
|
||
document.addEventListener('keydown', e=>{
|
||
const fire = e.code==='Space'||e.code==='Enter'||e.code==='KeyZ'||e.code==='KeyX';
|
||
if(fire){ e.preventDefault(); }
|
||
|
||
if(currentScreen==='attract' && fire){ openMenu(); return; }
|
||
if(currentScreen==='gameover'){
|
||
if(fire||e.code==='Space') restartGame();
|
||
if(e.code==='Escape') goToMenu();
|
||
return;
|
||
}
|
||
if(currentScreen==='game' && fire){ fireAction(); return; }
|
||
});
|
||
|
||
// Gamepad
|
||
window.addEventListener('gamepadconnected', e=>{ gamepads[e.gamepad.index]=e.gamepad; });
|
||
window.addEventListener('gamepaddisconnected', e=>{ delete gamepads[e.gamepad.index]; });
|
||
|
||
// ============================================================
|
||
// INIT
|
||
// ============================================================
|
||
initAttract();
|
||
</script>
|
||
</body>
|
||
</html>
|