Módulo GridMap
El módulo GridMap proporciona una estructura de datos de cuadrícula 2D optimizada para juegos y aplicaciones que requieren mapas de tiles, pathfinding y detección de colisiones basada en celdas. Cada celda almacena un valor entero de 0 a 255, permitiendo representar diferentes tipos de terreno, obstáculos o estados.

Este módulo es especialmente útil para desarrollar juegos tipo arcade, puzzles basados en cuadrículas, simulaciones de mapas y cualquier aplicación que necesite navegación inteligente entre puntos.
Uso
use GridMap
Constructor
new
La función GridMap.new(ancho, alto) crea una nueva cuadrícula con las dimensiones especificadas. Todas las celdas se inicializan a 0.
use GridMap
// Crear una cuadrícula de 20x15 celdas
var mapa = GridMap.new(20, 15)
| Parámetro | Tipo | Descripción |
|---|---|---|
ancho | integer | Número de columnas de la cuadrícula |
alto | integer | Número de filas de la cuadrícula |
Retorno
Devuelve un objeto GridMap con las siguientes propiedades:
| Propiedad | Tipo | Descripción |
|---|---|---|
width | integer | Ancho de la cuadrícula (columnas) |
height | integer | Alto de la cuadrícula (filas) |
Métodos de instancia
setCell
El método setCell(x, y, valor) establece el valor de una celda específica.
// Establecer una pared (valor 1) en la posición (5, 3)
mapa.setCell(5, 3, 1)
// Establecer diferentes tipos de terreno
mapa.setCell(0, 0, 0) // Suelo vacío
mapa.setCell(1, 0, 1) // Pared
mapa.setCell(2, 0, 2) // Agua
mapa.setCell(3, 0, 5) // Punto de interés
| Parámetro | Tipo | Descripción |
|---|---|---|
x | integer | Coordenada X (columna) |
y | integer | Coordenada Y (fila) |
valor | integer | Valor a asignar (0-255) |
getCell
El método getCell(x, y) obtiene el valor de una celda específica.
var valor = mapa.getCell(5, 3)
println("Valor en (5,3): ", valor)
| Parámetro | Tipo | Descripción |
|---|---|---|
x | integer | Coordenada X (columna) |
y | integer | Coordenada Y (fila) |
Retorno
Devuelve el valor entero (0-255) almacenado en la celda, o -1 si las coordenadas están fuera de rango.
isBlocked
El método isBlocked(x, y) comprueba si una celda está bloqueada (tiene un valor distinto de 0).
if (mapa.isBlocked(5, 3)) then
println("La celda está bloqueada")
else
println("La celda está libre")
end
| Parámetro | Tipo | Descripción |
|---|---|---|
x | integer | Coordenada X (columna) |
y | integer | Coordenada Y (fila) |
Retorno
Devuelve true si el valor de la celda es distinto de 0, false en caso contrario.
clear
El método clear(valor) establece todas las celdas de la cuadrícula al valor especificado.
// Limpiar todo el mapa (poner a 0)
mapa.clear(0)
// Llenar todo de paredes
mapa.clear(1)
| Parámetro | Tipo | Descripción |
|---|---|---|
valor | integer | Valor a asignar a todas las celdas (0-255) |
clone
El método clone() crea una copia profunda de la cuadrícula.
var copiaDelMapa = mapa.clone()
// Modificar la copia no afecta al original
copiaDelMapa.setCell(0, 0, 99)
println(mapa.getCell(0, 0)) // Valor original
println(copiaDelMapa.getCell(0, 0)) // 99
Retorno
Devuelve un nuevo objeto GridMap con los mismos valores que el original.
findPath
El método findPath(sx, sy, gx, gy [, pasables [, permitirWrap]]) encuentra el camino más corto entre dos puntos usando el algoritmo BFS (Breadth-First Search).
// Encontrar camino desde (0,0) hasta (10,10)
var camino = mapa.findPath(0, 0, 10, 10)
if (camino != nil) then
println("Camino encontrado con ", len(camino), " pasos")
foreach (var punto in camino)
println(" -> (", punto[0], ", ", punto[1], ")")
end
else
println("No hay camino posible")
end
| Parámetro | Tipo | Descripción |
|---|---|---|
sx | integer | Coordenada X de inicio |
sy | integer | Coordenada Y de inicio |
gx | integer | Coordenada X de destino |
gy | integer | Coordenada Y de destino |
pasables | list | (Opcional) Lista de valores considerados transitables. Por defecto: [1, 2, 3, 5] |
permitirWrap | boolean | (Opcional) Si true, permite movimiento toroidal (los bordes se conectan). Por defecto: false |
Retorno
Devuelve una lista de coordenadas [[x1,y1], [x2,y2], ...] representando el camino, o nil si no existe camino posible.
Por defecto, las celdas con valores 1, 2, 3 y 5 son transitables. La celda con valor 0 también es transitable (suelo vacío). Puedes personalizar qué valores son obstáculos pasando tu propia lista.
buildDistanceMap
El método buildDistanceMap(objetivos [, pasables [, permitirWrap]]) construye un mapa de distancias desde múltiples puntos objetivo usando BFS multi-fuente.
// Puntos de interés (ej: power-ups en un juego)
var objetivos = [[5, 5], [15, 10], [8, 12]]
// Construir mapa de distancias
var distancias = mapa.buildDistanceMap(objetivos)
// Obtener distancia desde cualquier punto al objetivo más cercano
var dist = distancias.getCell(0, 0)
println("Distancia al objetivo más cercano: ", dist)
| Parámetro | Tipo | Descripción |
|---|---|---|
objetivos | list | Lista de coordenadas [[x1,y1], [x2,y2], ...] |
pasables | list | (Opcional) Lista de valores transitables |
permitirWrap | boolean | (Opcional) Permite movimiento toroidal |
Retorno
Devuelve un nuevo GridMap donde cada celda contiene la distancia mínima al objetivo más cercano. Las celdas inalcanzables tienen el valor 255.
findNearestOf
El método findNearestOf(objetivos, sx, sy [, pasables [, permitirWrap]]) encuentra el objetivo más cercano desde una posición dada.
// Posiciones de los fantasmas
var fantasmas = [[2, 3], [8, 1], [12, 7]]
// Encontrar el fantasma más cercano al jugador
var resultado = mapa.findNearestOf(fantasmas, jugadorX, jugadorY)
if (resultado != nil) then
println("Fantasma más cercano en: (", resultado[0], ", ", resultado[1], ")")
println("Distancia: ", resultado[2], " pasos")
else
println("No se puede alcanzar ningún fantasma")
end
| Parámetro | Tipo | Descripción |
|---|---|---|
objetivos | list | Lista de coordenadas objetivo |
sx | integer | Coordenada X de inicio |
sy | integer | Coordenada Y de inicio |
pasables | list | (Opcional) Lista de valores transitables |
permitirWrap | boolean | (Opcional) Permite movimiento toroidal |
Retorno
Devuelve una lista [x, y, distancia] con las coordenadas del objetivo más cercano y la distancia, o nil si ningún objetivo es alcanzable.
Conceptos importantes
Valores de celda
Cada celda almacena un valor de 0 a 255 que puede representar:
| Valor | Uso típico |
|---|---|
0 | Suelo vacío / transitable |
1 | Pared / obstáculo |
2-254 | Diferentes tipos de terreno o estados |
255 | Reservado para "inalcanzable" en mapas de distancia |
Movimiento toroidal (Wrap)
Cuando permitirWrap es true, los bordes de la cuadrícula se conectan:
- Moverse a la derecha desde la última columna lleva a la primera columna
- Moverse hacia abajo desde la última fila lleva a la primera fila
Esto es útil para juegos estilo Pac-Man donde el personaje puede atravesar los bordes del mapa.
// Mapa con bordes conectados
var camino = mapa.findPath(0, 5, 19, 5, [0, 1, 2, 3, 5], true)
Complejidad algorítmica
Todas las operaciones de pathfinding usan BFS con complejidad O(W×H), donde W es el ancho y H es el alto de la cuadrícula.
Ejemplo completo: Juego estilo Pac-Man
use GridMap
use Display
use Bitmap
use Sprite
Display.open(320, 240)
var draw = Display.draw
// Crear mapa del laberinto (20x15 celdas de 16x16 píxeles)
var mapa = GridMap.new(20, 15)
// 0 = pasillo, 1 = pared, 5 = punto/píldora
// Configurar paredes del laberinto
for (var x = 0; x < 20; x++)
mapa.setCell(x, 0, 1) // Pared superior
mapa.setCell(x, 14, 1) // Pared inferior
end
for (var y = 0; y < 15; y++)
mapa.setCell(0, y, 1) // Pared izquierda
mapa.setCell(19, y, 1) // Pared derecha
end
// Añadir paredes internas
mapa.setCell(5, 5, 1)
mapa.setCell(5, 6, 1)
mapa.setCell(5, 7, 1)
mapa.setCell(14, 5, 1)
mapa.setCell(14, 6, 1)
mapa.setCell(14, 7, 1)
// Colocar puntos en los pasillos
for (var y = 1; y < 14; y++)
for (var x = 1; x < 19; x++)
if (mapa.getCell(x, y) == 0) then
mapa.setCell(x, y, 5) // Punto
end
end
end
// Cargar sprites
var tilePared = Bitmap.load("pared.bmp")
var tilePunto = Bitmap.load("punto.bmp")
var spriteJugador = Sprite.load("pacman.spr")
var spriteFantasma = Sprite.load("fantasma.spr")
// Posiciones iniciales
var jugadorX = 1
var jugadorY = 1
var fantasmaX = 10
var fantasmaY = 7
var puntuacion = 0
while (true)
// Entrada del jugador (simplificada)
var dx = 0
var dy = 0
// ... leer entrada GPIO o teclado ...
// Mover jugador si la celda destino no es pared
var nuevoX = jugadorX + dx
var nuevoY = jugadorY + dy
if (mapa.getCell(nuevoX, nuevoY) != 1) then
jugadorX = nuevoX
jugadorY = nuevoY
// Recoger punto
if (mapa.getCell(jugadorX, jugadorY) == 5) then
mapa.setCell(jugadorX, jugadorY, 0)
puntuacion = puntuacion + 10
end
end
// IA del fantasma: perseguir al jugador
var camino = mapa.findPath(fantasmaX, fantasmaY, jugadorX, jugadorY)
if (camino != nil and len(camino) > 1) then
fantasmaX = camino[1][0]
fantasmaY = camino[1][1]
end
// Dibujar
draw.cls(0x000000)
// Dibujar mapa
for (var y = 0; y < 15; y++)
for (var x = 0; x < 20; x++)
var valor = mapa.getCell(x, y)
if (valor == 1) then
draw.bitmap(tilePared, x * 16, y * 16)
elsif (valor == 5) then
draw.bitmap(tilePunto, x * 16, y * 16)
end
end
end
// Dibujar personajes
spriteJugador.pos(jugadorX * 16, jugadorY * 16)
spriteFantasma.pos(fantasmaX * 16, fantasmaY * 16)
draw.sprite(spriteJugador)
draw.sprite(spriteFantasma)
// UI
draw.text(5, 225, "Puntos: " + puntuacion, 0xFFFFFF)
// Detectar colisión jugador-fantasma
if (jugadorX == fantasmaX and jugadorY == fantasmaY) then
draw.text(100, 120, "GAME OVER", 0xFF0000)
end
Display.update()
pause(100)
end
Uso con el módulo Draw
El módulo Draw incluye la función gridBitmap para renderizar eficientemente cuadrículas:
use GridMap
use Bitmap
use Display
Display.open(320, 240)
var draw = Display.draw
var mapa = GridMap.new(20, 15)
// ... configurar mapa ...
var tilePared = Bitmap.load("pared.bmp")
var tileSuelo = Bitmap.load("suelo.bmp")
// Dibujar todas las paredes de una vez
draw.gridBitmap(mapa, 1, tilePared, 0, 0, 16, 16)
// Dibujar todo el suelo
draw.gridBitmap(mapa, 0, tileSuelo, 0, 0, 16, 16)
Display.update()
Consideraciones de rendimiento
- Una cuadrícula de 100×100 ocupa aproximadamente 10 KB
- Las operaciones de pathfinding son O(W×H), considera el tamaño del mapa para aplicaciones en tiempo real
- Usa
buildDistanceMapcuando necesites calcular distancias desde múltiples puntos de forma eficiente
Plataformas soportadas
| Plataforma | Soporte | Notas |
|---|---|---|
| Windows (SDL2) | ✅ | Soporte completo |
| ESP32 | ✅ | Soporte completo |
| Emscripten (Web) | ✅ | Soporte completo |
| SiFive | 🚧 | En desarrollo |