Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
-- snake.lua — классическая "Змейка" для OpenComputers -- Управление: стрелки ← ↑ → ↓, Пауза: P, Выход: Q -- Адаптируется к текущему разрешению; безопасно возвращает настройки при выходе. local comp = require("component") local event = require("event") local keyboard = require("keyboard") local term = require("term") assert(comp.isAvailable("gpu"), "Нужна видеокарта (gpu).") local gpu = comp.gpu -- Палитра local COL_BG = 0x202020 -- тёмно-серый фон local COL_BORDER = 0x404040 local COL_TEXT = 0xFFFFFF local COL_SNAKE = 0x00FF66 -- зелёная змейка local COL_FOOD = 0x33CCFF -- голубая еда -- Сохранение текущих настроек, чтобы красиво выйти local oldFg, oldBg = gpu.getForeground(), gpu.getBackground() local oldW, oldH = gpu.getResolution() local function cleanup(msg) gpu.setForeground(oldFg); gpu.setBackground(oldBg) gpu.setResolution(oldW, oldH) term.clear() if msg then print(msg) end end -- Настройка разумного резолюшена под игру (не больше максимума GPU) do local maxW, maxH = gpu.maxResolution() local targetW = math.min(100, maxW) local targetH = math.min(35, maxH) pcall(gpu.setResolution, targetW, targetH) end local W, H = gpu.getResolution() -- Поле: оставим рамку и статус-строку local LEFT, TOP = 2, 3 local RIGHT, BOTTOM = W - 1, H - 1 local FIELD_W = RIGHT - LEFT + 1 local FIELD_H = BOTTOM - TOP + 1 -- Защита: поле должно быть достаточно большим if FIELD_W < 10 or FIELD_H < 8 then cleanup("Слишком маленькое разрешение экрана для игры.") return end -- Утилиты отрисовки local function cls() gpu.setBackground(COL_BG); gpu.setForeground(COL_TEXT) term.clear() end local function drawFrame() gpu.setForeground(COL_BORDER) -- Верхняя панель gpu.fill(1, 1, W, 1, " ") gpu.set(2, 1, "S N A K E (P - пауза, Q - выход)") -- Рамка for x = LEFT-1, RIGHT+1 do gpu.set(x, TOP-1, "─"); gpu.set(x, BOTTOM+1, "─") end for y = TOP-1, BOTTOM+1 do gpu.set(LEFT-1, y, "│"); gpu.set(RIGHT+1, y, "│") end gpu.set(LEFT-1, TOP-1, "┌"); gpu.set(RIGHT+1, TOP-1, "┐") gpu.set(LEFT-1, BOTTOM+1, "└"); gpu.set(RIGHT+1, BOTTOM+1, "┘") end local function status(score, speed) gpu.setForeground(COL_TEXT) local line = string.format(" Score: %d Speed: %.1f fps ", score, speed) gpu.fill(1, 2, W, 1, " ") gpu.set(math.max(2, math.floor((W - #line)/2)), 2, line) end local function fillField() gpu.setBackground(COL_BG) gpu.fill(LEFT, TOP, FIELD_W, FIELD_H, " ") end -- Игровые координаты local function rnd(a, b) return math.random(a, b) end local function posEq(a, b) return a.x == b.x and a.y == b.y end -- Генерация еды на свободной клетке local function spawnFood(snake) while true do local fx = rnd(LEFT, RIGHT) local fy = rnd(TOP, BOTTOM) local clash = false for i=1,#snake do if snake[i].x == fx and snake[i].y == fy then clash = true; break end end if not clash then return {x=fx, y=fy} end end end -- Отрисовка змейки/еды local function drawCell(x, y, color, ch) gpu.setBackground(COL_BG) -- подложка gpu.setForeground(color) gpu.set(x, y, ch or "█") end -- Инициализация змейки local snake = {} local startLen = 5 local sx = math.floor((LEFT + RIGHT) / 2) local sy = math.floor((TOP + BOTTOM) / 2) for i=0,startLen-1 do table.insert(snake, 1, {x = sx - i, y = sy}) end local dir = {x = 1, y = 0} -- движемся вправо local pendingDir = dir local food = spawnFood(snake) local score = 0 local paused = false local alive = true -- Скорость (кадры/сек). Повышаем по мере роста змейки. local fps = 8 local function stepDelay() return 1.0 / fps end -- Ограничение: нельзя разворачиваться на 180° local function setDirection(nx, ny) -- если новая ось противоположна текущей — игнор if (#snake >= 2) then local head, neck = snake[1], snake[2] -- Проверим, не ведёт ли новый вектор в шею (разворот) if head.x + nx == neck.x and head.y + ny == neck.y then return end end pendingDir = {x = nx, y = ny} end -- Логика шага local function tick() dir = pendingDir local head = snake[1] local nx, ny = head.x + dir.x, head.y + dir.y -- Столкновение со стеной if nx < LEFT or nx > RIGHT or ny < TOP or ny > BOTTOM then alive = false; return end -- Столкновение с собой for i=1,#snake do if snake[i].x == nx and snake[i].y == ny then alive = false; return end end -- Добавляем новую голову table.insert(snake, 1, {x=nx, y=ny}) drawCell(nx, ny, COL_SNAKE, "█") -- Проверка еды if nx == food.x and ny == food.y then score = score + 1 -- немного ускоряемся, но с ограничением fps = math.min(20, 8 + score * 0.3) food = spawnFood(snake) drawCell(food.x, food.y, COL_FOOD, "●") else -- убираем хвост (перерисовываем ячейку фоном) local tail = table.remove(snake) gpu.setForeground(COL_BG) gpu.set(tail.x, tail.y, " ") end end -- Рендер стартового состояния math.randomseed(os.time()) cls() drawFrame() fillField() for i=1,#snake do drawCell(snake[i].x, snake[i].y, COL_SNAKE, "█") end drawCell(food.x, food.y, COL_FOOD, "●") status(score, fps) -- Главный цикл local lastTime = computer.uptime and computer.uptime() or os.clock() local function now() return (computer.uptime and computer.uptime()) or os.clock() end while alive do -- обработка ввода (не блокируя логику шага) local timeout = stepDelay() local ev = {event.pull(timeout, "key_down")} if #ev > 0 then local _, _, _, code = table.unpack(ev) if code == keyboard.keys.q then break end if code == keyboard.keys.p then paused = not paused end if code == keyboard.keys.up then setDirection(0, -1) end if code == keyboard.keys.down then setDirection(0, 1) end if code == keyboard.keys.left then setDirection(-1, 0) end if code == keyboard.keys.right then setDirection(1, 0) end end if paused then gpu.setForeground(COL_TEXT) gpu.set(math.floor(W/2)-3, 2, "[PAUSE]") else -- тикаем по времени (вдруг event.pull вернулось раньше) local t = now() if t - lastTime >= stepDelay() then tick() status(score, fps) lastTime = t end end end if alive then cleanup("Вы вышли из игры. Счёт: "..tostring(score)) else cleanup("Игра окончена. Счёт: "..tostring(score)) end
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)