Viridian Games

Viridian talks about his kids, game development, and anything else that comes to mind.

Archive for the 'Game Programming' Category

Planitia Update 30: MULTIPLAYER GET!

That’s right. After weeks of work and a near-full engine rewrite I have multiplayer working in Planitia. Now, right now everything has to be hardcoded - number of clients, the IP addresses, everything. So I can’t release a demo yet. I’ll need to at least bang in some code so that clients and servers can find each other on a LAN before I do.

I’m just terribly, terribly excited. I did a ton of research for this (and of course I’ll be Writing An Article) and it paid off tremendously - everything is working exactly like I expected it would once the system was implemented.

Now, that’s not to say it’s perfect. The system is updating an average of six times a second, which means that right now units jump across the map and there’s a bit of lag between clicking a button and having something happen in the world. Both of these can be made to look better with interpolation and prediction, though they don’t actually change how the game plays.

If you guys want to get a leg up on finding out how I did the multiplayer, you can read the following articles:

For making your engine multiplayer ready:
Instant Replay: Building a Game Engine with Reproducible Behavior

For implementing network multiplayer in an RTS:

1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond
“Real-Time Strategy Network Protocol”, Game Programming Gems 3 page 496 or Best of Game Programming Gems page 459, by Jan Svarovsky

Teehee! I’m so excited!

Oh, and the next installment of Let’s Play Starflight will be delayed a day. For some reason.

1 comment

“Ben There, Dan That!” and the Supremacy of Community

So two froody dudes, Dan “Gibbage” Marshall and Ben Ward, decide to stop piddling about with their own pathetic projects and team up, creating Zombie Cow Studios in the process.

And to celebrate, they decided to give away a game for free - an adventure game called Ben There, Dan That!, which stars…um, them. That’s right, you control Ben and Dan as they bumble through a loving homage to the classic Lucasarts Adventure games, doing things like smacking priests with bibles, visiting alternate dimensions, and…um…climbing out of a cow’s rear end. Hey, they’re British.

Now, even given the fact that they used Adventure Game Studio to create the game, that’s a heck of a lot of work to just give away. But I heartily, heartily approve of the process, and not just because I’m cheap. I think it’s the right thing to do because it helps them grow their community, and I believe that community is the solution to all of gaming’s problems.

Does your game stink? Get people interested in the potential your game might have and they can help you fix it. And you don’t have to do it all before you ship. Feedback after you ship is just as vital - but those lines of communication must be open.

Are you having trouble marketing your game? Again, community can help. Bungie’s testers sang the praises of Myth: The Fallen Lords to all their friends once their NDAs were lifted, which helped Bungie as they took their first steps into the PC market.

Are you having trouble keeping people interested in your game? Once again, community to the rescue. The most popular online first-person shooter in the world is still Counter-Strike, which kept copies of the original Half-Life on store shelves for years. The incredible response of the Korean community means that you can still walk into a Wal-Mart and buy a copy of StarCraft - a game that was released in 1998! Caravel Games goes even farther with their Deadly Rooms of Death series. The DRoD games consist of a layout of rooms, each containing a puzzle. The DRoD website gives you an overall map of the game - and clicking any room on the map takes you to a forum thread discussing that room. It’s an excellent way to provide player-based support, in addition to player-created content.

Are you having trouble funding your game? Yes, this is the iffiest one, but it’s been done. Lots of people have started by creating a small, well-supported game and then rolling the profits from that into something much larger. I think my favorite story of this nature is that of Jeff Minter, who was saved from having to get a real job by the incredible response to Llamatron, which Minter released for free along with a README.TXT file that included this paragraph:

Here’s the deal. You play Llamatron and check out the hook. If it gets you (and I reckon it will if you like mayhem), then send us a fiver and, as a reward for being so honest, we will send you an ace poster of our gun-toting llama, a newsletter, and a complete copy of Andes Attack, originally released in 1988 to considerable critical acclaim. Two games for a fiver - can’t be bad. And if the response is good, there will be more Shareware. And better.

And of course there’s also the aforementioned Dan Marshall, who is currently in the process of giving away two hundred pounds to an indie developer chosen by his readers.

This is the kind of thing Jeff Vogel is talking about when he says, “Shareware is a force for good.”

And finally, the big one.

Are you having trouble with people pirating your game?

Well, of course you are. People pirate stuff. They’re going to do it. You can’t do much about it.

If you want to come to terms with piracy, you need to come to understand that you’re not trying to eliminate it. You’re trying to reduce its impact to the point where you can still make the money you need to make on your game to stay in business. I wish I could tell you to just ignore piracy but I can’t - you should be going onto those download sites and demanding that they remove your game, because you do want pirating your game to be more complicated than just doing a Google search.

How can community help here?

Well, it’s harder to steal from somebody when you feel like you know them personally. It’s also harder to steal from somebody when they are trying to be the good guys.

The seminal example of using community to beat piracy is Stardock’s Galactic Civilizations 2. Absolutely no anti-piracy stuff on the disc. No CD key. No CD check. No phoning home. No refusing to run if there’s a compiler on the same system. No installing low-level drivers that monitor all data traffic without the user’s knowledge. Nothing. The only thing it uses is a unique account key that allows you to create a support account on Stardock’s digital distribution network, so that you can redownload the game if you lose your discs.

And yet it sold a bazillion copies and was a huge moneymaker for Stardock. And as I’ve mentioned before, one of those copies was sold to me. Even though I’ll never have time to play such an involved game. Why did I buy it? Because they were doing it right.

I have said that game design is a conversation between the developer and the player. But now I’ve come to realize that the metagame of game development is the same thing.

If you want to succeed in game development, don’t just make games. Help people have fun. And that means getting personally involved, with all the risks that carries.

3 comments

What My Friends Are Doing

Yes, it’s another “while you are waiting” post. Deal.

I’ve got a couple friends here at work whose websites are definitely worth checking out.

First, Patrick Rogers. He’s an avid Go player who recently hit traffic gold on his site by being the first person to post the complete lyrics to all three episodes of Dr. Horrible.

Second, Brandon “Rusty” Parks. Rusty’s a real character, as you’ll be able to tell when he starts talking about how the universe has a discrete pixel size and a discrete frame rate.

Third, Bobby Thurman…who I actually don’t work with any more and probably should keep in better contact with.

And finally, you know those people who keep coming into game development forums or IRC channels and ask how to program an MMORPG? Yeah, laugh at them. Go ahead. Because everybody knows that nobody can possibly write an indie MMORPG. And oddly enough, it’s being worked on by all three of the gentlemen I detailed above! What are the odds?!

3 comments

Powermonger Map File Format

This post is mostly for Arkiruthis/Mrthingy, but if the rest of you want to read it, feel free!

All of the map data for Powermonger is contained in the MAPDATA.DAT file. This file is 65,268 bytes long and contains 196 Powermonger maps. It’s broken down into:

* One header that is 196 bytes long. It’s possible this header was going to flag certain maps as being certain types, but since all of the entries are zeroes it probably wasn’t used.

* One hundred and ninety-six map files that are each 332 bytes long.

While I have not figured out everything each byte in a map file represents, I’ve figured out a lot. Here’s the map file for the third level (I picked this one because it’s more interesting than the first two). I’ve grouped the bytes into groups of four because…well, you’ll see.

First off, here’s a cleaned-up version of how the minimap for the third level looks:

The first 40 lines (160 bytes) contain data I haven’t identified yet, but I can say that most of these lines are exactly the same in all files.

0 10 0 32
0 250 0 0
0 10 0 15
0 7 0 2
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 21 0 48
0 250 0 4
0 10 0 20
0 7 0 2
0 0 0 0
0 6 0 0
0 0 0 0
0 0 0 0
0 15 0 32
0 250 0 8
0 10 0 20
0 7 0 2
3 0 208 0
0 0 0 0
0 0 0 0
0 0 0 0
0 10 0 32
1 14 0 1
0 10 0 15
0 7 0 2
3 212 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 10 0 32
1 24 0 2
0 10 0 10
0 7 0 2
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

Now things get interesting. The first three bytes of line 41 contain the values that are passed into the terrain generation algorithm. Altering them alters the terrain of the map. The last byte is apparently passed into the forest-creating algorithm, since changing it changes the forests without changing the underlying terrain.

   2    97  18   0

The first byte on line 42 (in this case, 0) is also apparently fed into the forest algorithm.

The second byte on line 42 (in this case, 6) appears to set the upper Z limit - raising and lowering this value makes the terrain hillier or flatter without altering the shape of the terrain on the map.

The fourth byte (32) is an X-coordinate offset. It won’t change the shape of the terrain, but it will move the entire terrain mass left or right on the map. The terrain mass will wrap around if necessary.

   0     6   0  32

The second byte on line 43 (48) is, you guessed it, the Y offset. It will move the entire terrain mass up or down on the map, wrapping around as necessary.

The fourth byte on line 43 (3) is apparently a terrain smoothing factor. Setting this value low causes the terrain to get very jagged; setting it high causes the terrain to smooth out until there’s nothing left.

   0    48   0   3

Now we can FINALLY stop guessing, because from line 44 until the end of the file, each four-byte group encodes one “object” that is dropped on top of the terrain after generation. The four bytes represent the X-coordinate, Y-coordinate, team of the object and finally the object type. The X and Y coordinates correspond perfectly to what pixel that object is in on the minimap (which is why I was able to figure these out).

The player’s team is team 1; all higher numbers refer to computer-controlled teams. Unfortunately I do not know what all the codes mean yet because I haven’t been able to access maps that use those objects. Here are the object codes I do know:

1 - Road Endpoint
2 - Tiny Village
3 - Medium Village
5 - Large Village
16 - Tower
17 - Road Segment

You will always see a “1 16″ pair (a tower belonging to Player 1) in the list. This designates where the player starts.

  52    24   1  16  - Tower belonging to Team 1 at 52, 24
  14    65   2  16  - Tower belonging to Team 2 at 14, 65
  17    41   3   3  - Medium village belonging to Team 3 at 17, 41
  41    66   3   3  - Medium village belonging to Team 3 at 41, 66
  44    99   2   5  - Large village belonging to Team 2 at 44, 99
  35    78   3   3  - Medium village belonging to Team 3 at 35, 78
  54    77   3   3  - Medium village belonging to Team 3 at 54, 77
   8    77   3   3  - Medium village belonging to Team 3 at 8, 77
  41    66   1  17  - Road segment belonging to Team 1
  54    77   1  17  - Road segment belonging to Team 1
  55    91   1  17  - Road segment belonging to Team 1
  44    95   1  17  - Road segment belonging to Team 1
  37    90   1  17  - Road segment belonging to Team 1
  35    78   1   1  - Road segment belonging to Team 1
  35    85   1  17  - Road segment belonging to Team 1
  26    94   1  17  - Road segment belonging to Team 1
  22    94   1  17  - Road segment belonging to Team 1
  19    86   1  17  - Road segment belonging to Team 1
  16    75   1  17  - Road segment belonging to Team 1
  11    72   1  17  - Road segment belonging to Team 1
   8    77   1   1  - Road segment belonging to Team 1
  48    40   3   3  - Medium village belonging to Team 3 at 48, 40
  26    52   3   3  - Medium village belonging to Team 3 at 26, 52
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0
   0     0   0   0

Notes:

Yes, the road segments belong to team 1 (the players’ team). I’m not sure why.

You can easily beat any Powermonger map by finding the data for that map in MAPDATA.DAT and changing all the villages to belong to team 1. Next time you load that map you’ll be instantly declared the winner.

When the terrain generator drops these objects on the map, it creates terrain underneath them if there isn’t already some.

And finally, here is the source for the program that can scan the original MAPDATA.DAT and split out the map files.

And now as a special bonus! These are some notes I took about how the village simulation in Powermonger works. They are kind of rough, so I present them as-is :)

Notes on Powermonger:

Powermonger allows the two triangles in a cell to be different terrain types. Thus, you can have half be beach and the other water, half be farmland and the other mountain, etc.

Speaking of farmland, it’s not marked on the map, but all the clear, flat tiles (or half-tiles) around a village is considered farmland.

By the same token, all the water that is at least one square from a beach is considered “fishable”.

While there are only two official “jobs” (farmer and fisher) there appear to be five things a walker can do in Powermonger:

Gather food from a farm (this REQUIRES the job “Farmer”).

Gather food from the ocean (this REQUIRES the job “Fisher”).

Gather wood (no specific job required).

Bring a sheep back to the village center (no specific job required).

Defend themselves when attacked (no specific job required).

(Units also make things, but since that is all handled internally there is absolutely no way to tell what unit made what and why or how they chose to make that particular thing.)

Farming and fishing cannot happen during the winter. Walkers usually gather wood or make things in the winter. If a walker has no supported job, he simply stands in the center of the town.

Hard to tell how often units “eat”, but it appears they consume 2 food every time they do.

When walkers encounter sheep (which is pretty random, since the sheep walk around randomly and the walker must get near the sheep in the course of doing another job), they bring the sheep back to the center of town. It APPEARS that as long as the sheep is near the center of town, the village gets a constant low food income. But the sheep will continue to wander off, and thus will have to be brought back again.

Towns cannot die off. Ever. If you take all the walkers from a village and the last walker is about to starve, then five men from your army will leave your army, become walkers, and rejoin the village.

4 comments

PIX

One of the reasons I haven’t been posting updates on Planitia is because I’ve had this weird graphical bug that I haven’t been able to get rid of. How bad is it? Well…here, see for yourself:

Huh...the paint's run.  But I used Krylon!

Note that some of the houses are drawing just fine, while others are drawing as green-and-brown smears. It’s not awful, but it’s like a pimple on an otherwise attractive face - it’s all you notice.

Now, it’s obvious what is happening - the houses that aren’t drawing right are losing their texture coordinates. The renderer no longer draws the entire texture over the house but just a single pixel from the texture - thus, the solid green and brown colors. This happens if all texture coordinates for the mesh are set to 0, 0.

But it’s not obvious why that’s happening. The hardest bugs to debug are the ones that only happen some of the time and DirectX’s infamous undebuggability just makes it worse. So after several evenings of playing around with DirectX’s render states to absolutely no effect I finally just gave up and moved on to other stuff. I knew I’d have to come back and fix this bug eventually and I wasn’t looking forward to it.

And this morning I decided to take another shot at it. My renderer supports two sets of texture coordinates but the second set of coordinates isn’t set on this mesh…perhaps it was picking up the second set accidentally? Let’s turn the second set off completely. Damn! That still doesn’t fix it! How about if we specify the same set of coordinates for the second set as the first? Holy smoke, that still doesn’t fix it…

Now, at work I’ve been working on my first renderer in a production environment. It’s for a Kaplan SAT program. I’m working on the PC version and I was having trouble with a cartoon shader I was writing. Searching “debug vertex shaders” brought up several recommendations to “just use PIX”.

PIX? What’s that?

It’s the official DirectX debugging tool. It’s included with the DirectX SDK. And I had no idea it existed. Mostly because nobody told me. (Baleful glare at all my programmer friends.)

With PIX I was able to figure out what was wrong with my shader at work, so I decided to use it to try to fix my bug on Planitia.

PIX is pretty easy to use. You start by creating a new experiment:

Starting a PIX experiment.

Point the Program path field to the executable you want to debug, then choose one of the four options below it. Options 1 and 4 provide the most data, but if you’re just debugging something it’s probably too much (it’s much more useful if you’re optimizing). I like option 2, where PIX takes a “snapshot” of what DirectX is doing whenever you press F12.

Click “Start Experiment” and your program will run. PIX will add some text to show you that it is functioning properly:

PIX running on Planitia.

Now it’s running. To debug my problem I panned the camera over to a house that wasn’t drawing correctly and hit F12.

Taking a snapshot of the problem.

Now when I exit the program PIX brings up the results of the experiment.

Results of the experiment.

Now we’ve got a TON of information about what DirectX was doing during the frame we captured. Let’s look at the Events window…

Events window.

And expand Frame 270.

Frame 270 expanded.

We now have a list of every. Single. Freakin’. Thing DirectX did during that frame. DirectX is inscrutable no more!

Not only do we have the list of commands, but the Details window shows exactly what that command drew:

This DrawIndexedPrimitive() call drew the sand underneath the water.

So let’s step through the list of draw commands…ah, here’s the first house it drew. This house was drawn correctly (except that since it wasn’t on the screen, it wasn’t actually drawn at all, as shown by the Viewport window). Notice the columns that show the texture coordinates for the house.

The first house it drew.

Let’s keep stepping…wait, what the hell?

Problem drawing a point sprite list?

A problem drawing a point sprite list? Why is it drawing a point sprite list? There aren’t any point sprites in the scene! Wait a minute, I’ll bet…

The broken house.

Yep. The very next thing it tries to draw is the broken house. Notice that the texture coordinates are now missing.

And now I know what the problem is. I was calling Draw() on a point sprite system that didn’t actually draw any point sprites. This put the renderer into “point sprite mode” - and point sprites don’t have any texture coordinates. Now, sometimes the renderer would fix itself on the next draw call - and sometimes it wouldn’t, and the house would be drawn with no texture coordinates.

The fix: change this code:

The broken code.

To this code:

The fixed code.

Time taken: ten minutes.

Minor lesson learned: I shouldn’t call DrawPrimitive() if I don’t actually have any primitives to draw.

Major lesson learned: I should use PIX - and I shouldn’t ever complain again about DirectX being undebuggable.

4 comments

“No. There Is Another.”

It’s not just me! I’m not alone! The thing I like most about this is that he’s taking a completely different tack. He’s doing as straight a remake as possible, whereas I, in my Yankee arrogance, have decided to actually try to improve on the original game.

I can’t wait to play it.

2 comments

500th Submit!

I just submitted my 500th change to my SVN server (I was refactoring some stuff on Planitia in preparation for adding the network code). I guess that’s some kind of accomplishment!

1 comment

First Ludum Dare Practice Game - Wizard!

This is something I started a while back but didn’t get too far with. Now I’ve picked it back up and expanded on it in order to get some practice writing platformer mechanics.

7 comments

Time to Level Up

I’ve been thinking that it’s about time to start challenging myself again. Yes, yes, Planitia…but there’s something else I’ve been wanting to do.

I’ve mentioned the self-confidence problems that I’ve had in the past and while I’m a lot better (look, Ma! I’m writing in public!) there is one thing I still don’t like to do and that is compete. I shy away from testing my skills against other people, because I’m afraid I’ll discover that I suck. Well, it’s time to meet this thing head-on.

Therefore, I am hereby announcing that I will compete in Ludum Dare Eleven, which will be held from April 18-20.

Now, see, in order for this to really work I’m going to need to make a pretty good showing of it. So for the next month I’m going to be making lots and lots of small games. I’m hoping to do at least four and I don’t want any of them to take longer than a week to do. This will get me better at starting out quickly and sand over any edges in my 2D development skills.

So the bad news is that there won’t be any Planitia news for a while. The good news is that there should be lots more news on all the other games I’m doing leading up to the competition.

I’m also going to have to come up with a few good recipes, since one of the categories you’re graded on is food

4 comments

Collector - A One-Page Game

Bwahaha! The One-Page Game meme grows!

Casey Dunham has now written a one-page game called Collector. Collector is based on a famous arcade game just like my game Sandworm was. Which one? I’ll let you find out yourself :)

Casey said that he likes the one-page game format because he’s so busy as a student that he doesn’t really have time for anything more involved. Well done, Casey!

2 comments

Next Page »