Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local board = {}
- local size = 4
- local score = 0
- local highScore = 0
- local width, height = term.getSize()
- local t = 0
- local gameOver = false
- local won = false
- local isMonochrome = false
- local speaker = peripheral.find("speaker")
- local function playSound(instrument, volume, pitch)
- if speaker then
- speaker.playNote(instrument, volume, pitch)
- end
- end
- local requiredColors = {"gray", "lightBlue", "cyan", "blue", "green", "lime", "yellow", "orange", "red", "magenta", "purple", "pink", "white", "black", "lightGray"}
- for _, color in ipairs(requiredColors) do
- if not colors[color] then
- error("Required color not available: " .. color)
- end
- end
- local tileColors = {
- [0] = colors.gray,
- [2] = colors.lightBlue,
- [4] = colors.cyan,
- [8] = colors.blue,
- [16] = colors.green,
- [32] = colors.lime,
- [64] = colors.yellow,
- [128] = colors.orange,
- [256] = colors.red,
- [512] = colors.magenta,
- [1024] = colors.purple,
- [2048] = colors.pink
- }
- local monochromeColors = {
- [0] = colors.gray,
- [2] = colors.lightGray,
- [4] = colors.white,
- [8] = colors.white,
- [16] = colors.lightGray,
- [32] = colors.lightGray,
- [64] = colors.gray,
- [128] = colors.gray,
- [256] = colors.black,
- [512] = colors.black,
- [1024] = colors.black,
- [2048] = colors.black
- }
- local shadowColors = {
- [0] = colors.lightGray,
- [2] = colors.blue,
- [4] = colors.blue,
- [8] = colors.black,
- [16] = colors.blue,
- [32] = colors.green,
- [64] = colors.orange,
- [128] = colors.red,
- [256] = colors.magenta,
- [512] = colors.purple,
- [1024] = colors.black,
- [2048] = colors.magenta
- }
- local monochromeShadowColors = {
- [0] = colors.lightGray,
- [2] = colors.gray,
- [4] = colors.gray,
- [8] = colors.lightGray,
- [16] = colors.lightGray,
- [32] = colors.gray,
- [64] = colors.gray,
- [128] = colors.black,
- [256] = colors.black,
- [512] = colors.black,
- [1024] = colors.black,
- [2048] = colors.black
- }
- local rainbowColors = {
- colors.red,
- colors.orange,
- colors.yellow,
- colors.lime,
- colors.cyan,
- colors.blue,
- colors.purple
- }
- local tileWidth = 5
- local tileHeight = 3
- local boardWidth = size * tileWidth + (size - 1)
- local boardHeight = size * tileHeight + (size - 1)
- local startX = math.floor((width - boardWidth) / 2)
- local startY = math.floor((height - boardHeight) / 2)
- local buffer = {}
- for y = 1, height do
- buffer[y] = {}
- for x = 1, width do
- buffer[y][x] = {
- char = " ",
- textColor = colors.white,
- backgroundColor = colors.black
- }
- end
- end
- local function setBufferPixel(x, y, char, textColor, backgroundColor)
- if x >= 1 and x <= width and y >= 1 and y <= height then
- if not buffer[y] then
- buffer[y] = {}
- end
- buffer[y][x] = {
- char = char or " ",
- textColor = textColor or colors.white,
- backgroundColor = backgroundColor or colors.black
- }
- end
- end
- local function writeToBuffer(x, y, text, textColor, backgroundColor)
- for i = 1, #text do
- setBufferPixel(x + i - 1, y, text:sub(i, i), textColor, backgroundColor)
- end
- end
- local particles = {}
- local function createParticles(x, y, value)
- for i = 1, 10 do
- table.insert(particles, {
- x = x + math.random() * tileWidth,
- y = y + math.random() * tileHeight,
- dx = (math.random() - 0.5) * 2,
- dy = (math.random() - 0.5) * 2,
- life = 10,
- color = isMonochrome and monochromeColors[value] or tileColors[value] or colors.white
- })
- end
- end
- local function updateParticles()
- for i = #particles, 1, -1 do
- local p = particles[i]
- p.x = p.x + p.dx
- p.y = p.y + p.dy
- p.life = p.life - 1
- if p.life <= 0 then
- table.remove(particles, i)
- end
- end
- end
- local function drawParticles()
- for _, p in ipairs(particles) do
- setBufferPixel(math.floor(p.x), math.floor(p.y), "•", p.color, colors.black)
- end
- end
- local function newBoard()
- board = {}
- for i = 1, size do
- board[i] = {}
- for j = 1, size do
- board[i][j] = {value = 0, mergeEffect = 0}
- end
- end
- score = 0
- gameOver = false
- won = false
- end
- local function addTile()
- local emptyCells = {}
- for i = 1, size do
- for j = 1, size do
- if board[i][j].value == 0 then
- table.insert(emptyCells, {i, j})
- end
- end
- end
- if #emptyCells > 0 then
- local cell = emptyCells[math.random(#emptyCells)]
- board[cell[1]][cell[2]].value = math.random() < 0.9 and 2 or 4
- end
- end
- local function drawPlasma()
- for y = 1, height do
- for x = 1, width do
- local v = math.sin(x * 0.1 + t) + math.sin(y * 0.1 + t) +
- math.sin((x + y) * 0.1 + t) + math.sin(math.sqrt(x^2 + y^2) * 0.1 + t)
- v = (v + 4) / 8
- local color = math.floor(v * 15) + 1
- if isMonochrome then
- color = math.floor(v * 3) + colors.black
- end
- setBufferPixel(x, y, " ", colors.white, color)
- end
- end
- t = t + 0.1
- end
- local function drawTile(x, y, tileData)
- local value = tileData.value
- local color = isMonochrome and monochromeColors[value] or tileColors[value] or colors.white
- local shadowColor = isMonochrome and monochromeShadowColors[value] or shadowColors[value] or colors.gray
- if tileData.mergeEffect > 0 then
- color = isMonochrome and colors.white or colors.white
- tileData.mergeEffect = tileData.mergeEffect - 1
- end
- for i = 1, tileHeight do
- setBufferPixel(x + tileWidth, y + i, " ", colors.black, shadowColor)
- end
- for j = 1, tileWidth do
- setBufferPixel(x + j, y + tileHeight, " ", colors.black, shadowColor)
- end
- for i = 0, tileHeight - 1 do
- for j = 0, tileWidth - 1 do
- setBufferPixel(x + j, y + i, " ", colors.black, color)
- end
- end
- if value > 0 then
- local valueStr = tostring(value)
- local xOffset = math.floor(tileWidth/2 - #valueStr/2)
- writeToBuffer(x + xOffset, y + math.floor(tileHeight/2), valueStr, colors.black, color)
- end
- end
- local function drawBoard()
- for i = 1, size do
- for j = 1, size do
- local x = startX + (j - 1) * (tileWidth + 1)
- local y = startY + (i - 1) * (tileHeight + 1)
- drawTile(x, y, board[i][j])
- end
- end
- end
- local function drawUI()
- writeToBuffer(2, height - 1, "Score: " .. score, colors.white, colors.black)
- writeToBuffer(width - 15, height - 1, "High Score: " .. highScore, colors.white, colors.black)
- end
- local logoOffset = 0
- local function drawLogo()
- local gameTitle = "nono2048 2!"
- local logoY = height
- for i = 1, #gameTitle do
- local colorIndex = ((i-1 + logoOffset) % #rainbowColors) + 1
- local color = isMonochrome and colors.white or rainbowColors[colorIndex]
- setBufferPixel(math.floor((width - #gameTitle) / 2) + i - 1, logoY, gameTitle:sub(i,i), color, colors.black)
- end
- logoOffset = (logoOffset + 1) % #rainbowColors
- end
- local function checkGameOver()
- for i = 1, size do
- for j = 1, size do
- if board[i][j].value == 0 then
- return false
- end
- if i < size and board[i][j].value == board[i+1][j].value then
- return false
- end
- if j < size and board[i][j].value == board[i][j+1].value then
- return false
- end
- end
- end
- return true
- end
- local function moveTiles(direction)
- local moved = false
- local function shiftTile(i, j, di, dj)
- while i + di >= 1 and i + di <= size and j + dj >= 1 and j + dj <= size do
- if board[i + di][j + dj].value == 0 then
- board[i + di][j + dj].value = board[i][j].value
- board[i][j].value = 0
- i, j = i + di, j + dj
- moved = true
- elseif board[i + di][j + dj].value == board[i][j].value then
- board[i + di][j + dj].value = board[i + di][j + dj].value * 2
- board[i + di][j + dj].mergeEffect = 5
- score = score + board[i + di][j + dj].value
- board[i][j].value = 0
- moved = true
- local x = startX + (j + dj - 1) * (tileWidth + 1)
- local y = startY + (i + di - 1) * (tileHeight + 1)
- createParticles(x, y, board[i + di][j + dj].value)
- playSound("bit", 3, 1)
- if board[i + di][j + dj].value == 2048 then
- won = true
- end
- break
- else
- break
- end
- end
- end
- if direction == "up" then
- for j = 1, size do
- for i = 2, size do
- if board[i][j].value ~= 0 then
- shiftTile(i, j, -1, 0)
- end
- end
- end
- elseif direction == "down" then
- for j = 1, size do
- for i = size - 1, 1, -1 do
- if board[i][j].value ~= 0 then
- shiftTile(i, j, 1, 0)
- end
- end
- end
- elseif direction == "left" then
- for i = 1, size do
- for j = 2, size do
- if board[i][j].value ~= 0 then
- shiftTile(i, j, 0, -1)
- end
- end
- end
- elseif direction == "right" then
- for i = 1, size do
- for j = size - 1, 1, -1 do
- if board[i][j].value ~= 0 then
- shiftTile(i, j, 0, 1)
- end
- end
- end
- end
- return moved
- end
- local function swapBuffers()
- for y = 1, height do
- for x = 1, width do
- local pixel = buffer[y][x]
- term.setCursorPos(x, y)
- term.setTextColor(pixel.textColor)
- term.setBackgroundColor(pixel.backgroundColor)
- term.write(pixel.char)
- end
- end
- end
- local function updateDisplay()
- drawPlasma()
- drawBoard()
- updateParticles()
- drawParticles()
- drawUI()
- drawLogo()
- if gameOver then
- writeToBuffer(width/2 - 4, height/2, "Game Over!", colors.red, colors.black)
- elseif won then
- writeToBuffer(width/2 - 7, height/2, "You've won! 2048!", colors.green, colors.black)
- end
- swapBuffers()
- end
- local asciiLogo = [[
- __
- ___ ___ ___ ___ ___| |
- ___ ___ ___ ___|_ | | | | . | |_ | |
- | | . | | . | _| | |_ | . | | _|__|
- |_|_|___|_|_|___|___|___| |_|___| |___|__|
- ]]
- term.clear()
- term.setCursorPos(1, 1)
- print(asciiLogo)
- print("\nWelcome to nono2048 2!")
- print("Press 'c' for color mode or 'm' for monochrome mode.")
- local event, key
- repeat
- event, key = os.pullEvent("key")
- until key == keys.c or key == keys.m
- isMonochrome = (key == keys.m)
- newBoard()
- addTile()
- addTile()
- local updateTimer = os.startTimer(0.05)
- while true do
- local event, param = os.pullEventRaw()
- if event == "timer" and param == updateTimer then
- updateDisplay()
- updateTimer = os.startTimer(0.05)
- elseif event == "key" then
- local moved = false
- if param == keys.up then
- moved = moveTiles("up")
- elseif param == keys.down then
- moved = moveTiles("down")
- elseif param == keys.left then
- moved = moveTiles("left")
- elseif param == keys.right then
- moved = moveTiles("right")
- elseif param == keys.q then
- break
- elseif param == keys.r then
- newBoard()
- addTile()
- addTile()
- gameOver = false
- particles = {}
- end
- if moved then
- addTile()
- if score > highScore then
- highScore = score
- end
- gameOver = checkGameOver()
- if gameOver then
- playSound("bass", 3, 0)
- end
- end
- elseif event == "terminate" then
- break
- end
- end
- term.setBackgroundColor(colors.black)
- term.clear()
- term.setCursorPos(1, 1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement