7DRL Day 5: Cleaning Up The Streets


Though it took half a shot of Nyquil, I managed to sleep better last night. Bright-eyed enough, the first thing I did was grab a hearty roast beef sub for breakfast. Then I was ready to try and get the procedural generation in Leerie finalized so I could focus on the gameplay.

Since I was lapsing a bit there, I thought I would kill the idea of visiting the interiors of buildings. That's fine. A Leerie's job is to light the lamps along the road, not go into people's houses. Slashing features is the inevitable result of scope creep, and this fancy-pants procedural generation of mine was scope creep incarnate. I popped open Tiled and created another mockup of how I'd like it to look.

When I first began to create Leerie, I thought perhaps the city blocks would be ten tiles wide. Later, twelve tiles, so I could fit two lamps along each edge. As with this latest mockup, I'm thinking seven tiles for some appropriately snug-looking Victorian-era streets. From this mockup, I was able to figure out some simple rules of generation:

  • Buildings and road chunks are self-contained. Each building has a specific wall type: brick, stone, or higher-quality stone. I had a nice set of windows and doors in Kenney 1-Bit to support each kind.
  • Sidewalks are just one tile thick. Lamps are placed on the sidewalk when there is not a door or road leading in that direction.

Alright, first thing's first: I need to figure out why my map was such a mess yesterday.

It took me almost three increasingly-frustrating hours to figure out.

Of course, the reason why the map messed up was that the math was wrong. But complicating the solution was three kinds of coordinates.  

  1. The ones I call "global" coordinates are the position of a map tile as defined in the space of the entire game. That way, no two map tiles can occupy the same place.
  2. The "chunk" coordinates are that of the city block. Several map tiles make up each block.
  3. Finally, there are the "local" coordinates of each chunk. Those are because the blocks are capable of performing internal procedural generation.

The main stumbling block turned out to be my decision to use an endless map. As my frustration mounted, I considered dumping this feature. I refused. This stubborn problem was so simple my pride couldn't let it go! (Besides, I wanted to keep this code for myself later and have working boundless maps.)

The trouble is that the global coordinates can go right through the origin (0,0). Now I have a "fencepost" problem, something I am used to dealing with in arrays that go in the positive direction but not so much the other way. The same methods used to calculate positive chunks and local coordinates from the global one did not work once I went into the negatives.

The first thing corrected was that the local coordinates mirrored when calculated from a global coordinate under zero. That was because local coordinates were simply the remainder left after dividing the global coordinates by the chunk length. When I made it stopped reflecting, the local coordinates of each chunk were way off, and the procedural generation algorithm needed those to know what to place:


Deriving the local coordinates using the mirrored result and subtracting it from the chunk length didn't help because positive chunks included the origin, but the negative ones didn't. That would make one of the first negative chunks a tile row or column short. Just looking at it, I had no idea what was happening. The positive and negative chunks are neighbors, right next to each other! What difference does going negative make?! Why won't this work?! Was I going insane?!!

In the end, it came down to the fact that my arbitrary system of tile measurement had nothing to do with the laws of mathematics. I used different logic for negative coordinates to get the chunk coordinate, multiplied by chunk length, and removed it from the global coordinate to derive the local coordinate. As no expert mathematician, it took me a lot of trial and error to figure out. But, once I did, I could take a walk around all the chunks and verify with a debug method that all the tiles were staying put in the right places.

Finally, I could put this mathematical stumbling block behind me and start content generation towards the morning mockup!

I started cataloging the sprites I'd need. That took another hour or so. I guess I shouldn't have switched back to Kenney 1-Bit quite yet. Okay, now I'm ready for some serious content generation!

I created a support method to identify what local coordinates were on the border of the chunk. Then another one to quickly identify the ones in the middle of it or one of its borders. Okay, now I'm ready for some serious content generation!

I changed how my road chunks how to look for other adjacent chunks so they'd know where to place the sidewalks and lamps. They couldn't see each other, so I needed to create a support class to help them do that. Okay, that's still more of a support utility than any serious content generation!


I still haven't managed a proper cross-chunk communication architecture. That's why no sidewalks or lamps are getting spawned. But, hey, things look a lot more like city blocks than they were last night! That's a step in the right direction!

I'll need a more robust data structure. I switched from referencing city blocks as prefabs to instancing actual game objects for them. That means each city block can have discrete variables! For example, I added a little more logic, and these city block game objects are now keeping track of the tiles illuminated in them. They're even getting recycled when all of their tiles go dark and cease existing. Nice work!

Then the 12th pomodoro was over. It was now about 5:30 pm, and I was out of time for the day. If I learned anything from yesterday's exhaustion, it's that staying up late working on the project sabotages my efforts the next day. It's time to incubate until morning. I was hoping to show those sidewalks and lamps; I'm very close to that working. But this is as far as I'm getting today.

Two days of the 7DRL event remain.

Get Leerie

Leave a comment

Log in with itch.io to leave a comment.