Загрузить файлы в «Prehistorik»

This commit is contained in:
2026-02-23 21:16:54 +03:00
parent 3870fe54d4
commit deff698041
4 changed files with 171 additions and 0 deletions

76
Prehistorik/audio.js Normal file
View File

@@ -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;
}

21
Prehistorik/constants.js Normal file
View File

@@ -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

28
Prehistorik/index.html Normal file
View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PREHISTORIK - Stone Age Adventure</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="wrapper">
<canvas id="gameCanvas" width="800" height="500" tabindex="0"></canvas>
<div id="focus-overlay">🖱 CLICK TO FOCUS</div>
<div id="controls-hint">ARROWS/WASD=Move &nbsp; SPACE/W=Jump &nbsp; Z/X/CTRL=Attack &nbsp; ESC=Pause</div>
</div>
<!-- Порядок загрузки важен: каждый файл зависит от предыдущих -->
<script src="js/constants.js"></script> <!-- canvas, ctx, W, H, константы физики -->
<script src="js/particles.js"></script> <!-- система частиц -->
<script src="js/input.js"></script> <!-- keys, pressed(), justPressed(), grabFocus() -->
<script src="js/audio.js"></script> <!-- SFX, beep() -->
<script src="js/draw.js"></script> <!-- все функции рисования -->
<script src="js/entities.js"></script> <!-- Player, Raptor, Pterodactyl, Mammoth, Item, ScorePopup -->
<script src="js/levels.js"></script> <!-- LEVELS[] -->
<script src="js/game.js"></script> <!-- игровой цикл, старт -->
</body>
</html>

46
Prehistorik/style.css Normal file
View File

@@ -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;
}