{"id":1108,"date":"2025-09-08T08:00:00","date_gmt":"2025-09-08T07:00:00","guid":{"rendered":"https:\/\/jorgeturiel.es\/?p=1108"},"modified":"2025-08-30T16:34:20","modified_gmt":"2025-08-30T15:34:20","slug":"mapas-aleatorios-en-juegos","status":"publish","type":"post","link":"https:\/\/jorgeturiel.es\/?p=1108","title":{"rendered":"Mapas aleatorios en juegos"},"content":{"rendered":"\n<p>Recientemente vi un <a href=\"https:\/\/www.youtube.com\/watch?v=biIB4luFzu8&amp;t=26s\">v\u00eddeo de Hdeleon<\/a> en Youtube, en el explicaba de una manera sencilla como se pueden crear mapas aleatorios en juegos. Lo interesante de este v\u00eddeo, es que hace uso de matrices (o arrays) bidimensionales. Primero crea una matriz con de caracteres, donde cada tipo de car\u00e1cter representa algo en un mapa. Luego explica como crear una imagen, recorriendo la matriz que ha creado. As\u00ed que decid\u00ed replicarlo Free Pascal. <\/p>\n\n\n\n<!--more-->\n\n\n\n<p> Lo primero ser\u00e1 crear un nuevo proyecto que sea un programa  en Lazarus.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:100%\"><div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"338\" height=\"416\" src=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusCrearProyecto.jpg\" alt=\"\" class=\"wp-image-386\" srcset=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusCrearProyecto.jpg 338w, https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusCrearProyecto-244x300.jpg 244w\" sizes=\"auto, (max-width: 338px) 100vw, 338px\" \/><\/figure>\n<\/div>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"563\" height=\"334\" src=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusEscogerProyecto.jpg\" alt=\"\" class=\"wp-image-388\" srcset=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusEscogerProyecto.jpg 563w, https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusEscogerProyecto-300x178.jpg 300w\" sizes=\"auto, (max-width: 563px) 100vw, 563px\" \/><\/figure>\n<\/div><\/div>\n<\/div>\n\n\n\n<p>Antes, de continuar, debes tener instalado el paquete <em><a href=\"https:\/\/bgrabitmap.github.io\/\">BGRAbitmap<\/a><\/em>. Este paquete  permite manipular las im\u00e1genes de una manera r\u00e1pida y sencilla. Aunque Lazarus tiene su propio paquete (<em><a href=\"https:\/\/wiki.freepascal.org\/Developing_with_Graphics\/es\">Graphics<\/a>)<\/em>, que podr\u00edamos usar en este caso, ya que no necesitamos velocidad, este solo funciona en aplicaciones de escritorio. <\/p>\n\n\n\n<p>Para instalar este paquete vete al men\u00fa <em>Herramientas->Online package manager<\/em>. Y busca BGRAbitmap<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"443\" height=\"382\" src=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2025\/08\/Captura-de-pantalla_20250830_165152.png\" alt=\"\" class=\"wp-image-1111\" srcset=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2025\/08\/Captura-de-pantalla_20250830_165152.png 443w, https:\/\/jorgeturiel.es\/wp-content\/uploads\/2025\/08\/Captura-de-pantalla_20250830_165152-300x259.png 300w\" sizes=\"auto, (max-width: 443px) 100vw, 443px\" \/><figcaption class=\"wp-element-caption\">Men\u00fa Paquete<\/figcaption><\/figure>\n<\/div>\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"950\" height=\"729\" src=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2025\/08\/Captura-de-pantalla_20250830_165402.png\" alt=\"\" class=\"wp-image-1112\" srcset=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2025\/08\/Captura-de-pantalla_20250830_165402.png 950w, https:\/\/jorgeturiel.es\/wp-content\/uploads\/2025\/08\/Captura-de-pantalla_20250830_165402-300x230.png 300w, https:\/\/jorgeturiel.es\/wp-content\/uploads\/2025\/08\/Captura-de-pantalla_20250830_165402-768x589.png 768w\" sizes=\"auto, (max-width: 950px) 100vw, 950px\" \/><\/figure>\n\n\n\n<p>Tras instalar el paquete, empezamos a programar. Lo primero es a\u00f1adir las unidades que vamos a usar al principio del documento, y luego declaramos un tipo de variable llamado <em>Tmap<\/em> la cual ser\u00e1 un array de dos dimensiones de caracteres, pero de dimensi\u00f3n desconocida.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >uses\n  SysUtils,\n  BGRABitmap,\n  BGRABitmapTypes;\n\ntype\n  Tmap = array of array of char; <\/pre><\/div>\n\n\n\n<p>Lo siguiente es crear una funci\u00f3n que nos devuelva un mapa. Este mapa ser\u00e1 de un ancho y alto que pasamos por par\u00e1metros.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >function GenerateMap(AAncho: integer; AAlto: integer): Tmap;\n  var\n    Y, X: integer;\n  begin\n    Result := Tmap.Create;\n    SetLength(Result, AAncho, AAlto);\n    for Y := 0 to AAncho - 1 do\n    begin\n      for x := 0 to AAlto - 1 do\n      begin\n        if Random() &lt; 0.15 then\n        begin\n          Result[y, x] := '#';\n        end\n        else\n        begin\n          Result[y, x] := '.';\n        end;\n      end;\n    end;\n\n  end;                   <\/pre><\/div>\n\n\n\n<p>F\u00edjate, que en la l\u00ednea 6, se ajusta el tama\u00f1o del array seg\u00fan los par\u00e1metros que recibe la funci\u00f3n.<\/p>\n\n\n\n<p>Luego recorremos el array, y en cada posici\u00f3n de este, a\u00f1adimos el car\u00e1cter <em>\u00ab#\u00bb <\/em>en caso que sea un \u00e1rbol, o el car\u00e1cter \u00ab.\u00bb en el caso que no hay un \u00e1rbol. Para decidir si se pone un \u00e1rbol o no, lo que hace el \u0107odigo, es generar un n\u00famero aleatorio entre 0 y 0.99. Si este n\u00famero es menor de 0.15 consideremos que hay un a\u0155bol. Esto ser\u00eda como indicar que queremos un 15% de \u00e1rboles en nuestro mapa.<\/p>\n\n\n\n<p>Para mostrar el mapa en pantalla, creamos un procedimiento llamado <em>PrintMap<\/em>, que recibe como par\u00e1metro el mapa que queremos mostrar por pantalla.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" > procedure PrintMap(AMap: Tmap);\n  var\n    Y, X: integer;\n  begin\n    for Y := 0 to High(AMap) do\n    begin\n      for X := 0 to High(AMap[1]) do\n      begin\n        Write(AMap[y, x]);\n      end;\n      Writeln();\n    end;\n  end;            <\/pre><\/div>\n\n\n\n<p>En este procedimiento recorremos el array desde su inicio, hasta el final. Para conocer el tama\u00f1o del array usamos la funci\u00f3n <em>High<\/em>, lo cual no devolver\u00e1 el tama\u00f1o de la primera dimensi\u00f3n (l\u00ednea 5 de c\u00f3digo anterior). Para obtener el tama\u00f1o de la segunda dimensi\u00f3n, lo indicamos entre corchetes. (l\u00ednea 7).<\/p>\n\n\n\n<p>Ya para terminar solo nos queda generar la imagen y guardarla en el disco duro. Para ello creamos un procedimiento llamado <em>SaveMapAsImage<\/em>, que recibe dos par\u00e1metros, el primero es un mapa, y el segundo el nombre con el que queremos guardar la imagen generada.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >procedure SaveMapAsImage(AMap: Tmap; AFileName: TFilename);\n  var\n    Ancho, Alto, Y, X: integer;\n    Tree, Grass: TBGRABitmap;\n    Image: TBGRABitmap;\n  begin\n    Ancho := High(AMap);\n    Alto := High(AMap[1]);\n\n    Tree := TBGRABitmap.Create;\n    Grass := TBGRABitmap.Create;\n    Image := TBGRABitmap.Create(Ancho * 16, Alto * 16);\n\n    Tree.LoadFromFile('tree.png');\n    Grass.LoadFromFile('grass.png');\n\n    for X := 0 to Ancho  do\n    begin\n      for Y := 0 to Alto do\n      begin\n        if AMap[X, Y] = '#' then\n        begin\n          Image.PutImage(X * 16, Y * 16, Tree, dmSet);\n        end\n        else\n        begin\n          Image.PutImage(X * 16, Y * 16, Grass, dmSet);\n        end;\n      end;\n    end;\n    Image.SaveToFile(AFileName);\n    FreeAndNil(Grass);\n    FreeAndNil(Tree);\n    FreeAndNil(Image);                         <\/pre><\/div>\n\n\n\n<p> Lo primero es conocer las dimensiones del mapa que se pasa por par\u00e1metros, l\u00edneas 7 y 8. <\/p>\n\n\n\n<p>Creamos tres objetos del tipo TBGRABitmap. Que llamamos <em>Tree, Grass, Image<\/em>. El objeto <em>Image <\/em>contendr\u00e1 la imagen resultante, as\u00ed que como imagen que voy a usar es de 16&#215;16 pixels por cada car\u00e1cter, su tama\u00f1o ser\u00e1 el ancho del mapa por 16, y lo el alto, ser\u00e1 el alto del mapa por 16. Esto son los datos que indicamos al crear el objeto.<\/p>\n\n\n\n<p>En Tree cargamos una imagen de un \u00e1rbol, y en Grass, cargamos una imagen de la hierba.<\/p>\n\n\n\n<p>Despu\u00e9s recorremos el mapa comprobando que car\u00e1cter hay en cada posici\u00f3n. Si es el car\u00e1cter <em>\u00ab#\u00bb<\/em>, en la posici\u00f3n que nos indica el array, multiplicado por 16, para desplazarnos a la posici\u00f3n dentro de image, que le corresponde copiamos la imagen <em>Tree.<\/em> En el caso contrario copiaremos la imagen <em>Grass<\/em>. <\/p>\n\n\n\n<p>Al terminar los bucles, se guarda la imagen con el nombre que se indic\u00f3 en el par\u00e1metro <em>AFileName<\/em>. Y por \u00faltimo liberamos los objetos que hemos creado.<\/p>\n\n\n\n<p>Con todo listo, solo queda hacer uso del c\u00f3digo que hemos generado.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >const\n  Ancho: integer = 50;\n  Alto: integer = 50;\n\nvar\n  Map: Tmap;\nbegin\n  Map := GenerateMap(Ancho, Alto);\n  PrintMap(Map);\n  SaveMapAsImage(Map, 'map.png');\n\nend.                     <\/pre><\/div>\n\n\n\n<p>El c\u00f3digo fuente completo as\u00ed como la im\u00e1genes que us\u00e9 est\u00e1n disponibles en mi Github, <a href=\"https:\/\/github.com\/Blueicaro\/Ejercicios-Programacion\/tree\/main\/Mapas%20Aleatorios\">aqu\u00ed<\/a>.<\/p>\n\n\n\n<p>Saludos<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Una manera sencilla de como se pueden crear mapas aleatorios en juegos. <\/p>\n","protected":false},"author":2,"featured_media":1110,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[61,48],"tags":[64,23,21,24],"class_list":["post-1108","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-free-pascal","category-videojuegos","tag-ejercicio-programacion","tag-lazarus","tag-pascal","tag-programacion"],"_links":{"self":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/1108","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1108"}],"version-history":[{"count":6,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/1108\/revisions"}],"predecessor-version":[{"id":1117,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/1108\/revisions\/1117"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/media\/1110"}],"wp:attachment":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1108"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1108"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1108"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}