{"id":146,"date":"2026-10-31T16:34:42","date_gmt":"2026-10-31T16:34:42","guid":{"rendered":"https:\/\/petersen-projects.com\/?p=146"},"modified":"2026-11-03T16:38:01","modified_gmt":"2026-11-03T16:38:01","slug":"saltwake-six-nights-over-pre-rendered-rooms","status":"publish","type":"post","link":"https:\/\/petersen-projects.com\/?p=146","title":{"rendered":"Saltwake, a big project that&#8217;s coming up"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Saltwake is the game I&#8217;m working on right now and for a good amount of time already, and it&#8217;ll be on Steam in January (hopefully). It takes place in Ostrand, a harbour city, during the last six nights of 1999. At a museum preview sixty guests light up from the inside and turn into salt. Ines Varga, who has been with the harbour police for only ten weeks, was at the door that night, and she&#8217;s the only one who doesn&#8217;t burn.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you played the cinematic action RPGs from the late 90s you&#8217;ll know the look right away: fixed cameras over pre-rendered rooms, everything at 320 by 240, and fights that start right where you&#8217;re standing. While you move around a gauge fills up, and when it&#8217;s full you can stop time. A dome opens around Ines showing what she can reach, then you pick a target and shoot. She moves freely with the stick, because parasite eve, a game which this is heavily inspired from, moves like that (also it&#8217;s easier to move during battles).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_quay_new.jpg\" alt=\"The Marine Hall quay on the first night\" class=\"wp-image-149\" srcset=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_quay_new.jpg 1920w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_quay_new-300x169.jpg 300w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_quay_new-1024x576.jpg 1024w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_quay_new-768x432.jpg 768w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_quay_new-1536x864.jpg 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><figcaption class=\"wp-element-caption\">The Marine Hall quay on the first night<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_gate_dome_new.jpg\" alt=\"Time stopped in a fight at the fish market gate, with the dome open and a frost crab targeted\" class=\"wp-image-150\" srcset=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_gate_dome_new.jpg 1920w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_gate_dome_new-300x169.jpg 300w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_gate_dome_new-1024x576.jpg 1024w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_gate_dome_new-768x432.jpg 768w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_gate_dome_new-1536x864.jpg 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><figcaption class=\"wp-element-caption\">Time stopped in a fight at the fish market gate, with the dome open and a frost crab targeted<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">How the rooms work<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Every room is a still picture rendered in Blender, and Godot only draws the characters on top of it. I don&#8217;t build the rooms by hand though. Each room is a data file with boxes, props, lights and cameras, and a script builds the scene in Blender and renders it at 640 by 480, then it gets scaled down to 320 by 240. The game has 98 rooms in the city so far, and 79 more in the sealed levels.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The hard part is that a picture is flat, so when Ines walks behind a table the picture doesn&#8217;t know about it. To fix this I load the same meshes from the render into Godot as an invisible matte. It writes depth but no colour, so the table in the picture covers her exactly where the real table would.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This only works if the matte and the picture line up perfectly, so every camera has a check for it. The game draws each piece of the room in its own flat colour, Blender renders the same flat view from the same camera, and then I compare the two pixel by pixel. This is how it looks for the shipyard deck and the cathedral nave:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1932\" height=\"720\" src=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_hy_deck.png\" alt=\"The shipyard deck render next to its flat colour alignment view\" class=\"wp-image-140\" srcset=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_hy_deck.png 1932w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_hy_deck-300x112.png 300w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_hy_deck-1024x382.png 1024w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_hy_deck-768x286.png 768w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_hy_deck-1536x572.png 1536w\" sizes=\"auto, (max-width: 1932px) 100vw, 1932px\" \/><figcaption class=\"wp-element-caption\">The render on the left, and the same camera with every piece in its own flat colour on the right<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1932\" height=\"720\" src=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_ca_nave.png\" alt=\"The cathedral nave render next to its flat colour alignment view\" class=\"wp-image-141\" srcset=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_ca_nave.png 1932w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_ca_nave-300x112.png 300w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_ca_nave-1024x382.png 1024w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_ca_nave-768x286.png 768w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_align_ca_nave-1536x572.png 1536w\" sizes=\"auto, (max-width: 1932px) 100vw, 1932px\" \/><figcaption class=\"wp-element-caption\">The same for the nave of the old town cathedral<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">That check found a few things I&#8217;d never see by eye. The museum tanks were sitting exactly on their sills and left a one pixel gap along each one, so now anything sitting on top of something else floats 4 mm above it. Glass shows in the picture but it&#8217;s left out of the matte, otherwise Ines would disappear behind a display case instead of showing through it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Some cameras also turn to follow her. For those I render one wider picture aimed at the middle of the turn, and the game works out where each part of the matte goes in it, so the room stays lined up with the picture no matter how far the camera turns.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_06_n3_saint_brigids_ward.jpg\" alt=\"A ward in the hospital on the third night\" class=\"wp-image-138\" srcset=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_06_n3_saint_brigids_ward.jpg 1920w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_06_n3_saint_brigids_ward-300x169.jpg 300w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_06_n3_saint_brigids_ward-1024x576.jpg 1024w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_06_n3_saint_brigids_ward-768x432.jpg 768w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_06_n3_saint_brigids_ward-1536x864.jpg 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><figcaption class=\"wp-element-caption\">A ward in the hospital on the third night<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Collision<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Collision comes from the same data file. Each piece says if it blocks Ines or not, and the floor she can walk on is a set of rectangles, so the walls, the props and the floor always match the picture.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1400\" height=\"746\" src=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_collision_hy_deck.png\" alt=\"Top down collision map of the shipyard deck\" class=\"wp-image-142\" srcset=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_collision_hy_deck.png 1400w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_collision_hy_deck-300x160.png 300w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_collision_hy_deck-1024x546.png 1024w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_collision_hy_deck-768x409.png 768w\" sizes=\"auto, (max-width: 1400px) 100vw, 1400px\" \/><figcaption class=\"wp-element-caption\">The shipyard deck from above: the floor she can walk on in green, the pieces that block her in grey, the two cameras in yellow and an invisible archway door in red<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Of course it still went wrong sometimes. While playing I walked around the end of a railing next to a drained tank and fell right in, because the railing ended a metre before the wall. After that I added an audit that goes through every room, pushes Ines out from every edge of the floor and checks that something stops her. The first run found 25 rooms where she could walk through an open archway and right off the edge of the world (you leave through archways with the interact button, same as doors). Now each of those archways has an invisible door that never shows in the render.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The audit runs with the rest of the tests, about six thousand pushes, and I made sure it failed on the tank and the archways first, so when it passes I know it really means something.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The models<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before a model goes into the game I look at a turntable of it and a sheet with its animations, and that&#8217;s where most problems show up. The guests at the preview, for example, were standing around with their arms sticking out, because they were using Ines&#8217;s idle animation on bodies with the arms modelled further out than hers.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"240\" src=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_ines_turntable.png\" alt=\"Ines Varga model turntable\" class=\"wp-image-144\" srcset=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_ines_turntable.png 1024w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_ines_turntable-300x70.png 300w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_ines_turntable-768x180.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Ines from four sides<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"2048\" height=\"2240\" src=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_ines_weapons.jpg\" alt=\"Sheet of Ines with each kind of weapon\" class=\"wp-image-145\" srcset=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_ines_weapons.jpg 2048w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_ines_weapons-274x300.jpg 274w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_ines_weapons-936x1024.jpg 936w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_ines_weapons-768x840.jpg 768w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_ines_weapons-1404x1536.jpg 1404w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_ines_weapons-1872x2048.jpg 1872w\" sizes=\"auto, (max-width: 2048px) 100vw, 2048px\" \/><figcaption class=\"wp-element-caption\">Ines holding and aiming each kind of weapon (still needs polishing)<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The creatures get rigged by a script that weights each vertex by how close it is to each bone. In the game the bones move depending on what they&#8217;re part of, so spines and tails ripple, legs step in pairs, wings beat and jaws open before an attack. The bigger creatures have parts you can shoot off, and when a part is gone, the attack that used it is gone too.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"990\" src=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_creatures.png\" alt=\"Sheets of four creatures from four sides\" class=\"wp-image-143\" srcset=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_creatures.png 1024w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_creatures-300x290.png 300w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_creatures-768x743.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">A few of the creatures: the swan, a dock crab, the tide crown and the grey mother<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Props render at full detail, around 50,000 faces each, but the matte uses a lighter copy with 8,000 faces, because it only needs the right outline.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_yard_new.jpg\" alt=\"A yard in the old town on the fifth night, with the snow coming down\" class=\"wp-image-148\" srcset=\"https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_yard_new.jpg 1920w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_yard_new-300x169.jpg 300w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_yard_new-1024x576.jpg 1024w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_yard_new-768x432.jpg 768w, https:\/\/petersen-projects.com\/wp-content\/uploads\/2026\/10\/saltwake_yard_new-1536x864.jpg 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><figcaption class=\"wp-element-caption\">A yard in the old town on the fifth night, with the snow coming down<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">When<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Saltwake comes to Steam in January 2027 for Windows, fully voiced in English and with Brazilian Portuguese subtitles. You can wishlist it here: <a href=\"https:\/\/store.steampowered.com\/app\/5512160\/Saltwake\/\">https:\/\/store.steampowered.com\/app\/5512160\/Saltwake\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The game I&#8217;m working on now, a cinematic action RPG over pre-rendered rooms, and how those rooms hide the heroine behind a flat picture and keep her on the floor.<\/p>\n","protected":false},"author":1,"featured_media":135,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-146","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/petersen-projects.com\/index.php?rest_route=\/wp\/v2\/posts\/146","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/petersen-projects.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/petersen-projects.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/petersen-projects.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/petersen-projects.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=146"}],"version-history":[{"count":13,"href":"https:\/\/petersen-projects.com\/index.php?rest_route=\/wp\/v2\/posts\/146\/revisions"}],"predecessor-version":[{"id":188,"href":"https:\/\/petersen-projects.com\/index.php?rest_route=\/wp\/v2\/posts\/146\/revisions\/188"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/petersen-projects.com\/index.php?rest_route=\/wp\/v2\/media\/135"}],"wp:attachment":[{"href":"https:\/\/petersen-projects.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=146"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/petersen-projects.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=146"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/petersen-projects.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=146"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}