{"id":123,"date":"2026-05-08T14:12:13","date_gmt":"2026-05-08T14:12:13","guid":{"rendered":"https:\/\/pushergame.site\/?p=123"},"modified":"2026-05-21T14:49:32","modified_gmt":"2026-05-21T14:49:32","slug":"devlog-adding-procedural-generation-to-pusher","status":"publish","type":"post","link":"https:\/\/pushergame.site\/?p=123","title":{"rendered":"Devlog- Adding Procedural Generation to PUSHER"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">A big problem with the game up until now has been the fact that it takes entirely within an infinite dark void. To fix that, I want to add some procedurally generated terrain using Godot&#8217;s built in tilemap and noise map generation, which thankfully makes it easy.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Adding Obstacles<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To make things easier for myself I&#8217;m going to be using scenes for the tiles with individual sprites. I could figure out collision within the TileMap itself some other time but the specific setup I have in mind works this way for me.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1001\" height=\"1024\" src=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-10-1001x1024.png\" alt=\"\" class=\"wp-image-124\" style=\"aspect-ratio:0.9775533543972552;width:565px;height:auto\" srcset=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-10-1001x1024.png 1001w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-10-293x300.png 293w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-10-768x786.png 768w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-10.png 1300w\" sizes=\"auto, (max-width: 1001px) 100vw, 1001px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The blue outline shows the bounds of the regular hitbox that enemies can crash into, and will block player movement, and the red outline shows the bounds of the &#8220;NavHitbox&#8221;. This will be used for the enemy AI&#8217;s pathfinding to make sure they don&#8217;t graze any corners and die.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now I need to write a script that randomly generates these at runtime. Getting where to place the tiles is pretty easy using Godot&#8217;s built-in noise generator, FastNoiseLite:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"283\" src=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-11-1024x283.png\" alt=\"\" class=\"wp-image-125\" srcset=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-11-1024x283.png 1024w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-11-300x83.png 300w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-11-768x212.png 768w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-11.png 1449w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The tricky part of this is actually enabling infinite generation. To do this I&#8217;m going to use chunks.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"415\" src=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-12-1024x415.png\" alt=\"\" class=\"wp-image-126\" srcset=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-12-1024x415.png 1024w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-12-300x121.png 300w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-12-768x311.png 768w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-12.png 1447w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The code above gets the current chunk (a square of 16 tiles) and puts it and every chunk near it in an array. Then, it ensures to load (aka spawn the tiles of) every chunk that&#8217;s within that array, and unload (despawn the tiles) every other chunk.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"602\" src=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-13-1024x602.png\" alt=\"\" class=\"wp-image-127\" srcset=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-13-1024x602.png 1024w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-13-300x176.png 300w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-13-768x452.png 768w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-13.png 1459w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The is_obstacle function queries the noise map to see if it&#8217;s over a certain threshold, and if it&#8217;s over it will spawn a tile there.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"64\" src=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-14-1024x64.png\" alt=\"\" class=\"wp-image-128\" srcset=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-14-1024x64.png 1024w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-14-300x19.png 300w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-14-768x48.png 768w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-14.png 1441w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">We can also use this function in other scripts in the future to detect obstacles!<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Now the tiles spawn around us!<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"763\" src=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-15-1024x763.png\" alt=\"\" class=\"wp-image-129\" style=\"aspect-ratio:1.3413213468801533;width:685px;height:auto\" srcset=\"https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-15-1024x763.png 1024w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-15-300x224.png 300w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-15-768x573.png 768w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-15-1536x1145.png 1536w, https:\/\/pushergame.site\/wp-content\/uploads\/2026\/05\/image-15-2048x1527.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Next I&#8217;ll be adding the ability for enemies to navigate around this new environment!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A big problem with the game up until now has been the fact that it takes entirely within an infinite dark void. To fix that, I want to add some procedurally generated terrain using Godot&#8217;s built in tilemap and noise map generation, which thankfully makes it easy. Adding Obstacles To make things easier for myself [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":129,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[10],"class_list":["post-123","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-devlog"],"_links":{"self":[{"href":"https:\/\/pushergame.site\/index.php?rest_route=\/wp\/v2\/posts\/123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pushergame.site\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pushergame.site\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pushergame.site\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pushergame.site\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=123"}],"version-history":[{"count":1,"href":"https:\/\/pushergame.site\/index.php?rest_route=\/wp\/v2\/posts\/123\/revisions"}],"predecessor-version":[{"id":130,"href":"https:\/\/pushergame.site\/index.php?rest_route=\/wp\/v2\/posts\/123\/revisions\/130"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pushergame.site\/index.php?rest_route=\/wp\/v2\/media\/129"}],"wp:attachment":[{"href":"https:\/\/pushergame.site\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pushergame.site\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pushergame.site\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}