{"id":45,"date":"2024-05-15T13:31:51","date_gmt":"2024-05-15T13:31:51","guid":{"rendered":"https:\/\/dasnaddy.de\/?page_id=45"},"modified":"2024-05-22T10:36:07","modified_gmt":"2024-05-22T10:36:07","slug":"adjustable-hexmap-in-godot","status":"publish","type":"page","link":"https:\/\/dasnaddy.de\/index.php\/adjustable-hexmap-in-godot\/","title":{"rendered":"Adjustable HexMap in Godot"},"content":{"rendered":"\n<p>This tutorial is about creating a Map with Hexagon Tiles in Godot. <\/p>\n\n\n\n<p>For a game prototype i wanted to have an overworld map with HexTiles. But not procedural generated but really fixed. So &#8230; i searched for tutorials. HexGrid basics and procedural generations are there, but i wanted something else&#8230; <br>I wanted to easily create and change a hexmap in Godot.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"360\" src=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-01904.png\" alt=\"\" class=\"wp-image-47\" srcset=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-01904.png 640w, https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-01904-300x169.png 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n\n\n\n<p>This shows the possible outcome of a generated map in Godot. <\/p>\n\n\n\n<p>What will be covered in this tutorial:<br>&#8211; <a href=\"#importResources\">How to import the free resources i used<\/a><br>&#8211; <a href=\"#ProblemsWithHexMaps\">Problems with HexMaps<\/a><br>&#8211; <a href=\"#positioningTheTiles\">Positioning of HexTiles on a map with simple coords<\/a><br>&#8211; <a href=\"#mapGeneration\">Generating a Map in a Square Size<\/a><br>&#8211; <a href=\"#changeMapSize\">Change the Map Size<\/a><br>&#8211; <a href=\"#changeableTiles\">Having MapTiles that you can change<\/a><br>&#8211; <a href=\"#createCollisions\">Getting Collisionshapes out of the used models<\/a><\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"importResources\">Import free resources<\/h2>\n\n\n<p>I used the sources of a really cool artist: <a href=\"https:\/\/kaylousberg.com\/\" data-type=\"link\" data-id=\"https:\/\/kaylousberg.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Kay Lousberg<\/a>. He recently published his &#8220;Medieval Hexagon Pack&#8221; on itch and it has a really big and cool free part&#8230; <\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/kaylousberg.itch.io\/kaykit-medieval-hexagon\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"537\" height=\"315\" src=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-02870.png\" alt=\"\" class=\"wp-image-68\" style=\"width:423px;height:auto\" srcset=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-02870.png 537w, https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-02870-300x176.png 300w\" sizes=\"auto, (max-width: 537px) 100vw, 537px\" \/><\/a><\/figure>\n\n\n\n<p>You can just use the free set to follow this or give him some money for his great work and please look at his other assets as well.<\/p>\n\n\n\n<p>After you downloaded and extracted the zip file you need to go into the assets folder and for godot we need the content of the gtlf folder wich contains all the models of the kit to use with godot.<\/p>\n\n\n\n<p>Now open Godot with your project or create a new one for this tutorial. <\/p>\n\n\n\n<p>I created a folder &#8220;Assets&#8221; inside my project and pulled the subfolders of the gtlf folder into it. <\/p>\n\n\n\n<p class=\"o-typing-faster\"><sub><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-ti-accent-color\">Small note: you need to select the folder you want to drag somethin into in godot first so it is highlighted, because godot will import into the hightlighted folder<\/mark><\/sub><\/p>\n\n\n\n<p>After importing the files we are ready to start.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"ProblemsWithHexMaps\">Problems with HexMaps<\/h2>\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"950\" height=\"656\" src=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-07528.png\" alt=\"\" class=\"wp-image-73\" srcset=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-07528.png 950w, https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-07528-300x207.png 300w, https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-07528-768x530.png 768w\" sizes=\"auto, (max-width: 950px) 100vw, 950px\" \/><\/figure>\n\n\n\n<p>Using HexMaps is cool i really like them, but positioning them by hand is really time comsuming. You need to position every single tile and then never touch the coords again. <\/p>\n\n\n\n<p>I just lost my drive trying to align 10 HexTiles and my idea was to have a base map of 10&#215;10.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"positioningTheTiles\">Positioning of HexTiles on a map with simple coords<\/h2>\n\n\n<p>So the first thing we need is something that positions the hextiles for us. It needs to be done in the editor and not only when running the game and not randomly, since the outcome we are aiming for in this tutorial is a static map that we can easily edit in the editor.<\/p>\n\n\n\n<p>I want to use simple 2D coords for the map. (0\/0) being in the 0\/0\/0 position of the map. <\/p>\n\n\n\n<p><sub><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-ti-accent-color\">Small note: Godot 2D coords (x\/y) are simple but the 3D coords (x\/y\/z) shift since the y in the 3D space is the &#8220;up\/down&#8221; coord&#8230; so we need to always transfer the second (y) coord of our tile to the third (z) value of the position of the tile in the 3D space<\/mark><\/sub><\/p>\n\n\n\n<p>So first of all we need to create a 3D Scene in our game. I named it &#8220;World&#8221; and inside that add another Node3D and name it &#8220;MapTile&#8221; and drag the &#8220;hex_grass.gltf&#8221; from the &#8220;Assets-&gt;tiles-&gt;base&#8221; under the &#8220;MapTile&#8221; you just added.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"958\" height=\"660\" src=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-08684.png\" alt=\"\" class=\"wp-image-74\" style=\"width:742px;height:auto\" srcset=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-08684.png 958w, https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-08684-300x207.png 300w, https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/Frame-08684-768x529.png 768w\" sizes=\"auto, (max-width: 958px) 100vw, 958px\" \/><\/figure>\n\n\n\n<p>Since we will need this as a loadable element and add some more stuff to it later, let&#8217;s save this as it&#8217;s own scene. Do do this right-click on the &#8220;MapTile&#8221; and select &#8220;Save Branch as Scene&#8230;&#8221;. <\/p>\n\n\n\n<p>I created a folder under the project root named &#8220;Tiles&#8221; to save all my tiles stuff under.  <\/p>\n\n\n\n<p>Open the newly created scene and add a script to it.<br>First of all we add 2 consts that define the dimensions of our tile:<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>const TILE_WIDTH:int = 2\nconst TILE_HEIGHT:int = 1<\/code><\/pre>\n\n\n\n<p>The width defines the distance from the flat to the flat on the surface, <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"308\" height=\"247\" src=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-5.png\" alt=\"\" class=\"wp-image-121\" srcset=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-5.png 308w, https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-5-300x241.png 300w\" sizes=\"auto, (max-width: 308px) 100vw, 308px\" \/><\/figure>\n\n\n\n<p>the height the y-height of the tile (so we may change the tile positioning on the y axis later)<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"451\" height=\"349\" src=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-6.png\" alt=\"\" class=\"wp-image-122\" style=\"width:317px;height:auto\" srcset=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-6.png 451w, https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-6-300x232.png 300w\" sizes=\"auto, (max-width: 451px) 100vw, 451px\" \/><\/figure>\n\n\n\n<p>Than we need the varable for the coords. It should be an @export var so it can be manipulated in the editor later. But first of all we need to talk about another notation to be used in this script and this is @tool.<\/p>\n\n\n\n<p><sub><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-ti-accent-color\">Small note: @tool notation on top of a script will let it execute code inside the editor.<\/mark><\/sub><\/p>\n\n\n\n<p>So the script should now look like this. Combining the @tool notation and the setter of a value you can create code that is executed in the editor when you change a variable.<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa has-small-font-size\" style=\"border-width:4px;font-style:normal;font-weight:600\"><code>@tool\nextends Node3D\n\nconst TILE_WIDTH:int = 2\nconst TILE_HEIGHT:int = 1\n\n@export var coords:Vector3i:\n\tset(value):\n\t\tcoords = value\n\t\tvar modifier = 0 if coords.z % 2 == 0 else TILE_WIDTH \/ 2\n\t\tposition.x = coords.x * TILE_WIDTH + modifier\n\t\tposition.y = coords.y * TILE_HEIGHT \n\t\tposition.z = coords.z * TILE_WIDTH * cos(deg_to_rad(30))<\/code><\/pre>\n\n\n\n<p>I won&#8217;t explain the calculations i depth. If you are interested in the calculations please what one of the tutorials you can find about hexgrid generation. <br>&#8211; The modifier in this code checks if the tile is on an even or odd row and moves it accordingly to fit into the space it should occupy<br>&#8211; The z-coord is calculated with the tile-width and the cosinus to get the correct positioning.<\/p>\n\n\n\n<p>When you now hop to the 2D view and change the coords&#8230; nothing happens&#8230; this is because Godot didn&#8217;t register the @tool notation yet. To fix this close the &#8220;MapTile&#8221; Scene and reopen it. Now changing the coords values should change the positioning of the MapTile in the editor.<\/p>\n\n\n\n<p>First step done!<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"mapGeneration\">Generating a Map in a Square Size<\/h2>\n\n\n<p>Ok, now we are able to add a tile and just change the coords so it is in the right position, now it would be cool if godot would do the positioning for us. <\/p>\n\n\n\n<p>For this we open the &#8220;World&#8221; scene and add another &#8220;Node 3D&#8221; to it and call it &#8220;Map&#8221;. This map should work for us, so we add a script to it (i just saved it under the main root, like the world node as well)<\/p>\n\n\n\n<p>The map-script needs to be a tool script too and it needs to know where it can find our MapTile it should position on the map, as well as the size the map should be. Since we will only generate the map in two dimensions we only need a Vector2D for this variable. <\/p>\n\n\n\n<p>I will also add a preloading of the map_tile so the script knows it and we can instaitate it easily as well as a dictionary that will help access the tiles we generate later.<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>@tool\nextends Node3D\n\n@onready var map_tile_prefab = preload(\"res:\/\/Tiles\/map_tile.tscn\")\n\n@export var map_tiles:Dictionary\n@export var map_size: Vector2i = Vector2i(2,2)<\/code><\/pre>\n\n\n\n<p><sub><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-ti-accent-color\">Small note: i&#8217;m using Vector2i for this since the map size can only have integer values since the map cannot be 2,5 tiles wide with this script<\/mark><\/sub><\/p>\n\n\n\n<p>Now we need a method to trigger our map generation in the editor. Since it is not possible to add buttons in the editor inspector without writing a bigger tool we fake one with a checkbox.<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>@export var generate_the_map:bool:\n\tset(value):\n\t\tif value == true:\n\t\t\tgenerate_map()\n\t\t\tgenerate_the_map = false<\/code><\/pre>\n\n\n\n<p>with this the funciton &#8220;generate_map()&#8221; will be triggered everytime we click on the checkbox. Since we only need it to trigger the function, we never set the value to true.<\/p>\n\n\n\n<p>Now we need the generate map function but we need to check if the map can be generated at all.<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa has-small-font-size\" style=\"border-width:4px;font-style:normal;font-weight:600\"><code>func generate_map():\n\tif map_size == Vector2i.ZERO || map_size.x == 0 || map_size.y == 0:\n\t\tprinterr(\"MapSize or one of its values is Zero!, cannot generate Map\")\n\t\treturn \n\n\tvar start = Vector2i.ZERO\n\tfor x in map_size.x:\n\t\tfor z in map_size.y:\n\t\t\tvar new_pos = Vector3i(start.x+x, 0, start.y+z)\n\t\t\tadd_tile(new_pos)\n\nfunc add_tile(new_pos):\n\tvar scene = get_tree().get_edited_scene_root()\n\tvar new_tile = map_tile_prefab.instantiate()\n\tadd_child(new_tile)\n\tnew_tile.set_owner(scene)\n\tnew_tile.name = \"MapTile\"+str(new_pos)\n\tnew_tile.coords = new_pos\n\tmap_tiles&#91;new_tile.coords] = new_tile<\/code><\/pre>\n\n\n\n<p><sub><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-ti-accent-color\">Site note: Remember that we set the start.y coord to the z part of the coord of the tile since the y-axis-vaue of the start (Vector2i) needs to be put in the z-axis-value of the tile-coord (Vector3i)<\/mark><\/sub><\/p>\n\n\n\n<p>I positioned the actual adding of the tile in a separate function so we can reuse it later. For better identification i also name the Tiles with &#8220;MapTile&#8221; and the given coords.<\/p>\n\n\n\n<p>The scene and the set_owner are needed so the Tiles you add via code are shown in the Scene tree and therefor be saved when you save the map. Otherwise these would be lost when closing and saving the scene (wich would be really annoying)<\/p>\n\n\n\n<p>Generation starts at 0\/0 and moves on, thats cool but maybe we want the 0\/0 to be the center, so we can add a &#8220;start_at_zero&#8221; variable that we wil use when generating the map. <\/p>\n\n\n\n<p>Just add <\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>@export var start_at_zero:bool = true<\/code><\/pre>\n\n\n\n<p>at the top where the other variables are created and change the generate_map-Function by adding<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>if !start_at_zero: start -= map_size\/2<\/code><\/pre>\n\n\n\n<p>after the initalising the start variable.<\/p>\n\n\n\n<p>Now up to the next problem: <br>When you recreate your map&#8230; it creates it on top of the old tiles. So, either we need to delete them ourselfs (boooo), or we need something to clear the map (yeaaahhh). Then let&#8217;s add another checkbox to trigger a function:<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>@export_category(\"DELETE\")\n@export var clear_the_map:bool:\n\tset(value):\n\t\tif value == true:\n\t\t\tclear_map()\n\t\t\tclear_the_map = false<\/code><\/pre>\n\n\n\n<p>and the clear_map function<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>func clear_map():\n\tfor c in get_children():\n\t\tc.queue_free()<\/code><\/pre>\n\n\n\n<p>wich is really simple it only removes the children of the map node&#8230; wooosh&#8230; <\/p>\n\n\n\n<p>I added &#8220;@export_category(&#8220;DELETE&#8221;)&#8221; on top of the new export-variable so it will have it&#8217;s own section inside the inspector and you are less prone to click on it and erase your map.<\/p>\n\n\n\n<p>Let&#8217;s change the MapTile by adding some debug-informations like the coords<\/p>\n\n\n\n<p>Open or focus the &#8220;MapTile&#8221; scene and add a Label3D Node to the root of the scene and name it &#8220;DebugText&#8221; and set visible to false. <\/p>\n\n\n\n<p>Change the Transform settings to this, so it is positioned slightly above the tile facing up:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"253\" height=\"186\" src=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik.png\" alt=\"\" class=\"wp-image-100\"\/><\/figure>\n\n\n\n<p>I chose the following settings:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"247\" height=\"242\" src=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-2.png\" alt=\"\" class=\"wp-image-102\" style=\"width:241px;height:auto\"\/><\/figure>\n\n\n\n<p>Add a variable to your MapTile script and a function to handle the display of it<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>@export var show_debug_text:bool:\n\tset(value):\n\t\tshow_debug_text = value\n\t\tif Engine.is_editor_hint(): show_debug()\n\nfunc show_debug():\n\tvar debug_text = get_node_or_null(\"DebugText\")\n\tif debug_text == null: return\n\t$DebugText.text = str(coords)\n\t$DebugText.visible = show_debug_text<\/code><\/pre>\n\n\n\n<p>the first two lines of the show_debug functions are for save fail only. Since it may be that the debug text it not there or not loaded so in this case the function simply returns and does nothing<\/p>\n\n\n\n<p>The &#8220;Engine.is_editor_hint()&#8221; is a function you can use when you want to check if the code is run in the editor or not. In this case it only should run in the editor.<\/p>\n\n\n\n<p>So changing this variable in the editor inspector should change the visibility of the debug text and set it to the correct value of the coords. To have the value change when you change the coords simply add the following line to the setter of the coords<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>if Engine.is_editor_hint(): show_debug()<\/code><\/pre>\n\n\n\n<p>Ok MapTile done for now, change back to the world scene and open the map script again since we want to be able to trigger the debug text in the map itself and not for every single map tile<\/p>\n\n\n\n<p>We add a variable to the script, naming it like the one in the tile<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>@export var show_debug_text:bool = false:\n\tset(value):\n\t\tshow_debug_text = value\n\t\tshow_debug()<\/code><\/pre>\n\n\n\n<p>and the show_debug function<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>func show_debug():\n\tfor t in get_children():\n\t\tt.show_debug_text = show_debug_text<\/code><\/pre>\n\n\n\n<p>wich is quite straight forward<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"changeMapSize\">Change the Map Size<\/h2>\n\n\n<p>Right now we can only replace a map but not change it&#8217;s size and keep the old one. But when we start placing stuff on top of different tiles we would want to keep the already existent tiles when changing the size.<\/p>\n\n\n\n<p>For this we split up the generation of the map and change the &#8220;generate_map&#8221; function<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa has-small-font-size\" style=\"border-width:4px;font-style:normal;font-weight:600\"><code>func generate_map():\n\tif map_size == Vector2i.ZERO || map_size.x == 0 || map_size.y == 0:\n\t\tprinterr(\"MapSize or one of its values is Zero!, cannot generate Map\")\n\t\treturn \n\tif get_child_count() == 0:\n\t\tgenerate_clear_map()\n\telse:\n\t\tgenerate_changed_map()<\/code><\/pre>\n\n\n\n<p>The old map generation gets it&#8217;s own function<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa has-small-font-size\" style=\"border-width:4px;font-style:normal;font-weight:600\"><code>func generate_clear_map():\n\tvar start = Vector2i.ZERO\n\tif !start_at_zero: start -= map_size\/2\n\tfor x in map_size.x:\n\t\tfor z in map_size.y:\n\t\t\tvar new_pos = Vector3i(start.x+x, 0, start.y+z)\n\t\t\tadd_tile(new_pos)<\/code><\/pre>\n\n\n\n<p><sub><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-ti-accent-color\">Site note: Remember that we set the start.y coord to the z part of the coord of the tile since the y-axis-vaue of the start (Vector2i) needs to be put in the z-axis-value of the tile-coord (Vector3i)<\/mark><\/sub><\/p>\n\n\n\n<p>For the new function we need to get the following stuff worked through:<br>&#8211; if the map size is smaller: remove the &#8220;overhang&#8221;<br>&#8211; if the map size is greater: add new tiles<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa has-small-font-size\" style=\"border-width:4px;font-style:normal;font-weight:600\"><code>func generate_changed_map():\n\tvar start = Vector2i.ZERO\n\tif !start_at_zero: start -= map_size\/2\n\t##remove tiles not in map anymore\n\tfor tile_pos in map_tiles.keys():\n\t\tvar test = Vector3i(start.x-map_size.x-1,0,start.y+map_size.y-1)\n\t\tif tile_pos.x &gt; test.x || tile_pos.z &gt; test.z: remove_tile(tile_pos)\n\t\telif tile_pos.x &lt; start.x || tile_pos.z &lt; start.y: remove_tile(tile_pos)\n\t##add new tiles\n\tfor x in map_size.x:\n\t\tfor z in map_size.y:\n\t\t\tvar current_pos = Vector3i(start.x+x, 0, start.y+z)\n\t\t\tif !map_tiles.has(current_pos):\n\t\t\t\tadd_tile(current_pos)\n\nfunc remove_tile(tile_pos):\n\tif map_tiles.has(tile_pos):\n\t\tvar to_remove = map_tiles&#91;tile_pos]\n\t\tmap_tiles.erase(tile_pos)\n\t\tto_remove.get_parent().remove_child(to_remove)<\/code><\/pre>\n\n\n\n<p><sub><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-ti-accent-color\">Site note: the removing of the tiles seams a bit warped but we want to be sure that the tile isn&#8217;t in the map_tile dictionary anymore and is not referenced by anything. The weird way of using the geet_parent().remove_child() function called by the child itself seems to do the trick<\/mark><\/sub><\/p>\n\n\n\n<p>So we remove every tile that as an x or y coord value below the new starting point (only happening when you have start_at_zero = false) or the x or y coord are higher that the starting point plus the map-size minus one.<\/p>\n\n\n\n<p>To add new tiles the code simply checks if a tile exists for every coord the new map size will produce.<\/p>\n\n\n\n<p>With that we can change the size and all the tiles inside the new map_size remain untouched by the change.<\/p>\n\n\n\n<p><sub><span class=\"highlight\">Update 20.05.2024 (found a problem with loading the map)<\/span><\/sub><\/p>\n\n\n\n<p>To be able to use the generation with changed maps after freshly loading the Map in the editor we need to help the script load the dictionary of the tiles correctly. So we add a new function that recreates the map_tiles dictionary<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>func check_map_tiles_dict():\n\tmap_tiles = {}\n\tfor c in get_children():\n\t\tmap_tiles&#91;c.coords] = c<\/code><\/pre>\n\n\n\n<p>Then call this function on top of the &#8220;generate_changed_map&#8221; function and you should be save<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"changeableTiles\">Having MapTiles that you can change<\/h2>\n\n\n<p>Alright&#8230; the map is being created and now it would be really cool if we could just change the tiles by clicking on them.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"981\" height=\"834\" src=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-3.png\" alt=\"\" class=\"wp-image-114\" style=\"width:589px;height:auto\" srcset=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-3.png 981w, https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-3-300x255.png 300w, https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-3-768x653.png 768w\" sizes=\"auto, (max-width: 981px) 100vw, 981px\" \/><\/figure>\n\n\n\n<p>Just clicking on a tile and having a range of tiles to choose from would be cool, wouldn&#8217;t it?<\/p>\n\n\n\n<p>To create this, we need to change our MapTile a bit. For this we remove the &#8220;hex_gras&#8221; from our MapTile Scene and add a new Node3D and name it HexTile. This will be our container for the actual visual Tile we want to select.<\/p>\n\n\n\n<p>Add another Node3D this &#8220;HexTile&#8221; Node and name it &#8220;GrassTile&#8221;, all other Tiles will be inherited from this one. Drag and drop the hex_grass from our Assets\/tiles\/base folder into the &#8220;GrassTile&#8221; Node and create a new Scene out of this (right click on the &#8220;GrassTile&#8221; node and select &#8220;Save Branch as Scene&#8221;. Save it into the same folder you saved the HexTile Scene into. <\/p>\n\n\n\n<p>Please check that the hex_grass is at the 0\/0\/0 position just to be sure.<\/p>\n\n\n\n<p>For other Tile Types you can either follow the same way and maybe add Houses on Top of the grass tile or you create inherited scenes where you keep the stuff of the parent scene and just add stuff on top.<\/p>\n\n\n\n<p>For this tutorial i created a grass-tile and a water-tile just to show how my idea works.<\/p>\n\n\n\n<p>Now you go to the MapTile scene and remove the node or nodes that are children of the MapTile Scene <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"263\" height=\"122\" src=\"https:\/\/dasnaddy.de\/wp-content\/uploads\/2024\/05\/grafik-4.png\" alt=\"\" class=\"wp-image-115\"\/><\/figure>\n\n\n\n<p>To be able to change the tiles with the variable we need to preload all the options<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>@onready var preloads:Dictionary = {\n\t\"grass\": load(\"res:\/\/Tiles\/grass_tile.tscn\"),\n\t\"water\": load(\"res:\/\/Tiles\/water_tile.tscn\")\n}<\/code><\/pre>\n\n\n\n<p>Then we need the select box to select the tiletypes. For this we use the @export_enum annotation wich i really like for stuff like this<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>@export_enum(\"grass\",\"water\") var tile_type:String = \"grass\":\n\tset(value):\n\t\ttile_type = value\n\t\tinit_hex_tile()<\/code><\/pre>\n\n\n\n<p>For this to work in the editor we use a setter, again \ud83d\ude09<\/p>\n\n\n\n<p>The called init_hex_tile function wich simply sets the hex_tile that should be used by the map_tile<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>func init_hex_tile():\n\tif tile_type in preloads:\n\t\tused_tile = preloads&#91;tile_type].instantiate()<\/code><\/pre>\n\n\n\n<p>This triggers the setter of another variable wich stores the instatiated tile we want to display.<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>var used_tile:\n\tset(value):\n\t\tused_tile = value\n\t\tif Engine.is_editor_hint(): set_hex_tile()<\/code><\/pre>\n\n\n\n<p>In editor we now want to actually set the hex tile. When the game is running this will be handled by the _ready function<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa has-small-font-size\" style=\"border-width:4px;font-style:normal;font-weight:600\"><code>func set_hex_tile():\n\tclear_hex_tile()\n\tvar hex_tile = get_node_or_null(\"HexTile\")\n\tif hex_tile == null: return\n\t$HexTile.add_child(used_tile)\n\tused_tile.set_owner(self)\n\t\t\nfunc clear_hex_tile():\n\tvar hex_tile = get_node_or_null(\"HexTile\")\n\tif hex_tile != null:\n\t\tfor c in hex_tile.get_children():\n\t\t\tc.queue_free()<\/code><\/pre>\n\n\n\n<p>These two functions take care of loading the tiletype you want to have on your tile. First the HexTile container is cleared and then the wanted hexTile is loaded into the HexTile container. <\/p>\n\n\n\n<p><sub><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-ti-accent-color\">Small note: reminder: you need to set the owner so the code-added-node appears in the scene tree in the editor<\/mark><\/sub><\/p>\n\n\n\n<p>For ingame-functionality just add the _ready function<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa\" style=\"border-width:4px;font-size:18px;font-style:normal;font-weight:600\"><code>func _ready():\n\tif !Engine.is_editor_hint(): show_debug()\n\tinit_hex_tile()\n\tif !Engine.is_editor_hint(): set_hex_tile()<\/code><\/pre>\n\n\n\n<p>You may need to close and reopen the MapTile Scene to get this working in the editor<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"createCollisions\">Getting Collisionshapes out of the used models<\/h2>\n\n\n<p>Last thing you may want to add is a StaticBody3D to your MapTile so you can get click-actions or other collision stuff on your tiles.<\/p>\n\n\n\n<p>So add a StaticBody3D Node to your MapTile<\/p>\n\n\n\n<p>The cool thing is you can geht the collisionshapes out of the data you have in your hex tiles<\/p>\n\n\n\n<p>Change the set_hex_tile and clear_hex_tile functions like this:<\/p>\n\n\n\n<pre class=\"wp-block-code ticss-4b6ba9aa has-small-font-size\" style=\"border-width:4px;font-style:normal;font-weight:600\"><code>func set_hex_tile():\n\tclear_hex_tile()\n\tvar hex_tile = get_node_or_null(\"HexTile\")\n\tif hex_tile == null: return\n\t$HexTile.add_child(used_tile)\n\tused_tile.set_owner(self)\n\tfor c in used_tile.get_children():\n\t\tfor m in c.get_children():\n\t\t\tif m is MeshInstance3D:\n\t\t\t\tvar polygon = m.mesh.create_convex_shape(true, true)\n\t\t\t\tvar shape = CollisionShape3D.new()\n\t\t\t\tshape.shape = polygon\n\t\t\t\t$StaticBody3D.add_child(shape)\n\t\t\t\tshape.position = c.position\n\t\t\t\tshape.scale = c.scale\n\t\t\t\tshape.set_owner(self)\n\t\nfunc clear_hex_tile():\n\tvar hex_tile = get_node_or_null(\"HexTile\")\n\tif hex_tile != null:\n\t\tfor c in hex_tile.get_children():\n\t\t\tc.queue_free()\n\tvar static_body = get_node_or_null(\"StaticBody3D\")\n\tif static_body != null:\n\t\tfor c in $StaticBody3D.get_children():\n\t\t\tc.queue_free()<\/code><\/pre>\n\n\n\n<p>This extracts the shapes out of the MeshInstance3D and the inlaid Meshes and creates polygons out of it wich can use as shapes for CollisionShape3D nodes&#8230; wich you then add to your $StaticBody3D.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><em>And thats it for this Tutorial&#8230; hope you enjoyed it. If you have questions, just join the Sehoni Island Discord &#8230; you can find the link in the footer right below.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial is about creating a Map with Hexagon Tiles in Godot. For a game prototype i wanted to have an overworld map with HexTiles. But not procedural generated but really fixed. So &#8230; i searched for tutorials. HexGrid basics and procedural generations are there, but i wanted something else&#8230; I wanted to easily create [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_themeisle_gutenberg_block_has_review":false,"footnotes":""},"class_list":["post-45","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/dasnaddy.de\/index.php\/wp-json\/wp\/v2\/pages\/45","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dasnaddy.de\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/dasnaddy.de\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/dasnaddy.de\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dasnaddy.de\/index.php\/wp-json\/wp\/v2\/comments?post=45"}],"version-history":[{"count":30,"href":"https:\/\/dasnaddy.de\/index.php\/wp-json\/wp\/v2\/pages\/45\/revisions"}],"predecessor-version":[{"id":136,"href":"https:\/\/dasnaddy.de\/index.php\/wp-json\/wp\/v2\/pages\/45\/revisions\/136"}],"wp:attachment":[{"href":"https:\/\/dasnaddy.de\/index.php\/wp-json\/wp\/v2\/media?parent=45"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}