Не врежься в камни 3.0
by FlashMaker26572 lines19.8 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Не врежься в камни 3.0</title>
<style>
body { margin: 0; background: #0a0a12; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; font-family: Arial; overflow: hidden; touch-action: none; }
canvas { background: #1a1a2e; border: 2px solid #e94560; border-radius: 8px; touch-action: none; }
#hud { font-size: 13px; margin-bottom: 4px; color: #eee; font-weight: bold; text-align: center; }
</style>
</head>
<body>
<div id="hud">🪨 Счёт: 0 | Рекорд: 0 | 🟡 Золото: 0</div>
<canvas id="game" width="360" height="560"></canvas>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const hud = document.getElementById('hud');
// Состояния: 'menu', 'skins', 'playing', 'gameover'
let state = 'menu';
let player, obstacles, goldStones, particles;
let score = 0, best = 0, goldScore = 0;
let spawnTimer = 0, scrollSpeed = 2, time = 0, menuPulse = 0;
// === СКИНЫ ===
const SKINS = [
{ name: 'Шарик', color: '#e94560', stroke: '#b02a40', type: 'circle' },
{ name: 'Звезда', color: '#ffd700', stroke: '#daa520', type: 'star' },
{ name: 'Робот', color: '#00ffcc', stroke: '#0099aa', type: 'robot' },
{ name: 'Кот', color: '#ff8c00', stroke: '#cc6600', type: 'cat' },
{ name: 'Огонь', color: '#ff4400', stroke: '#aa2200', type: 'fire' },
{ name: 'Ледяной', color: '#00ccff', stroke: '#0088aa', type: 'ice' }
];
let currentSkin = 0;
// Кнопки
const btnPlay = { x: 80, y: 340, w: 200, h: 55 };
const btnSkins = { x: 80, y: 410, w: 200, h: 45 };
const btnReset = { x: 80, y: 470, w: 200, h: 40 };
const btnBack = { x: 20, y: 20, w: 90, h: 40 };
// --- ЗВУК ---
let audioCtx = null;
function initAudio() {
if (audioCtx) return;
try { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } catch(e) {}
}
function playSound(freq, dur, type, vol) {
if (!audioCtx) return;
try {
const o = audioCtx.createOscillator();
const g = audioCtx.createGain();
o.type = type || 'square'; o.frequency.value = freq;
g.gain.setValueAtTime(vol || 0.08, audioCtx.currentTime);
g.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + dur);
o.connect(g); g.connect(audioCtx.destination);
o.start(); o.stop(audioCtx.currentTime + dur);
} catch(e) {}
}
function sfxJump() { playSound(500, 0.08, 'square', 0.06); }
function sfxHit() { playSound(100, 0.3, 'sawtooth', 0.15); }
function sfxScore() { playSound(900, 0.08, 'sine', 0.06); }
function sfxGold() { playSound(1200, 0.1, 'sine', 0.1); setTimeout(() => playSound(1600, 0.15, 'sine', 0.1), 80); }
function sfxClick() { playSound(600, 0.05, 'square', 0.06); }
function init() {
player = { x: 100, y: 280, r: 16, vy: 0, rotation: 0 };
obstacles = []; goldStones = []; particles = [];
score = 0; goldScore = 0;
spawnTimer = 0; scrollSpeed = 2; time = 0;
updateHUD();
}
function updateHUD() {
hud.textContent = `🪨 Счёт: ${score} | Рекорд: ${best} | 🟡 ${goldScore} | ${SKINS[currentSkin].name}`;
}
function spawnObstacle() {
const type = Math.random() < 0.15 ? 2 : (Math.random() < 0.25 ? 1 : 0);
const gap = type === 2 ? 140 : 160;
const minH = 60;
const maxH = canvas.height - gap - minH;
const topH = minH + Math.random() * (maxH - minH);
const bottomH = canvas.height - gap - topH;
obstacles.push({
x: canvas.width, topH, bottomH, w: 60, passed: false, type,
baseTopH: topH, baseBottomH: bottomH, phase: Math.random() * 6
});
if (Math.random() < 0.25) {
goldStones.push({ x: canvas.width + 30, y: topH + gap / 2, r: 14, collected: false, pulse: 0 });
}
}
// === РИСОВАНИЕ СКИНОВ ===
function drawSkinShape(px, py, r, skin, rotation) {
ctx.save();
ctx.translate(px, py);
ctx.rotate(rotation);
if (skin.type === 'circle') {
// Шарик
ctx.beginPath(); ctx.arc(0, 0, r, 0, Math.PI * 2);
ctx.fillStyle = skin.color; ctx.fill();
ctx.strokeStyle = skin.stroke; ctx.lineWidth = 3; ctx.stroke();
} else if (skin.type === 'star') {
// Звезда
ctx.beginPath();
for (let i = 0; i < 10; i++) {
const angle = (i * Math.PI / 5) - Math.PI / 2;
const rad = i % 2 === 0 ? r : r * 0.5;
ctx.lineTo(Math.cos(angle) * rad, Math.sin(angle) * rad);
}
ctx.closePath();
ctx.fillStyle = skin.color; ctx.fill();
ctx.strokeStyle = skin.stroke; ctx.lineWidth = 2; ctx.stroke();
} else if (skin.type === 'robot') {
// Робот-квадрат
ctx.fillStyle = skin.color;
ctx.fillRect(-r, -r, r*2, r*2);
ctx.strokeStyle = skin.stroke; ctx.lineWidth = 3;
ctx.strokeRect(-r, -r, r*2, r*2);
// Антенна
ctx.beginPath(); ctx.moveTo(0, -r); ctx.lineTo(0, -r - 6); ctx.stroke();
ctx.fillStyle = '#ff0066';
ctx.beginPath(); ctx.arc(0, -r - 6, 3, 0, Math.PI * 2); ctx.fill();
} else if (skin.type === 'cat') {
// Кот
ctx.beginPath(); ctx.arc(0, 0, r, 0, Math.PI * 2);
ctx.fillStyle = skin.color; ctx.fill();
ctx.strokeStyle = skin.stroke; ctx.lineWidth = 3; ctx.stroke();
// Уши
ctx.fillStyle = skin.color;
ctx.beginPath(); ctx.moveTo(-r*0.7, -r*0.7); ctx.lineTo(-r*0.3, -r*1.3); ctx.lineTo(0, -r*0.7); ctx.fill();
ctx.beginPath(); ctx.moveTo(r*0.7, -r*0.7); ctx.lineTo(r*0.3, -r*1.3); ctx.lineTo(0, -r*0.7); ctx.fill();
} else if (skin.type === 'fire') {
// Огонь
ctx.beginPath();
ctx.moveTo(0, -r);
ctx.quadraticCurveTo(r, -r*0.3, r*0.7, r);
ctx.quadraticCurveTo(0, r*0.6, -r*0.7, r);
ctx.quadraticCurveTo(-r, -r*0.3, 0, -r);
ctx.fillStyle = skin.color; ctx.fill();
ctx.strokeStyle = skin.stroke; ctx.lineWidth = 2; ctx.stroke();
// Внутренний огонь
ctx.beginPath();
ctx.moveTo(0, -r*0.5);
ctx.quadraticCurveTo(r*0.5, 0, 0, r*0.6);
ctx.quadraticCurveTo(-r*0.5, 0, 0, -r*0.5);
ctx.fillStyle = '#ffdd00'; ctx.fill();
} else if (skin.type === 'ice') {
// Лёд (шестиугольник)
ctx.beginPath();
for (let i = 0; i < 6; i++) {
const angle = (i * Math.PI / 3) - Math.PI / 2;
ctx.lineTo(Math.cos(angle) * r, Math.sin(angle) * r);
}
ctx.closePath();
ctx.fillStyle = skin.color; ctx.fill();
ctx.strokeStyle = skin.stroke; ctx.lineWidth = 2; ctx.stroke();
// Блик
ctx.fillStyle = 'rgba(255,255,255,0.6)';
ctx.beginPath(); ctx.arc(-r*0.3, -r*0.3, r*0.3, 0, Math.PI * 2); ctx.fill();
}
ctx.restore();
}
function drawPlayer() {
const skin = SKINS[currentSkin];
const px = player.x, py = player.y;
// Свечение
ctx.fillStyle = skin.color.replace(')', ',0.2)').replace('rgb', 'rgba');
if (skin.color.startsWith('#')) {
ctx.fillStyle = 'rgba(255,255,255,0.15)';
}
ctx.beginPath(); ctx.arc(px, py, player.r + 8, 0, Math.PI * 2); ctx.fill();
drawSkinShape(px, py, player.r, skin, player.rotation);
// Глаза (для всех кроме звезды и огня)
if (skin.type !== 'star' && skin.type !== 'fire') {
ctx.fillStyle = '#fff';
ctx.beginPath();
ctx.arc(px - 5, py - 4, 4, 0, Math.PI * 2);
ctx.arc(px + 5, py - 4, 4, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#000';
ctx.beginPath();
ctx.arc(px - 4, py - 4, 2, 0, Math.PI * 2);
ctx.arc(px + 6, py - 4, 2, 0, Math.PI * 2);
ctx.fill();
}
}
function drawObstacle(o) {
const x = o.x, w = o.w;
if (o.type === 2) {
ctx.fillStyle = 'rgba(255,0,102,0.8)';
ctx.fillRect(x + w/2 - 3, 0, 6, o.topH);
ctx.fillStyle = '#fff';
ctx.fillRect(x + w/2 - 1, 0, 2, o.topH);
ctx.fillStyle = 'rgba(255,0,102,0.8)';
ctx.fillRect(x + w/2 - 3, canvas.height - o.bottomH, 6, o.bottomH);
ctx.fillStyle = '#fff';
ctx.fillRect(x + w/2 - 1, canvas.height - o.bottomH, 2, o.bottomH);
return;
}
ctx.fillStyle = '#5a4a3a';
ctx.beginPath();
ctx.moveTo(x, 0); ctx.lineTo(x + w, 0);
ctx.lineTo(x + w, o.topH - 10); ctx.lineTo(x + w/2, o.topH); ctx.lineTo(x, o.topH - 15);
ctx.closePath(); ctx.fill();
ctx.strokeStyle = '#3a2a1a'; ctx.lineWidth = 2; ctx.stroke();
ctx.fillStyle = '#5a4a3a';
ctx.beginPath();
const by = canvas.height - o.bottomH;
ctx.moveTo(x, canvas.height); ctx.lineTo(x + w, canvas.height);
ctx.lineTo(x + w, by + 15); ctx.lineTo(x + w/2, by); ctx.lineTo(x, by + 10);
ctx.closePath(); ctx.fill(); ctx.stroke();
}
function drawGoldStone(g) {
if (g.collected) return;
const pulse = Math.sin(Date.now() / 150 + g.pulse) * 3;
ctx.fillStyle = 'rgba(255,215,0,0.3)';
ctx.beginPath(); ctx.arc(g.x, g.y, g.r + 8 + pulse, 0, Math.PI * 2); ctx.fill();
ctx.fillStyle = '#ffd700';
ctx.beginPath(); ctx.arc(g.x, g.y, g.r, 0, Math.PI * 2); ctx.fill();
ctx.strokeStyle = '#daa520'; ctx.lineWidth = 3; ctx.stroke();
ctx.fillStyle = 'rgba(255,255,255,0.7)';
ctx.beginPath(); ctx.arc(g.x - 4, g.y - 4, 4, 0, Math.PI * 2); ctx.fill();
ctx.fillStyle = '#b8860b'; ctx.font = 'bold 14px Arial'; ctx.textAlign = 'center';
ctx.fillText('★', g.x, g.y + 5); ctx.textAlign = 'left';
}
// === МЕНЮ ===
function drawMenu() {
menuPulse += 0.05;
const grad = ctx.createLinearGradient(0, 0, 0, canvas.height);
grad.addColorStop(0, '#0a0a2e');
grad.addColorStop(1, '#2a0a2e');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < 40; i++) {
const sx = (i * 137 + time * 0.5) % 360;
const sy = (i * 97) % 560;
ctx.fillStyle = `rgba(255,255,255,${0.2 + (i % 3) * 0.15})`;
ctx.fillRect(sx, sy, 2, 2);
}
const scale = 1 + Math.sin(menuPulse) * 0.03;
ctx.save();
ctx.translate(canvas.width/2, 110);
ctx.scale(scale, scale);
ctx.fillStyle = '#e94560';
ctx.font = 'bold 26px Arial';
ctx.textAlign = 'center';
ctx.fillText('НЕ ВРЕЖЬСЯ', 0, 0);
ctx.fillText('В КАМНИ', 0, 32);
ctx.fillStyle = '#ffd700';
ctx.font = 'bold 18px Arial';
ctx.fillText('3.0', 0, 60);
ctx.restore();
// Показ текущего скина
drawSkinShape(canvas.width/2, 220, 22, SKINS[currentSkin], 0);
ctx.fillStyle = '#fff';
ctx.font = '16px Arial';
ctx.textAlign = 'center';
ctx.fillText('Скин: ' + SKINS[currentSkin].name, canvas.width/2, 265);
ctx.fillStyle = '#fff';
ctx.font = '16px Arial';
ctx.fillText('🏆 Рекорд: ' + best, canvas.width/2, 300);
ctx.textAlign = 'left';
// Кнопка Играть
ctx.fillStyle = '#e94560';
ctx.fillRect(btnPlay.x, btnPlay.y, btnPlay.w, btnPlay.h);
ctx.strokeStyle = '#fff'; ctx.lineWidth = 3;
ctx.strokeRect(btnPlay.x, btnPlay.y, btnPlay.w, btnPlay.h);
ctx.fillStyle = '#fff';
ctx.font = 'bold 22px Arial';
ctx.textAlign = 'center';
ctx.fillText('▶ ИГРАТЬ', btnPlay.x + btnPlay.w/2, btnPlay.y + 36);
// Кнопка Скины
ctx.fillStyle = 'rgba(255,215,0,0.2)';
ctx.fillRect(btnSkins.x, btnSkins.y, btnSkins.w, btnSkins.h);
ctx.strokeStyle = '#ffd700'; ctx.lineWidth = 2;
ctx.strokeRect(btnSkins.x, btnSkins.y, btnSkins.w, btnSkins.h);
ctx.fillStyle = '#ffd700';
ctx.font = '18px Arial';
ctx.fillText('🎨 СКИНЫ', btnSkins.x + btnSkins.w/2, btnSkins.y + 28);
// Кнопка Сброс
ctx.fillStyle = 'rgba(255,255,255,0.1)';
ctx.fillRect(btnReset.x, btnReset.y, btnReset.w, btnReset.h);
ctx.strokeStyle = '#aaa'; ctx.lineWidth = 2;
ctx.strokeRect(btnReset.x, btnReset.y, btnReset.w, btnReset.h);
ctx.fillStyle = '#aaa';
ctx.font = '14px Arial';
ctx.fillText('Сбросить рекорд', btnReset.x + btnReset.w/2, btnReset.y + 25);
ctx.textAlign = 'left';
}
// === ЭКРАН СКИНОВ ===
function drawSkinsMenu() {
const grad = ctx.createLinearGradient(0, 0, 0, canvas.height);
grad.addColorStop(0, '#0a0a2e');
grad.addColorStop(1, '#2a0a2e');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#ffd700';
ctx.font = 'bold 24px Arial';
ctx.textAlign = 'center';
ctx.fillText('ВЫБЕРИ СКИН', canvas.width/2, 60);
ctx.textAlign = 'left';
// Сетка скинов 2x3
const cols = 2, rows = 3;
const cellW = 140, cellH = 130;
const startX = (canvas.width - cols * cellW) / 2 + 10;
const startY = 100;
SKINS.forEach((skin, i) => {
const col = i % cols;
const row = Math.floor(i / cols);
const x = startX + col * cellW + cellW/2;
const y = startY + row * cellH + cellH/2;
// Рамка выбора
if (i === currentSkin) {
ctx.strokeStyle = '#ffd700'; ctx.lineWidth = 3;
ctx.strokeRect(x - 55, y - 55, 110, 110);
ctx.fillStyle = 'rgba(255,215,0,0.1)';
ctx.fillRect(x - 55, y - 55, 110, 110);
} else {
ctx.strokeStyle = 'rgba(255,255,255,0.2)'; ctx.lineWidth = 1;
ctx.strokeRect(x - 55, y - 55, 110, 110);
}
// Скин
drawSkinShape(x, y - 10, 20, skin, 0);
// Название
ctx.fillStyle = i === currentSkin ? '#ffd700' : '#fff';
ctx.font = '14px Arial';
ctx.textAlign = 'center';
ctx.fillText(skin.name, x, y + 40);
ctx.textAlign = 'left';
});
// Кнопка назад
ctx.fillStyle = 'rgba(255,255,255,0.15)';
ctx.fillRect(btnBack.x, btnBack.y, btnBack.w, btnBack.h);
ctx.strokeStyle = '#fff'; ctx.lineWidth = 2;
ctx.strokeRect(btnBack.x, btnBack.y, btnBack.w, btnBack.h);
ctx.fillStyle = '#fff';
ctx.font = '18px Arial';
ctx.textAlign = 'center';
ctx.fillText('← Назад', btnBack.x + btnBack.w/2, btnBack.y + 27);
ctx.textAlign = 'left';
}
function drawGame() {
const grad = ctx.createLinearGradient(0, 0, 0, canvas.height);
grad.addColorStop(0, '#1a1a2e');
grad.addColorStop(1, '#2a2a4e');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < 30; i++) {
const sx = (i * 137 + time * 0.5) % 360;
const sy = (i * 97) % 560;
ctx.fillStyle = `rgba(255,255,255,${0.2 + (i % 3) * 0.1})`;
ctx.fillRect(sx, sy, 2, 2);
}
obstacles.forEach(o => drawObstacle(o));
goldStones.forEach(g => drawGoldStone(g));
particles.forEach(p => {
ctx.globalAlpha = p.life / p.maxLife;
ctx.fillStyle = p.color;
ctx.fillRect(p.x, p.y, p.size, p.size);
ctx.globalAlpha = 1;
});
if (state !== 'gameover') drawPlayer();
if (state === 'gameover') {
ctx.fillStyle = 'rgba(0,0,0,0.75)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#e94560';
ctx.font = 'bold 28px Arial';
ctx.textAlign = 'center';
ctx.fillText('ИГРА ОКОНЧЕНА', canvas.width/2, canvas.height/2 - 80);
ctx.fillStyle = '#fff';
ctx.font = '20px Arial';
ctx.fillText('Счёт: ' + score, canvas.width/2, canvas.height/2 - 35);
ctx.fillStyle = '#ffd700';
ctx.fillText('Золото: ' + goldScore, canvas.width/2, canvas.height/2 - 5);
ctx.fillStyle = '#fff';
ctx.fillText('Рекорд: ' + best, canvas.width/2, canvas.height/2 + 25);
ctx.font = '15px Arial';
ctx.fillStyle = '#aaa';
ctx.fillText('Нажми, чтобы выйти в меню', canvas.width/2, canvas.height/2 + 90);
ctx.textAlign = 'left';
}
}
function draw() {
if (state === 'menu') drawMenu();
else if (state === 'skins') drawSkinsMenu();
else drawGame();
}
function update() {
if (state !== 'playing') return;
time++;
player.vy += 0.5;
if (player.vy > 10) player.vy = 10;
player.y += player.vy;
player.rotation += 0.05;
if (player.y - player.r < 0) { player.y = player.r; player.vy = 0; }
if (player.y + player.r > canvas.height) { player.y = canvas.height - player.r; player.vy = 0; }
spawnTimer++;
const spawnRate = Math.max(40, 100 - Math.min(score * 3, 60));
if (spawnTimer > spawnRate) { spawnTimer = 0; spawnObstacle(); }
obstacles.forEach((o, i) => {
o.x -= scrollSpeed + score * 0.03;
if (o.type === 1) {
o.phase += 0.05;
o.topH = o.baseTopH + Math.sin(o.phase) * 30;
o.bottomH = o.baseBottomH - Math.sin(o.phase) * 30;
}
const px = player.x, py = player.y;
if (px + player.r > o.x && px - player.r < o.x + o.w) {
let hit = false;
if (o.type === 2) {
if (px + player.r > o.x + o.w/2 - 3 && px - player.r < o.x + o.w/2 + 3) {
hit = (py - player.r < o.topH || py + player.r > canvas.height - o.bottomH);
}
} else {
hit = (py - player.r < o.topH || py + player.r > canvas.height - o.bottomH);
}
if (hit) {
state = 'gameover';
sfxHit();
if (score > best) best = score;
updateHUD();
for (let k = 0; k < 15; k++) {
particles.push({
x: px, y: py,
vx: (Math.random() - 0.5) * 10, vy: (Math.random() - 0.5) * 10,
life: 30, maxLife: 30, color: '#e94560', size: 3 + Math.random() * 4
});
}
}
}
if (!o.passed && o.x + o.w < player.x) {
o.passed = true; score++; sfxScore(); updateHUD();
}
if (o.x + o.w < -50) obstacles.splice(i, 1);
});
goldStones.forEach((g, i) => {
g.x -= scrollSpeed + score * 0.03;
const dx = player.x - g.x;
const dy = player.y - g.y;
if (Math.sqrt(dx*dx + dy*dy) < player.r + g.r) {
g.collected = true; goldScore += 5; score += 5;
sfxGold();
for (let k = 0; k < 10; k++) {
particles.push({
x: g.x, y: g.y,
vx: (Math.random() - 0.5) * 8, vy: (Math.random() - 0.5) * 8 - 2,
life: 30, maxLife: 30, color: '#ffd700', size: 3 + Math.random() * 3
});
}
updateHUD();
}
if (g.x < -50) goldStones.splice(i, 1);
});
particles.forEach((p, i) => {
p.x += p.vx; p.y += p.vy; p.vy += 0.2; p.life--;
if (p.life <= 0) particles.splice(i, 1);
});
}
function loop() { update(); draw(); requestAnimationFrame(loop); }
// === УПРАВЛЕНИЕ ===
function handleTap(x, y) {
initAudio();
if (state === 'menu') {
if (x > btnPlay.x && x < btnPlay.x + btnPlay.w && y > btnPlay.y && y < btnPlay.y + btnPlay.h) {
sfxClick(); init(); state = 'playing'; return;
}
if (x > btnSkins.x && x < btnSkins.x + btnSkins.w && y > btnSkins.y && y < btnSkins.y + btnSkins.h) {
sfxClick(); state = 'skins'; return;
}
if (x > btnReset.x && x < btnReset.x + btnReset.w && y > btnReset.y && y < btnReset.y + btnReset.h) {
sfxClick(); best = 0; updateHUD(); return;
}
return;
}
if (state === 'skins') {
// Кнопка назад
if (x > btnBack.x && x < btnBack.x + btnBack.w && y > btnBack.y && y < btnBack.y + btnBack.h) {
sfxClick(); state = 'menu'; return;
}
// Сетка скинов
const cols = 2, cellW = 140, cellH = 130;
const startX = (canvas.width - cols * cellW) / 2 + 10;
const startY = 100;
for (let i = 0; i < SKINS.length; i++) {
const col = i % cols;
const row = Math.floor(i / cols);
const cx = startX + col * cellW + cellW/2;
const cy = startY + row * cellH + cellH/2;
if (x > cx - 55 && x < cx + 55 && y > cy - 55 && y < cy + 55) {
currentSkin = i;
sfxClick();
updateHUD();
return;
}
}
return;
}
if (state === 'gameover') { sfxClick(); state = 'menu'; return; }
if (state === 'playing') { player.vy = -6.5; sfxJump(); }
}
canvas.addEventListener('touchstart', e => {
e.preventDefault();
const rect = canvas.getBoundingClientRect();
const t = e.touches[0];
handleTap(t.clientX - rect.left, t.clientY - rect.top);
});
canvas.addEventListener('mousedown', e => {
e.preventDefault();
const rect = canvas.getBoundingClientRect();
handleTap(e.clientX - rect.left, e.clientY - rect.top);
});
document.addEventListener('keydown', e => {
if (e.key === ' ' || e.key === 'ArrowUp' || e.key === 'w' || e.key === 'W') {
if (state === 'playing') { player.vy = -6.5; sfxJump(); }
else if (state === 'menu') { init(); state = 'playing'; sfxClick(); }
else if (state === 'gameover') { state = 'menu'; sfxClick(); }
else if (state === 'skins') { state = 'menu'; sfxClick(); }
e.preventDefault();
}
});
init();
state = 'menu';
loop();
</script>
</body>
</html>Game Source: Не врежься в камни 3.0
Creator: FlashMaker26
Libraries: none
Complexity: complex (572 lines, 19.8 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: 3-0-flashmaker26" to link back to the original. Then publish at arcadelab.ai/publish.