
Cambio de paleta en Löve 2D"
Sin Usar Shaders
Fecha:Cambiar el color de una imagen puede ser una forma muy útil de reutilizar un
recurso sin aumentar el tamaño en disco del juego. Es posible cambiar el color
de las imágenes utilizando las capacidades de ImageData
para acceder
a los píxeles directamente, ya sea para leer los colores como para cambiarlos.

El algoritmo consiste en cargar a la memoria nuestra imagen como un objeto de
tipo ImageData
, en el cual no haremos cambios y solo vamos a usar como
un "mapa" para saber que color se supone que debemos utilizar,
por eso lo llamaremos image_map
.
También creamos una imagen de las mismas dimensiones
donde vamos a escribir todos los cambios que hagamos, a esta la llamaremos
image_data
1

Hay que cargar una imagen que contiene las paletas a utilizar, que
sera palette_data
, donde cada franja horizontal de un píxel
de alto es una paleta:

lua
image_map = love.image.newImageData('ima.png')
image_data = love.image.newImageData( image_map:getWidth(), image_map:getHeight())
palette_data = love.image.newImageData('palette.png')
También debemos calcular el numero máximo de paletas (max_palettes
)
que podemos utilizar, este sera igual al tamaño vertical de la imagen donde
guardamos las paletas.
lua
max_palettes = palette_data:getHeight()
Ahora creamos una tabla donde veremos a que cada columna de la primera fila
de imagen de paletas se corresponde cada color que compone la primera paleta.
A esta tabla la llamaremos look_up_color_table
.
Crearemos una cadena que nos servirá de id
para identificar a cada
color rápidamente.
lua
look_up_color_table = {}
local col = palette_data:getWidth()
local i = 0
while i < col do
local r,g,b,a = palette_data:getPixel(i,0)
-- El id es creado usando un valor similar al hexadecimal
local id = ("%X_%X_%X_%X"):format(
math.floor((o_r)*255),
math.floor((o_g)*255),
math.floor((o_b)*255),
math.floor((o_a)*255)
)
look_up_color_table[id] = i
i=i+1
end
Fijamos la paleta que queremos usar y cambiamos los colores de
image_data
.
lua
use_palette = 1
changePalete()
Lo que ocurre dentro de la función changePalete()
,
es que llamamos al método mapPixel()
del objeto
ImageData
. mapPixel()
nos permite mandar una
función que se ejecutara por cada uno de los píxeles que componen el objeto, en
este caso, la función con la cual cambiamos los colores.
Después, como los objetos de tipo ImageData
no pueden ser
dibujados creamos una imagen para poder dibujar en pantalla, y le decimos que
queremos que se dibuje nítida.
lua
function changePalete()
image_data:mapPixel(changeColors)
image = love.graphics.newImage(image_data)
image:setFilter('nearest','nearest')
end
Ahora, es en la función changeColors()
donde ocurre todo.

Primero recibimos las coordenadas (x,y) del color que queremos cambiar,
buscamos que color es en image_map
con el método
getPixel(x,y)
, después transformamos ese color a un id
,
con el cual accedemos a la tabla look_up_color_table
, que nos regresa
un numero de columna. Con el numero de use_palette
que es igual al
numero de la fila, y ya sabiendo la columna, tomamos ese color de nuestra paleta,
y lo regresamos para colocado en las coordenadas (x,y) en
image_data
lua
function changeColors(x, y, r,g,b,a)
local o_r,o_g,o_b,o_a = image_map:getPixel(x,y)
local id = ("%X_%X_%X_%X"):format(
math.floor((o_r)*255),
math.floor((o_g)*255),
math.floor((o_b)*255),
math.floor((o_a)*255)
)
-- Revisar si el color existe en la tabla
if look_up_color_table[id] then
--if exist, then get the color on the palete
local col = look_up_color_table[id]
local row = use_palette-1
return palette_data:getPixel(col,row)
end
--si no, regresamos el color original.
return r, g, b, a
end
Por cada vez que cambiemos la paleta de la imagen, solo necesitamos establecer cuál es la fila correspondiente y cambiarla.
lua
use_palette = 3
changePalete()
Ojo, una desventaja de este método sin sombreadores, es el hecho de que cambian las paletas, cuanto más grande sea el área a cambiar, esto será más lento de manera exponencial
Eso seria todo, puedes descargar el archivo con el código fuente .zip justo aquí y revisarlo por ti mismo. Puedes usar las flechas para cambiar entre paletas.