diff --git a/Prehistorik/audio.js b/Prehistorik/audio.js new file mode 100644 index 0000000..4eac318 --- /dev/null +++ b/Prehistorik/audio.js @@ -0,0 +1,76 @@ +'use strict'; + +let audioCtx = null; + +function getAudio() { + if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)(); + return audioCtx; +} + +function beep(freq, freq2, dur, type = 'sine', vol = 0.3) { + try { + const ac = getAudio(); + const o = ac.createOscillator(); + const g = ac.createGain(); + o.type = type; + o.connect(g); g.connect(ac.destination); + o.frequency.setValueAtTime(freq, ac.currentTime); + if (freq2 && freq2 !== freq) o.frequency.exponentialRampToValueAtTime(freq2, ac.currentTime + dur); + g.gain.setValueAtTime(vol, ac.currentTime); + g.gain.exponentialRampToValueAtTime(0.001, ac.currentTime + dur); + o.start(ac.currentTime); + o.stop(ac.currentTime + dur + 0.01); + } catch(e) {} +} + +const SFX = { + jump: () => beep(280, 560, 0.18, 'sine', 0.25), + attack: () => beep(140, 70, 0.12, 'sawtooth', 0.30), + stomp: () => { beep(200, 80, 0.1, 'square', 0.35); beep(400, 400, 0.08, 'sine', 0.2); }, + hurt: () => beep(180, 90, 0.28, 'square', 0.40), + die: () => beep(380, 50, 0.80, 'square', 0.40), + collect: () => beep(550, 880, 0.10, 'sine', 0.20), + heart: () => { beep(660, 660, 0.06, 'sine', 0.2); setTimeout(() => beep(880, 880, 0.12, 'sine', 0.2), 70); }, + killEnemy: () => beep(260, 100, 0.25, 'sawtooth', 0.28), + combo: (n) => beep(440 + n * 40, 550 + n * 40, 0.08, 'sine', 0.18), + levelUp: () => { + [523, 659, 784, 1047].forEach((f, i) => + setTimeout(() => beep(f, f, i === 3 ? 0.25 : 0.08, 'sine', 0.28), i * 100) + ); + }, +}; + +// ─── Background Music ───────────────────────────────────────────────────────── +let _musicTimer = null; +let _musicStep = 0; + +const MUSIC = { + menu: { bpm: 112, notes: [392,0,523,0,659,523,392,330, 392,0,523,659,784,659,523,0] }, + grass: { bpm: 132, notes: [523,0,659,0,784,659,523,0, 440,0,523,0,659,523,440,0] }, + cave: { bpm: 96, notes: [294,0,330,0,262,0,294,0, 220,0,247,0,262,0,220,0] }, + ice: { bpm: 108, notes: [440,0,494,523,587,0,523,494, 440,0,392,0,440,494,523,0] }, +}; + +function startMusic(theme) { + stopMusic(); + try { getAudio(); } catch(e) { return; } + const pat = MUSIC[theme] || MUSIC.menu; + const beatMs = (60000 / pat.bpm) / 2; // eighth-note duration + _musicStep = 0; + + const tick = () => { + const freq = pat.notes[_musicStep % pat.notes.length]; + if (freq > 0) { + beep(freq / 2, freq / 2, beatMs / 1000 * 0.75, 'square', 0.04); + if (_musicStep % 2 === 0) beep(freq, freq, beatMs / 1000 * 0.55, 'triangle', 0.05); + } + _musicStep++; + _musicTimer = setTimeout(tick, beatMs); + }; + _musicTimer = setTimeout(tick, 0); +} + +function stopMusic() { + if (_musicTimer) { clearTimeout(_musicTimer); _musicTimer = null; } + _musicStep = 0; +} diff --git a/Prehistorik/constants.js b/Prehistorik/constants.js new file mode 100644 index 0000000..9505034 --- /dev/null +++ b/Prehistorik/constants.js @@ -0,0 +1,21 @@ +'use strict'; + +// ─── Canvas ────────────────────────────────────────────────────────────────── +const canvas = document.getElementById('gameCanvas'); +const ctx = canvas.getContext('2d'); +const W = canvas.width; +const H = canvas.height; + +// ─── Physics ───────────────────────────────────────────────────────────────── +const GRAVITY = 0.55; +const MAX_FALL = 16; +const JUMP_POW = -12.5; +const WALK_SPD = 4; +const STOMP_BOUNCE = -11; // vy after successful stomp + +// ─── Gameplay ──────────────────────────────────────────────────────────────── +const ATTACK_FRAMES = 22; +const INVINC_FRAMES = 100; +const WORLD_H = 600; +const COMBO_TIMEOUT = 150; // frames before combo resets +const MAX_COMBO_MULT = 8; // maximum score multiplier diff --git a/Prehistorik/index.html b/Prehistorik/index.html new file mode 100644 index 0000000..80ae393 --- /dev/null +++ b/Prehistorik/index.html @@ -0,0 +1,28 @@ + + + + + + PREHISTORIK - Stone Age Adventure + + + + +
+ +
🖱 CLICK TO FOCUS
+
ARROWS/WASD=Move   SPACE/W=Jump   Z/X/CTRL=Attack   ESC=Pause
+
+ + + + + + + + + + + + + diff --git a/Prehistorik/style.css b/Prehistorik/style.css new file mode 100644 index 0000000..25a3b97 --- /dev/null +++ b/Prehistorik/style.css @@ -0,0 +1,46 @@ +* { margin: 0; padding: 0; box-sizing: border-box; } + +body { + background: #000; + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + font-family: monospace; + overflow: hidden; +} + +#wrapper { + position: relative; + display: inline-block; +} + +canvas { + display: block; + image-rendering: pixelated; + border: 3px solid #FFD700; + box-shadow: 0 0 40px rgba(255, 165, 0, 0.4); + outline: none; + cursor: default; +} + +#focus-overlay { + display: none; + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.72); + color: #FFD700; + font: bold 22px monospace; + text-align: center; + padding-top: 210px; + letter-spacing: 1px; + pointer-events: none; +} + +#controls-hint { + color: #666; + font-size: 12px; + text-align: center; + margin-top: 6px; + letter-spacing: 1px; +}