Thursday, May 04, 2006
To continue my long tradition of starting games and never finishing them, I've started on another game design in SL. This time, it's kind of a low-end horror/survival first person shooter. Or, as it seems to be shaping up, a somewhat slower moving, first-person version of Robotron: 2084.
This all spawned from one of several sessions with my Louise neighbor, Will Webb, blasting away at things with freebie machine guns. Okay, not the most intellectual of pursuits, but entertaining nonetheless. Our preferred targets are Daniel Luchador's Man v1.6 (a man in a top hat that explodes in a shower of blood and internal organs when hit a sufficient number of times- check your freebie boxes, you almost certainly have one) and Fenrir Reitveld's roaming Daleks (realistic mobile models of the infamous Dr. Who baddies, which also explode in a shower of parts- robotic, this time). But, as immensely cool as these targets are, they don't really interact with the user (aside from, you know, exploding when you shoot them). So, in the classic see-a-need-fill-a-need fashion, I set about to make targets that fight back. And, well, it's gotten a bit out of hand.
My ultimate goal is to create a multi-player game with HUD controls and a central tracking server to track players and adjust difficulty (mostly in terms of maximum numbers of simultaneous monsters) based on the number of people in game. Ultimately, I'd like to rig everything inside an arena at ~1500m (using the same altitude tricks used for the SkyLounge), perhaps with an observation deck a hundred or so meters above it (with seating equipped with various camera controls so the viewers can get right into the action). This has the dual advantages of keeping the framerate up (no pesky scenery in range to slow down the client) and hiding the arena from casual view (since it'll be both huge and not much to look at, initially). But, I'm a long way from that right now.
For now, I've been focusing on building the monsters. This is unfortunate, since I've found that I'm going to have to recode major portions to work with the game server. Moral: don't start with the fun part, I guess. But, still, the monsters are turning out pretty well. There are two general classes: flyers and walkers. So far, I've concentrated most of my efforts on the flying monsters.
The Rippers are the most sophisticated baddies so far. They're smallish (approximately 0.75m across) UFOs with spinning saw blades at their middles. Their flight paths are generally linear as they home in on the player, with adjustments for flight elevation selected at random in order to reduce aerial pile ups... Most of the time. However, there is still a fair bit of mid-air collisions. Short of creating a flocking algorithm (doable, but complex), there isn't much way around this. They all home in on the same target. So, instead, I've decided to turn this minor bug into a feature. When one Ripper bot runs into another, it inflicts a small amount of damage (about half what a bullet inflicts). So, if the player is clever and fast on his feet, he can force the Rippers to slice one another to ribbons without firing a shot. Kind of like the old Daleks computer game, but in 3-D.
These things taught me a fair bit about dealing with collisions. The flat discs of the blades caused all sorts of problems when they collided with players or with each other. During initial tests, I was launched across the sim (and through a wall!) about every 10th hit. I was seriously considering added a movelock to the game HUD. Finally, I realized that the problem was caused by the unpredictable narrow edge colliding with my av's bounding box. The Rippers are now encased in a transparent, flattened sphere. This has dramatically reduced (although not completely removed) the unpredictable physics effects. There is still the rare bad bounce (usually an odd combination of events involving three or four collisions, in rapid succession and close quarters) that sends a Ripper through the floor, but that's easy to fix: just kill it off. There's always more monsters!
The Rippers come with the expected buzzing flight effects, and emit random clanking noises and sparks when hit. They also make a disturbingly organic tearing sound on collision. I think, perhaps, I went a bit overboard with the blood spray effects.
The Jack o' Lanterns are pretty simple, behavior-wise. They home in on the target and explode. They're easy to kill, which is fortunate, since the explosion is extremely damaging. The Jack o' Lanterns forced me to come up with a some communications methods that proved to be useful later on. See, when they explode, they damage everything- player or monster- within a few meters. This required a damage system based on llSay, instead of collisions. (It senses nearby targets, and effectively tells them that they've been damaged. Kind of a Voodoo-esque approach, but it works.) Before long, I'd converted all of the monsters and damage tracking to use the llSay based damage system.
I'm kind of proud of the texture work here. I'm not all that p-shop savvy, but the shading in the striations turned out pretty well. The actual face cut-out is made of alpha shapes cut into the texture, allowing the viewer to see the particle flames inside. The flames stream upward, out of the hole in the top of the pumpkin. I think this looks better than a traditional Jack o' Lantern cap, and it incidentally saved me a prim or two making the cap and stem.
Here I am being attacked by Poltergeists. These are insubstantial, amorphous blobs of protoplasm that fly in circular paths intersecting the player. They've proven to be very difficult to track in mouselook. Perhaps too difficult, really. I'm already planning on slowing them down a fair bit and reducing their life totals, to make them easier to kill.
From a look-and-feel standpoint, these are kind of unusual. The model is simply a twisted torus (embedded inside a transparent sphere). Every 10 to 30 seconds, they change their twist revolutions at random, effectively changing their shape. The animation rate on the texture (which is simply the client "sizzle" texture) also changes, causing them to flicker at a different rate. Between that, the simple white particle effect, and the quiet looped ambient noises accompanying them, they have quite an eerie feel to them. I've already added a simplified version of the Poltergeists to the gravesite at the back of the Garden of Mo, with scripts to create one when someone walks over the grave.
(What? Oh, yeah. I have a grave on my land. It's called the "Grave of Hope," and has all sorts of mopey, moody descriptions built into the various parts (mound of earth, headstone, plastic flowers). I was having a really, really bad week when I built it. Kind of embarrassing, now, but I can't quite bring myself to delete it.)
I think that about does it with the airborne menaces, anyway. The rest of the roll call of horrors will be groundbound. Above is a zombie. Oooh, scary, huh? Okay, right now it's an ambulatory sheet of plywood. Eventually, the wood texture will be replaced with assorted cutout pictures, perhaps with simple two frame animations for walking. My intention is to build the monsters as avatars in game, then photograph them. This is the best way I can figure to get a good image of both the fronts and backs of each of the different types. Eventually, groundpounding fiends will include:
- Skeleton- basic walking monsters with no special abilities.
- Vampire- moderately fast and tough, regenerates life over time.
- Zombie- very tough, slow. Falls down briefly if damaged sufficiently. Periodically moans "Braaaains!"
- Coffee Zombie- like zombies, but faster. Periodically moans "Cofffffeeeee!"
- Blob Zombie- huge, fat, exceedingly tough. Occasionally stops to air guitar to clips from Rob Zombie's "Dragula."
- Spawn of Fa'Shun- female zombie, impeccably dressed in the latest styles and accessories.
And any other horrible jokes I can come up with along the way. So far, though, I've built a couple different types of menacing lumber. Slow and steady, I guess.
I had originally planned to allow players to use their own weaponry to fight in the monster arena. But I soon found that the average production machine gun was far too fast to register properly with the health tracking scripts. (The game pretty much requires a machine gun, or some other method of landing large numbers of slugs quickly. If someone tried to use a revolver, they'd be quickly overrun.) I've put a fair bit of time into optimizing the code for speed, but even so it takes time for a flurry of bullets to register.
So, I've decided to come up with an approved custom weapon for the game. In the picture above, you can see one of the weapon settings in operation: the shotgun. It fires a burst of 10 pellets in an adjustable grouping. (I actually have 10 different scripts working in concert for this task.) The pellets rez in a circular pattern, with random placements for each pellet. (Imagine a wagon wheel with 10 spokes. A given pellet can appear anywhere along the length of each spoke.) This both gives a nice grouping (the choke can be easily adjusted in the script, for looser or tighter group) and isolates each bullet to its own zone, minimizing the number of mid-air collisions normally present in weapons that fire multiple rounds at once.
I have got to take the time to come up with the final gun model. I ended up slapping the scripts in a handy freebie gun I already had in my inventory. Unfortunately, it bears a striking resemblance to a black chromed marital aid. I think I'll move this to the top of my to-do list.
The other setting for the gun (so far) is a basic machine gun. This presented its own set of problems. As above, the machine gun uses the same 10 launcher scripts. But this time they're called one at a time, in sequence. Like many in-game machine guns, this one was initially plagued with mid-air bullet collisions. Often, this is solved by adding a random component to the initial rez locations for the bullets. That works reasonably well, but since I already had the shotgun scripts, I had a different approach. Basically, I just removed the spread and the random placement component from the shotgun rezzing routines. This results in each bullet being rezzed along the circumference of a circle, with the next one appearing evenly spaced along the same perimeter, and so on. As you can see in the picture above, this results in a spiral pattern as the bullets fly through the air. Kind of nifty, I think. And, barring physics glitches and lag effects, I get very few mid air collisions now. Note that I've increased the radius of the spiral for the pictures. It's normally only a few centimeters across.
With the collision problem solved, that just left the issue of speed. The distributed script scheme neatly gets around the 0.1 second script delay for rezzing objects (like bullets). In fact, it worked a little too well. In my initial tests, I used unscripted temporary-on-rez bullets. After a couple of test firings, I was informed that the simulator was full! I've since added timers to kill the bullets after 3 seconds, as well as code to kill them upon collision with other objects, but I still had to come up with a way to throttle the rate of fire to reasonable levels. For now, I've set the rate of fire back down to 10 rounds per second. So far, that appears sufficient. I'll have to see if I need more firepower when it comes time for live testing.
I'm still working on a way to deal with melee combat. The main problem with guns- and this seems to be universal- is that they don't seem to work within a meter or so. In order to avoid rezzing bullets inside the bounding box of the user, most guns rez their bullets about a meter in front of the user's face. (Remember, we're using mouselook, so most guns correct the rez point such that the bullets line up with the mouselook crosshairs. Otherwise, the bullets will end up something like a meter below the target.) So, if the monster elbows its way closer than this, the bullets will end up appearing behind it. Quite frustrating. Since I now have the llSay damage system, it would be a reasonably easy matter to use a short range sensor to detect the nearest monster on command, and tell it it has been damaged. This would be the bare bones of a punch, kick, bayonet, etc. Of course, this would also mean being close enough to the monster to be hit in return (so far, all monsters must run into or get very close to the player to damage him). I'm going to have to look closely at balance issues to see if this would ever be worthwhile.
There's still a long way to go. I've added three or four things to the to-be-solved list while writing this. Assuming I don't just end up shelving the project, I'll be sure and bore you with future updates.
Links to this post:
Return to Main Page
Thanks to you, I just went and wasted precious minutes of my life reading this playtest of Spawn of Fashan. Curse you.
Gah! I couldn't even make it through the character creation part. I cannot imagine trying to play the actual game.Post a Comment
Links to this post:
Return to Main Page