Загрузка данных
@echo off
chcp 65001 >nul
set "SELF=%~f0"
powershell -NoProfile -ExecutionPolicy Bypass -Command "$f=[IO.File]::ReadAllText($env:SELF,[Text.Encoding]::UTF8); Invoke-Expression ($f -split ('#===PS'+'_CODE==='))[1]"
exit /b
#===PS_CODE===
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::CursorVisible = $false
$Host.UI.RawUI.WindowTitle = "CYBER GALAXY: OVERDRIVE"
$ESC = [char]27
$W = 64
$H = 24
$grid = New-Object char[] ($W * $H)
$cols = New-Object int[] ($W * $H)
$rnd = New-Object System.Random
function Set-Cell([int]$x, [int]$y, [char]$ch, [int]$c) {
if ($x -ge 0 -and $x -lt $W -and $y -ge 0 -and $y -lt $H) {
$idx = $y * $W + $x
$script:grid[$idx] = $ch
$script:cols[$idx] = $c
}
}
function Draw-Text([int]$x, [int]$y, [string]$text, [int]$c) {
for ($i = 0; $i -lt $text.Length; $i++) {
Set-Cell ($x + $i) $y $text[$i] $c
}
}
function Spawn-Explosion([double]$ex, [double]$ey, [int]$count) {
$chars = @('*', '+', '.', 'o', 'x')
$pcols = @(93, 91, 33, 31, 97)
for ($i = 0; $i -lt $count; $i++) {
$ang = $rnd.NextDouble() * 6.283
$spd = 0.3 + $rnd.NextDouble() * 1.2
[void]$particles.Add(@{
x = $ex; y = $ey
vx = [Math]::Cos($ang) * $spd * 1.6
vy = [Math]::Sin($ang) * $spd
life = $rnd.Next(5, 14)
ch = $chars[$rnd.Next($chars.Count)]
c = $pcols[$rnd.Next($pcols.Count)]
})
}
}
: outerLoop while ($true) {
Clear-Host
$px = 32; $py = 20
$hp = 100; $ult = 50; $score = 0; $weapon = 1; $wave = 1
$nextBossScore = 250
$boss = $null
$tick = 0
$bullets = New-Object System.Collections.ArrayList
$ebullets = New-Object System.Collections.ArrayList
$enemies = New-Object System.Collections.ArrayList
$particles = New-Object System.Collections.ArrayList
$items = New-Object System.Collections.ArrayList
$stars = New-Object System.Collections.ArrayList
for ($i = 0; $i -lt 38; $i++) {
[void]$stars.Add(@{
x = $rnd.Next(1, $W - 1)
y = $rnd.NextDouble() * ($H - 2) + 1
spd = if ($i % 3 -eq 0) { 0.45 } else { 0.18 }
ch = if ($i % 3 -eq 0) { '*' } else { '.' }
c = if ($i % 3 -eq 0) { 37 } else { 90 }
})
}
# Главный игровой цикл
while ($hp -gt 0) {
$sw = [System.Diagnostics.Stopwatch]::StartNew()
$tick++
# --- СЧИТЫВАНИЕ УПРАВЛЕНИЯ ---
$mx = 0; $my = 0; $useUlt = $false
while ([Console]::KeyAvailable) {
$k = [Console]::ReadKey($true).Key
switch ($k) {
'LeftArrow' { $mx = -2 }
'A' { $mx = -2 }
'RightArrow' { $mx = 2 }
'D' { $mx = 2 }
'UpArrow' { $my = -1 }
'W' { $my = -1 }
'DownArrow' { $my = 1 }
'S' { $my = 1 }
'Spacebar' { $useUlt = $true }
'Escape' { Clear-Host; [Console]::CursorVisible = $true; exit }
}
}
$px = [Math]::Max(3, [Math]::Min($W - 4, $px + $mx))
$py = [Math]::Max(4, [Math]::Min($H - 3, $py + $my))
# --- УЛЬТРА-ШТОРМ (ПРОБЕЛ) ---
if ($useUlt -and $ult -ge 100) {
$ult = 0
$ebullets.Clear()
for ($bx = 2; $bx -lt ($W - 2); $bx += 2) {
[void]$bullets.Add(@{ x = $bx; y = $py - 1; vx = 0; vy = -1.5; c = 96; ch = '!' })
}
Spawn-Explosion $px $py 25
}
# --- АВТО-СТРЕЛЬБА КОРАБЛЯ ---
if ($tick % 4 -eq 0) {
if ($weapon -eq 1) {
[void]$bullets.Add(@{ x = $px; y = $py - 1; vx = 0; vy = -1.2; c = 96; ch = '|' })
} elseif ($weapon -eq 2) {
[void]$bullets.Add(@{ x = $px - 1; y = $py - 1; vx = 0; vy = -1.2; c = 96; ch = '|' })
[void]$bullets.Add(@{ x = $px + 1; y = $py - 1; vx = 0; vy = -1.2; c = 96; ch = '|' })
} elseif ($weapon -eq 3) {
[void]$bullets.Add(@{ x = $px; y = $py - 1; vx = 0; vy = -1.3; c = 93; ch = '!' })
[void]$bullets.Add(@{ x = $px - 2; y = $py; vx = -0.25; vy = -1.1; c = 96; ch = '/' })
[void]$bullets.Add(@{ x = $px + 2; y = $py; vx = 0.25; vy = -1.1; c = 96; ch = '\' })
} else {
[void]$bullets.Add(@{ x = $px - 1; y = $py - 1; vx = 0; vy = -1.4; c = 93; ch = '!' })
[void]$bullets.Add(@{ x = $px + 1; y = $py - 1; vx = 0; vy = -1.4; c = 93; ch = '!' })
[void]$bullets.Add(@{ x = $px - 2; y = $py; vx = -0.35; vy = -1.2; c = 95; ch = '\' })
[void]$bullets.Add(@{ x = $px + 2; y = $py; vx = 0.35; vy = -1.2; c = 95; ch = '/' })
}
}
# --- СПАВН ВРАГОВ И БОССА ---
if ($null -eq $boss -and $score -ge $nextBossScore) {
$maxB = 40 + $wave * 20
$boss = @{ x = 32.0; y = 3.0; vx = 0.6; hp = $maxB; maxHp = $maxB }
}
$spawnRate = [Math]::Max(8, 22 - $wave * 2)
if ($null -eq $boss -and ($tick % $spawnRate -eq 0)) {
$type = if ($rnd.Next(100) -lt 28) { 2 } else { 1 }
[void]$enemies.Add(@{
x = [double]$rnd.Next(4, $W - 5)
y = 2.0
vx = ($rnd.NextDouble() - 0.5) * 0.5
vy = if ($type -eq 1) { 0.28 + $wave * 0.03 } else { 0.16 }
hp = if ($type -eq 1) { 1 + [int]($wave / 3) } else { 4 + $wave }
type = $type
})
}
# --- ОЧИСТКА БУФЕРА КАДРА ---
for ($i = 0; $i -lt ($W * $H); $i++) { $grid[$i] = ' '; $cols[$i] = 37 }
# --- ОБНОВЛЕНИЕ ЗВЕЗД ---
foreach ($s in $stars) {
$s.y += $s.spd
if ($s.y -ge ($H - 1)) { $s.y = 1.0; $s.x = $rnd.Next(1, $W - 1) }
Set-Cell ([int]$s.x) ([int]$s.y) $s.ch $s.c
}
# --- ОБНОВЛЕНИЕ БОНУСОВ ---
for ($i =$items.Count - 1; $i -ge 0; $i--) {
$it =$items[$i]$it.y += 0.25
$ix = [int][Math]::Round($it.x); $iy = [int][Math]::Round($it.y)
if ([Math]::Abs($ix -$px) -le 2 -and [Math]::Abs($iy -$py) -le 1) {
if ($it.t -eq 'W') {$weapon = [Math]::Min(4, $weapon + 1);$score += 25 }
elseif ($it.t -eq '+') { $hp = [Math]::Min(100,$hp + 30) }
elseif ($it.t -eq 'E') { $ult = [Math]::Min(100,$ult + 50) }
$items.RemoveAt($i); continue
}
if ($iy -ge ($H - 1)) {$items.RemoveAt($i); continue }$ic = if ($it.t -eq 'W') { 96 } elseif ($it.t -eq '+') { 92 } else { 93 }
Draw-Text ($ix - 1) $iy "[$($it.t)]" $ic
}
# --- ЛОГИКА БОССА ---
if ($null -ne$boss) {
$boss.x +=$boss.vx
if ($boss.x -le 8 -or $boss.x -ge ($W - 9)) { $boss.vx = -$boss.vx }
$bx = [int][Math]::Round($boss.x); $by = [int][Math]::Round($boss.y)
Draw-Text ($bx - 6)$by "╔═══╦═══╦═══╗" 95
Draw-Text ($bx - 6) ($by + 1) "╚═╦═╩═█═╩═╦═╝" 91
Draw-Text ($bx - 4) ($by + 2) "V V V" 93
if ($tick % 14 -eq 0) {
[void]$ebullets.Add(@{ x = $bx - 4; y =$by + 2; vx = 0; vy = 0.65 })
[void]$ebullets.Add(@{ x =$bx + 4; y = $by + 2; vx = 0; vy = 0.65 })$dx = ($px -$bx) * 0.04
[void]$ebullets.Add(@{ x =$bx; y = $by + 2; vx =$dx; vy = 0.7 })
}
}
# --- ОБНОВЛЕНИЕ ВРАГОВ ---
for ($i = $enemies.Count - 1; $i -ge 0; $i--) {$e = $enemies[$i]
$e.x +=$e.vx; $e.y +=$e.vy
if ($e.x -le 3 -or $e.x -ge ($W - 4)) { $e.vx = -$e.vx }
$ex = [int][Math]::Round($e.x); $ey = [int][Math]::Round($e.y)
if ($ey -ge ($H - 1)) { $enemies.RemoveAt($i); continue }
# Столкновение с игроком
if ([Math]::Abs($ex - $px) -le 2 -and [Math]::Abs($ey - $py) -le 1) {$hp -= 20
Spawn-Explosion $ex$ey 12
$enemies.RemoveAt($i); continue
}
# Выстрелы врагов
if ($e.type -eq 2 -and ($tick % 28 -eq 0)) {
[void]$ebullets.Add(@{ x = $ex; y =$ey + 1; vx = 0; vy = 0.6 })
}
if ($e.type -eq 1) { Draw-Text ($ex - 1)$ey "<V>" 91 }
else { Draw-Text ($ex - 2)$ey "[=O=]" 95 }
}
# --- ОБНОВЛЕНИЕ ПУЛЬ ИГРОКА ---
for ($i = $bullets.Count - 1; $i -ge 0; $i--) {$b = $bullets[$i]
$b.x +=$b.vx; $b.y +=$b.vy
$bx = [int][Math]::Round($b.x); $by = [int][Math]::Round($b.y)
if ($by -le 1 -or$bx -le 1 -or $bx -ge ($W - 1)) { $bullets.RemoveAt($i); continue }
$hit =$false
# Попадание по боссу
if ($null -ne$boss) {
if ([Math]::Abs($bx - $boss.x) -le 6 -and [Math]::Abs($by - ($boss.y + 1)) -le 1) {$boss.hp--
Spawn-Explosion $bx$by 3
$bullets.RemoveAt($i)
if ($boss.hp -le 0) {
Spawn-Explosion $boss.x ($boss.y + 1) 40
$score += 150$wave++
$nextBossScore =$score + 250 + ($wave * 50)
[void]$items.Add(@{ x = $boss.x - 2; y =$boss.y; t = 'W' })
[void]$items.Add(@{ x = $boss.x + 2; y =$boss.y; t = '+' })
$boss =$null
}
continue
}
}
# Попадание по обычным врагам
for ($j = $enemies.Count - 1; $j -ge 0; $j--) {$e = $enemies[$j]
$rad = if ($e.type -eq 1) { 1.8 } else { 2.6 }
if ([Math]::Abs($bx -$e.x) -le $rad -and [Math]::Abs($by - $e.y) -le 1.0) {$e.hp--
$hit =$true
Spawn-Explosion $bx$by 3
if ($e.hp -le 0) {
Spawn-Explosion $e.x $e.y 12
$score += if ($e.type -eq 1) { 10 } else { 25 }
$ult = [Math]::Min(100,$ult + 6)
if ($rnd.Next(100) -lt 22) {$types = @('W', '+', 'E')
[void]$items.Add(@{ x = $e.x; y =$e.y; t = $types[$rnd.Next(3)] })
}
$enemies.RemoveAt($j)
}
break
}
}
if ($hit) { $bullets.RemoveAt($i); continue }
Set-Cell $bx$by $b.ch $b.c
}
# --- ПУЛИ ВРАГОВ ---
for ($i = $ebullets.Count - 1; $i -ge 0; $i--) {$eb = $ebullets[$i]
$eb.x +=$eb.vx; $eb.y +=$eb.vy
$bx = [int][Math]::Round($eb.x); $by = [int][Math]::Round($eb.y)
if ($by -ge ($H - 1)) { $ebullets.RemoveAt($i); continue }
if ([Math]::Abs($bx - $px) -le 2 -and [Math]::Abs($by - $py) -le 1) {$hp -= 12
Spawn-Explosion $px$py 10
$ebullets.RemoveAt($i); continue
}
Set-Cell $bx$by 'v' 91
}
# --- ЧАСТИЦЫ ВЗРЫВОВ ---
for ($i =$particles.Count - 1; $i -ge 0; $i--) {
$p =$particles[$i]$p.x += $p.vx; $p.y += $p.vy; $p.life--
if ($p.life -le 0) { $particles.RemoveAt($i); continue }
Set-Cell ([int][Math]::Round($p.x)) ([int][Math]::Round($p.y)) $p.ch $p.c
}
# --- ОТРИСОВКА ИГРОКА ---
Draw-Text ($px - 2)$py "<═▲═>" 96
$flame = if ($tick % 2 -eq 0) { " ^ " } else { " ' " }
Draw-Text ($px - 1) ($py + 1)$flame 93
# --- РАМКА И ИНТЕРФЕЙС (HUD) ---
Draw-Text 0 0 ("╔" + ("═" * ($W - 2)) + "╗") 36
Draw-Text 0 ($H - 1) ("╚" + ("═" * ($W - 2)) + "╝") 36
for ($ry = 1; $ry -lt ($H - 1);$ry++) {
Set-Cell 0 $ry '║' 36; Set-Cell ($W - 1)$ry '║' 36
}
$hpBlocks = [Math]::Max(0, [int]($hp / 10))
$hpBar = ("█" * $hpBlocks) + ("░" * (10 - $hpBlocks))$ultBlocks = [Math]::Max(0, [int]($ult / 10))$ultBar = ("█" * $ultBlocks) + ("░" * (10 - $ultBlocks))
$topHud = " СЧЕТ: $($score.ToString('00000')) │ ВОЛНА: $wave │ ОРУЖИЕ: УР.$weapon "
Draw-Text 2 0 $topHud 97
if ($null -ne$boss) {
$bBlocks = [Math]::Max(0, [int](($boss.hp / $boss.maxHp) * 10))$bBar = "БОСС:[" + ("█" * $bBlocks) + ("░" * (10 - $bBlocks)) + "]"
Draw-Text ($W - 19) 0$bBar 91
}
$hpCol = if ($hp -gt 40) { 92 } else { 91 }
$ultCol = if ($ult -ge 100) { 93 } else { 96 }
Draw-Text 2 ($H - 1) " БРОНЯ:[$hpBar] " $hpCol$ultTxt = if ($ult -ge 100) { "УЛЬТА(ПРОБЕЛ):[ГОТОВО!]" } else { "УЛЬТА:[$ultBar]" }
Draw-Text 26 ($H - 1) $ultTxt$ultCol
# --- ВЫВОД КАДРА НА ЭКРАН ЗА ОДИН ВЫЗОВ (БЕЗ МЕРЦАНИЯ) ---
$sb = New-Object System.Text.StringBuilder 4096
[void]$sb.Append("$ESC[H")
$lastC = -1
for ($y = 0; $y -lt$H; $y++) {$rowOff = $y * $W
for ($x = 0; $x -lt $W; $x++) {
$c =$cols[$rowOff +$x]
if ($c -ne$lastC) {
[void]$sb.Append("$ESC[$($c)m")
$lastC =$c
}
[void]$sb.Append($grid[$rowOff +$x])
}
if ($y -lt ($H - 1)) { [void]$sb.Append("`r`n") }
}
[void]$sb.Append("$ESC[0m")
[Console]::Write($sb.ToString())
$el = [int]$sw.ElapsedMilliseconds
if ($el -lt 32) { [System.Threading.Thread]::Sleep(32 -$el) }
}
# --- ЭКРАН ОКОНЧАНИЯ ИГРЫ ---
[Console]::SetCursorPosition(16, 10)
Write-Host "$ESC[91m╔══════════════════════════════╗$ESC[0m"
[Console]::SetCursorPosition(16, 11)
Write-Host "$ESC[91m║ КОРАБЛЬ УНИЧТОЖЕН! ║$ESC[0m"
[Console]::SetCursorPosition(16, 12)
Write-Host "$ESC[91m║ ИТОГОВЫЙ СЧЕТ: $($score.ToString('000000')) ║$ESC[0m"
[Console]::SetCursorPosition(16, 13)
Write-Host "$ESC[91m║ [R] Заново [ESC] Выход ║$ESC[0m"
[Console]::SetCursorPosition(16, 14)
Write-Host "$ESC[91m╚══════════════════════════════╝$ESC[0m"
while ($true) {
if ([Console]::KeyAvailable) {
$k = [Console]::ReadKey($true).Key
if ($k -eq 'R') { continue outerLoop }
if ($k -eq 'Escape') { Clear-Host; [Console]::CursorVisible =$true; exit }
}
[System.Threading.Thread]::Sleep(50)
}
}