Ir al contenido principal

Quiéres estos diseños en tu ropa o en diferentes productos?

Publicidad

Interfaz gráfica con Love2D


 

Un saludo a todos, hoy les quiero explicar como crear una simple interfaz gráfica con Love2D que nos pueda ayudar a desarrollar más adelante nuestro propio código adaptado al programa que queramos desarrollar. Aquí explicaré como crear un botón, una caja de texto, deslizador y una caja de selección.

Trataré de hacer el código lo más pequeño posible para que se pueda entender todo lo que hace y como lo hace y espero les sirva de ayuda en sus proyectos.

Las funciones que tendremos serán las siguientes:

function puntoEnRectangulo(puntoX,puntoY,rectX,rectY,rectAncho,RectAlto)
function nuevoControl(texto,x,y,ancho,alto,tipo)
function dibujaControles()
function controlTextInput(k)
function controlKeyPressed(tecla)
function controlMouseReleased(x,y,boton)
function controlWheelMoved(w)
function ajustaFoco(control)         --el control que se pase será el activo
function obtenerControles()          --devuelve la tabla "listaControles"
function agregarControl(control)  --agrega un control a "listaControles"
function removerControl(control) --remueve un control de la lista
function ajustarValorDeslizador(control,valor)
local function calculaValorDeslizador(control,cursorx)
local function calculaPorcentajeDeslizador(distancia,valorMaximo)
local function ajustaTexto(control)
 
Las variable internas son las siguientes:
 
local enFoco = nil
local listaControles = {}
temaControles      = {
    colorFondo        = {0.85,0.85,0.85},
    colorTexto         = {0,0,0},
    fondoTexto        = {1,1,1},
    colorFoco          = {0,0.5,1},
    colorDeslizador = {0.1,0.2,1},
    colorMarca        = {0.1,0.2,1},
    colorBorde         = {0.6,0.6,0.6}

Ahora veamos como funcionará todo esto. Con la función "nuevoControl" crearemos cualquiera de los controles antes nombrados indicando en el parámetro "tipo" la clase de control al que pertenecerá, al control que obtenemos le podemos modificar sus valores y luego lo agregamos a la lista de controles, cuando con el puntero del ratón hagamos clic sobre algún control, este pasa a estar en el foco y por lo tanto recibirá entrada de texto si es de tipo "texto" o si se usa la rueda del ratón si es de tipo "deslizador" y si es de tipo "boton" ejecutará la acción que se le configuró. La función "dibujaControles" sabrá como dibujar el componente de acuerdo a su tipo, y debido a que todos comparten la mayoría de las características no se necesita código muy complejo para realizar esta tarea.

Veamos la función "nuevoControl", aquí creamos una tabla llamada "control" y le agregamos todo este conjunto de variables, los nombres son bastante claros para identificar su uso, luego devolvemos la variable control para ser usada y modificada a nuestra necesidad. La variable "acción" será una función que deseemos y que será invocada al hacer clic sobre el control.

function nuevoControl(texto,x,y,ancho,alto,tipo)
    local control = {}
    control.x = x
    control.y = y
    control.ancho = ancho
    control.alto = alto
    control.tipo = tipo
    control.texto = texto
    control.accion = nil
    control.valorDeslizador = 0
    control.valorMaximoDeslizador = 100
    control.incrementoDeslizador = 1
    control.porcentajeDeslizador = 0
    control.marcado = false
    control.margenTexto = 0
    control.margen = {0,0,0,0} --arriba,derecha,abajo,izquierda
    control.sinBorde = false  --no dibuja el borde del rectángulo
    control.sinFondo = false  --no dibuje el fondo
    control.sinFoco = false    --si está enfocado no dibuja el foco
    if tipo == "deslizador" then
        control.texto = "0"
    end
    return control
end

La función "dibujaControl" es bastante simple, en un bucle que atraviesa la tabla "listaControles" y va dibujando los rectángulos con los colores del tema, y muestra el texto que el componente tenga. De acuerdo al tipo de componente se agregan elementos extra como por ejemplo cuando es tipo "marca" se agrega un cuadrado al lado del texto para identificar si el control está marcado o no. El texto es recortado si es demasiado largo y el valor de "margen" ayuda a mover el texto dentro de su área limitando también su visibilidad.

function dibujaControles()
    for indice,control in ipairs(listaControles) do
        if control.tipo == "texto" then
            love.graphics.setColor(unpack(temaControles.fondoTexto))
        else
            love.graphics.setColor(unpack(temaControles.colorFondo))
        end
 
        if not control.sinFondo then
            love.graphics.rectangle("fill",control.x,control.y,control.ancho,control.alto)
        end

        if control.tipo == "deslizador" then
            love.graphics.setColor(unpack(temaControles.colorDeslizador))
        love.graphics.rectangle("fill",control.x,control.y,control.ancho*control.porcentajeDeslizador,control.alto)
        end

        love.graphics.setColor(unpack(temaControles.colorTexto))
        local cheqMargen = 0
        local altoLetra = 0
        if control.tipo == "marca" then
            altoLetra = love.graphics.getFont():getHeight()
            cheqMargen = altoLetra + 5
        end
 
        local clipx = control.x + control.margen[4]
        local clipy = control.y + control.margen[1]
        local clipAncho = control.ancho - control.margen[4] - control.margen[2] - cheqMargen
        local clipAlto = control.alto - control.margen[1] - control.margen[3]
        love.graphics.setScissor(clipx,clipy,clipAncho,clipAlto)
        love.graphics.print(control.texto,control.x + control.margen[4] - control.margenTexto,control.y + control.margen[1])
        love.graphics.setScissor()
        love.graphics.setColor(unpack(temaControles.colorMarca))

        if control.marcado then
            love.graphics.rectangle("fill",control.x + control.ancho - cheqMargen,control.y + control.margen[1],altoLetra,altoLetra)
        else
            love.graphics.rectangle("line",control.x + control.ancho - cheqMargen,control.y + control.margen[1],altoLetra,altoLetra)
        end

        if enFoco == control and not control.sinFoco then
            love.graphics.setColor(unpack(temaControles.colorFoco))
            love.graphics.rectangle("line",control.x,control.y,control.ancho,control.alto)
        elseif not control.sinBorde then
            love.graphics.setColor(unpack(temaControles.colorBorde))
            love.graphics.rectangle("line",control.x,control.y,control.ancho,control.alto)
        end
    end
end

Para ayudar en los momentos que se escriba dentro de una caja de texto tenemos la función "ajustaTexto" que calcula si el texto supera al área del control y si es así aumentando al valor del "margenTexto" para ver siempre el final del texto mientras se escribe, si el control ya no tiene el foco el "margenTexto" regresa a ser cero. El valor "margenTexto" es usado durante el dibujado para mover el texto a la izquierda.

local function ajustaTexto(control)
    local anchoTexto = love.graphics.getFont():getWidth(control.texto)
    local anchoRecorte = control.ancho - control.margen[2] - control.margen[4]
    local diferencia = anchoRecorte - anchoTexto
    if diferencia < 0 then
        control.margenTexto = math.abs(diferencia)
    else
        control.margenTexto = 0
    end
end

Es necesario que cuando se haga clic sobre un control de tipo "deslizador" se modifique el tamaño del rectángulo indicador de acuerdo a la posición dónde se coloque el cursor del ratón. Las siguientes funciones trabajan en conjunto para esto, "calculaPorcentajeDeslizador" devuelve el valor que es utilizado para calcular el ancho del rectángulo durante el dibujado, "calculaValorDeslizador" se utiliza cuando hacemos clic en algún punto del área del control, y "ajustaValorDeslizador" cuando queramos modificar el valor por medio de código y así pueda ser mostrado el cambio durante el dibujado.

local function calculaPorcentajeDeslizador(distancia,valorMaximo)
    local porcentaje = math.modf((100 * distancia)/valorMaximo)
    return porcentaje/100
end

local function calcularValorDeslizador(control,cursorx)
    local distancia = cursorx - control.x
    control.porcentajeDeslizador = calculaPorcentajeDeslizador(distancia,control.ancho)
    control.valorDeslizador = control.valorMaximoDeslizador * control.porcentajeDeslizador
    control.texto = ""..control.valorDeslizador
end

function ajustaValorDeslizador(control,valor)
    if valor < 0 then
        valor = 0
    elseif valor > control.valorMaximoDeslizador then
        valor = control.valorMaximoDeslizador
    end
    control.valorDeslizador = valor
    control.texto = ""..control.valorDeslizador
    control.porcentajeDeslizador = calculaPorcentajeDeslizador(control.valorDeslizador,control.valorMaximoDeslizador)
end

Las funciones "controlTextInput", "controlKeyPressed", "controlMouseReleased", "controlWheelMoved" deben colocarse en los lugares respectivos dentro de las funciones de Love2D para que los controles puedan reaccionar correctamente al teclado y el ratón. Estas funciones son bucles que verifican cada control dentro de la lista, si el control está en foco y de acuerdo al tipo se actualiza su valor correspondiente.

Veamos un ejemplo simple:

require "controles"

function love.load()
    love.keyboard.setkeyRepeat(true)
    love.graphics.setBackgroundColor(0.9,0.9,0.9)

    etiqueta = nuevoControl("Etiqueta",5,5,100,25,"etiqueta")
    etiqueta.margen = {5,5,5,5}

    deslizador = nuevoControl("",5,35,100,25,"deslizador")
    deslizador.margen = {5,5,5,5}

    boton = nuevoControl("Botón",5,65,100,25,"boton")
    boton.margen = {5,5,5,5}
    boton.accion = function () --escribe tu código aquí end

    texto = nuevoControl("",5,95,100,25,"texto")
    texto.margen = {5,5,5,5}

    marca = nuevoControl("Marca",5,125,100,25,"marca")
    marca.margen = {5,5,5,5}
    agregarControl(etiqueta)
    agregarControl(deslizador)
    agregarControl(boton)
    agregarControl(texto)
    agregarControl(marca)
end

function love.textInput(k)
    controlTextInput(k)
end

function love.keypresed(key)
    controlKeyPressed(key)
end

function love.wheelmoved(x,y)
    controlWheelMoved(y)
end

function love.mousereleased(x,y,boton)
    controlMouseReleased(x,y,boton)
end

function love.draw()
    dibujaControles()
end

Y así se vería este ejemplo.
 
 

 

Y este un video corto.

 


También creé una pequeña calculadora como práctica y aquí te dejo un video corto.


Como puedes ver es una interfaz muy simple que espero te sea útil y además estoy seguro de que podrás crear algo mucho mejor. Te dejaré el código aquí para que puedas probarlo.


Comentarios

  1. No se puede descargar el código. Gracias.

    ResponderEliminar
    Respuestas
    1. El enlace funciona, ya fué verificado. espero puedas acceder y descargarlo

      Eliminar

Publicar un comentario