Módulo GridMap
Un GridMap es una rejilla de celdas en la que cada celda guarda un número de 0 a 255. Es el mapa de un juego: qué tile se pinta en cada celda (con draw.tilemap), qué celdas son pared para los sprites, por dónde se puede ir de un sitio a otro y dónde está cada cosa.

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.
use GridMap
Cómo es un GridMap
Celdas y valores
Cada celda se nombra por su columna x y su fila y, contadas desde 0: en un mapa de 20 × 15, x va de 0 a 19 e y de 0 a 14. Cada celda guarda un valor de 0 a 255, que es lo que tú decidas:
| Valor | Uso típico |
|---|---|
0 | Suelo vacío / transitable |
1 | Pared / obstáculo |
2-254 | Diferentes tipos de terreno o estados |
255 | En un mapa de tiles, celda vacía que no se pinta; en un mapa de distancias de dMap, inalcanzable |
Para pintar el mapa y para que choque con los sprites, el mapa necesita además el tamaño en píxeles de su tile (tSize) y su posición en la pantalla (x, y). Un mapa que solo usas para buscar caminos no los necesita.
Sólidos y plataformas
Las listas solids y platforms dicen qué valores de celda son pared y cuáles son plataformas que solo frenan desde arriba. Las usan:
- las colisiones con sprites:
hitsysprite.hitsGrid; - la búsqueda de caminos:
path,dMapynearestpasan por las celdas que no están ensolids.
Movimiento toroidal (wrap)
Cuando wrapX o wrapY son true, los bordes de la cuadrícula se conectan:
wrapX: moverse a la derecha desde la última columna lleva a la primera columna.wrapY: moverse hacia abajo desde la última fila lleva a la primera fila.
Esto es útil para juegos de laberinto donde el personaje puede atravesar los bordes del mapa. Lo tienen en cuenta get, las colisiones, draw.tilemap (que repite el mapa) y la búsqueda de caminos.
mapa.wrapX = true
mapa.wrapY = true
var camino = mapa.path(0, 5, 19, 5) // Puede rodear por los bordes
path, dMap y nearest no distinguen los ejes: en cuanto wrapX o wrapY vale true, conectan los bordes en horizontal y en vertical. El parámetro permitirWrap de dMap y nearest hace lo mismo. Si solo quieres un eje, cierra el otro con una fila o una columna de paredes.
Coste
- Una cuadrícula ocupa un byte por celda: una de 100 × 100, unos 10 KB.
path,dMapynearestrecorren el mapa entero (búsqueda en anchura, coste O(ancho × alto)); ten en cuenta el tamaño del mapa en un juego que las llama a menudo.- Para que varios enemigos vayan hacia lo mismo, calcula
dMapuna vez y llama adiruna vez por enemigo en cada fotograma.
Funciones
| Función | Qué hace | Devuelve |
|---|---|---|
GridMap.new(ancho, alto) | Crea un mapa con todas las celdas a 0 | Un GridMap |
GridMap.load(fichero) | Carga un mapa de un fichero .gmap | Un GridMap |
Los métodos y las funciones de GridMap lanzan una excepción cuando algo falla (un argumento de otro tipo, una celda fuera del mapa…), que se captura con try (ver Errores y excepciones).
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 | entero | Número de columnas de la cuadrícula |
alto | entero | Número de filas de la cuadrícula |
El mapa nuevo no tiene tamaño de tile (tSize() es [0, 0]), ni tileset, ni solids. Con un ancho o un alto de 0 lanza ERR_INVALID_VALUE; con decimales, ERR_TYPE_MISMATCH.
load
La función GridMap.load(archivo) carga un mapa desde un fichero .gmap.
var mapa = GridMap.load("Maps/Nivel1_cells.gmap")
| Parámetro | Tipo | Descripción |
|---|---|---|
archivo | cadena | Ruta al fichero .gmap |
Devuelve un GridMap con las celdas del fichero y su tamaño de tile. No trae ni el tileset, ni solids, ni platforms: pónselos tú.
El IDE crea los .gmap al compilar, a partir de los mapas del editor de mapas: Maps/<mapa>_tiles.gmap con los tiles y Maps/<mapa>_cells.gmap con los valores de celda. Qué lleva cada uno y cómo es el fichero lo cuenta Lo que guarda y lo que genera.
| Error | Cuándo |
|---|---|
ERR_FILE_NOT_FOUND | El fichero no está. |
ERR_INVALID_FORMAT | No es un .gmap, es de otra versión o le faltan celdas. |
ERR_INVALID_VALUE | El mapa del fichero mide 0 de ancho o de alto. |
ERR_TYPE_MISMATCH | La ruta no es una cadena. |
Propiedades
Las propiedades se leen y se asignan directamente, como campos del objeto.
| Propiedad | Tipo | De serie | Para qué |
|---|---|---|---|
x, y | decimal | 0 | Dónde va la celda (0, 0), en píxeles |
wrapX, wrapY | sí/no | false | Conectar los bordes |
solids | lista o nil | nil | Los valores de pared |
platforms | lista o nil | nil | Los valores de plataforma |
tileset | Bitmap o nil | nil | La imagen de los tiles |
bouncy | sí/no | false | Rebotar contra el mapa |
elasticity | decimal, de 0 a 1 | 0 | Cuánto rebota |
x / y
Posición del mapa en el espacio de pantalla, en píxeles: dónde va la esquina de arriba a la izquierda de la celda (0, 0). La tienen en cuenta draw.tilemap, draw.scene y las colisiones con el mapa; draw.gridBitmap no la usa, porque recibe su propia posición.
mapa.x = 32
mapa.y = 16
println(mapa.x) // 32
| Propiedad | Tipo | Descripción |
|---|---|---|
x | decimal | Posición horizontal del mapa |
y | decimal | Posición vertical del mapa |
Para hacer scroll sin escena, cámbialas: con valores negativos, el mapa se va hacia la izquierda y hacia arriba. Asignarles algo que no es un número lanza ERR_INVALID_VALUE.
wrapX / wrapY
Activan el movimiento toroidal (los bordes del mapa se conectan). Cuando están activos, la búsqueda de caminos y las colisiones los tienen en cuenta automáticamente (ver Movimiento toroidal).
mapa.wrapX = true // Los bordes izquierdo y derecho se conectan
mapa.wrapY = false
println(mapa.wrapX) // true
| Propiedad | Tipo | Descripción |
|---|---|---|
wrapX | sí/no | Conecta el borde derecho con el izquierdo |
wrapY | sí/no | Conecta el borde inferior con el superior |
solids
Lista de valores de celda considerados sólidos (obstáculos). Las funciones path, dMap, nearest y hits usan esta lista automáticamente si no se les pasan parámetros adicionales.
mapa.solids = [1, 2, 3] // Los tiles 1, 2 y 3 son sólidos
println(mapa.solids) // [1, 2, 3]
mapa.solids = nil // Sin sólidos definidos
| Propiedad | Tipo | Descripción |
|---|---|---|
solids | lista | nil | Lista de valores de celda sólidos |
El mapa guarda la misma lista que le das, no una copia: si después la cambias, cambian los sólidos. Con algo que no es una lista ni nil (un array, por ejemplo), lanza ERR_TYPE_MISMATCH.
platforms
Lista de valores de celda que actúan como plataformas unidireccionales (solo bloquean desde arriba). Usada por hits y por sprite.hitsGrid.
mapa.platforms = [4]
| Propiedad | Tipo | Descripción |
|---|---|---|
platforms | lista | nil | Lista de valores de celda para plataformas de un solo sentido |
tileset
Bitmap vinculado al mapa, usado por draw.tilemap para renderizar automáticamente los tiles, y por draw.scene para el mapa de la escena.
var ts = Bitmap.load("Images/tileset.bmp")
mapa.tileset = ts
println(mapa.tileset) // <Obj Bitmap>
mapa.tileset = nil // Desvincular
| Propiedad | Tipo | Descripción |
|---|---|---|
tileset | Bitmap | nil | Tileset asociado al mapa |
bouncy / elasticity
Controlan el rebote de los sprites al resolver sus colisiones con el mapa mediante hits.
mapa.bouncy = true
mapa.elasticity = 0.8
| Propiedad | Tipo | Descripción |
|---|---|---|
bouncy | sí/no | Activa el rebote al colisionar |
elasticity | decimal | Factor de rebote (0.0 = sin rebote, 1.0 = rebote total) |
Con bouncy = false, el sprite no rebota: se para contra la pared. Con true, el rebote combina la elasticity del mapa y la del sprite. Un valor fuera de 0–1 se queda en el límite.
Métodos del mapa
| Método | Qué hace | Devuelve |
|---|---|---|
set(x, y, valor) | Cambia el valor de una celda | nil |
get(x, y) | Lee el valor de una celda | Un entero |
width(), height() | Las medidas en celdas | Un entero |
clear(valor) | Pone todas las celdas a un valor | nil |
clone() | Hace una copia | Un GridMap |
tSize() / tSize(ancho, alto) | Lee o cambia el tamaño del tile | [ancho, alto] / nil |
tEmpty() / tEmpty(valor) | Lee o cambia el tile que no se pinta | Un entero / true |
count(valor) | Cuántas celdas tienen un valor | Un entero |
has(valor) | Si alguna celda tiene un valor | true o false |
find(valor) | Dónde están las celdas con un valor | Una lista [x, y, …] |
around(x, y [, usar8 [, permitirWrap]]) | Los valores de las celdas vecinas | Una lista |
see(x1, y1, x2, y2, bloqueantes) | Si hay línea de visión entre dos celdas | true o false |
path(sx, sy, gx, gy) | El camino más corto entre dos celdas | Una lista [x, y, …], o nil |
dMap(objetivos [, transitables [, permitirWrap]]) | Un mapa de distancias a unas celdas | Un GridMap |
nearest(objetivos, sx, sy [, transitables [, permitirWrap]]) | El camino a la celda objetivo más cercana | Una lista [x, y, …], o nil |
dir(x, y [, usar8]) | En un mapa de distancias, hacia dónde ir | Un entero de 0 a 8 |
hits(sprite) | Saca de las paredes a uno o varios sprites | Una lista de valores |
set
El método set(x, y, valor) establece el valor de una celda específica.
mapa.set(5, 3, 1) // Pared
mapa.set(0, 0, 0) // Suelo vacío
mapa.set(2, 0, 5) // Punto de interés
| Parámetro | Tipo | Descripción |
|---|---|---|
x | entero | Coordenada X (columna) |
y | entero | Coordenada Y (fila) |
valor | entero | Valor a asignar (0-255) |
| Error | Cuándo |
|---|---|
ERR_INVALID_VALUE | valor no está entre 0 y 255. |
ERR_INDEX_OUT_OF_RANGE | La celda está fuera del mapa. set no usa el wrap. |
ERR_TYPE_MISMATCH | Algún argumento no es un entero (también los decimales). |
get
El método get(x, y) obtiene el valor de una celda específica.
var valor = mapa.get(5, 3)
println("Valor en (5,3): ", valor)
| Parámetro | Tipo | Descripción |
|---|---|---|
x | número | Coordenada X (columna) |
y | número | Coordenada Y (fila) |
Devuelve el valor entero (0-255) almacenado en la celda.
- Acepta decimales, y los redondea hacia abajo:
get(1.9, 0.2)es la celda(1, 0), y-0.5es la-1. - Con
wrapXowrapY, una coordenada fuera del mapa da la vuelta en ese eje: en un mapa de 4 de ancho conwrapX,get(5, 0)esget(1, 0). - Fuera del mapa, sin wrap en ese eje, lanza
ERR_INDEX_OUT_OF_RANGE.
width / height
Los métodos width() y height() devuelven las dimensiones de la cuadrícula.
println("Ancho: ", mapa.width())
println("Alto: ", mapa.height())
clear
El método clear(valor) establece todas las celdas al valor especificado.
mapa.clear(0) // Limpiar todo el mapa
mapa.clear(1) // Llenar todo de paredes
| Parámetro | Tipo | Descripción |
|---|---|---|
valor | entero | Valor a asignar a todas las celdas (0-255) |
Un valor fuera de 0–255 lanza ERR_INVALID_VALUE.
draw.tilemap no ve el clearEn Windows, después de clear, draw.tilemap sigue pintando el mapa de antes hasta que cambias una celda con set. Haz un set de cualquier celda después del clear, por ejemplo mapa.set(0, 0, mapa.get(0, 0)).
clone
El método clone() crea una copia profunda de la cuadrícula.
var copia = mapa.clone()
copia.set(0, 0, 99)
println(mapa.get(0, 0)) // Valor original inalterado
println(copia.get(0, 0)) // 99
Devuelve un nuevo GridMap con los mismos valores que el original, y también su posición, su tamaño de tile, el wrap, el rebote, el tile vacío y su tileset (la misma imagen). solids y platforms se copian: cambiar las de la copia no toca las del original.
tSize
El método tSize() / tSize(ancho, alto) lee o cambia el tamaño en píxeles de cada tile. Lo usan draw.tilemap, draw.scene, hits y sprite.hitsGrid: sin él, no pintan ni chocan.
mapa.tSize(16, 16) // Establecer tiles de 16x16 px
var tam = mapa.tSize() // Obtener -> [16, 16]
println(tam[0], "x", tam[1])
| Uso | Parámetros | Retorno |
|---|---|---|
| Leer | ninguno | [tileAncho, tileAlto] (lista) |
| Cambiar | ancho:entero, alto:entero (1-255) | nil |
Un mapa nuevo tiene [0, 0], y uno cargado de un .gmap, el del fichero. Fuera de 1–255 lanza ERR_INVALID_VALUE.
tEmpty
El método tEmpty() / tEmpty(valor) lee o cambia el índice del tile vacío. Las celdas con ese valor no se dibujan al renderizar el mapa.
mapa.tEmpty(0) // El tile 0 es el "vacío" (por defecto: 255)
println(mapa.tEmpty()) // 0
| Uso | Parámetros | Retorno |
|---|---|---|
| Leer | ninguno | entero (0-255) |
| Cambiar | valor:entero | true |
Las celdas con 255 no se pintan nunca, sea cual sea tEmpty.
count
El método count(valor) cuenta cuántas celdas tienen un valor específico.
var numParedes = mapa.count(1)
println("Paredes: ", numParedes)
| Parámetro | Tipo | Descripción |
|---|---|---|
valor | entero | Valor de celda a buscar (0-255) |
Devuelve un entero con el número de celdas que tienen ese valor.
has
El método has(valor) comprueba si existe al menos una celda con el valor dado.
if (mapa.has(5)) then
println("Quedan puntos en el mapa")
end
| Parámetro | Tipo | Descripción |
|---|---|---|
valor | entero | Valor de celda a buscar (0-255) |
Devuelve true si existe al menos una celda con ese valor, false en caso contrario.
find
El método find(valor) busca todas las celdas con un valor específico y devuelve sus coordenadas.
var posiciones = mapa.find(5) // Todas las celdas con valor 5
for (var i = 0; i < posiciones.size(); i += 2)
var x = posiciones[i]
var y = posiciones[i + 1]
println("Punto en (", x, ", ", y, ")")
end
| Parámetro | Tipo | Descripción |
|---|---|---|
valor | entero | Valor de celda a buscar (0-255) |
Devuelve una lista plana [x1, y1, x2, y2, ...] con las coordenadas de todas las coincidencias (en orden fila por fila). Lista vacía si no hay ninguna. Sirve, por ejemplo, para poner los enemigos donde el editor de mapas marcó sus celdas.
around
El método around(x, y [, usar8 [, permitirWrap]]) obtiene los valores de las celdas vecinas a una posición.
var vecinos4 = mapa.around(5, 3) // 4 vecinos cardinales
var vecinos8 = mapa.around(5, 3, true) // 8 vecinos (+ diagonales)
var vecinosW = mapa.around(0, 0, false, true) // 4 vecinos con wrap toroidal
| Parámetro | Tipo | Descripción |
|---|---|---|
x | entero | Coordenada X de la celda central |
y | entero | Coordenada Y de la celda central |
usar8 | sí/no | (Opcional) Si true, incluye las 4 diagonales. Por defecto: false |
permitirWrap | sí/no | (Opcional) Si true, los bordes se conectan. Por defecto: false |
Devuelve una lista con los valores de las celdas vecinas válidas, en este orden: arriba, abajo, izquierda, derecha y, con usar8, arriba a la izquierda, arriba a la derecha, abajo a la izquierda y abajo a la derecha. Sin wrap, las celdas fuera de los límites se saltan (la lista puede tener menos de 4/8 elementos), así que en un borde la posición en la lista no dice qué vecino es. Usa el argumento permitirWrap, no wrapX ni wrapY.
see
El método see(x1, y1, x2, y2, bloqueantes) comprueba si hay línea de visión libre entre dos celdas usando el algoritmo de Bresenham.
// ¿Puede el jugador ver al fantasma? Las paredes (valor 1) bloquean
if (mapa.see(jugX, jugY, fanX, fanY, 1)) then
println("El fantasma te ve")
end
// Múltiples valores bloqueantes
if (mapa.see(jugX, jugY, fanX, fanY, [1, 2, 3])) then
println("Línea de visión libre")
end
| Parámetro | Tipo | Descripción |
|---|---|---|
x1, y1 | entero | Coordenadas de origen |
x2, y2 | entero | Coordenadas de destino |
bloqueantes | entero | lista | array | Valores de celda que bloquean la visión |
Devuelve true si el trayecto entre origen y destino no pasa por ninguna celda bloqueante, false en caso contrario. Las celdas de origen y de destino no cuentan: aunque sean pared, no tapan. No usa el wrap.
path
El método path(sx, sy, gx, gy) encuentra el camino más corto entre dos puntos, moviéndose en las cuatro direcciones (BFS).
Los métodos de búsqueda de caminos derivan automáticamente las celdas transitables a partir de la propiedad solids del mapa (transitable = NO sólido). El wrap toroidal se toma de las propiedades wrapX y wrapY. Si se necesita un comportamiento diferente, los métodos dMap y nearest admiten parámetros opcionales para especificar manualmente los transitables y el wrap.
use GridMap
var mapa = GridMap.new(8, 5)
mapa.solids = [1]
// Un pequeño mapa con dos paredes
// . . . . . . . .
// . # # # # # . .
// . . . . . . . .
// . . # # # # # .
// . . . . . . . .
for (var x = 1; x <= 5; x++) mapa.set(x, 1, 1) end
for (var x = 2; x <= 6; x++) mapa.set(x, 3, 1) end
var camino = mapa.path(0, 0, 7, 4)
if (camino != nil) then
println(len(camino) div 2, " celdas")
println(camino)
else
println("Sin camino")
end
12 celdas
[0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 7, 1, 7, 2, 7, 3, 7, 4]
| Parámetro | Tipo | Descripción |
|---|---|---|
sx | entero | Coordenada X de inicio |
sy | entero | Coordenada Y de inicio |
gx | entero | Coordenada X de destino |
gy | entero | Coordenada Y de destino |
Devuelve una lista plana [x0, y0, x1, y1, ..., gx, gy] con las coordenadas del camino, empezando por el origen, o nil si no existe camino posible o si el origen/destino no son transitables. Si el origen ya es el destino, el camino es esa casilla: [x, y]. Con un origen o un destino fuera del mapa lanza ERR_INDEX_OUT_OF_RANGE, y con decimales, ERR_TYPE_MISMATCH.
Las celdas transitables se calculan automáticamente como el complemento de mapa.solids. Asegúrate de asignar mapa.solids antes de llamar a path. El wrap se toma de mapa.wrapX y mapa.wrapY.
dMap
El método dMap(objetivos [, transitables [, permitirWrap]]) construye un mapa de distancias BFS desde todas las celdas que tengan los valores objetivo.
// Mapa de distancias al tipo de celda 5 (puntos/píldoras)
mapa.solids = [1]
var distancias = mapa.dMap(5)
// Consultar distancia desde cualquier posición
var dist = distancias.get(jugadorX, jugadorY)
println("Distancia al punto más cercano: ", dist)
// Con múltiples tipos de objetivo
var distancias2 = mapa.dMap([5, 6])
// Con transitables y wrap manual
var distancias3 = mapa.dMap(5, [0, 5, 6], true)
| Parámetro | Tipo | Descripción |
|---|---|---|
objetivos | entero | lista | array | Valor(es) de celda desde los que se mide la distancia |
transitables | entero | lista | array | (Opcional) Valores de celda por los que se puede pasar |
permitirWrap | sí/no | (Opcional) Permite movimiento toroidal |
Devuelve un nuevo GridMap donde cada celda contiene la distancia mínima al objetivo más cercano, en pasos de una celda. Las celdas objetivo valen 0 y las inalcanzables, 255. Las distancias de 254 o más se quedan en 254. El mapa nuevo es solo de distancias: no tiene tamaño de tile, tileset ni solids.
Con un solo argumento, dMap deriva los transitables de mapa.solids (transitable = NO sólido) y el wrap de mapa.wrapX/mapa.wrapY.
nearest
El método nearest(objetivos, sx, sy [, transitables [, permitirWrap]]) encuentra el camino más corto desde una posición hasta la celda más cercana que tenga uno de los valores objetivo.
// Posición del jugador: ¿cuál es el punto más cercano?
mapa.solids = [1]
var camino = mapa.nearest(5, jugadorX, jugadorY)
if (camino != nil) then
// El último par de valores es la posición del objetivo encontrado
var n = camino.size()
var tx = camino[n - 2]
var ty = camino[n - 1]
println("Punto más cercano en (", tx, ", ", ty, ")")
println("Pasos: ", n div 2 - 1)
else
println("No hay puntos alcanzables")
end
| Parámetro | Tipo | Descripción |
|---|---|---|
objetivos | entero | lista | array | Valor(es) de celda que se buscan |
sx | entero | Coordenada X de inicio |
sy | entero | Coordenada Y de inicio |
transitables | entero | lista | array | (Opcional) Valores de celda transitables |
permitirWrap | sí/no | (Opcional) Permite movimiento toroidal |
Devuelve una lista plana [sx, sy, ..., tx, ty] con el camino desde el origen hasta la celda objetivo más cercana, o nil si ningún objetivo es alcanzable (también si el origen es una pared). Si el origen ya es un objetivo, devuelve [sx, sy].
dir
El método dir(x, y [, usar8]) obtiene la mejor dirección a seguir desde una posición en un mapa de distancias (resultado de dMap). Permite mover un agente hacia el objetivo más cercano sin recalcular el camino completo en cada fotograma.
mapa.solids = [1]
var distancias = mapa.dMap(5) // Mapa de distancias a los puntos
// IA del fantasma: moverse hacia el punto más cercano
var dir = distancias.dir(fantasmaX, fantasmaY)
if (dir == 1) then fantasmaY -= 1 // Arriba
elsif (dir == 2) then fantasmaY += 1 // Abajo
elsif (dir == 3) then fantasmaX -= 1 // Izquierda
elsif (dir == 4) then fantasmaX += 1 // Derecha
end
| Parámetro | Tipo | Descripción |
|---|---|---|
x | entero | Coordenada X actual |
y | entero | Coordenada Y actual |
usar8 | sí/no | (Opcional) Si true, considera también las diagonales. Por defecto: false |
Devuelve un entero indicando la dirección óptima:
| Valor | Dirección |
|---|---|
0 | Sin movimiento (ya en objetivo o celda inalcanzable) |
1 | Arriba (y-1) |
2 | Abajo (y+1) |
3 | Izquierda (x-1) |
4 | Derecha (x+1) |
5 | Arriba-izquierda (x-1, y-1) — solo con 8 direcciones |
6 | Arriba-derecha (x+1, y-1) — solo con 8 direcciones |
7 | Abajo-izquierda (x-1, y+1) — solo con 8 direcciones |
8 | Abajo-derecha (x+1, y+1) — solo con 8 direcciones |
Elige el vecino con menos distancia; si empatan, el primero en ese orden. No usa el wrap: en el borde del mapa no da la vuelta. Con 8 direcciones solo mira la distancia de la celda en diagonal, no si las dos de al lado son pared: puede cortar una esquina.
hits
El método hits(sprite_o_lista) resuelve la colisión física entre uno o varios sprites y el mapa. Lee las propiedades solids y platforms directamente del GridMap para determinar qué tiles bloquean y cuáles son plataformas de un solo sentido.
mapa.solids = [1, 2]
mapa.platforms = [3]
// Colisión con un sprite
var tilesGolpeados = mapa.hits(jugador)
// Colisión con varios sprites a la vez
var todos = [jugador, enemigo1, enemigo2]
var golpeados = mapa.hits(todos)
| Parámetro | Tipo | Descripción |
|---|---|---|
sprite_o_lista | Sprite | lista | Sprite individual o lista de sprites a resolver |
Devuelve una lista con los valores de los tiles con los que ha habido colisión, vacía si no hay ninguna.
A diferencia de sprite.hitsGrid, que solo pregunta, hits mueve los sprites: saca de las paredes a los que se han metido y les quita la velocidad contra la pared (o los hace rebotar, con bouncy). Para eso:
- Solo trabaja con cuerpos
DYNAMIC. Los sprites de otro tipo de la lista se saltan; por eso le puedes pasar la lista entera. - El mapa necesita su tamaño de tile (
tSize). Sin él, no hace nada. - Usa el recorrido desde
prevX,prevY: un sprite rápido no atraviesa una pared fina. En una escena,scene.update()los pone al día. - Llámalo en cada fotograma, después de
scene.update(): la física de la escena mueve los cuerpos, pero no mira el mapa (lo cuenta Scene). - Pone
onGround()atrueen los sprites que el mapa sostiene (sprite.onGround).
Acepta un sprite o una lista; con un array u otra cosa, lanza ERR_TYPE_MISMATCH.
Ejemplo completo
Un perseguidor (rojo) va hacia el jugador (verde) por un laberinto: cada seis fotogramas calcula con dMap las distancias hasta la celda del jugador y da un paso con dir. Las paredes se pintan con rectángulos, así que no necesita imágenes.
use Display, GridMap
const CELDA = 20
// El laberinto: 1 es pared y 0 es pasillo
var filas = [
"111111111111",
"100000010001",
"101111010101",
"100001000101",
"111101111101",
"100000000001",
"101111011101",
"100000010001",
"111111111111"
]
var mapa = GridMap.new(12, 9)
for (var y = 0; y < 9; y++)
for (var x = 0; x < 12; x++)
if (filas[y][x] == "1") then mapa.set(x, y, 1) end
end
end
mapa.solids = [1]
var jugX = 10 // el jugador, quieto
var jugY = 7
var perX = 1 // el perseguidor
var perY = 1
var ruta = mapa.path(perX, perY, jugX, jugY)
println("Camino más corto: ", len(ruta) div 2 - 1, " pasos") // 15 pasos
// dir() devuelve 0 (quieto), 1 arriba, 2 abajo, 3 izquierda o 4 derecha
var dx = [0, 0, 0, -1, 1]
var dy = [0, -1, 1, 0, 0]
Display.open(240, 180)
Display.fps = 30
var draw = Display.draw
for (var f = 0; f < 300; f++) // 10 segundos
if (f % 6 == 0) then // un paso cada 6 fotogramas
mapa.set(jugX, jugY, 9) // la celda del jugador, objetivo del dMap
var dist = mapa.dMap(9)
mapa.set(jugX, jugY, 0)
var d = dist.dir(perX, perY)
perX = perX + dx[d]
perY = perY + dy[d]
end
draw.color = 0x3050A0
for (var y = 0; y < 9; y++)
for (var x = 0; x < 12; x++)
if (mapa.get(x, y) == 1) then
draw.rect(x * CELDA, y * CELDA, CELDA, CELDA, true)
end
end
end
draw.color = 0x40FF40
draw.rect(jugX * CELDA + 4, jugY * CELDA + 4, 12, 12, true)
draw.color = 0xFF4040
draw.rect(perX * CELDA + 4, perY * CELDA + 4, 12, 12, true)
Display.update()
end
println("El perseguidor está en (", perX, ", ", perY, ")") // (10, 7)
Display.close()
Para pintar el mapa con imágenes en vez de rectángulos, usa draw.tilemap (un tile por celda, con un tileset) o draw.gridBitmap (una imagen en las celdas con un valor).
Trampas y problemas conocidos
path,dMapynearestconectan los dos ejes en cuanto uno tiene wrap (ver Movimiento toroidal).- En Windows,
draw.tilemapno ve lo que cambiaclearhasta el siguienteset(ver clear). setno acepta decimales, ygetsí. Si calculas la celda dividiendo píxeles entre el tamaño del tile, usadivparaset(mapa.set(px div 16, py div 16, 1)).solidsyplatformsguardan tu lista, no una copia: si cambias la lista después, cambian también en el mapa.count,hasyfindno comprueban el valor: uno fuera de 0–255 da la vuelta en un byte (count(256)cuenta los 0).hitssolo mueve cuerposDYNAMIC, y solo con el tamaño de tile puesto (ver hits).
Todos los problemas conocidos de JARU, juntos, están en Problemas conocidos.