Como hacer un Snake en Love2D

Archivos

Comenzamos creando los archivos main.lua y conf.lua, en el conf.lua solo añadimos lo siguiente:

function love.conf(t)
  t.window.title = "Snake - made in Love2D by Deybis Melendez"
  t.window.width = 400
  t.window.height = 400
end


function love.load()

Vamos a comenzar declarando las variables que utilizaremos, cada linea de código tendrá un comentario con su explicación:

  t = 20 -- tamaño de cada celda
  timer = 0 -- Controlaremos el tiempo de ejecución con esta variable
  perder = false -- Para controlar cuando pierde el juego
  ganar = false -- Para controlar cuando gana el juego
  love.graphics.setBackgroundColor(0.6039, 0.7725, 0.0117) -- Colocaos un fondo verde
  area = {} -- Nos ayudará a definir un area de juego
  area.x = t -- La posición del area en la parte superior izquierda
  area.y = t * 2 --La posición del area en la parte inferior izquierda
  area.w = love.graphics.getWidth() - t * 2 -- (Width o Ancho) La posición del area en la parte superior derecha
  area.h = love.graphics.getHeight() - t * 3 -- (Height o Alto) La posición del area en la parte inferior derecha
  snake = {} -- Los datos de la serpiente
  snake.velX = 20 -- Velocidad inicial en X de la serpiente
  snake.velY = 0 -- Velocidad inicial en Y de la serpiente
  snake.cola = {} -- contiene todos los puntos x , y de cada parte de la serpiente
  snake.cola[0] = {x = area.x , y = area.y} -- Cabeza de la serpiente
  comida = {} -- Los datos de la comida
  comida.radio = 8 -- La comida será representada por un circulo, por lo que necesitamos un radio
  comida.offset = t/2 -- Ajuste de la posición del circulo en la celda.
  comida.x = (math.random((area.w - area.x)/t)) * t + area.x --Posición inicial random en el eje X
  comida.y = (math.random((area.h - area.y)/t)) * t + area.y -- Posición inicial random en el eje Y


function love.draw()

Ahora daremos las instrucciones para dibujar el juego:

  love.graphics.setColor(0,0.1,0) -- El color que utilizaremos para dibujar el juego
  if not perder  and not ganar then -- Si no ha perdido o no ha ganado entonces...
    love.graphics.print("Puntuación: " .. #snake.cola, 16, 16) -- Imprimimos la Puntuación en la posición 16,16
  elseif not perder and ganar then -- Si no ha perdido pero ha ganado entonces...
    love.graphics.print("Ganaste! presiona R para reiniciar :D" , 16 , 16) -- Imprimimos que ganamos en la posición 16,16
  else -- Si no se cumplen las condiciones entonces
    love.graphics.print("Perdiste! Tu Puntuación es: " .. #snake.cola .. ", presiona R para reiniciar", 16 , 16) -- Imprimimos que perdiste en la posición 16,16
  end
  for i = 0, #snake.cola do -- Obtenemos cada contenido de snake.cola, es decir, cada x,y (cada parte de la serpiente)
    -- A continuación por cada Posición en x , y que tiene snake.cola, dibujaremos 4 cuadrados para simular el estilo retro del Nokia.
    love.graphics.rectangle("fill", snake.cola[i].x, snake.cola[i].y,t/2 - 1 , t/2 - 1)
    love.graphics.rectangle("fill", snake.cola[i].x + t/2, snake.cola[i].y, t/2 - 1, t/2 - 1)
    love.graphics.rectangle("fill", snake.cola[i].x, snake.cola[i].y + t/2, t/2 - 1, t/2 - 1)
    love.graphics.rectangle("fill", snake.cola[i].x + t/2, snake.cola[i].y + t/2, t/2 - 1, t/2 - 1)
  end
  love.graphics.rectangle("line", area.x, area.y, area.w , area.h ) --Dibujamos la linea que representará el area del juego
  love.graphics.circle("line", comida.x + comida.offset, comida.y + comida.offset, comida.radio) -- Dibujamos el circulo que representa la comida
end



function love.update(dt)

Primero, para ordenar un poco el código y se entienda, vamos a crear unas funciones, esto fuera del love.update:

function comer()

if snake.cola[0].x == comida.x and snake.cola[0].y == comida.y then -- Si la serpiente está encima de la comida entonces...
    snake.cola[#snake.cola + 1] = {x = snake.cola[#snake.cola].x - snake.velX , y  = snake.cola[#snake.cola].y - snake.velY} -- Añadimos una cola a la serpiente.
    if #snake.cola < 361 then -- Si la serpiente no tiene ocupado todo el area del juego, area es 19x19
      while contains(snake.cola , comida, 0) do -- Repetimos el siguiente codigo si la comida aparece encima de la serpiente
        -- damos una nueva posición random hasta que la comida esté fuera de la serpiente.
        comida.x = (math.random((area.w - area.x)/t)) * t + area.x
        comida.y = (math.random((area.h - area.y)/t)) * t + area.y
      end
    else -- Si la serpiente ocupa todo el area entonces...
      ganar = true -- Has ganado.
    end
  end
end



function mover()

  -- El sguiente for significa: Para i = cantidad de partes de la serpiente , repetimos el codigo hasta llegar que i = 0, restando -1 a i en cada repetición.
  for i = #snake.cola , 0 , -1 do -- Obtenemos cada parte de la serpiente, comenzando desde la cola hasta la cabeza, (en orden descendente, ej: 5,4,3,2,1,0)
    if i == 0 then -- snake.cola[0] es la cabeza de la serpiente, por lo que con ella controlamos el movimiento.
      snake.cola[0].x = snake.cola[0].x + snake.velX
      snake.cola[0].y = snake.cola[0].y + snake.velY
    else -- Para las demás hacemos que cada parte de la cola sea igual a la vecina anterior (i-1)
      snake.cola[i].x = snake.cola[i-1].x
      snake.cola[i].y = snake.cola[i-1].y
    end
  end
end



function contains(tabla,val,num)

-- Debido a que en Lua no existe un has() para saber si alguna variable existe en una tabla,
-- He conseguido esta función en internet que hace lo mismo, con la diferencia que he añadido una variable num
-- Que utilizaremos en 2 variantes en nuestro juego.
function contains(tabla, val, num)
   for i=num,#tabla do
      if tabla[i].x == val.x and tabla[i].y == val.y then
         return true
      end
   end
   return false
end





Ahora sí, añadimos el love.update(dt):

function love.update(dt)

  if timer < 0.1 then -- Con esto controlaremos cada actualización de pantalla a 0.1 segundos
    timer = timer + dt
  elseif not perder and not ganar then -- El juego no continuará si has perdido o ganado
    timer = 0 -- Indica que el contador del tiempo de cada frame comienza
    comer()
    mover()
    if contains(snake.cola , snake.cola[0] , 1) then -- Revisamos si snake.cola tiene un valor igual a la cabeza(snake.cola[0]), añadimos 1 para que no cuente la cabeza.
      perder = true -- Si ha colisionado entonces ha perdido
    end
    -- Aqui controlamos que la serpiente se mantenga dentro del area, reapareciendo en el lado opuesto.
    if snake.cola[0].x > area.w then
      snake.cola[0].x = area.x
    elseif snake.cola[0].x < area.x then
      snake.cola[0].x = area.w
    elseif snake.cola[0].y > area.h + t then
      snake.cola[0].y = area.y
    elseif snake.cola[0].y < area.y then
      snake.cola[0].y = area.h + t
    end
  end
end



function love.keypressed()

Por último, añadimos la función del teclado y como manipulamos el juego:

function love.keypressed(key, scancode, isrepeat)
  if key == "up" and snake.velY ~= t then
    snake.velX = 0
    snake.velY = - t
  elseif key == "down" and snake.velY ~= -t then
    snake.velX = 0
    snake.velY = t
  elseif key == "left" and snake.velX ~= t then
    snake.velX = - t
    snake.velY = 0
  elseif key == "right" and snake.velX ~= -t then
    snake.velX = t
    snake.velY = 0
  elseif key == "r" and (perder or ganar) then -- Solo ejecuta si ha perdido o ganado.
    snake.cola[0] = {x = area.x , y = area.y} -- Colocamos la cabeza de la serpiente en el lugar inicial
    for i = 1 , #snake.cola do -- Borramos todo el contenido de snake.cola menos la cabeza (snake.cola[0])
      snake.cola[i] = nil
    end
    -- Reiniciamos las variables del juego a su valor inicial...
    snake.velX = t
    snake.velY = 0
    comida.x = (math.random((area.w - area.x)/t)) * t + area.x
    comida.y = (math.random((area.h - area.y)/t)) * t + area.y
    perder = false
    ganar = false
  end
end





Y listo, ya tenemos un juego básico de snake al puro estilo de los antiguos celulares Nokias,  a continuación un pequeño gameplay del juego:

 

1 comentario:

  1. Este Blog esta genial, es una lastima que no hay as entradas, por que hay muy poco de Love2D en español ahí afuera

    ResponderEliminar

Como hacer un Snake en Love2D

Archivos Comenzamos creando los archivos main.lua y conf.lua, en el conf.lua solo añadimos lo siguiente: function love.conf(t)   t.win...