🎮ArcadeLab

Космо Турбикс 🚀

by PixelFox56
367 lines13.8 KB
▶ Play
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Космо Турбикс 🚀</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🚀</text></svg>">
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#000;color:#fff;font-family:'Segoe UI',Arial,sans-serif;overflow:hidden;user-select:none}
#game{display:block;width:100vw;height:100vh;touch-action:none}
.hud{position:absolute;top:10px;left:10px;right:10px;display:flex;justify-content:space-between;z-index:10;pointer-events:none;font-weight:bold;color:#0ff;text-shadow:0 0 10px #0ff;font-size:14px;flex-wrap:wrap;gap:5px}
.hud-box{background:rgba(0,0,0,0.7);border:2px solid #0ff;border-radius:8px;padding:5px 10px}
#start{position:absolute;top:0;left:0;width:100vw;height:100vh;background:rgba(0,0,0,0.9);z-index:100;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:20px}
#start h1{font-size:44px;background:linear-gradient(180deg,#0ff,#00f);-webkit-background-clip:text;background-clip:text;color:transparent;margin-bottom:15px;font-weight:900}
#start p{color:#88aaff;font-size:15px;margin-bottom:20px;line-height:1.6}
#start button{background:linear-gradient(180deg,#00f,#006);color:#fff;border:2px solid #0ff;border-radius:14px;padding:18px 50px;font-size:20px;font-weight:bold;cursor:pointer;font-family:inherit;box-shadow:0 0 30px #0ff}
#controls{position:absolute;bottom:20px;left:0;right:0;display:flex;justify-content:space-between;padding:0 20px;z-index:10;pointer-events:none;gap:10px}
#controls > * {pointer-events:auto}
.dpad{display:grid;grid-template-columns:repeat(3,55px);grid-template-rows:repeat(3,55px);gap:4px}
.dpad button{background:rgba(0,100,200,0.5);border:2px solid #0ff;border-radius:12px;color:#0ff;font-size:22px;font-weight:bold;cursor:pointer;font-family:inherit}
.dpad .empty{visibility:hidden}
.actions{display:flex;flex-direction:column;gap:10px;align-items:flex-end}
.action-btn{width:80px;height:80px;border-radius:50%;border:3px solid #0ff;background:radial-gradient(circle,#0080ff,#001a66);color:#0ff;font-size:14px;font-weight:900;cursor:pointer;font-family:inherit;box-shadow:0 0 20px #0ff}
.fire{width:100px;height:100px;border-radius:50%;border:4px solid #0ff;background:radial-gradient(circle,#0080ff,#001a66);color:#0ff;font-size:20px;font-weight:900;cursor:pointer;font-family:inherit;box-shadow:0 0 30px #0ff}
#abilities{position:absolute;top:80px;left:10px;z-index:10;display:flex;flex-direction:column;gap:8px;pointer-events:none}
.ability{background:rgba(0,0,0,0.7);border:2px solid #0ff;border-radius:8px;padding:6px 10px;color:#0ff;font-size:12px;font-weight:bold;opacity:0.4}
.ability.active{opacity:1;box-shadow:0 0 15px #0ff}
</style>
</head>
<body>

<canvas id="game"></canvas>

<div class="hud">
  <div class="hud-box">🏆 <span id="score">0</span></div>
  <div class="hud-box">❤️ <span id="lives">3</span></div>
  <div class="hud-box">🌊 <span id="wave">1</span></div>
  <div class="hud-box">💎 <span id="crystals">0</span></div>
</div>

<div id="abilities">
  <div class="ability" id="ab-shield">🛡️ Щит: <span id="cd-shield">0</span></div>
  <div class="ability" id="ab-bomb">💥 Бомба: <span id="cd-bomb">0</span></div>
  <div class="ability" id="ab-speed">⚡ Скорость: <span id="cd-speed">0</span></div>
</div>

<div id="controls">
  <div class="dpad">
    <button class="empty"></button>
    <button ontouchstart="setKey('up',true)" ontouchend="setKey('up',false)">▲</button>
    <button class="empty"></button>
    <button ontouchstart="setKey('left',true)" ontouchend="setKey('left',false)">◀</button>
    <button class="empty"></button>
    <button ontouchstart="setKey('right',true)" ontouchend="setKey('right',false)">▶</button>
    <button class="empty"></button>
    <button ontouchstart="setKey('down',true)" ontouchend="setKey('down',false)">▼</button>
    <button class="empty"></button>
  </div>
  <div class="actions">
    <button class="action-btn" onclick="useShield()">🛡️<br>ЩИТ</button>
    <button class="action-btn" onclick="useBomb()">💥<br>БОМБА</button>
    <button class="action-btn" onclick="useSpeed()">⚡<br>СКОРОСТЬ</button>
    <button class="fire" ontouchstart="fire()" onmousedown="fire()">🔥</button>
  </div>
</div>

<div id="start">
  <h1>🚀 КОСМО ТУРБИКС</h1>
  <p>Управляй кораблём, уничтожай инопланетян!<br>
  ▲▼◀▶ — движение, 🔥 — выстрел<br>
  🛡️ Щит · 💥 Бомба · ⚡ Скорость — 3 новые фишки!</p>
  <button onclick="startGame()">🚀 НАЧАТЬ</button>
</div>

<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
let W, H;
function resize(){ W = canvas.width = window.innerWidth; H = canvas.height = window.innerHeight; }
resize();
window.addEventListener('resize', resize);

let keys = { up:false, down:false, left:false, right:false };
function setKey(k, v){ keys[k] = v; }
document.onkeydown = e => {
  if(e.key==='ArrowUp'||e.key==='w') keys.up = true;
  if(e.key==='ArrowDown'||e.key==='s') keys.down = true;
  if(e.key==='ArrowLeft'||e.key==='a') keys.left = true;
  if(e.key==='ArrowRight'||e.key==='d') keys.right = true;
  if(e.key===' ') fire();
  if(e.key==='1') useShield();
  if(e.key==='2') useBomb();
  if(e.key==='3') useSpeed();
};
document.onkeyup = e => {
  if(e.key==='ArrowUp'||e.key==='w') keys.up = false;
  if(e.key==='ArrowDown'||e.key==='s') keys.down = false;
  if(e.key==='ArrowLeft'||e.key==='a') keys.left = false;
  if(e.key==='ArrowRight'||e.key==='d') keys.right = false;
};

let ship, bullets, enemies, particles, bonuses, score, lives, wave, running, lastTime, cooldown, crystals;
// Фишки
let shieldTime, shieldCooldown, bombCooldown, speedTime, speedCooldown;

function startGame(){
  document.getElementById('start').style.display = 'none';
  ship = { x: W/2, y: H/2, angle: -Math.PI/2, speed: 300, hp: 3 };
  bullets = []; enemies = []; particles = []; bonuses = [];
  score = 0; lives = 3; wave = 1; running = true; crystals = 0;
  cooldown = 0; lastTime = performance.now();
  shieldTime = 0; shieldCooldown = 0;
  bombCooldown = 0;
  speedTime = 0; speedCooldown = 0;
  updateHud();
  spawnWave();
  requestAnimationFrame(loop);
}

function spawnWave(){
  const count = 3 + wave;
  for(let i=0; i<count; i++){
    const a = Math.random() * Math.PI * 2;
    const d = 400 + Math.random() * 200;
    enemies.push({
      x: W/2 + Math.cos(a) * d, y: H/2 + Math.sin(a) * d,
      angle: 0, hp: 20 + wave * 10, speed: 60 + wave * 10,
      lastShot: 0, shotInterval: 2, radius: 15 + wave
    });
  }
}

// ========== ФИШКА 1: ЩИТ ==========
function useShield(){
  if(!running) return;
  if(shieldCooldown > 0) return;
  shieldTime = 3;
  shieldCooldown = 15;
  showToast('🛡️ ЩИТ АКТИВЕН!');
}

// ========== ФИШКА 2: БОМБА ==========
function useBomb(){
  if(!running) return;
  if(bombCooldown > 0) return;
  if(enemies.length === 0) return;
  bombCooldown = 20;
  enemies.forEach(e => {
    for(let k=0; k<10; k++){
      particles.push({x:e.x, y:e.y, vx:(Math.random()-0.5)*500, vy:(Math.random()-0.5)*500, life:0.8});
    }
    score += 100;
  });
  enemies = [];
  showToast('💥 БОМБА! Все враги уничтожены!');
}

// ========== ФИШКА 3: УСКОРЕНИЕ ==========
function useSpeed(){
  if(!running) return;
  if(speedCooldown > 0) return;
  speedTime = 5;
  speedCooldown = 15;
  showToast('⚡ УСКОРЕНИЕ!');
}

function showToast(msg){
  const t = document.createElement('div');
  t.style.cssText = 'position:fixed;top:80px;left:50%;transform:translateX(-50%);background:rgba(0,255,255,0.9);color:#000;padding:12px 24px;border-radius:10px;font-weight:bold;z-index:200;pointer-events:none;font-size:14px;';
  t.innerText = msg;
  document.body.appendChild(t);
  setTimeout(() => t.remove(), 1500);
}

function fire(){
  if(!running) return;
  if(cooldown > 0) return;
  cooldown = 0.2;
  bullets.push({
    x: ship.x + Math.cos(ship.angle) * 20,
    y: ship.y + Math.sin(ship.angle) * 20,
    vx: Math.cos(ship.angle) * 700,
    vy: Math.sin(ship.angle) * 700,
    life: 2
  });
}

function updateHud(){
  document.getElementById('score').innerText = score;
  document.getElementById('lives').innerText = lives;
  document.getElementById('wave').innerText = wave;
  document.getElementById('crystals').innerText = crystals;
  document.getElementById('cd-shield').innerText = Math.ceil(shieldCooldown) + 'с';
  document.getElementById('cd-bomb').innerText = Math.ceil(bombCooldown) + 'с';
  document.getElementById('cd-speed').innerText = Math.ceil(speedCooldown) + 'с';
  document.getElementById('ab-shield').className = 'ability' + (shieldTime > 0 ? ' active' : '');
  document.getElementById('ab-speed').className = 'ability' + (speedTime > 0 ? ' active' : '');
}

let hudTimer = 0;
function loop(now){
  if(!running) return;
  requestAnimationFrame(loop);
  const dt = Math.min((now - lastTime)/1000, 0.1);
  lastTime = now;
  cooldown = Math.max(0, cooldown - dt);
  shieldTime = Math.max(0, shieldTime - dt);
  shieldCooldown = Math.max(0, shieldCooldown - dt);
  bombCooldown = Math.max(0, bombCooldown - dt);
  speedTime = Math.max(0, speedTime - dt);
  speedCooldown = Math.max(0, speedCooldown - dt);

  hudTimer += dt;
  if(hudTimer > 0.1){ hudTimer = 0; updateHud(); }

  // Движение (со ускорением)
  const speedMult = speedTime > 0 ? 2 : 1;
  const sp = ship.speed * speedMult * dt;
  if(keys.up){ ship.x += Math.cos(ship.angle) * sp; ship.y += Math.sin(ship.angle) * sp; }
  if(keys.down){ ship.x -= Math.cos(ship.angle) * sp; ship.y -= Math.sin(ship.angle) * sp; }
  if(keys.left) ship.angle -= 3 * dt;
  if(keys.right) ship.angle += 3 * dt;
  ship.x = Math.max(20, Math.min(W-20, ship.x));
  ship.y = Math.max(20, Math.min(H-20, ship.y));

  // Пули
  for(let i = bullets.length-1; i >= 0; i--){
    const b = bullets[i];
    b.x += b.vx * dt; b.y += b.vy * dt; b.life -= dt;
    if(b.life <= 0 || b.x < 0 || b.x > W || b.y < 0 || b.y > H){ bullets.splice(i,1); continue; }
    for(let j = enemies.length-1; j >= 0; j--){
      const e = enemies[j];
      if(Math.hypot(b.x-e.x, b.y-e.y) < e.radius){
        e.hp -= 25; bullets.splice(i,1);
        for(let k=0; k<5; k++) particles.push({x:e.x, y:e.y, vx:(Math.random()-0.5)*300, vy:(Math.random()-0.5)*300, life:0.5});
        if(e.hp <= 0){
          enemies.splice(j,1); score += 100; crystals += Math.random() < 0.3 ? 1 : 0;
        }
        break;
      }
    }
  }

  // Враги
  enemies.forEach(e => {
    const dx = ship.x - e.x, dy = ship.y - e.y;
    const dist = Math.hypot(dx, dy);
    e.angle = Math.atan2(dy, dx);
    if(dist > 100){ e.x += (dx/dist) * e.speed * dt; e.y += (dy/dist) * e.speed * dt; }
    e.lastShot += dt;
    if(e.lastShot > e.shotInterval && dist < 500){
      e.lastShot = 0;
      bullets.push({x:e.x, y:e.y, vx:Math.cos(e.angle)*400, vy:Math.sin(e.angle)*400, life:2, enemy:true});
    }
    if(dist < e.radius + 15 && shieldTime <= 0){
      lives--; updateHud();
      if(lives <= 0) gameOver();
      e.hp = 0;
    }
  });
  enemies = enemies.filter(e => e.hp > 0);

  // Попадание в игрока
  for(let i = bullets.length-1; i >= 0; i--){
    const b = bullets[i];
    if(b.enemy && Math.hypot(b.x-ship.x, b.y-ship.y) < 15 && shieldTime <= 0){
      bullets.splice(i,1);
      lives--; updateHud();
      if(lives <= 0) gameOver();
    }
  }

  // Частицы
  for(let i = particles.length-1; i >= 0; i--){
    const p = particles[i];
    p.x += p.vx * dt; p.y += p.vy * dt; p.life -= dt;
    if(p.life <= 0) particles.splice(i,1);
  }

  if(enemies.length === 0){
    wave++; updateHud();
    spawnWave();
  }

  draw();
}

function draw(){
  ctx.fillStyle = '#000';
  ctx.fillRect(0, 0, W, H);
  // Звёзды
  ctx.fillStyle = '#fff';
  for(let i = 0; i < 80; i++){
    const x = (i * 137) % W;
    const y = (i * 251) % H;
    ctx.fillRect(x, y, 1.5, 1.5);
  }

  // Корабль
  ctx.save();
  ctx.translate(ship.x, ship.y);
  ctx.rotate(ship.angle);
  // Щит вокруг
  if(shieldTime > 0){
    ctx.strokeStyle = '#0ff';
    ctx.lineWidth = 3;
    ctx.beginPath();
    ctx.arc(0, 0, 30, 0, Math.PI * 2);
    ctx.stroke();
  }
  ctx.fillStyle = speedTime > 0 ? '#ff0' : '#0ff';
  ctx.beginPath();
  ctx.moveTo(20, 0); ctx.lineTo(-15, -12); ctx.lineTo(-8, 0); ctx.lineTo(-15, 12);
  ctx.closePath(); ctx.fill();
  ctx.strokeStyle = '#fff'; ctx.lineWidth = 2; ctx.stroke();
  ctx.restore();

  // Враги
  enemies.forEach(e => {
    ctx.save();
    ctx.translate(e.x, e.y);
    ctx.fillStyle = '#f0f';
    ctx.beginPath();
    ctx.arc(0, 0, e.radius, 0, Math.PI * 2);
    ctx.fill();
    ctx.strokeStyle = '#fff'; ctx.lineWidth = 2; ctx.stroke();
    ctx.restore();
  });

  // Пули
  bullets.forEach(b => {
    ctx.fillStyle = b.enemy ? '#f00' : (speedTime > 0 ? '#ff0' : '#fff');
    ctx.beginPath();
    ctx.arc(b.x, b.y, 4, 0, Math.PI * 2);
    ctx.fill();
  });

  // Частицы
  particles.forEach(p => {
    ctx.fillStyle = 'rgba(255,200,0,' + (p.life * 2) + ')';
    ctx.fillRect(p.x-2, p.y-2, 4, 4);
  });
}

function gameOver(){
  running = false;
  ctx.fillStyle = 'rgba(0,0,0,0.9)';
  ctx.fillRect(0, 0, W, H);
  ctx.fillStyle = '#0ff';
  ctx.font = 'bold 40px Arial';
  ctx.textAlign = 'center';
  ctx.fillText('💥 ИГРА ОКОНЧЕНА', W/2, H/2 - 40);
  ctx.font = 'bold 24px Arial';
  ctx.fillText('Счёт: ' + score, W/2, H/2 + 10);
  ctx.font = '18px Arial';
  ctx.fillStyle = '#88aaff';
  ctx.fillText('Нажми, чтобы играть снова', W/2, H/2 + 60);
  canvas.onclick = () => {
    canvas.onclick = null;
    document.getElementById('start').style.display = 'flex';
  };
}
</script>

</body>
</html>

Game Source: Космо Турбикс 🚀

Creator: PixelFox56

Libraries: none

Complexity: complex (367 lines, 13.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: game-pixelfox56-muts6h5v" to link back to the original. Then publish at arcadelab.ai/publish.