.comment-link {margin-left:.6em;}
Moriash Moreau: My Second Life
Tuesday, August 29, 2006
Burning Life 2006
There probably won't be many updates here for the next week or three. I won a plot at Burning Life 2006, so most of my SL time will be spent building there. However, I've decided not to document it here until after it's completed. No sense in ruining the surprise. I'll try to take copious pictures and post here once it's done.
Wednesday, August 23, 2006
Walking Tour
Well, I've been walking in SL for the past four mornings now. So far, it's working fairly well. It's making me want to continue walking, anyway, which I suppose is the whole point. I have noticed a few peculiarities arising from the unusual method of input, though.

Apparently, either the client, the USB interface, or both don't like it when you tap the forward key multiple times per second for several minutes on end. (Or have your motorized exercise equipment do it for you.) I've had a few odd bugs pop up in the course of extended walks. First, occasionally the F1 Help box will pop up unbidden. I can't find a reason for this, beyond a general "must be pressing the key too fast" hunch. Similarly, my av will sometimes decide to fly on its own, for the same inexplicable non-reason. The former, I've been forced to deal with by dragging my help box off the screen. (I seldom used it anyway.) The latter, well, all I can do is hit "F" again to turn it off. Irritating. I suppose I'm going to have to come up with some kind of hack to convert multiple keypresses (momentary switch closures) into one long, held keypress (continuously closed switch) until the multiple keypresses stop (or a bit thereafter). I honestly have no idea how to do that. If anyone has any ideas of general electronic circuit types that'd do the job, please drop me a comment! Even a general name for the concept would be enough for research; I don't even know enough to find the right search terms.

Addendum, 9/10/06
Well, it appears that the problem was simpler, and more unexpected, than I anticipated. Near as I can tell, the wiring was run too close to the treadmill's motor, and somehow (don't ask me to explain how) spurious signals were being sent back to the USB keyboard. It was kind of odd, really. In addition to other possible keys not bound to anything in particular, it would signal the F1 key, the jump key (don't know if it was the "E" or "Page Up") and, oddest of all, the calculator button. My desktop would sometimes have four or five Windows calculators spawned after a normal walk.

I discovered this accidentally after making some improvements (added a cooling fan) to the treadmill, and moving the wires out of the way. I didn't bother to neatly bundle them back as I had them (down the upright post to the floor) and, voila, no glitches next walk. Kind of weird, really. I guess I'll accept it as a lesson learned and move on. I got another code snippet out of it (a jump/no-jump key toggle), so I guess it wasn't a complete waste.

One thing I didn't anticipate, and probably should have, is that I'd run across interesting sights while I was walking. Funny how you miss the obvious when you're knee deep in a project! I didn't want to stop and make a landmark each time, so I decided to use the SLurl system. I came up with a simple script to do the recording for me, and put it in a HUD. Now, I just have to hit a single function key (a gesture mapped to a voice command on a hidden channel), and the location where I'm standing is translated into a SLurl and saved for me. Then, at the end of the walk, I have it dump the entire list to an e-mail for later perusal.

Maddeningly, there is no LSL command to get the name of the parcel you're standing on, so I'm left with a chronological list of mystery locations to visit. (That's not so bad, really. Most of the time, I'm walking down a road on Linden "Protected Land" anyway.) Here is the SLurl Dump script, if you'd like to try it out. Don't let the length fool you. There's more comment than code.
A few folks have made quite impressive attempts at building in-world "universal translator" objects. This has been going on for quite a while, actually, but the latest version has just made a splash in recent news. Coincidentally, I happened to be working on a very, very stripped down version for another project (which I'm certain I will be babbling about in great detail in the coming month, assuming it doesn't fall through), and put one together myself a week or so back.

The new SL HTTP commands make this kind of thing a breeze. Most of the free online translation services can be run directly from a single HTTP call, if you dig into them enough, and look closely at the source code and URLs they generate. I chose to use Google Language Tools, mostly because I like Google. That, and Google seems to be somewhat faster than Alta Vista's Babelfish.

Once you've sorted out the specifics of the translation service's PHP calls, you have to come up with a page for it to translate. While there are probably dozens of different ways to approach this, I settled on a simple, one-line PHP command. See the comments in the script linked below. Blogger doesn't seem to be smart enough to validate the HTML Code markup.

In any case, the .php file uses the Echo command to simply parrot anything sent to it by a GET call. Sadly, it took me a couple of hours to figure that out; this was my "Hello World" to PHP coding. I was gratified to see how many similarities there were to LSL (the only programming language I know, aside from some 10 year old HTML). If I ever get a hankering to do real world programming, it may go a little easier. I keep telling myself that, anyway, so I'm not completely wasting untold hours tinkering with LSL scripts.

Anyway, take that one line and dump it in a .php file. (Keep it on one line, with no carriage returns. The returns will show up later, and complicate your formatting and processing.) Put that on a PHP enabled webserver. (For the love of Pete, don't ask me how to do that! I'm a complete n00b at that kind of thing.) Then you can call it with "text" equal to your message, or have Google translate call it, and a simple one-line webpage will result. Have your in-world LSL script call Google translate to translate your echoed message, and you're in business.

If you're interested, here is the translator script I've been tinkering with. It's heavily commented, but the actual script is really quite simple. There's room for improvement in the interface (you have to modify the script to select language pairs, for example), but it does what I need it to do. You'll need to find your own server to host the required PHP file.

Keep in mind that llHTTPRequest is throttled to 20 calls (20 translations) per 100 seconds. I wouldn't expect this to be a problem in normal circumstances, but it could come up in crowded rooms if you use an open listen on the main chat channel. If you're serious about making a universal translator, you'd probably be better off issuing each participant in the conversation his own translator, which listens only to its owner. Or create some other scheme to limit the translation requests.

Addendum, 9/8/06:
Two things. First, the llHTTPRequest throttling is about to be changed (or may have already been, depending on when you read this) to "one request per second, per owner, per sim." This is both better and worse. (More requests available on a per minute basis, but less ability to send short, fast bursts of calls.) I'm not certain how this will affect the translator, although I'd expect the script to fall behind and possibly mis-attribute translations if this script is used on an open channel in a large, chatty crowd. This happens every once in a while now (with the 20 per second throttle), in unusually active chats, when there's a large backlog of requests sent to Google at once. The script tends to attribute backlogs to the last speaker when the requests finally clear. Some form of key checking (to make sure the right name is matched to a given translation request, when said request clears) for the HTTP requests would be good for a polished version of the script.

It's probably better to create individual translator attachments, with llListen restricted to the owner only, for each member of the conversation in those cases. That's probably better, anyway, if you're dealing with a real conversation. One attachment would go, say, from English to Spanish (worn by the English speaking user), while another would translate from Spanish to English (worn by the Spanish speaking user). A better interface would, of course, help with that.

Second, there is a better PHP script available. It helps deal with Magic Quotes settings on some PHP servers (and doesn't hurt anything on PHP servers without Magic Quotes enabled). I'm a little foggy on what Magic Quotes is for, but the upshot is it added a backslash "\" in front of all special characters when an escaped string was received (via GET) that contained special characters. This included punctuation like apostrophes (made a mess out of contractions like "it's" and "I'm") and quotation marks, and prevented Google from translating properly. (It doesn't know what "it\'s" or "I\'m" means.) Tremendous thanks to Sophia Weary for her help and her PHP wizardry in figuring this one out.

Oh, I'm afraid the PHP script above will not work if linked directly. The server it's hosted on doesn't have a workable version of PHP installed, and it's marked as a .TXT file anyway. You'll still need your own PHP server. I can't afford the bandwidth to host a publicly available PHP echo script. Sorry.
Sunday, August 20, 2006
A More Scenic Walk
Well, this project has officially gotten out of hand. I can always tell that this has happened when it looks like R2D2 threw up all over my office. As soon as I hit "publish" here, I think I'm going to spend the next half hour or so bundling and organizing wires.

I went ahead and added a keyboard tray to my setup. It's just a sheet of masonite pegboard, attached to the legs of the pushup stands I'd already added previously. Those pushup stands have turned out to be well worth the dollar I spent on them at a local garage sale a while back. They've formed the framework for most of the modifications and additions I've made for this project. The keyboard now fits quite nicely in the unused space between the handlebars. Unfortunately, there was no room for a mouse, so I expect I'll have to either make do without, or spring for a keyboard with a trackball. I think I'll wait and see how much I actually use this contraption before I decide.

I also added a kill switch for the reed switch attached to the treadmill pulley (described previously). That's the little black paddle switch and bundle of electrical tape attached (with foam tape and zip tie) to the control column at center. Now I can easily cut the signal to the forward direction contacts without having to step off the treadmill and shut it down. This also keeps the contacts from being locked closed in the event that the treadmill pulley stops with the encoder magnet near the reed switch. It's not pretty, but it seems to work.

Finally, as you can see, I rigged up a spare 17" monitor in front of the treadmill. In order to get the right elevation, I stacked two wooden TV trays on top of each other, and did what I could to make them stable. This involved using a bungee cord to lash the lower tray to the frame of the treadmill, then taping the legs of the upper tray in place with duct tape. I also added some cross bracing on the upper tray using a length of PVC piping and a few zip ties (not shown in the picture- added after testing). It still wobbles a little bit, but it seems reasonably stable. I guess I'll have to see how long I can stand working/playing at my desk with the Monitor of Damocles hanging over my head.

On a related note, this morning (before installing the monitor and keyboard- used the monitor on my desk), I took my morning walk inside SL. It was actually kind of fun, or as fun as walking and sweating can be. I walked for half an hour and about 1.2 miles, as usual, at an average speed of around 2.4 miles per hour (1.1 m/s). Yeah, I know, that's not much of a workout. But I only started three weeks ago. Given my sedentary lifestyle and somewhat cetacean physique, that's quite enough for me.

I started my walk at the beginning of the road on the east edge of Abitibi, and followed it roughly westward (give or take some meandering) to Whiskey, a trip of approximately 6.3 kilometers. According to the Debug menu velocity HUD, I was moving at about 3.5 m/s (7.8 MPH). (This is a little faster than the normal walking speed of 3.0 m/s. Apparently tapping the forward key squeezes more speed out of a walk than holding it down. I have no good explanation for that. Perhaps the rig is signaling faster than the keyboard repeat rate?) As you can see, there's a bit of a disparity between SL walking speed and my walking speed. According to Wikipedia, average human walking speed is about 1.0 to 1.5 m/s (2.2 to 3.4 MPH). Avatars appear to walk two to three times faster than their RL human counterparts.

For reference, avatars run at a bit under 5 m/s (11.2 MPH) (and fly at about 15 m/s, or 33.6 MPH). World record setting sprinters have been clocked at 10.3 m/s (22.8 MPH), while accomplished long distance runners can manage a 4 minute mile (15 MPH, or 6.7 m/s). It seems like SL avatar running is a little more realistic, at least for normal human speeds.

The upshot of all this is that SL avatars walk too fast. (And I'll bet that's the first time anyone's ever said that.) That's fine for scenic walks in the country, or on the back roads of the grid, but I think I might be obligated to script some kind of limiter attachment to hold my avatar's speed down to realistic levels when the walking matters. It seems a bit like cheating.

Addendum, 9/29/06
This project was featured on Make: blog! Now, a bit over a month later, I'm still using the treadmill and interface more-or-less daily (four or five times a week, typically). Kind of a nifty way to see SL, anyway, and it helps counter some of the intrinsic feeling of futility that goes with walking on a treadmill. I'm still not getting anywhere, but at least my avatar is.

Saturday, August 19, 2006
Going for a Walk
Well, since my external controller interface box got a mention in Make blog (does that mean I'm "made?"), I figured I'd better do something with it. So, I went ahead and wired up my treadmill.

There are two basic parts to the project: movement and steering. Movement is detected by a simple magnetic reed switch mounted next to the belt drive pulley. As it turns out, this is similar to what the manufacturer did to interface with the treadmill's speedometer. The image above shows a closeup of the drive pulley (the whole drive system is shown at upper left). As you can see at upper middle, the pulley already has a built-in magnet. At middle left is a Hall effect sensor. It sends a signal every time the magnet passes. If I was up on my electronics, I probably would have worked with a Hall effect sensor, as well.

But, since I barely know one end of a soldering iron from the other (and I have the burns to prove it), I settled for using the reed switch. That's the small white plastic box at middle right. I ended up using an old wooden domino as a spacer, and holding it all in place with double-sided foam tape. (Great stuff. No toolbox should be without it.) Every time the magnet passes, the metal leaves inside the reed switch are drawn together, closing the circuit. This is wired to the forward contacts on the controller box.

On the plus side, a reed switch requires no additional electronics to run. On the minus side, it has moving parts. (Well, flexing parts, anyway.) I'm not certain how long it'll operate before the reeds succumb to metal fatigue. I guess I'll find out! If it turns out to be failure prone, I'll have to look into alternate encoders.

The steering system is pretty simple, as well. Electronically, it's just two momentary-connect switches tied into the left and right contacts on the controller box. No biggie there. The mechanics required a bit of thought, however.

I decided to go ahead and make a universal control switch that could be used for multiple future projects. It's always nice to have interchangeable parts, if for no other reason than it helps me defeat my inertia, by reducing the amount of work required later on.

In order to make a reusable device, I needed to rig up some kind of sturdy casing for the switches. Fortunately, I had plenty of office supplies left over from previous projects. The body of a permanent marker worked rather well.

To mount the switches on the handlebars of the treadmill, I ended up making some simple scabbard-like brackets out of some scraps of 3/4" PVC piping. There is a metal washer wedged between the ends of the pipes, inside the connector fitting, to keep the switch from falling out the bottom while allowing a path for the wire. The PVC switch brackets were bound to the handlebars with zip ties. This lets me steer with my thumbs while still maintaining a firm grip on the handles.

The push-up frames attached to the handlebars were from an earlier improvement: they increase the height of the handlebars, so I don't have hunch over when I walk. (Evidently, I'm a few inches taller than the design treadmill user.) They were also attached using zip ties. For me, zip ties are rapidly supplanting duct tape as the handyman's secret weapon.

Once I finished putting it all together, I took a short walk in Second Life. Initial results were highly encouraging. When I first thought about this project, I considered making some kind of vehicle or attachment designed to take occasional keypresses and translate them into constant movement. However, this proved not to be necessary for normal walking. Since the drive pulley turns several times for each step on the treadmill belt, the reed switch provides a constant, rapid string of signals when in use. The keypresses effectively come so rapidly that the avatar doesn't slow significantly between signals. I was able to take a normal walk, apparently indistinguishable from a normal, keyboard driven journey.

All told, I'm quite pleased with this first attempt. There are still a few bugs to work out. First, I can't easily stop the treadmill. It takes a moment to wind down, and a few seconds to start up again. In both cases, I must stop what I'm doing and manipulate the treadmill controls. Effectively, the treadmill is driving me, not the other way around. Heck, I could just turn it on and go grab a Coke, and my av would still blithely walk along in a straight line. There's also a minor issue with the reed switch hanging in the "on" position, if I happen to stop the treadmill with the pulley magnet near the reeds. I believe both of these problems can be helped with a kill switch to stop signals from the reed switch. I'd still not be able to start walking without minor inconvenience, but at least I'll be able to put on the brakes quickly. In the meantime, I'm still looking for a stationary exercise bicycle. It's a shame that non-motorized treadmills work so poorly, because otherwise they'd be the ideal solution.

There are also problems with difficult terrain. Since the avatar is being moved with a rapid series of keypress signals, instead of a continuously held forward key, it sometimes has problems climbing steep inclines (try climbing a cliff by tapping the forward key, and you'll see what I mean). I probably need a jump key for such situations. Similarly, flight is somewhat jerky, for the same reasons. I expect that I will someday make some kind of vehicle to smooth out the motion somewhat.

Finally, there's the simple problem of access. If I end up using this contraption often enough, I'll need to find a way to get a full keyboard, mouse (or similar), and monitor mounted in some usable fashion on or around the treadmill.

But, in spite of the minor kinks, I'm still getting a kick out of all this. I think I'll go take another walk. More to come.
Monday, August 14, 2006
Flash, Bang
Earlier this evening, I added one last small bit of special-effects to the GoD. This is something of a red-letter event for me, because it means I've completed the last scripted portion of the Garage of DOOM. The game is now functionally complete. From here on out, it's just cosmetic tweaking and playtesting. Pardon me while I do a little happy dance in my chair...

...Okay, I'm back. As you can see in the picture below, I added a simple muzzle flash effect to the Monster Gun. Nothing too spectacular, but it does add a bit of realism (or at least verisimilitude). The invisible bang was kind of jarring.

I opted for an animated texture instead of a particle effect, mostly because I already use particle effects for creature damage. I didn't want to exceed the client particle counts during pitched skirmishes. That being said, the texture was definitely the way to go. It's handy to be able to control the effect reliably, without trusting to the vagaries of sim performance.

And I learned a little something from even this. Originally, I'd used a collection of six intersecting prim panes (up, down, left, right, front, and rear facings) to create the effect. (I'm sure you've seen variants of this method for making 2-dimensional images look 3-dimensional if you've ever looked closely at a player-made tree.) This was so that I could use the same image for all of the side facings. The image flipped the wrong way around on half the facings if I pasted it on both sides of the prim and animated it. Texture animation overrides texture flipping and angle settings. Additionally, I had the gun activate a single cycle of the animation (thus calling for a full update to be communicated to the sim) for each shot.

That worked just fine, until I started looking at the sim stats. Performing full updates on the parameters of 6 different prims at the rate of fire of the automatic rifle (10 rounds per second) actually had a noticeable impact on the sim. It was small, but in the worst case it sometimes showed up on the dilation readings (0.01 to 0.02 seconds or so) when I cut loose with an extended spray of gunfire with two or three test guns at once. That was a bit of a surprise, initially, but they were calling for 60 updates a second, each!

Dismaying. I take some pride in the minimal impact the game has had on sim performance. I've promised myself that I'd take out anything that proved to cause a notable effect on sim performance. I've already dumped a couple of monster ideas for this reason. And the Rover is on the watch list now, due to the number of physical collisions it generates. (Too bad. It's one of my favorites.) And now this minor effect proved to be the straw that broke the server's back.

Fortunately, I was able to rescue it. First, I trimmed the muzzle flash prim count down to three by making a second, flipped muzzle flash texture. Yes, it's another texture that must be loaded into the client cache, but I think halving the number of prim updates per second is more than worth an extra one-time texture download!

Second, I changed the way the animations are run. When in blunderbuss mode, the gun only fires one shot per second. Three prim (horizontal, vertical, front-back) updates per second is much more acceptable. (That'd be an advantage to a particle effect: only one object - the emitter prim - needs to be updated to activate it. But the trade off is more client-side lag, in addition to the particle count issues mentioned above.) So I stuck with the same trigger-the-animation-each-shot method.

However, the automatic rifle was another issue. I ended up having to go with a looped animation effect in that case. (More experienced weapons designers are probably saying, "Well, duh!" to their screens now.) Now, the first shot turns on the animation loop, which times out a little over a tenth of a second later. Each subsequent shot resets the animation kill timer, effectively keeping the animation running (and the prims un-altered- animated textures only require updates when they're changed) until the player stops shooting. Thus, the three muzzle flash prims only have to update twice per burst: once at the start and once at the end. And since most players tend to use their Monster Guns like firehoses, these updates are generally spread well apart.

This seems to work pretty well, all told. The sim load is no longer noticeable. (And, oh, how I wish some of my neighbors would do similar tests on their sim-squelching scripts. My sim ecology self-righteousness is little comfort when the time dilation dips to 0.3 every two minutes.) The flash timing tends to drift a bit in long bursts, sometimes even to the point of flashing an extra time after the trigger is released. But, given the rate of fire and the other activity during the game (you know, the business of monster killing and not dying), I'd bet I'm the only one who ever notices, and even that is only when I'm not actually playing. I can live with that.

And now, I'll leave you with a lovely little sentiment from a neon sign in Chamonix. Sleep well.

Addendum, 8/18/06:
After some observation, it appears that the system lag I've been seeing in Louise for the past couple weeks has always been coincident with large spikes in Image Frame time (spikes up to a couple hundred milliseconds). So, after all the work, it's quite possible the gun tests just happened to fall on a period of high lag from other sources. Vexing, but I suppose efficiency is its own reward, even if it's not strictly required to fix an apparent problem.

I spoke with Live Help regarding the spikes in sim lag, the image frame time, and the resultant time dilation issues. Turns out there's an ongoing gridwide problem (which the Linden I spoke to was maddeningly vague about), which is being looked into as we speak (spoke). So I might have misjudged my neighbors. We'll see.

Sunday, August 13, 2006
Virtual Solipsism
Did a little more tinkering with invisiprims and occlusion culling. (Remember, you can find more information on invisibility prims here and here.) And, while I was at it, I played around with FRAPS a bit, too.

The experiment illustrated below is pretty straightforward. I made a 10x10x10 hollow cube and set it up with an invisibility prim script. Then I walked inside and took a look around.

It did a fairly decent job of hiding the surroundings, provided I didn't move the camera too quickly. Interestingly, the patch of ground that still shows when the invisiprim is active is somewhat larger than 10 meters across. As touched on in the previous entry on this topic, opaque prims that are only partially in the occluded field of view are fully rendered. This evidently applies to the ground, as well. Since a portion of the ground patch was inside the cube with me, it wasn't blotted out.

Not a particularly useful discovery, but interesting, nonetheless. Might be worth further experimentation, if someone wanted to make an invisiprim window for their ground-level home. You could place the invisiprim window (and the associated wall) at the edge of a ground patch (perhaps located by looking for pattern repetition in the ground texture?), to avoid unsightly strips of ground in your carefully sculpted and culled field of view. As noted by Ami Chyan in the previous entry, an invisiprim window effectively converts any view into a kinda, sorta ocean view (provided you are close enough to sea level to see it). I'm tempted to go in with something like this myself, just to recapture a portion of my own lost ocean view.
Thursday, August 10, 2006
Worked out something kind of interesting a couple days ago. The old "invisiprim" (which can be found here or here) interacts rather interestingly with the (relatively) new object-object occlusion filter. Apparently, the texture used for the invisiprim trick is treated as opaque for purposes of occlusion calculations. The net result is the objects that are fully occluded behind an invisiprim are not rendered, just as if they were behind a solid wall. So, under a limited set of circumstances, the invisiprim will hide solid, opaque objects, as well as objects with transparency/alpha masks.

(If that doesn't make sense, I'd recommend following one of the links above and playing with an invisiprim yourself. It's kind of neat.)

I'd noticed this effect before, when placing my camera very close to an avatar that incorporated a large invisiprim. Large, fully opaque objects behind the avatar suddenly disappeared! But the reasons behind it only clicked in my mind a couple nights ago. Last night, I made a simple test case using a large (10x10x0.1) invisiprim.

Here is an overhead view of the setup. The occluded field of view is just a sample. I observed the same results from multiple locations behind the pane. Far away objects (further than 10 meters or so) completely failed to render. This included local walls (I was inside a building at the time), floors, furniture, and so on. The only thing remaining in the middle-to-far view was land and sky.

The nearby view was more interesting. Prims apparently cannot be partially occluded (this is possibly common knowledge, I just never really thought about it). So, fully opaque objects that are only partway inside the occluded field of view are still fully visible. (Naturally, alpha/transparent objects behaved as expected, with portions of a prim disappearing behind the invisiprim.) Occlusion appears to work on a prim level, not an object level. So parts of an opaque object may disappear, while other parts remain.

So what? Well, it's mostly just an oddity. In practice, most invisiprims are small, generally no bigger than is needed to hide legs or feet for exotic avatars and high-heeled shoes. So you'll seldom see this effect by accident. But I can see this being useful for dealing with the eyesores that may appear on the grid from time to time. Don't like your view? One too many giant, spinning "For Sale" signs on the horizon? Slip an invisiprim behind your windows (remember, you only need to use the invisiprim texture on the side you're seeing- you can texture the outside view however you like), and remove the offending portion of the grid from your sight.

Of course, it'll also remove all other objects, trees, and clouds, leaving nothing but empty land as far as the eye can see. (And maybe your front porch, depending on how much of it is fully occluded behind the pane). This may be what you want. It is kind of peaceful, in a solipsistic sort of way. But for most cases, I'd guess this is more useful for skyboxes in crowded airspace, or in other cases where the absence of background objects won't be noticed.
Minor Progress
Haven't been spending a lot of time in game lately. It happens that way, sometimes. And I've been spending what little game time I have had catching up with in-world friends. I really need to work on making that a priority more often. It's been far too easy to get buried in coding lately.

But I did sort out a minor game play issue, anyway. Specifically, a player can now only use the continue function of the death teleporter (the gold orb) twice, instead of indefinitely. After the third death, he must leave the game and return to the security office.

This is the first part of some changes that grew out of a brief IM discussion with Hamlet Au. (Who is, incidentally, the reigning best Legendary Monster Slayer. Going to have to see about dethroning him sometime soon.) Or, more specifically, he asked me one question, "How many players can play at one time?"

You'd think I'd have a ready answer to that, wouldn't you? Strictly speaking, there is no limit. You could have a few dozen players crammed in one 60x60 space, and the game would probably be able to more or less chug along. The main problem is monster count, at that level. Yes, the players could be there. But there is a preset limit to the maximum number of monsters that can be in play at any one time. (This is both to limit lag and keep the monster server system from bogging down.) Monster count increases with player count, up to that limit. Beyond that, the players would probably get pretty bored. The game gets kind of slow when there's only one or two monsters per player.

So, to keep things from getting out of hand, I've decided to limit the number of players in game at any one time. The continues limit above is part of that. If things are really busy, I want to give other players the chance to get in on the game, by kicking out folks who have already been playing for a while.

The other part of the equation is entry control. I'm already counting players as part of the monster targeting system, so it should be relatively easy to shout the player count to the entry doors (the double doors in the security room). Under normal circumstances, using these doors is the only way to activate the game HUD and start play. Given that, I can simply deactivate the door when player count is too high. I'll probably limit it to 4 or 5 players and see how it goes. Extra players can at least watch the game using the security monitors (camera overriding seats with four preset camera views).

I should be able to sort that out tonight. From there, it's just play testing and cosmetic issues. More to come.
Sunday, August 06, 2006
Just finished a little weekend project I've been kicking around for a while now. I've taken a USB numeric keypad, ripped out its innards, and wired a set of contacts to the six main SL-related movement keys (forward, back, left, right, page up, page down- I seldom use the strafe keys). Basically, at this point, it's just a bare interface board for future use. But now I have a handy way to easily wire all sorts of things into SL movement.

Of course, the controller will require a script within SL to use it properly. Some people (see below) have used external hardware and software to intercept the signals and pre-process them before sending them to SL (by programming keypress lengths, detecting time-outs for key release, and so on). Given that my real-world programming skills are virtually non-existent, I'm shifting the processing burden onto LSL scripts in game. That, at least, I know pretty well. Ultimately, I don't see this being any more demanding than the typical vehicle script, or simply walking your avatar from one end of the room to the other. As far as SL is concerned, a keypress is a keypress, no matter the actual hardware source behind it.

I have a few nebulous plans, but nothing terribly concrete at this point. I'd originally wanted to come up with a virtual flying bicycle kind of thing, similar to the vehicle used in Prop Cycle. Unfortunately, I've had a bear of a time finding a cheap, used stationary exercise bike. I guess they're sufficiently out of style that they're not even being sold used anymore.

I'm still looking for an exer-cycle, mostly because I loved that video game, and I can't seem to find it anymore. But, in the interim, I'm kicking around wiring up my existing treadmill to map into in-world walks. Recently, I've taken up walking on said treadmill, in order to cope with the ever-expanding case of swivel-chair spread caused by spending all day sitting in front of a computer, followed by coming home to spend all night in front of a computer. And since playing Second Life for hours on end has been a major contributing factor to my voluminous spare tire, it seems fitting that SL at least make working it off again a little more entertaining.

Also, at least in my pipe dreams, I'd like to look into walking next year's SL Relay for Life using such a setup. It'd be kind of neat to walk the virtual track for real. But that will ultimately depend on whether I can come up with a reasonable vehicle and/or attachment that can walk the path without causing problems with things like climbing stairs and maneuvering around other pedestrians. That, and on my general willingness to be a spectacle and/or laughing-stock if I publicize it.

For the sake of completeness, I should mention that this kind of externally-controlled virtual movement has been done in SL before, by Kyle Machulis (AKA qDot Bunnyhug in SL), and possibly others. I've pretty much given up on originality in SL. It's all been done before. But it should still be fun to play with. I'm sure I'll post more when I come up with some applications for the controller.

Addendum, 8/14/06:
This project was posted in Make blog! How cool is that? I guess I'll have to get my rear in gear and use it for something. Thanks to Mark Wallace (aka Walker Spaight) for the post and the heads-up.

Since I didn't give any specifics earlier, I thought I'd take a moment to briefly describe how I wired this mess up. There's nothing too exotic about it, really. The main issue was coming up with a way to make solder points on the keyboard membrane. As you may already know, most cheap keyboards nowadays use thin plastic sheets as substrates for the switches and associated conductors. Under each key, a contact is painted on the plastic with metallic paint. The key pushes down and mashes the plastic sheets together in such a way that two of these contacts meet.

That works fine for the intended purpose, but it doesn't lend itself to tinkering. I wasn't brave enough to try and solder directly to the plastic, and I was too cheap to spend $25 on conductive silver epoxy cement, so I came up with a mechanical connection, instead. I don't claim that this is the best way to do it, but it seems to work well enough for my purposes.

First, take apart the keyboard. Profuse swearing seems to help here. Inside, you'll find the circuit board, USB cable wiring (careful- thin wires!), and the aforementioned sandwich of plastic sheets. The "bread" is actually a single sheet of plastic, folded in half. The "meat" is another sheet with holes cut out under each switch contact. This acts both as an insulator and a spacer. You'll probably end up cutting this piece out before the project is done. Don't expect to use the keyboard for anything else (such as, say, a functional keyboard) after this process.

We're interested in the outer layer of plastic. Carefully fold this layer open. You may not want to press it completely flat, as the plastic at the fold (and the associated wiring that runs through it) is sharply creased, and could easily crack or break.

Now figure out which contacts you wish to bridge, by referring back to the keys themselves and finding where they'd land when pressed. Next, take a straight pin and carefully punch two holes in the plastic at the contact: one off to the side, and one inside the conductive paint (see the bottom view, above). I found it useful to place it against a stiff, but easily pierced, surface when doing this. (I used the bull's-eye core from a plastic foam archery target, but a flat chunk of Styrofoam would do just as well.) Make the hole in the conductive paint somewhat off center (as shown), in order to maximize contact area.

That brings us to the wire. Find a short length of stiff, solid-core wire. (I used 22 gauge, just because I had it handy.) Bend it into a rough "J" shape. Then, bend the bottom cross-piece of the "J" into a horizontal "S" curve. This both maximizes contact area with the conductive paint and lends the wire some stability, once it's installed. It also makes it easy to make minor width adjustments if you misjudged the distance between the pin holes.

Once you have your bent wire, push the two vertical segments into the pin holes. The short leg should penetrate the painted contactor, while the long leg penetrates the empty plastic. This order is probably not required, but it put another couple millimeters of unimportant, empty plastic between the heated portion of the wire and the metallic paint conductor. It seemed like a good idea to have a little bit of a buffer, in case the plastic started melting during soldering later on.

Be careful not to bend, crease, or tear the plastic. And don't apply too much force to the connection between the plastic sheet/circuit and the main circuit board. (The connecting socket on mine looked a bit fragile.) Once the wire is seated, it should rest flat against the plastic and the painted contact. See step one in the side view, above.

Then, once the wire is in place, carefully bend the short leg over such that it clamps onto the plastic (as shown in step two, above). Crimp it as tight as you can without damaging the plastic.

Now, all that remains is to insulate and stiffen the connection. You'll want to find something relatively stiff to glue over the connection. I ended up using scrap Velcro patches (about 1/2" square), because they were made with stiff plastic and had a foam tape backing. (And I already had them, a big plus.) I expect thin double-sided foam tape and a piece of plastic would work just as well. I added a smaller piece on the opposite side of the plastic, just to lend the assembly additional stiffness. See step three, above.

And that's that. As for soldering, well, I am really bad at that. All I can recommend is that you use a heat sink and take all possible steps to avoid melting the plastic sheets. Be sure to avoid twisting the wire as you work. The mechanical connection created is reasonably stiff, but it is very easy to tear the plastic and loosen the connection under torque.

Oh, in case you're wondering, the little plastic button in the picture above is wired to the NumLock key on the keypad. You'll probably want to do the same thing, so you can turn off number lock when you're using your board to control movement in-game. On most systems, number lock defaults to "on" when the computer reboots or when a new keyboard is installed

Addendum, 8/20/06:
I've just finished my first project using the controller box. Seems to work pretty well.
Thursday, August 03, 2006
Live from SL
Just ran across a couple of events in SL that even you non-SL folks might find interesting.

First, tonight (Thursday, August 3) at 7pm (my time) or 5pm (SL time), Suzanne Vega will be performing "live" in SL... For certain values of "live." In this case, it'll be a live audio stream combined with a live view of her virtual likeness standing on a virtual stage. Pretty slick, and a bit of a coup for SL in general. It's another baby step toward mainstream acceptance of SL as more than WoW's touchy-feely weak sister.

I expect the audio to be good, of course, but I still have a few reservations about the visual portion of the performance. Some preliminary articles have mentioned custom animations and such, presumably run by a third party puppeteer. I dearly hope that's the case, anyway. Previous live performances I've seen have often ended up featuring an avatar standing stock still and playing the same canned guitar-strum animation for 90 minutes straight. And I can understand that, of course. The performers have better things to do - like singing, playing their chosen instruments, and generally kicking ass - than running an animation HUD. It's not that big a deal, I guess. Mostly it reminded me of a mediocre Winamp visualization plugin: it didn't hurt the music, but it didn't add anything to the experience. I have hopes that this considerably higher profile concert will have commensurately higher production values. I'm sure I'll be confirming- or reversing- my fears in addendum later tonight.

Second, on Tuesday, August 8, noted author Kurt Vonnegut will be appearing virtually for a semi-live talk and reading. As before, virtual avatar, real audio stream. Should prove interesting. We'll see how it works out.

There are also two other speakers, John Maeda and Howard Rheingold, coming up on Friday and Monday (respectively). I fear that I don't recognize the names, but from the blurbs it sounds like they're both big names in the virtual community.

If you're interested, you can find more information here. URLs for the Quicktime and Shoutcast streams (for those not lucky enough to get one of the coveted ~90 available SL seats) are available an hour before the appointed time.

And please, oh please tell me they're equipping the esteemed speakers and performer with industrial strength movelocks. (Or better yet, turning off pushes altogether with the spanking new no-push flag that appeared in yesterday's update.) All we need is for some putz with a freebie push gun to orbit Kurt Vonnegut. That'd really make the mainstream world take us seriously.