Загрузить файлы в «Prehistorik»
This commit is contained in:
76
Prehistorik/audio.js
Normal file
76
Prehistorik/audio.js
Normal 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
21
Prehistorik/constants.js
Normal 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
28
Prehistorik/index.html
Normal 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 SPACE/W=Jump Z/X/CTRL=Attack 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
46
Prehistorik/style.css
Normal 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user