En este pequeño tutorial exploraremos la forma en la que podemos manipular los objetos administrados dentro de un display group
y como podemos aprovechar la asignación personalizada de propiedades en objetos del tipo display
en un ejercicio simple de “activar” un conjunto de elementos aleatorios en la interfaz.
Este artículo esta escrito pensando que es la primera vez que el lector se enfrenta a estos dos conceptos (objetos en display groups
y asignación de propiedades). Si ya estas familiarizado con ellos puedes ir directamente al final del artículo, analizar el código final y ajustarlo a tus necesidades.
Introducción – Planteando el problema
En este tutorial la interfaz que buscamos lograr tiene un total de 15 elementos inactivos que llevan los números del 1 al 4 (de forma aleatoria) y en la parte inferior una moneda que, cada vez que la presionemos, nos ayudará a controlar un contador que iluminará los elementos inactivos en pantalla que correspondan al número del contador. Es decir, la primera vez que presionemos la moneda todos los elementos con el número 1 se iluminarán, la segunda vez que la presionemos los elementos con el número 2 se iluminarán y así sucesivamente. La interfaz inicial que buscamos se ve así:

La mejor forma de resolver un problema siempre será analizar y entender sus partes antes de empezar a escribir una sola línea de código. En esencia lo que debe pasar es lo siguiente:
- Agregar en pantalla los 15 elementos inactivos
- Agregar un elemento como botón que ejecute una función que realice las siguientes operaciones:
- Sumar +1 a un contador global
- Verificar que elementos inactivos en pantalla coinciden con el contador global
- Poner la imagen activa en la misma posición que el elemento inactivo
- Eliminar la imagen inactiva de pantalla **
[su_note note_color=”#FEFBBC” text_color=”#000000″]** Nota: En Corona un elemento display como newImage
o newImageRect
no tiene una forma de sustituir la imagen original por otra, por lo que es necesario crear una nueva imagen con esos métodos y eliminar la que originalmente teníamos.[/su_note]
Para el ejercicio tengo disponibles una serie de imágenes de elementos activos e inactivos nombrados por números (1_off.png, 1_on.png, 2_off.png, 2_on.png, etc…) ademas de una imagen para la moneda (coin.png).
Paso 1 – Crear las imágenes con números a mostrar en pantalla
local grupoNumeros = display.newGroup() for fila=1,3 do for columna=1,5 do local numeroRandom = math.random(1, 4) local producto = display.newImageRect( numeroRandom.."_off.png", 150, 150) producto.x = 245 + ( 175 * (columna - 1) ) producto.y = 170 + ( 175 * (fila - 1) ) grupoNumeros:insert(producto) end end
El código anterior nos permite mostrar las imágenes con números inactivos, es un código sencillo pero exploremos que es lo que ha pasado en cada parte del mismo.
- Primero hemos declarado un
display group
de nombre grupoNumeros, es en este donde almacenaremos todos los objetos que deseamos iluminar por la acción del botón. - Con ayuda de un par de ciclos FOR anidados definimos la cantidad de filas y el número de objetos por fila que deseamos mostrar. En este caso son 3 filas con 5 elementos cada una.
- Para asegurar que la imagen sea aleatoria nos apoyamos de la función
math.random()
para obtener un número entre 1 y 4, mismos que corresponden al número usado en los nombres de las imágenes mencionadas anteriormente. - Con el número aleatorio podemos concatenar el nombre de la imagen que deseamos mostrar y crear el objeto usando la función
display.newImageRect()
. - Para posicionar las imágenes creadas estoy apoyándome de una pequeña formula que me permite distribuir fácilmente una cuadricula de elementos definiendo la posición inicial del primer elemento (el que se ubica en la esquina superior izquierda en este caso la posición x=245, y=170) y la distancia entre elementos que debe existir tanto en filas como columnas (en este caso 175 px)
- Una vez creado y posicionado el objeto solo es necesario que lo agregue al
display group
que me ayudará a gestionar todos estos elementos.
¿Por qué deberíamos agregar estas imágenes con números en un display group
?
Al insertar todos estos objetos dentro de un display group puedes acceder a ellos por medio del indice en el que se encuentra dicho objeto y, una vez recuperado, acceder / modificar sus propiedades lo que te puede ayudar a sintetizar tu codificación ¿te imaginas tener que crear 15 variables para mostrar cada uno de estas imágenes con número? ¿Qué pasaría si ahora en vez de 15 fueran 50 los elementos que debes mostrar? Sería imposible dar mantenimiento a un código como ese.
Paso 2 – creación del botón con la moneda
local totalMonedas = 0 function fnt_sumaMonedas(event) totalMonedas = totalMonedas + 1 print("Numero total: "..totalMonedas) end --crear el botón de monedas local opcionesBoton = { defaultFile = "coin.png", overFile = "coin.png", x = display.contentCenterX, y = display.actualContentHeight - 100, width = 120, height = 120, onRelease = fnt_sumaMonedas } widget.newButton( opcionesBoton )
- Empezamos por definir una variable global con la que vamos a controlar el total de veces que se ha presionado el botón moneda.
- La función
fnt_sumaMonedas
como podemos observar por ahora solo incrementa el número del contador global y lo imprimimos en consola - Definimos las características del botón y lo creamos.
En este punto podemos verificar que todo esta en orden en nuestro programa al ver en consola como se va sumando el número global al presionar el botón moneda.
Paso 3 – Asignación de propiedades a objetos
El siguiente paso es recuperar cada número y verificar si el contador global coincide con el número de la imagen y sustituirla con la nueva imagen.
for indice=grupoNumeros.numChildren,1,-1 do local imagenNumeroInactivo = grupoNumeros[indice] end
El código anterior nos permite recorrer el grupo del último elemento al primero y guardar en la variable imagenNumeroActivo
una referencia al elemento que actualmente estamos validando como se muestra en la siguiente figura.

Sin embargo, ese objeto no tiene alguna propiedad que lo identifique aunque si tiene información como el ancho, el alto, su posición (x,y), etc. Para resolverlo podemos, en la construcción del objeto original, agregar propiedades personalizadas pues este tipo de objetos se construyen en base a una tabla asociativa de LUA (para información mas detallada de como es posible esto consulta el post LUA 101 – Tablas).
Por lo tanto modificaremos el código del paso 1 donde construimos las imágenes con números y agregamos lo siguiente antes de insertar el objeto al grupo
producto.y = 170 + ( 175 * (fila - 1) ) producto.numero_moneda = numeroRandom — Se inserta esta línea grupoNumeros:insert(producto)
De esta manera ya tenemos disponible en ese objeto una propiedad de nombre numero_moneda
que tiene almacenado el número que obtuvimos en la función random()
. Por lo tanto el código de la función fnt_sumaMonedas
quedaría así:
function fnt_sumaMonedas(event) totalMonedas = totalMonedas + 1 for indice=grupoNumeros.numChildren,1,-1 do local imagenNumeroInactivo = grupoNumeros[indice] if imagenNumeroInactivo.numero_moneda == totalMonedas then local imagenNumeroActivo = display.newImageRect(totalMonedas.."_on.png", 150, 150) imagenNumeroActivo.x = imagenNumeroInactivo.x imagenNumeroActivo.y = imagenNumeroInactivo.y grupoNumeros:remove(imagenNumeroInactivo) end end end
Analicemos que es lo que esta sucediendo en esta función:
- Al inicio de la función incrementamos el número del contador global (eliminamos el print pues ya no lo ocupamos)
- Recorremos uno a uno los elementos del grupo que tiene guardados las imágenes con números.
- Guardamos una referencia del objeto que el ciclo FOR nos devuelve en la vuelta actual.
- Usando la propiedad que asignamos a ese objeto en su creación (de nombre
numero_moneda
) validamos si el valor almacenado en esa propiedad coincide con el del contador global.- Si resultan iguales creamos una nueva imagen, usando el mismo número del contador, pero ahora para mostrar la imagen con número “activa”.
- Aprovechamos la información de la imagen inactiva para ubicar las coordenadas (x, y) de la imagen activa.
- Finalmente eliminamos del grupo la imagen activa
Con esta codificación cada vez que toquemos el botón de la moneda se “iluminarán” los objetos cuando el número coincida con el contador global.

El código completo de este tutorial lo puedes ver a continuación.
local composer = require( "composer" ) local scene = composer.newScene() local widget = require ( "widget" ) local grupoNumeros = display.newGroup() for fila=1,3 do for columna=1,5 do local numeroRandom = math.random(1, 4) local producto = display.newImageRect( numeroRandom.."_off.png", 150, 150) producto.x = 245 + ( 175 * (columna - 1) ) producto.y = 170 + ( 175 * (fila - 1) ) producto.numero_moneda = numeroRandom grupoNumeros:insert(producto) end end local totalMonedas = 0 function fnt_sumaMonedas(event) totalMonedas = totalMonedas + 1 for indice=grupoNumeros.numChildren,1,-1 do local imagenNumeroInactivo = grupoNumeros[indice] if imagenNumeroInactivo.numero_moneda == totalMonedas then local imagenNumeroActivo = display.newImageRect(totalMonedas.."_on.png", 150, 150) imagenNumeroActivo.x = imagenNumeroInactivo.x imagenNumeroActivo.y = imagenNumeroInactivo.y grupoNumeros:remove(imagenNumeroInactivo) end end end local opcionesBoton = { defaultFile = "coin.png", overFile = "coin.png", x = display.contentCenterX, y = display.actualContentHeight - 100, width = 120, height = 120, onRelease = fnt_sumaMonedas } widget.newButton( opcionesBoton )
Espero hayas disfrutado y aprendido muchas cosas de este artículo y por favor siéntete libre de compartir esta información en tus redes sociales para que otras personas interesadas también puedan conocer algo nuevo que les pueda ayudar en sus proyectos futuros. ¡Hasta la próxima!