If you ever wondered why a site called “Twenty Sided” talks so much about videogames, now you can find out.
Stolen Pixels #84: Left 4 Dumb: Part 6
Procedural City, Part 7: The Street-Level Trap
Streetlights
Now it’s time to round out the scene with lights. But in order to place the streetlights, I need to know where the streets are. In an earlier step I reserved street space, but now I’ll take that space and divide it up into sidewalks and specific lanes.
That done, I can have it scan over the world and look for places that need streetlights.
Bloom Lighting
I add another render pass for doing bloom lighting. The effect is of course striking, but unrealistic.
I don’t want to embrace or discard the feature, so I make it so the effect can be toggled off and on. Naturally enabling it causes a performance hit, but I can’t really appraise how bad it is until I get some of the more egregious slowdowns fixed and the overall performance optimized.
Cars
Now for cars. Since I have the lanes defined, I can just drop cars randomly onto lanes and let them figure out which way to go. They then select a speed and drive in a straight line until they get to the edge of the map, and then they randomly appear in a new location and repeat the process. The program draws a simple 2d panel at a car’s location. If the car is heading away, it draws it red, otherwise, white. This would look crazy if you were looking straight down on the scene, but up here in the News 5 chopper it looks okay.
I thought it might be cool to have the cars engage in more elaborate behavior. So I wrote a bunch of code to have them switch lanes if they find themselves behind a dawdler, and randomly make turns when they come to an intersection. I spent over an hour fussing with a couple of intersections and tuning the car behavior to make lane changes and cornering look natural. It was still a little stiff, but I was confident that with a bit more tuning I could make it work.
Then I pulled back to the city-wide view and found that all that work was almost completely unnoticeable. It was actually hard to spot a car doing something interesting. On the rare occasions where I was looking when a car made a turn, the robotic movement actually hurt the verisimilitude of the scene instead of helping. Both turns and lane changes actions are very complex. Turns are not linear. Cars decelerate before the turn, increase the rate of turn as they go, and begin to accelerate again before the turn is completed. This is aside from the fact that steering with the front wheels produces some fairly noticeable differences between the movement of headlights and taillights. Worse, the tiny bit of AI I’d written was slowing the program down. It was small and simple, but multiplied by hundreds and hundreds of cars it was causing a measurable performance hit.
So… I wasted a bunch of time writing code that slowed down the program and looked terrible when you noticed it at all.
Click & drag over text. Press delete.
This is a classic case of oversimulation. The programmer (me, in this case) sits down and thinks “oooh! I know how this system works, so I’ll write a simulation of it!” It’s a deadly trap, because once you start simulating one thing (cars changing lanes) then you suddenly need to simulate other things (making visually believable lane-changing movements for automobiles) which requires still other things (turning behavior of a car) and pretty soon you’re coding some sort of time-devouring boondoggle when all you wanted was to write a few simple rules about going around slow people.
John Carmack talked about this at Quakecon in 2004. (That article is long. The relevant passage is about halfway down.) During development of Doom 3, they had a programmer write a complex audio / acoustics engine that would try to propagate sounds realistically. It was supposed to make big rooms echo, dampen sounds in other areas, and so on. In the end, the result was worse than the simplistic system it was supposed to replace. It was actually easier to have artists manually specify how things ought to sound and how far particular sounds could travel than to have the game try to intuit it. They scrapped the audio simulation and replaced it with more conventional videogame sound behavior. Luckily for me, my losses were only a bit over an hour. Theirs was months. Then again, I might have incurred the worse losses as a percentage of total budget. (An hour and a half is about 5% of my budget, assuming I stick to it. (Although I’ve lost track of how many hours I’ve sunk into it. Weekends do that, particularly since I had a lot of Left 4 Dead mixed in with the coding hours. Still I’m going to take a wild guess and say I have perhaps three or four hours left before I hit my 30 hour goal. Maybe.))
Street-level detail
I pull back and assess the view now that all of the key details are in place, and I’m not happy with the result. I’d looked at a lot of reference pictures where the streets were pure black, and only streetlights and car lights were visible. But the same effect is not working here in my city. I look down in the blank areas between the buildings and I expect to see a street. The black void looks unnatural.
Looking at the reference photographs again, I realize that the “black street” effect is something you only get at extreme distances. Looking down from above, the streets are always brightly lit. As a test, I make a cheap texture map to slip under the city. It’s a single huge texture that just shows all of the streets. It’s of such low detail that a lane of traffic is just one pixel wide.
The street is awful, cheap, lo-res, and doesn’t even fit in with the buildings. And yet it still looks better than the pitch black. My original concept for the streets is unacceptable. I need to somehow depict the streets in this world.
| Cheap, 1-pixel lanes, no lines on the road, no surface detail, nothing. But it still looks better than black. |
But this is almost dragging us back to the problems that come with oversimulation. I wanted to just hint at the streets. The last thing I wanted was to draw the eye down there with a bunch of detail. Making streets that are illuminated is fundamentally different from my intent, which was to leave things in shadow and get by using smoke & mirrors. If I make a well-lit street, then this will draw the attention of the viewer. My light-source cars will no longer look right, because it won’t be black cars on a black background, it will be invisible cars on a light background. If I add little cars, then the user will probably notice that the streets are barren – no traffic lights, lines, or crosswalks. If I add all of that, then my high-detail streets will look out of place next to the silhouette buildings. If I add a bunch of storefront-type detail, then those blank areas around buildings will stand out more. What will I do then? Add little parks and parking lots?
This sounds like a lot of fun, actually, but adding all of that detail would obliterate my time budget. In fact, each of those elements could turn into a week-long project in itself, all to simulate something I did not want the user to see in the first place!
I need to think about this.
I think the next step should be to begin optimizing performance. I’m down to 30 frames a second (varies) at this point, and so this needs to be done. (Remember my budget is ~100 FPS.) Once I have that finished, I’ll know how many CPU / GPU cycles I have to waste on street details. And maybe I’ll get some good ideas in the meantime.
Left 4 Dead: Survival Mode
Last night I discovered that Valve has released the long-awaited content for L4D, the new “Survival” gameplay mode. The premise is simple. The four of you begin at a lighthouse. For reasons never explained, your characters activate the light and fog horn. The light and sound draw zombies. All of them. Forever. Your goal, as you’ve probably guessed by now, is to survive as long as you can in the face of insurmountable odds and a highly unreliable building. The infected come, and keep coming, and keep coming, and just when you think it’s getting a little ridiculous, it will send a handful of special infected at your group. Your understanding of the game is incomplete until you’ve fought a wave of infected and two tanks. (Tanks are big, musclebound infected that absorb and dish out ridiculous levels of damage. In the other game modes, the group usually fights a single tank all by itself, with plenty of warning beforehand. And it’s still a huge challenge. But to fight one while the common infected keep coming is madness. And two at once is simply griefing on the part of the AI director.) Or perhaps you’ve always wanted to fight common infected, three smokers, two hunters, and a tank all at once? In survival mode this demented and masochistic dream of your can become a reality. (Weirdo.)
Our first attempt lasted just over two and a half minutes.
Is it good? Well, it consumed my evening, destroying precious blocks of time I desperately needed to spend making articles, comics, and posts about procedural cities. So I would have to say that the new mode is not good. It’s obnoxiously fun and infuriatingly addictive. Although, it slightly redeems itself by being a little buggy and eventually forcing me to quit playing for the night.
One amusing but benign bug – the talking cinderblock:
![]() |
I don’t know what the deal was, but when we entered the game there was this chat icon over a cinderblock in front of the lighthouse. The icon suggests it is voice chatting to us, but we never did hear what wisdom the cinderblock was trying to impart. Alas.
Last weekend I purchased another server for the Twenty Sided group on Steam. I made it an eight person server, thinking we could get a game of Versus going at some point. I upgraded the server to play survival mode last night, but discovered that the updated server no longer honors the group designation. This means it was no longer a private server for our little group, but instead was a general public server, free to all the clawing unwashed masses, the beggars, and the riff-raff. I have played with dozens of you over the last few weeks, and I would say it was fun without qualification. But playing a game which requires communication and teamwork with anonymous hyperactive jerks is more or less impossible. I could find no way of keeping them out short of booting them, only to have them replaced by other people who do not speak or listen, which isn’t really so much a solution as a form of catharsis.
The other game-ending bug was the loss of survival mode itself. In attempting to correct the public-access issue, I rebooted the server and found that survival mode was no longer available. Forcing the server to use the Lighthouse survival level caused the game to start in some sort of inexplicable mode halfway between campaign and survival:
![]() |
Note that in this screenshot, the playable game area is on the other side of the fence. The game was essentially spawning us backstage, walled off from the content. We could only stare longingly through the fence and the fun that sat just beyond our reach.
There were also some screwy clipping issues and the like, although I didn’t get screenshots of those at the time.
But when the game was good, it was very good. I’m particularly proud of our initial efforts. Early in the evening before the server went to hell I had a great time. Our first few rounds ended in humiliating defeat, but as we played we grew individually and as a team. Each round we saw our performance improve, demolishing our earlier impressions on what we could accomplish. The speed of the game allows for lots of experimentation, and the chaotic pressure has a bonding effect on the team. Our final round:
![]() |
I really hope it takes them a nice long time to fix these bugs, or else this site is finished.
Stolen Pixels #83: Left 4 Dumb: Part 5
So I made another comic that has Left 4 Dead stuff in it and I was kind of hoping you would read it.
Also, The Escapist has been nominated for a Webby award. As you well know, online media companies make their money almost exclusively from winning online awards. (In fact, this is the real reason print media is struggling so badly. The Star Tribune wouldn’t be in so much trouble if they were eligible for some web awards.) I think it would be great if The Escapist won. </hint hint>.
Procedural City, Part 6: Sky
Gradient Sky
I need to make a sky for my city. So… I guess I better add one.
![]() |
| This is not religious iconography. |
On the computer, it’s possible to draw this box, and then render everything else in the world on top of it, which creates the illusion that the mountains are a huge distance (infinite, actually) away. Now, my skybox isn’t going to be box shaped. Since I’m focusing on making a night time scene, I don’t need the top or bottom. So I’ll make some textures and place them on in side of a shortened tube instead of a cube. So, the viewer of my program is unwittingly wearing a lampshade on their head. Ha ha.
I make a smear of colors and put it on the lampshade.
It’s amazing how you can blur just about any two colors across the view and see it as a horizon. I start with a random warm color, which then fades to a blue, then fades to a very dark blue, and then to black. The specific colors are randomly chosen. I don’t know if it’s supposed to be a sunset or simply city lights bouncing off the atmosphere. It’s a little bright and colorful to be ambient light. But it goes all the way around the horizon, which is something sunsets don’t usually do.
I add some stars.
That’s good, but I’m going to need clouds if I really want to make this lampshade look sky-esque. For some reason, I thought I’d try and generate some puffy clouds fractally. It became apparent very early on that this was a foolhardy approach, but I messed with it a bit longer than I should simply because it was generating such interesting images.
One of the many fractal non-clouds:
Eventually I stop playing around and get back to work. This is very far from my mission parameters. My goal is to sell the scene using simple tricks, and trying to create believable clouds using fractals is the opposite of that. I save the fractal code elsewhere in case I want to play with it again, and devise a simple trick:
I draw my fading circle texture onto the canvas, only I color the circle black. Then I squash it vertically and draw it again, only slightly lighter. The further down the canvas I go, the more I compress my circles vertically. So the circles near the top will be nearly round, but those at the bottom will be nearly a horizontal line. The result:
And now I slap that texture over top of the gradient and the stars:
This is the way to go. I spend some time fussing with the color parameters: Cloud size, opacity, density, the contrast of the lit underside of the cloud, and the degree to which they flatten out as they approach the bottom of the texture. (The horizon, from the user’s point of view.) Unlike the buildings, these parameters aren’t something I can just plug into the random number spewer and create infinite content. Most of these numbers are tradeoffs, and making it look better one way will diminish it in another. Eventually I decide to stop messing with it:
We’re getting close now.
Procedural City, Part 5: Fixes
The time spent contemplating the program did not go to waste. I was able to correct several things that had been bothering me.
Building Textures
I mentioned before that I had two approaches to making the building textures: One would light windows completely scattershot. Each window had a fixed chance to be lit or unlit. The other approach was to light them in horizontal groups, so that the lit windows would always be grouped together.
Stepping back and looking at what I’m trying to simulate, I can see the scattershot doesn’t make much sense, and doesn’t seem to match what we see in cityscapes. Worse, all buildings had the same percentage of lit windows, which made the view even more monotonous.
All buildings should exhibit some level of lit-window grouping. The only difference from one building to the next is in how big each office / apartment is. Also, not all buildings have the same ratio of lit windows to dim ones.
So I replaced the old window-generating code with a new one. It randomly decides at the outset how big the interior spaces are, and what percent of the windows should be lit.
Now different buildings have different window shapes and different densities of lit windows and different group sizes. The city lights now look less like uniform noise and more like chaos that springs from complex ordered systems.
Tower Buildings
As I mentioned in the post on building shapes, my classic tower-style buildings weren’t going to cut it. I was supposedly making these buildings with elaborate stonework. My goal was to present the outline of such a building and allow the viewer’s imagination and prior experience to fill in the blanks with engravings and such. But I didn’t leave any blanks for them to fill in! Every building was all windows, edge-to-edge, top-to-bottom. I tore out the old code and replaced it with a new building generator:
These new buildings are very rarely covered in windows. They have vertical stripes or windowless areas running down the face of the building. The buildings are broken into tiers, and there are a few blank floors between each tier. It begins at the bottom, drops a tier into place, then puts a lid on that tier, then builds a new tier on top of the lid, onward until it reaches the planned building height.
I love the new one because it has a ton of parameters that govern the shape of the building:
- How tall each tier is. (More accurately, how much of the remaining height is given to the current tier. One-half, one-third, one-forth, etc.)
- How much (if any) the lid sticks out from the side, forming a ledge.
- How tall the lid is, in stories.
- If the corners of the building are explicitly windowless.
- The grouping of the windows and blank areas on the face of the building.
- If the tower gets narrower towards the top.
- The window texture used.
- The tint of the window texture, from a handful of various types of light sources.
These values allow for a huge number of meaningful changes to the shape of the structure, giving the world a ton of visual variety. Also, the vertical blank areas seem very subtle, but it’s shocking how the eye can instantly spot the break in the pattern:
Modern Buildings
These buildings looked fine to begin with, but they didn’t have a lot of variety. A slight change brought about compelling results.
Instead of just randomly cutting off sections of a cylinder, it chooses to do so at regular intervals. And it can make cuts in 45 degree sections as well as 90. And as with the other buildings, I added some vertical window gaps. Although, it doesn’t really make the buildings that much more interesting.
They look interesting in wireframe, but without the lines one deformed cylinder looks much like another.
Other Changes
As you’ve probably noticed in the screenshots, I’ve added a few polygons of roof clutter to hint at HVAC systems and whatnot. The building colors are now limited to a handful of hues that match common lights. And I put larger gaps between buildings, which gives their silhouettes more opportunities to stand out.
A few improvements to the existing systems made a big difference to the overall appearance.
Seven Springs
The true story of three strange days in 1989, when the last months of my adolescence ran out and the first few sparks of adulthood appeared.
Patreon!
Why Google sucks, and what made me switch to crowdfunding for this site.
The Best of 2016
My picks for what was important, awesome, or worth talking about in 2016.
Linux vs. Windows
Finally, the age-old debate has been settled.
Raytracing
Raytracing is coming. Slowly. Eventually. What is it and what will it mean for game development?
Twelve Years
Even allegedly smart people can make life-changing blunders that seem very, very obvious in retrospect.
What Does a Robot Want?
No, self-aware robots aren't going to turn on us, Skynet-style. Not unless we designed them to.
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.
DM of the Rings
Both a celebration and an evisceration of tabletop roleplaying games, by twisting the Lord of the Rings films into a D&D game.
Charging More for a Worse Product
No, game prices don't "need" to go up. That's not how supply and demand works. Instead, the publishers need to be smarter about where they spend their money.
T w e n t y S i d e d



