The programming bug has bitten again. This is bad. I’ve got other writing I need to do. My Wolfenstein series ends in two days. If I don’t get the next series done then you folks won’t have anything to read on Thursdays. Still, this project got stuck in my head and after a week or so of not working on it I realized I wasn’t getting anything else done because I was spending all my mental energy just trying to not think about this. Now I’m hoping that if I put a few days into this I’ll be able to think about other things.
A lot of things brought this about. My time with Grand Theft Auto V has got me thinking about the problem of crafting urban gamespace and the terrifying expense and complexity of the problem. My friend Paul got me thinking about programming again. Out of the blue, a couple of people sent emails mentioning or asking about Pixel City, a project I did way back in 2009. Also, I’ve recently played Left 4 Dead again, and that game was one of the inspirations behind Pixel City.
If you never saw Pixel City, it was a programming project where I tried to fake a city using nothing but black cubes and lit windows. It turned out okay:
I want to do a next-generation version of this that can be explored on foot. (Or at least, from ground level. I doubt I’ll make actual walking mechanicsSpoiler: Wrong!..) I’m not trying to make a game or anythingThis is still true.. I just want to make a city using nothing but code.
I also want to mess around with some rendering tricks I’ve been thinking about. I like the idea of taking a full-color scene and crushing it down to EGA or even CGA color levels. Maybe experiment with dithering? I’m just curious what that sort of effect will look like in motion.
It’s important to set goals now so that when I fail to meet them later we know which parts of the project I’m supposed to be ashamed of. Here’s what I’m shooting for:
- A city of proper “videogame” size. It doesn’t need to be Manhattan, but it needs to be big enough to FEEL like Manhattan in terms of how players perceive scale within a gameworld.
- It needs to run in realtime. Decent framerate. I mean, I’m not aiming for “playable” or anything, but if my world is slow to the point of being annoying or uncomfortable to navigate then that’s not good enough.
- The procgen stuff needs to run in a reasonable time. Say 15 seconds or less. I want to hit a button and get a city without needing to wait for half an hour to see the result.
- The buildings in Pixel City were pretty good, but I’d like to revisit those ideas and maybe make some more interesting shapes.
- The world needs to have the framework for detail, even if I ultimately don’t put that detail in the city. Like, I’m not planning on learning Blender so I can make streetlights, trash cans, traffic lights, newsstands, vending machines, pay phones, parking meters, dumpsters, fire hydrants, benches, road signs, bus shelters, billboards, road signs, and bike racks. This is a programming project, not an art one. But maybe I’ll put some simple primitives in the world to show that I know where these kinds of objects WOULD go. We’ll see.
To keep things from getting too crazy and having the whole project spiral out of control, I want to constrain it to something I can do in a few days or a week. So let’s put some limits on the scope of the project:
- The ground will be flat. I’m not going to mess around with fitting a city to rolling terrain. That can complicate things tenfold.
- No cars, pedestrians, or other things that will require tons of programming / art.
- No building interiors.
- The city will be night only. I’m not going to make the buildings featureless black cubes like in the original Pixel City, but nighttime lighting conditions can cover a lot of corner-cutting.
- I’m not going to use procgen textures this time. That was fun last time around, but this time if I need a texture map I’ll spend five minutes bashing pixels together in an image editor rather than spend two hours trying to write code to accomplish the same thing.
I’m starting this project in C++, using my usual frameworkSpoiler: It won’t stay there. of SDL and OpenGL.
Note that the timeline is going to be a bit wonky. By convention I write these entries in present tense, but I’m actually writing this after several days of developmentI wrongly suspected that I could pour a couple of days into this and go back to doing other things and I wouldn’t have anything worth writing about.. I’m going to publish these entries once a week, but each entry represents roughly a day or so of development time. By the time we get to the fourth entry we’ll be well into May, but you’ll still be reading about what I was doing at the end of March. Also, while I’m writing this from the future, I’m not writing this from particularly far in the future. This entire project might hit a wall or come to nothing. I might lose interest. While I don’t know what will become of the project as I’m writing this now, I’ll probably know by the time you read this.
I realize this is horribly confusing. Sorry. For the sake of brevity and basic comprehension I’m going to continue to write in present tense, regardless of what’s going on in a temporal sense. Otherwise this whole series will come off sounding like Primer fanfiction.
Anyway. Enough disclaimers. Let’s get started.
So the most basic problem is “How do you form the city layout?” This is one of those annoying problems that’s obvious to do by hand but rather fiddly to do with code. A child can draw you a passable street layout, but then again a child can identify pictures of birds and it turns out that’s also a really hard problem for computers to solve.
Sure, you can do the brute-force thing of having streets form a strict grid. Every street can be locked to a world axis. But that’s boring. I want something that can gracefully handle T-junctions, diagonals, and so on.
So here’s what I come up with:
The program will draw lines to form a mangled grid. No curves to start with, but the roads will meet at odd angles and such. These lines are streets.
Then each street will put down marker points for where a sidewalk will go. These points will have a direction associated with them and will be oriented with “right side forward” scheme. Imagine you’re driving down the road on right side. To your right will be (invisible to the player) markers that point forward, just off the side of the road. On the other side of the street will be the same kind of markers pointing in the opposite direction.
Once that’s done, we’ll have all these crazy criss-crossing groups of points. It will be chaos. If we use these points to create sidewalks then we’d end up with sidewalks all over the roads. So the second step is to have each road “clean up” any sidewalk points that are encroaching on its space. Once that’s done, we should have something that looks like this:
You can see we already have city blocks isolated as little islands. Now I can just grab a point and go the way its arrow indicates, grabbing the next closest point in that direction. If I’m confused about which point to choose, I can favor right turns, which ought to let me enclose all of these city blocks. The only exception is those bits around the edge. If the program hits a dead end, it assumes it’s on the edge of the city and just throws away all the points.
This works. I can then use these points as an outline to create the polygons.
(If this seems like an odd way to go about this, you’re right. I’ll come back to this in a few days. I’ll talk more about this then.)
So now I have these enclosed shapes, which form city blocks. Now I just need to put buildings on them.
I already have these points scattered everywhere. They’re a perfect starting point for this job. Here’s what you do:
Grab a city block. Within that block, grab the first point that makes up its perimeter. This point also has a vector, indicating which way to go to walk down the sidewalk. (Walking on the right side of the street.) All I need to do is make a right-angle turn from where this thing is pointing, and I should be facing the big empty interior of the block. From there I can attempt to slap down a rectangle, aligned with this sidewalk. Let’s start with one that’s 10 meters x 10 meters. This rectangle will be the site for a building.
If the rectangle doesn’t overlap with the sidewalk, and it doesn’t overlap with any other building sites, then it’s good. I can nudge it a little larger and see if it still fits. I try making it wider. Then deeperThat is, the back of the building is father away from the sidewalk.. Then wider again. I try to make it as large as I can get away with, while also keeping it roughly square. I go around the block, fitting in rectangular sites like this to fill in each block as much as possible.
Once complete, I have lines for streets, rough outlines for city blocks, and scattered rectangles for building sites. Technically this is everything we need to build a big city like in the original Pixel City. (For the record, those red incomplete blocks on the edge of the city aren’t really relevant anymore. The program throws them away, but they’re still being drawn here for development purposes.)
Just to get a sense of how this is looking in terms of scale, I turn it into polygons so I can have a look around:
I realize this doesn’t look very impressive in terms of videogame graphics, but I’m pretty happy with what I’m seeing. Try not to think of these cuboids as literal buildings but instead as a representation of the volume for where a building would go. Also, you sort of have to imagine a street and sidewalk textures and such.
The point is that I like how this is working out spatially. Since I’m being a little more ambitious this time, it’s going to take us a bit longer to reach the point where we see something interesting. This is particularly true because I’m about to do something really absurd and silly. I’m about to start over with different tools.
Next week we’re doing this again, except in Unity.
 Spoiler: Wrong!.
 This is still true.
 Spoiler: It won’t stay there.
 I wrongly suspected that I could pour a couple of days into this and go back to doing other things and I wouldn’t have anything worth writing about.
 That is, the back of the building is father away from the sidewalk.
Grand Theft Auto Retrospective
This series began as a cheap little 2D overhead game and grew into the most profitable entertainment product ever made. I have a love / hate relationship with the series.
Starcraft: Bot Fight
Let's do some scripting to make the Starcraft AI fight itself, and see how smart it is. Or isn't.
Are Lootboxes Gambling?
Obviously they are. Right? Actually, is this another one of those sneaky hard-to-define things?
Resident Evil 4
Who is this imbecile and why is he wandering around Europe unsupervised?
Fixing Match 3
For one of the most popular casual games in existence, Match 3 is actually really broken. Until one developer fixed it.