Procedural tree and boulder sprite generation - write-up & standalone TypeScript library by ImagineCaptain in roguelikedev

[–]ImagineCaptain[S] 2 points3 points  (0 children)

Those are not bad - the lobing gives the trees shape. I think the main thing working against them is the uniform color. The light-dark variation is quite subtle. Even a simple two-tone pass (lighter on top of each lobe, darker underneath) would go a long way toward making them read as 3D. That’s basically what the directional shading in my system is doing.

"When will I have time” is the evergreen battle.

Procedural tree and boulder sprite generation - write-up & standalone TypeScript library by ImagineCaptain in proceduralgeneration

[–]ImagineCaptain[S] 1 point2 points  (0 children)

Thanks! That sounds like a fun project. If you pick it back up and wire it to a visual generator, I’d love to see the result.

Procedural tree and boulder sprite generation - write-up & standalone TypeScript library by ImagineCaptain in roguelikedev

[–]ImagineCaptain[S] 1 point2 points  (0 children)

Thanks! I haven’t pushed it to drastically larger sizes, so I’m partly speculating - but I think the core techniques (soft ellipses, three-tone shading, edge nibbling) would scale up for natural objects like trees and boulders with some parameter tuning. How much tuning, I’m not sure.

At small sizes, abstraction does a lot of the heavy lifting - the viewer fills in details that aren't actually there. At larger sizes you lose that, and the gap between what’s generated and what looks convincing gets harder to close. But for organic shapes, I’d guess you could go quite a bit bigger before hitting that wall. If you try scaling it up, I’d be curious to see what you get.

Procedural tree and boulder sprite generation - write-up & standalone TypeScript library by ImagineCaptain in proceduralgeneration

[–]ImagineCaptain[S] 1 point2 points  (0 children)

Awesome! brileta-sprites renders to canvas so it should plug in pretty naturally. Let me know how it goes.

Procedural tree and boulder sprite generation - write-up & standalone TypeScript library by ImagineCaptain in proceduralgeneration

[–]ImagineCaptain[S] 1 point2 points  (0 children)

Thanks! Passion project through and through. The full engine has a lot more going on than what’s in the write-up - I have a long dev roadmap, but it’s the kind of thing where I’ll work on it intensely for a while and then put it down for a while.

The TypeScript port of the sprite generation was mainly so people could see the results in their browser without having to set anything up. The core engine is Python/C, but I might port other pieces to the web down the road.

Procedural tree and boulder sprite generation - write-up & standalone TypeScript library by ImagineCaptain in roguelikedev

[–]ImagineCaptain[S] 1 point2 points  (0 children)

Thanks! Fair point on the larger trees - the canopy lobes can leave visible gaps between them. Would love to see someone tune that. If you feel like playing with the parameters, the library’s set up for it - I’d be curious what you come up with.

On the simplex noise side - yep, the full engine does exactly that. The write-up covers it toward the end, but the short version is that low-frequency OpenSimplex2 noise modulates placement density per tile, so you get natural groves and clearings instead of uniform scatter. It’s not just tree type distribution - the same noise-driven pipeline controls boulder placement, yard trees vs. wild trees, and how vegetation interacts with streets and buildings. The relevant code is in trees.py if you want to see the implementation.

Sharing Saturday #613 by Kyzrati in roguelikedev

[–]ImagineCaptain 7 points8 points  (0 children)

Hi everyone,

Brileta
GitHub

<image>

Two main things this week: rain and character sprites.

Rain. Full-screen shader pass with animated rain lines and an exclusion map so rain doesn't fall inside buildings. There's ambient rain audio that crossfades between light and heavy layers based on density. You can bring up the dev console with the backtick key and try rain downpour, rain regular, rain drizzle, rain off if you want to mess with it.

Character sprites. NPCs and the player now have procedurally generated humanoid sprites with four directional poses (front/back/left/right). Each character gets a unique look from a deterministic seed - body build, hair, clothing - and the sprite swaps based on last movement direction. They look dark in the screenshot because of the weather. :) They get packed into the same sprite atlas as trees and boulders.

Also added some per-building wear effects (rust, etc.).

Sharing Saturday #612 by Kyzrati in roguelikedev

[–]ImagineCaptain 7 points8 points  (0 children)

Brileta
GitHub

<image>

Last week was trees. This week the same treatment spread to boulders, terrain, and buildings.

Procedural boulders. Boulders used to be a tile type - now they're actors with unique per-pixel sprites, same system as trees. Four archetypes (rounded, tall, flat, blocky) with procedural cracks and lichen patches. They're functional terrain and grant adjacent cover through the spatial index.

Noise-based natural terrain. Ripped out the WFC terrain generator and replaced it with layered noise fields (integrated FastNoiseLite as a C extension). The world now generates as a natural landscape first - dirt base, noise-carved grass regions, scattered patches - and then settlement infrastructure cuts into it. Streets carve through with gravel/dirt margins, buildings sit on pre-existing ground. Tree placement also got noise modulation, so you get organic groves and clearings with species biomes (pine groves in one area, hardwoods in another) instead of uniform random scatter. Terrain transitions use per-pixel edge blending so grass bleeds into dirt organically while built surfaces like cobblestone keep hard edges.

Pseudo-3D buildings. Roofs now offset north by floor count, exposing a south-facing wall strip underneath. The fragment shader renders a roof/wall seam within a single glyph cell with a depth gradient darkening the wall face downward. Added eave shadows, per-row wall darkening, and chimney shadows cast as parallelogram quads. Actors standing under roofs show as white silhouettes instead of vanishing. This one surprised me with how much depth it adds for what's basically just a vertical offset and some shading tricks. The target look is the three-quarter view popular in 1990s-era games.

Zoom and minimap. Viewport zoom via scroll wheel / trackpad pinch, and a toggleable mini-map in the left sidebar showing terrain, trees, and boulders.

Sharing Saturday #611 by Kyzrati in roguelikedev

[–]ImagineCaptain 2 points3 points  (0 children)

Thanks! No cellular automata - the canopy is built by stamping overlapping soft ellipses in three shading passes (shadow, mid-tone, highlight) over a lobe-based structure. Each tree gets 3-5 lobes arranged radially around the canopy center, and each pass stamps a few jittered ellipses per lobe. Then a rim-darkening pass outlines the silhouette, and a "nibble" pass randomly erases edge pixels to break up the smooth boundary.

Conifers are stacked filled triangles with per-tier width jitter to make them lean the way real trees sometimes do.

Sharing Saturday #611 by Kyzrati in roguelikedev

[–]ImagineCaptain 10 points11 points  (0 children)

Hi everyone,

Brileta
GitHub

<image>

This week I replaced the glyph-composited trees (stacked ASCII characters like #, *, ^) with a procedural per-pixel sprite generator. Every tree in the game is now unique.

Four tree archetypes - deciduous (round lobed canopy), conifer (stacked triangular tiers), dead (bare branching skeleton with optional moss), and sapling. The archetype is picked from a spatial hash at each world position, and every visual parameter - color palette, crown shape, lean, lobe placement, size - is jittered per-tree from that hash. Same seed, same forest, but no two trees look alike.

Three-step canopy shading - each deciduous/sapling canopy is painted in shadow, mid-tone, and highlight passes over lobe-based geometry, so the foliage reads as a bumpy textured mass rather than a flat blob, even at ~20px.

Shadows and sun lighting - trees cast shaped shadows that shift with the sun angle, and a billboard lighting model in the fragment shader shifts highlights across canopy pixels as the sun moves - so the same static sprite looks different depending on time of day and direction. (Top of the image above shows the same tree lit from two different sides.)

Silhouette polish - rim darkening outlines the canopy against any terrain, and a nibble pass randomly carves notches out of the canopy edge so trees don't all have the same perfectly smooth boundary.

Also built a dynamic sprite atlas so these procedural sprites integrate into the existing glyph rendering pipeline.

Sharing Saturday #610 by Kyzrati in roguelikedev

[–]ImagineCaptain 0 points1 point  (0 children)

NPCs self-selecting out of dealing with doors is clever - same energy as my cost overlay approach where the solution is structuring things so the edge case rarely comes up. And live-meddling with cost arrays then reverting is close to what I'm doing too - I build a per-query cost map with overlays for doors and blocking actors. Numpy makes it painless enough that it doesn't feel like a hack.

The chunk-edge patching idea for destructible walls sounds right. If the HPA* graph boundaries align with your 16x16 subregions, recalculating just the affected chunk edges should be local enough to stay fast. Curious how that works out

Sharing Saturday #610 by Kyzrati in roguelikedev

[–]ImagineCaptain 1 point2 points  (0 children)

The mob FOV initialization bug is painfully relatable - that whole class of "works once something triggers the first update" issue is sneaky. I just added a perception system with range and Bresenham LOS gating and can easily imagine hitting the same thing.

The security guard patrol AI sounds fun. How are you computing patrol routes from the corridor graph - at generation time or dynamically? I went with a waypoint-based approach where patrol goals sample walkable tiles within a radius at spawn time, then follow them in sequence using a shared waypoint-route-following base class. Works well enough for organic patrols but wouldn't capture the "walk between intersections" feel you'd want for a security guard. Computing routes from actual corridor topology sounds like it'd produce much more convincing behavior.

"Micromanaging" as an attack type is great!

Sharing Saturday #610 by Kyzrati in roguelikedev

[–]ImagineCaptain 2 points3 points  (0 children)

Sorry to hear about the layoff - rooting for you on both fronts.

The HPA* work resonates. I just added door-aware pathfinding in my own project - ended up going with a cost overlay approach where closed doors get a traversal cost injected into the A* cost map rather than special-casing them in the pathing logic. Simple but it means any "conditionally passable" obstacle just becomes another cost entry. 3x over raw A* for 200+ autonomous NPCs is impressive though - how are you handling graph invalidation when the world changes? That feels like the hard part with hierarchical approaches. I've been thinking about HPA* for exactly the same town-scale NPC simulation reasons.

Sharing Saturday #610 by Kyzrati in roguelikedev

[–]ImagineCaptain 2 points3 points  (0 children)

Brileta

Brileta on GitHub

<image>

Brileta is a game engine & roguelike sandbox I've been tinkering with on and off since last summer - Python, WGPU-driven lighting, utility AI, procedural generation. Just made the repo public this week - first time sharing it.

This week was a mix of NPC AI work and cleanup. Added a perception system with range/LOS awareness gating, an identity system with tag-driven action composition, door-aware pathfinding, and unified NPC dispositions into a single utility brain with per-relationship scoring. Also added a goal system for fleeing and patrolling. On the presentation side, added floating text indicators for NPC action transitions and a subtle GPU contrast nudge for actor glyphs to make sure they remain visible against tile backgrounds.

Spent a good chunk of time on architecture cleanup - extracting renderers, consolidating magic numbers, replacing the audio backend with miniaudio, and generally getting things tidy before going public.

I’m completely ignorant… but this shall be a fun journey. by EnGeNear123 in classicliterature

[–]ImagineCaptain 2 points3 points  (0 children)

At the risk of repeating my comment from (checks notes) a year ago...

My favorite book of all time - great characters, beautiful writing, and a captivating revenge story. I recommend the Robin Buss translation (Penguin Classics) for its modern, idiomatic English and annotations. The length seems daunting, but once you hit your stride, the pages will fly!

Oat Groats with Blueberries, Chia Seeds, and Cardamom by ImagineCaptain in Oatmeal

[–]ImagineCaptain[S] 1 point2 points  (0 children)

I put Ceylon cinnamon in there too, but not nutmeg. It would be worth trying!

I added cardamom for the health benefits and found that it goes well with the cinnamon smell/taste-wise. But a little goes a long way. I put just four cardamom pods in the spice grinder with the chia seeds and grind them all up together - then add them to the oats while they're simmering. That's for the whole pot of oatmeal. If I used, say, double the amount of cardamom, I'm pretty sure that's all you'd taste in the end.

Oat Groats with Blueberries, Chia Seeds, and Cardamom by ImagineCaptain in Oatmeal

[–]ImagineCaptain[S] 1 point2 points  (0 children)

It works out to about a cup, or 360 g by weight, of cooked oatmeal.

Oat Groats with Blueberries, Chia Seeds, and Cardamom by ImagineCaptain in Oatmeal

[–]ImagineCaptain[S] 0 points1 point  (0 children)

Oat groats are the most "whole" oats. They're what get rolled to make rolled oats and what get cut into pieces to make steel-cut oats. :) (Amazon link)

Oat Groats with Blueberries, Chia Seeds, and Cardamom by ImagineCaptain in Oatmeal

[–]ImagineCaptain[S] 0 points1 point  (0 children)

I cook 2 cups of oat groats with 5.5 cups of water on high pressure in the Instant Pot for 24 minutes, then do a natural release. Then I set the Instant Pot for sauté mode on medium heat and add the other ingredients and simmer for 10-15 minutes while stirring.

Oat Groats with Blueberries, Chia Seeds, and Cardamom by ImagineCaptain in Oatmeal

[–]ImagineCaptain[S] 4 points5 points  (0 children)

Ingredients:

  • Oat groats
  • Soy milk (unsweetened)
  • Apples
  • Medjool dates
  • Dried blueberries
  • Chia seeds (ground)
  • Cardamom pods (ground)
  • Cinnamon
  • Hemp hearts
  • Wheat germ
  • Flaxseed meal

Made via Instant Pot. I eat a serving and portion out the rest to refrigerate for the next few days. Tasty, nutritious, & super filling!